mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-10 19:51:00 +00:00
[improvement][headless-fe] Migrating scaffold version to @umi/max (#1030)
* [improvement][semantic-fe] Add model alias setting & Add view permission restrictions to the model permission management tab. [improvement][semantic-fe] Add permission control to the action buttons for the main domain; apply high sensitivity filtering to the authorization of metrics/dimensions. [improvement][semantic-fe] Optimize the editing mode in the dimension/metric/datasource components to use the modelId stored in the database for data, instead of relying on the data from the state manager. * [improvement][semantic-fe] Add time granularity setting in the data source configuration. * [improvement][semantic-fe] Dictionary import for dimension values supported in Q&A visibility * [improvement][semantic-fe] Modification of data source creation prompt wording" * [improvement][semantic-fe] metric market experience optimization * [improvement][semantic-fe] enhance the analysis of metric trends * [improvement][semantic-fe] optimize the presentation of metric trend permissions * [improvement][semantic-fe] add metric trend download functionality * [improvement][semantic-fe] fix the dimension initialization issue in metric correlation * [improvement][semantic-fe] Fix the issue of database changes not taking effect when creating based on an SQL data source. * [improvement][semantic-fe] Optimizing pagination logic and some CSS styles * [improvement][semantic-fe] Fixing the API for the indicator list by changing "current" to "pageNum" * [improvement][semantic-fe] Fixing the default value setting for the indicator list * [improvement][semantic-fe] Adding batch operations for indicators/dimensions/models * [improvement][semantic-fe] Replacing the single status update API for indicators/dimensions with a batch update API * [improvement][semantic-fe] Redesigning the indicator homepage to incorporate trend charts and table functionality for indicators * [improvement][semantic-fe] Optimizing the logic for setting dimension values and editing data sources, and adding system settings functionality * [improvement][semantic-fe] Upgrading antd version to 5.x, extracting the batch operation button component, optimizing the interaction for system settings, and expanding the configuration generation types for list-to-select component. * [improvement][semantic-fe] Adding the ability to filter dimensions based on whether they are tags or not. * [improvement][semantic-fe] Adding the ability to edit relationships between models in the canvas. * [improvement][semantic-fe] Updating the datePicker component to use dayjs instead. * [improvement][semantic-fe] Fixing the issue with passing the model ID for dimensions in the indicator market. * [improvement][semantic-fe] Fixing the abnormal state of the popup when creating a model. * [improvement][semantic-fe] Adding permission logic for bulk operations in the indicator market. * [improvement][semantic-fe] Adding the ability to download and transpose data. * [improvement][semantic-fe] Fixing the initialization issue with the date selection component in the indicator details page when switching time granularity. * [improvement][semantic-fe] Fixing the logic error in the dimension value setting. * [improvement][semantic-fe] Fixing the synchronization issue with the question and answer settings information. * [improvement][semantic-fe] Optimizing the canvas functionality for better performance and user experience. * [improvement][semantic-fe] Optimizing the update process for drawing model relationship edges in the canvas. * [improvement][semantic-fe] Changing the line type for canvas connections. * [improvement][semantic-fe] Replacing the initialization variable from "semantic" to "headless". * [improvement][semantic-fe] Fixing the missing migration issue for default drill-down dimension configuration in model editing. Additionally, optimizing the data retrieval method for initializing fields in the model. * [improvement][semantic-fe] Updating the logic for the fieldName. * [improvement][semantic-fe] Adjusting the position of the metrics tab. * [improvement][semantic-fe] Changing the 字段名称 to 英文名称. * [improvement][semantic-fe] Fix metric measurement deletion. * [improvement][semantic-fe] UI optimization for metric details page. * [improvement][semantic-fe] UI optimization for metric details page. * [improvement][semantic-fe] UI adjustment for metric details page. * [improvement][semantic-fe] The granularity field in the time type of model editing now supports setting it as empty. * [improvement][semantic-fe] Added field type and metric type to the metric creation options. * [improvement][semantic-fe] The organization structure selection feature has been added to the permission management. * [improvement][semantic-fe] Improved user experience for the metric list. * [improvement][semantic-fe] fix update the metric list. * [improvement][headless-fe] Added view management functionality. * [improvement][headless-fe] The view management functionality has been added. This feature allows users to create, edit, and manage different views within the system. * [improvement][headless-fe] Added model editing side effect detection. * [improvement][headless-fe] Fixed the logic error in view editing. * [improvement][headless-fe] Fixed the issue with initializing dimension associations in metric settings. * [improvement][headless-fe] Added the ability to hide the Q&A settings entry point. * [improvement][headless-fe] Fixed the issue with selecting search results in metric field creation. * [improvement][headless-fe] Added search functionality to the field list in model editing. * [improvement][headless-fe] fix the field list in model editing * [improvement][headless-fe] Restructured the data for the dimension value settings interface. * [improvement][headless-fe] Added dynamic variable functionality to model creation based on SQL scripts. * [improvement][headless-fe] Added support for passing dynamic variables as parameters in the executeSql function. * [improvement][headless-fe] Resolved the issue where users were unable to select all options for dimensions, metrics, and fields in the metric generation process. * [improvement][headless-fe] Replaced the term "view" with "dataset" * [improvement][headless-fe] Added the ability to export metrics and dimensions to a specific target. * [improvement][headless-fe] Enhanced dataset creation to support the tag mode. * [improvement][headless-fe] Added tag value setting. * [improvement][headless-fe] Optimized the tag setting system. * [improvement][headless-fe] Optimized the tag setting system. * [improvement][headless-fe] Updated the data initialization for model editing to use API requests instead. * [improvement][headless-fe] Added search functionality to model management. * [improvement][headless-fe] Removed field null validation during model editing. * [improvement][headless-fe] Updated the batch operation button component. * [improvement][headless-fe] Optimized the logic for initializing indicators in dimension value settings. * [improvement][headless-fe] Adjusted the length of the input field for model editing names. * [improvement][headless-fe] Lock the version of the @ant-design/pro-table component and replace it with @ant-design/pro-components. * [improvement][headless-fe] Optimized the style of the metrics market and tags market. * [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling. * [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling * [improvement][headless-fe] The quick creation of model fields now defaults to using the "comment" field for filling. * [improvement][headless-fe] Fixed the issue where the conditions for metric measurement creation were not being saved correctly. * [improvement][headless-fe] Default value setting for hiding dimensions. * [improvement][headless-fe] Updated the file imports in the project. * [improvement][headless-fe] Adjusted the logic for displaying the tab in the theme domain. * [improvement][headless-fe] Added term management functionality. * [improvement][headless-fe] When creating a model, the current metric operator now allows for clearance. * [improvement][headless-fe] Term management interface transformation * [improvement][headless-fe] Migrating scaffold version to @umi/max
This commit is contained in:
@@ -1,19 +1,16 @@
|
||||
// https://umijs.org/config/
|
||||
import { defineConfig } from 'umi';
|
||||
import defaultSettings, { publicPath } from './defaultSettings';
|
||||
import themeSettings from './themeSettings';
|
||||
import { defineConfig } from '@umijs/max';
|
||||
// import { join } from 'path';
|
||||
import defaultSettings from './defaultSettings';
|
||||
import proxy from './proxy';
|
||||
import routes from './routes';
|
||||
import moment from 'moment';
|
||||
import dayjs from 'dayjs';
|
||||
const { REACT_APP_ENV = 'dev', RUN_TYPE } = process.env;
|
||||
|
||||
const publicPath = '/webapp/';
|
||||
import ENV_CONFIG from './envConfig';
|
||||
import CompressionWebpackPlugin from 'compression-webpack-plugin'
|
||||
|
||||
|
||||
const { REACT_APP_ENV, RUN_TYPE } = process.env;
|
||||
|
||||
export default defineConfig({
|
||||
webpack5: {},
|
||||
mfsu: false,
|
||||
define: {
|
||||
// 添加这个自定义的环境变量
|
||||
// 'process.env.REACT_APP_ENV': process.env.REACT_APP_ENV, // * REACT_APP_ENV 本地开发环境:dev,测试服:test,正式服:prod
|
||||
@@ -28,68 +25,161 @@ export default defineConfig({
|
||||
metas: [
|
||||
{
|
||||
name: 'app_version',
|
||||
content: moment().format('YYYY-MM-DD HH:mm:ss'),
|
||||
content: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
},
|
||||
],
|
||||
devServer: { port: 8002 },
|
||||
/**
|
||||
* @name 开启 hash 模式
|
||||
* @description 让 build 之后的产物包含 hash 后缀。通常用于增量发布和避免浏览器加载缓存。
|
||||
* @doc https://umijs.org/docs/api/config#hash
|
||||
*/
|
||||
hash: true,
|
||||
// history: { type: 'hash' },
|
||||
antd: {},
|
||||
dva: {
|
||||
hmr: true,
|
||||
|
||||
/**
|
||||
* @name 兼容性设置
|
||||
* @description 设置 ie11 不一定完美兼容,需要检查自己使用的所有依赖
|
||||
* @doc https://umijs.org/docs/api/config#targets
|
||||
*/
|
||||
// targets: {
|
||||
// ie: 11,
|
||||
// },
|
||||
/**
|
||||
* @name 路由的配置,不在路由中引入的文件不会编译
|
||||
* @description 只支持 path,component,routes,redirect,wrappers,title 的配置
|
||||
* @doc https://umijs.org/docs/guides/routes
|
||||
*/
|
||||
// umi routes: https://umijs.org/docs/routing
|
||||
routes,
|
||||
/**
|
||||
* @name 主题的配置
|
||||
* @description 虽然叫主题,但是其实只是 less 的变量设置
|
||||
* @doc antd的主题设置 https://ant.design/docs/react/customize-theme-cn
|
||||
* @doc umi 的theme 配置 https://umijs.org/docs/api/config#theme
|
||||
*/
|
||||
theme: {
|
||||
// 如果不想要 configProvide 动态设置主题需要把这个设置为 default
|
||||
// 只有设置为 variable, 才能使用 configProvide 动态设置主色调
|
||||
'root-entry-name': 'variable',
|
||||
// 'primary-color': '#f87653',
|
||||
'primary-color': '#1672fa',
|
||||
},
|
||||
/**
|
||||
* @name Dayjs 的国际化配置
|
||||
* @description 如果对国际化没有要求,打开之后能减少js的包大小
|
||||
* @doc https://umijs.org/docs/api/config#ignoremomentlocale
|
||||
*/
|
||||
ignoreMomentLocale: true,
|
||||
/**
|
||||
* @name 代理配置
|
||||
* @description 可以让你的本地服务器代理到你的服务器上,这样你就可以访问服务器的数据了
|
||||
* @see 要注意以下 代理只能在本地开发时使用,build 之后就无法使用了。
|
||||
* @doc 代理介绍 https://umijs.org/docs/guides/proxy
|
||||
* @doc 代理配置 https://umijs.org/docs/api/config#proxy
|
||||
*/
|
||||
proxy: proxy[REACT_APP_ENV as keyof typeof proxy],
|
||||
base: publicPath,
|
||||
publicPath,
|
||||
outputPath: RUN_TYPE === 'local' ? 'supersonic-webapp' : 'dist',
|
||||
/**
|
||||
* @name 快速热更新配置
|
||||
* @description 一个不错的热更新组件,更新时可以保留 state
|
||||
*/
|
||||
fastRefresh: true,
|
||||
//============== 以下都是max的插件配置 ===============
|
||||
/**
|
||||
* @name 数据流插件
|
||||
* @@doc https://umijs.org/docs/max/data-flow
|
||||
*/
|
||||
model: {},
|
||||
/**
|
||||
* 一个全局的初始数据流,可以用它在插件之间共享数据
|
||||
* @description 可以用来存放一些全局的数据,比如用户信息,或者一些全局的状态,全局初始状态在整个 Umi 项目的最开始创建。
|
||||
* @doc https://umijs.org/docs/max/data-flow#%E5%85%A8%E5%B1%80%E5%88%9D%E5%A7%8B%E7%8A%B6%E6%80%81
|
||||
*/
|
||||
initialState: {},
|
||||
/**
|
||||
* @name layout 插件
|
||||
* @doc https://umijs.org/docs/max/layout-menu
|
||||
*/
|
||||
title: 'TME内容库',
|
||||
layout: {
|
||||
name: '',
|
||||
locale: true,
|
||||
siderWidth: 208,
|
||||
...defaultSettings,
|
||||
},
|
||||
/**
|
||||
* @name moment2dayjs 插件
|
||||
* @description 将项目中的 Dayjs 替换为 Dayjs
|
||||
* @doc https://umijs.org/docs/max/moment2dayjs
|
||||
*/
|
||||
// moment2dayjs: {
|
||||
// preset: 'antd',
|
||||
// plugins: ['duration'],
|
||||
// },
|
||||
/**
|
||||
* @name 国际化插件
|
||||
* @doc https://umijs.org/docs/max/i18n
|
||||
*/
|
||||
locale: {
|
||||
// default zh-CN
|
||||
default: 'zh-CN',
|
||||
antd: true,
|
||||
// default true, when it is true, will use `navigator.language` overwrite default
|
||||
baseNavigator: false,
|
||||
baseNavigator: true,
|
||||
},
|
||||
// dynamicImport: {
|
||||
// loading: '@ant-design/pro-layout/es/PageLoading',
|
||||
/**
|
||||
* @name antd 插件
|
||||
* @description 内置了 babel import 插件
|
||||
* @doc https://umijs.org/docs/max/antd#antd
|
||||
*/
|
||||
antd: {},
|
||||
/**
|
||||
* @name 网络请求配置
|
||||
* @description 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。
|
||||
* @doc https://umijs.org/docs/max/request
|
||||
*/
|
||||
request: {},
|
||||
/**
|
||||
* @name 权限插件
|
||||
* @description 基于 initialState 的权限插件,必须先打开 initialState
|
||||
* @doc https://umijs.org/docs/max/access
|
||||
*/
|
||||
access: {},
|
||||
/**
|
||||
* @name <head> 中额外的 script
|
||||
* @description 配置 <head> 中额外的 script
|
||||
*/
|
||||
headScripts: [
|
||||
// 解决首次加载时白屏的问题
|
||||
{ src: '/webapp/scripts/loading.js', async: true },
|
||||
],
|
||||
|
||||
//================ pro 插件配置 =================
|
||||
presets: ['umi-presets-pro'],
|
||||
/**
|
||||
* @name openAPI 插件的配置
|
||||
* @description 基于 openapi 的规范生成serve 和mock,能减少很多样板代码
|
||||
* @doc https://pro.ant.design/zh-cn/docs/openapi/
|
||||
*/
|
||||
// openAPI: [
|
||||
// {
|
||||
// requestLibPath: "import { request } from '@umijs/max'",
|
||||
// // 或者使用在线的版本
|
||||
// // schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json"
|
||||
// schemaPath: join(__dirname, 'oneapi.json'),
|
||||
// mock: false,
|
||||
// },
|
||||
targets: {
|
||||
ie: 11,
|
||||
},
|
||||
// umi routes: https://umijs.org/docs/routing
|
||||
routes,
|
||||
// Theme for antd: https://ant.design/docs/react/customize-theme-cn
|
||||
theme: {
|
||||
...themeSettings,
|
||||
},
|
||||
alias: {
|
||||
'antd/es/style': '@/assets/style',
|
||||
},
|
||||
esbuild: {},
|
||||
title: false,
|
||||
ignoreMomentLocale: true,
|
||||
proxy: proxy[REACT_APP_ENV || 'dev'],
|
||||
manifest: {
|
||||
basePath: '/',
|
||||
},
|
||||
base: publicPath,
|
||||
publicPath,
|
||||
outputPath: RUN_TYPE === 'local' ? 'supersonic-webapp' : 'dist',
|
||||
resolve: {
|
||||
includes: ['src/components'],
|
||||
},
|
||||
chainWebpack: (config) => {
|
||||
if (process.env.NODE_ENV === 'production') { // 生产模式开启
|
||||
config.plugin('compression-webpack-plugin').use(
|
||||
new CompressionWebpackPlugin({
|
||||
algorithm: 'gzip',
|
||||
test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'),
|
||||
threshold: 10240,
|
||||
minRatio: 0.6,
|
||||
deleteOriginalAssets: false, // 不删除源文件
|
||||
})
|
||||
);
|
||||
}
|
||||
// {
|
||||
// requestLibPath: "import { request } from '@umijs/max'",
|
||||
// schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json',
|
||||
// projectName: 'swagger',
|
||||
// },
|
||||
// ],
|
||||
// 将insights-flow相关包排除出mfsu编译,在pnpm link 模式下保持热更新
|
||||
mfsu: {
|
||||
strategy: 'normal',
|
||||
// exclude: ['supersonic-insights-flow-components', 'supersonic-insights-flow-core'],
|
||||
},
|
||||
requestRecord: {},
|
||||
exportStatic: {},
|
||||
// esbuildMinifyIIFE: true,
|
||||
});
|
||||
|
||||
@@ -41,11 +41,39 @@ const ROUTES = [
|
||||
envEnableList: [ENV_KEY.CHAT],
|
||||
},
|
||||
{
|
||||
path: '/model/:domainId?/:modelId?/:menuKey?',
|
||||
path: '/model/metric/edit/:metricId',
|
||||
name: 'metricEdit',
|
||||
hideInMenu: true,
|
||||
component: './SemanticModel/Metric/Edit',
|
||||
envEnableList: [ENV_KEY.SEMANTIC],
|
||||
},
|
||||
{
|
||||
path: '/model/',
|
||||
component: './SemanticModel/DomainManager',
|
||||
name: 'semanticModel',
|
||||
envEnableList: [ENV_KEY.SEMANTIC],
|
||||
routes: [
|
||||
{
|
||||
path: '/model/:domainId/:modelId',
|
||||
component: './SemanticModel/DomainManager',
|
||||
// name: 'semanticModel',
|
||||
envEnableList: [ENV_KEY.SEMANTIC],
|
||||
},
|
||||
{
|
||||
path: '/model/:domainId/:modelId/:menuKey',
|
||||
component: './SemanticModel/DomainManager',
|
||||
// name: 'semanticModel',
|
||||
envEnableList: [ENV_KEY.SEMANTIC],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// {
|
||||
// path: '/model/:domainId/:modelId/:menuKey',
|
||||
// component: './SemanticModel/DomainManager',
|
||||
// name: 'semanticModel',
|
||||
// envEnableList: [ENV_KEY.SEMANTIC],
|
||||
// },
|
||||
|
||||
{
|
||||
path: '/metric',
|
||||
@@ -70,6 +98,13 @@ const ROUTES = [
|
||||
component: './SemanticModel/Metric/Detail',
|
||||
envEnableList: [ENV_KEY.SEMANTIC],
|
||||
},
|
||||
{
|
||||
path: '/metric/detail/edit/:metricId',
|
||||
name: 'metricDetail',
|
||||
hideInMenu: true,
|
||||
component: './SemanticModel/Metric/Edit',
|
||||
envEnableList: [ENV_KEY.SEMANTIC],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
@@ -57,6 +57,11 @@ export const configProviderTheme = {
|
||||
Radio: {
|
||||
colorPrimary: '#3182ce',
|
||||
},
|
||||
Checkbox: {
|
||||
colorPrimary: '#3182ce',
|
||||
borderRadiusSM: 0,
|
||||
checkboxSize: 24,
|
||||
},
|
||||
Table: {
|
||||
headerBg: '#f9fafb',
|
||||
headerColor: '#667085',
|
||||
|
||||
@@ -4,23 +4,23 @@
|
||||
"private": true,
|
||||
"description": "data chat",
|
||||
"scripts": {
|
||||
"analyze": "cross-env ANALYZE=1 umi build",
|
||||
"analyze": "cross-env ANALYZE=1 max build",
|
||||
"build": "npm run build:os",
|
||||
"build:os": "cross-env REACT_APP_ENV=prod APP_TARGET=opensource umi build",
|
||||
"build:os-local": "cross-env REACT_APP_ENV=prod APP_TARGET=opensource RUN_TYPE=local umi build",
|
||||
"build:inner": "cross-env REACT_APP_ENV=prod APP_TARGET=inner umi build",
|
||||
"build:test": "cross-env REACT_APP_ENV=test umi build",
|
||||
"build:os": "cross-env REACT_APP_ENV=prod APP_TARGET=opensource max build",
|
||||
"build:os-local": "cross-env REACT_APP_ENV=prod APP_TARGET=opensource RUN_TYPE=local max build",
|
||||
"build:inner": "cross-env REACT_APP_ENV=prod APP_TARGET=inner max build",
|
||||
"build:test": "cross-env REACT_APP_ENV=test max build",
|
||||
"deploy": "npm run site && npm run gh-pages",
|
||||
"dev": "npm run start:osdev",
|
||||
"dev:os": "npm run start:osdev",
|
||||
"dev:inner": "npm run start:dev",
|
||||
"no:dev:os": "NODE_OPTIONS=--openssl-legacy-provider npm run start:osdev",
|
||||
"no:dev:inner": "NODE_OPTIONS=--openssl-legacy-provider npm run start:dev",
|
||||
"no:build:inner": "cross-env NODE_OPTIONS=--openssl-legacy-provider REACT_APP_ENV=prod APP_TARGET=inner umi build",
|
||||
"no:build:inner": "cross-env NODE_OPTIONS=--openssl-legacy-provider REACT_APP_ENV=prod APP_TARGET=inner max build",
|
||||
"gh-pages": "gh-pages -d dist",
|
||||
"i18n-remove": "pro i18n-remove --locale=zh-CN --write",
|
||||
"postinstall": "umi g tmp",
|
||||
"lint": "umi g tmp && npm run lint:js && npm run lint:style && npm run lint:prettier",
|
||||
"postinstall": "max setup",
|
||||
"lint": "max g tmp && npm run lint:js && npm run lint:style && npm run lint:prettier",
|
||||
"lint-staged": "lint-staged",
|
||||
"lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ",
|
||||
"lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style",
|
||||
@@ -29,17 +29,17 @@
|
||||
"lint:style": "stylelint --fix \"src/**/*.less\" --syntax less",
|
||||
"precommit": "lint-staged",
|
||||
"prettier": "prettier -c --write \"src/**/*\"",
|
||||
"start": "NODE_OPTIONS=--openssl-legacy-provider npm run start:osdev",
|
||||
"start:dev": "cross-env REACT_APP_ENV=dev MOCK=none APP_TARGET=inner umi dev",
|
||||
"start:osdev": "cross-env REACT_APP_ENV=dev PORT=9000 MOCK=none APP_TARGET=opensource umi dev",
|
||||
"start:no-mock": "cross-env MOCK=none umi dev",
|
||||
"start:no-ui": "cross-env UMI_UI=none umi dev",
|
||||
"start:pre": "cross-env REACT_APP_ENV=pre umi dev",
|
||||
"start:test": "cross-env REACT_APP_ENV=test MOCK=none umi dev",
|
||||
"start": "npm run start:osdev",
|
||||
"start:dev": "cross-env PORT=8002 REACT_APP_ENV=dev MOCK=none APP_TARGET=inner max dev",
|
||||
"start:osdev": "cross-env REACT_APP_ENV=dev PORT=9000 MOCK=none APP_TARGET=opensource max dev",
|
||||
"start:no-mock": "cross-env MOCK=none max dev",
|
||||
"start:no-ui": "cross-env UMI_UI=none max dev",
|
||||
"start:pre": "cross-env REACT_APP_ENV=pre max dev",
|
||||
"start:test": "cross-env REACT_APP_ENV=test MOCK=none max dev",
|
||||
"pretest": "node ./tests/beforeTest",
|
||||
"test": "umi test",
|
||||
"test": "max test",
|
||||
"test:all": "node ./tests/run-tests.js",
|
||||
"test:component": "umi test ./src/components",
|
||||
"test:component": "max test ./src/components",
|
||||
"tsc": "tsc --noEmit"
|
||||
},
|
||||
"lint-staged": {
|
||||
@@ -67,7 +67,7 @@
|
||||
"@types/numeral": "^2.0.2",
|
||||
"@types/react-draft-wysiwyg": "^1.13.2",
|
||||
"@types/react-syntax-highlighter": "^13.5.0",
|
||||
"@umijs/route-utils": "^1.0.33",
|
||||
"@umijs/route-utils": "2.2.2",
|
||||
"ace-builds": "^1.4.12",
|
||||
"ahooks": "^3.7.7",
|
||||
"antd": "5.11.2",
|
||||
@@ -87,6 +87,7 @@
|
||||
"omit.js": "^2.0.2",
|
||||
"path-to-regexp": "^2.4.0",
|
||||
"qs": "^6.9.0",
|
||||
"query-string": "^9.0.0",
|
||||
"react": "^17.0.0",
|
||||
"react-ace": "^9.4.1",
|
||||
"react-dev-inspector": "^1.8.4",
|
||||
@@ -97,10 +98,9 @@
|
||||
"react-split-pane": "^2.0.3",
|
||||
"react-syntax-highlighter": "^15.4.3",
|
||||
"sql-formatter": "^2.3.3",
|
||||
"supersonic-chat-sdk": "^1.0.10",
|
||||
"supersonic-insights-flow-components": "^1.4.6",
|
||||
"umi": "3.5",
|
||||
"umi-request": "^1.4.0"
|
||||
"supersonic-chat-sdk": "^1.1.6",
|
||||
"supersonic-insights-flow-components": "^1.4.9",
|
||||
"umi-request": "1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/pro-cli": "^2.0.2",
|
||||
@@ -117,13 +117,9 @@
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@types/react-helmet": "^6.1.0",
|
||||
"@umijs/fabric": "^2.4.0",
|
||||
"@umijs/plugin-blocks": "^2.0.5",
|
||||
"@umijs/plugin-esbuild": "^1.0.1",
|
||||
"@umijs/preset-ant-design-pro": "^1.2.0",
|
||||
"@umijs/preset-dumi": "^1.1.0-rc.6",
|
||||
"@umijs/preset-react": "^1.7.4",
|
||||
"@umijs/yorkie": "^2.0.3",
|
||||
"@umijs/max": "^4.2.5",
|
||||
"@umijs/fabric": "^4.0.1",
|
||||
"@umijs/plugin-model": "^2.6.2",
|
||||
"carlo": "^0.9.46",
|
||||
"cross-port-killer": "^1.1.1",
|
||||
"detect-installer": "^1.0.1",
|
||||
@@ -138,7 +134,8 @@
|
||||
"pro-download": "1.0.1",
|
||||
"puppeteer-core": "^5.0.0",
|
||||
"stylelint": "^13.0.0",
|
||||
"typescript": "^4.0.3"
|
||||
"typescript": "^4.0.3",
|
||||
"umi-presets-pro": "2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <20.0.0"
|
||||
|
||||
196
webapp/packages/supersonic-fe/public/scripts/loading.js
Normal file
196
webapp/packages/supersonic-fe/public/scripts/loading.js
Normal file
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* loading 占位
|
||||
* 解决首次加载时白屏的问题
|
||||
*/
|
||||
(function () {
|
||||
const _root = document.querySelector('#root');
|
||||
if (_root && _root.innerHTML === '') {
|
||||
_root.innerHTML = `
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#root {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
}
|
||||
|
||||
.loading-title {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.loading-sub-title {
|
||||
margin-top: 20px;
|
||||
font-size: 1rem;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.page-loading-warp {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 26px;
|
||||
}
|
||||
.ant-spin {
|
||||
position: absolute;
|
||||
display: none;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
color: #1890ff;
|
||||
font-size: 14px;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
list-style: none;
|
||||
opacity: 0;
|
||||
-webkit-transition: -webkit-transform 0.3s
|
||||
cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||
transition: -webkit-transform 0.3s
|
||||
cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86),
|
||||
-webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||
-webkit-font-feature-settings: "tnum";
|
||||
font-feature-settings: "tnum";
|
||||
}
|
||||
|
||||
.ant-spin-spinning {
|
||||
position: static;
|
||||
display: inline-block;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ant-spin-dot {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
background-color: #1890ff;
|
||||
border-radius: 100%;
|
||||
-webkit-transform: scale(0.75);
|
||||
-ms-transform: scale(0.75);
|
||||
transform: scale(0.75);
|
||||
-webkit-transform-origin: 50% 50%;
|
||||
-ms-transform-origin: 50% 50%;
|
||||
transform-origin: 50% 50%;
|
||||
opacity: 0.3;
|
||||
-webkit-animation: antspinmove 1s infinite linear alternate;
|
||||
animation: antSpinMove 1s infinite linear alternate;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item:nth-child(1) {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item:nth-child(2) {
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-animation-delay: 0.4s;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item:nth-child(3) {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
-webkit-animation-delay: 0.8s;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item:nth-child(4) {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
-webkit-animation-delay: 1.2s;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
|
||||
.ant-spin-dot-spin {
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
-webkit-animation: antrotate 1.2s infinite linear;
|
||||
animation: antRotate 1.2s infinite linear;
|
||||
}
|
||||
|
||||
.ant-spin-lg .ant-spin-dot {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.ant-spin-lg .ant-spin-dot i {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
|
||||
.ant-spin-blur {
|
||||
background: #fff;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
min-height: 362px;
|
||||
">
|
||||
<div class="page-loading-warp">
|
||||
<div class="ant-spin ant-spin-lg ant-spin-spinning">
|
||||
<span class="ant-spin-dot ant-spin-dot-spin">
|
||||
<i class="ant-spin-dot-item"></i>
|
||||
<i class="ant-spin-dot-item"></i>
|
||||
<i class="ant-spin-dot-item"></i>
|
||||
<i class="ant-spin-dot-item"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
})();
|
||||
@@ -1,6 +1,10 @@
|
||||
import { ROUTE_AUTH_CODES } from '../config/routes';
|
||||
|
||||
export default function access({ authCodes }: { authCodes: string[] }) {
|
||||
export default function access(params) {
|
||||
if (!params) {
|
||||
return {};
|
||||
}
|
||||
const { authCodes } = params;
|
||||
return Object.keys(ROUTE_AUTH_CODES).reduce((result, key) => {
|
||||
const data = { ...result };
|
||||
const code = ROUTE_AUTH_CODES[key];
|
||||
|
||||
@@ -3,18 +3,16 @@ import S2Icon, { ICON } from '@/components/S2Icon';
|
||||
import type { Settings as LayoutSettings } from '@ant-design/pro-layout';
|
||||
import { Space, Spin, ConfigProvider } from 'antd';
|
||||
import ScaleLoader from 'react-spinners/ScaleLoader';
|
||||
import type { RunTimeLayoutConfig } from 'umi';
|
||||
import { history } from 'umi';
|
||||
import { history, RunTimeLayoutConfig } from '@umijs/max';
|
||||
import defaultSettings from '../config/defaultSettings';
|
||||
import settings from '../config/themeSettings';
|
||||
import { queryCurrentUser } from './services/user';
|
||||
import { traverseRoutes, isMobile, getToken } from './utils/utils';
|
||||
import { deleteUrlQuery, isMobile, getToken } from '@/utils/utils';
|
||||
import { publicPath } from '../config/defaultSettings';
|
||||
import { Copilot } from 'supersonic-chat-sdk';
|
||||
import { getSystemConfig } from '@/services/user';
|
||||
import { configProviderTheme } from '../config/themeSettings';
|
||||
export { request } from './services/request';
|
||||
import { ROUTE_AUTH_CODES } from '../config/routes';
|
||||
import { configProviderTheme } from '../config/themeSettings';
|
||||
|
||||
const replaceRoute = '/';
|
||||
|
||||
@@ -32,14 +30,6 @@ Spin.setDefaultIndicator(
|
||||
<ScaleLoader color={settings['primary-color']} height={25} width={2} radius={2} margin={2} />,
|
||||
);
|
||||
|
||||
export const initialStateConfig = {
|
||||
loading: (
|
||||
<Spin wrapperClassName="initialLoading">
|
||||
<div className="loadingPlaceholder" />
|
||||
</Spin>
|
||||
),
|
||||
};
|
||||
|
||||
const getAuthCodes = (params: any) => {
|
||||
const { currentUser } = params;
|
||||
const codes = [];
|
||||
@@ -66,7 +56,6 @@ export async function getInitialState(): Promise<{
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
let currentUser: any;
|
||||
if (!window.location.pathname.includes('login')) {
|
||||
currentUser = await fetchUserInfo();
|
||||
@@ -91,33 +80,37 @@ export async function getInitialState(): Promise<{
|
||||
};
|
||||
}
|
||||
|
||||
export async function patchRoutes({ routes }) {
|
||||
const config = await getRunningEnv();
|
||||
if (config && config.env) {
|
||||
window.RUNNING_ENV = config.env;
|
||||
const { env } = config;
|
||||
const target = routes[0].routes;
|
||||
if (env) {
|
||||
const envRoutes = traverseRoutes(target, env);
|
||||
// 清空原本route;
|
||||
target.splice(0, 99);
|
||||
// 写入根据环境转换过的的route
|
||||
target.push(...envRoutes);
|
||||
}
|
||||
} else {
|
||||
const target = routes[0].routes;
|
||||
// start-standalone模式不存在env,在此模式下不显示chatSetting
|
||||
const envRoutes = target.filter((item: any) => {
|
||||
return !['chatSetting'].includes(item.name);
|
||||
});
|
||||
target.splice(0, 99);
|
||||
target.push(...envRoutes);
|
||||
}
|
||||
}
|
||||
// export async function patchRoutes({ routes }) {
|
||||
// const config = await getRunningEnv();
|
||||
// if (config && config.env) {
|
||||
// window.RUNNING_ENV = config.env;
|
||||
// const { env } = config;
|
||||
// const target = routes[0].routes;
|
||||
// if (env) {
|
||||
// const envRoutes = traverseRoutes(target, env);
|
||||
// // 清空原本route;
|
||||
// target.splice(0, 99);
|
||||
// // 写入根据环境转换过的的route
|
||||
// target.push(...envRoutes);
|
||||
// }
|
||||
// } else {
|
||||
// const target = routes[0].routes;
|
||||
// // start-standalone模式不存在env,在此模式下不显示chatSetting
|
||||
// const envRoutes = target.filter((item: any) => {
|
||||
// return !['chatSetting'].includes(item.name);
|
||||
// });
|
||||
// target.splice(0, 99);
|
||||
// target.push(...envRoutes);
|
||||
// }
|
||||
// }
|
||||
|
||||
export function onRouteChange() {
|
||||
const title = window.document.title.split('-SuperSonic')[0];
|
||||
if (!title.includes('SuperSonic')) {
|
||||
window.document.title = `${title}-SuperSonic`;
|
||||
} else {
|
||||
window.document.title = 'SuperSonic';
|
||||
}
|
||||
}
|
||||
|
||||
export const layout: RunTimeLayoutConfig = (params) => {
|
||||
@@ -132,21 +125,25 @@ export const layout: RunTimeLayoutConfig = (params) => {
|
||||
<S2Icon
|
||||
icon={ICON.iconlogobiaoshi}
|
||||
size={30}
|
||||
color="#fff"
|
||||
color="#1672fa"
|
||||
style={{ display: 'inline-block', marginTop: 8 }}
|
||||
/>
|
||||
<div className="logo">SuperSonic</div>
|
||||
<div className="logo" style={{ color: '#262626' }}>
|
||||
SuperSonic
|
||||
</div>
|
||||
</Space>
|
||||
),
|
||||
contentStyle: { ...(initialState?.contentStyle || {}) },
|
||||
rightContentRender: () => <RightContent />,
|
||||
disableContentMargin: true,
|
||||
menuHeaderRender: undefined,
|
||||
childrenRender: (dom: any) => {
|
||||
// menuHeaderRender: undefined,
|
||||
childrenRender: (dom) => {
|
||||
return (
|
||||
<ConfigProvider theme={configProviderTheme}>
|
||||
<div
|
||||
style={{ height: location.pathname.includes('chat') ? 'calc(100vh - 56px)' : undefined }}
|
||||
style={{
|
||||
height: location.pathname.includes('chat') ? 'calc(100vh - 56px)' : undefined,
|
||||
}}
|
||||
>
|
||||
{dom}
|
||||
{history.location.pathname !== '/chat' && !isMobile && (
|
||||
|
||||
BIN
webapp/packages/supersonic-fe/src/assets/fonts/DINPro.woff2
Normal file
BIN
webapp/packages/supersonic-fe/src/assets/fonts/DINPro.woff2
Normal file
Binary file not shown.
Binary file not shown.
3
webapp/packages/supersonic-fe/src/assets/icon/vector.svg
Normal file
3
webapp/packages/supersonic-fe/src/assets/icon/vector.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.68182 13.6364H1.13636C0.834981 13.6364 0.545943 13.7561 0.332833 13.9692C0.119724 14.1823 0 14.4713 0 14.7727V23.8636C0 24.165 0.119724 24.4541 0.332833 24.6672C0.545943 24.8803 0.834981 25 1.13636 25H5.68182C5.9832 25 6.27224 24.8803 6.48535 24.6672C6.69846 24.4541 6.81818 24.165 6.81818 23.8636V14.7727C6.81818 14.4713 6.69846 14.1823 6.48535 13.9692C6.27224 13.7561 5.9832 13.6364 5.68182 13.6364ZM4.54545 22.7273H2.27273V15.9091H4.54545V22.7273ZM23.8636 9.09091H19.3182C19.0168 9.09091 18.7278 9.21063 18.5147 9.42374C18.3015 9.63685 18.1818 9.92589 18.1818 10.2273V23.8636C18.1818 24.165 18.3015 24.4541 18.5147 24.6672C18.7278 24.8803 19.0168 25 19.3182 25H23.8636C24.165 25 24.4541 24.8803 24.6672 24.6672C24.8803 24.4541 25 24.165 25 23.8636V10.2273C25 9.92589 24.8803 9.63685 24.6672 9.42374C24.4541 9.21063 24.165 9.09091 23.8636 9.09091ZM22.7273 22.7273H20.4545V11.3636H22.7273V22.7273ZM14.7727 0H10.2273C9.92589 0 9.63685 0.119724 9.42374 0.332833C9.21063 0.545943 9.09091 0.834981 9.09091 1.13636V23.8636C9.09091 24.165 9.21063 24.4541 9.42374 24.6672C9.63685 24.8803 9.92589 25 10.2273 25H14.7727C15.0741 25 15.3631 24.8803 15.5763 24.6672C15.7894 24.4541 15.9091 24.165 15.9091 23.8636V1.13636C15.9091 0.834981 15.7894 0.545943 15.5763 0.332833C15.3631 0.119724 15.0741 0 14.7727 0ZM13.6364 22.7273H11.3636V2.27273H13.6364V22.7273Z" fill="#FF694A"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -1,110 +0,0 @@
|
||||
/* stylelint-disable */
|
||||
.bezierEasingMixin() {
|
||||
@functions: ~`(function() {
|
||||
var NEWTON_ITERATIONS = 4;
|
||||
var NEWTON_MIN_SLOPE = 0.001;
|
||||
var SUBDIVISION_PRECISION = 0.0000001;
|
||||
var SUBDIVISION_MAX_ITERATIONS = 10;
|
||||
|
||||
var kSplineTableSize = 11;
|
||||
var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
|
||||
|
||||
var float32ArraySupported = typeof Float32Array === 'function';
|
||||
|
||||
function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
|
||||
function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
|
||||
function C (aA1) { return 3.0 * aA1; }
|
||||
|
||||
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
|
||||
function calcBezier (aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; }
|
||||
|
||||
// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
|
||||
function getSlope (aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); }
|
||||
|
||||
function binarySubdivide (aX, aA, aB, mX1, mX2) {
|
||||
var currentX, currentT, i = 0;
|
||||
do {
|
||||
currentT = aA + (aB - aA) / 2.0;
|
||||
currentX = calcBezier(currentT, mX1, mX2) - aX;
|
||||
if (currentX > 0.0) {
|
||||
aB = currentT;
|
||||
} else {
|
||||
aA = currentT;
|
||||
}
|
||||
} while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
|
||||
return currentT;
|
||||
}
|
||||
|
||||
function newtonRaphsonIterate (aX, aGuessT, mX1, mX2) {
|
||||
for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
|
||||
var currentSlope = getSlope(aGuessT, mX1, mX2);
|
||||
if (currentSlope === 0.0) {
|
||||
return aGuessT;
|
||||
}
|
||||
var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
|
||||
aGuessT -= currentX / currentSlope;
|
||||
}
|
||||
return aGuessT;
|
||||
}
|
||||
|
||||
var BezierEasing = function (mX1, mY1, mX2, mY2) {
|
||||
if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) {
|
||||
throw new Error('bezier x values must be in [0, 1] range');
|
||||
}
|
||||
|
||||
// Precompute samples table
|
||||
var sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
|
||||
if (mX1 !== mY1 || mX2 !== mY2) {
|
||||
for (var i = 0; i < kSplineTableSize; ++i) {
|
||||
sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
|
||||
}
|
||||
}
|
||||
|
||||
function getTForX (aX) {
|
||||
var intervalStart = 0.0;
|
||||
var currentSample = 1;
|
||||
var lastSample = kSplineTableSize - 1;
|
||||
|
||||
for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
|
||||
intervalStart += kSampleStepSize;
|
||||
}
|
||||
--currentSample;
|
||||
|
||||
// Interpolate to provide an initial guess for t
|
||||
var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
|
||||
var guessForT = intervalStart + dist * kSampleStepSize;
|
||||
|
||||
var initialSlope = getSlope(guessForT, mX1, mX2);
|
||||
if (initialSlope >= NEWTON_MIN_SLOPE) {
|
||||
return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
|
||||
} else if (initialSlope === 0.0) {
|
||||
return guessForT;
|
||||
} else {
|
||||
return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
|
||||
}
|
||||
}
|
||||
|
||||
return function BezierEasing (x) {
|
||||
if (mX1 === mY1 && mX2 === mY2) {
|
||||
return x; // linear
|
||||
}
|
||||
// Because JavaScript number are imprecise, we should guarantee the extremes are right.
|
||||
if (x === 0) {
|
||||
return 0;
|
||||
}
|
||||
if (x === 1) {
|
||||
return 1;
|
||||
}
|
||||
return calcBezier(getTForX(x), mY1, mY2);
|
||||
};
|
||||
};
|
||||
|
||||
this.colorEasing = BezierEasing(0.26, 0.09, 0.37, 0.18);
|
||||
// less 3 requires a return
|
||||
return '';
|
||||
})()`;
|
||||
}
|
||||
// It is hacky way to make this function will be compiled preferentially by less
|
||||
// resolve error: `ReferenceError: colorPalette is not defined`
|
||||
// https://github.com/ant-design/ant-motion/issues/44
|
||||
.bezierEasingMixin();
|
||||
@@ -1,85 +0,0 @@
|
||||
/* stylelint-disable no-duplicate-selectors */
|
||||
@import "bezierEasing";
|
||||
@import "tinyColor";
|
||||
|
||||
// We create a very complex algorithm which take the place of original tint/shade color system
|
||||
// to make sure no one can understand it 👻
|
||||
// and create an entire color palette magicly by inputing just a single primary color.
|
||||
// We are using bezier-curve easing function and some color manipulations like tint/shade/darken/spin
|
||||
.colorPaletteMixin() {
|
||||
@functions: ~`(function() {
|
||||
var hueStep = 2;
|
||||
var saturationStep = 0.16;
|
||||
var saturationStep2 = 0.05;
|
||||
var brightnessStep1 = 0.05;
|
||||
var brightnessStep2 = 0.15;
|
||||
var lightColorCount = 5;
|
||||
var darkColorCount = 4;
|
||||
|
||||
var getHue = function(hsv, i, isLight) {
|
||||
var hue;
|
||||
if (hsv.h >= 60 && hsv.h <= 240) {
|
||||
hue = isLight ? hsv.h - hueStep * i : hsv.h + hueStep * i;
|
||||
} else {
|
||||
hue = isLight ? hsv.h + hueStep * i : hsv.h - hueStep * i;
|
||||
}
|
||||
if (hue < 0) {
|
||||
hue += 360;
|
||||
} else if (hue >= 360) {
|
||||
hue -= 360;
|
||||
}
|
||||
return Math.round(hue);
|
||||
};
|
||||
var getSaturation = function(hsv, i, isLight) {
|
||||
// grey color don't change saturation
|
||||
if (hsv.h === 0 && hsv.s === 0) {
|
||||
return hsv.s;
|
||||
}
|
||||
var saturation;
|
||||
if (isLight) {
|
||||
saturation = hsv.s - saturationStep * i;
|
||||
} else if (i === darkColorCount) {
|
||||
saturation = hsv.s + saturationStep;
|
||||
} else {
|
||||
saturation = hsv.s + saturationStep2 * i;
|
||||
}
|
||||
if (saturation > 1) {
|
||||
saturation = 1;
|
||||
}
|
||||
if (isLight && i === lightColorCount && saturation > 0.1) {
|
||||
saturation = 0.1;
|
||||
}
|
||||
if (saturation < 0.06) {
|
||||
saturation = 0.06;
|
||||
}
|
||||
return Number(saturation.toFixed(2));
|
||||
};
|
||||
var getValue = function(hsv, i, isLight) {
|
||||
var value;
|
||||
if (isLight) {
|
||||
value = hsv.v + brightnessStep1 * i;
|
||||
}else{
|
||||
value = hsv.v - brightnessStep2 * i
|
||||
}
|
||||
if (value > 1) {
|
||||
value = 1;
|
||||
}
|
||||
return Number(value.toFixed(2))
|
||||
};
|
||||
|
||||
this.colorPalette = function(color, index) {
|
||||
var isLight = index <= 6;
|
||||
var hsv = tinycolor(color).toHsv();
|
||||
var i = isLight ? lightColorCount + 1 - index : index - lightColorCount - 1;
|
||||
return tinycolor({
|
||||
h: getHue(hsv, i, isLight),
|
||||
s: getSaturation(hsv, i, isLight),
|
||||
v: getValue(hsv, i, isLight),
|
||||
}).toHexString();
|
||||
};
|
||||
})()`;
|
||||
}
|
||||
// It is hacky way to make this function will be compiled preferentially by less
|
||||
// resolve error: `ReferenceError: colorPalette is not defined`
|
||||
// https://github.com/ant-design/ant-motion/issues/44
|
||||
.colorPaletteMixin();
|
||||
@@ -1,162 +0,0 @@
|
||||
@import 'colorPalette';
|
||||
|
||||
// color palettes
|
||||
@blue-base: #1890ff;
|
||||
@blue-1: color(~`colorPalette('@{blue-6}', 1) `);
|
||||
@blue-2: color(~`colorPalette('@{blue-6}', 2) `);
|
||||
@blue-3: color(~`colorPalette('@{blue-6}', 3) `);
|
||||
@blue-4: color(~`colorPalette('@{blue-6}', 4) `);
|
||||
@blue-5: color(~`colorPalette('@{blue-6}', 5) `);
|
||||
@blue-6: @blue-base;
|
||||
@blue-7: color(~`colorPalette('@{blue-6}', 7) `);
|
||||
@blue-8: color(~`colorPalette('@{blue-6}', 8) `);
|
||||
@blue-9: color(~`colorPalette('@{blue-6}', 9) `);
|
||||
@blue-10: color(~`colorPalette('@{blue-6}', 10) `);
|
||||
|
||||
@purple-base: #722ed1;
|
||||
@purple-1: color(~`colorPalette('@{purple-6}', 1) `);
|
||||
@purple-2: color(~`colorPalette('@{purple-6}', 2) `);
|
||||
@purple-3: color(~`colorPalette('@{purple-6}', 3) `);
|
||||
@purple-4: color(~`colorPalette('@{purple-6}', 4) `);
|
||||
@purple-5: color(~`colorPalette('@{purple-6}', 5) `);
|
||||
@purple-6: @purple-base;
|
||||
@purple-7: color(~`colorPalette('@{purple-6}', 7) `);
|
||||
@purple-8: color(~`colorPalette('@{purple-6}', 8) `);
|
||||
@purple-9: color(~`colorPalette('@{purple-6}', 9) `);
|
||||
@purple-10: color(~`colorPalette('@{purple-6}', 10) `);
|
||||
|
||||
@cyan-base: #13c2c2;
|
||||
@cyan-1: color(~`colorPalette('@{cyan-6}', 1) `);
|
||||
@cyan-2: color(~`colorPalette('@{cyan-6}', 2) `);
|
||||
@cyan-3: color(~`colorPalette('@{cyan-6}', 3) `);
|
||||
@cyan-4: color(~`colorPalette('@{cyan-6}', 4) `);
|
||||
@cyan-5: color(~`colorPalette('@{cyan-6}', 5) `);
|
||||
@cyan-6: @cyan-base;
|
||||
@cyan-7: color(~`colorPalette('@{cyan-6}', 7) `);
|
||||
@cyan-8: color(~`colorPalette('@{cyan-6}', 8) `);
|
||||
@cyan-9: color(~`colorPalette('@{cyan-6}', 9) `);
|
||||
@cyan-10: color(~`colorPalette('@{cyan-6}', 10) `);
|
||||
|
||||
@green-base: #52c41a;
|
||||
@green-1: color(~`colorPalette('@{green-6}', 1) `);
|
||||
@green-2: color(~`colorPalette('@{green-6}', 2) `);
|
||||
@green-3: color(~`colorPalette('@{green-6}', 3) `);
|
||||
@green-4: color(~`colorPalette('@{green-6}', 4) `);
|
||||
@green-5: color(~`colorPalette('@{green-6}', 5) `);
|
||||
@green-6: @green-base;
|
||||
@green-7: color(~`colorPalette('@{green-6}', 7) `);
|
||||
@green-8: color(~`colorPalette('@{green-6}', 8) `);
|
||||
@green-9: color(~`colorPalette('@{green-6}', 9) `);
|
||||
@green-10: color(~`colorPalette('@{green-6}', 10) `);
|
||||
|
||||
@magenta-base: #eb2f96;
|
||||
@magenta-1: color(~`colorPalette('@{magenta-6}', 1) `);
|
||||
@magenta-2: color(~`colorPalette('@{magenta-6}', 2) `);
|
||||
@magenta-3: color(~`colorPalette('@{magenta-6}', 3) `);
|
||||
@magenta-4: color(~`colorPalette('@{magenta-6}', 4) `);
|
||||
@magenta-5: color(~`colorPalette('@{magenta-6}', 5) `);
|
||||
@magenta-6: @magenta-base;
|
||||
@magenta-7: color(~`colorPalette('@{magenta-6}', 7) `);
|
||||
@magenta-8: color(~`colorPalette('@{magenta-6}', 8) `);
|
||||
@magenta-9: color(~`colorPalette('@{magenta-6}', 9) `);
|
||||
@magenta-10: color(~`colorPalette('@{magenta-6}', 10) `);
|
||||
|
||||
// alias of magenta
|
||||
@pink-base: #eb2f96;
|
||||
@pink-1: color(~`colorPalette('@{pink-6}', 1) `);
|
||||
@pink-2: color(~`colorPalette('@{pink-6}', 2) `);
|
||||
@pink-3: color(~`colorPalette('@{pink-6}', 3) `);
|
||||
@pink-4: color(~`colorPalette('@{pink-6}', 4) `);
|
||||
@pink-5: color(~`colorPalette('@{pink-6}', 5) `);
|
||||
@pink-6: @pink-base;
|
||||
@pink-7: color(~`colorPalette('@{pink-6}', 7) `);
|
||||
@pink-8: color(~`colorPalette('@{pink-6}', 8) `);
|
||||
@pink-9: color(~`colorPalette('@{pink-6}', 9) `);
|
||||
@pink-10: color(~`colorPalette('@{pink-6}', 10) `);
|
||||
|
||||
@red-base: #f5222d;
|
||||
@red-1: color(~`colorPalette('@{red-6}', 1) `);
|
||||
@red-2: color(~`colorPalette('@{red-6}', 2) `);
|
||||
@red-3: color(~`colorPalette('@{red-6}', 3) `);
|
||||
@red-4: color(~`colorPalette('@{red-6}', 4) `);
|
||||
@red-5: color(~`colorPalette('@{red-6}', 5) `);
|
||||
@red-6: @red-base;
|
||||
@red-7: color(~`colorPalette('@{red-6}', 7) `);
|
||||
@red-8: color(~`colorPalette('@{red-6}', 8) `);
|
||||
@red-9: color(~`colorPalette('@{red-6}', 9) `);
|
||||
@red-10: color(~`colorPalette('@{red-6}', 10) `);
|
||||
|
||||
@orange-base: #fa8c16;
|
||||
@orange-1: color(~`colorPalette('@{orange-6}', 1) `);
|
||||
@orange-2: color(~`colorPalette('@{orange-6}', 2) `);
|
||||
@orange-3: color(~`colorPalette('@{orange-6}', 3) `);
|
||||
@orange-4: color(~`colorPalette('@{orange-6}', 4) `);
|
||||
@orange-5: color(~`colorPalette('@{orange-6}', 5) `);
|
||||
@orange-6: @orange-base;
|
||||
@orange-7: color(~`colorPalette('@{orange-6}', 7) `);
|
||||
@orange-8: color(~`colorPalette('@{orange-6}', 8) `);
|
||||
@orange-9: color(~`colorPalette('@{orange-6}', 9) `);
|
||||
@orange-10: color(~`colorPalette('@{orange-6}', 10) `);
|
||||
|
||||
@yellow-base: #fadb14;
|
||||
@yellow-1: color(~`colorPalette('@{yellow-6}', 1) `);
|
||||
@yellow-2: color(~`colorPalette('@{yellow-6}', 2) `);
|
||||
@yellow-3: color(~`colorPalette('@{yellow-6}', 3) `);
|
||||
@yellow-4: color(~`colorPalette('@{yellow-6}', 4) `);
|
||||
@yellow-5: color(~`colorPalette('@{yellow-6}', 5) `);
|
||||
@yellow-6: @yellow-base;
|
||||
@yellow-7: color(~`colorPalette('@{yellow-6}', 7) `);
|
||||
@yellow-8: color(~`colorPalette('@{yellow-6}', 8) `);
|
||||
@yellow-9: color(~`colorPalette('@{yellow-6}', 9) `);
|
||||
@yellow-10: color(~`colorPalette('@{yellow-6}', 10) `);
|
||||
|
||||
@volcano-base: #fa541c;
|
||||
@volcano-1: color(~`colorPalette('@{volcano-6}', 1) `);
|
||||
@volcano-2: color(~`colorPalette('@{volcano-6}', 2) `);
|
||||
@volcano-3: color(~`colorPalette('@{volcano-6}', 3) `);
|
||||
@volcano-4: color(~`colorPalette('@{volcano-6}', 4) `);
|
||||
@volcano-5: color(~`colorPalette('@{volcano-6}', 5) `);
|
||||
@volcano-6: @volcano-base;
|
||||
@volcano-7: color(~`colorPalette('@{volcano-6}', 7) `);
|
||||
@volcano-8: color(~`colorPalette('@{volcano-6}', 8) `);
|
||||
@volcano-9: color(~`colorPalette('@{volcano-6}', 9) `);
|
||||
@volcano-10: color(~`colorPalette('@{volcano-6}', 10) `);
|
||||
|
||||
@geekblue-base: #2f54eb;
|
||||
@geekblue-1: color(~`colorPalette('@{geekblue-6}', 1) `);
|
||||
@geekblue-2: color(~`colorPalette('@{geekblue-6}', 2) `);
|
||||
@geekblue-3: color(~`colorPalette('@{geekblue-6}', 3) `);
|
||||
@geekblue-4: color(~`colorPalette('@{geekblue-6}', 4) `);
|
||||
@geekblue-5: color(~`colorPalette('@{geekblue-6}', 5) `);
|
||||
@geekblue-6: @geekblue-base;
|
||||
@geekblue-7: color(~`colorPalette('@{geekblue-6}', 7) `);
|
||||
@geekblue-8: color(~`colorPalette('@{geekblue-6}', 8) `);
|
||||
@geekblue-9: color(~`colorPalette('@{geekblue-6}', 9) `);
|
||||
@geekblue-10: color(~`colorPalette('@{geekblue-6}', 10) `);
|
||||
|
||||
@lime-base: #a0d911;
|
||||
@lime-1: color(~`colorPalette('@{lime-6}', 1) `);
|
||||
@lime-2: color(~`colorPalette('@{lime-6}', 2) `);
|
||||
@lime-3: color(~`colorPalette('@{lime-6}', 3) `);
|
||||
@lime-4: color(~`colorPalette('@{lime-6}', 4) `);
|
||||
@lime-5: color(~`colorPalette('@{lime-6}', 5) `);
|
||||
@lime-6: @lime-base;
|
||||
@lime-7: color(~`colorPalette('@{lime-6}', 7) `);
|
||||
@lime-8: color(~`colorPalette('@{lime-6}', 8) `);
|
||||
@lime-9: color(~`colorPalette('@{lime-6}', 9) `);
|
||||
@lime-10: color(~`colorPalette('@{lime-6}', 10) `);
|
||||
|
||||
@gold-base: #faad14;
|
||||
@gold-1: color(~`colorPalette('@{gold-6}', 1) `);
|
||||
@gold-2: color(~`colorPalette('@{gold-6}', 2) `);
|
||||
@gold-3: color(~`colorPalette('@{gold-6}', 3) `);
|
||||
@gold-4: color(~`colorPalette('@{gold-6}', 4) `);
|
||||
@gold-5: color(~`colorPalette('@{gold-6}', 5) `);
|
||||
@gold-6: @gold-base;
|
||||
@gold-7: color(~`colorPalette('@{gold-6}', 7) `);
|
||||
@gold-8: color(~`colorPalette('@{gold-6}', 8) `);
|
||||
@gold-9: color(~`colorPalette('@{gold-6}', 9) `);
|
||||
@gold-10: color(~`colorPalette('@{gold-6}', 10) `);
|
||||
|
||||
@preset-colors: pink, magenta, red, volcano, orange, yellow, gold, cyan, lime, green, blue, geekblue,
|
||||
purple;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
@root-entry-name: default;
|
||||
|
||||
@import './themes/compact.less';
|
||||
@import './core/index';
|
||||
@@ -1,10 +0,0 @@
|
||||
// Config global less under antd
|
||||
[class^=~'@{ant-prefix}-'],
|
||||
[class*=~' @{ant-prefix}-'] {
|
||||
// remove the clear button of a text input control in IE10+
|
||||
&::-ms-clear,
|
||||
input::-ms-clear,
|
||||
input::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,491 +0,0 @@
|
||||
/* stylelint-disable property-no-vendor-prefix, at-rule-no-vendor-prefix */
|
||||
|
||||
// Reboot
|
||||
//
|
||||
// Normalization of HTML elements, manually forked from Normalize.css to remove
|
||||
// styles targeting irrelevant browsers while applying new styles.
|
||||
//
|
||||
// Normalize is licensed MIT. https://github.com/necolas/normalize.css
|
||||
|
||||
// HTML & Body reset
|
||||
@{html-selector},
|
||||
body {
|
||||
.square(100%);
|
||||
}
|
||||
|
||||
// remove the clear button of a text input control in IE10+
|
||||
input::-ms-clear,
|
||||
input::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Document
|
||||
//
|
||||
// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
|
||||
// 2. Change the default font family in all browsers.
|
||||
// 3. Correct the line height in all browsers.
|
||||
// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.
|
||||
// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so
|
||||
// we force a non-overlapping, non-auto-hiding scrollbar to counteract.
|
||||
// 6. Change the default tap highlight to be completely transparent in iOS.
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box; // 1
|
||||
}
|
||||
|
||||
@{html-selector} {
|
||||
font-family: sans-serif; // 2
|
||||
line-height: 1.15; // 3
|
||||
-webkit-text-size-adjust: 100%; // 4
|
||||
-ms-text-size-adjust: 100%; // 4
|
||||
-ms-overflow-style: scrollbar; // 5
|
||||
-webkit-tap-highlight-color: fade(@black, 0%); // 6
|
||||
}
|
||||
|
||||
// IE10+ doesn't honor `<meta name="viewport">` in some cases.
|
||||
@-ms-viewport {
|
||||
width: device-width;
|
||||
}
|
||||
|
||||
// Body
|
||||
//
|
||||
// 1. remove the margin in all browsers.
|
||||
// 2. As a best practice, apply a default `body-background`.
|
||||
|
||||
body {
|
||||
margin: 0; // 1
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
font-family: @font-family;
|
||||
font-variant: @font-variant-base;
|
||||
line-height: @line-height-base;
|
||||
background-color: @body-background; // 2
|
||||
font-feature-settings: @font-feature-settings-base;
|
||||
}
|
||||
|
||||
// Suppress the focus outline on elements that cannot be accessed via keyboard.
|
||||
// This prevents an unwanted focus outline from appearing around elements that
|
||||
// might still respond to pointer events.
|
||||
//
|
||||
// Credit: https://github.com/suitcss/base
|
||||
[tabindex='-1']:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
// Content grouping
|
||||
//
|
||||
// 1. Add the correct box sizing in Firefox.
|
||||
// 2. Show the overflow in Edge and IE.
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; // 1
|
||||
height: 0; // 1
|
||||
overflow: visible; // 2
|
||||
}
|
||||
|
||||
//
|
||||
// Typography
|
||||
//
|
||||
|
||||
// remove top margins from headings
|
||||
//
|
||||
// By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top
|
||||
// margin for easier control within type scales as it avoids margin collapsing.
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5em;
|
||||
color: @heading-color;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
// Reset margins on paragraphs
|
||||
//
|
||||
// Similarly, the top margin on `<p>`s get reset. However, we also reset the
|
||||
// bottom margin to use `em` units instead of `em`.
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
// Abbreviations
|
||||
//
|
||||
// 1. remove the bottom border in Firefox 39-.
|
||||
// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
// 3. Add explicit cursor to indicate changed behavior.
|
||||
// 4. Duplicate behavior to the data-* attribute for our tooltip plugin
|
||||
|
||||
abbr[title],
|
||||
abbr[data-original-title] {
|
||||
// 4
|
||||
text-decoration: underline; // 2
|
||||
text-decoration: underline dotted; // 2
|
||||
border-bottom: 0; // 1
|
||||
cursor: help; // 3
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1em;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
input[type='text'],
|
||||
input[type='password'],
|
||||
input[type='number'],
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5em;
|
||||
margin-left: 0; // Undo browser default
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
dfn {
|
||||
font-style: italic; // Add the correct font style in Android 4.3-
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%; // Add the correct font size in all browsers
|
||||
}
|
||||
|
||||
//
|
||||
// Prevent `sub` and `sup` elements from affecting the line height in
|
||||
// all browsers.
|
||||
//
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
//
|
||||
// Links
|
||||
//
|
||||
|
||||
a {
|
||||
color: @link-color;
|
||||
text-decoration: @link-decoration;
|
||||
background-color: transparent; // remove the gray background on active links in IE 10.
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
-webkit-text-decoration-skip: objects; // remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||
|
||||
&:hover {
|
||||
color: @link-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @link-active-color;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&:hover {
|
||||
text-decoration: @link-hover-decoration;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/22503
|
||||
&:focus {
|
||||
text-decoration: @link-focus-decoration;
|
||||
outline: @link-focus-outline;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Code
|
||||
//
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-size: 1em; // Correct the odd `em` font sizing in all browsers.
|
||||
font-family: @code-family;
|
||||
}
|
||||
|
||||
pre {
|
||||
// remove browser default top margin
|
||||
margin-top: 0;
|
||||
// Reset browser default of `1em` to use `em`s
|
||||
margin-bottom: 1em;
|
||||
// Don't allow content to break outside
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
//
|
||||
// Figures
|
||||
//
|
||||
figure {
|
||||
// Apply a consistent margin strategy (matches our type styles).
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
//
|
||||
// Images and content
|
||||
//
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none; // remove the border on images inside links in IE 10-.
|
||||
}
|
||||
|
||||
// Avoid 300ms click delay on touch devices that support the `touch-action` CSS property.
|
||||
//
|
||||
// In particular, unlike most other browsers, IE11+Edge on Windows 10 on touch devices and IE Mobile 10-11
|
||||
// DON'T remove the click delay when `<meta name="viewport" content="width=device-width">` is present.
|
||||
// However, they DO support emoving the click delay via `touch-action: manipulation`.
|
||||
// See:
|
||||
// * https://getbootstrap.com/docs/4.0/content/reboot/#click-delay-optimization-for-touch
|
||||
// * http://caniuse.com/#feat=css-touch-action
|
||||
// * https://patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay
|
||||
|
||||
a,
|
||||
area,
|
||||
button,
|
||||
[role='button'],
|
||||
input:not([type='range']),
|
||||
label,
|
||||
select,
|
||||
summary,
|
||||
textarea {
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
//
|
||||
// Tables
|
||||
//
|
||||
|
||||
table {
|
||||
border-collapse: collapse; // Prevent double borders
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.75em;
|
||||
padding-bottom: 0.3em;
|
||||
color: @text-color-secondary;
|
||||
text-align: left;
|
||||
caption-side: bottom;
|
||||
}
|
||||
|
||||
//
|
||||
// Forms
|
||||
//
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0; // remove the margin in Firefox and Safari
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
overflow: visible; // Show the overflow in Edge
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none; // remove the inheritance of text transform in Firefox
|
||||
}
|
||||
|
||||
// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||
// controls in Android 4.
|
||||
// 2. Correct the inability to style clickable types in iOS and Safari.
|
||||
button,
|
||||
@{html-selector} [type="button"], /* 1 */
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button; // 2
|
||||
}
|
||||
|
||||
// remove inner border and padding from Firefox, but don't restore the outline like Normalize.
|
||||
button::-moz-focus-inner,
|
||||
[type='button']::-moz-focus-inner,
|
||||
[type='reset']::-moz-focus-inner,
|
||||
[type='submit']::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
input[type='radio'],
|
||||
input[type='checkbox'] {
|
||||
box-sizing: border-box; // 1. Add the correct box sizing in IE 10-
|
||||
padding: 0; // 2. remove the padding in IE 10-
|
||||
}
|
||||
|
||||
input[type='date'],
|
||||
input[type='time'],
|
||||
input[type='datetime-local'],
|
||||
input[type='month'] {
|
||||
// remove the default appearance of temporal inputs to avoid a Mobile Safari
|
||||
// bug where setting a custom line-height prevents text from being vertically
|
||||
// centered within the input.
|
||||
// See https://bugs.webkit.org/show_bug.cgi?id=139848
|
||||
// and https://github.com/twbs/bootstrap/issues/11266
|
||||
-webkit-appearance: listbox;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto; // remove the default vertical scrollbar in IE.
|
||||
// Textareas should really only resize vertically so they don't break their (horizontal) containers.
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
// Browsers set a default `min-width: min-content;` on fieldsets,
|
||||
// unlike e.g. `<div>`s, which have `min-width: 0;` by default.
|
||||
// So we reset that to ensure fieldsets behave more like a standard block element.
|
||||
// See https://github.com/twbs/bootstrap/issues/12359
|
||||
// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
// Reset the default outline behavior of fieldsets so they don't affect page layout.
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// 1. Correct the text wrapping in Edge and IE.
|
||||
// 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
legend {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%; // 1
|
||||
margin-bottom: 0.5em;
|
||||
padding: 0;
|
||||
color: inherit; // 2
|
||||
font-size: 1.5em;
|
||||
line-height: inherit;
|
||||
white-space: normal; // 1
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
}
|
||||
|
||||
// Correct the cursor style of incement and decement buttons in Chrome.
|
||||
[type='number']::-webkit-inner-spin-button,
|
||||
[type='number']::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type='search'] {
|
||||
// This overrides the extra rounded corners on search inputs in iOS so that our
|
||||
// `.form-control` class can properly style them. Note that this cannot simply
|
||||
// be added to `.form-control` as it's not specific enough. For details, see
|
||||
// https://github.com/twbs/bootstrap/issues/11586.
|
||||
outline-offset: -2px; // 2. Correct the outline style in Safari.
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
//
|
||||
// remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
//
|
||||
|
||||
[type='search']::-webkit-search-cancel-button,
|
||||
[type='search']::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
//
|
||||
// 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
// 2. Change font properties to `inherit` in Safari.
|
||||
//
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit; // 2
|
||||
-webkit-appearance: button; // 1
|
||||
}
|
||||
|
||||
//
|
||||
// Correct element displays
|
||||
//
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item; // Add the correct display in all browsers
|
||||
}
|
||||
|
||||
template {
|
||||
display: none; // Add the correct display in IE
|
||||
}
|
||||
|
||||
// Always hide an element with the `hidden` HTML attribute (from PureCSS).
|
||||
// Needed for proper display in IE 10-.
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: @yellow-1;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: @text-color-inverse;
|
||||
background: @text-selection-bg;
|
||||
}
|
||||
|
||||
// Utility classes
|
||||
.clearfix {
|
||||
.clearfix();
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
@import '../themes/index';
|
||||
@import '../mixins/iconfont';
|
||||
|
||||
.@{iconfont-css-prefix} {
|
||||
.iconfont-mixin();
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/33703
|
||||
& > & {
|
||||
line-height: 0;
|
||||
vertical-align: 0;
|
||||
}
|
||||
|
||||
&[tabindex] {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-spin,
|
||||
.@{iconfont-css-prefix}-spin::before {
|
||||
display: inline-block;
|
||||
animation: loadingCircle 1s infinite linear;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@import '../mixins/index';
|
||||
@import 'base';
|
||||
@import 'global';
|
||||
@import 'iconfont';
|
||||
@import 'motion';
|
||||
@@ -1,22 +0,0 @@
|
||||
// @import '../mixins/motion'; This has moved to theme/xxx inside.
|
||||
@import 'motion/fade';
|
||||
@import 'motion/move';
|
||||
@import 'motion/other';
|
||||
@import 'motion/slide';
|
||||
@import 'motion/zoom';
|
||||
|
||||
// For common/openAnimation
|
||||
.ant-motion-collapse-legacy {
|
||||
overflow: hidden;
|
||||
|
||||
&-active {
|
||||
transition: height @animation-duration-base @ease-in-out,
|
||||
opacity @animation-duration-base @ease-in-out !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-motion-collapse {
|
||||
overflow: hidden;
|
||||
transition: height @animation-duration-base @ease-in-out,
|
||||
opacity @animation-duration-base @ease-in-out !important;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
.fade-motion(@className, @keyframeName) {
|
||||
@name: ~'@{ant-prefix}-@{className}';
|
||||
.make-motion(@name, @keyframeName);
|
||||
.@{name}-enter,
|
||||
.@{name}-appear {
|
||||
opacity: 0;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
.@{name}-leave {
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
}
|
||||
|
||||
.fade-motion(fade, antFade);
|
||||
|
||||
@keyframes antFadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antFadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
.move-motion(@className, @keyframeName) {
|
||||
@name: ~'@{ant-prefix}-@{className}';
|
||||
.make-motion(@name, @keyframeName);
|
||||
.@{name}-enter,
|
||||
.@{name}-appear {
|
||||
opacity: 0;
|
||||
animation-timing-function: @ease-out-circ;
|
||||
}
|
||||
.@{name}-leave {
|
||||
animation-timing-function: @ease-in-circ;
|
||||
}
|
||||
}
|
||||
|
||||
.move-motion(move-up, antMoveUp);
|
||||
.move-motion(move-down, antMoveDown);
|
||||
.move-motion(move-left, antMoveLeft);
|
||||
.move-motion(move-right, antMoveRight);
|
||||
|
||||
@keyframes antMoveDownIn {
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveDownOut {
|
||||
0% {
|
||||
transform: translateY(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveLeftIn {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveLeftOut {
|
||||
0% {
|
||||
transform: translateX(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveRightIn {
|
||||
0% {
|
||||
transform: translateX(100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveRightOut {
|
||||
0% {
|
||||
transform: translateX(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveUpIn {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antMoveUpOut {
|
||||
0% {
|
||||
transform: translateY(0%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
@keyframes loadingCircle {
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@click-animating-true: ~"[@{ant-prefix}-click-animating='true']";
|
||||
@click-animating-with-extra-node-true: ~"[@{ant-prefix}-click-animating-without-extra-node='true']";
|
||||
|
||||
@{click-animating-true},
|
||||
@{click-animating-with-extra-node-true} {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
html {
|
||||
--antd-wave-shadow-color: @primary-color;
|
||||
--scroll-bar: 0;
|
||||
}
|
||||
|
||||
@click-animating-with-extra-node-true-after: ~'@{click-animating-with-extra-node-true}::after';
|
||||
|
||||
@{click-animating-with-extra-node-true-after},
|
||||
.@{ant-prefix}-click-animating-node {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
border-radius: inherit;
|
||||
box-shadow: 0 0 0 0 @primary-color;
|
||||
box-shadow: 0 0 0 0 var(--antd-wave-shadow-color);
|
||||
opacity: 0.2;
|
||||
animation: fadeEffect 2s @ease-out-circ, waveEffect 0.4s @ease-out-circ;
|
||||
animation-fill-mode: forwards;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes waveEffect {
|
||||
100% {
|
||||
box-shadow: 0 0 0 @primary-color;
|
||||
box-shadow: 0 0 0 @wave-animation-width var(--antd-wave-shadow-color);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeEffect {
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
.slide-motion(@className, @keyframeName) {
|
||||
@name: ~'@{ant-prefix}-@{className}';
|
||||
.make-motion(@name, @keyframeName);
|
||||
.@{name}-enter,
|
||||
.@{name}-appear {
|
||||
transform: scale(0);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
animation-timing-function: @ease-out-quint;
|
||||
}
|
||||
.@{name}-leave {
|
||||
animation-timing-function: @ease-in-quint;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-motion(slide-up, antSlideUp);
|
||||
.slide-motion(slide-down, antSlideDown);
|
||||
.slide-motion(slide-left, antSlideLeft);
|
||||
.slide-motion(slide-right, antSlideRight);
|
||||
|
||||
@keyframes antSlideUpIn {
|
||||
0% {
|
||||
transform: scaleY(0.8);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleY(1);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideUpOut {
|
||||
0% {
|
||||
transform: scaleY(1);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleY(0.8);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideDownIn {
|
||||
0% {
|
||||
transform: scaleY(0.8);
|
||||
transform-origin: 100% 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleY(1);
|
||||
transform-origin: 100% 100%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideDownOut {
|
||||
0% {
|
||||
transform: scaleY(1);
|
||||
transform-origin: 100% 100%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleY(0.8);
|
||||
transform-origin: 100% 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideLeftIn {
|
||||
0% {
|
||||
transform: scaleX(0.8);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(1);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideLeftOut {
|
||||
0% {
|
||||
transform: scaleX(1);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(0.8);
|
||||
transform-origin: 0% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideRightIn {
|
||||
0% {
|
||||
transform: scaleX(0.8);
|
||||
transform-origin: 100% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(1);
|
||||
transform-origin: 100% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSlideRightOut {
|
||||
0% {
|
||||
transform: scaleX(1);
|
||||
transform-origin: 100% 0%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(0.8);
|
||||
transform-origin: 100% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
.zoom-motion(@className, @keyframeName, @duration: @animation-duration-base) {
|
||||
@name: ~'@{ant-prefix}-@{className}';
|
||||
.make-motion(@name, @keyframeName, @duration);
|
||||
.@{name}-enter,
|
||||
.@{name}-appear {
|
||||
transform: scale(0); // need this by yiminghe
|
||||
opacity: 0;
|
||||
animation-timing-function: @ease-out-circ;
|
||||
|
||||
&-prepare {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
.@{name}-leave {
|
||||
animation-timing-function: @ease-in-out-circ;
|
||||
}
|
||||
}
|
||||
|
||||
// For Modal, Select choosen item
|
||||
.zoom-motion(zoom, antZoom);
|
||||
// For Popover, Popconfirm, Dropdown
|
||||
.zoom-motion(zoom-big, antZoomBig);
|
||||
// For Tooltip
|
||||
.zoom-motion(zoom-big-fast, antZoomBig, @animation-duration-fast);
|
||||
|
||||
.zoom-motion(zoom-up, antZoomUp);
|
||||
.zoom-motion(zoom-down, antZoomDown);
|
||||
.zoom-motion(zoom-left, antZoomLeft);
|
||||
.zoom-motion(zoom-right, antZoomRight);
|
||||
|
||||
@keyframes antZoomIn {
|
||||
0% {
|
||||
transform: scale(0.2);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.2);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomBigIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomBigOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomUpIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 50% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
transform-origin: 50% 0%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomUpOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
transform-origin: 50% 0%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 50% 0%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomLeftIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 0% 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
transform-origin: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomLeftOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
transform-origin: 0% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 0% 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomRightIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 100% 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
transform-origin: 100% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomRightOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
transform-origin: 100% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 100% 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomDownIn {
|
||||
0% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 50% 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
transform-origin: 50% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomDownOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
transform-origin: 50% 100%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8);
|
||||
transform-origin: 50% 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
import './index.css';
|
||||
@@ -1,4 +0,0 @@
|
||||
@root-entry-name: default;
|
||||
|
||||
@import './themes/dark.less';
|
||||
@import './core/index';
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
// This is same as `index.less` but given `root-entry-name` for `dist/antd.less` usage
|
||||
@root-entry-name: default;
|
||||
|
||||
@import './index';
|
||||
@@ -1,2 +0,0 @@
|
||||
@import './themes/index';
|
||||
@import './core/index';
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
import './index.less';
|
||||
@@ -1 +0,0 @@
|
||||
import './index.less';
|
||||
@@ -1,3 +0,0 @@
|
||||
@root-entry-name: default;
|
||||
|
||||
@import './index-pure.less';
|
||||
@@ -1,7 +0,0 @@
|
||||
.box(@position: absolute) {
|
||||
position: @position;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// mixins for clearfix
|
||||
// ------------------------
|
||||
.clearfix() {
|
||||
// https://github.com/ant-design/ant-design/issues/21301#issuecomment-583955229
|
||||
&::before {
|
||||
display: table;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&::after {
|
||||
// https://github.com/ant-design/ant-design/issues/21864
|
||||
display: table;
|
||||
clear: both;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
.compact-item-vertical-border-radius(@prefix-cls) {
|
||||
&-item:not(&-first-item):not(&-last-item) {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&-item&-first-item:not(&-last-item) {
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
&-item&-last-item:not(&-first-item) {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.compact-item-vertical-border(@prefix-cls) {
|
||||
// border collapse
|
||||
&-item:not(&-last-item) {
|
||||
margin-bottom: -@border-width-base;
|
||||
}
|
||||
|
||||
&-item {
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compact-item-vertical(@prefix-cls) {
|
||||
&-compact-vertical {
|
||||
.compact-item-vertical-border(@prefix-cls);
|
||||
.compact-item-vertical-border-radius(@prefix-cls);
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
.compact-item-border-radius(@prefix-cls, @bordered-item-cls: null) {
|
||||
& when (@bordered-item-cls = null) {
|
||||
// border-radius
|
||||
&-item:not(&-first-item):not(&-last-item).@{prefix-cls} {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&-item.@{prefix-cls}&-first-item:not(&-last-item):not(&-item-rtl) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
&-item.@{prefix-cls}&-last-item:not(&-first-item):not(&-item-rtl) {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
// ----------rtl for first item----------
|
||||
&-item.@{prefix-cls}&-item-rtl&-first-item:not(&-last-item) {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
// ----------rtl for last item----------
|
||||
&-item.@{prefix-cls}&-item-rtl&-last-item:not(&-first-item) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& when (not (@bordered-item-cls = null)) {
|
||||
// border-radius
|
||||
&-item:not(&-first-item):not(&-last-item).@{prefix-cls} > .@{bordered-item-cls} {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&-item&-first-item.@{prefix-cls}:not(&-last-item):not(&-item-rtl) > .@{bordered-item-cls} {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
&-item&-last-item.@{prefix-cls}:not(&-first-item):not(&-item-rtl) > .@{bordered-item-cls} {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
// ----------rtl for first item----------
|
||||
&-item.@{prefix-cls}&-first-item&-item-rtl:not(&-last-item) > .@{bordered-item-cls} {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
// ----------rtl for last item----------
|
||||
&-item.@{prefix-cls}&-last-item&-item-rtl:not(&-first-item) > .@{bordered-item-cls} {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compact-item-border(@prefix-cls, @bordered-item-cls: null, @special-open-cls) {
|
||||
& when (@bordered-item-cls = null) {
|
||||
// border collapse
|
||||
&-item:not(&-last-item):not(&-item-rtl) {
|
||||
margin-right: -@border-width-base;
|
||||
}
|
||||
|
||||
// rtl border collapse
|
||||
&-item:not(&-last-item)&-item-rtl {
|
||||
margin-left: -@border-width-base;
|
||||
}
|
||||
|
||||
&-item {
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
// Select has an extra focus className
|
||||
& when (not (@special-item-cls = null)) {
|
||||
&.@{special-item-cls} {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& when (not (@bordered-item-cls = null)) {
|
||||
// border collapse
|
||||
&-item:not(&-last-item) {
|
||||
margin-right: -@border-width-base;
|
||||
|
||||
&.@{prefix-cls}-compact-item-rtl {
|
||||
margin-right: 0;
|
||||
margin-left: -@border-width-base;
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
> * {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Select has an special focus-item
|
||||
& when (not (@special-item-cls = null)) {
|
||||
&.@{special-item-cls} > * {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled] > * {
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compact-item(@prefix-cls, @bordered-item-cls: null, @special-item-cls: null) {
|
||||
&-compact {
|
||||
.compact-item-border(@prefix-cls, @bordered-item-cls, @special-item-cls);
|
||||
|
||||
.compact-item-border-radius(@prefix-cls, @bordered-item-cls);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
// Compatibility for browsers.
|
||||
|
||||
// Placeholder text
|
||||
.placeholder(@color: @input-placeholder-color) {
|
||||
&::placeholder {
|
||||
color: @color;
|
||||
user-select: none; // https://github.com/ant-design/ant-design/pull/32639
|
||||
}
|
||||
|
||||
&:placeholder-shown {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
// customize dark components background in popover containers(like Modal, Drawer, Card, Popover, Popconfirm, Notification, ...)
|
||||
// for dark theme
|
||||
.popover-customize-bg(@containerClass, @background: @popover-background, @prefix: @ant-prefix)
|
||||
when
|
||||
(@theme = dark) {
|
||||
@picker-prefix-cls: ~'@{prefix}-picker';
|
||||
@slider-prefix-cls: ~'@{prefix}-slider';
|
||||
@anchor-prefix-cls: ~'@{prefix}-anchor';
|
||||
@collapse-prefix-cls: ~'@{prefix}-collapse';
|
||||
@tab-prefix-cls: ~'@{prefix}-tabs';
|
||||
@timeline-prefix-cls: ~'@{prefix}-timeline';
|
||||
@tree-prefix-cls: ~'@{prefix}-tree';
|
||||
@card-prefix-cls: ~'@{prefix}-card';
|
||||
@badge-prefix-cls: ~'@{prefix}-badge';
|
||||
@transfer-prefix-cls: ~'@{prefix}-transfer';
|
||||
@calendar-prefix-cls: ~'@{prefix}-picker-calendar';
|
||||
@calendar-picker-prefix-cls: ~'@{prefix}-picker';
|
||||
@table-prefix-cls: ~'@{prefix}-table';
|
||||
|
||||
@popover-border: @border-width-base @border-style-base @popover-customize-border-color;
|
||||
|
||||
.@{containerClass} {
|
||||
.@{picker-prefix-cls}-clear,
|
||||
.@{slider-prefix-cls}-handle,
|
||||
.@{anchor-prefix-cls}-wrapper,
|
||||
.@{collapse-prefix-cls}-content,
|
||||
.@{timeline-prefix-cls}-item-head,
|
||||
.@{card-prefix-cls} {
|
||||
background-color: @background;
|
||||
}
|
||||
|
||||
.@{transfer-prefix-cls} {
|
||||
&-list {
|
||||
&-header {
|
||||
background: @background;
|
||||
border-bottom: @popover-border;
|
||||
}
|
||||
&-content-item:not(.@{transfer-prefix-cls}-list-content-item-disabled):hover {
|
||||
background-color: @item-hover-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.@{table-prefix-cls}-expanded-row {
|
||||
&,
|
||||
&:hover {
|
||||
> td {
|
||||
background: #272727;
|
||||
}
|
||||
}
|
||||
}
|
||||
.@{table-prefix-cls}.@{table-prefix-cls}-small {
|
||||
thead {
|
||||
> tr {
|
||||
> th {
|
||||
background-color: @background;
|
||||
border-bottom: @popover-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.@{table-prefix-cls} {
|
||||
background-color: @background;
|
||||
.@{table-prefix-cls}-row-expand-icon {
|
||||
border: @popover-border;
|
||||
}
|
||||
|
||||
tfoot {
|
||||
> tr {
|
||||
> th,
|
||||
> td {
|
||||
border-bottom: @popover-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thead {
|
||||
> tr {
|
||||
> th {
|
||||
background-color: #272727;
|
||||
border-bottom: @popover-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
> tr {
|
||||
> td {
|
||||
border-bottom: @popover-border;
|
||||
&.@{table-prefix-cls}-cell-fix-left,
|
||||
&.@{table-prefix-cls}-cell-fix-right {
|
||||
background-color: @background;
|
||||
}
|
||||
}
|
||||
&.@{table-prefix-cls}-row:hover {
|
||||
> td {
|
||||
background: @table-header-sort-active-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.@{table-prefix-cls}-bordered {
|
||||
.@{table-prefix-cls}-title {
|
||||
border: @popover-border;
|
||||
}
|
||||
|
||||
// ============================= Cell =============================
|
||||
thead > tr > th,
|
||||
tbody > tr > td,
|
||||
tfoot > tr > th,
|
||||
tfoot > tr > td {
|
||||
border-right: @popover-border;
|
||||
}
|
||||
|
||||
// Fixed right should provides additional border
|
||||
.@{table-prefix-cls}-cell-fix-right-first::after {
|
||||
border-right: @popover-border;
|
||||
}
|
||||
|
||||
// ============================ Header ============================
|
||||
table > {
|
||||
thead {
|
||||
> tr:not(:last-child) > th {
|
||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =========================== Content ============================
|
||||
.@{table-prefix-cls}-container {
|
||||
border: @popover-border;
|
||||
}
|
||||
|
||||
// ========================== Expandable ==========================
|
||||
.@{table-prefix-cls}-expanded-row-fixed {
|
||||
&::after {
|
||||
border-right: @popover-border;
|
||||
}
|
||||
}
|
||||
|
||||
.@{table-prefix-cls}-footer {
|
||||
border: @popover-border;
|
||||
}
|
||||
}
|
||||
.@{table-prefix-cls}-filter-trigger-container-open {
|
||||
background-color: #525252;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-full {
|
||||
background-color: @background;
|
||||
.@{calendar-picker-prefix-cls}-panel {
|
||||
background-color: @background;
|
||||
.@{calendar-prefix-cls}-date {
|
||||
border-top: 2px solid @popover-customize-border-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{tab-prefix-cls} {
|
||||
&.@{tab-prefix-cls}-card .@{tab-prefix-cls}-card-bar .@{tab-prefix-cls}-tab-active {
|
||||
background-color: @background;
|
||||
border-bottom: @border-width-base solid @background;
|
||||
}
|
||||
}
|
||||
|
||||
.@{badge-prefix-cls} {
|
||||
&-count {
|
||||
box-shadow: 0 0 0 1px @background;
|
||||
}
|
||||
}
|
||||
|
||||
.@{tree-prefix-cls} {
|
||||
&-show-line {
|
||||
.@{tree-prefix-cls}-switcher {
|
||||
background: @background;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
.iconfont-mixin() {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: @icon-color;
|
||||
font-style: normal;
|
||||
line-height: 0;
|
||||
text-align: center;
|
||||
text-transform: none;
|
||||
vertical-align: -0.125em; // for SVG icon, see https://blog.prototypr.io/align-svg-icons-to-text-and-say-goodbye-to-font-icons-d44b3d7b26b4
|
||||
text-rendering: optimizelegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
> * {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
svg {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: none; // dont display old icon.
|
||||
}
|
||||
|
||||
& &-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Mixins
|
||||
// --------------------------------------------------
|
||||
@import 'size';
|
||||
@import 'compatibility';
|
||||
@import 'clearfix';
|
||||
@import 'iconfont';
|
||||
@import 'typography';
|
||||
@import 'customize';
|
||||
@import 'box';
|
||||
@import 'modal-mask';
|
||||
@import 'motion';
|
||||
@import 'reset';
|
||||
@import 'operation-unit';
|
||||
@import 'rounded-arrow';
|
||||
@import 'compact-item';
|
||||
@import 'compact-item-vertical';
|
||||
@@ -1,30 +0,0 @@
|
||||
@import 'box';
|
||||
|
||||
.modal-mask() {
|
||||
pointer-events: none;
|
||||
|
||||
&.@{ant-prefix}-zoom-enter,
|
||||
&.@{ant-prefix}-zoom-appear {
|
||||
transform: none; // reset scale avoid mousePosition bug
|
||||
opacity: 0;
|
||||
animation-duration: @animation-duration-slow;
|
||||
user-select: none; // https://github.com/ant-design/ant-design/issues/11777
|
||||
}
|
||||
|
||||
&-mask {
|
||||
.box(fixed);
|
||||
z-index: @zindex-modal-mask;
|
||||
height: 100%;
|
||||
background-color: @modal-mask-bg;
|
||||
|
||||
&-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-wrap {
|
||||
.box(fixed);
|
||||
overflow: auto;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
.motion-common(@duration: @animation-duration-base) {
|
||||
animation-duration: @duration;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.motion-common-leave(@duration: @animation-duration-base) {
|
||||
animation-duration: @duration;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.make-motion(@className, @keyframeName, @duration: @animation-duration-base) {
|
||||
.@{className}-enter,
|
||||
.@{className}-appear {
|
||||
.motion-common(@duration);
|
||||
|
||||
animation-play-state: paused;
|
||||
}
|
||||
.@{className}-leave {
|
||||
.motion-common-leave(@duration);
|
||||
|
||||
animation-play-state: paused;
|
||||
}
|
||||
.@{className}-enter.@{className}-enter-active,
|
||||
.@{className}-appear.@{className}-appear-active {
|
||||
animation-name: ~'@{keyframeName}In';
|
||||
animation-play-state: running;
|
||||
}
|
||||
.@{className}-leave.@{className}-leave-active {
|
||||
animation-name: ~'@{keyframeName}Out';
|
||||
animation-play-state: running;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
.operation-unit() {
|
||||
color: @link-color;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:focus-visible,
|
||||
&:hover {
|
||||
color: @link-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @link-active-color;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
.reset-component() {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
font-variant: @font-variant-base;
|
||||
line-height: @line-height-base;
|
||||
list-style: none;
|
||||
font-feature-settings: @font-feature-settings-base;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
.roundedArrow(@width, @outer-radius, @bg-color: var(--antd-arrow-background-color)) {
|
||||
@corner-height: unit(((@outer-radius) * (1 - 1 / sqrt(2))));
|
||||
|
||||
@width-without-unit: unit(@width);
|
||||
@outer-radius-without-unit: unit(@outer-radius);
|
||||
@inner-radius-without-unit: unit(@arrow-border-radius);
|
||||
|
||||
@a-x: @width-without-unit - @corner-height;
|
||||
@a-y: 2 * @width-without-unit + @corner-height;
|
||||
@b-x: @a-x + @outer-radius-without-unit * (1 / sqrt(2));
|
||||
@b-y: 2 * @width-without-unit;
|
||||
@c-x: 2 * @width-without-unit - @inner-radius-without-unit;
|
||||
@c-y: 2 * @width-without-unit;
|
||||
@d-x: 2 * @width-without-unit;
|
||||
@d-y: 2 * @width-without-unit - @inner-radius-without-unit;
|
||||
@e-x: 2 * @width-without-unit;
|
||||
@e-y: @f-y + @outer-radius-without-unit * (1 / sqrt(2));
|
||||
@f-x: 2 * @width-without-unit + @corner-height;
|
||||
@f-y: @width-without-unit - @corner-height;
|
||||
@g-x: @f-x - 1;
|
||||
@g-y: @f-y;
|
||||
@h-x: @a-x;
|
||||
@h-y: @a-y - 1;
|
||||
|
||||
border-radius: 0 0 @arrow-border-radius;
|
||||
pointer-events: none;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: -@width;
|
||||
left: -@width;
|
||||
width: @width * 3;
|
||||
height: @width * 3;
|
||||
background: @bg-color;
|
||||
// Hack firefox: https://github.com/ant-design/ant-design/pull/33710#issuecomment-1015287825
|
||||
background-repeat: no-repeat;
|
||||
background-position: ceil(-@width + 1px) ceil(-@width + 1px);
|
||||
content: '';
|
||||
clip-path: inset(33% 33%); // For browsers that do not support path()
|
||||
clip-path: path(
|
||||
'M @{a-x} @{a-y} A @{outer-radius-without-unit} @{outer-radius-without-unit} 0 0 1 @{b-x} @{b-y} L @{c-x} @{c-y} A @{inner-radius-without-unit} @{inner-radius-without-unit} 0 0 0 @{d-x} @{d-y} L @{e-x} @{e-y} A @{outer-radius-without-unit} @{outer-radius-without-unit} 0 0 1 @{f-x} @{f-y} L @{g-x} @{g-y} L @{h-x} @{h-y} Z'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// Sizing shortcuts
|
||||
|
||||
.size(@width; @height) {
|
||||
width: @width;
|
||||
height: @height;
|
||||
}
|
||||
|
||||
.square(@size) {
|
||||
.size(@size; @size);
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
// =============== Common ===============
|
||||
.typography-paragraph() {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.typography-title(@fontSize; @fontWeight; @lineHeight; @headingColor; @headingMarginBottom;) {
|
||||
margin-bottom: @headingMarginBottom;
|
||||
color: @headingColor;
|
||||
font-weight: @fontWeight;
|
||||
font-size: @fontSize;
|
||||
line-height: @lineHeight;
|
||||
}
|
||||
|
||||
.typography-title-1() {
|
||||
.typography-title(
|
||||
@heading-1-size,
|
||||
@typography-title-font-weight,
|
||||
1.23,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
.typography-title-2() {
|
||||
.typography-title(
|
||||
@heading-2-size,
|
||||
@typography-title-font-weight,
|
||||
1.35,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
.typography-title-3() {
|
||||
.typography-title(
|
||||
@heading-3-size,
|
||||
@typography-title-font-weight,
|
||||
1.35,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
.typography-title-4() {
|
||||
.typography-title(
|
||||
@heading-4-size,
|
||||
@typography-title-font-weight,
|
||||
1.4,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
.typography-title-5() {
|
||||
.typography-title(
|
||||
@heading-5-size,
|
||||
@typography-title-font-weight,
|
||||
1.5,
|
||||
@heading-color,
|
||||
@typography-title-margin-bottom
|
||||
);
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
@import './default.less';
|
||||
|
||||
@line-height-base: 1.66667;
|
||||
@mode: compact;
|
||||
@font-size-base: 12px;
|
||||
@font-size-lg: @font-size-base + 2px;
|
||||
|
||||
// default paddings
|
||||
@default-padding-lg: 24px; // containers
|
||||
@default-padding-md: 16px; // small containers and buttons
|
||||
@default-padding-sm: 12px; // Form controls and items
|
||||
@default-padding-xs: 8px; // small items
|
||||
@default-padding-xss: 4px; // more small
|
||||
|
||||
// vertical paddings
|
||||
@padding-lg: 16px; // containers
|
||||
@padding-md: 8px; // small containers and buttons
|
||||
@padding-sm: 8px; // Form controls and items
|
||||
@padding-xs: 4px; // small items
|
||||
@padding-xss: 0px; // more small
|
||||
|
||||
// vertical padding for all form controls
|
||||
@control-padding-horizontal: @padding-sm;
|
||||
@control-padding-horizontal-sm: @default-padding-xs;
|
||||
|
||||
// vertical margins
|
||||
@margin-lg: 16px; // containers
|
||||
@margin-md: 8px; // small containers and buttons
|
||||
@margin-sm: 8px; // Form controls and items
|
||||
@margin-xs: 4px; // small items
|
||||
@margin-xss: 0px; // more small
|
||||
|
||||
// height rules
|
||||
@height-base: 28px;
|
||||
@height-lg: 32px;
|
||||
@height-sm: 22px;
|
||||
|
||||
// Button
|
||||
// ---
|
||||
@btn-padding-horizontal-base: @default-padding-sm - 1px;
|
||||
@btn-padding-horizontal-lg: @btn-padding-horizontal-base;
|
||||
@btn-padding-horizontal-sm: @default-padding-xs - 1px;
|
||||
@btn-square-only-icon-size-lg: 16px;
|
||||
@btn-square-only-icon-size: 14px;
|
||||
@btn-square-only-icon-size-sm: 12px;
|
||||
|
||||
// Breadcrumb
|
||||
// ---
|
||||
@breadcrumb-font-size: @font-size-base;
|
||||
@breadcrumb-icon-font-size: @font-size-base;
|
||||
|
||||
//Dropdown
|
||||
@dropdown-line-height: 18px;
|
||||
|
||||
// Menu
|
||||
@menu-item-padding-horizontal: 12px;
|
||||
@menu-horizontal-line-height: 38px;
|
||||
@menu-inline-toplevel-item-height: 32px;
|
||||
@menu-item-height: 32px;
|
||||
@menu-item-vertical-margin: 0px;
|
||||
@menu-item-boundary-margin: 0px;
|
||||
@menu-icon-margin-right: 8px;
|
||||
|
||||
// Checkbox
|
||||
@checkbox-size: 14px;
|
||||
@checkbox-group-item-margin-right: 6px;
|
||||
|
||||
// picker
|
||||
@picker-panel-cell-height: 22px;
|
||||
@picker-panel-cell-width: 32px;
|
||||
@picker-text-height: 32px;
|
||||
@picker-time-panel-cell-height: 24px;
|
||||
@picker-panel-without-time-cell-height: 48px;
|
||||
|
||||
// Form
|
||||
// ---
|
||||
@form-item-margin-bottom: 16px;
|
||||
@form-vertical-label-padding: 0 0 4px;
|
||||
|
||||
// Rate
|
||||
// ---
|
||||
@rate-star-size: 16px;
|
||||
|
||||
// Radio
|
||||
// ---
|
||||
@radio-size: 14px;
|
||||
@radio-wrapper-margin-right: 6px;
|
||||
|
||||
// Switch
|
||||
// ---
|
||||
@switch-height: 20px;
|
||||
@switch-sm-height: 14px;
|
||||
@switch-min-width: 40px;
|
||||
@switch-sm-min-width: 24px;
|
||||
@switch-inner-margin-min: 4px;
|
||||
@switch-inner-margin-max: 22px;
|
||||
|
||||
// Slider
|
||||
// ---
|
||||
@slider-handle-size: 12px;
|
||||
@slider-handle-margin-top: -4px;
|
||||
|
||||
// Input
|
||||
// ---
|
||||
@input-padding-vertical-base: round(
|
||||
max(
|
||||
(round(((@input-height-base - @font-size-base * @line-height-base) / 2) * 10) / 10) -
|
||||
@border-width-base,
|
||||
2px
|
||||
)
|
||||
);
|
||||
@input-padding-horizontal-lg: 11px;
|
||||
|
||||
// PageHeader
|
||||
// ---
|
||||
@page-header-padding: 16px;
|
||||
@page-header-padding-vertical: 8px;
|
||||
@page-header-heading-title: 16px;
|
||||
@page-header-heading-sub-title: 12px;
|
||||
@page-header-tabs-tab-font-size: 14px;
|
||||
|
||||
// Pagination
|
||||
// ---
|
||||
@pagination-mini-options-size-changer-top: 1px;
|
||||
@pagination-item-size-sm: 22px;
|
||||
|
||||
// Cascader
|
||||
// ----
|
||||
@cascader-dropdown-line-height: @dropdown-line-height;
|
||||
|
||||
// Select
|
||||
// ---
|
||||
@select-dropdown-height: @height-base;
|
||||
@select-single-item-height-lg: 32px;
|
||||
@select-multiple-item-height: @input-height-base - max(@input-padding-vertical-base, 4) * 2; // Normal 24px
|
||||
@select-multiple-item-height-lg: 24px;
|
||||
@select-multiple-item-spacing-half: 3px;
|
||||
|
||||
// Tree
|
||||
// ---
|
||||
@tree-title-height: 20px;
|
||||
|
||||
// Transfer
|
||||
// ---
|
||||
@transfer-item-padding-vertical: 3px;
|
||||
@transfer-list-search-icon-top: 8px;
|
||||
@transfer-header-height: 36px;
|
||||
|
||||
// Comment
|
||||
// ---
|
||||
@comment-actions-margin-bottom: 0px;
|
||||
@comment-actions-margin-top: @margin-xs;
|
||||
@comment-content-detail-p-margin-bottom: 0px;
|
||||
|
||||
// Steps
|
||||
// ---
|
||||
@steps-icon-size: 24px;
|
||||
@steps-icon-custom-size: 20px;
|
||||
@steps-icon-custom-font-size: 20px;
|
||||
@steps-icon-custom-top: 2px;
|
||||
@steps-icon-margin: 2px 8px 2px 0;
|
||||
@steps-icon-font-size: @font-size-base;
|
||||
@steps-dot-top: 4px;
|
||||
@steps-icon-top: 0px;
|
||||
@steps-small-icon-size: 20px;
|
||||
@steps-vertical-icon-width: 12px;
|
||||
@steps-vertical-tail-width: 12px;
|
||||
@steps-vertical-tail-width-sm: 10px;
|
||||
// Collapse
|
||||
// ---
|
||||
//@collapse-header-padding-extra: 32px;
|
||||
@collapse-content-padding: @padding-md @padding-lg;
|
||||
|
||||
// List
|
||||
// ---
|
||||
@list-item-meta-description-font-size: @font-size-sm;
|
||||
@list-item-padding-sm: 4px 12px;
|
||||
@list-item-padding-lg: 12px 16px;
|
||||
|
||||
// Drawer
|
||||
// ---
|
||||
@drawer-header-padding: 11px @padding-lg;
|
||||
@drawer-footer-padding-vertical: @padding-sm;
|
||||
@drawer-footer-padding-horizontal: @padding-sm;
|
||||
@drawer-header-close-size: 44px;
|
||||
|
||||
// Modal
|
||||
// --
|
||||
@modal-header-padding-vertical: 11px;
|
||||
@modal-header-padding: @modal-header-padding-vertical @modal-header-padding-horizontal;
|
||||
@modal-footer-padding-vertical: @padding-sm;
|
||||
@modal-header-close-size: @modal-header-title-line-height + 2 * @modal-header-padding-vertical;
|
||||
@modal-confirm-body-padding: 24px 24px 16px;
|
||||
|
||||
// Message
|
||||
// ---
|
||||
@message-notice-content-padding: 8px 16px;
|
||||
|
||||
// popover
|
||||
// --
|
||||
@popover-min-height: 28px;
|
||||
@popover-padding-horizontal: @default-padding-sm;
|
||||
|
||||
// Card
|
||||
// ---
|
||||
@card-head-height: 36px;
|
||||
@card-head-font-size: @card-head-font-size-sm;
|
||||
@card-head-padding: 8.5px;
|
||||
@card-padding-base: 12px;
|
||||
@card-padding-base-sm: @card-padding-base;
|
||||
@card-head-height-sm: 30px;
|
||||
@card-head-padding-sm: 6px;
|
||||
@card-actions-li-margin: 4px 0;
|
||||
@card-head-tabs-margin-bottom: -9px;
|
||||
|
||||
// Table
|
||||
// ---
|
||||
@table-padding-vertical: 12px;
|
||||
@table-padding-horizontal: 8px;
|
||||
@table-padding-vertical-md: 8px;
|
||||
@table-padding-horizontal-md: 8px;
|
||||
@table-padding-vertical-sm: 4px;
|
||||
@table-padding-horizontal-sm: 4px;
|
||||
@table-selection-column-width: 32px;
|
||||
|
||||
// Statistic
|
||||
// ---
|
||||
@statistic-content-font-size: 20px;
|
||||
|
||||
// Alert
|
||||
// ---
|
||||
@alert-with-description-no-icon-padding-vertical: 7px;
|
||||
@alert-with-description-padding-vertical: 11px;
|
||||
@alert-icon-top: 7px + @font-size-base * (@line-height-base / 2) - (@font-size-base / 2);
|
||||
@alert-with-description-icon-size: 20px;
|
||||
|
||||
// Skeleton
|
||||
// ---
|
||||
@skeleton-paragraph-margin-top: 20px;
|
||||
@skeleton-paragraph-li-margin-top: 12px;
|
||||
@skeleton-paragraph-li-height: 14px;
|
||||
@skeleton-title-height: 14px;
|
||||
@skeleton-title-paragraph-margin-top: 20px;
|
||||
|
||||
// Descriptions
|
||||
@descriptions-title-margin-bottom: 8px;
|
||||
@descriptions-default-padding: 12px @padding-lg;
|
||||
@descriptions-item-padding-bottom: @padding-xs;
|
||||
|
||||
// Avatar
|
||||
// ---
|
||||
@avatar-size-base: 28px;
|
||||
@avatar-size-lg: 32px;
|
||||
@avatar-size-sm: 22px;
|
||||
@avatar-font-size-base: 16px;
|
||||
@avatar-font-size-lg: 20px;
|
||||
@avatar-font-size-sm: 12px;
|
||||
|
||||
// Badge
|
||||
// ---
|
||||
@badge-height: 18px;
|
||||
|
||||
// Tag
|
||||
// ---
|
||||
@tag-line-height: 18px;
|
||||
|
||||
// Notification
|
||||
// ---
|
||||
@notification-padding-vertical: 12px;
|
||||
@notification-padding-horizontal: 16px;
|
||||
|
||||
// Result
|
||||
// ---
|
||||
@result-title-font-size: 20px;
|
||||
@result-icon-font-size: 64px;
|
||||
@result-extra-margin: 24px 0 0 0;
|
||||
|
||||
// Anchor
|
||||
// ---
|
||||
@anchor-link-top: 4px;
|
||||
@anchor-link-left: 16px;
|
||||
@anchor-link-padding: @anchor-link-top 0 @anchor-link-top @anchor-link-left;
|
||||
|
||||
// Tabs
|
||||
// ---
|
||||
@tabs-card-horizontal-padding: 4px @padding-md;
|
||||
|
||||
// Progress
|
||||
// ---
|
||||
@progress-circle-text-font-size: 0.833333em;
|
||||
|
||||
// Image
|
||||
// ---
|
||||
@image-size-base: 48px;
|
||||
@image-font-size-base: 24px;
|
||||
@@ -1,457 +0,0 @@
|
||||
@import './default.less';
|
||||
|
||||
@theme: dark;
|
||||
// color palettes
|
||||
@blue-1: mix(color(~`colorPalette('@{blue-base}', 8) `), @component-background, 15%);
|
||||
@blue-2: mix(color(~`colorPalette('@{blue-base}', 7) `), @component-background, 25%);
|
||||
@blue-3: mix(@blue-base, @component-background, 30%);
|
||||
@blue-4: mix(@blue-base, @component-background, 45%);
|
||||
@blue-5: mix(@blue-base, @component-background, 65%);
|
||||
@blue-6: mix(@blue-base, @component-background, 85%);
|
||||
@blue-7: mix(color(~`colorPalette('@{blue-base}', 5) `), @component-background, 90%);
|
||||
@blue-8: mix(color(~`colorPalette('@{blue-base}', 4) `), @component-background, 95%);
|
||||
@blue-9: mix(color(~`colorPalette('@{blue-base}', 3) `), @component-background, 97%);
|
||||
@blue-10: mix(color(~`colorPalette('@{blue-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@purple-1: mix(color(~`colorPalette('@{purple-base}', 8) `), @component-background, 15%);
|
||||
@purple-2: mix(color(~`colorPalette('@{purple-base}', 7) `), @component-background, 25%);
|
||||
@purple-3: mix(@purple-base, @component-background, 30%);
|
||||
@purple-4: mix(@purple-base, @component-background, 45%);
|
||||
@purple-5: mix(@purple-base, @component-background, 65%);
|
||||
@purple-6: mix(@purple-base, @component-background, 85%);
|
||||
@purple-7: mix(color(~`colorPalette('@{purple-base}', 5) `), @component-background, 90%);
|
||||
@purple-8: mix(color(~`colorPalette('@{purple-base}', 4) `), @component-background, 95%);
|
||||
@purple-9: mix(color(~`colorPalette('@{purple-base}', 3) `), @component-background, 97%);
|
||||
@purple-10: mix(color(~`colorPalette('@{purple-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@cyan-1: mix(color(~`colorPalette('@{cyan-base}', 8) `), @component-background, 15%);
|
||||
@cyan-2: mix(color(~`colorPalette('@{cyan-base}', 7) `), @component-background, 25%);
|
||||
@cyan-3: mix(@cyan-base, @component-background, 30%);
|
||||
@cyan-4: mix(@cyan-base, @component-background, 45%);
|
||||
@cyan-5: mix(@cyan-base, @component-background, 65%);
|
||||
@cyan-6: mix(@cyan-base, @component-background, 85%);
|
||||
@cyan-7: mix(color(~`colorPalette('@{cyan-base}', 5) `), @component-background, 90%);
|
||||
@cyan-8: mix(color(~`colorPalette('@{cyan-base}', 4) `), @component-background, 95%);
|
||||
@cyan-9: mix(color(~`colorPalette('@{cyan-base}', 3) `), @component-background, 97%);
|
||||
@cyan-10: mix(color(~`colorPalette('@{cyan-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@green-1: mix(color(~`colorPalette('@{green-base}', 8) `), @component-background, 15%);
|
||||
@green-2: mix(color(~`colorPalette('@{green-base}', 7) `), @component-background, 25%);
|
||||
@green-3: mix(@green-base, @component-background, 30%);
|
||||
@green-4: mix(@green-base, @component-background, 45%);
|
||||
@green-5: mix(@green-base, @component-background, 65%);
|
||||
@green-6: mix(@green-base, @component-background, 85%);
|
||||
@green-7: mix(color(~`colorPalette('@{green-base}', 5) `), @component-background, 90%);
|
||||
@green-8: mix(color(~`colorPalette('@{green-base}', 4) `), @component-background, 95%);
|
||||
@green-9: mix(color(~`colorPalette('@{green-base}', 3) `), @component-background, 97%);
|
||||
@green-10: mix(color(~`colorPalette('@{green-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@magenta-1: mix(color(~`colorPalette('@{magenta-base}', 8) `), @component-background, 15%);
|
||||
@magenta-2: mix(color(~`colorPalette('@{magenta-base}', 7) `), @component-background, 25%);
|
||||
@magenta-3: mix(@magenta-base, @component-background, 30%);
|
||||
@magenta-4: mix(@magenta-base, @component-background, 45%);
|
||||
@magenta-5: mix(@magenta-base, @component-background, 65%);
|
||||
@magenta-6: mix(@magenta-base, @component-background, 85%);
|
||||
@magenta-7: mix(color(~`colorPalette('@{magenta-base}', 5) `), @component-background, 90%);
|
||||
@magenta-8: mix(color(~`colorPalette('@{magenta-base}', 4) `), @component-background, 95%);
|
||||
@magenta-9: mix(color(~`colorPalette('@{magenta-base}', 3) `), @component-background, 97%);
|
||||
@magenta-10: mix(color(~`colorPalette('@{magenta-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@pink-1: mix(color(~`colorPalette('@{pink-base}', 8) `), @component-background, 15%);
|
||||
@pink-2: mix(color(~`colorPalette('@{pink-base}', 7) `), @component-background, 25%);
|
||||
@pink-3: mix(@pink-base, @component-background, 30%);
|
||||
@pink-4: mix(@pink-base, @component-background, 45%);
|
||||
@pink-5: mix(@pink-base, @component-background, 65%);
|
||||
@pink-6: mix(@pink-base, @component-background, 85%);
|
||||
@pink-7: mix(color(~`colorPalette('@{pink-base}', 5) `), @component-background, 90%);
|
||||
@pink-8: mix(color(~`colorPalette('@{pink-base}', 4) `), @component-background, 95%);
|
||||
@pink-9: mix(color(~`colorPalette('@{pink-base}', 3) `), @component-background, 97%);
|
||||
@pink-10: mix(color(~`colorPalette('@{pink-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@red-1: mix(color(~`colorPalette('@{red-base}', 8) `), @component-background, 15%);
|
||||
@red-2: mix(color(~`colorPalette('@{red-base}', 7) `), @component-background, 25%);
|
||||
@red-3: mix(@red-base, @component-background, 30%);
|
||||
@red-4: mix(@red-base, @component-background, 45%);
|
||||
@red-5: mix(@red-base, @component-background, 65%);
|
||||
@red-6: mix(@red-base, @component-background, 85%);
|
||||
@red-7: mix(color(~`colorPalette('@{red-base}', 5) `), @component-background, 90%);
|
||||
@red-8: mix(color(~`colorPalette('@{red-base}', 4) `), @component-background, 95%);
|
||||
@red-9: mix(color(~`colorPalette('@{red-base}', 3) `), @component-background, 97%);
|
||||
@red-10: mix(color(~`colorPalette('@{red-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@orange-1: mix(color(~`colorPalette('@{orange-base}', 8) `), @component-background, 15%);
|
||||
@orange-2: mix(color(~`colorPalette('@{orange-base}', 7) `), @component-background, 25%);
|
||||
@orange-3: mix(@orange-base, @component-background, 30%);
|
||||
@orange-4: mix(@orange-base, @component-background, 45%);
|
||||
@orange-5: mix(@orange-base, @component-background, 65%);
|
||||
@orange-6: mix(@orange-base, @component-background, 85%);
|
||||
@orange-7: mix(color(~`colorPalette('@{orange-base}', 5) `), @component-background, 90%);
|
||||
@orange-8: mix(color(~`colorPalette('@{orange-base}', 4) `), @component-background, 95%);
|
||||
@orange-9: mix(color(~`colorPalette('@{orange-base}', 3) `), @component-background, 97%);
|
||||
@orange-10: mix(color(~`colorPalette('@{orange-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@yellow-1: mix(color(~`colorPalette('@{yellow-base}', 8) `), @component-background, 15%);
|
||||
@yellow-2: mix(color(~`colorPalette('@{yellow-base}', 7) `), @component-background, 25%);
|
||||
@yellow-3: mix(@yellow-base, @component-background, 30%);
|
||||
@yellow-4: mix(@yellow-base, @component-background, 45%);
|
||||
@yellow-5: mix(@yellow-base, @component-background, 65%);
|
||||
@yellow-6: mix(@yellow-base, @component-background, 85%);
|
||||
@yellow-7: mix(color(~`colorPalette('@{yellow-base}', 5) `), @component-background, 90%);
|
||||
@yellow-8: mix(color(~`colorPalette('@{yellow-base}', 4) `), @component-background, 95%);
|
||||
@yellow-9: mix(color(~`colorPalette('@{yellow-base}', 3) `), @component-background, 97%);
|
||||
@yellow-10: mix(color(~`colorPalette('@{yellow-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@volcano-1: mix(color(~`colorPalette('@{volcano-base}', 8) `), @component-background, 15%);
|
||||
@volcano-2: mix(color(~`colorPalette('@{volcano-base}', 7) `), @component-background, 25%);
|
||||
@volcano-3: mix(@volcano-base, @component-background, 30%);
|
||||
@volcano-4: mix(@volcano-base, @component-background, 45%);
|
||||
@volcano-5: mix(@volcano-base, @component-background, 65%);
|
||||
@volcano-6: mix(@volcano-base, @component-background, 85%);
|
||||
@volcano-7: mix(color(~`colorPalette('@{volcano-base}', 5) `), @component-background, 90%);
|
||||
@volcano-8: mix(color(~`colorPalette('@{volcano-base}', 4) `), @component-background, 95%);
|
||||
@volcano-9: mix(color(~`colorPalette('@{volcano-base}', 3) `), @component-background, 97%);
|
||||
@volcano-10: mix(color(~`colorPalette('@{volcano-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@geekblue-1: mix(color(~`colorPalette('@{geekblue-base}', 8) `), @component-background, 15%);
|
||||
@geekblue-2: mix(color(~`colorPalette('@{geekblue-base}', 7) `), @component-background, 25%);
|
||||
@geekblue-3: mix(@geekblue-base, @component-background, 30%);
|
||||
@geekblue-4: mix(@geekblue-base, @component-background, 45%);
|
||||
@geekblue-5: mix(@geekblue-base, @component-background, 65%);
|
||||
@geekblue-6: mix(@geekblue-base, @component-background, 85%);
|
||||
@geekblue-7: mix(color(~`colorPalette('@{geekblue-base}', 5) `), @component-background, 90%);
|
||||
@geekblue-8: mix(color(~`colorPalette('@{geekblue-base}', 4) `), @component-background, 95%);
|
||||
@geekblue-9: mix(color(~`colorPalette('@{geekblue-base}', 3) `), @component-background, 97%);
|
||||
@geekblue-10: mix(color(~`colorPalette('@{geekblue-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@lime-1: mix(color(~`colorPalette('@{lime-base}', 8) `), @component-background, 15%);
|
||||
@lime-2: mix(color(~`colorPalette('@{lime-base}', 7) `), @component-background, 25%);
|
||||
@lime-3: mix(@lime-base, @component-background, 30%);
|
||||
@lime-4: mix(@lime-base, @component-background, 45%);
|
||||
@lime-5: mix(@lime-base, @component-background, 65%);
|
||||
@lime-6: mix(@lime-base, @component-background, 85%);
|
||||
@lime-7: mix(color(~`colorPalette('@{lime-base}', 5) `), @component-background, 90%);
|
||||
@lime-8: mix(color(~`colorPalette('@{lime-base}', 4) `), @component-background, 95%);
|
||||
@lime-9: mix(color(~`colorPalette('@{lime-base}', 3) `), @component-background, 97%);
|
||||
@lime-10: mix(color(~`colorPalette('@{lime-base}', 2) `), @component-background, 98%);
|
||||
|
||||
@gold-1: mix(color(~`colorPalette('@{gold-base}', 8) `), @component-background, 15%);
|
||||
@gold-2: mix(color(~`colorPalette('@{gold-base}', 7) `), @component-background, 25%);
|
||||
@gold-3: mix(@gold-base, @component-background, 30%);
|
||||
@gold-4: mix(@gold-base, @component-background, 45%);
|
||||
@gold-5: mix(@gold-base, @component-background, 65%);
|
||||
@gold-6: mix(@gold-base, @component-background, 85%);
|
||||
@gold-7: mix(color(~`colorPalette('@{gold-base}', 5) `), @component-background, 90%);
|
||||
@gold-8: mix(color(~`colorPalette('@{gold-base}', 4) `), @component-background, 95%);
|
||||
@gold-9: mix(color(~`colorPalette('@{gold-base}', 3) `), @component-background, 97%);
|
||||
@gold-10: mix(color(~`colorPalette('@{gold-base}', 2) `), @component-background, 98%);
|
||||
|
||||
// Color used by default to control hover and active backgrounds and for
|
||||
// alert info backgrounds.
|
||||
@primary-1: mix(color(~`colorPalette('@{primary-color}', 8) `), @component-background, 15%);
|
||||
@primary-2: mix(color(~`colorPalette('@{primary-color}', 7) `), @component-background, 25%);
|
||||
@primary-3: mix(@primary-color, @component-background, 30%);
|
||||
@primary-4: mix(@primary-color, @component-background, 45%);
|
||||
@primary-5: mix(@primary-color, @component-background, 65%);
|
||||
@primary-6: @primary-color;
|
||||
@primary-7: mix(color(~`colorPalette('@{primary-color}', 5) `), @component-background, 90%);
|
||||
@primary-8: mix(color(~`colorPalette('@{primary-color}', 4) `), @component-background, 95%);
|
||||
@primary-9: mix(color(~`colorPalette('@{primary-color}', 3) `), @component-background, 97%);
|
||||
@primary-10: mix(color(~`colorPalette('@{primary-color}', 2) `), @component-background, 98%);
|
||||
|
||||
// Layer background
|
||||
@popover-background: #1f1f1f;
|
||||
@popover-customize-border-color: #3a3a3a;
|
||||
@body-background: @black;
|
||||
@component-background: #141414;
|
||||
|
||||
@text-color: fade(@white, 85%);
|
||||
@text-color-secondary: fade(@white, 45%);
|
||||
@text-color-inverse: @white;
|
||||
@icon-color-hover: fade(@white, 75%);
|
||||
@heading-color: fade(@white, 85%);
|
||||
|
||||
// The background colors for active and hover states for things like
|
||||
// list items or table cells.
|
||||
@item-active-bg: @primary-1;
|
||||
@item-hover-bg: fade(@white, 8%);
|
||||
|
||||
// Border color
|
||||
@border-color-base: #434343; // base border outline a component
|
||||
@border-color-split: #303030; // split border inside a component
|
||||
|
||||
@background-color-light: fade(@white, 4%); // background of header and selected item
|
||||
@background-color-base: fade(@white, 8%); // Default grey background color
|
||||
|
||||
// Disabled states
|
||||
@disabled-color: fade(@white, 30%);
|
||||
@disabled-bg: @background-color-base;
|
||||
@disabled-color-dark: fade(@white, 30%);
|
||||
|
||||
// Tree
|
||||
// ---
|
||||
@tree-bg: transparent;
|
||||
|
||||
// List
|
||||
// ---
|
||||
@list-customize-card-bg: transparent;
|
||||
|
||||
// Shadow
|
||||
// ---
|
||||
@shadow-color: rgba(0, 0, 0, 0.45);
|
||||
@shadow-color-inverse: @component-background;
|
||||
@box-shadow-base: @shadow-2;
|
||||
@shadow-1-up: 0 -6px 16px -8px rgba(0, 0, 0, 0.32), 0 -9px 28px 0 rgba(0, 0, 0, 0.2),
|
||||
0 -12px 48px 16px rgba(0, 0, 0, 0.12);
|
||||
@shadow-1-down: 0 6px 16px -8px rgba(0, 0, 0, 0.32), 0 9px 28px 0 rgba(0, 0, 0, 0.2),
|
||||
0 12px 48px 16px rgba(0, 0, 0, 0.12);
|
||||
@shadow-1-right: 6px 0 16px -8px rgba(0, 0, 0, 0.32), 9px 0 28px 0 rgba(0, 0, 0, 0.2),
|
||||
12px 0 48px 16px rgba(0, 0, 0, 0.12);
|
||||
@shadow-2: 0 3px 6px -4px rgba(0, 0, 0, 0.48), 0 6px 16px 0 rgba(0, 0, 0, 0.32),
|
||||
0 9px 28px 8px rgba(0, 0, 0, 0.2);
|
||||
|
||||
// Buttons
|
||||
// ---
|
||||
@btn-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
|
||||
@btn-primary-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
|
||||
@btn-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
|
||||
|
||||
@btn-default-bg: transparent;
|
||||
|
||||
@btn-default-ghost-color: @text-color;
|
||||
@btn-default-ghost-border: fade(@white, 25%);
|
||||
|
||||
@btn-text-hover-bg: rgba(255, 255, 255, 0.03);
|
||||
|
||||
// Checkbox
|
||||
// ---
|
||||
@checkbox-check-bg: transparent;
|
||||
|
||||
// Descriptions
|
||||
// ---
|
||||
@descriptions-bg: @background-color-light;
|
||||
|
||||
// Divider
|
||||
// ---
|
||||
@divider-color: rgba(255, 255, 255, 12%);
|
||||
|
||||
// Modal
|
||||
// ---
|
||||
@modal-header-bg: @popover-background;
|
||||
@modal-header-border-color-split: @border-color-split;
|
||||
@modal-content-bg: @popover-background;
|
||||
@modal-footer-border-color-split: @border-color-split;
|
||||
|
||||
// Radio
|
||||
// ---
|
||||
@radio-solid-checked-color: @white;
|
||||
@radio-dot-disabled-color: fade(@white, 20%);
|
||||
|
||||
// Radio buttons
|
||||
// ---
|
||||
@radio-disabled-button-checked-bg: fade(@white, 20%);
|
||||
@radio-disabled-button-checked-color: @disabled-color;
|
||||
|
||||
// Layout
|
||||
// ---
|
||||
@layout-body-background: @body-background;
|
||||
@layout-header-background: @popover-background;
|
||||
@layout-trigger-background: #262626;
|
||||
|
||||
// Input
|
||||
// ---
|
||||
@input-bg: transparent;
|
||||
@input-placeholder-color: fade(@white, 30%);
|
||||
@input-icon-color: fade(@white, 30%);
|
||||
@input-number-handler-active-bg: @item-hover-bg;
|
||||
@input-icon-hover-color: fade(@white, 85%);
|
||||
|
||||
// Select
|
||||
// ---
|
||||
@select-background: transparent;
|
||||
@select-dropdown-bg: @popover-background;
|
||||
@select-clear-background: @component-background;
|
||||
@select-selection-item-bg: fade(@white, 8);
|
||||
@select-selection-item-border-color: @border-color-split;
|
||||
@select-multiple-disabled-background: @component-background;
|
||||
@select-multiple-item-disabled-color: #595959;
|
||||
@select-multiple-item-disabled-border-color: @popover-background;
|
||||
|
||||
// Cascader
|
||||
// ---
|
||||
@cascader-bg: transparent;
|
||||
@cascader-menu-bg: @popover-background;
|
||||
@cascader-menu-border-color-split: @border-color-split;
|
||||
|
||||
// Tooltip
|
||||
// ---
|
||||
// Tooltip background color
|
||||
@tooltip-bg: #434343;
|
||||
|
||||
// Menu
|
||||
// ---
|
||||
// dark theme
|
||||
@menu-dark-inline-submenu-bg: @component-background;
|
||||
@menu-dark-bg: @popover-background;
|
||||
@menu-popup-bg: @popover-background;
|
||||
|
||||
// Message
|
||||
// ---
|
||||
@message-notice-content-bg: @popover-background;
|
||||
|
||||
// Notification
|
||||
@notification-bg: @popover-background;
|
||||
|
||||
// LINK
|
||||
@link-hover-color: @primary-5;
|
||||
@link-active-color: @primary-7;
|
||||
|
||||
// Table
|
||||
// --
|
||||
@table-header-bg: #1d1d1d;
|
||||
@table-body-sort-bg: fade(@white, 1%);
|
||||
@table-row-hover-bg: #262626;
|
||||
@table-header-cell-split-color: fade(@white, 8%);
|
||||
@table-header-sort-bg: #262626;
|
||||
@table-header-filter-active-bg: #434343;
|
||||
@table-header-sort-active-bg: #303030;
|
||||
@table-fixed-header-sort-active-bg: #222;
|
||||
@table-filter-btns-bg: @popover-background;
|
||||
@table-expanded-row-bg: @table-header-bg;
|
||||
@table-filter-dropdown-bg: @popover-background;
|
||||
@table-expand-icon-bg: transparent;
|
||||
|
||||
// Tag
|
||||
// ---
|
||||
@info-color-deprecated-bg: @primary-1;
|
||||
@info-color-deprecated-border: @primary-3;
|
||||
@success-color-deprecated-bg: @green-1;
|
||||
@success-color-deprecated-border: @green-3;
|
||||
@warning-color-deprecated-bg: @orange-1;
|
||||
@warning-color-deprecated-border: @orange-3;
|
||||
@error-color-deprecated-bg: @red-1;
|
||||
@error-color-deprecated-border: @red-3;
|
||||
|
||||
// TimePicker
|
||||
// ---
|
||||
@picker-basic-cell-hover-with-range-color: darken(@primary-color, 35%);
|
||||
@picker-basic-cell-disabled-bg: #303030;
|
||||
@picker-border-color: @border-color-split;
|
||||
@picker-bg: transparent;
|
||||
@picker-date-hover-range-border-color: darken(@primary-color, 20%);
|
||||
|
||||
// Dropdown
|
||||
// ---
|
||||
@dropdown-menu-bg: @popover-background;
|
||||
@dropdown-menu-submenu-disabled-bg: transparent;
|
||||
|
||||
// Steps
|
||||
// ---
|
||||
@steps-nav-arrow-color: fade(@white, 20%);
|
||||
@steps-background: transparent;
|
||||
|
||||
// Avatar
|
||||
// ---
|
||||
@avatar-bg: fade(@white, 30%);
|
||||
|
||||
// Progress
|
||||
// ---
|
||||
@progress-steps-item-bg: fade(@white, 8%);
|
||||
|
||||
// Calendar
|
||||
// ---
|
||||
@calendar-bg: @popover-background;
|
||||
@calendar-input-bg: @calendar-bg;
|
||||
@calendar-border-color: transparent;
|
||||
@calendar-full-bg: @component-background;
|
||||
|
||||
// Badge
|
||||
// ---
|
||||
@badge-text-color: @white;
|
||||
|
||||
// Popover
|
||||
@popover-bg: @popover-background;
|
||||
|
||||
// Drawer
|
||||
@drawer-bg: @popover-background;
|
||||
|
||||
// Card
|
||||
// ---
|
||||
@card-actions-background: @component-background;
|
||||
@card-skeleton-bg: #303030;
|
||||
@card-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.64), 0 3px 6px 0 rgba(0, 0, 0, 0.48),
|
||||
0 5px 12px 4px rgba(0, 0, 0, 0.36);
|
||||
|
||||
// Transfer
|
||||
// ---
|
||||
@transfer-item-hover-bg: #262626;
|
||||
|
||||
// Comment
|
||||
// ---
|
||||
@comment-bg: transparent;
|
||||
@comment-author-time-color: fade(@white, 30%);
|
||||
@comment-action-hover-color: fade(@white, 65%);
|
||||
|
||||
// Rate
|
||||
// ---
|
||||
@rate-star-bg: fade(@white, 12%);
|
||||
|
||||
// Switch
|
||||
// ---
|
||||
@switch-bg: @white;
|
||||
|
||||
// Pagination
|
||||
// ---
|
||||
@pagination-item-bg: transparent;
|
||||
@pagination-item-bg-active: transparent;
|
||||
@pagination-item-link-bg: transparent;
|
||||
@pagination-item-disabled-bg-active: fade(@white, 25%);
|
||||
@pagination-item-disabled-color-active: @black;
|
||||
@pagination-item-input-bg: @pagination-item-bg;
|
||||
|
||||
// PageHeader
|
||||
// ---
|
||||
@page-header-back-color: @icon-color;
|
||||
@page-header-ghost-bg: transparent;
|
||||
|
||||
// Slider
|
||||
// ---
|
||||
@slider-rail-background-color: #262626;
|
||||
@slider-rail-background-color-hover: @border-color-base;
|
||||
@slider-dot-border-color: @border-color-split;
|
||||
@slider-dot-border-color-active: @primary-4;
|
||||
|
||||
// Skeleton
|
||||
// ---
|
||||
@skeleton-to-color: fade(@white, 16%);
|
||||
|
||||
// Alert
|
||||
// ---
|
||||
@alert-success-border-color: @green-3;
|
||||
@alert-success-bg-color: @green-1;
|
||||
@alert-success-icon-color: @success-color;
|
||||
@alert-info-border-color: @primary-3;
|
||||
@alert-info-bg-color: @primary-1;
|
||||
@alert-info-icon-color: @info-color;
|
||||
@alert-warning-border-color: @gold-3;
|
||||
@alert-warning-bg-color: @gold-1;
|
||||
@alert-warning-icon-color: @warning-color;
|
||||
@alert-error-border-color: @red-3;
|
||||
@alert-error-bg-color: @red-1;
|
||||
@alert-error-icon-color: @error-color;
|
||||
|
||||
// Timeline
|
||||
// ---
|
||||
@timeline-color: @border-color-split;
|
||||
@timeline-dot-color: @primary-color;
|
||||
|
||||
// Mentions
|
||||
// ---
|
||||
@mentions-dropdown-bg: @popover-background;
|
||||
|
||||
// Segmented
|
||||
// ---
|
||||
@segmented-bg: fade(@black, 25%);
|
||||
@segmented-hover-bg: fade(@black, 45%);
|
||||
@segmented-selected-bg: #333333;
|
||||
@segmented-label-color: fade(@white, 65%);
|
||||
@segmented-label-hover-color: fade(@white, 85%);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
||||
// Default using variable as entry to support site variable version
|
||||
// This will be replaced in webpack bundle
|
||||
// @root-entry-name: variable;
|
||||
|
||||
// @import './default.less';
|
||||
// @import './variable.less';
|
||||
@import './@{root-entry-name}.less';
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
@root-entry-name: variable;
|
||||
|
||||
@import './themes/variable.less';
|
||||
@import './core/index';
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
DeleteOutlined,
|
||||
ExportOutlined,
|
||||
RocketOutlined,
|
||||
FormOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
export type BatchCtrlDropDownButtonProps = {
|
||||
@@ -52,6 +53,12 @@ const BatchCtrlDropDownButton: FC<BatchCtrlDropDownButtonProps> = ({
|
||||
icon: <RocketOutlined />,
|
||||
disabled: disabledList?.includes('batchUnPublish'),
|
||||
},
|
||||
batchAddClass: {
|
||||
key: 'batchAddClass',
|
||||
label: '批量分类',
|
||||
icon: <FormOutlined />,
|
||||
disabled: disabledList?.includes('batchAddClass'),
|
||||
},
|
||||
};
|
||||
|
||||
const extenderButtonList: any[] = extenderList.reduce((list: any[], key) => {
|
||||
|
||||
@@ -18,7 +18,7 @@ const FormItemTitle: React.FC<IProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<Space direction="vertical" size={2} style={{ width: '100%' }}>
|
||||
<div>{title}</div>
|
||||
<div className={styles.title}>{title}</div>
|
||||
<div className={styles.subTitleContainer}>
|
||||
{subTitleEditable ? (
|
||||
<Paragraph
|
||||
@@ -31,7 +31,7 @@ const FormItemTitle: React.FC<IProps> = ({
|
||||
{subTitle || '添加描述'}
|
||||
</Paragraph>
|
||||
) : (
|
||||
subTitle && <span style={{ fontSize: '12px', color: '#6a6a6a' }}>{subTitle}</span>
|
||||
subTitle && <span style={{ fontSize: '12px', color: '#7b809a' }}>{subTitle}</span>
|
||||
)}
|
||||
</div>
|
||||
</Space>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
.title {
|
||||
font-family: var(--tencent-font-family);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.subTitleContainer {
|
||||
width: 500px;
|
||||
color: #7b809a;
|
||||
:global {
|
||||
.ant-typography{
|
||||
font-size: 12px;
|
||||
|
||||
@@ -51,7 +51,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = () => {
|
||||
<HeaderDropdown menu={{ items }} disabled={APP_TARGET === 'inner'}>
|
||||
<span className={`${styles.action} ${styles.account}`}>
|
||||
<TMEAvatar className={styles.avatar} size="small" staffName={currentUser.staffName} />
|
||||
<span style={{ color: '#fff' }}>{currentUser.staffName}</span>
|
||||
<span className={styles.userName}>{currentUser.staffName}</span>
|
||||
</span>
|
||||
</HeaderDropdown>
|
||||
);
|
||||
|
||||
@@ -27,19 +27,21 @@
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
color: #fff;
|
||||
margin-right: 10px;
|
||||
>span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #296df3;
|
||||
background: rgba(232, 232, 232, 0.65);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
&:global(.opened) {
|
||||
background: @pro-header-hover-bg;
|
||||
}
|
||||
// &:global(.opened) {
|
||||
// background: @pro-header-hover-bg;
|
||||
// }
|
||||
}
|
||||
|
||||
.search {
|
||||
@@ -53,9 +55,13 @@
|
||||
.account {
|
||||
.avatar {
|
||||
margin-right: 8px;
|
||||
color: @primary-color;
|
||||
color: var(--tme-primary-color);
|
||||
vertical-align: top;
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
background: rgba(150, 150, 150, 0.85);
|
||||
}
|
||||
.userName {
|
||||
color: var(--tme-primary-color);
|
||||
font-family: var(--tencent-font-family);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import type { FC } from 'react';
|
||||
import { Select, message } from 'antd';
|
||||
import { Select } from 'antd';
|
||||
import type { UserItem } from './service';
|
||||
import { getAllUser } from './service';
|
||||
|
||||
import { useModel } from '@umijs/max';
|
||||
import styles from './index.less';
|
||||
import { useFetchDataEffect } from '@/utils/curd';
|
||||
import TMEAvatar from '../TMEAvatar';
|
||||
|
||||
interface Props {
|
||||
@@ -17,27 +15,20 @@ interface Props {
|
||||
|
||||
const SelectTMEPerson: FC<Props> = ({ placeholder, value, isMultiple = true, onChange }) => {
|
||||
const [userList, setUserList] = useState<UserItem[]>([]);
|
||||
const allUserModel = useModel('allUserData');
|
||||
const { allUserList, MrefreshUserList } = allUserModel;
|
||||
|
||||
useFetchDataEffect(
|
||||
{
|
||||
fetcher: async () => {
|
||||
const res = await getAllUser();
|
||||
if (res.code == 200 || Number(res.code) == 0) {
|
||||
return res.data || [];
|
||||
} else {
|
||||
message.error(res.msg);
|
||||
throw new Error(res.msg);
|
||||
}
|
||||
},
|
||||
updater: (list) => {
|
||||
const queryTmePersonData = async () => {
|
||||
const list = await MrefreshUserList();
|
||||
setUserList(list);
|
||||
},
|
||||
cleanup: () => {
|
||||
setUserList([]);
|
||||
},
|
||||
},
|
||||
[],
|
||||
);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (Array.isArray(allUserList) && allUserList.length > 0) {
|
||||
setUserList(allUserList);
|
||||
} else {
|
||||
queryTmePersonData();
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Select
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
export const EnumTransModelType = {
|
||||
edit: '编辑',
|
||||
add: '新增',
|
||||
};
|
||||
|
||||
export const EnumDescSensitivity = {
|
||||
low: {
|
||||
value: 1,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
:root:root {
|
||||
--primary-color: #f87653;
|
||||
--tme-primary-color: #1672fa;
|
||||
--blue: #296df3;
|
||||
--deep-blue: #446dff;
|
||||
--chat-blue: #1b4aef;
|
||||
@@ -22,13 +22,15 @@
|
||||
--processing-color: #ff2442;
|
||||
--error-color: #ff4d4f;
|
||||
--highlight-color: #ff4d4f;
|
||||
--font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Microsoft YaHei,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
|
||||
--tencent-font-family: 'tencentFont',-apple-system,BlinkMacSystemFont,"Segoe UI",Microsoft YaHei,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
height: 100%;
|
||||
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Microsoft YaHei,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
|
||||
font-family: var(--tencent-font-family);
|
||||
-webkit-font-smoothing:antialiased;
|
||||
margin: 0;
|
||||
}
|
||||
@@ -56,6 +58,16 @@ ol {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DINPro Medium';
|
||||
src: url('~@/assets/fonts/DINPro.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'tencentFont';
|
||||
src: url('~@/assets/fonts/TencentSans-W7.woff') format('woff');
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.ant-table {
|
||||
width: 100%;
|
||||
@@ -96,9 +108,9 @@ ol {
|
||||
margin: 12px 12px 0 !important;
|
||||
}
|
||||
|
||||
.ant-page-header {
|
||||
padding-bottom: 10px !important;
|
||||
}
|
||||
// .ant-page-header {
|
||||
// padding-bottom: 10px !important;
|
||||
// }
|
||||
|
||||
.ant-spin-spinning {
|
||||
display: flex !important;
|
||||
@@ -120,10 +132,12 @@ ol {
|
||||
height: 100vh;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-pro-layout .ant-pro-layout-bg-list {
|
||||
background: #fafafb;
|
||||
}
|
||||
.ant-pro-layout .ant-pro-layout-content {
|
||||
padding: 0;
|
||||
background-color: #f0f2f5;
|
||||
background-color: #fafafb;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,51 +146,55 @@ ol {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ant-pro-top-nav-header-menu {
|
||||
padding: 0!important;
|
||||
line-height: unset!important;
|
||||
}
|
||||
|
||||
.ant-menu-root>.ant-menu-item,
|
||||
.ant-menu-root>.ant-menu-submenu {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
&>span>a,
|
||||
&>a {
|
||||
color: white;
|
||||
&:hover {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: #296DF3!important;
|
||||
}
|
||||
}
|
||||
|
||||
// .ant-menu-root>.ant-menu-item,
|
||||
// .ant-menu-root>.ant-menu-submenu {
|
||||
// font-weight: bold;
|
||||
// font-size: 14px;
|
||||
// &>span>a,
|
||||
// &>a {
|
||||
// color: white;
|
||||
// &:hover {
|
||||
// color: white;
|
||||
// }
|
||||
// }
|
||||
// &:hover {
|
||||
// background-color: #296DF3!important;
|
||||
// }
|
||||
// }
|
||||
|
||||
.ant-menu-root>.ant-menu-item.ant-menu-item-selected {
|
||||
background-color: #296DF3!important;
|
||||
color: white;
|
||||
// background-color: #296DF3!important;
|
||||
color: var(--tme-primary-color);
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.ant-menu-light.ant-menu-horizontal >.ant-menu-item-selected::after {
|
||||
border-bottom-width: 2px;
|
||||
border-bottom-color: var(--tme-primary-color);
|
||||
}
|
||||
|
||||
// .ant-menu-light.ant-menu-horizontal >.ant-menu-item-selected::hover {
|
||||
// border-bottom-width: 2px;
|
||||
// border-bottom-color: var(--tme-primary-color);
|
||||
// }
|
||||
|
||||
.ant-pro-top-nav-header-logo h1 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.ant-layout-header {
|
||||
background: linear-gradient(to right, #153d8f, #0a276d) !important;
|
||||
background-color: rgba(0, 0, 0, 0.2) !important;
|
||||
backdrop-filter: blur(10px) !important;
|
||||
// font-size: 18px;
|
||||
color: var(--tme-primary-color)
|
||||
}
|
||||
|
||||
|
||||
|
||||
.ant-pro-top-nav-header-main-left {
|
||||
min-width: 100px !important;
|
||||
}
|
||||
|
||||
.ant-pro-top-nav-header-logo {
|
||||
min-width: 100px !important;
|
||||
}
|
||||
// .ant-pro-top-nav-header-main-left {
|
||||
// min-width: 100px !important;
|
||||
// }
|
||||
|
||||
// .ant-pro-top-nav-header-logo {
|
||||
// min-width: 100px !important;
|
||||
// }
|
||||
|
||||
|
||||
.logo {
|
||||
@@ -240,3 +258,37 @@ ol {
|
||||
font-weight: 500;
|
||||
color: #667085;
|
||||
}
|
||||
|
||||
.ant-select-dropdown {
|
||||
.ant-select-item {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
background-color: transparent;
|
||||
outline: 0px;
|
||||
border: 0px;
|
||||
margin: 0px;
|
||||
border-radius: 0px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
vertical-align: middle;
|
||||
appearance: none;
|
||||
color: #606060;
|
||||
font-size: 14px;
|
||||
line-height: 1.57;
|
||||
font-family: var(--tencent-font-family);
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
min-height: 36px;
|
||||
padding: 6px 16px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
font-weight: 400;
|
||||
}
|
||||
&.ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
|
||||
font-weight: 400;
|
||||
color: rgb(38, 38, 38);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ export default {
|
||||
'menu.semanticModel': '语义建模',
|
||||
'menu.metric': '指标市场',
|
||||
'menu.metric.metricDetail': '指标详情页',
|
||||
'menu.metricEdit': '指标编辑',
|
||||
'menu.tag': '标签市场',
|
||||
'menu.tag.tagDetail': '标签详情页',
|
||||
'menu.database': '数据库管理',
|
||||
|
||||
25
webapp/packages/supersonic-fe/src/models/allUserData.ts
Normal file
25
webapp/packages/supersonic-fe/src/models/allUserData.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { useState } from 'react';
|
||||
import { getAllUser } from '../components/SelectTMEPerson/service';
|
||||
import type { UserItem } from '../components/SelectTMEPerson/service';
|
||||
|
||||
export default function Model() {
|
||||
const [allUserList, setAllUserList] = useState<UserItem[]>([]);
|
||||
|
||||
const queryUserData = async () => {
|
||||
const { code, data } = await getAllUser();
|
||||
if (code === 200 || Number(code) === 0) {
|
||||
setAllUserList(data);
|
||||
return data;
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const MrefreshUserList = async () => {
|
||||
return await queryUserData();
|
||||
};
|
||||
|
||||
return {
|
||||
allUserList,
|
||||
MrefreshUserList,
|
||||
};
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
import { useLocation } from 'umi';
|
||||
import { useLocation } from '@umijs/max';
|
||||
import { getToken } from '@/utils/utils';
|
||||
import queryString from 'query-string';
|
||||
import { Chat } from 'supersonic-chat-sdk';
|
||||
|
||||
const ChatPage = () => {
|
||||
const location = useLocation();
|
||||
const { agentId } = (location as any).query;
|
||||
const query = queryString.parse(location.search) || {};
|
||||
const { agentId } = query;
|
||||
|
||||
return (
|
||||
<Chat initialAgentId={agentId ? +agentId : undefined} token={getToken() || ''} isDeveloper />
|
||||
|
||||
@@ -12,23 +12,19 @@ import {
|
||||
getUnAvailableItem,
|
||||
getTagObjectList,
|
||||
} from '../../service';
|
||||
import type { Dispatch } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import { connect } from 'umi';
|
||||
import { useModel } from '@umijs/max';
|
||||
import { ISemantic, IDataSource } from '../../data';
|
||||
import { isArrayOfValues } from '@/utils/utils';
|
||||
import EffectDimensionAndMetricTipsModal from './EffectDimensionAndMetricTipsModal';
|
||||
|
||||
export type CreateFormProps = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
createModalVisible: boolean;
|
||||
sql?: string;
|
||||
sqlParams?: IDataSource.ISqlParamsItem[];
|
||||
databaseId?: number;
|
||||
modelItem: ISemantic.IModelItem;
|
||||
onCancel?: () => void;
|
||||
onSubmit?: (dataSourceInfo: any) => void;
|
||||
onSubmit?: (modelItem: ISemantic.IModelItem) => void;
|
||||
scriptColumns?: any[] | undefined;
|
||||
basicInfoFormMode?: 'normal' | 'fast';
|
||||
onDataBaseTableChange?: (tableName: string) => void;
|
||||
@@ -44,7 +40,6 @@ const initFormVal = {
|
||||
};
|
||||
|
||||
const ModelCreateForm: React.FC<CreateFormProps> = ({
|
||||
domainManger,
|
||||
onCancel,
|
||||
createModalVisible,
|
||||
scriptColumns,
|
||||
@@ -63,7 +58,7 @@ const ModelCreateForm: React.FC<CreateFormProps> = ({
|
||||
const [fields, setFields] = useState<any[]>([]);
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
// const [hasEmptyNameField, setHasEmptyNameField] = useState<boolean>(false);
|
||||
|
||||
const [formDatabaseId, setFormDatabaseId] = useState<number>();
|
||||
const [queryParamsState, setQueryParamsState] = useState({});
|
||||
const [effectTipsModalOpenState, setEffectTipsModalOpenState] = useState<boolean>(false);
|
||||
@@ -74,21 +69,18 @@ const ModelCreateForm: React.FC<CreateFormProps> = ({
|
||||
const [tagObjectIdState, setTagObjectIdState] = useState(modelItem?.tagObjectId);
|
||||
const formValRef = useRef(initFormVal as any);
|
||||
const [form] = Form.useForm();
|
||||
const { databaseConfigList, selectModelId: modelId, selectDomainId, domainData } = domainManger;
|
||||
const domainModel = useModel('SemanticModel.domainData');
|
||||
const modelModel = useModel('SemanticModel.modelData');
|
||||
const { selectDomainId, selectDomain: domainData } = domainModel;
|
||||
const { selectModelId: modelId } = modelModel;
|
||||
|
||||
const databaseModel = useModel('SemanticModel.databaseData');
|
||||
const { databaseConfigList } = databaseModel;
|
||||
|
||||
const updateFormVal = (val: any) => {
|
||||
formValRef.current = val;
|
||||
};
|
||||
const [sqlFilter, setSqlFilter] = useState<string>('');
|
||||
// useEffect(() => {
|
||||
// const hasEmpty = fields.some((item) => {
|
||||
// const { name, isCreateDimension, isCreateMetric } = item;
|
||||
// if ((isCreateMetric || isCreateDimension) && !name) {
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// });
|
||||
// setHasEmptyNameField(hasEmpty);
|
||||
// }, [fields]);
|
||||
|
||||
const [fieldColumns, setFieldColumns] = useState<IDataSource.IExecuteSqlColumn[]>(
|
||||
scriptColumns || [],
|
||||
@@ -155,8 +147,8 @@ const ModelCreateForm: React.FC<CreateFormProps> = ({
|
||||
|
||||
const saveModel = async (queryParams: any) => {
|
||||
setSaveLoading(true);
|
||||
const queryDatasource = isEdit ? updateModel : createModel;
|
||||
const { code, msg, data } = await queryDatasource(queryParams);
|
||||
const querySaveModel = isEdit ? updateModel : createModel;
|
||||
const { code, msg, data } = await querySaveModel(queryParams);
|
||||
setSaveLoading(false);
|
||||
if (code === 200) {
|
||||
message.success('保存模型成功!');
|
||||
@@ -218,7 +210,6 @@ const ModelCreateForm: React.FC<CreateFormProps> = ({
|
||||
isCreateDimension,
|
||||
name,
|
||||
type,
|
||||
// entityNames,
|
||||
tagObjectId: modelItem?.tagObjectId,
|
||||
});
|
||||
break;
|
||||
@@ -502,7 +493,6 @@ const ModelCreateForm: React.FC<CreateFormProps> = ({
|
||||
onClick={() => {
|
||||
handleNext(true);
|
||||
}}
|
||||
// disabled={hasEmptyNameField}
|
||||
>
|
||||
保 存
|
||||
</Button>
|
||||
@@ -590,6 +580,4 @@ const ModelCreateForm: React.FC<CreateFormProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(ModelCreateForm);
|
||||
export default ModelCreateForm;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Button, Table, message, Tooltip, Space, Dropdown } from 'antd';
|
||||
import SplitPane from 'react-split-pane';
|
||||
import Pane from 'react-split-pane/lib/Pane';
|
||||
import { connect } from 'umi';
|
||||
import { useModel } from '@umijs/max';
|
||||
import sqlFormatter from 'sql-formatter';
|
||||
import {
|
||||
FullscreenOutlined,
|
||||
@@ -19,7 +19,6 @@ import FullScreen from '@/components/FullScreen';
|
||||
import SqlEditor from '@/components/SqlEditor';
|
||||
import type { TaskResultItem, TaskResultColumn } from '../data';
|
||||
import { excuteSql } from '@/pages/SemanticModel/service';
|
||||
import type { Dispatch } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import SqlParams from './SqlParams';
|
||||
import styles from '../style.less';
|
||||
@@ -37,8 +36,6 @@ export type DataSourceSubmitData = {
|
||||
};
|
||||
|
||||
type IProps = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
dataSourceItem: IDataSource.IDataSourceItem;
|
||||
onUpdateSql?: (sql: string) => void;
|
||||
sql?: string;
|
||||
@@ -61,13 +58,14 @@ type DatabaseItem = {
|
||||
};
|
||||
|
||||
const SqlDetail: React.FC<IProps> = ({
|
||||
domainManger,
|
||||
dataSourceItem,
|
||||
onSubmitSuccess,
|
||||
sql = '',
|
||||
onUpdateSql,
|
||||
}) => {
|
||||
const { databaseConfigList } = domainManger;
|
||||
const databaseModel = useModel('SemanticModel.databaseData');
|
||||
const { databaseConfigList } = databaseModel;
|
||||
|
||||
const [resultTable, setResultTable] = useState<ResultTableItem[]>([]);
|
||||
const [resultTableLoading, setResultTableLoading] = useState(false);
|
||||
const [resultCols, setResultCols] = useState<ResultColItem[]>([]);
|
||||
@@ -385,7 +383,6 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
}, [resultTable, isSqlResFullScreen]);
|
||||
|
||||
useEffect(() => {
|
||||
// queryDatabaseConfig();
|
||||
const windowHeight = window.innerHeight;
|
||||
let size: ScreenSize = 'small';
|
||||
if (windowHeight > 1100) {
|
||||
@@ -479,10 +476,7 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={variableCollapsed ? styles.hideSqlParams : styles.sqlParams}
|
||||
// style={{ height: sqlEditorHeight }}
|
||||
>
|
||||
<div className={variableCollapsed ? styles.hideSqlParams : styles.sqlParams}>
|
||||
<SqlParams
|
||||
value={sqlParams}
|
||||
onChange={(params) => {
|
||||
@@ -538,6 +532,4 @@ const SqlDetail: React.FC<IProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(SqlDetail);
|
||||
export default SqlDetail;
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from './model';
|
||||
import OverviewContainer from './OverviewContainer';
|
||||
import type { Dispatch } from 'umi';
|
||||
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
type Props = {};
|
||||
const DomainManager: React.FC<Props> = () => {
|
||||
return (
|
||||
<>
|
||||
@@ -16,6 +10,4 @@ const DomainManager: React.FC<Props> = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(DomainManager);
|
||||
export default DomainManager;
|
||||
|
||||
@@ -30,17 +30,14 @@ import './index.less';
|
||||
/** Mock所有与服务端交互的接口 */
|
||||
import { MockApi } from './service';
|
||||
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
type Props = {};
|
||||
|
||||
/** 鼠标的引用 */
|
||||
let cursorTipRef: HTMLDivElement;
|
||||
/** 鼠标在画布的位置 */
|
||||
let cursorLocation: any;
|
||||
|
||||
const DomainManger: React.FC<Props> = (demoProps: Props) => {
|
||||
const HeadLessFlows: React.FC<Props> = (demoProps: Props) => {
|
||||
/** XFlow应用实例 */
|
||||
const app = useXFlowApp();
|
||||
|
||||
@@ -309,6 +306,4 @@ const DomainManger: React.FC<Props> = (demoProps: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(DomainManger);
|
||||
export default HeadLessFlows;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { message, Tabs, Button, Space } from 'antd';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { getTagData } from '../service';
|
||||
import { connect, useParams, history } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import { useParams, history } from 'umi';
|
||||
import styles from './style.less';
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import TagTrendSection from './components/TagTrendSection';
|
||||
@@ -16,7 +15,7 @@ type Props = Record<string, any>;
|
||||
const TagDetail: React.FC<Props> = () => {
|
||||
const params: any = useParams();
|
||||
const tagId = params.tagId;
|
||||
const [tagData, setTagData] = useState<ISemantic.IMetricItem>();
|
||||
const [tagData, setTagData] = useState<ISemantic.ITagItem>();
|
||||
const [dimensionMap, setDimensionMap] = useState<Record<string, ISemantic.IDimensionItem>>({});
|
||||
|
||||
const [metricMap, setMetricMap] = useState<Record<string, ISemantic.IMetricItem>>({});
|
||||
@@ -146,6 +145,4 @@ const TagDetail: React.FC<Props> = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(TagDetail);
|
||||
export default TagDetail;
|
||||
|
||||
@@ -2,9 +2,7 @@ import type { ActionType, ProColumns } from '@ant-design/pro-components';
|
||||
import { ProTable } from '@ant-design/pro-components';
|
||||
import { message, Space, Popconfirm } from 'antd';
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { connect, useModel } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import { useModel } from 'umi';
|
||||
import { SENSITIVE_LEVEL_ENUM } from '../constant';
|
||||
import { getTagList, deleteTag, batchDeleteTag, getTagObjectList } from '../service';
|
||||
import TagFilter from './components/TagFilter';
|
||||
@@ -15,10 +13,7 @@ import { ISemantic } from '../data';
|
||||
import BatchCtrlDropDownButton from '@/components/BatchCtrlDropDownButton';
|
||||
import { ColumnsConfig } from '../components/TableColumnRender';
|
||||
|
||||
type Props = {
|
||||
dispatch: Dispatch;
|
||||
domainManger: StateType;
|
||||
};
|
||||
type Props = {};
|
||||
|
||||
type QueryMetricListParams = {
|
||||
id?: string;
|
||||
@@ -29,11 +24,9 @@ type QueryMetricListParams = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const ClassMetricTable: React.FC<Props> = ({}) => {
|
||||
const { initialState = {} } = useModel('@@initialState');
|
||||
|
||||
const { currentUser = {} } = initialState as any;
|
||||
const { selectDomainId, selectModelId: modelId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const defaultPagination = {
|
||||
current: 1,
|
||||
@@ -400,8 +393,6 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
|
||||
{createModalVisible && (
|
||||
<TagInfoCreateForm
|
||||
domainId={selectDomainId}
|
||||
modelId={Number(modelId)}
|
||||
createModalVisible={createModalVisible}
|
||||
tagItem={tagItem}
|
||||
onSubmit={() => {
|
||||
@@ -416,6 +407,4 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(ClassMetricTable);
|
||||
export default ClassMetricTable;
|
||||
|
||||
@@ -2,10 +2,8 @@ import type { ActionType, ProColumns } from '@ant-design/pro-components';
|
||||
import { ProTable } from '@ant-design/pro-components';
|
||||
import { message, Button, Space, Popconfirm, Input, Select } from 'antd';
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { StatusEnum } from '../../enum';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import { useModel } from '@umijs/max';
|
||||
import { SENSITIVE_LEVEL_ENUM, SENSITIVE_LEVEL_OPTIONS } from '../../constant';
|
||||
import { getTagList, deleteTag, batchUpdateTagStatus } from '../../service';
|
||||
import TagInfoCreateForm from './TagInfoCreateForm';
|
||||
@@ -17,13 +15,14 @@ import { ISemantic } from '../../data';
|
||||
import { ColumnsConfig } from '../../components/TableColumnRender';
|
||||
import TagValueSettingModal from './TagValueSettingModal';
|
||||
|
||||
type Props = {
|
||||
dispatch: Dispatch;
|
||||
domainManger: StateType;
|
||||
};
|
||||
type Props = {};
|
||||
|
||||
const ClassTagTable: React.FC<Props> = ({}) => {
|
||||
const domainModel = useModel('SemanticModel.domainData');
|
||||
const modelModel = useModel('SemanticModel.modelData');
|
||||
const { selectDomainId } = domainModel;
|
||||
const { selectModelId: modelId } = modelModel;
|
||||
|
||||
const ClassTagTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const { selectModelId: modelId, selectDomainId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const [tagItem, setTagItem] = useState<ISemantic.ITagItem>();
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||
@@ -369,6 +368,4 @@ const ClassTagTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(ClassTagTable);
|
||||
export default ClassTagTable;
|
||||
|
||||
@@ -15,8 +15,7 @@ import { ISemantic } from '../../data';
|
||||
|
||||
export type CreateFormProps = {
|
||||
datasourceId?: number;
|
||||
domainId: number;
|
||||
modelId: number;
|
||||
modelId?: number;
|
||||
createModalVisible: boolean;
|
||||
tagItem?: ISemantic.ITagItem;
|
||||
onCancel?: () => void;
|
||||
@@ -78,8 +77,8 @@ const TagInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
const forward = () => setCurrentStep(currentStep + 1);
|
||||
const backward = () => setCurrentStep(currentStep - 1);
|
||||
|
||||
const queryModelDetail = async () => {
|
||||
const { code, data } = await getModelDetail({ modelId: modelId || tagItem?.modelId });
|
||||
const queryModelDetail = async (modelId) => {
|
||||
const { code, data } = await getModelDetail({ modelId });
|
||||
if (code === 200) {
|
||||
if (Array.isArray(data?.modelDetail?.fields)) {
|
||||
if (Array.isArray(tagItem?.tagDefineParams?.dependencies)) {
|
||||
@@ -112,10 +111,14 @@ const TagInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
queryModelDetail();
|
||||
queryDimensionList(modelId);
|
||||
queryMetricList(modelId);
|
||||
}, [modelId]);
|
||||
const id = modelId || tagItem?.modelId;
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
queryModelDetail(id);
|
||||
queryDimensionList(id);
|
||||
queryMetricList(id);
|
||||
}, [modelId, tagItem]);
|
||||
|
||||
const handleNext = async () => {
|
||||
const fieldsValue = await form.validateFields();
|
||||
@@ -226,7 +229,7 @@ const TagInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
if (isArrayOfValues(tagItem?.tagDefineParams?.dependencies)) {
|
||||
const fieldList = list.map((item: ISemantic.IDimensionItem) => {
|
||||
const { id } = item;
|
||||
if (tagItem.tagDefineParams.dependencies.includes(id)) {
|
||||
if (tagItem?.tagDefineParams.dependencies.includes(id)) {
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 9999,
|
||||
@@ -262,7 +265,7 @@ const TagInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
if (isArrayOfValues(tagItem?.tagDefineParams?.dependencies)) {
|
||||
const fieldList = list.map((item: ISemantic.IMetricItem) => {
|
||||
const { id } = item;
|
||||
if (tagItem.tagDefineParams.dependencies.includes(id)) {
|
||||
if (tagItem?.tagDefineParams.dependencies.includes(id)) {
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 9999,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Tag, Space, Tooltip, Typography } from 'antd';
|
||||
import { Tag, Space, Tooltip } from 'antd';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import dayjs from 'dayjs';
|
||||
import {
|
||||
@@ -23,7 +22,6 @@ import IndicatorStar from '../../components/IndicatorStar';
|
||||
|
||||
type Props = {
|
||||
tagData: ISemantic.ITagItem;
|
||||
domainManger: StateType;
|
||||
onNodeChange: (params?: { eventName?: string }) => void;
|
||||
onEditBtnClick?: (tagData: any) => void;
|
||||
onDimensionRelationBtnClick?: () => void;
|
||||
@@ -251,6 +249,4 @@ const TagInfoSider: React.FC<Props> = ({ tagData, dimensionMap, metricMap }) =>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(TagInfoSider);
|
||||
export default TagInfoSider;
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
import type { ActionType, ProColumns } from '@ant-design/pro-components';
|
||||
import { ProTable } from '@ant-design/pro-components';
|
||||
import { message, Button, Space, Popconfirm, Input, Select } from 'antd';
|
||||
import { message, Button, Space, Popconfirm } from 'antd';
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { StatusEnum } from '../../enum';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import { SENSITIVE_LEVEL_ENUM, SENSITIVE_LEVEL_OPTIONS } from '../../constant';
|
||||
import { useModel } from '@umijs/max';
|
||||
import { getTagObjectList, deleteTagObject, batchUpdateTagStatus } from '../../service';
|
||||
|
||||
import TagObjectCreateForm from './TagObjectCreateForm';
|
||||
// import BatchCtrlDropDownButton from '@/components/BatchCtrlDropDownButton';
|
||||
import TableHeaderFilter from '../../components/TableHeaderFilter';
|
||||
import moment from 'moment';
|
||||
import styles from '../style.less';
|
||||
import { ISemantic } from '../../data';
|
||||
import { ColumnsConfig } from '../../components/TableColumnRender';
|
||||
import TagValueSettingModal from './TagValueSettingModal';
|
||||
|
||||
type Props = {
|
||||
dispatch: Dispatch;
|
||||
domainManger: StateType;
|
||||
};
|
||||
type Props = {};
|
||||
|
||||
const TagObjectTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const { selectModelId: modelId, selectDomainId } = domainManger;
|
||||
const TagObjectTable: React.FC<Props> = ({}) => {
|
||||
const domainModel = useModel('SemanticModel.domainData');
|
||||
const modelModel = useModel('SemanticModel.modelData');
|
||||
const { selectDomainId } = domainModel;
|
||||
const { selectModelId: modelId } = modelModel;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const [tagItem, setTagItem] = useState<ISemantic.ITagItem>();
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||
@@ -273,6 +267,4 @@ const TagObjectTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(TagObjectTable);
|
||||
export default TagObjectTable;
|
||||
|
||||
@@ -1,28 +1,19 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Button, Modal, Space } from 'antd';
|
||||
import { KnowledgeConfigTypeEnum } from '../../enum';
|
||||
import { ISemantic } from '../../data';
|
||||
import DimensionValueSettingForm from '../../components/Entity/DimensionValueSettingForm';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
|
||||
export type CreateFormProps = {
|
||||
onCancel: () => void;
|
||||
tagItem: ISemantic.ITagItem;
|
||||
open: boolean;
|
||||
onSubmit: (values?: any) => void;
|
||||
domainManger: StateType;
|
||||
};
|
||||
|
||||
type TableDataSource = { techName: string; bizName: string; alias?: string[] };
|
||||
|
||||
const TagValueSettingModal: React.FC<CreateFormProps> = ({
|
||||
onCancel,
|
||||
open,
|
||||
tagItem,
|
||||
domainManger,
|
||||
onSubmit,
|
||||
}) => {
|
||||
const TagValueSettingModal: React.FC<CreateFormProps> = ({ onCancel, open, tagItem, onSubmit }) => {
|
||||
const [tableDataSource, setTableDataSource] = useState<TableDataSource[]>([]);
|
||||
|
||||
// const handleSubmit = async () => {
|
||||
@@ -81,6 +72,4 @@ const TagValueSettingModal: React.FC<CreateFormProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(TagValueSettingModal);
|
||||
export default TagValueSettingModal;
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import React from 'react';
|
||||
import { Outlet } from '@umijs/max';
|
||||
|
||||
const market: React.FC = ({ children }) => {
|
||||
return <>{children}</>;
|
||||
const market: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<Outlet />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default market;
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
padding: 0px;
|
||||
background-color: transparent;
|
||||
.tabContainer {
|
||||
height: 100%;
|
||||
width: calc(100vw - 450px);
|
||||
background-color: rgb(240, 242, 245);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { message, Tabs, Button, Space } from 'antd';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { getMetricData, getDimensionList, getDrillDownDimension } from '../service';
|
||||
import { connect, useParams, history } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import { useParams, history } from '@umijs/max';
|
||||
import styles from './style.less';
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import MetricTrendSection from '@/pages/SemanticModel/Metric/components/MetricTrendSection';
|
||||
@@ -159,6 +158,4 @@ const MetricDetail: React.FC<Props> = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(MetricDetail);
|
||||
export default MetricDetail;
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import { message, Tabs, Button, Space } from 'antd';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { getMetricData, getDimensionList, getDrillDownDimension } from '../service';
|
||||
import { connect, useParams, history } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import styles from './style.less';
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import MetricTrendSection from '@/pages/SemanticModel/Metric/components/MetricTrendSection';
|
||||
import { ISemantic } from '../data';
|
||||
import MetricBasicInfo from './components/MetricBasicInfo';
|
||||
import DimensionAndMetricRelationModal from '../components/DimensionAndMetricRelationModal';
|
||||
import MetricInfoEditSider from './MetricInfoEditSider';
|
||||
import MetricInfoCreateForm from './components/MetricInfoCreateForm';
|
||||
import { MetricSettingKey, MetricSettingWording } from './constants';
|
||||
|
||||
type Props = Record<string, any>;
|
||||
|
||||
const MetricDetail: React.FC<Props> = () => {
|
||||
const params: any = useParams();
|
||||
const metricId = params.metricId;
|
||||
const [metricRelationModalOpenState, setMetricRelationModalOpenState] = useState<boolean>(false);
|
||||
const [metircData, setMetircData] = useState<ISemantic.IMetricItem>();
|
||||
const [dimensionList, setDimensionList] = useState<ISemantic.IDimensionItem[]>([]);
|
||||
const [drillDownDimension, setDrillDownDimension] = useState<ISemantic.IDrillDownDimensionItem[]>(
|
||||
[],
|
||||
);
|
||||
const [relationDimensionOptions, setRelationDimensionOptions] = useState<
|
||||
{ value: string; label: string; modelId: number }[]
|
||||
>([]);
|
||||
|
||||
const [settingKey, setSettingKey] = useState<MetricSettingKey>(MetricSettingKey.BASIC);
|
||||
|
||||
useEffect(() => {
|
||||
if (!metricId) {
|
||||
return;
|
||||
}
|
||||
queryMetricData(metricId);
|
||||
queryDrillDownDimension(metricId);
|
||||
}, [metricId]);
|
||||
|
||||
const queryMetricData = async (metricId: string) => {
|
||||
const { code, data, msg } = await getMetricData(metricId);
|
||||
if (code === 200) {
|
||||
setMetircData({ ...data });
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
const queryDrillDownDimension = async (metricId: number) => {
|
||||
const { code, data, msg } = await getDrillDownDimension(metricId);
|
||||
if (code === 200 && Array.isArray(data)) {
|
||||
setDrillDownDimension(data);
|
||||
const ids = data.map((item) => item.dimensionId);
|
||||
queryDimensionList(ids);
|
||||
return data;
|
||||
} else {
|
||||
setDimensionList([]);
|
||||
setRelationDimensionOptions([]);
|
||||
}
|
||||
if (code !== 200) {
|
||||
message.error(msg);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const queryDimensionList = async (ids: number[]) => {
|
||||
if (!(Array.isArray(ids) && ids.length > 0)) {
|
||||
setRelationDimensionOptions([]);
|
||||
return;
|
||||
}
|
||||
const { code, data, msg } = await getDimensionList({ ids });
|
||||
if (code === 200 && Array.isArray(data?.list)) {
|
||||
setDimensionList(data.list);
|
||||
setRelationDimensionOptions(
|
||||
data.list.map((item: ISemantic.IMetricItem) => {
|
||||
return { label: item.name, value: item.bizName, modelId: item.modelId };
|
||||
}),
|
||||
);
|
||||
return data.list;
|
||||
}
|
||||
message.error(msg);
|
||||
return [];
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.metricEditWrapper}>
|
||||
<div className={styles.metricDetail}>
|
||||
<div className={styles.siderContainer}>
|
||||
<MetricInfoEditSider
|
||||
onSettingKeyChange={(key: string) => {
|
||||
setSettingKey(key);
|
||||
}}
|
||||
metircData={metircData}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.tabContainer}>
|
||||
{/* {metircData && ( */}
|
||||
<MetricInfoCreateForm
|
||||
settingKey={settingKey}
|
||||
// domainId={metircData?.domainId}
|
||||
// modelId={metircData?.modelId}
|
||||
metricItem={metircData}
|
||||
/>
|
||||
{/* )} */}
|
||||
</div>
|
||||
</div>
|
||||
<DimensionAndMetricRelationModal
|
||||
metricItem={metircData}
|
||||
relationsInitialValue={drillDownDimension}
|
||||
open={metricRelationModalOpenState}
|
||||
onCancel={() => {
|
||||
setMetricRelationModalOpenState(false);
|
||||
}}
|
||||
onSubmit={(relations) => {
|
||||
queryMetricData(metricId);
|
||||
queryDrillDownDimension(metricId);
|
||||
setMetricRelationModalOpenState(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetricDetail;
|
||||
@@ -1,11 +1,9 @@
|
||||
import type { ActionType, ProColumns } from '@ant-design/pro-components';
|
||||
import { ProTable } from '@ant-design/pro-components';
|
||||
import { message, Space, Popconfirm, Tag, Spin, Tooltip } from 'antd';
|
||||
import { message, Space, Popconfirm, Spin } from 'antd';
|
||||
import MetricAddClass from './components/MetricAddClass';
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { connect, history, useModel } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import { history, useModel } from '@umijs/max';
|
||||
import { SENSITIVE_LEVEL_ENUM } from '../constant';
|
||||
import {
|
||||
queryMetric,
|
||||
@@ -18,8 +16,7 @@ import {
|
||||
import MetricFilter from './components/MetricFilter';
|
||||
import MetricInfoCreateForm from '../components/MetricInfoCreateForm';
|
||||
import MetricCardList from './components/MetricCardList';
|
||||
import NodeInfoDrawer from '../SemanticGraph/components/NodeInfoDrawer';
|
||||
import { SemanticNodeType, StatusEnum } from '../enum';
|
||||
import { StatusEnum } from '../enum';
|
||||
import moment from 'moment';
|
||||
import styles from './style.less';
|
||||
import { ISemantic } from '../data';
|
||||
@@ -27,8 +24,7 @@ import BatchCtrlDropDownButton from '@/components/BatchCtrlDropDownButton';
|
||||
import { ColumnsConfig } from '../components/TableColumnRender';
|
||||
|
||||
type Props = {
|
||||
dispatch: Dispatch;
|
||||
domainManger: StateType;
|
||||
|
||||
};
|
||||
|
||||
type QueryMetricListParams = {
|
||||
@@ -40,11 +36,9 @@ type QueryMetricListParams = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const ClassMetricTable: React.FC<Props> = ({ }) => {
|
||||
const { initialState = {} } = useModel('@@initialState');
|
||||
|
||||
const { currentUser = {} } = initialState as any;
|
||||
const { selectDomainId, selectModelId: modelId } = domainManger;
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const defaultPagination = {
|
||||
current: 1,
|
||||
@@ -59,7 +53,6 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const [filterParams, setFilterParams] = useState<Record<string, any>>({
|
||||
showType: localStorage.getItem('metricMarketShowType') === '1' ? true : false,
|
||||
});
|
||||
const [infoDrawerVisible, setInfoDrawerVisible] = useState<boolean>(false);
|
||||
|
||||
const [downloadLoading, setDownloadLoading] = useState<boolean>(false);
|
||||
|
||||
@@ -193,55 +186,16 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
{
|
||||
dataIndex: 'name',
|
||||
title: '指标',
|
||||
// width: '20%',
|
||||
width: 280,
|
||||
fixed: 'left',
|
||||
render: columnsConfig.indicatorInfo.render,
|
||||
},
|
||||
// {
|
||||
// dataIndex: 'modelName',
|
||||
// title: '所属模型',
|
||||
// render: (_, record: any) => {
|
||||
// if (record.hasAdminRes) {
|
||||
// return (
|
||||
// <a
|
||||
// target="blank"
|
||||
// href={`/webapp/model/${record.domainId}/${record.modelId}/metric`}
|
||||
// // onClick={() => {
|
||||
// // history.push(`/model/${record.domainId}/${record.modelId}/metric`);
|
||||
// // }}
|
||||
// >
|
||||
// {record.modelName}
|
||||
// </a>
|
||||
// );
|
||||
// }
|
||||
// return <> {record.modelName}</>;
|
||||
// },
|
||||
// },
|
||||
{
|
||||
dataIndex: 'sensitiveLevel',
|
||||
title: '敏感度',
|
||||
// width: 150,
|
||||
valueEnum: SENSITIVE_LEVEL_ENUM,
|
||||
render: columnsConfig.sensitiveLevel.render,
|
||||
},
|
||||
// {
|
||||
// dataIndex: 'isPublish',
|
||||
// title: '是否发布',
|
||||
// width: 100,
|
||||
// search: false,
|
||||
// render: (isPublish) => {
|
||||
// switch (isPublish) {
|
||||
// case 0:
|
||||
// return '否';
|
||||
// case 1:
|
||||
// return <span style={{ color: '#1677ff' }}>是</span>;
|
||||
// default:
|
||||
// return <Tag color="default">未知</Tag>;
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
|
||||
{
|
||||
dataIndex: 'description',
|
||||
title: '描述',
|
||||
@@ -259,7 +213,6 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
{
|
||||
dataIndex: 'createdBy',
|
||||
title: '创建人',
|
||||
// width: 150,
|
||||
search: false,
|
||||
},
|
||||
{
|
||||
@@ -477,45 +430,18 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
|
||||
{createModalVisible && (
|
||||
<MetricInfoCreateForm
|
||||
domainId={Number(selectDomainId)}
|
||||
createModalVisible={createModalVisible}
|
||||
modelId={modelId}
|
||||
metricItem={metricItem}
|
||||
onSubmit={() => {
|
||||
setCreateModalVisible(false);
|
||||
queryMetricList(filterParams);
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
onCancel={() => {
|
||||
setCreateModalVisible(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{infoDrawerVisible && (
|
||||
<NodeInfoDrawer
|
||||
nodeData={{ ...metricItem, nodeType: SemanticNodeType.METRIC }}
|
||||
placement="right"
|
||||
onClose={() => {
|
||||
setInfoDrawerVisible(false);
|
||||
}}
|
||||
width="100%"
|
||||
open={infoDrawerVisible}
|
||||
mask={true}
|
||||
getContainer={false}
|
||||
onEditBtnClick={(nodeData: any) => {
|
||||
handleMetricEdit(nodeData);
|
||||
}}
|
||||
maskClosable={true}
|
||||
onNodeChange={({ eventName }: { eventName: string }) => {
|
||||
setInfoDrawerVisible(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{addClassVisible && (
|
||||
<MetricAddClass
|
||||
ids={selectedRowKeys as number[]}
|
||||
@@ -526,18 +452,10 @@ const ClassMetricTable: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
onSuccess={() => {
|
||||
setAddClassVisible(false);
|
||||
queryMetricList(filterParams);
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
domainId: selectDomainId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(ClassMetricTable);
|
||||
export default ClassMetricTable
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
import { Tag, Space, Tooltip } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import { MetricSettingKey, MetricSettingWording } from './constants';
|
||||
import {
|
||||
ExportOutlined,
|
||||
SolutionOutlined,
|
||||
PartitionOutlined,
|
||||
ProjectOutlined,
|
||||
ConsoleSqlOutlined,
|
||||
SettingOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import styles from './style.less';
|
||||
import { ISemantic } from '../data';
|
||||
import IndicatorStar from '../components/IndicatorStar';
|
||||
|
||||
type Props = {
|
||||
metircData: ISemantic.IMetricItem;
|
||||
onSettingKeyChange?: (key: MetricSettingKey) => void;
|
||||
};
|
||||
|
||||
const MetricInfoEditSider: React.FC<Props> = ({ metircData, onSettingKeyChange }) => {
|
||||
const [settingKey, setSettingKey] = useState<MetricSettingKey>(MetricSettingKey.BASIC);
|
||||
|
||||
const settingList = [
|
||||
{
|
||||
icon: <ProjectOutlined />,
|
||||
key: MetricSettingKey.BASIC,
|
||||
text: MetricSettingWording[MetricSettingKey.BASIC],
|
||||
},
|
||||
{
|
||||
icon: <ConsoleSqlOutlined />,
|
||||
key: MetricSettingKey.SQL_CONFIG,
|
||||
text: MetricSettingWording[MetricSettingKey.SQL_CONFIG],
|
||||
},
|
||||
// {
|
||||
// icon: <DashboardOutlined />,
|
||||
// key: MetricSettingKey.DIMENSION_CONFIG,
|
||||
// text: MetricSettingWording[MetricSettingKey.DIMENSION_CONFIG],
|
||||
// },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={styles.metricInfoSider}>
|
||||
<div className={styles.sectionContainer}>
|
||||
{metircData?.id ? (
|
||||
<div className={styles.title}>
|
||||
<div className={styles.name}>
|
||||
<Space>
|
||||
<IndicatorStar indicatorId={metircData?.id} initState={metircData?.isCollect} />
|
||||
{metircData?.name}
|
||||
{metircData?.hasAdminRes && (
|
||||
<span
|
||||
className={styles.gotoMetricListIcon}
|
||||
onClick={() => {
|
||||
window.open(`/webapp/model/${metircData.domainId}/${metircData.modelId}/`);
|
||||
}}
|
||||
>
|
||||
<Tooltip title="前往所属模型指标列表">
|
||||
<ExportOutlined />
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
{metircData?.bizName && <div className={styles.bizName}>{metircData.bizName}</div>}
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.createTitle}>
|
||||
<Space>
|
||||
<SettingOutlined />
|
||||
新建指标
|
||||
</Space>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<hr className={styles.hr} />
|
||||
<div className={styles.section} style={{ padding: '16px 0' }}>
|
||||
<ul className={styles.settingList}>
|
||||
{settingList.map((item) => {
|
||||
return (
|
||||
<li
|
||||
className={item.key === settingKey ? styles.active : ''}
|
||||
key={item.key}
|
||||
onClick={() => {
|
||||
onSettingKeyChange?.(item.key);
|
||||
setSettingKey(item.key);
|
||||
}}
|
||||
>
|
||||
<div className={styles.icon}>{item.icon}</div>
|
||||
<div className={styles.content}>
|
||||
<span className={styles.text}> {item.text}</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
{/* <hr className={styles.hr} /> */}
|
||||
{metircData?.id && (
|
||||
<div className={styles.section} style={{ marginTop: 'auto' }}>
|
||||
<div className={styles.sectionTitleBox}>
|
||||
<span className={styles.sectionTitle}>
|
||||
<Space>
|
||||
<SolutionOutlined />
|
||||
创建信息
|
||||
</Space>
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<span className={styles.itemLable}>所属模型: </span>
|
||||
<span className={styles.itemValue}>
|
||||
<Space>
|
||||
<Tag icon={<PartitionOutlined />} color="#3b5999">
|
||||
{metircData?.modelName || '模型名为空'}
|
||||
</Tag>
|
||||
{metircData?.hasAdminRes && (
|
||||
<span
|
||||
className={styles.gotoMetricListIcon}
|
||||
onClick={() => {
|
||||
window.open(`/webapp/model/${metircData.domainId}/0/overview`);
|
||||
}}
|
||||
>
|
||||
<Tooltip title="前往模型设置页">
|
||||
<ExportOutlined />
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
</Space>
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<span className={styles.itemLable}>创建人: </span>
|
||||
<span className={styles.itemValue}>{metircData?.createdBy}</span>
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<span className={styles.itemLable}>创建时间: </span>
|
||||
<span className={styles.itemValue}>
|
||||
{metircData?.createdAt
|
||||
? dayjs(metircData?.createdAt).format('YYYY-MM-DD HH:mm:ss')
|
||||
: ''}
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<span className={styles.itemLable}>更新时间: </span>
|
||||
<span className={styles.itemValue}>
|
||||
{metircData?.createdAt
|
||||
? dayjs(metircData?.updatedAt).format('YYYY-MM-DD HH:mm:ss')
|
||||
: ''}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* <hr className={styles.hr} /> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetricInfoEditSider;
|
||||
@@ -1,7 +1,5 @@
|
||||
import { Tag, Space, Tooltip, Typography } from 'antd';
|
||||
import React from 'react';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import { isArrayOfValues } from '@/utils/utils';
|
||||
import dayjs from 'dayjs';
|
||||
import {
|
||||
@@ -22,7 +20,6 @@ const { Text } = Typography;
|
||||
|
||||
type Props = {
|
||||
metircData: ISemantic.IMetricItem;
|
||||
domainManger: StateType;
|
||||
relationDimensionOptions: { value: string; label: string; modelId: number }[];
|
||||
onNodeChange: (params?: { eventName?: string }) => void;
|
||||
onEditBtnClick?: (metircData: any) => void;
|
||||
@@ -256,6 +253,4 @@ const MetricInfoSider: React.FC<Props> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(MetricInfoSider);
|
||||
export default MetricInfoSider;
|
||||
|
||||
@@ -3,10 +3,7 @@ import React, { useState } from 'react';
|
||||
import { Dropdown, Popconfirm, Typography } from 'antd';
|
||||
import { EllipsisOutlined } from '@ant-design/icons';
|
||||
import { ISemantic } from '../../data';
|
||||
import { connect } from 'umi';
|
||||
import icon from '../../../../assets/icon/sourceState.svg';
|
||||
import type { Dispatch } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import { SemanticNodeType } from '../../enum';
|
||||
import styles from '../style.less';
|
||||
|
||||
@@ -17,8 +14,6 @@ type Props = {
|
||||
onMetricChange?: (metricItem: ISemantic.IMetricItem) => void;
|
||||
onEditBtnClick?: (metricItem: ISemantic.IMetricItem) => void;
|
||||
onDeleteBtnClick?: (metricItem: ISemantic.IMetricItem) => void;
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
|
||||
const MetricCardList: React.FC<Props> = ({
|
||||
@@ -27,7 +22,6 @@ const MetricCardList: React.FC<Props> = ({
|
||||
onMetricChange,
|
||||
onEditBtnClick,
|
||||
onDeleteBtnClick,
|
||||
domainManger,
|
||||
}) => {
|
||||
const [currentNodeData, setCurrentNodeData] = useState<any>({});
|
||||
|
||||
@@ -129,6 +123,4 @@ const MetricCardList: React.FC<Props> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(MetricCardList);
|
||||
export default MetricCardList;
|
||||
|
||||
@@ -0,0 +1,944 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
Form,
|
||||
Button,
|
||||
Input,
|
||||
Select,
|
||||
Radio,
|
||||
Switch,
|
||||
InputNumber,
|
||||
message,
|
||||
Result,
|
||||
Row,
|
||||
Col,
|
||||
Space,
|
||||
Divider,
|
||||
Tooltip,
|
||||
Tag,
|
||||
} from 'antd';
|
||||
|
||||
import MetricMeasuresFormTable from '../../components/MetricMeasuresFormTable';
|
||||
import { SENSITIVE_LEVEL_OPTIONS, METRIC_DEFINE_TYPE, TAG_DEFINE_TYPE } from '../../constant';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import FormItemTitle from '@/components/FormHelper/FormItemTitle';
|
||||
import styles from '../../components/style.less';
|
||||
import {
|
||||
getMetricsToCreateNewMetric,
|
||||
getModelDetail,
|
||||
getDrillDownDimension,
|
||||
batchCreateTag,
|
||||
batchDeleteTag,
|
||||
} from '../../service';
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import MetricMetricFormTable from '../../components/MetricMetricFormTable';
|
||||
import MetricFieldFormTable from '../../components/MetricFieldFormTable';
|
||||
import DimensionAndMetricRelationModal from '../../components/DimensionAndMetricRelationModal';
|
||||
import TableTitleTooltips from '../../components/TableTitleTooltips';
|
||||
import { createMetric, updateMetric, mockMetricAlias, getMetricTags } from '../../service';
|
||||
import { MetricSettingKey, MetricSettingWording } from '../constants';
|
||||
import { ISemantic } from '../../data';
|
||||
import { history } from '@umijs/max';
|
||||
|
||||
export type CreateFormProps = {
|
||||
datasourceId?: number;
|
||||
metricItem: any;
|
||||
settingKey: MetricSettingKey;
|
||||
onCancel?: () => void;
|
||||
onSubmit?: (values: any) => void;
|
||||
};
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { TextArea } = Input;
|
||||
const { Option } = Select;
|
||||
|
||||
const queryParamsTypeParamsKey = {
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: 'metricDefineByMeasureParams',
|
||||
[METRIC_DEFINE_TYPE.METRIC]: 'metricDefineByMetricParams',
|
||||
[METRIC_DEFINE_TYPE.FIELD]: 'metricDefineByFieldParams',
|
||||
};
|
||||
|
||||
const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
|
||||
datasourceId,
|
||||
onCancel,
|
||||
settingKey,
|
||||
metricItem,
|
||||
onSubmit,
|
||||
}) => {
|
||||
const isEdit = !!metricItem?.id;
|
||||
const domainId = metricItem?.domainId;
|
||||
const modelId = metricItem?.modelId;
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const formValRef = useRef({} as any);
|
||||
const [form] = Form.useForm();
|
||||
const updateFormVal = (val: any) => {
|
||||
const formVal = {
|
||||
...formValRef.current,
|
||||
...val,
|
||||
};
|
||||
formValRef.current = formVal;
|
||||
};
|
||||
|
||||
const [classMeasureList, setClassMeasureList] = useState<ISemantic.IMeasure[]>([]);
|
||||
|
||||
const [exprTypeParamsState, setExprTypeParamsState] = useState<{
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: ISemantic.IMeasureTypeParams;
|
||||
[METRIC_DEFINE_TYPE.METRIC]: ISemantic.IMetricTypeParams;
|
||||
[METRIC_DEFINE_TYPE.FIELD]: ISemantic.IFieldTypeParams;
|
||||
}>({
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: {
|
||||
measures: [],
|
||||
expr: '',
|
||||
},
|
||||
[METRIC_DEFINE_TYPE.METRIC]: {
|
||||
metrics: [],
|
||||
expr: '',
|
||||
},
|
||||
[METRIC_DEFINE_TYPE.FIELD]: {
|
||||
fields: [],
|
||||
expr: '',
|
||||
},
|
||||
} as any);
|
||||
|
||||
// const [exprTypeParamsState, setExprTypeParamsState] = useState<ISemantic.IMeasure[]>([]);
|
||||
|
||||
const [defineType, setDefineType] = useState(METRIC_DEFINE_TYPE.MEASURE);
|
||||
|
||||
const [createNewMetricList, setCreateNewMetricList] = useState<ISemantic.IMetricItem[]>([]);
|
||||
const [fieldList, setFieldList] = useState<ISemantic.IFieldTypeParamsItem[]>([]);
|
||||
const [isPercentState, setIsPercentState] = useState<boolean>(false);
|
||||
const [isDecimalState, setIsDecimalState] = useState<boolean>(false);
|
||||
const [hasMeasuresState, setHasMeasuresState] = useState<boolean>(true);
|
||||
const [llmLoading, setLlmLoading] = useState<boolean>(false);
|
||||
|
||||
const [tagOptions, setTagOptions] = useState<{ label: string; value: string }[]>([]);
|
||||
|
||||
const [metricRelationModalOpenState, setMetricRelationModalOpenState] = useState<boolean>(false);
|
||||
|
||||
const [drillDownDimensions, setDrillDownDimensions] = useState<
|
||||
ISemantic.IDrillDownDimensionItem[]
|
||||
>([]);
|
||||
|
||||
const [drillDownDimensionsConfig, setDrillDownDimensionsConfig] = useState<
|
||||
ISemantic.IDrillDownDimensionItem[]
|
||||
>([]);
|
||||
|
||||
const forward = () => setCurrentStep(currentStep + 1);
|
||||
const backward = () => setCurrentStep(currentStep - 1);
|
||||
|
||||
const queryModelDetail = async () => {
|
||||
const { code, data } = await getModelDetail({ modelId: modelId || metricItem?.modelId });
|
||||
if (code === 200) {
|
||||
if (Array.isArray(data?.modelDetail?.fields)) {
|
||||
if (Array.isArray(metricItem?.metricDefineByFieldParams?.fields)) {
|
||||
const fieldList = data.modelDetail.fields.map((item: ISemantic.IFieldTypeParamsItem) => {
|
||||
const { fieldName } = item;
|
||||
if (
|
||||
metricItem?.metricDefineByFieldParams?.fields.find(
|
||||
(measureParamsItem: ISemantic.IFieldTypeParamsItem) =>
|
||||
measureParamsItem.fieldName === fieldName,
|
||||
)
|
||||
) {
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 9999,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 0,
|
||||
};
|
||||
});
|
||||
|
||||
const sortList = fieldList.sort(
|
||||
(
|
||||
a: ISemantic.IFieldTypeParamsItem & { orderNumber: number },
|
||||
b: ISemantic.IFieldTypeParamsItem & { orderNumber: number },
|
||||
) => b.orderNumber - a.orderNumber,
|
||||
);
|
||||
setFieldList(sortList);
|
||||
} else {
|
||||
setFieldList(data.modelDetail.fields);
|
||||
}
|
||||
}
|
||||
if (Array.isArray(data?.modelDetail?.measures)) {
|
||||
if (Array.isArray(metricItem?.metricDefineByMeasureParams?.measures)) {
|
||||
const measureList = data.modelDetail.measures.map((item: ISemantic.IMeasure) => {
|
||||
const { bizName } = item;
|
||||
if (
|
||||
metricItem?.metricDefineByMeasureParams?.measures.find(
|
||||
(measureParamsItem: ISemantic.IMeasure) => measureParamsItem.bizName === bizName,
|
||||
)
|
||||
) {
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 9999,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 0,
|
||||
};
|
||||
});
|
||||
const sortMeasureList = measureList.sort(
|
||||
(
|
||||
a: ISemantic.IMeasure & { orderNumber: number },
|
||||
b: ISemantic.IMeasure & { orderNumber: number },
|
||||
) => b.orderNumber - a.orderNumber,
|
||||
);
|
||||
setClassMeasureList(sortMeasureList);
|
||||
} else {
|
||||
setClassMeasureList(data.modelDetail.measures);
|
||||
}
|
||||
|
||||
if (datasourceId) {
|
||||
const hasMeasures = data.some(
|
||||
(item: ISemantic.IMeasure) => item.datasourceId === datasourceId,
|
||||
);
|
||||
setHasMeasuresState(hasMeasures);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
setClassMeasureList([]);
|
||||
};
|
||||
|
||||
const queryDrillDownDimension = async (metricId: number) => {
|
||||
const { code, data, msg } = await getDrillDownDimension(metricId);
|
||||
if (code === 200 && Array.isArray(data)) {
|
||||
setDrillDownDimensionsConfig(data);
|
||||
}
|
||||
if (code !== 200) {
|
||||
message.error(msg);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
queryModelDetail();
|
||||
queryMetricsToCreateNewMetric();
|
||||
queryMetricTags();
|
||||
}, []);
|
||||
|
||||
const handleSave = async () => {
|
||||
const fieldsValue = await form.validateFields();
|
||||
const submitForm = {
|
||||
...formValRef.current,
|
||||
...fieldsValue,
|
||||
metricDefineType: defineType,
|
||||
[queryParamsTypeParamsKey[defineType]]: exprTypeParamsState[defineType],
|
||||
};
|
||||
updateFormVal(submitForm);
|
||||
|
||||
await saveMetric(submitForm);
|
||||
};
|
||||
|
||||
const initData = () => {
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
bizName,
|
||||
description,
|
||||
sensitiveLevel,
|
||||
typeParams,
|
||||
isTag,
|
||||
dataFormat,
|
||||
dataFormatType,
|
||||
alias,
|
||||
classifications,
|
||||
metricDefineType,
|
||||
metricDefineByMeasureParams,
|
||||
metricDefineByMetricParams,
|
||||
metricDefineByFieldParams,
|
||||
} = metricItem;
|
||||
const isPercent = dataFormatType === 'percent';
|
||||
const isDecimal = dataFormatType === 'decimal';
|
||||
const initValue = {
|
||||
id,
|
||||
name,
|
||||
bizName,
|
||||
sensitiveLevel,
|
||||
description,
|
||||
classifications,
|
||||
isTag,
|
||||
// isPercent,
|
||||
dataFormatType: dataFormatType || '',
|
||||
alias: alias && alias.trim() ? alias.split(',') : [],
|
||||
dataFormat: dataFormat || {
|
||||
decimalPlaces: 2,
|
||||
needMultiply100: false,
|
||||
},
|
||||
};
|
||||
const editInitFormVal = {
|
||||
...formValRef.current,
|
||||
...initValue,
|
||||
};
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.MEASURE) {
|
||||
const { measures, expr } = metricDefineByMeasureParams || {};
|
||||
setExprTypeParamsState({
|
||||
...exprTypeParamsState,
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: {
|
||||
measures: measures || [],
|
||||
expr: expr || '',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.METRIC) {
|
||||
const { metrics, expr } = metricDefineByMetricParams || {};
|
||||
setExprTypeParamsState({
|
||||
...exprTypeParamsState,
|
||||
[METRIC_DEFINE_TYPE.METRIC]: {
|
||||
metrics: metrics || [],
|
||||
expr: expr || '',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.FIELD) {
|
||||
const { fields, expr } = metricDefineByFieldParams || {};
|
||||
setExprTypeParamsState({
|
||||
...exprTypeParamsState,
|
||||
[METRIC_DEFINE_TYPE.FIELD]: {
|
||||
fields: fields || [],
|
||||
expr: expr || '',
|
||||
},
|
||||
});
|
||||
}
|
||||
updateFormVal(editInitFormVal);
|
||||
form.setFieldsValue(initValue);
|
||||
setDefineType(metricDefineType);
|
||||
setIsPercentState(isPercent);
|
||||
setIsDecimalState(isDecimal);
|
||||
queryDrillDownDimension(metricItem?.id);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isEdit) {
|
||||
initData();
|
||||
}
|
||||
}, [metricItem]);
|
||||
|
||||
const isEmptyConditions = (
|
||||
metricDefineType: METRIC_DEFINE_TYPE,
|
||||
metricDefineParams:
|
||||
| ISemantic.IMeasureTypeParams
|
||||
| ISemantic.IMetricTypeParams
|
||||
| ISemantic.IFieldTypeParams,
|
||||
) => {
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.MEASURE) {
|
||||
const { measures } = (metricDefineParams as ISemantic.IMeasureTypeParams) || {};
|
||||
if (!(Array.isArray(measures) && measures.length > 0)) {
|
||||
message.error('请添加一个度量');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.METRIC) {
|
||||
const { metrics } = (metricDefineParams as ISemantic.IMetricTypeParams) || {};
|
||||
if (!(Array.isArray(metrics) && metrics.length > 0)) {
|
||||
message.error('请添加一个指标');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.FIELD) {
|
||||
const { fields } = (metricDefineParams as ISemantic.IFieldTypeParams) || {};
|
||||
if (!(Array.isArray(fields) && fields.length > 0)) {
|
||||
message.error('请添加一个字段');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const saveMetric = async (fieldsValue: any) => {
|
||||
const queryParams = {
|
||||
modelId: isEdit ? metricItem.modelId : modelId,
|
||||
relateDimension: {
|
||||
...(metricItem?.relateDimension || {}),
|
||||
drillDownDimensions,
|
||||
},
|
||||
...fieldsValue,
|
||||
};
|
||||
const { alias, dataFormatType } = queryParams;
|
||||
queryParams.alias = Array.isArray(alias) ? alias.join(',') : '';
|
||||
if (!queryParams[queryParamsTypeParamsKey[defineType]]?.expr) {
|
||||
message.error('请输入度量表达式');
|
||||
return;
|
||||
}
|
||||
if (!dataFormatType) {
|
||||
delete queryParams.dataFormat;
|
||||
}
|
||||
if (isEmptyConditions(defineType, queryParams[queryParamsTypeParamsKey[defineType]])) {
|
||||
return;
|
||||
}
|
||||
|
||||
let saveMetricQuery = createMetric;
|
||||
if (queryParams.id) {
|
||||
saveMetricQuery = updateMetric;
|
||||
}
|
||||
const { code, msg, data } = await saveMetricQuery(queryParams);
|
||||
if (code === 200) {
|
||||
if (queryParams.isTag) {
|
||||
queryBatchExportTag(data.id || metricItem?.id);
|
||||
}
|
||||
|
||||
if (metricItem?.id && !queryParams.isTag) {
|
||||
queryBatchDelete(metricItem);
|
||||
}
|
||||
message.success('编辑指标成功');
|
||||
onSubmit?.(queryParams);
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
const queryBatchDelete = async (metricItem: ISemantic.IMetricItem) => {
|
||||
const { code, msg } = await batchDeleteTag([
|
||||
{
|
||||
itemIds: [metricItem.id],
|
||||
tagDefineType: TAG_DEFINE_TYPE.METRIC,
|
||||
},
|
||||
]);
|
||||
if (code === 200) {
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
const queryBatchExportTag = async (id: number) => {
|
||||
const { code, msg } = await batchCreateTag([
|
||||
{ itemId: id, tagDefineType: TAG_DEFINE_TYPE.METRIC },
|
||||
]);
|
||||
|
||||
if (code === 200) {
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
const generatorMetricAlias = async () => {
|
||||
setLlmLoading(true);
|
||||
const { code, data } = await mockMetricAlias({ ...metricItem });
|
||||
const formAlias = form.getFieldValue('alias');
|
||||
setLlmLoading(false);
|
||||
if (code === 200) {
|
||||
form.setFieldValue('alias', Array.from(new Set([...formAlias, ...data])));
|
||||
} else {
|
||||
message.error('大语言模型解析异常');
|
||||
}
|
||||
};
|
||||
|
||||
const queryMetricTags = async () => {
|
||||
const { code, data } = await getMetricTags();
|
||||
if (code === 200) {
|
||||
setTagOptions(
|
||||
Array.isArray(data)
|
||||
? data.map((tag: string) => {
|
||||
return { label: tag, value: tag };
|
||||
})
|
||||
: [],
|
||||
);
|
||||
} else {
|
||||
message.error('获取指标标签失败');
|
||||
}
|
||||
};
|
||||
const queryMetricsToCreateNewMetric = async () => {
|
||||
if (!metricItem?.id) {
|
||||
return;
|
||||
}
|
||||
const { code, data } = await getMetricsToCreateNewMetric({
|
||||
modelId: modelId || metricItem?.modelId,
|
||||
});
|
||||
if (code === 200) {
|
||||
if (Array.isArray(metricItem?.metricDefineByMetricParams?.metrics)) {
|
||||
const fieldList = data.map((item: ISemantic.IMetricTypeParamsItem) => {
|
||||
const { bizName } = item;
|
||||
if (
|
||||
metricItem?.metricDefineByMetricParams?.metrics.find(
|
||||
(measureParamsItem: ISemantic.IMetricTypeParamsItem) =>
|
||||
measureParamsItem.bizName === bizName,
|
||||
)
|
||||
) {
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 9999,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 0,
|
||||
};
|
||||
});
|
||||
|
||||
const sortList = fieldList.sort(
|
||||
(
|
||||
a: ISemantic.IMetricTypeParamsItem & { orderNumber: number },
|
||||
b: ISemantic.IMetricTypeParamsItem & { orderNumber: number },
|
||||
) => b.orderNumber - a.orderNumber,
|
||||
);
|
||||
setCreateNewMetricList(sortList);
|
||||
} else {
|
||||
setCreateNewMetricList(data);
|
||||
}
|
||||
} else {
|
||||
message.error('获取指标标签失败');
|
||||
}
|
||||
};
|
||||
|
||||
const renderContent = () => {
|
||||
if (settingKey === MetricSettingKey.SQL_CONFIG) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
marginLeft: '-24px',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
padding: '0 0 0px 24px',
|
||||
}}
|
||||
>
|
||||
<Space size={20}>
|
||||
<Radio.Group
|
||||
buttonStyle="solid"
|
||||
value={defineType}
|
||||
onChange={(e) => {
|
||||
setDefineType(e.target.value);
|
||||
}}
|
||||
>
|
||||
<Radio.Button value={METRIC_DEFINE_TYPE.MEASURE}>按度量</Radio.Button>
|
||||
<Radio.Button value={METRIC_DEFINE_TYPE.METRIC}>按指标</Radio.Button>
|
||||
<Radio.Button value={METRIC_DEFINE_TYPE.FIELD}>按字段</Radio.Button>
|
||||
</Radio.Group>
|
||||
{defineType === METRIC_DEFINE_TYPE.METRIC && (
|
||||
<p className={styles.desc}>
|
||||
基于
|
||||
<Tag color="#2499ef14" className={styles.markerTag}>
|
||||
已有
|
||||
</Tag>
|
||||
指标来衍生新的指标
|
||||
</p>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
{defineType === METRIC_DEFINE_TYPE.MEASURE && (
|
||||
<>
|
||||
<MetricMeasuresFormTable
|
||||
datasourceId={datasourceId}
|
||||
typeParams={exprTypeParamsState[METRIC_DEFINE_TYPE.MEASURE]}
|
||||
measuresList={classMeasureList}
|
||||
onFieldChange={(measures: ISemantic.IMeasure[]) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.MEASURE],
|
||||
measures,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
onSqlChange={(expr: string) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.MEASURE],
|
||||
expr,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{defineType === METRIC_DEFINE_TYPE.METRIC && (
|
||||
<>
|
||||
<MetricMetricFormTable
|
||||
typeParams={exprTypeParamsState[METRIC_DEFINE_TYPE.METRIC]}
|
||||
metricList={createNewMetricList}
|
||||
onFieldChange={(metrics: ISemantic.IMetricTypeParamsItem[]) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.METRIC]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.METRIC],
|
||||
metrics,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
onSqlChange={(expr: string) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.METRIC]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.METRIC],
|
||||
expr,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{defineType === METRIC_DEFINE_TYPE.FIELD && (
|
||||
<>
|
||||
<MetricFieldFormTable
|
||||
typeParams={exprTypeParamsState[METRIC_DEFINE_TYPE.FIELD]}
|
||||
fieldList={fieldList}
|
||||
onFieldChange={(fields: ISemantic.IFieldTypeParamsItem[]) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.FIELD]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.FIELD],
|
||||
fields,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
onSqlChange={(expr: string) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.FIELD]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.FIELD],
|
||||
expr,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormItem hidden={true} name="id" label="ID">
|
||||
<Input placeholder="id" />
|
||||
</FormItem>
|
||||
<Row gutter={20}>
|
||||
<Col span={12}>
|
||||
<FormItem
|
||||
name="name"
|
||||
label="指标名称"
|
||||
rules={[{ required: true, message: '请输入指标名称' }]}
|
||||
>
|
||||
<Input placeholder="名称不可重复" />
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<FormItem
|
||||
name="bizName"
|
||||
label="英文名称"
|
||||
rules={[{ required: true, message: '请输入英文名称' }]}
|
||||
>
|
||||
<Input placeholder="名称不可重复" disabled={isEdit} />
|
||||
</FormItem>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={20}>
|
||||
<Col span={12}>
|
||||
<FormItem
|
||||
name="sensitiveLevel"
|
||||
label="敏感度"
|
||||
rules={[{ required: true, message: '请选择敏感度' }]}
|
||||
>
|
||||
<Select placeholder="请选择敏感度">
|
||||
{SENSITIVE_LEVEL_OPTIONS.map((item) => (
|
||||
<Option key={item.value} value={item.value}>
|
||||
{item.label}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<FormItem name="classifications" label="分类">
|
||||
<Select
|
||||
mode="tags"
|
||||
placeholder="支持手动输入及选择"
|
||||
tokenSeparators={[',']}
|
||||
maxTagCount={9}
|
||||
options={tagOptions}
|
||||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<FormItem
|
||||
name="description"
|
||||
label={
|
||||
<TableTitleTooltips
|
||||
title="业务口径"
|
||||
overlayInnerStyle={{ width: 600 }}
|
||||
tooltips={
|
||||
<>
|
||||
<p>
|
||||
在录入指标时,请务必详细填写指标口径。口径描述对于理解指标的含义、计算方法和使用场景至关重要。一个清晰、准确的口径描述可以帮助其他用户更好地理解和使用该指标,避免因为误解而导致错误的数据分析和决策。在填写口径时,建议包括以下信息:
|
||||
</p>
|
||||
<p>1. 指标的计算方法:详细说明指标是如何计算的,包括涉及的公式、计算步骤等。</p>
|
||||
<p>2. 数据来源:描述指标所依赖的数据来源,包括数据表、字段等信息。</p>
|
||||
<p>3. 使用场景:说明该指标适用于哪些业务场景,以及如何在这些场景中使用该指标。</p>
|
||||
<p>4. 任何其他相关信息:例如数据更新频率、数据质量要求等。</p>
|
||||
<p>
|
||||
请确保口径描述清晰、简洁且易于理解,以便其他用户能够快速掌握指标的核心要点。
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
}
|
||||
rules={[{ required: true, message: '请输入业务口径' }]}
|
||||
>
|
||||
<TextArea placeholder="请输入业务口径" style={{ minHeight: 173 }} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="别名">
|
||||
<Row gutter={20}>
|
||||
<Col flex="1 1 200px">
|
||||
<FormItem name="alias" noStyle>
|
||||
<Select
|
||||
style={{ maxWidth: 500 }}
|
||||
mode="tags"
|
||||
placeholder="输入别名后回车确认,多别名输入、复制粘贴支持英文逗号自动分隔"
|
||||
tokenSeparators={[',']}
|
||||
maxTagCount={9}
|
||||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
{isEdit && (
|
||||
<Col flex="0 1 75px">
|
||||
<Tooltip title="智能填充将根据指标相关信息,使用大语言模型获取指标别名">
|
||||
<Button
|
||||
type="primary"
|
||||
loading={llmLoading}
|
||||
style={{ top: '5px' }}
|
||||
onClick={() => {
|
||||
generatorMetricAlias();
|
||||
}}
|
||||
>
|
||||
智能填充
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</FormItem>
|
||||
<Divider />
|
||||
<FormItem
|
||||
name="isTag"
|
||||
valuePropName="checked"
|
||||
getValueFromEvent={(value) => {
|
||||
return value === true ? 1 : 0;
|
||||
}}
|
||||
getValueProps={(value) => {
|
||||
return {
|
||||
checked: value === 1,
|
||||
};
|
||||
}}
|
||||
>
|
||||
<Row gutter={20}>
|
||||
<Col flex="1 1 200px">
|
||||
<FormItemTitle
|
||||
title={`设为标签`}
|
||||
subTitle={`如果勾选,代表取值都是一种'标签',可用作对实体的圈选`}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col flex="0 1 75px">
|
||||
<Switch />
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<Divider />
|
||||
<FormItem>
|
||||
<Row gutter={20}>
|
||||
<Col flex="1 1 200px">
|
||||
<FormItemTitle
|
||||
title={'下钻维度配置'}
|
||||
subTitle={'配置下钻维度后,将可以在指标卡中进行下钻'}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col flex="0 1 75px">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setMetricRelationModalOpenState(true);
|
||||
}}
|
||||
>
|
||||
设 置
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<Divider />
|
||||
<FormItem label={<FormItemTitle title={'数据格式化'} />} name="dataFormatType">
|
||||
<Radio.Group buttonStyle="solid" size="middle">
|
||||
<Radio.Button value="">默认</Radio.Button>
|
||||
<Radio.Button value="decimal">小数</Radio.Button>
|
||||
<Radio.Button value="percent">百分比</Radio.Button>
|
||||
</Radio.Group>
|
||||
</FormItem>
|
||||
|
||||
{(isPercentState || isDecimalState) && (
|
||||
<FormItem
|
||||
label={
|
||||
<FormItemTitle
|
||||
title={'小数位数'}
|
||||
subTitle={`对小数位数进行设置,如保留两位,0.021252 -> 0.02${
|
||||
isPercentState ? '%' : ''
|
||||
}`}
|
||||
/>
|
||||
}
|
||||
name={['dataFormat', 'decimalPlaces']}
|
||||
>
|
||||
<InputNumber placeholder="请输入需要保留小数位数" style={{ width: '300px' }} />
|
||||
</FormItem>
|
||||
)}
|
||||
{isPercentState && (
|
||||
<>
|
||||
<FormItem
|
||||
label={
|
||||
<FormItemTitle
|
||||
title={'原始值是否乘以100'}
|
||||
subTitle={'如 原始值0.001 ->展示值0.1% '}
|
||||
/>
|
||||
}
|
||||
name={['dataFormat', 'needMultiply100']}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</FormItem>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
const renderFooter = () => {
|
||||
if (!hasMeasuresState) {
|
||||
return <Button onClick={onCancel}>取消</Button>;
|
||||
}
|
||||
if (currentStep === 1) {
|
||||
return (
|
||||
<>
|
||||
<Button style={{ float: 'left' }} onClick={backward}>
|
||||
上一步
|
||||
</Button>
|
||||
<Button onClick={onCancel}>取消</Button>
|
||||
<Button type="primary" onClick={handleSave}>
|
||||
完成
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Button onClick={onCancel}>取消</Button>
|
||||
<Button type="primary" onClick={handleSave}>
|
||||
下一步
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
{hasMeasuresState ? (
|
||||
<>
|
||||
<div className={styles.infoCard}>
|
||||
<div className={styles.infoCardTitle}>
|
||||
<span style={{ flex: 'auto' }}>{MetricSettingWording[settingKey]}</span>
|
||||
|
||||
<span style={{ flex: 'none' }}>
|
||||
<Button
|
||||
size="middle"
|
||||
type="link"
|
||||
key="backListBtn"
|
||||
onClick={() => {
|
||||
history.back();
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
<ArrowLeftOutlined />
|
||||
返回列表页
|
||||
</Space>
|
||||
</Button>
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.infoCardContainer}>
|
||||
<Form
|
||||
className={styles.supersonicForm}
|
||||
{...formLayout}
|
||||
form={form}
|
||||
initialValues={{
|
||||
...formValRef.current,
|
||||
dataFormatType: '',
|
||||
}}
|
||||
onValuesChange={(value, values: any) => {
|
||||
const { dataFormatType } = values;
|
||||
if (dataFormatType === 'percent') {
|
||||
setIsPercentState(true);
|
||||
setIsDecimalState(false);
|
||||
}
|
||||
if (dataFormatType === 'decimal') {
|
||||
setIsPercentState(false);
|
||||
setIsDecimalState(true);
|
||||
}
|
||||
if (!dataFormatType) {
|
||||
setIsPercentState(false);
|
||||
setIsDecimalState(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{renderContent()}
|
||||
</Form>
|
||||
</div>
|
||||
<div className={styles.infoCardFooter}>
|
||||
<div className={styles.infoCardFooterContainer}>
|
||||
<Button type="primary" onClick={handleSave}>
|
||||
保 存
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DimensionAndMetricRelationModal
|
||||
metricItem={metricItem}
|
||||
relationsInitialValue={drillDownDimensionsConfig}
|
||||
open={metricRelationModalOpenState}
|
||||
onCancel={() => {
|
||||
setMetricRelationModalOpenState(false);
|
||||
}}
|
||||
onSubmit={(relations) => {
|
||||
setDrillDownDimensions(relations);
|
||||
setMetricRelationModalOpenState(false);
|
||||
}}
|
||||
onRefreshRelationData={() => {
|
||||
queryDrillDownDimension(metricItem?.id);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Result
|
||||
style={{ background: '#fff' }}
|
||||
status="warning"
|
||||
subTitle="当前数据源缺少度量,无法创建指标。请前往数据源配置中,将字段设置为度量"
|
||||
extra={
|
||||
<Button
|
||||
type="primary"
|
||||
key="console"
|
||||
onClick={() => {
|
||||
history.replace(`/model/${domainId}/${modelId || metricItem?.modelId}/dataSource`);
|
||||
onCancel?.();
|
||||
}}
|
||||
>
|
||||
去创建
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetricInfoCreateForm;
|
||||
@@ -0,0 +1,540 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
Form,
|
||||
Button,
|
||||
Input,
|
||||
Select,
|
||||
Radio,
|
||||
Switch,
|
||||
InputNumber,
|
||||
message,
|
||||
Result,
|
||||
Row,
|
||||
Col,
|
||||
Space,
|
||||
Divider,
|
||||
Tooltip,
|
||||
Tag,
|
||||
} from 'antd';
|
||||
|
||||
import MetricMeasuresFormTable from '../../components/MetricMeasuresFormTable';
|
||||
import { SENSITIVE_LEVEL_OPTIONS, METRIC_DEFINE_TYPE, TAG_DEFINE_TYPE } from '../../constant';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import FormItemTitle from '@/components/FormHelper/FormItemTitle';
|
||||
import styles from '../../components/style.less';
|
||||
import {
|
||||
getMetricsToCreateNewMetric,
|
||||
getModelDetail,
|
||||
getDrillDownDimension,
|
||||
batchCreateTag,
|
||||
batchDeleteTag,
|
||||
} from '../../service';
|
||||
import MetricMetricFormTable from '../../components/MetricMetricFormTable';
|
||||
import MetricFieldFormTable from '../../components/MetricFieldFormTable';
|
||||
import DimensionAndMetricRelationModal from '../../components/DimensionAndMetricRelationModal';
|
||||
import TableTitleTooltips from '../../components/TableTitleTooltips';
|
||||
import { createMetric, updateMetric, mockMetricAlias, getMetricTags } from '../../service';
|
||||
import { MetricSettingKey, MetricSettingWording } from '../constants';
|
||||
import { ISemantic } from '../../data';
|
||||
import { history } from 'umi';
|
||||
|
||||
export type CreateFormProps = {
|
||||
datasourceId?: number;
|
||||
domainId: number;
|
||||
modelId: number;
|
||||
metricItem: any;
|
||||
settingKey: MetricSettingKey;
|
||||
onCancel?: () => void;
|
||||
onSubmit?: (values: any) => void;
|
||||
};
|
||||
|
||||
const queryParamsTypeParamsKey = {
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: 'metricDefineByMeasureParams',
|
||||
[METRIC_DEFINE_TYPE.METRIC]: 'metricDefineByMetricParams',
|
||||
[METRIC_DEFINE_TYPE.FIELD]: 'metricDefineByFieldParams',
|
||||
};
|
||||
|
||||
const MetricInfoCreateSqlConfig: React.FC<CreateFormProps> = ({
|
||||
datasourceId,
|
||||
modelId,
|
||||
metricItem,
|
||||
onSubmit,
|
||||
}) => {
|
||||
const isEdit = !!metricItem?.id;
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const formValRef = useRef({} as any);
|
||||
const [form] = Form.useForm();
|
||||
const updateFormVal = (val: any) => {
|
||||
const formVal = {
|
||||
...formValRef.current,
|
||||
...val,
|
||||
};
|
||||
formValRef.current = formVal;
|
||||
};
|
||||
|
||||
const [classMeasureList, setClassMeasureList] = useState<ISemantic.IMeasure[]>([]);
|
||||
|
||||
const [exprTypeParamsState, setExprTypeParamsState] = useState<{
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: ISemantic.IMeasureTypeParams;
|
||||
[METRIC_DEFINE_TYPE.METRIC]: ISemantic.IMetricTypeParams;
|
||||
[METRIC_DEFINE_TYPE.FIELD]: ISemantic.IFieldTypeParams;
|
||||
}>({
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: {
|
||||
measures: [],
|
||||
expr: '',
|
||||
},
|
||||
[METRIC_DEFINE_TYPE.METRIC]: {
|
||||
metrics: [],
|
||||
expr: '',
|
||||
},
|
||||
[METRIC_DEFINE_TYPE.FIELD]: {
|
||||
fields: [],
|
||||
expr: '',
|
||||
},
|
||||
} as any);
|
||||
|
||||
// const [exprTypeParamsState, setExprTypeParamsState] = useState<ISemantic.IMeasure[]>([]);
|
||||
|
||||
const [defineType, setDefineType] = useState(METRIC_DEFINE_TYPE.MEASURE);
|
||||
|
||||
const [createNewMetricList, setCreateNewMetricList] = useState<ISemantic.IMetricItem[]>([]);
|
||||
const [fieldList, setFieldList] = useState<ISemantic.IFieldTypeParamsItem[]>([]);
|
||||
|
||||
const [drillDownDimensions, setDrillDownDimensions] = useState<
|
||||
ISemantic.IDrillDownDimensionItem[]
|
||||
>([]);
|
||||
|
||||
const [drillDownDimensionsConfig, setDrillDownDimensionsConfig] = useState<
|
||||
ISemantic.IDrillDownDimensionItem[]
|
||||
>([]);
|
||||
|
||||
const queryModelDetail = async () => {
|
||||
const { code, data } = await getModelDetail({ modelId: modelId || metricItem?.modelId });
|
||||
if (code === 200) {
|
||||
if (Array.isArray(data?.modelDetail?.fields)) {
|
||||
if (Array.isArray(metricItem?.metricDefineByFieldParams?.fields)) {
|
||||
const fieldList = data.modelDetail.fields.map((item: ISemantic.IFieldTypeParamsItem) => {
|
||||
const { fieldName } = item;
|
||||
if (
|
||||
metricItem?.metricDefineByFieldParams?.fields.find(
|
||||
(measureParamsItem: ISemantic.IFieldTypeParamsItem) =>
|
||||
measureParamsItem.fieldName === fieldName,
|
||||
)
|
||||
) {
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 9999,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 0,
|
||||
};
|
||||
});
|
||||
|
||||
const sortList = fieldList.sort(
|
||||
(
|
||||
a: ISemantic.IFieldTypeParamsItem & { orderNumber: number },
|
||||
b: ISemantic.IFieldTypeParamsItem & { orderNumber: number },
|
||||
) => b.orderNumber - a.orderNumber,
|
||||
);
|
||||
setFieldList(sortList);
|
||||
} else {
|
||||
setFieldList(data.modelDetail.fields);
|
||||
}
|
||||
}
|
||||
if (Array.isArray(data?.modelDetail?.measures)) {
|
||||
if (Array.isArray(metricItem?.metricDefineByMeasureParams?.measures)) {
|
||||
const measureList = data.modelDetail.measures.map((item: ISemantic.IMeasure) => {
|
||||
const { bizName } = item;
|
||||
if (
|
||||
metricItem?.metricDefineByMeasureParams?.measures.find(
|
||||
(measureParamsItem: ISemantic.IMeasure) => measureParamsItem.bizName === bizName,
|
||||
)
|
||||
) {
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 9999,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 0,
|
||||
};
|
||||
});
|
||||
const sortMeasureList = measureList.sort(
|
||||
(
|
||||
a: ISemantic.IMeasure & { orderNumber: number },
|
||||
b: ISemantic.IMeasure & { orderNumber: number },
|
||||
) => b.orderNumber - a.orderNumber,
|
||||
);
|
||||
setClassMeasureList(sortMeasureList);
|
||||
} else {
|
||||
setClassMeasureList(data.modelDetail.measures);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
setClassMeasureList([]);
|
||||
};
|
||||
|
||||
const queryDrillDownDimension = async (metricId: number) => {
|
||||
const { code, data, msg } = await getDrillDownDimension(metricId);
|
||||
if (code === 200 && Array.isArray(data)) {
|
||||
setDrillDownDimensionsConfig(data);
|
||||
}
|
||||
if (code !== 200) {
|
||||
message.error(msg);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
queryModelDetail();
|
||||
queryMetricsToCreateNewMetric();
|
||||
}, []);
|
||||
|
||||
const initData = () => {
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
bizName,
|
||||
description,
|
||||
sensitiveLevel,
|
||||
typeParams,
|
||||
isTag,
|
||||
dataFormat,
|
||||
dataFormatType,
|
||||
alias,
|
||||
classifications,
|
||||
metricDefineType,
|
||||
metricDefineByMeasureParams,
|
||||
metricDefineByMetricParams,
|
||||
metricDefineByFieldParams,
|
||||
} = metricItem;
|
||||
const initValue = {
|
||||
id,
|
||||
name,
|
||||
bizName,
|
||||
sensitiveLevel,
|
||||
description,
|
||||
classifications,
|
||||
isTag,
|
||||
// isPercent,
|
||||
dataFormatType: dataFormatType || '',
|
||||
alias: alias && alias.trim() ? alias.split(',') : [],
|
||||
dataFormat: dataFormat || {
|
||||
decimalPlaces: 2,
|
||||
needMultiply100: false,
|
||||
},
|
||||
};
|
||||
const editInitFormVal = {
|
||||
...formValRef.current,
|
||||
...initValue,
|
||||
};
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.MEASURE) {
|
||||
const { measures, expr } = metricDefineByMeasureParams || {};
|
||||
setExprTypeParamsState({
|
||||
...exprTypeParamsState,
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: {
|
||||
measures: measures || [],
|
||||
expr: expr || '',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.METRIC) {
|
||||
const { metrics, expr } = metricDefineByMetricParams || {};
|
||||
setExprTypeParamsState({
|
||||
...exprTypeParamsState,
|
||||
[METRIC_DEFINE_TYPE.METRIC]: {
|
||||
metrics: metrics || [],
|
||||
expr: expr || '',
|
||||
},
|
||||
});
|
||||
}
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.FIELD) {
|
||||
const { fields, expr } = metricDefineByFieldParams || {};
|
||||
setExprTypeParamsState({
|
||||
...exprTypeParamsState,
|
||||
[METRIC_DEFINE_TYPE.FIELD]: {
|
||||
fields: fields || [],
|
||||
expr: expr || '',
|
||||
},
|
||||
});
|
||||
}
|
||||
updateFormVal(editInitFormVal);
|
||||
form.setFieldsValue(initValue);
|
||||
setDefineType(metricDefineType);
|
||||
|
||||
queryDrillDownDimension(metricItem?.id);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isEdit) {
|
||||
initData();
|
||||
}
|
||||
}, [metricItem]);
|
||||
|
||||
const isEmptyConditions = (
|
||||
metricDefineType: METRIC_DEFINE_TYPE,
|
||||
metricDefineParams:
|
||||
| ISemantic.IMeasureTypeParams
|
||||
| ISemantic.IMetricTypeParams
|
||||
| ISemantic.IFieldTypeParams,
|
||||
) => {
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.MEASURE) {
|
||||
const { measures } = (metricDefineParams as ISemantic.IMeasureTypeParams) || {};
|
||||
if (!(Array.isArray(measures) && measures.length > 0)) {
|
||||
message.error('请添加一个度量');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.METRIC) {
|
||||
const { metrics } = (metricDefineParams as ISemantic.IMetricTypeParams) || {};
|
||||
if (!(Array.isArray(metrics) && metrics.length > 0)) {
|
||||
message.error('请添加一个指标');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (metricDefineType === METRIC_DEFINE_TYPE.FIELD) {
|
||||
const { fields } = (metricDefineParams as ISemantic.IFieldTypeParams) || {};
|
||||
if (!(Array.isArray(fields) && fields.length > 0)) {
|
||||
message.error('请添加一个字段');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const saveMetric = async (fieldsValue: any) => {
|
||||
const queryParams = {
|
||||
modelId: isEdit ? metricItem.modelId : modelId,
|
||||
relateDimension: {
|
||||
...(metricItem?.relateDimension || {}),
|
||||
drillDownDimensions,
|
||||
},
|
||||
...fieldsValue,
|
||||
};
|
||||
const { alias, dataFormatType } = queryParams;
|
||||
queryParams.alias = Array.isArray(alias) ? alias.join(',') : '';
|
||||
if (!queryParams[queryParamsTypeParamsKey[defineType]]?.expr) {
|
||||
message.error('请输入度量表达式');
|
||||
return;
|
||||
}
|
||||
if (!dataFormatType) {
|
||||
delete queryParams.dataFormat;
|
||||
}
|
||||
if (isEmptyConditions(defineType, queryParams[queryParamsTypeParamsKey[defineType]])) {
|
||||
return;
|
||||
}
|
||||
|
||||
let saveMetricQuery = createMetric;
|
||||
if (queryParams.id) {
|
||||
saveMetricQuery = updateMetric;
|
||||
}
|
||||
const { code, msg, data } = await saveMetricQuery(queryParams);
|
||||
if (code === 200) {
|
||||
if (queryParams.isTag) {
|
||||
queryBatchExportTag(data.id || metricItem?.id);
|
||||
}
|
||||
|
||||
if (metricItem?.id && !queryParams.isTag) {
|
||||
queryBatchDelete(metricItem);
|
||||
}
|
||||
message.success('编辑指标成功');
|
||||
onSubmit?.(queryParams);
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
const queryBatchDelete = async (metricItem: ISemantic.IMetricItem) => {
|
||||
const { code, msg } = await batchDeleteTag([
|
||||
{
|
||||
itemIds: [metricItem.id],
|
||||
tagDefineType: TAG_DEFINE_TYPE.METRIC,
|
||||
},
|
||||
]);
|
||||
if (code === 200) {
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
const queryBatchExportTag = async (id: number) => {
|
||||
const { code, msg } = await batchCreateTag([
|
||||
{ itemId: id, tagDefineType: TAG_DEFINE_TYPE.METRIC },
|
||||
]);
|
||||
|
||||
if (code === 200) {
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
const queryMetricsToCreateNewMetric = async () => {
|
||||
const { code, data } = await getMetricsToCreateNewMetric({
|
||||
modelId: modelId || metricItem?.modelId,
|
||||
});
|
||||
if (code === 200) {
|
||||
if (Array.isArray(metricItem?.metricDefineByMetricParams?.metrics)) {
|
||||
const fieldList = data.map((item: ISemantic.IMetricTypeParamsItem) => {
|
||||
const { bizName } = item;
|
||||
if (
|
||||
metricItem?.metricDefineByMetricParams?.metrics.find(
|
||||
(measureParamsItem: ISemantic.IMetricTypeParamsItem) =>
|
||||
measureParamsItem.bizName === bizName,
|
||||
)
|
||||
) {
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 9999,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
orderNumber: 0,
|
||||
};
|
||||
});
|
||||
|
||||
const sortList = fieldList.sort(
|
||||
(
|
||||
a: ISemantic.IMetricTypeParamsItem & { orderNumber: number },
|
||||
b: ISemantic.IMetricTypeParamsItem & { orderNumber: number },
|
||||
) => b.orderNumber - a.orderNumber,
|
||||
);
|
||||
setCreateNewMetricList(sortList);
|
||||
} else {
|
||||
setCreateNewMetricList(data);
|
||||
}
|
||||
} else {
|
||||
message.error('获取指标标签失败');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
padding: '0 0 20px 24px',
|
||||
// borderBottom: '1px solid #eee',
|
||||
}}
|
||||
>
|
||||
<Radio.Group
|
||||
buttonStyle="solid"
|
||||
value={defineType}
|
||||
onChange={(e) => {
|
||||
setDefineType(e.target.value);
|
||||
}}
|
||||
>
|
||||
<Radio.Button value={METRIC_DEFINE_TYPE.MEASURE}>按度量</Radio.Button>
|
||||
<Radio.Button value={METRIC_DEFINE_TYPE.METRIC}>按指标</Radio.Button>
|
||||
<Radio.Button value={METRIC_DEFINE_TYPE.FIELD}>按字段</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
{defineType === METRIC_DEFINE_TYPE.MEASURE && (
|
||||
<>
|
||||
<MetricMeasuresFormTable
|
||||
datasourceId={datasourceId}
|
||||
typeParams={exprTypeParamsState[METRIC_DEFINE_TYPE.MEASURE]}
|
||||
measuresList={classMeasureList}
|
||||
onFieldChange={(measures: ISemantic.IMeasure[]) => {
|
||||
// setClassMeasureList(measures);
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.MEASURE],
|
||||
measures,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
onSqlChange={(expr: string) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.MEASURE]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.MEASURE],
|
||||
expr,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{defineType === METRIC_DEFINE_TYPE.METRIC && (
|
||||
<>
|
||||
<p className={styles.desc}>
|
||||
基于
|
||||
<Tag color="#2499ef14" className={styles.markerTag}>
|
||||
已有
|
||||
</Tag>
|
||||
指标来衍生新的指标
|
||||
</p>
|
||||
|
||||
<MetricMetricFormTable
|
||||
typeParams={exprTypeParamsState[METRIC_DEFINE_TYPE.METRIC]}
|
||||
metricList={createNewMetricList}
|
||||
onFieldChange={(metrics: ISemantic.IMetricTypeParamsItem[]) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.METRIC]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.METRIC],
|
||||
metrics,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
onSqlChange={(expr: string) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.METRIC]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.METRIC],
|
||||
expr,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{defineType === METRIC_DEFINE_TYPE.FIELD && (
|
||||
<>
|
||||
<MetricFieldFormTable
|
||||
typeParams={exprTypeParamsState[METRIC_DEFINE_TYPE.FIELD]}
|
||||
fieldList={fieldList}
|
||||
onFieldChange={(fields: ISemantic.IFieldTypeParamsItem[]) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.FIELD]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.FIELD],
|
||||
fields,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
onSqlChange={(expr: string) => {
|
||||
setExprTypeParamsState((prevState) => {
|
||||
return {
|
||||
...prevState,
|
||||
[METRIC_DEFINE_TYPE.FIELD]: {
|
||||
...prevState[METRIC_DEFINE_TYPE.FIELD],
|
||||
expr,
|
||||
},
|
||||
};
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetricInfoCreateSqlConfig;
|
||||
@@ -0,0 +1,11 @@
|
||||
export enum MetricSettingKey {
|
||||
BASIC = 'BASIC',
|
||||
SQL_CONFIG = 'SQLCONFIG',
|
||||
DIMENSION_CONFIG = 'DIMENSION_CONFIG',
|
||||
}
|
||||
|
||||
export const MetricSettingWording = {
|
||||
[MetricSettingKey.BASIC]: '基本信息',
|
||||
[MetricSettingKey.SQL_CONFIG]: '表达式',
|
||||
[MetricSettingKey.DIMENSION_CONFIG]: '下钻维度配置',
|
||||
};
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import React from 'react';
|
||||
import { Outlet } from 'umi';
|
||||
|
||||
const market: React.FC = ({ children }) => {
|
||||
return <>{children}</>;
|
||||
const market: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<Outlet />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default market;
|
||||
|
||||
@@ -168,6 +168,76 @@
|
||||
}
|
||||
}
|
||||
|
||||
.metricEditWrapper {
|
||||
// height: calc(100vh - 56px);
|
||||
// overflow: scroll;
|
||||
.metricDetailTab {
|
||||
:global {
|
||||
.ant-tabs-nav {
|
||||
margin: 10px 20px 0 20px;
|
||||
padding: 0 20px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 8px;
|
||||
transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||
}
|
||||
.ant-tabs-tab {
|
||||
padding: 12px 0;
|
||||
color: #344767;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
.metricDetail {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
background-color: transparent;
|
||||
height: 100%;
|
||||
.tabContainer {
|
||||
padding: 24px;
|
||||
// height: 100%;
|
||||
min-height: calc(100vh - 78px);
|
||||
width: calc(100vw - 350px);
|
||||
background-color: #fafafb;
|
||||
}
|
||||
.metricInfoContent {
|
||||
padding: 25px;
|
||||
.title {
|
||||
position: relative;
|
||||
margin-bottom: 12px;
|
||||
color: #0e73ff;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: -10px;
|
||||
display: block;
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
font-size: 0;
|
||||
background: #0e73ff;
|
||||
border: 1px solid #0e73ff;
|
||||
border-radius: 2px;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
}
|
||||
.siderContainer {
|
||||
width: 350px;
|
||||
min-height: calc(100vh - 78px);
|
||||
// margin: 10px 20px 20px 0;
|
||||
// background-color: rgb(255, 255, 255);
|
||||
border-radius: 6px;
|
||||
padding: 24px 0 24px 24px;
|
||||
// box-shadow: rgba(0, 0, 0, 0.08) 6px 0px 16px 0px, rgba(0, 0, 0, 0.12) 3px 0px 6px -4px,
|
||||
// rgba(0, 0, 0, 0.05) 9px 0px 28px 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.metricDetailWrapper {
|
||||
height: calc(100vh - 56px);
|
||||
overflow: scroll;
|
||||
@@ -194,9 +264,12 @@
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
background-color: transparent;
|
||||
height: 100%;
|
||||
.tabContainer {
|
||||
height: 100%;
|
||||
min-height: calc(100vh - 78px);
|
||||
width: calc(100vw - 450px);
|
||||
background-color: rgb(240, 242, 245);
|
||||
background-color: #fafafb;
|
||||
}
|
||||
.metricInfoContent {
|
||||
padding: 25px;
|
||||
@@ -246,8 +319,19 @@
|
||||
}
|
||||
|
||||
.metricInfoSider {
|
||||
padding: 24px;
|
||||
padding: 20px;
|
||||
color: #344767;
|
||||
background-color: #fff;
|
||||
height: 100%;
|
||||
border: 1px solid #e6ebf1;
|
||||
border-radius: 6px;
|
||||
.createTitle {
|
||||
margin-bottom: 10px;
|
||||
color:#344767;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
font-family: var(--tencent-font-family);
|
||||
}
|
||||
.gotoMetricListIcon {
|
||||
color: #3182ce;
|
||||
cursor: pointer;
|
||||
@@ -256,6 +340,7 @@
|
||||
}
|
||||
}
|
||||
.title {
|
||||
margin-bottom: 20px;
|
||||
.name {
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
@@ -287,11 +372,16 @@
|
||||
opacity: 1;
|
||||
}
|
||||
.sectionContainer {
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: scroll;
|
||||
|
||||
|
||||
overflow: hidden;
|
||||
// box-shadow: #888888 0px 0px 1px, rgba(29, 41, 57, 0.08) 0px 1px 3px;
|
||||
background-image: none;
|
||||
// transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||
border-radius: 6px;
|
||||
.section {
|
||||
padding: 16px;
|
||||
@@ -420,3 +510,70 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settingList {
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
position: relative;
|
||||
padding: 0px;
|
||||
li {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
background-color: transparent;
|
||||
outline: 0px;
|
||||
border: 0px;
|
||||
margin: 0px;
|
||||
border-radius: 0px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
vertical-align: middle;
|
||||
appearance: none;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
min-width: 0px;
|
||||
box-sizing: border-box;
|
||||
text-align: left;
|
||||
padding: 8px 16px;
|
||||
transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||
&.active {
|
||||
background-color: rgba(22, 119, 255, 0.08);
|
||||
.icon {
|
||||
color: rgb(22, 119, 255);
|
||||
}
|
||||
.content {
|
||||
.text {
|
||||
color: rgb(22, 119, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
min-width: 32px;
|
||||
color: #344767;
|
||||
flex-shrink: 0;
|
||||
display: inline-flex;
|
||||
}
|
||||
.content {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
.text {
|
||||
margin: 0px;
|
||||
color: #344767;
|
||||
font-size: 16px;
|
||||
// line-height: 1.57;
|
||||
// font-family: var(--tencent-font-family);
|
||||
font-weight: 600;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,39 @@
|
||||
import { Popover, message, Space } from 'antd';
|
||||
import { message } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect, history, useParams } from 'umi';
|
||||
import { history, useParams, useModel } from '@umijs/max';
|
||||
import DomainListTree from './components/DomainList';
|
||||
|
||||
import styles from './components/style.less';
|
||||
import type { StateType } from './model';
|
||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import { ISemantic } from './data';
|
||||
import { getDomainList, getModelList } from './service';
|
||||
// import ChatSettingTab from './ChatSetting/ChatSettingTab';
|
||||
import DomainManagerTab from './components/DomainManagerTab';
|
||||
import type { Dispatch } from 'umi';
|
||||
|
||||
type Props = {
|
||||
mode: 'domain';
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
|
||||
const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) => {
|
||||
const OverviewContainer: React.FC<Props> = ({ mode }) => {
|
||||
const params: any = useParams();
|
||||
const domainId = params.domainId;
|
||||
const modelId = params.modelId;
|
||||
|
||||
const domainModel = useModel('SemanticModel.domainData');
|
||||
const modelModel = useModel('SemanticModel.modelData');
|
||||
const dimensionModel = useModel('SemanticModel.dimensionData');
|
||||
const metricModel = useModel('SemanticModel.metricData');
|
||||
const databaseModel = useModel('SemanticModel.databaseData');
|
||||
const { selectDomainId, domainList, setSelectDomain, setDomainList } = domainModel;
|
||||
const {
|
||||
selectModelId,
|
||||
modelList,
|
||||
MrefreshModelList,
|
||||
setSelectModel,
|
||||
setModelTableHistoryParams,
|
||||
} = modelModel;
|
||||
const { MrefreshDimensionList } = dimensionModel;
|
||||
const { MrefreshMetricList } = metricModel;
|
||||
const { MrefreshDatabaseList } = databaseModel;
|
||||
const menuKey = params.menuKey ? params.menuKey : !Number(modelId) ? 'overview' : '';
|
||||
const { selectDomainId, selectModelId, domainList } = domainManger;
|
||||
const [modelList, setModelList] = useState<ISemantic.IModelItem[]>([]);
|
||||
// const [modelList, setModelList] = useState<ISemantic.IModelItem[]>([]);
|
||||
const [isModel, setIsModel] = useState<boolean>(false);
|
||||
const [collapsedState, setCollapsedState] = useState(true);
|
||||
const [activeKey, setActiveKey] = useState<string>(menuKey);
|
||||
@@ -39,24 +47,13 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
return item.parentId === 0;
|
||||
})[0];
|
||||
if (firstRootNode) {
|
||||
const { id, name } = firstRootNode;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData: firstRootNode,
|
||||
});
|
||||
const { id } = firstRootNode;
|
||||
setSelectDomain(firstRootNode);
|
||||
setActiveKey(menuKey);
|
||||
pushUrlMenu(id, 0, menuKey);
|
||||
}
|
||||
} else {
|
||||
const { id, name } = targetNode;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData: targetNode,
|
||||
});
|
||||
setSelectDomain(targetNode);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -64,10 +61,7 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
const { code, data, msg } = await getDomainList();
|
||||
if (code === 200) {
|
||||
initSelectedDomain(data);
|
||||
dispatch({
|
||||
type: 'domainManger/setDomainList',
|
||||
payload: { domainList: data },
|
||||
});
|
||||
setDomainList(data);
|
||||
} else {
|
||||
message.error(msg);
|
||||
}
|
||||
@@ -75,22 +69,10 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
|
||||
useEffect(() => {
|
||||
initProjectTree();
|
||||
dispatch({
|
||||
type: 'domainManger/queryDatabaseList',
|
||||
});
|
||||
MrefreshDatabaseList();
|
||||
return () => {
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: 0,
|
||||
selectDomainName: '',
|
||||
domainData: undefined,
|
||||
});
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectModel',
|
||||
selectModelId: 0,
|
||||
selectModelName: '',
|
||||
modelData: undefined,
|
||||
});
|
||||
setSelectDomain(undefined);
|
||||
setSelectModel(undefined);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -102,26 +84,15 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
}, [selectDomainId]);
|
||||
|
||||
const queryModelList = async () => {
|
||||
const { code, data } = await getModelList(selectDomainId);
|
||||
if (code === 200) {
|
||||
setModelList(data);
|
||||
const model = data.filter((item: any) => {
|
||||
const list = await MrefreshModelList(selectDomainId);
|
||||
const model = list.filter((item: any) => {
|
||||
return `${item.id}` === modelId;
|
||||
})[0];
|
||||
if (model) {
|
||||
const { id, name } = model;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectModel',
|
||||
selectModelId: id,
|
||||
selectModelName: name,
|
||||
modelData: model,
|
||||
});
|
||||
setSelectModel(model);
|
||||
setActiveKey(menuKey);
|
||||
setIsModel(true);
|
||||
pushUrlMenu(selectDomainId, id, menuKey);
|
||||
}
|
||||
} else {
|
||||
message.error('获取模型列表失败!');
|
||||
pushUrlMenu(model.domainId, model.id, menuKey);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -144,18 +115,8 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
return;
|
||||
}
|
||||
initModelConfig();
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
modelId: selectModelId,
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
modelId: selectModelId,
|
||||
},
|
||||
});
|
||||
MrefreshDimensionList({ modelId: selectModelId });
|
||||
MrefreshMetricList({ modelId: selectModelId });
|
||||
}, [selectModelId]);
|
||||
|
||||
const pushUrlMenu = (domainId: number, modelId: number, menuKey: string) => {
|
||||
@@ -163,32 +124,21 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
};
|
||||
|
||||
const handleModelChange = (model?: ISemantic.IModelItem) => {
|
||||
// queryModelList();
|
||||
console.log(model, 1111);
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
if (`${model.id}` === `${selectModelId}`) {
|
||||
initModelConfig();
|
||||
}
|
||||
const { id, name } = model;
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectModel',
|
||||
selectModelId: id,
|
||||
selectModelName: name,
|
||||
modelData: model,
|
||||
});
|
||||
setSelectModel(model);
|
||||
};
|
||||
|
||||
const cleanModelInfo = (domainId) => {
|
||||
setIsModel(false);
|
||||
setActiveKey('overview');
|
||||
pushUrlMenu(domainId, 0, 'overview');
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectModel',
|
||||
selectModelId: 0,
|
||||
selectModelName: '',
|
||||
modelData: undefined,
|
||||
});
|
||||
setSelectModel(undefined);
|
||||
};
|
||||
|
||||
const handleCollapsedBtn = () => {
|
||||
@@ -203,19 +153,11 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
<DomainListTree
|
||||
createDomainBtnVisible={mode === 'domain' ? true : false}
|
||||
onTreeSelected={(domainData: ISemantic.IDomainItem) => {
|
||||
const { id, name } = domainData;
|
||||
const { id } = domainData;
|
||||
cleanModelInfo(id);
|
||||
dispatch({
|
||||
type: 'domainManger/setSelectDomain',
|
||||
selectDomainId: id,
|
||||
selectDomainName: name,
|
||||
domainData,
|
||||
});
|
||||
dispatch({
|
||||
type: 'domainManger/setModelTableHistoryParams',
|
||||
payload: {
|
||||
setSelectDomain(domainData);
|
||||
setModelTableHistoryParams({
|
||||
[id]: {},
|
||||
},
|
||||
});
|
||||
}}
|
||||
onTreeDataUpdate={() => {
|
||||
@@ -232,7 +174,6 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
>
|
||||
{collapsedState ? <LeftOutlined /> : <RightOutlined />}
|
||||
</div>
|
||||
{/* <RightOutlined /> */}
|
||||
</div>
|
||||
<div className={styles.content}>
|
||||
{selectDomainId ? (
|
||||
@@ -243,6 +184,7 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
modelList={modelList}
|
||||
handleModelChange={(model) => {
|
||||
handleModelChange(model);
|
||||
MrefreshModelList(selectDomainId);
|
||||
}}
|
||||
onBackDomainBtnClick={() => {
|
||||
cleanModelInfo(selectDomainId);
|
||||
@@ -262,6 +204,4 @@ const OverviewContainer: React.FC<Props> = ({ mode, domainManger, dispatch }) =>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(OverviewContainer);
|
||||
export default OverviewContainer;
|
||||
|
||||
@@ -3,26 +3,22 @@ import { Drawer } from 'antd';
|
||||
import { WorkspacePanel, useXFlowApp, useModelAsync, XFlowGraphCommands } from '@antv/xflow';
|
||||
import { useJsonSchemaFormModel } from '@antv/xflow-extension/es/canvas-json-schema-form/service';
|
||||
import { NS_DATA_SOURCE_RELATION_MODAL_OPEN_STATE } from '../ConfigModelService';
|
||||
import { connect } from 'umi';
|
||||
import { DATASOURCE_NODE_RENDER_ID } from '../constant';
|
||||
import DataSourceRelationFormDrawer from './DataSourceRelationFormDrawer';
|
||||
import ModelCreateForm from '../../Datasource/components/ModelCreateForm';
|
||||
// import ClassModelTypeModal from '../../components/ClassDataSourceTypeModal1';
|
||||
import { GraphApi } from '../service';
|
||||
import { SemanticNodeType } from '../../enum';
|
||||
import type { StateType } from '../../model';
|
||||
import DataSource from '../../Datasource';
|
||||
|
||||
export type CreateFormProps = {
|
||||
controlMapService: any;
|
||||
formSchemaService: any;
|
||||
formValueUpdateService: any;
|
||||
domainManger: StateType;
|
||||
selectDomainId:number
|
||||
};
|
||||
|
||||
const XflowJsonSchemaFormDrawerForm: React.FC<CreateFormProps> = (props) => {
|
||||
const { domainManger } = props;
|
||||
const { selectDomainId } = domainManger;
|
||||
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||
const [dataSourceItem, setDataSourceItem] = useState<any>();
|
||||
@@ -91,7 +87,7 @@ const XflowJsonSchemaFormDrawerForm: React.FC<CreateFormProps> = (props) => {
|
||||
return (
|
||||
<WorkspacePanel position={{}}>
|
||||
<DataSourceRelationFormDrawer
|
||||
domainId={domainManger.selectDomainId}
|
||||
domainId={props.selectDomainId}
|
||||
nodeDataSource={nodeDataSource}
|
||||
onClose={() => {
|
||||
handleDataSourceRelationDrawerClose();
|
||||
@@ -136,7 +132,6 @@ const XflowJsonSchemaFormDrawerForm: React.FC<CreateFormProps> = (props) => {
|
||||
>
|
||||
<DataSource
|
||||
initialValues={dataSourceItem}
|
||||
domainId={Number(domainManger?.selectDomainId)}
|
||||
onSubmitSuccess={(dataSourceInfo: any) => {
|
||||
setCreateModalVisible(false);
|
||||
const { targetCell, targetData } = state;
|
||||
@@ -174,6 +169,4 @@ const XflowJsonSchemaFormDrawerForm: React.FC<CreateFormProps> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(XflowJsonSchemaFormDrawerForm);
|
||||
export default XflowJsonSchemaFormDrawerForm
|
||||
|
||||
@@ -27,8 +27,7 @@ import { useMenuConfig } from './ConfigMenu';
|
||||
import { useToolbarConfig } from './ConfigToolbar';
|
||||
/** 配置Dnd组件面板 */
|
||||
import * as dndPanelConfig from './ConfigDndPanel';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import { useModel } from '@umijs/max';
|
||||
import './index.less';
|
||||
import XflowJsonSchemaFormDrawer from './components/XflowJsonSchemaFormDrawer';
|
||||
import { getViewInfoList } from '../service';
|
||||
@@ -38,12 +37,17 @@ import '@antv/xflow/dist/index.css';
|
||||
|
||||
import { registerEdgeTool } from './ReactNodes/ToolTipsNode';
|
||||
|
||||
export interface IProps {
|
||||
domainManger: StateType;
|
||||
}
|
||||
export interface IProps {}
|
||||
|
||||
export const SemanticFlow: React.FC<IProps> = (props) => {
|
||||
const { domainManger } = props;
|
||||
const domainModel = useModel('SemanticModel.domainData');
|
||||
const modelModel = useModel('SemanticModel.modelData');
|
||||
const { selectDomain } = domainModel;
|
||||
const { selectModel } = modelModel;
|
||||
const domainManger: any = {
|
||||
...selectDomain,
|
||||
...selectModel,
|
||||
};
|
||||
|
||||
const graphHooksConfig = useGraphHookConfig(props);
|
||||
const toolbarConfig = useToolbarConfig();
|
||||
@@ -148,6 +152,4 @@ export const SemanticFlow: React.FC<IProps> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(SemanticFlow);
|
||||
export default SemanticFlow;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { NsGraph } from '@antv/xflow';
|
||||
import { uuidv4 } from '@antv/xflow';
|
||||
import type { StateType } from '../model';
|
||||
import { GraphApi } from './service';
|
||||
import { NODE_WIDTH, NODE_HEIGHT } from './constant';
|
||||
import moment from 'moment';
|
||||
@@ -51,7 +50,7 @@ export const computedSingerNodesEdgesPosition = ({ nodes, edges }: NsGraph.IGrap
|
||||
|
||||
export const addClassInfoAsDataSourceParents = (
|
||||
{ nodes = [], edges = [] }: NsGraph.IGraphData,
|
||||
domainManger: StateType,
|
||||
domainManger: any,
|
||||
) => {
|
||||
const { selectDomainId, selectDomainName } = domainManger;
|
||||
const sourceId = `classNodeId-${selectDomainId}`;
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import { Space, Checkbox } from 'antd';
|
||||
import type { CheckboxValueType } from 'antd/es/checkbox/Group';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import styles from '../style.less';
|
||||
|
||||
type Props = {
|
||||
legendOptions: LegendOptionsItem[];
|
||||
value?: string[];
|
||||
domainManger: StateType;
|
||||
onChange?: (ids: CheckboxValueType[]) => void;
|
||||
defaultCheckAll?: boolean;
|
||||
[key: string]: any;
|
||||
@@ -78,6 +74,4 @@ const GraphLegend: React.FC<Props> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(GraphLegend);
|
||||
export default GraphLegend;
|
||||
|
||||
@@ -2,11 +2,7 @@ import { Button, Space } from 'antd';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import React from 'react';
|
||||
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
onClick: (params?: { eventName?: string }) => void;
|
||||
[key: string]: any;
|
||||
};
|
||||
@@ -61,6 +57,4 @@ const GraphToolBar: React.FC<Props> = ({ onClick }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(GraphToolBar);
|
||||
export default GraphToolBar
|
||||
|
||||
@@ -2,8 +2,6 @@ import { Button, Drawer, message, Row, Col, Divider, Tag, Space, Popconfirm } fr
|
||||
import React, { useState, useEffect, ReactNode } from 'react';
|
||||
import { SemanticNodeType } from '../../enum';
|
||||
import { deleteDimension, deleteMetric, deleteDatasource } from '../../service';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import moment from 'moment';
|
||||
import styles from '../style.less';
|
||||
import TransTypeTag from '../../components/TransTypeTag';
|
||||
@@ -11,7 +9,6 @@ import { SENSITIVE_LEVEL_ENUM } from '../../constant';
|
||||
|
||||
type Props = {
|
||||
nodeData: any;
|
||||
domainManger: StateType;
|
||||
onNodeChange: (params?: { eventName?: string }) => void;
|
||||
onEditBtnClick?: (nodeData: any) => void;
|
||||
[key: string]: any;
|
||||
@@ -47,13 +44,11 @@ const DescriptionItem = ({ title, content }: DescriptionItemProps) => (
|
||||
|
||||
const NodeInfoDrawer: React.FC<Props> = ({
|
||||
nodeData,
|
||||
domainManger,
|
||||
onNodeChange,
|
||||
onEditBtnClick,
|
||||
...restProps
|
||||
}) => {
|
||||
const [infoList, setInfoList] = useState<InfoListItem[]>([]);
|
||||
const { selectModelName } = domainManger;
|
||||
|
||||
useEffect(() => {
|
||||
if (!nodeData) {
|
||||
@@ -87,7 +82,7 @@ const NodeInfoDrawer: React.FC<Props> = ({
|
||||
{
|
||||
label: '所属模型',
|
||||
value: modelName,
|
||||
content: <Tag>{modelName || selectModelName}</Tag>,
|
||||
content: <Tag>{modelName}</Tag>,
|
||||
},
|
||||
|
||||
{
|
||||
@@ -266,6 +261,4 @@ const NodeInfoDrawer: React.FC<Props> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(NodeInfoDrawer);
|
||||
export default NodeInfoDrawer
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../model';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { useModel } from 'umi';
|
||||
import {
|
||||
typeConfigs,
|
||||
formatterRelationData,
|
||||
@@ -37,12 +35,9 @@ import GraphLegendVisibleModeItem from './components/GraphLegendVisibleModeItem'
|
||||
import ModelRelationFormDrawer from './components/ModelRelationFormDrawer';
|
||||
import ControlToolBar from './components/ControlToolBar';
|
||||
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
dispatch: Dispatch;
|
||||
};
|
||||
type Props = {};
|
||||
|
||||
const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const SemanticGraph: React.FC<Props> = ({}) => {
|
||||
const ref = useRef(null);
|
||||
const dataSourceRef = useRef<ISemantic.IDomainSchemaRelaList>([]);
|
||||
const [graphData, setGraphData] = useState<TreeGraphData>();
|
||||
@@ -63,7 +58,15 @@ const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
|
||||
const [dataSourceInfoList, setDataSourceInfoList] = useState<IDataSource.IDataSourceItem[]>([]);
|
||||
|
||||
const { dimensionList, metricList, selectModelId: modelId, selectDomainId } = domainManger;
|
||||
const domainModel = useModel('SemanticModel.domainData');
|
||||
const modelModel = useModel('SemanticModel.modelData');
|
||||
const dimensionModel = useModel('SemanticModel.dimensionData');
|
||||
const metricModel = useModel('SemanticModel.metricData');
|
||||
|
||||
const { selectDomainId, selectDomainName } = domainModel;
|
||||
const { selectModelId: modelId } = modelModel;
|
||||
const { MdimensionList: dimensionList, MrefreshDimensionList } = dimensionModel;
|
||||
const { MmetricList: metricList, MrefreshMetricList } = metricModel;
|
||||
|
||||
const dimensionListRef = useRef<ISemantic.IDimensionItem[]>([]);
|
||||
const metricListRef = useRef<ISemantic.IMetricItem[]>([]);
|
||||
@@ -134,7 +137,7 @@ const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
|
||||
const graphRootData = {
|
||||
id: 'root',
|
||||
name: domainManger.selectDomainName,
|
||||
name: selectDomainName,
|
||||
children: relationData,
|
||||
};
|
||||
return graphRootData;
|
||||
@@ -211,7 +214,6 @@ const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
const saveRelationConfig = async (domainId: number, graphData: any) => {
|
||||
const configData = {
|
||||
id: relationConfig?.id,
|
||||
// modelId: domainManger.selectModelId,
|
||||
domainId: domainId,
|
||||
type: 'modelEdgeRelation',
|
||||
config: JSON.stringify(graphData),
|
||||
@@ -1050,20 +1052,10 @@ const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
updateGraphData();
|
||||
setInfoDrawerVisible(false);
|
||||
if (eventName === SemanticNodeType.METRIC) {
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
MrefreshMetricList({ modelId });
|
||||
}
|
||||
if (eventName === SemanticNodeType.DIMENSION) {
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
MrefreshDimensionList({ modelId });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -1078,12 +1070,7 @@ const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
onSubmit={() => {
|
||||
setCreateDimensionModalVisible(false);
|
||||
updateGraphData();
|
||||
dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
MrefreshDimensionList({ modelId });
|
||||
}}
|
||||
onCancel={() => {
|
||||
setCreateDimensionModalVisible(false);
|
||||
@@ -1101,12 +1088,7 @@ const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
onSubmit={() => {
|
||||
setCreateMetricModalVisible(false);
|
||||
updateGraphData();
|
||||
dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
MrefreshMetricList({ modelId });
|
||||
}}
|
||||
onCancel={() => {
|
||||
setCreateMetricModalVisible(false);
|
||||
@@ -1134,18 +1116,8 @@ const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
setConfirmModalOpenState(false);
|
||||
updateGraphData();
|
||||
graphShowTypeState === SemanticNodeType.DIMENSION
|
||||
? dispatch({
|
||||
type: 'domainManger/queryDimensionList',
|
||||
payload: {
|
||||
modelId,
|
||||
},
|
||||
})
|
||||
: dispatch({
|
||||
type: 'domainManger/queryMetricList',
|
||||
payload: {
|
||||
modelId,
|
||||
},
|
||||
});
|
||||
? MrefreshDimensionList({ modelId })
|
||||
: MrefreshMetricList({ modelId });
|
||||
}}
|
||||
onCancelClick={() => {
|
||||
setConfirmModalOpenState(false);
|
||||
@@ -1154,7 +1126,7 @@ const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
/>
|
||||
}
|
||||
<ModelRelationFormDrawer
|
||||
domainId={domainManger.selectDomainId}
|
||||
domainId={selectDomainId}
|
||||
nodeModel={nodeModel}
|
||||
relationData={currentRelationDataItem}
|
||||
onClose={() => {
|
||||
@@ -1176,6 +1148,4 @@ const DomainManger: React.FC<Props> = ({ domainManger, dispatch }) => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(DomainManger);
|
||||
export default SemanticGraph;
|
||||
|
||||
@@ -8,12 +8,12 @@ import { SemanticNodeType } from './enum';
|
||||
import SemanticGraph from './SemanticGraph';
|
||||
|
||||
type Props = {
|
||||
domainManger: StateType;
|
||||
|
||||
};
|
||||
|
||||
const SemanticGraphCanvas: React.FC<Props> = ({ domainManger }) => {
|
||||
const SemanticGraphCanvas: React.FC<Props> = ({ }) => {
|
||||
// const [graphShowType, setGraphShowType] = useState<SemanticNodeType>(SemanticNodeType.DIMENSION);
|
||||
const { selectDomainId } = domainManger;
|
||||
|
||||
return (
|
||||
<div className={styles.semanticGraphCanvas}>
|
||||
{/* <div className={styles.toolbar}>
|
||||
@@ -46,6 +46,4 @@ const SemanticGraphCanvas: React.FC<Props> = ({ domainManger }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(SemanticGraphCanvas);
|
||||
export default SemanticGraphCanvas;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import type { ActionType, ProColumns } from '@ant-design/pro-components';
|
||||
import { ProTable } from '@ant-design/pro-components';
|
||||
import { message, Button, Space, Popconfirm, Input, Tag } from 'antd';
|
||||
import { message, Button, Space, Popconfirm } from 'antd';
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import { StatusEnum } from '../../enum';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import { useModel } from '@umijs/max';
|
||||
import { deleteView, updateView, getViewList, getAllModelByDomainId } from '../../service';
|
||||
import ViewCreateFormModal from './ViewCreateFormModal';
|
||||
import moment from 'moment';
|
||||
@@ -17,12 +15,12 @@ import ViewSearchFormModal from './ViewSearchFormModal';
|
||||
type Props = {
|
||||
disabledEdit?: boolean;
|
||||
modelList: ISemantic.IModelItem[];
|
||||
dispatch: Dispatch;
|
||||
domainManger: StateType;
|
||||
};
|
||||
|
||||
const DataSetTable: React.FC<Props> = ({ disabledEdit = false, domainManger }) => {
|
||||
const { selectDomainId } = domainManger;
|
||||
const DataSetTable: React.FC<Props> = ({ disabledEdit = false }) => {
|
||||
const domainModel = useModel('SemanticModel.domainData');
|
||||
const { selectDomainId } = domainModel;
|
||||
|
||||
const [viewItem, setViewItem] = useState<ISemantic.IViewItem>();
|
||||
const [saveLoading, setSaveLoading] = useState<boolean>(false);
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
@@ -254,6 +252,4 @@ const DataSetTable: React.FC<Props> = ({ disabledEdit = false, domainManger }) =
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(DataSetTable);
|
||||
export default DataSetTable;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user