first push

main
zhoux 1 year ago
parent c8212e90b7
commit fbb14a6e7e

@ -0,0 +1,16 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab

@ -0,0 +1,6 @@
# 平台本地运行端口号
REACT_APP_ENV = dev
API_SERVER = 127.0.0.1:8888
SERVER_HOST = http://localhost:8888/
FILE_SERVER_HOST = http://192.168.10.28:8088
WEBRTC_SERVER_HOST = http://192.168.10.96:9005

@ -0,0 +1,6 @@
# 平台本地运行端口号
REACT_APP_ENV = dev
API_SERVER = 127.0.0.1:8888
SERVER_HOST = http://localhost:8888/
FILE_SERVER_HOST = http://192.168.10.28:8088
WEBRTC_SERVER_HOST = http://192.168.10.96:9005

@ -0,0 +1,5 @@
REACT_APP_ENV = prod
API_SERVER = 127.0.0.1:8888
SERVER_HOST = /
FILE_SERVER_HOST = http://192.168.10.96
WEBRTC_SERVER_HOST = http://192.168.10.96:9005

@ -0,0 +1,8 @@
/lambda/
/scripts
/config
.history
public
dist
.umi
mock

@ -0,0 +1,8 @@
module.exports = {
extends: [require.resolve('@umijs/lint/dist/config/eslint')],
globals: {
page: true,
REACT_APP_ENV: true,
SERVER_HOST: true,
},
};

46
.gitignore vendored

@ -1,11 +1,47 @@
# ---> Vue
# gitignore template for Vue.js projects
#
# Recommended template: Node.gitignore
# TODO: where does this rule come from?
docs/_book
# TODO: where does this rule come from?
test/
# dependencies
**/node_modules
# roadhog-api-doc ignore
/src/utils/request-temp.js
_roadhog-api-doc
# production
/dist
/taskDoc
/src/pages/Demo
# misc
.DS_Store
npm-debug.log*
yarn-error.log
/coverage
.idea
yarn.lock
package-lock.json
*bak
.vscode
# visual studio code
.history
*.log
functions/*
.temp/**
# umi
.umi
.umi-production
.umi-test
# screenshot
screenshot
.firebase
.eslintcache
build

@ -0,0 +1,22 @@
**/*.svg
.umi
.umi-production
/dist
.dockerignore
.DS_Store
.eslintignore
*.png
*.toml
docker
.editorconfig
Dockerfile*
.gitignore
.prettierignore
LICENSE
.eslintcache
*.lock
yarn-error.log
.history
CNAME
/build
/public

@ -0,0 +1,21 @@
module.exports = {
singleQuote: true,
trailingComma: 'all',
printWidth: 100,
proseWrap: 'never',
endOfLine: 'lf',
overrides: [
{
files: '.prettierrc',
options: {
parser: 'json',
},
},
{
files: 'document.ejs',
options: {
parser: 'html',
},
},
],
};

@ -0,0 +1,13 @@
FROM circleci/node:latest-browsers
WORKDIR /usr/src/app
RUN npm config set registry https://registry.npmmirror.com
USER root
COPY package.json ./
RUN yarn
COPY ./ ./
RUN npm run test:all
CMD ["npm", "run", "build"]

@ -0,0 +1,187 @@
// https://umijs.org/config/
import { defineConfig } from '@umijs/max';
import { join } from 'path';
import defaultSettings from './defaultSettings';
import proxy from './proxy';
import routes from './routes';
const { REACT_APP_ENV,
API_SERVER,
SERVER_HOST,
FILE_SERVER_HOST,
WEBRTC_SERVER_HOST
} = process.env;
console.log(REACT_APP_ENV)
export default defineConfig({
/**
* @name hash
* @description build hash
* @doc https://umijs.org/docs/api/config#hash
*/
hash: true,
define: {
API_SERVER: API_SERVER,
SERVER_HOST: SERVER_HOST,
FILE_SERVER_HOST: FILE_SERVER_HOST,
WEBRTC_SERVER_HOST: WEBRTC_SERVER_HOST,
},
/**
* @name
* @description ie11 使
* @doc https://umijs.org/docs/api/config#targets
*/
// targets: {
// ie: 11,
// },
/**
* @name
* @description pathcomponentsroutesredirectwrapperstitle
* @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',
},
/**
* @name moment
* @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],
/**
* @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: 'Ant Design Pro',
layout: {
locale: true,
...defaultSettings,
},
/**
* @name moment2dayjs
* @description moment 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: true,
},
/**
* @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: '/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,
// },
// {
// requestLibPath: "import { request } from '@umijs/max'",
// schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json',
// projectName: 'swagger',
// },
// {
// requestLibPath: "import { request } from '@umijs/max'",
// // 或者使用在线的版本
// // schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json"
// // schemaPath: join(__dirname, 'oneapi.json'),
// schemaPath: 'http://localhost:8888/api/v1/swagger/doc.json',
// mock: false,
// apiPrefix: "'/api/v1'",
// projectName: 'device1',
// },
// {
// requestLibPath: "import { request } from '@umijs/max'",
// // 或者使用在线的版本
// // schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json"
// // schemaPath: join(__dirname, 'oneapi.json'),
// schemaPath: 'http://127.0.0.1:9000/swagger.json',
// mock: false,
// apiPrefix: "'/api/v1'",
// projectName: 'staff',
// },
],
mfsu: {
strategy: 'normal',
},
requestRecord: {},
});

@ -0,0 +1 @@
// 待启用 抽屉全局配置

@ -0,0 +1,60 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-13 14:19:57
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-22 13:15:04
* @FilePath: \general-ai-platform-web\config\defaultForm.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE2
*/
import { StepsFormProps } from "@ant-design/pro-components";
import { ReactNode } from "react";
// 通用表单配置
export const proFormCommonOptions: Record<string,any> = {
}
const formBoxMargin = 2 * 24
const formItemGap = 16
// Small 560
export const proFormSmallModelWidth: number = 560;
export const proFormSmallItemStyleProps: Record<string, any> = {
width: proFormSmallModelWidth - formBoxMargin, // 一列
// column2Width: (proFormSmallModelWidth - 2 * formBoxMargin)/2 , // 两列
};
// normal 804
export const proFormModelWidth: number = 804;
export const proFormItemStyleProps: Record<string, any> = {
width: proFormModelWidth - formBoxMargin, // 一列
column2Width: (proFormModelWidth - formBoxMargin - formItemGap)/2 , // 两列
};
// max 968
export const proFormMaxModelWidth: number = 968;
export const proFormMaxItemStyleProps: Record<string, any> = {
width: proFormMaxModelWidth - formBoxMargin,
column2Width: (proFormMaxModelWidth - formBoxMargin - formItemGap)/2 , // 两列
};
/**表单具体单项配置 */
// proFormList 新增一项按钮配置
export const proFormListCreatorButtonProps : {
creatorButtonText?: ReactNode;
position?: 'top' | 'bottom';
} = {
position: 'bottom',
creatorButtonText: '添加参数字段', // 设置新增一项数据的文案
}
// 分步表单统一配置
export const proFormStepsFormProps: StepsFormProps = {
stepsProps: {
labelPlacement: 'vertical',
}
}

@ -0,0 +1,32 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-28 14:13:05
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-28 17:48:37
* @FilePath: \general-ai-platform-web\config\defaultIcon.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%A
*/
import { proFormItemStyleProps } from './defaultForm';
// 分步表单统一配置
export const proIconSelectWrapStyle: React.CSSProperties = {
position: 'relative',
width: 290,
background: 'red',
left: 0,
};
export const proIconSelectStyle: React.CSSProperties = {
position: 'absolute',
left: '0',
padding: 16,
top: '5%',
width: '94%',
height: 500,
zIndex: 9,
boxShadow: '0px 4px 12px 0px rgba(0, 0, 0, 0.30)',
background: '#fff',
borderRadius: 4,
overflowY: 'scroll',
};

@ -0,0 +1,35 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-22 10:02:59
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-12-05 11:09:13
* @FilePath: \react-adpro-fabric\config\defaultSettings.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { ProLayoutProps } from '@ant-design/pro-components';
/**
* @name
*/
const Settings: ProLayoutProps & {
pwa?: boolean;
logo?: string;
} = {
navTheme: 'light',
// 拂晓蓝
colorPrimary: '#155BD4',
layout: 'mix',
contentWidth: 'Fluid',
fixedHeader: false,
fixSiderbar: true,
colorWeak: false,
title: 'fabric智能AI系统',
pwa: true,
logo: '/my_logo.svg',
iconfontUrl: '',
token: {
// 参见ts声明demo 见文档通过token 修改样式
//https://procomponents.ant.design/components/layout#%E9%80%9A%E8%BF%87-token-%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F
},
};
export default Settings;

@ -0,0 +1,46 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-13 11:32:26
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-21 13:36:39
* @FilePath: \general-ai-platform-web\config\defaultTable.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { ProColumns } from "@ant-design/pro-components";
import { PaginationProps } from "antd";
// 通用列表配置
export const proTableCommonOptions: Record<string,any> = {
scrollX: 'max-content', // 保证左右侧列的固定,并能保证没列标题不换行
scrollY: 500, // 保证列表高度固定
commscrollX: 1300,
commscrollY: 500, // 保证列表高度固定
searchLabelWidth: 'auto', // 整体对齐label根据实际字数自适应
}
// 操作栏位配置
export const proTableActionColumnOptions: Record<string,any> = {
dataIndex: 'option',
valueType: 'option',
align: 'center',
fixed: 'right',
}
// 分页器配置
export const proTablePaginationOptions: PaginationProps = {
showSizeChanger: true,
// showQuickJumper: true,
showTotal: (total) => `${total}`,
}
// 默认索引列配置
// export const proTableIndexColumnOptions : ProColumns = {
// title: '序号',
// dataIndex: 'index',
// valueType: 'index', // 增加该属性以添加边框
// fixed: 'left', // 将该列固定在左侧
// width: 70,
// align:'center'
// }

@ -0,0 +1,22 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-23 16:05:23
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-23 16:11:53
* @FilePath: \react-adpro-fabric\config\demoRoutes.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
export const demoRoutes = [
{
path: '/fabric',
name: 'fabric',
routes: [
{
name: 'fabricOfReactCavas1',
path: '/fabric/fabricOfReact/cavas1',
component: 'Demo/FabricOfReact/Cavas1',
access: 'canReadMenu',
},
]
}
]

@ -0,0 +1,593 @@
{
"openapi": "3.0.1",
"info": {
"title": "Ant Design Pro",
"version": "1.0.0"
},
"servers": [
{
"url": "http://localhost:8080/"
},
{
"url": "https://localhost:8080/"
}
],
"paths": {
"/api/currentUser": {
"get": {
"tags": ["api"],
"description": "获取当前的用户",
"operationId": "currentUser",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CurrentUser"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"x-swagger-router-controller": "api"
},
"/api/login/captcha": {
"post": {
"description": "发送验证码",
"operationId": "getFakeCaptcha",
"tags": ["login"],
"parameters": [
{
"name": "phone",
"in": "query",
"description": "手机号",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FakeCaptcha"
}
}
}
}
}
}
},
"/api/login/outLogin": {
"post": {
"description": "登录接口",
"operationId": "outLogin",
"tags": ["login"],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "object"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"x-swagger-router-controller": "api"
},
"/api/login/account": {
"post": {
"tags": ["login"],
"description": "登录接口",
"operationId": "login",
"requestBody": {
"description": "登录系统",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginParams"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginResult"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"x-codegen-request-body-name": "body"
},
"x-swagger-router-controller": "api"
},
"/api/notices": {
"summary": "getNotices",
"description": "NoticeIconItem",
"get": {
"tags": ["api"],
"operationId": "getNotices",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/NoticeIconList"
}
}
}
}
}
}
},
"/api/rule": {
"get": {
"tags": ["rule"],
"description": "获取规则列表",
"operationId": "rule",
"parameters": [
{
"name": "current",
"in": "query",
"description": "当前的页码",
"schema": {
"type": "number"
}
},
{
"name": "pageSize",
"in": "query",
"description": "页面的容量",
"schema": {
"type": "number"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RuleList"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"post": {
"tags": ["rule"],
"description": "新建规则",
"operationId": "addRule",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RuleListItem"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"put": {
"tags": ["rule"],
"description": "新建规则",
"operationId": "updateRule",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RuleListItem"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"delete": {
"tags": ["rule"],
"description": "删除规则",
"operationId": "removeRule",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "object"
}
}
}
},
"401": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
}
},
"x-swagger-router-controller": "api"
},
"/swagger": {
"x-swagger-pipe": "swagger_raw"
}
},
"components": {
"schemas": {
"CurrentUser": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"avatar": {
"type": "string"
},
"userid": {
"type": "string"
},
"email": {
"type": "string"
},
"signature": {
"type": "string"
},
"title": {
"type": "string"
},
"group": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
}
}
}
},
"notifyCount": {
"type": "integer",
"format": "int32"
},
"unreadCount": {
"type": "integer",
"format": "int32"
},
"country": {
"type": "string"
},
"access": {
"type": "string"
},
"geographic": {
"type": "object",
"properties": {
"province": {
"type": "object",
"properties": {
"label": {
"type": "string"
},
"key": {
"type": "string"
}
}
},
"city": {
"type": "object",
"properties": {
"label": {
"type": "string"
},
"key": {
"type": "string"
}
}
}
}
},
"address": {
"type": "string"
},
"phone": {
"type": "string"
}
}
},
"LoginResult": {
"type": "object",
"properties": {
"status": {
"type": "string"
},
"type": {
"type": "string"
},
"currentAuthority": {
"type": "string"
}
}
},
"PageParams": {
"type": "object",
"properties": {
"current": {
"type": "number"
},
"pageSize": {
"type": "number"
}
}
},
"RuleListItem": {
"type": "object",
"properties": {
"key": {
"type": "integer",
"format": "int32"
},
"disabled": {
"type": "boolean"
},
"href": {
"type": "string"
},
"avatar": {
"type": "string"
},
"name": {
"type": "string"
},
"owner": {
"type": "string"
},
"desc": {
"type": "string"
},
"callNo": {
"type": "integer",
"format": "int32"
},
"status": {
"type": "integer",
"format": "int32"
},
"updatedAt": {
"type": "string",
"format": "datetime"
},
"createdAt": {
"type": "string",
"format": "datetime"
},
"progress": {
"type": "integer",
"format": "int32"
}
}
},
"RuleList": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RuleListItem"
}
},
"total": {
"type": "integer",
"description": "列表的内容总数",
"format": "int32"
},
"success": {
"type": "boolean"
}
}
},
"FakeCaptcha": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"status": {
"type": "string"
}
}
},
"LoginParams": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
},
"autoLogin": {
"type": "boolean"
},
"type": {
"type": "string"
}
}
},
"ErrorResponse": {
"required": ["errorCode"],
"type": "object",
"properties": {
"errorCode": {
"type": "string",
"description": "业务约定的错误码"
},
"errorMessage": {
"type": "string",
"description": "业务上的错误信息"
},
"success": {
"type": "boolean",
"description": "业务上的请求是否成功"
}
}
},
"NoticeIconList": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/NoticeIconItem"
}
},
"total": {
"type": "integer",
"description": "列表的内容总数",
"format": "int32"
},
"success": {
"type": "boolean"
}
}
},
"NoticeIconItemType": {
"title": "NoticeIconItemType",
"description": "已读未读列表的枚举",
"type": "string",
"properties": {},
"enum": ["notification", "message", "event"]
},
"NoticeIconItem": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"extra": {
"type": "string",
"format": "any"
},
"key": { "type": "string" },
"read": {
"type": "boolean"
},
"avatar": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "string"
},
"datetime": {
"type": "string",
"format": "date"
},
"description": {
"type": "string"
},
"type": {
"extensions": {
"x-is-enum": true
},
"$ref": "#/components/schemas/NoticeIconItemType"
}
}
}
}
}
}

@ -0,0 +1,64 @@
/**
* @name
* @see
* -------------------------------
* The agent cannot take effect in the production environment
* so there is no configuration of the production environment
* For details, please see
* https://pro.ant.design/docs/deploy
*
* @doc https://umijs.org/docs/guides/proxy
*/
export default {
// 如果需要自定义本地开发服务器 请取消注释按需调整
// dev: {
// // localhost:8000/api/** -> https://preview.pro.ant.design/api/**
// '/api/': {
// // 要代理的地址
// target: 'https://preview.pro.ant.design',
// // 配置了这个可以从 http 代理到 https
// // 依赖 origin 的功能可能需要这个,比如 cookie
// changeOrigin: true,
// },
// },
dev: {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
'/api/v1/': {
// 要代理的地址
target: 'http://192.168.10.96:8888/',
// target: 'https://www.baidu.com',
// 配置了这个可以从 http 代理到 https
// 依赖 origin 的功能可能需要这个,比如 cookie
changeOrigin: true,
secure: false,
},
// '/video_save_path/': {
// // 要代理的地址
// target: 'http://192.168.10.96/',
// // target: 'https://www.baidu.com',
// // 配置了这个可以从 http 代理到 https
// // 依赖 origin 的功能可能需要这个,比如 cookie
// changeOrigin: true,
// secure: false,
// },
},
/**
* @name
* @doc https://github.com/chimurai/http-proxy-middleware
*/
test: {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
'/api/': {
target: 'https://proapi.azurewebsites.net',
changeOrigin: true,
pathRewrite: { '^': '' },
},
},
pre: {
'/api/': {
target: 'your pre url',
changeOrigin: true,
pathRewrite: { '^': '' },
},
},
};

@ -0,0 +1,37 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-22 10:02:59
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-12-20 14:40:04
* @FilePath: \react-adpro-fabric\config\routes.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/**
* @name umi
* @description path,components,routes,redirect,wrappers,name,icon
* @param path path :id *
* @param components location path React src/pages
* @param routes layout 使
* @param redirect
* @param wrappers
* @param name menu.ts menu.xxxx name login menu.ts menu.login
* @param icon https://ant.design/components/icon-cn 注意去除风格后缀和大小写,如想要配置图标为 <StepBackwardOutlined /> 则取值应为 stepBackward 或 StepBackward如想要配置图标为 <UserOutlined /> 则取值应为 user 或者 User
* @doc https://umijs.org/docs/guides/routes
*/
export default [
{
path: '/showInfo',
layout: false,
component: './404',
},
{
path: '/',
redirect: '/showInfo',
},
{
path: '*',
layout: false,
component: './404',
},
];

@ -0,0 +1,31 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-22 10:02:59
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-28 16:45:16
* @FilePath: \react-adpro-fabric\jest.config.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { configUmiAlias, createConfig } from '@umijs/max/test';
export default async () => {
const config = await configUmiAlias({
...createConfig({
target: 'browser',
}),
});
console.log(JSON.stringify(config));
return {
...config,
testEnvironmentOptions: {
...(config?.testEnvironmentOptions || {}),
url: 'http://localhost:8080',
},
setupFiles: [...(config.setupFiles || []), './tests/setupTests.jsx'],
globals: {
...config.globals,
localStorage: null,
},
};
};

@ -0,0 +1,11 @@
{
"compilerOptions": {
"jsx": "react-jsx",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

@ -0,0 +1,23 @@
// @ts-ignore
import { Request, Response } from 'express';
export default {
'POST /employee/createEmployee': (req: Request, res: Response) => {
res.status(200).send({});
},
'DELETE /employee/deleteEmployee': (req: Request, res: Response) => {
res.status(200).send({});
},
'DELETE /employee/deleteEmployeeByIds': (req: Request, res: Response) => {
res.status(200).send({});
},
'POST /employee/getEmployeeById': (req: Request, res: Response) => {
res.status(200).send({});
},
'POST /employee/getEmployeeList': (req: Request, res: Response) => {
res.status(200).send({});
},
'PUT /employee/updateEmployee': (req: Request, res: Response) => {
res.status(200).send({});
},
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,176 @@
import { Request, Response } from 'express';
import moment from 'moment';
import { parse } from 'url';
// mock tableListDataSource
const genList = (current: number, pageSize: number) => {
const tableListDataSource: API.RuleListItem[] = [];
for (let i = 0; i < pageSize; i += 1) {
const index = (current - 1) * 10 + i;
tableListDataSource.push({
key: index,
disabled: i % 6 === 0,
href: 'https://ant.design',
avatar: [
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
][i % 2],
name: `TradeCode ${index}`,
owner: '曲丽丽',
desc: '这是一段描述',
callNo: Math.floor(Math.random() * 1000),
status: Math.floor(Math.random() * 10) % 4,
updatedAt: moment().format('YYYY-MM-DD'),
createdAt: moment().format('YYYY-MM-DD'),
progress: Math.ceil(Math.random() * 100),
});
}
tableListDataSource.reverse();
return tableListDataSource;
};
let tableListDataSource = genList(1, 100);
function getRule(req: Request, res: Response, u: string) {
let realUrl = u;
if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') {
realUrl = req.url;
}
const { current = 1, pageSize = 10 } = req.query;
const params = parse(realUrl, true).query as unknown as API.PageParams &
API.RuleListItem & {
sorter: any;
filter: any;
};
let dataSource = [...tableListDataSource].slice(
((current as number) - 1) * (pageSize as number),
(current as number) * (pageSize as number),
);
if (params.sorter) {
const sorter = JSON.parse(params.sorter);
dataSource = dataSource.sort((prev, next) => {
let sortNumber = 0;
(Object.keys(sorter) as Array<keyof API.RuleListItem>).forEach((key) => {
let nextSort = next?.[key] as number;
let preSort = prev?.[key] as number;
if (sorter[key] === 'descend') {
if (preSort - nextSort > 0) {
sortNumber += -1;
} else {
sortNumber += 1;
}
return;
}
if (preSort - nextSort > 0) {
sortNumber += 1;
} else {
sortNumber += -1;
}
});
return sortNumber;
});
}
if (params.filter) {
const filter = JSON.parse(params.filter as any) as {
[key: string]: string[];
};
if (Object.keys(filter).length > 0) {
dataSource = dataSource.filter((item) => {
return (Object.keys(filter) as Array<keyof API.RuleListItem>).some((key) => {
if (!filter[key]) {
return true;
}
if (filter[key].includes(`${item[key]}`)) {
return true;
}
return false;
});
});
}
}
if (params.name) {
dataSource = dataSource.filter((data) => data?.name?.includes(params.name || ''));
}
const result = {
data: dataSource,
total: tableListDataSource.length,
success: true,
pageSize,
current: parseInt(`${params.current}`, 10) || 1,
};
return res.json(result);
}
function postRule(req: Request, res: Response, u: string, b: Request) {
let realUrl = u;
if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') {
realUrl = req.url;
}
const body = (b && b.body) || req.body;
const { method, name, desc, key } = body;
switch (method) {
/* eslint no-case-declarations:0 */
case 'delete':
tableListDataSource = tableListDataSource.filter((item) => key.indexOf(item.key) === -1);
break;
case 'post':
(() => {
const i = Math.ceil(Math.random() * 10000);
const newRule: API.RuleListItem = {
key: tableListDataSource.length,
href: 'https://ant.design',
avatar: [
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
][i % 2],
name,
owner: '曲丽丽',
desc,
callNo: Math.floor(Math.random() * 1000),
status: Math.floor(Math.random() * 10) % 2,
updatedAt: moment().format('YYYY-MM-DD'),
createdAt: moment().format('YYYY-MM-DD'),
progress: Math.ceil(Math.random() * 100),
};
tableListDataSource.unshift(newRule);
return res.json(newRule);
})();
return;
case 'update':
(() => {
let newRule = {};
tableListDataSource = tableListDataSource.map((item) => {
if (item.key === key) {
newRule = { ...item, desc, name };
return { ...item, desc, name };
}
return item;
});
return res.json(newRule);
})();
return;
default:
break;
}
const result = {
list: tableListDataSource,
pagination: {
total: tableListDataSource.length,
},
};
res.json(result);
}
export default {
'GET /api/rule': getRule,
'POST /api/rule': postRule,
};

@ -0,0 +1,68 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-09 14:29:49
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-09 15:34:50
* @FilePath: \general-ai-platform-web\mock\modelDetail.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { Request, Response } from 'express';
import { parse } from 'url';
// mock tableListDataSource
const genData = (params: Record<string, any>): Record<string, any> => {
const data: Record<string, any> = {
categoryFkId: 2,
createTime: '2023-10-20T06:23:56.158622Z',
defaultVersionFkId: null,
id: params.id,
name: '离岗',
remark: '',
updateTime: '2023-10-20T06:23:56.158622Z',
};
// key: index,
// disabled: i % 6 === 0,
// href: 'https://ant.design',
// avatar: [
// 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
// 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
// ][i % 2],
// name: `TradeCode ${index}`,
// owner: '曲丽丽',
// desc: '这是一段描述',
// callNo: Math.floor(Math.random() * 1000),
// status: Math.floor(Math.random() * 10) % 4,
// updatedAt: moment().format('YYYY-MM-DD'),
// createdAt: moment().format('YYYY-MM-DD'),
// progress: Math.ceil(Math.random() * 100),
return data;
};
function getModelDetail(req: Request, res: Response, u: string, b: Request) {
// let realUrl = u;
// if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') {
// realUrl = req.url;
// }
// const body = (b && b.body) || req.body;
// const { method, name, desc, key } = body;
// const params = parse(realUrl, true).query as unknown as API.PageParams &
// API.RuleListItem & {
// sorter: any;
// filter: any;
// };
// console.log(req, 'getModelDetailApi');
const result = {
data: genData({id: 2}),
success: true,
msg: '获取成功',
};
return res.json(result);
}
export default {
'GET /api/v1/mock/model/detail': getModelDetail,
};

@ -0,0 +1,115 @@
import { Request, Response } from 'express';
const getNotices = (req: Request, res: Response) => {
res.json({
data: [
{
id: '000000001',
avatar:
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/MSbDR4FR2MUAAAAAAAAAAAAAFl94AQBr',
title: '你收到了 14 份新周报',
datetime: '2017-08-09',
type: 'notification',
},
{
id: '000000002',
avatar:
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/hX-PTavYIq4AAAAAAAAAAAAAFl94AQBr',
title: '你推荐的 曲妮妮 已通过第三轮面试',
datetime: '2017-08-08',
type: 'notification',
},
{
id: '000000003',
avatar:
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/jHX5R5l3QjQAAAAAAAAAAAAAFl94AQBr',
title: '这种模板可以区分多种通知类型',
datetime: '2017-08-07',
read: true,
type: 'notification',
},
{
id: '000000004',
avatar:
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/Wr4mQqx6jfwAAAAAAAAAAAAAFl94AQBr',
title: '左侧图标用于区分不同的类型',
datetime: '2017-08-07',
type: 'notification',
},
{
id: '000000005',
avatar:
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/Mzj_TbcWUj4AAAAAAAAAAAAAFl94AQBr',
title: '内容不要超过两行字,超出时自动截断',
datetime: '2017-08-07',
type: 'notification',
},
{
id: '000000006',
avatar:
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/eXLzRbPqQE4AAAAAAAAAAAAAFl94AQBr',
title: '曲丽丽 评论了你',
description: '描述信息描述信息描述信息',
datetime: '2017-08-07',
type: 'message',
clickClose: true,
},
{
id: '000000007',
avatar:
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/w5mRQY2AmEEAAAAAAAAAAAAAFl94AQBr',
title: '朱偏右 回复了你',
description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像',
datetime: '2017-08-07',
type: 'message',
clickClose: true,
},
{
id: '000000008',
avatar:
'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/wPadR5M9918AAAAAAAAAAAAAFl94AQBr',
title: '标题',
description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像',
datetime: '2017-08-07',
type: 'message',
clickClose: true,
},
{
id: '000000009',
title: '任务名称',
description: '任务需要在 2017-01-12 20:00 前启动',
extra: '未开始',
status: 'todo',
type: 'event',
},
{
id: '000000010',
title: '第三方紧急代码变更',
description: '冠霖提交于 2017-01-06需在 2017-01-07 前完成代码变更任务',
extra: '马上到期',
status: 'urgent',
type: 'event',
},
{
id: '000000011',
title: '信息安全考试',
description: '指派竹尔于 2017-01-09 前完成更新并发布',
extra: '已耗时 8 天',
status: 'doing',
type: 'event',
},
{
id: '000000012',
title: 'ABCD 版本发布',
description: '冠霖提交于 2017-01-06需在 2017-01-07 前完成代码变更任务',
extra: '进行中',
status: 'processing',
type: 'event',
},
],
});
};
export default {
'GET /api/notices': getNotices,
};

@ -0,0 +1,324 @@
module.exports = {
'GET /api/currentUser': {
data: {
name: 'Serati Ma',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png',
userid: '00000001',
email: 'antdesign@alipay.com',
signature: '海纳百川,有容乃大',
title: '交互专家',
group: '蚂蚁金服某某某事业群某某平台部某某技术部UED',
tags: [
{ key: '0', label: '很有想法的' },
{ key: '1', label: '专注设计' },
{ key: '2', label: '辣~' },
{ key: '3', label: '大长腿' },
{ key: '4', label: '川妹子' },
{ key: '5', label: '海纳百川' },
],
notifyCount: 12,
unreadCount: 11,
country: 'China',
geographic: {
province: { label: '浙江省', key: '330000' },
city: { label: '杭州市', key: '330100' },
},
address: '西湖区工专路 77 号',
phone: '0752-268888888',
},
},
'GET /api/rule': {
data: [
{
key: 99,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 99',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 503,
status: '0',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 81,
},
{
key: 98,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 98',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 164,
status: '0',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 12,
},
{
key: 97,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 97',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 174,
status: '1',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 81,
},
{
key: 96,
disabled: true,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 96',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 914,
status: '0',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 7,
},
{
key: 95,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 95',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 698,
status: '2',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 82,
},
{
key: 94,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 94',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 488,
status: '1',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 14,
},
{
key: 93,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 93',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 580,
status: '2',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 77,
},
{
key: 92,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 92',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 244,
status: '3',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 58,
},
{
key: 91,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 91',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 959,
status: '0',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 66,
},
{
key: 90,
disabled: true,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 90',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 958,
status: '0',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 72,
},
{
key: 89,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 89',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 301,
status: '2',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 2,
},
{
key: 88,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 88',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 277,
status: '1',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 12,
},
{
key: 87,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 87',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 810,
status: '1',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 82,
},
{
key: 86,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 86',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 780,
status: '3',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 22,
},
{
key: 85,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 85',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 705,
status: '3',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 12,
},
{
key: 84,
disabled: true,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 84',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 203,
status: '0',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 79,
},
{
key: 83,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 83',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 491,
status: '2',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 59,
},
{
key: 82,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 82',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 73,
status: '0',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 100,
},
{
key: 81,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
name: 'TradeCode 81',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 406,
status: '3',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 61,
},
{
key: 80,
disabled: false,
href: 'https://ant.design',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
name: 'TradeCode 80',
owner: '曲丽丽',
desc: '这是一段描述',
callNo: 112,
status: '2',
updatedAt: '2022-12-06T05:00:57.040Z',
createdAt: '2022-12-06T05:00:57.040Z',
progress: 20,
},
],
total: 100,
success: true,
pageSize: 20,
current: 1,
},
'POST /api/login/outLogin': { data: {}, success: true },
'POST /api/login/account': {
status: 'ok',
type: 'account',
currentAuthority: 'admin',
},
};

@ -0,0 +1,5 @@
export default {
'/api/auth_routes': {
'/form/advanced-form': { authority: ['admin', 'user'] },
},
};

@ -0,0 +1,203 @@
import { Request, Response } from 'express';
const waitTime = (time: number = 100) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, time);
});
};
async function getFakeCaptcha(req: Request, res: Response) {
await waitTime(2000);
return res.json('captcha-xxx');
}
const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION } = process.env;
/**
*
* current user access if is '', user need login
* pro
*/
let access = ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site' ? 'admin' : '';
const getAccess = () => {
return access;
};
// 代码中会兼容本地 service mock 以及部署站点的静态数据
export default {
// 支持值为 Object 和 Array
'GET /api/currentUser': (req: Request, res: Response) => {
if (!getAccess()) {
res.status(401).send({
data: {
isLogin: false,
},
errorCode: '401',
errorMessage: '请先登录!',
success: true,
});
return;
}
res.send({
success: true,
data: {
name: 'Serati Ma',
avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
userid: '00000001',
email: 'antdesign@alipay.com',
signature: '海纳百川,有容乃大',
title: '交互专家',
group: '蚂蚁金服某某某事业群某某平台部某某技术部UED',
tags: [
{
key: '0',
label: '很有想法的',
},
{
key: '1',
label: '专注设计',
},
{
key: '2',
label: '辣~',
},
{
key: '3',
label: '大长腿',
},
{
key: '4',
label: '川妹子',
},
{
key: '5',
label: '海纳百川',
},
],
notifyCount: 12,
unreadCount: 11,
country: 'China',
access: getAccess(),
geographic: {
province: {
label: '浙江省',
key: '330000',
},
city: {
label: '杭州市',
key: '330100',
},
},
address: '西湖区工专路 77 号',
phone: '0752-268888888',
},
});
},
// GET POST 可省略
'GET /api/users': [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
],
'POST /api/login/account': async (req: Request, res: Response) => {
const { password, username, type } = req.body;
await waitTime(2000);
if (password === 'ant.design' && username === 'admin') {
res.send({
status: 'ok',
type,
currentAuthority: 'admin',
});
access = 'admin';
return;
}
if (password === 'ant.design' && username === 'user') {
res.send({
status: 'ok',
type,
currentAuthority: 'user',
});
access = 'user';
return;
}
if (type === 'mobile') {
res.send({
status: 'ok',
type,
currentAuthority: 'admin',
});
access = 'admin';
return;
}
res.send({
status: 'error',
type,
currentAuthority: 'guest',
});
access = 'guest';
},
'POST /api/login/outLogin': (req: Request, res: Response) => {
access = '';
res.send({ data: {}, success: true });
},
'POST /api/register': (req: Request, res: Response) => {
res.send({ status: 'ok', currentAuthority: 'user', success: true });
},
'GET /api/500': (req: Request, res: Response) => {
res.status(500).send({
timestamp: 1513932555104,
status: 500,
error: 'error',
message: 'error',
path: '/base/category/list',
});
},
'GET /api/404': (req: Request, res: Response) => {
res.status(404).send({
timestamp: 1513932643431,
status: 404,
error: 'Not Found',
message: 'No message available',
path: '/base/category/list/2121212',
});
},
'GET /api/403': (req: Request, res: Response) => {
res.status(403).send({
timestamp: 1513932555104,
status: 403,
error: 'Forbidden',
message: 'Forbidden',
path: '/base/category/list',
});
},
'GET /api/401': (req: Request, res: Response) => {
res.status(401).send({
timestamp: 1513932555104,
status: 401,
error: 'Unauthorized',
message: 'Unauthorized',
path: '/base/category/list',
});
},
'GET /api/login/captcha': getFakeCaptcha,
};

@ -0,0 +1,140 @@
{
"name": "ant-design-pro",
"version": "6.0.0",
"private": true,
"description": "An out-of-box UI solution for enterprise applications",
"scripts": {
"analyze": "cross-env ANALYZE=1 max build",
"build": "cross-env API_ENV=production max build",
"deploy": "npm run build && npm run gh-pages",
"dev": "npm run start:dev --port 8080",
"gh-pages": "gh-pages -d dist",
"i18n-remove": "pro i18n-remove --locale=zh-CN --write",
"postinstall": "max setup",
"jest": "jest",
"lint": "npm run lint:js && npm run lint:prettier && npm run tsc",
"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 ",
"lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src",
"lint:prettier": "prettier -c --write \"**/**.{js,jsx,tsx,ts,less,md,json}\" --end-of-line auto",
"openapi": "max openapi",
"prepare": "husky install",
"prettier": "prettier -c --write \"**/**.{js,jsx,tsx,ts,less,md,json}\"",
"preview": "npm run build && max preview --port 8080",
"record": "cross-env NODE_ENV=development REACT_APP_ENV=test max record --scene=login",
"serve": "umi-serve",
"start": "cross-env UMI_ENV=dev max dev",
"start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev max dev",
"start:no-mock": "cross-env MOCK=none UMI_ENV=dev max dev",
"start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev max dev",
"start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev",
"test": "jest",
"test:coverage": "npm run jest -- --coverage",
"test:update": "npm run jest -- -u",
"tsc": "tsc --noEmit"
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js",
"**/*.{js,jsx,tsx,ts,less,md,json}": [
"prettier --write"
]
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 10"
],
"dependencies": {
"@ant-design/charts": "^1.4.2",
"@ant-design/icons": "^4.8.0",
"@ant-design/pro-components": "^2.6.29",
"@ant-design/use-emotion-css": "1.0.4",
"@umijs/route-utils": "^2.2.2",
"antd": "^5.5.1",
"classnames": "^2.3.2",
"echarts": "^5.4.3",
"echarts-for-react": "^3.0.2",
"fabric": "^5.3.0",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"omit.js": "^2.0.2",
"prop-types": "^15.8.1",
"querystring": "^0.2.1",
"rc-menu": "^9.9.2",
"rc-util": "^5.32.2",
"react": "^18.2.0",
"react-cookies": "^0.1.1",
"react-dev-inspector": "^1.8.4",
"react-dom": "^18.2.0",
"react-fabricjs": "^0.1.6",
"react-helmet-async": "^1.3.0",
"uuid": "^9.0.1",
"video.js": "^8.5.2",
"webrtc-streamer": "^0.8.3-4-g2d0afce"
},
"devDependencies": {
"@ant-design/pro-cli": "^2.1.5",
"@testing-library/react": "^13.4.0",
"@types/classnames": "^2.3.1",
"@types/express": "^4.17.17",
"@types/fabric": "^5.3.6",
"@types/history": "^4.7.11",
"@types/jest": "^29.5.1",
"@types/js-yaml": "^4.0.8",
"@types/lodash": "^4.14.195",
"@types/react": "^18.2.7",
"@types/react-dom": "^18.2.4",
"@types/react-helmet": "^6.1.6",
"@umijs/fabric": "^2.14.1",
"@umijs/lint": "^4.0.69",
"@umijs/max": "^4.0.69",
"cross-env": "^7.0.3",
"eslint": "^8.41.0",
"express": "^4.18.2",
"gh-pages": "^3.2.3",
"husky": "^7.0.4",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"lint-staged": "^10.5.4",
"mockjs": "^1.1.0",
"prettier": "^2.8.8",
"swagger-ui-dist": "^4.19.0",
"ts-node": "^10.9.1",
"typescript": "^5.0.0",
"umi-presets-pro": "^2.0.3"
},
"engines": {
"node": ">=12.0.0"
},
"create-umi": {
"ignoreScript": [
"docker*",
"functions*",
"site",
"generateMock"
],
"ignoreDependencies": [
"netlify*",
"serverless"
],
"ignore": [
".dockerignore",
".git",
".github",
".gitpod.yml",
"CODE_OF_CONDUCT.md",
"Dockerfile",
"Dockerfile.*",
"lambda",
"LICENSE",
"netlify.toml",
"README.*.md",
"azure-pipelines.yml",
"docker",
"CNAME",
"create-umi"
]
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1 @@
preview.pro.ant.design

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.6/fabric.min.js"></script>
<title>Fabric.js Text Editing</title>
</head>
<style>
body {
background: ivory;
}
</style>
<body>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.js"></script> -->
<canvas id="c" width="1300" height="1200" ></canvas>
<script>
const canvas = new fabric.Canvas('c')
fabric.RectWithText = fabric.util.createClass(fabric.Rect, {
type: 'rectWithText',
text: null,
textOffsetLeft: 0,
textOffsetTop: 0,
_prevObjectStacking: null,
_prevAngle: 0,
recalcTextPosition: function () {
const sin = Math.sin(fabric.util.degreesToRadians(this.angle))
const cos = Math.cos(fabric.util.degreesToRadians(this.angle))
const newTop = sin * this.textOffsetLeft + cos * this.textOffsetTop
const newLeft = cos * this.textOffsetLeft - sin * this.textOffsetTop
const rectLeftTop = this.getPointByOrigin('left', 'top')
this.text.set('left', rectLeftTop.x + newLeft)
this.text.set('top', rectLeftTop.y + newTop)
},
initialize: function (rectOptions, textOptions, text) {
this.callSuper('initialize', rectOptions)
this.text = new fabric.Textbox(text, {
...textOptions,
selectable: false,
evented: false,
})
this.textOffsetLeft = this.text.left - this.left
this.textOffsetTop = this.text.top - this.top
this.on('moving', () => {
this.recalcTextPosition()
})
this.on('rotating', () => {
this.text.rotate(this.text.angle + this.angle - this._prevAngle)
this.recalcTextPosition()
this._prevAngle = this.angle
})
this.on('scaling', (e) => {
this.recalcTextPosition()
})
this.on('added', () => {
this.canvas.add(this.text)
})
this.on('removed', () => {
this.canvas.remove(this.text)
})
this.on('mousedown:before', () => {
this._prevObjectStacking = this.canvas.preserveObjectStacking
this.canvas.preserveObjectStacking = true
})
//双击
this.on('mousedblclick', () => {
this.text.selectable = true
this.text.evented = true
this.canvas.setActiveObject(this.text)
this.text.enterEditing()
this.selectable = false
})
this.on('deselected', () => {
this.canvas.preserveObjectStacking = this._prevObjectStacking
})
this.text.on('editing:exited', () => {
this.text.selectable = false
this.text.evented = false
this.selectable = true
})
}
})
const rectOptions = {
left: 10,
top: 10,
width: 200,
height: 75,
fill: 'rgba(30, 30, 30, 0.3)',
}
const textOptions = {
left: 35,
top: 30,
width: 150,
fill: 'white',
shadow: new fabric.Shadow({
color: 'rgba(34, 34, 100, 0.4)',
blur: 2,
offsetX: -2,
offsetY: 2
}),
fontSize: 30,
}
const rectWithText = new fabric.RectWithText(rectOptions, textOptions, 'Some text')
canvas.add(rectWithText)
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

@ -0,0 +1,24 @@
<svg width="64" height="24" viewBox="0 0 64 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_3180_54416" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="64" height="24">
<rect width="64" height="24" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_3180_54416)">
<path d="M14.039 4.05812L11.9366 4.49908C11.8873 4.51252 11.8707 4.57396 11.9072 4.6098L13.5648 6.2674C13.6006 6.30324 13.6627 6.28724 13.6755 6.23796L14.1203 4.1394C14.1337 4.09012 14.0883 4.04532 14.039 4.05812Z" fill="#E42F2F"/>
<path d="M15.1781 2.93749L12.133 3.75349C12.0972 3.76309 12.0856 3.80789 12.1112 3.83413L14.3404 6.06325C14.3666 6.08949 14.4114 6.07733 14.421 6.04149L15.237 2.99637C15.2466 2.96053 15.214 2.92789 15.1781 2.93749Z" fill="#FAEC18"/>
<path d="M21.4489 12.7755L17.8688 9.19532L16.4736 7.80013C16.3801 7.70669 16.2284 7.70669 16.1344 7.80013L10.0608 13.8737C9.9494 13.9851 9.76828 13.9851 9.65692 13.8737L8.0006 12.2174C7.88924 12.106 7.88924 11.9249 8.0006 11.8136L13.0803 6.73388C13.1737 6.64044 13.1737 6.48877 13.0803 6.39469L11.7017 5.01612C11.6083 4.92268 11.4566 4.92268 11.3625 5.01612L4.47804 11.9019C4.3846 11.9953 4.3846 12.147 4.47804 12.2411L8.10108 15.8641L9.49628 17.2593C9.58972 17.3528 9.7414 17.3528 9.83548 17.2593L16.1657 10.9291C16.2771 10.8177 16.4582 10.8177 16.5696 10.9291L18.2259 12.5854C18.3372 12.6968 18.3372 12.8779 18.2259 12.9892L11.8956 19.3195C11.8022 19.4129 11.8022 19.5646 11.8956 19.6587L13.2313 20.9944C13.3248 21.0878 13.4764 21.0878 13.5705 20.9944L21.4496 13.1153C21.5424 13.0206 21.5424 12.8689 21.4489 12.7755Z" fill="#154DDD"/>
<path d="M33.2839 6.32767H32.0116V5.51871H29.5962V6.21951H28.3239V5.51871H26.1569L26.0596 4.41919H28.3239V3.58911H29.5962V4.41919H32.0116V3.58911H33.2839V4.41919H35.6884V5.51871H33.2839V6.32767ZM26.0596 11.0611L27.0087 8.64575H28.2164L27.3217 11.0611H26.0596ZM33.8445 11.6109C33.7581 12.441 33.2193 12.9587 32.3137 13.0125C31.785 13.0554 30.9441 12.9907 30.2433 12.8723L29.9629 11.8048C30.5882 11.9232 31.3217 11.9776 31.7633 11.945C32.281 11.9232 32.5287 11.6864 32.5613 11.2224C32.6369 10.2842 32.626 9.14111 32.5613 8.24639C32.5505 8.13887 32.5185 8.09535 32.4103 8.09535H30.5127C30.3725 10.6938 29.2621 11.977 26.5985 13.2819L26.2644 12.064C28.162 11.1046 29.0567 9.97247 29.2186 8.09599H26.8468L26.7604 7.01759H29.2404V6.30591H30.5345V7.01759H33.0144C33.5213 7.01759 33.8017 7.32991 33.8445 7.81567C33.8663 8.02047 33.8765 8.21439 33.8874 8.41983H35.0624L35.9252 11.072H34.6209L33.8983 8.65663C33.9629 9.70239 33.9412 10.727 33.8445 11.6109Z" fill="#154DDD"/>
<path d="M39.57 9.79973V9.85349C39.57 10.8884 39.538 11.8913 39.2033 13.2391H37.8555C38.3406 11.5137 38.3515 10.4141 38.3515 9.19557V4.51589C38.3515 4.03077 38.6427 3.76133 39.1604 3.76133H40.8961C41.4139 3.76133 41.7044 4.01989 41.7044 4.51589V12.1716C41.7044 12.7649 41.2948 13.1309 40.6804 13.1745C40.3675 13.1962 40.0443 13.1527 39.8395 13.0989L39.57 11.9885C39.7428 12.0314 39.9905 12.0532 40.1736 12.0532C40.3784 12.0532 40.4865 11.9348 40.4865 11.7511V9.79973H39.57ZM40.4865 4.96902C40.4865 4.90438 40.4436 4.86086 40.379 4.86086H39.6891C39.6244 4.86086 39.5707 4.90374 39.5707 4.96902V6.32773H40.4871V4.96902H40.4865ZM40.4865 7.31973H39.57V8.80773H40.4865V7.31973ZM47.6993 11.8593V12.9805H42.082L41.9745 11.8593H44.3252V9.67046H42.5896L42.4814 8.54917H44.3252V6.53254H43.387C43.2897 6.97478 43.1713 7.39525 43.0203 7.79397H41.8343C42.2439 6.65093 42.4596 5.45413 42.4923 4.07429H43.6462C43.6353 4.53765 43.6033 4.99077 43.5598 5.41125H44.3252V3.54565H45.5867V5.41125H47.3659V6.53254H45.5867V8.54917H47.3012V9.67046H45.5867V11.8593H47.6993Z" fill="#154DDD"/>
<path d="M59.5924 11.9886L59.2039 13.3364C56.8212 12.3335 55.3978 11.5143 54.6433 9.9617C53.8887 11.4171 52.4007 12.4846 49.9853 13.3255L49.6404 12.0315C52.3361 10.9748 53.4356 10.0692 53.8023 8.47306H49.9425L49.8241 7.33002H53.9322C53.9431 7.18986 53.9431 7.03882 53.9431 6.88778V5.19498H50.6113L50.5037 4.09546H58.8058V5.19498H55.2577V7.14634V7.32938H59.3869V8.47242H55.3325C55.9482 10.3604 57.5329 11.2231 59.5924 11.9886Z" fill="#154DDD"/>
<path d="M25.8777 18.3961L26.5938 18.3277C26.6367 18.5632 26.7244 18.7366 26.8562 18.8467C26.9881 18.9574 27.166 19.0125 27.3894 19.0125C27.6262 19.0125 27.8054 18.9632 27.925 18.8653C28.0454 18.7667 28.1055 18.6521 28.1055 18.5203C28.1055 18.4358 28.0799 18.3641 28.0294 18.3046C27.9788 18.2451 27.8905 18.1939 27.7644 18.1498C27.678 18.1203 27.4815 18.0685 27.175 17.9936C26.7801 17.8976 26.5036 17.7798 26.3442 17.6403C26.1202 17.4438 26.0082 17.2038 26.0082 16.9209C26.0082 16.7392 26.0607 16.5689 26.1663 16.4102C26.2719 16.2515 26.423 16.1312 26.6214 16.048C26.8198 15.9654 27.0585 15.9238 27.3388 15.9238C27.7964 15.9238 28.1407 16.0224 28.3724 16.2189C28.6041 16.4153 28.725 16.6777 28.7366 17.0061L28.0006 17.0381C27.9692 16.8544 27.9014 16.7226 27.7977 16.6419C27.694 16.5613 27.5385 16.5216 27.3311 16.5216C27.1174 16.5216 26.9497 16.5645 26.8287 16.6509C26.7506 16.7059 26.7116 16.7801 26.7116 16.8729C26.7116 16.9574 26.7481 17.0298 26.821 17.0899C26.9138 17.1661 27.1391 17.2461 27.4975 17.3286C27.8559 17.4112 28.1202 17.497 28.2924 17.5859C28.4646 17.6749 28.5983 17.7958 28.695 17.9488C28.7922 18.1024 28.8402 18.2918 28.8402 18.5178C28.8402 18.7226 28.782 18.9145 28.6662 19.0931C28.5503 19.2717 28.3858 19.4048 28.174 19.4918C27.9615 19.5789 27.6972 19.6224 27.3804 19.6224C26.9196 19.6224 26.5657 19.5181 26.3186 19.3094C26.0735 19.1001 25.9263 18.7961 25.8777 18.3961Z" fill="#154DDD"/>
<path d="M29.3547 15.9854H30.0907V17.9207C30.0907 18.2279 30.0997 18.427 30.1183 18.5178C30.1496 18.6644 30.2245 18.7815 30.3435 18.8698C30.4619 18.9582 30.6239 19.0029 30.8299 19.0029C31.0386 19.0029 31.196 18.9614 31.3023 18.8775C31.4085 18.7937 31.4725 18.6913 31.4936 18.569C31.5154 18.4474 31.5263 18.2445 31.5263 17.9623V15.9854H32.2623V17.8625C32.2623 18.2913 32.2424 18.5946 32.2027 18.7719C32.1631 18.9492 32.0895 19.0983 31.9826 19.2206C31.8757 19.3428 31.7323 19.4394 31.5538 19.5118C31.3746 19.5841 31.141 19.6199 30.8523 19.6199C30.5042 19.6199 30.2399 19.5802 30.06 19.5015C29.8802 19.4228 29.7381 19.3204 29.6338 19.1943C29.5295 19.0682 29.4603 18.9364 29.4271 18.7981C29.3791 18.5933 29.3547 18.2913 29.3547 17.8913V15.9854Z" fill="#154DDD"/>
<path d="M32.9363 19.559V15.9858H34.1177C34.5651 15.9858 34.8569 16.0038 34.9932 16.0396C35.2019 16.0934 35.3772 16.2098 35.518 16.389C35.6588 16.5689 35.7292 16.8006 35.7292 17.0847C35.7292 17.3042 35.6889 17.4886 35.6076 17.6383C35.5264 17.7881 35.4233 17.9052 35.2979 17.9903C35.1724 18.0754 35.0457 18.1318 34.9164 18.1599C34.7404 18.1938 34.4864 18.2111 34.1529 18.2111H33.6729V19.559H32.9363ZM33.6729 16.59V17.6038H34.0755C34.3654 17.6038 34.5593 17.5852 34.6572 17.5474C34.7552 17.5103 34.832 17.4514 34.887 17.3721C34.9427 17.2927 34.9702 17.1999 34.9702 17.0943C34.9702 16.9644 34.9312 16.8569 34.8531 16.7724C34.775 16.6879 34.6764 16.6348 34.5574 16.6137C34.4697 16.5977 34.2931 16.5894 34.0275 16.5894H33.6729V16.59Z" fill="#154DDD"/>
<path d="M36.2317 19.559V15.9858H38.935V16.5906H36.9677V17.383H38.7981V17.9852H36.9677V18.958H39.0048V19.5602H36.2317V19.559Z" fill="#154DDD"/>
<path d="M39.5295 19.559V15.9858H41.079C41.4687 15.9858 41.7516 16.0178 41.9283 16.0818C42.1049 16.1458 42.2463 16.2604 42.3519 16.4242C42.4575 16.5881 42.5113 16.7762 42.5113 16.9874C42.5113 17.2556 42.4307 17.477 42.27 17.6518C42.1094 17.8265 41.8687 17.9366 41.5487 17.982C41.7081 18.0729 41.8393 18.1727 41.943 18.2815C42.0467 18.3903 42.1862 18.5836 42.3622 18.8614L42.8076 19.5583H41.927L41.3945 18.7807C41.2057 18.503 41.0764 18.3276 41.0067 18.2553C40.9369 18.183 40.8633 18.1337 40.7852 18.1068C40.7071 18.0799 40.5836 18.0665 40.4147 18.0665H40.2655V19.5583H39.5295V19.559ZM40.2662 17.4969H40.8108C41.1641 17.4969 41.3843 17.4822 41.4726 17.4527C41.5609 17.4233 41.6294 17.3734 41.6787 17.3017C41.7279 17.23 41.7535 17.141 41.7535 17.0335C41.7535 16.9132 41.7209 16.8159 41.655 16.7423C41.5891 16.6687 41.4969 16.6214 41.3779 16.6022C41.3183 16.5938 41.1391 16.59 40.8409 16.59H40.2662V17.4969Z" fill="#154DDD"/>
<path d="M43.9417 19.559L42.6387 15.9858H43.4368L44.3596 18.6303L45.2524 15.9858H46.0332L44.7276 19.559H43.9417Z" fill="#154DDD"/>
<path d="M46.2847 19.559V15.9858H47.0207V19.559H46.2847Z" fill="#154DDD"/>
<path d="M47.4341 18.3961L48.1502 18.3277C48.1931 18.5632 48.2808 18.7366 48.4126 18.8467C48.5445 18.9574 48.7224 19.0125 48.9464 19.0125C49.1832 19.0125 49.3618 18.9632 49.4821 18.8653C49.6024 18.7667 49.6626 18.6521 49.6626 18.5203C49.6626 18.4358 49.637 18.3641 49.5864 18.3046C49.5358 18.2451 49.4475 18.1939 49.3214 18.1498C49.235 18.1203 49.0386 18.0685 48.732 17.9936C48.3371 17.8976 48.0606 17.7798 47.9013 17.6403C47.6773 17.4438 47.5653 17.2038 47.5653 16.9209C47.5653 16.7392 47.6178 16.5689 47.7234 16.4102C47.8283 16.2515 47.98 16.1312 48.1784 16.048C48.3762 15.9654 48.6155 15.9238 48.8958 15.9238C49.3534 15.9238 49.6978 16.0224 49.9294 16.2189C50.1605 16.4153 50.2821 16.6777 50.2936 17.0061L49.5576 17.0381C49.5262 16.8544 49.4584 16.7226 49.3547 16.6419C49.251 16.5613 49.0955 16.5216 48.8882 16.5216C48.6744 16.5216 48.5067 16.5645 48.3858 16.6509C48.3077 16.7059 48.2686 16.7801 48.2686 16.8729C48.2686 16.9574 48.3051 17.0298 48.3781 17.0899C48.4709 17.1661 48.6962 17.2461 49.0546 17.3286C49.413 17.4112 49.6773 17.497 49.8494 17.5859C50.0216 17.6749 50.1554 17.7958 50.252 17.9488C50.3493 18.1024 50.3973 18.2918 50.3973 18.5178C50.3973 18.7226 50.339 18.9145 50.2232 19.0931C50.1074 19.2717 49.9429 19.4048 49.731 19.4918C49.5186 19.5789 49.2542 19.6224 48.9374 19.6224C48.4766 19.6224 48.1227 19.5181 47.8757 19.3094C47.6293 19.1001 47.4821 18.7961 47.4341 18.3961Z" fill="#154DDD"/>
<path d="M50.8933 19.559V15.9858H51.6293V19.559H50.8933Z" fill="#154DDD"/>
<path d="M52.0798 17.7939C52.0798 17.4298 52.1355 17.1245 52.2462 16.8774C52.3288 16.6957 52.4421 16.5318 52.5854 16.3872C52.7288 16.2425 52.8862 16.135 53.0565 16.0653C53.2837 15.9712 53.5454 15.9238 53.8424 15.9238C54.3794 15.9238 54.8094 16.087 55.132 16.4141C55.4546 16.7405 55.6158 17.1949 55.6158 17.7766C55.6158 18.3533 55.4558 18.8051 55.1358 19.1309C54.8158 19.4566 54.3877 19.6198 53.8526 19.6198C53.3106 19.6198 52.8792 19.4579 52.5592 19.1334C52.2398 18.8096 52.0798 18.3629 52.0798 17.7939ZM52.8382 17.7696C52.8382 18.1741 52.9336 18.4813 53.1243 18.6899C53.315 18.8985 53.557 19.0029 53.8507 19.0029C54.1445 19.0029 54.3851 18.8992 54.5733 18.6918C54.7614 18.4845 54.8555 18.1741 54.8555 17.7593C54.8555 17.3497 54.764 17.0445 54.581 16.8429C54.3979 16.6413 54.1547 16.5408 53.8507 16.5408C53.5474 16.5408 53.3029 16.6425 53.1173 16.8467C52.931 17.0509 52.8382 17.3587 52.8382 17.7696Z" fill="#154DDD"/>
<path d="M56.0967 19.559V15.9858H56.8128L58.3053 18.3724V15.9858H58.9895V19.559H58.2509L56.7808 17.2287V19.559H56.0967Z" fill="#154DDD"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" version="1.1" viewBox="0 0 200 200"><title>Group 28 Copy 5</title><desc>Created with Sketch.</desc><defs><linearGradient id="linearGradient-1" x1="62.102%" x2="108.197%" y1="0%" y2="37.864%"><stop offset="0%" stop-color="#4285EB"/><stop offset="100%" stop-color="#2EC7FF"/></linearGradient><linearGradient id="linearGradient-2" x1="69.644%" x2="54.043%" y1="0%" y2="108.457%"><stop offset="0%" stop-color="#29CDFF"/><stop offset="37.86%" stop-color="#148EFF"/><stop offset="100%" stop-color="#0A60FF"/></linearGradient><linearGradient id="linearGradient-3" x1="69.691%" x2="16.723%" y1="-12.974%" y2="117.391%"><stop offset="0%" stop-color="#FA816E"/><stop offset="41.473%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient><linearGradient id="linearGradient-4" x1="68.128%" x2="30.44%" y1="-35.691%" y2="114.943%"><stop offset="0%" stop-color="#FA8E7D"/><stop offset="51.264%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient></defs><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="logo" transform="translate(-20.000000, -20.000000)"><g id="Group-28-Copy-5" transform="translate(20.000000, 20.000000)"><g id="Group-27-Copy-3"><g id="Group-25" fill-rule="nonzero"><g id="2"><path id="Shape" fill="url(#linearGradient-1)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C99.2571609,26.9692191 101.032305,26.9692191 102.20193,28.1378823 L129.985225,55.8983314 C134.193707,60.1033528 141.017005,60.1033528 145.225487,55.8983314 C149.433969,51.69331 149.433969,44.8756232 145.225487,40.6706018 L108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/><path id="Shape" fill="url(#linearGradient-2)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C100.999864,25.6271836 105.751642,20.541824 112.729652,19.3524487 C117.915585,18.4685261 123.585219,20.4140239 129.738554,25.1889424 C125.624663,21.0784292 118.571995,14.0340304 108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/></g><path id="Shape" fill="url(#linearGradient-3)" d="M153.685633,135.854579 C157.894115,140.0596 164.717412,140.0596 168.925894,135.854579 L195.959977,108.842726 C200.659183,104.147384 200.659183,96.5636133 195.960527,91.8688194 L168.690777,64.7181159 C164.472332,60.5180858 157.646868,60.5241425 153.435895,64.7316526 C149.227413,68.936674 149.227413,75.7543607 153.435895,79.9593821 L171.854035,98.3623765 C173.02366,99.5310396 173.02366,101.304724 171.854035,102.473387 L153.685633,120.626849 C149.47715,124.83187 149.47715,131.649557 153.685633,135.854579 Z"/></g><ellipse id="Combined-Shape" cx="100.519" cy="100.437" fill="url(#linearGradient-4)" rx="23.6" ry="23.581"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 53 KiB

@ -0,0 +1,5 @@
<svg width="42" height="42" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill="#070707" d="m6.717392,13.773912l5.6,0c2.8,0 4.7,1.9 4.7,4.7c0,2.8 -2,4.7 -4.9,4.7l-2.5,0l0,4.3l-2.9,0l0,-13.7zm2.9,2.2l0,4.9l1.9,0c1.6,0 2.6,-0.9 2.6,-2.4c0,-1.6 -0.9,-2.4 -2.6,-2.4l-1.9,0l0,-0.1zm8.9,11.5l2.7,0l0,-5.7c0,-1.4 0.8,-2.3 2.2,-2.3c0.4,0 0.8,0.1 1,0.2l0,-2.4c-0.2,-0.1 -0.5,-0.1 -0.8,-0.1c-1.2,0 -2.1,0.7 -2.4,2l-0.1,0l0,-1.9l-2.7,0l0,10.2l0.1,0zm11.7,0.1c-3.1,0 -5,-2 -5,-5.3c0,-3.3 2,-5.3 5,-5.3s5,2 5,5.3c0,3.4 -1.9,5.3 -5,5.3zm0,-2.1c1.4,0 2.2,-1.1 2.2,-3.2c0,-2 -0.8,-3.2 -2.2,-3.2c-1.4,0 -2.2,1.2 -2.2,3.2c0,2.1 0.8,3.2 2.2,3.2z" class="st0" id="Ant-Design-Pro"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 677 B

@ -0,0 +1,202 @@
/**
* 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 class="loading-title">
正在加载资源
</div>
<div class="loading-sub-title">
初次加载资源可能需要较多时间 请耐心等待
</div>
</div>
`;
}
})();

@ -0,0 +1,22 @@
import {IRoute} from "@umijs/max";
/**
* @see https://umijs.org/zh-CN/plugins/plugin-access
* */
export default function access(initialState: { currentUser?: API.CurrentUser } | undefined) {
// const { currentUser } = initialState ?? {};
// const read_paths = currentUser?.read_paths || []
// const update_paths = currentUser?.update_paths || []
return {
// canReadMenu: read_paths?.includes(history.location.pathname),
canReadMenu: (route: IRoute)=>{
// return read_paths?.includes(route.path)
return true
},
canUpdate: (path: string)=>{
// return update_paths?.includes(path)
return true
}
};
}

@ -0,0 +1,231 @@
import { AvatarDropdown, AvatarName, Footer, Question, SelectLang } from '@/components';
import { LinkOutlined } from '@ant-design/icons';
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
import { SettingDrawer } from '@ant-design/pro-components';
import { RunTimeLayoutConfig, getLocale, history } from '@umijs/max';
import { RequestConfig } from 'umi';
import defaultSettings from '../config/defaultSettings';
import { errorConfig } from './requestErrorConfig';
const isDev = process.env.NODE_ENV === 'development';
const loginPath = '/showInfo';
// @ts-ignore
import { SelectRole } from '@/components/RightContent';
import zhCN from '@/locales/zh-CN';
import { postMenuGetMenu } from '@/services/system/Menu';
import { getUserGetUserInfo } from '@/services/system/User';
import fixMenuItemIcon from '@/utils/FixMenuItemIcon';
import { getAllRouteNameTile } from '@/utils/common';
import { addLocale } from '@@/plugin-locale';
import { MenuDataItem } from '@ant-design/pro-layout';
import { Button } from 'antd';
import cookie from 'react-cookies';
/**
* @see https://umijs.org/zh-CN/plugins/plugin-initial-state
* */
// 自定义路由路径集合
const isCustomPageTitlePaths: string[] = ['/resource/algorithm-model-detail'];
export async function getInitialState(): Promise<{
settings?: Partial<LayoutSettings>;
currentUser?: API.UserView;
loading?: boolean;
fetchUserInfo?: any;
menuData?: MenuDataItem[];
}> {
const fetchUserInfo = async () => {
// try {
// const msg = await getUserGetUserInfo();
// return msg.data.userInfo;
// } catch (error) {
// history.push(loginPath);
// }
history.push(loginPath);
return undefined;
};
// 如果不是登录页面,执行
const { location } = history;
if (location.pathname !== loginPath && localStorage.getItem('access')) {
const currentUser = await fetchUserInfo();
const menus = await postMenuGetMenu();
if (getLocale() === 'zh-CN') {
let localData = getAllRouteNameTile(menus.data.routes, '');
let localRes: any = {};
localData.forEach((v) => {
// console.log(v.title,'localData_v')
localRes[`menu${v.name}`] = v.title;
});
console.log(localRes, 'getAllRouteNameTile');
addLocale('zh-CN', localRes, {
momentLocale: 'zh-CN',
antd: zhCN,
});
}
return {
fetchUserInfo,
currentUser,
settings: defaultSettings as Partial<LayoutSettings>,
menuData: [
{
path: '/welcome',
key: '',
name: 'welcome',
icon: 'HomeOutlined',
access: '',
component: 'Welcome',
title: '首页',
// routes: [],
},
],
};
}
return {
fetchUserInfo,
settings: defaultSettings as Partial<LayoutSettings>,
};
}
// ProLayout 支持的api https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
return {
actionsRender: () => [
<SelectRole key="selectRole" />,
<Question key="doc" />,
<SelectLang key="SelectLang" />,
],
avatarProps: {
src: SERVER_HOST + initialState?.currentUser?.avatarUrl,
title: <AvatarName />,
render: (_, avatarChildren) => {
// console.log(avatarChildren,'')
return <AvatarDropdown>{avatarChildren}</AvatarDropdown>;
},
},
pageTitleRender: () => {
console.log(history, 'pageTitleRender');
// TODO 目前使用路由path全匹配后续改成从接口字段读取
let isCustom: boolean = false;
for (let i = 0; i < isCustomPageTitlePaths.length; i++) {
const item = isCustomPageTitlePaths[i];
if (history.location.pathname.includes(item)) {
isCustom = true;
break;
} else {
isCustom = false;
}
}
return isCustom ? '' : undefined;
// 默认不进行重定义 使用null即可
},
footerRender: () => <Footer />,
onPageChange: () => {
const { location } = history;
// 如果没有登录,重定向到 login
if (!initialState?.currentUser && location.pathname !== loginPath) {
history.push(loginPath);
}
},
menuDataRender: () => {
if (initialState?.menuData !== undefined) {
return fixMenuItemIcon(initialState?.menuData || []);
}
},
layoutBgImgList: [
{
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/D2LWSqNny4sAAAAAAAAAAAAAFl94AQBr',
left: 85,
bottom: 100,
height: '303px',
},
{
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/C2TWRpJpiC0AAAAAAAAAAAAAFl94AQBr',
bottom: -68,
right: -45,
height: '303px',
},
{
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/F6vSTbj8KpYAAAAAAAAAAAAAFl94AQBr',
bottom: 0,
left: 0,
width: '331px',
},
],
links: isDev
? [
// eslint-disable-next-line react/jsx-key
<Button
onClick={() => {
window.open('https://funcion_woqu.gitee.io/fabric-doc/api/');
}}
>
<LinkOutlined />
<span>fabric </span>
</Button>,
]
: [],
menuHeaderRender: undefined,
// 自定义 403 页面
// unAccessible: <div>unAccessible</div>,
// 增加一个 loading 的状态
childrenRender: (children) => {
// if (initialState?.loading) return <PageLoading />;
return (
<>
{children}
{isDev && (
<SettingDrawer
disableUrlParams
enableDarkTheme
settings={initialState?.settings}
onSettingChange={(settings) => {
setInitialState((preInitialState) => ({
...preInitialState,
settings,
}));
}}
/>
)}
</>
);
},
...initialState?.settings,
};
};
const csrfAndJwtHeaderInterceptor = (url: string, options: RequestConfig) => {
const csrfHeader = { 'X-CSRFToken': cookie.load('csrftoken') };
let bearerToken = {};
const access = localStorage.getItem('access');
if (access) {
bearerToken = { 'X-Token': `${access}` };
}
let locale = getLocale();
return {
url: `${url}`,
options: {
...options,
interceptors: true,
headers: { ...csrfHeader, ...bearerToken, 'Accept-Language': locale },
},
};
};
const responseHeaderInterceptor = (response: Response) => {
if ('new-token' in response.headers) {
localStorage.setItem('access', (response.headers['new-token'] || '') as string);
window.location.reload();
}
return response;
};
/**
* @name request
* axios ahooks useRequest
* @doc https://umijs.org/docs/max/request#配置
*/
export const request = {
...errorConfig,
requestInterceptors: [csrfAndJwtHeaderInterceptor],
responseInterceptors: [responseHeaderInterceptor],
};

@ -0,0 +1,54 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-16 14:30:15
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-16 14:35:20
* @FilePath: \general-ai-platform-web\src\components\BatchOperation\isBatchDelete.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { ExclamationCircleOutlined } from '@ant-design/icons';
// import { useIntl } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Modal } from 'antd';
import { FormattedMessage } from 'react-intl';
type IsBatchDeleteProps = {
// eslint-disable-next-line @typescript-eslint/ban-types
deleteApi: Function;
};
const IsBatchDelete: React.FC<IsBatchDeleteProps> = (props) => {
const intl = useIntl();
return (
<Button
danger
onClick={async () => {
Modal.confirm({
icon: <ExclamationCircleOutlined />,
title: intl.formatMessage({
id: 'common.modal.table.delete.title',
defaultMessage: '$$$',
}),
content: intl.formatMessage({
id: 'common.modal.table.delete.content',
defaultMessage: '$$$',
}),
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '$$$' }),
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '$$$' }),
onOk() {
// TODO 未对接批量删除接口
props.deleteApi();
},
onCancel() {
console.log('Cancel');
},
});
}}
>
<FormattedMessage id="pages.searchTable.batchDeletion" defaultMessage="Batch deletion" />
</Button>
);
};
export default IsBatchDelete;

@ -0,0 +1,32 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-15 15:01:34
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-22 13:24:58
* @FilePath: \general-ai-platform-web\src\components\DictionaryBox\isEnable.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { isEnableEnum } from '@/enums/common';
import { Badge } from 'antd';
import { FormattedMessage } from 'react-intl';
type IsEnableBoxProps = {
isEnable: boolean;
};
const IsEnableBox: React.FC<IsEnableBoxProps> = (props) => {
const { isEnable } = props;
const currentItem = isEnableEnum[isEnable ? '1' : '0']
return (
<div style={{ display: 'flex', alignItems: 'center'}}>
<Badge status={isEnable ? 'success' : 'default'}></Badge>
<span style={{color: currentItem.color, paddingLeft: 4 }}>
<FormattedMessage id={isEnable ? 'common.enable' : 'common.disable'} defaultMessage="$$$" />
</span>
</div>
);
};
export default IsEnableBox;

@ -0,0 +1,18 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-22 10:02:59
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-12-05 10:56:42
* @FilePath: \react-adpro-fabric\src\components\Footer\index.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { GithubOutlined } from '@ant-design/icons';
import { DefaultFooter } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import React from 'react';
const Footer: React.FC = () => {
return <></>
};
export default Footer;

@ -0,0 +1,23 @@
import { Dropdown } from 'antd';
import type { DropDownProps } from 'antd/es/dropdown';
import React from 'react';
import { useEmotionCss } from '@ant-design/use-emotion-css';
import classNames from 'classnames';
export type HeaderDropdownProps = {
overlayClassName?: string;
placement?: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topCenter' | 'topRight' | 'bottomCenter';
} & Omit<DropDownProps, 'overlay'>;
const HeaderDropdown: React.FC<HeaderDropdownProps> = ({ overlayClassName: cls, ...restProps }) => {
const className = useEmotionCss(({ token }) => {
return {
[`@media screen and (max-width: ${token.screenXS}px)`]: {
width: '100%',
},
};
});
return <Dropdown overlayClassName={classNames(className, cls)} {...restProps} />;
};
export default HeaderDropdown;

@ -0,0 +1,63 @@
import * as React from 'react';
import CopyableIcon from './CopyableIcon';
import type { ThemeType } from './index';
import type { CategoriesKeys } from './fields';
import { useIntl } from '@umijs/max';
import styles from './style.less';
interface CategoryProps {
title: CategoriesKeys;
icons: string[];
theme: ThemeType;
newIcons: string[];
onSelect: (type: string, name: string) => any;
}
const Category: React.FC<CategoryProps> = props => {
const { icons, title, newIcons, theme } = props;
const intl = useIntl();
const [justCopied, setJustCopied] = React.useState<string | null>(null);
const copyId = React.useRef<NodeJS.Timeout | null>(null);
const onSelect = React.useCallback((type: string, text: string) => {
const { onSelect } = props;
if (onSelect) {
onSelect(type, text);
}
setJustCopied(type);
copyId.current = setTimeout(() => {
setJustCopied(null);
}, 2000);
}, []);
React.useEffect(
() => () => {
if (copyId.current) {
clearTimeout(copyId.current);
}
},
[],
);
return (
<div>
<h4 style={{paddingTop: 16}}>{intl.formatMessage({
id: `app.docs.components.icon.category.${title}`,
defaultMessage: '信息',
})}</h4>
<ul className={styles.anticonsList}>
{icons.map(name => (
<CopyableIcon
key={name}
name={name}
theme={theme}
isNew={newIcons.includes(name)}
justCopied={justCopied}
onSelect={onSelect}
/>
))}
</ul>
</div>
);
};
export default Category;

@ -0,0 +1,52 @@
import * as React from 'react';
import { Tooltip } from 'antd';
import classNames from 'classnames';
import * as AntdIcons from '@ant-design/icons';
import type { ThemeType } from './index';
import styles from './style.less';
const allIcons: {
[key: string]: any;
} = AntdIcons;
export interface CopyableIconProps {
name: string;
isNew: boolean;
theme: ThemeType;
justCopied: string | null;
onSelect: (type: string, text: string) => any;
}
const CopyableIcon: React.FC<CopyableIconProps> = ({
name,
justCopied,
onSelect,
theme,
}) => {
const className = classNames({
gn: true,
themeBgHover: true,
copied: justCopied === name,
[theme]: !!theme,
});
return (
<li className={className}
style={{
lineHeight: '48px',
}}
onClick={() => {
if (onSelect) {
onSelect(theme, name);
}
}}>
<Tooltip title={name}>
{React.createElement(allIcons[name], { className: styles.anticon })}
</Tooltip>
{/* <span className={styles.anticonClass}>
<Badge dot={isNew}>{name}</Badge>
</span> */}
</li>
);
};
export default CopyableIcon;

@ -0,0 +1,233 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Upload, Tooltip, Popover, Modal, Progress, Spin, Result } from 'antd';
import * as AntdIcons from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import './style.less';
const allIcons: { [key: string]: any } = AntdIcons;
const { Dragger } = Upload;
interface AntdIconClassifier {
load: () => void;
predict: (imgEl: HTMLImageElement) => void;
}
declare global {
interface Window {
antdIconClassifier: AntdIconClassifier;
}
}
interface PicSearcherState {
loading: boolean;
modalOpen: boolean;
popoverVisible: boolean;
icons: iconObject[];
fileList: any[];
error: boolean;
modelLoaded: boolean;
}
interface iconObject {
type: string;
score: number;
}
const PicSearcher: React.FC = () => {
const intl = useIntl();
const {formatMessage} = intl;
const [state, setState] = useState<PicSearcherState>({
loading: false,
modalOpen: false,
popoverVisible: false,
icons: [],
fileList: [],
error: false,
modelLoaded: false,
});
const predict = (imgEl: HTMLImageElement) => {
try {
let icons: any[] = window.antdIconClassifier.predict(imgEl);
if (gtag && icons.length) {
gtag('event', 'icon', {
event_category: 'search-by-image',
event_label: icons[0].className,
});
}
icons = icons.map(i => ({ score: i.score, type: i.className.replace(/\s/g, '-') }));
setState(prev => ({ ...prev, loading: false, error: false, icons }));
} catch {
setState(prev => ({ ...prev, loading: false, error: true }));
}
};
// eslint-disable-next-line class-methods-use-this
const toImage = (url: string) =>
new Promise(resolve => {
const img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;
img.onload = () => {
resolve(img);
};
});
const uploadFile = useCallback((file: File) => {
setState(prev => ({ ...prev, loading: true }));
const reader = new FileReader();
reader.onload = () => {
toImage(reader.result as string).then(predict);
setState(prev => ({
...prev,
fileList: [{ uid: 1, name: file.name, status: 'done', url: reader.result }],
}));
};
reader.readAsDataURL(file);
}, []);
const onPaste = useCallback((event: ClipboardEvent) => {
const items = event.clipboardData && event.clipboardData.items;
let file = null;
if (items && items.length) {
for (let i = 0; i < items.length; i++) {
if (items[i].type.includes('image')) {
file = items[i].getAsFile();
break;
}
}
}
if (file) {
uploadFile(file);
}
}, []);
const toggleModal = useCallback(() => {
setState(prev => ({
...prev,
modalOpen: !prev.modalOpen,
popoverVisible: false,
fileList: [],
icons: [],
}));
if (!localStorage.getItem('disableIconTip')) {
localStorage.setItem('disableIconTip', 'true');
}
}, []);
useEffect(() => {
const script = document.createElement('script');
script.onload = async () => {
await window.antdIconClassifier.load();
setState(prev => ({ ...prev, modelLoaded: true }));
document.addEventListener('paste', onPaste);
};
script.src = 'https://cdn.jsdelivr.net/gh/lewis617/antd-icon-classifier@0.0/dist/main.js';
document.head.appendChild(script);
setState(prev => ({ ...prev, popoverVisible: !localStorage.getItem('disableIconTip') }));
return () => {
document.removeEventListener('paste', onPaste);
};
}, []);
return (
<div className="iconPicSearcher">
<Popover
content={formatMessage({id: 'app.docs.components.icon.pic-searcher.intro'})}
open={state.popoverVisible}
>
<AntdIcons.CameraOutlined className="icon-pic-btn" onClick={toggleModal} />
</Popover>
<Modal
title={intl.formatMessage({
id: 'app.docs.components.icon.pic-searcher.title',
defaultMessage: '信息',
})}
open={state.modalOpen}
onCancel={toggleModal}
footer={null}
>
{state.modelLoaded || (
<Spin
spinning={!state.modelLoaded}
tip={formatMessage({
id: 'app.docs.components.icon.pic-searcher.modelloading',
})}
>
<div style={{ height: 100 }} />
</Spin>
)}
{state.modelLoaded && (
<Dragger
accept="image/jpeg, image/png"
listType="picture"
customRequest={o => uploadFile(o.file as File)}
fileList={state.fileList}
showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }}
>
<p className="ant-upload-drag-icon">
<AntdIcons.InboxOutlined />
</p>
<p className="ant-upload-text">
{formatMessage({id: 'app.docs.components.icon.pic-searcher.upload-text'})}
</p>
<p className="ant-upload-hint">
{formatMessage({id: 'app.docs.components.icon.pic-searcher.upload-hint'})}
</p>
</Dragger>
)}
<Spin
spinning={state.loading}
tip={formatMessage({id: 'app.docs.components.icon.pic-searcher.matching'})}
>
<div className="icon-pic-search-result">
{state.icons.length > 0 && (
<div className="result-tip">
{formatMessage({id: 'app.docs.components.icon.pic-searcher.result-tip'})}
</div>
)}
<table>
{state.icons.length > 0 && (
<thead>
<tr>
<th className="col-icon">
{formatMessage({id: 'app.docs.components.icon.pic-searcher.th-icon'})}
</th>
<th>{formatMessage({id: 'app.docs.components.icon.pic-searcher.th-score'})}</th>
</tr>
</thead>
)}
<tbody>
{state.icons.map(icon => {
const { type } = icon;
const iconName = `${type
.split('-')
.map(str => `${str[0].toUpperCase()}${str.slice(1)}`)
.join('')}Outlined`;
return (
<tr key={iconName}>
<td className="col-icon">
<Tooltip title={icon.type} placement="right">
{React.createElement(allIcons[iconName])}
</Tooltip>
</td>
<td>
<Progress percent={Math.ceil(icon.score * 100)} />
</td>
</tr>
);
})}
</tbody>
</table>
{state.error && (
<Result
status="500"
title="503"
subTitle={formatMessage({id: 'app.docs.components.icon.pic-searcher.server-error'})}
/>
)}
</div>
</Spin>
</Modal>
</div>
);
};
export default PicSearcher;

@ -0,0 +1,223 @@
import * as AntdIcons from '@ant-design/icons/lib/icons';
const all = Object.keys(AntdIcons)
.map(n => n.replace(/(Outlined|Filled|TwoTone)$/, ''))
.filter((n, i, arr) => arr.indexOf(n) === i);
const direction = [
'StepBackward',
'StepForward',
'FastBackward',
'FastForward',
'Shrink',
'ArrowsAlt',
'Down',
'Up',
'Left',
'Right',
'CaretUp',
'CaretDown',
'CaretLeft',
'CaretRight',
'UpCircle',
'DownCircle',
'LeftCircle',
'RightCircle',
'DoubleRight',
'DoubleLeft',
'VerticalLeft',
'VerticalRight',
'VerticalAlignTop',
'VerticalAlignMiddle',
'VerticalAlignBottom',
'Forward',
'Backward',
'Rollback',
'Enter',
'Retweet',
'Swap',
'SwapLeft',
'SwapRight',
'ArrowUp',
'ArrowDown',
'ArrowLeft',
'ArrowRight',
'PlayCircle',
'UpSquare',
'DownSquare',
'LeftSquare',
'RightSquare',
'Login',
'Logout',
'MenuFold',
'MenuUnfold',
'BorderBottom',
'BorderHorizontal',
'BorderInner',
'BorderOuter',
'BorderLeft',
'BorderRight',
'BorderTop',
'BorderVerticle',
'PicCenter',
'PicLeft',
'PicRight',
'RadiusBottomleft',
'RadiusBottomright',
'RadiusUpleft',
'RadiusUpright',
'Fullscreen',
'FullscreenExit',
];
const suggestion = [
'Question',
'QuestionCircle',
'Plus',
'PlusCircle',
'Pause',
'PauseCircle',
'Minus',
'MinusCircle',
'PlusSquare',
'MinusSquare',
'Info',
'InfoCircle',
'Exclamation',
'ExclamationCircle',
'Close',
'CloseCircle',
'CloseSquare',
'Check',
'CheckCircle',
'CheckSquare',
'ClockCircle',
'Warning',
'IssuesClose',
'Stop',
];
const editor = [
'Edit',
'Form',
'Copy',
'Scissor',
'Delete',
'Snippets',
'Diff',
'Highlight',
'AlignCenter',
'AlignLeft',
'AlignRight',
'BgColors',
'Bold',
'Italic',
'Underline',
'Strikethrough',
'Redo',
'Undo',
'ZoomIn',
'ZoomOut',
'FontColors',
'FontSize',
'LineHeight',
'Dash',
'SmallDash',
'SortAscending',
'SortDescending',
'Drag',
'OrderedList',
'UnorderedList',
'RadiusSetting',
'ColumnWidth',
'ColumnHeight',
];
const data = [
'AreaChart',
'PieChart',
'BarChart',
'DotChart',
'LineChart',
'RadarChart',
'HeatMap',
'Fall',
'Rise',
'Stock',
'BoxPlot',
'Fund',
'Sliders',
];
const logo = [
'Android',
'Apple',
'Windows',
'Ie',
'Chrome',
'Github',
'Aliwangwang',
'Dingding',
'WeiboSquare',
'WeiboCircle',
'TaobaoCircle',
'Html5',
'Weibo',
'Twitter',
'Wechat',
'Youtube',
'AlipayCircle',
'Taobao',
'Skype',
'Qq',
'MediumWorkmark',
'Gitlab',
'Medium',
'Linkedin',
'GooglePlus',
'Dropbox',
'Facebook',
'Codepen',
'CodeSandbox',
'CodeSandboxCircle',
'Amazon',
'Google',
'CodepenCircle',
'Alipay',
'AntDesign',
'AntCloud',
'Aliyun',
'Zhihu',
'Slack',
'SlackSquare',
'Behance',
'BehanceSquare',
'Dribbble',
'DribbbleSquare',
'Instagram',
'Yuque',
'Alibaba',
'Yahoo',
'Reddit',
'Sketch',
'WhatsApp',
'Dingtalk',
];
const datum = [...direction, ...suggestion, ...editor, ...data, ...logo];
const other = all.filter(n => !datum.includes(n));
export const categories = {
direction,
suggestion,
editor,
data,
logo,
other,
};
export default categories;
export type Categories = typeof categories;
export type CategoriesKeys = keyof Categories;

@ -0,0 +1,11 @@
import React from 'react'
import * as icons from '@ant-design/icons'
// 自定义样式style
const Icon = (props: { icon: string, style?: object}) => {
const { icon, style } = props;
const antIcon: { [key: string]: any } = icons;
return React.createElement(antIcon[icon], { style });
};
export default Icon

@ -0,0 +1,147 @@
import * as React from 'react';
import Icon, * as AntdIcons from '@ant-design/icons';
import { Radio, Input, Empty } from 'antd';
import type { RadioChangeEvent } from 'antd/es/radio/interface';
import {debounce } from 'lodash';
import Category from './Category';
import IconPicSearcher from './IconPicSearcher';
import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons';
import type { CategoriesKeys } from './fields';
import { categories } from './fields';
// import { useIntl } from '@umijs/max';
export enum ThemeType {
Filled = 'Filled',
Outlined = 'Outlined',
TwoTone = 'TwoTone',
}
const allIcons: { [key: string]: any } = AntdIcons;
interface IconSelectorProps {
//intl: any;
onSelect: any;
}
interface IconSelectorState {
theme: ThemeType;
searchKey: string;
}
const IconSelector: React.FC<IconSelectorProps> = (props) => {
// const intl = useIntl();
// const { messages } = intl;
const { onSelect } = props;
const [displayState, setDisplayState] = React.useState<IconSelectorState>({
theme: ThemeType.Outlined,
searchKey: '',
});
const newIconNames: string[] = [];
const handleSearchIcon = React.useCallback(
debounce((searchKey: string) => {
setDisplayState(prevState => ({ ...prevState, searchKey }));
}),
[],
);
const handleChangeTheme = React.useCallback((e: RadioChangeEvent) => {
setDisplayState(prevState => ({ ...prevState, theme: e.target.value as ThemeType }));
}, []);
const renderCategories = React.useMemo<React.ReactNode | React.ReactNode[]>(() => {
const { searchKey = '', theme } = displayState;
const categoriesResult = Object.keys(categories)
.map((key: CategoriesKeys) => {
let iconList = categories[key];
if (searchKey) {
const matchKey = searchKey
// eslint-disable-next-line prefer-regex-literals
.replace(new RegExp(`^<([a-zA-Z]*)\\s/>$`, 'gi'), (_, name) => name)
.replace(/(Filled|Outlined|TwoTone)$/, '')
.toLowerCase();
iconList = iconList.filter((iconName:string) => iconName.toLowerCase().includes(matchKey));
}
// CopyrightCircle is same as Copyright, don't show it
iconList = iconList.filter((icon:string) => icon !== 'CopyrightCircle');
return {
category: key,
icons: iconList.map((iconName:string) => iconName + theme).filter((iconName:string) => allIcons[iconName]),
};
})
.filter(({ icons }) => !!icons.length)
.map(({ category, icons }) => (
<Category
key={category}
title={category as CategoriesKeys}
theme={theme}
icons={icons}
newIcons={newIconNames}
onSelect={(type, name) => {
if (onSelect) {
onSelect(name, allIcons[name]);
}
}}
/>
));
return categoriesResult.length === 0 ? <Empty style={{ margin: '2em 0' }} /> : categoriesResult;
}, [displayState.searchKey, displayState.theme]);
return (
<>
<div className='gn' style={{ display: 'flex', justifyContent: 'space-between' }}>
{/*
* //TODO 二级:输入框上方提示文案悬浮会覆盖清空菜单图标项按钮
*/}
<Input.Search
// placeholder={messages['app.docs.components.icon.search.placeholder']}
style={{ marginRight: 12, flex: 1 }}
allowClear
onChange={e => handleSearchIcon(e.currentTarget.value)}
size="large"
autoFocus
suffix={<IconPicSearcher />}
/>
{/* <Icon component={OutlinedIcon} /> <Icon component={FilledIcon} TwoToneIcon /> */}
<Radio.Group
value={displayState.theme}
onChange={handleChangeTheme}
size="large"
optionType="button"
buttonStyle="solid"
options={[
{
label: <>线</> ,
value: ThemeType.Outlined
},
{
label: <></> ,
value: ThemeType.Filled
},
{
label: <></>,
value: ThemeType.TwoTone
},
]}
>
{/* <Radio.Button value={ThemeType.Outlined}>
<Icon components={OutlinedIcon} /> {messages['app.docs.components.icon.outlined']}
</Radio.Button>
<Radio.Button value={ThemeType.Filled}>
<Icon components={FilledIcon} /> {messages['app.docs.components.icon.filled']}
</Radio.Button>
<Radio.Button value={ThemeType.TwoTone}>
<Icon components={TwoToneIcon} /> {messages['app.docs.components.icon.two-tone']}
</Radio.Button> */}
</Radio.Group>
</div>
{renderCategories}
</>
);
};
export default IconSelector

@ -0,0 +1,137 @@
.iconPicSearcher {
display: inline-block;
margin: 0 8px;
.icon-pic-btn {
color: @text-color-secondary;
cursor: pointer;
transition: all 0.3s;
&:hover {
color: @input-icon-hover-color;
}
}
}
.icon-pic-preview {
width: 30px;
height: 30px;
margin-top: 10px;
padding: 8px;
text-align: center;
border: 1px solid @border-color-base;
border-radius: 4px;
> img {
max-width: 50px;
max-height: 50px;
}
}
.icon-pic-search-result {
min-height: 50px;
padding: 0 10px;
> .result-tip {
padding: 10px 0;
color: @text-color-secondary;
}
> table {
width: 100%;
.col-icon {
width: 80px;
padding: 10px 0;
> .anticon {
font-size: 30px;
:hover {
color: @link-hover-color;
}
}
}
}
}
ul.anticonsList {
margin: 2px 0;
overflow: hidden;
direction: ltr;
list-style: none;
li {
position: relative;
float: left;
width: 48px;
height: 48px;
margin: 3px 0;
padding: 2px 0 0;
overflow: hidden;
color: #555;
text-align: center;
list-style: none;
background-color: inherit;
border-radius: 4px;
cursor: pointer;
transition: color 0.3s ease-in-out, background-color 0.3s ease-in-out;
.rtl & {
margin: 3px 0;
padding: 2px 0 0;
}
.anticon {
margin: 4px 0 2px;
font-size: 24px;
transition: transform 0.3s ease-in-out;
will-change: transform;
}
.anticonClass {
display: block;
font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
white-space: nowrap;
text-align: center;
transform: scale(0.83);
.ant-badge {
transition: color 0.3s ease-in-out;
}
}
&:hover {
color: #fff;
background-color: @primary-color;
.anticon {
transform: scale(1.4);
}
.ant-badge {
color: #fff;
}
}
&.TwoTone:hover {
background-color: #8ecafe;
}
&.copied:hover {
color: rgba(255, 255, 255, 0.2);
}
&.copied::after {
top: -2px;
opacity: 1;
}
}
}
.copied-code {
padding: 2px 4px;
font-size: 12px;
background: #f5f5f5;
border-radius: 2px;
}

@ -0,0 +1,41 @@
import * as React from 'react';
export const FilledIcon: React.FC = props => {
const path =
'M864 64H160C107 64 64 107 64 160v' +
'704c0 53 43 96 96 96h704c53 0 96-43 96-96V16' +
'0c0-53-43-96-96-96z';
return (
<svg {...props} viewBox="0 0 1024 1024">
<path d={path} />
</svg>
);
};
export const OutlinedIcon: React.FC = props => {
const path =
'M864 64H160C107 64 64 107 64 160v7' +
'04c0 53 43 96 96 96h704c53 0 96-43 96-96V160c' +
'0-53-43-96-96-96z m-12 800H172c-6.6 0-12-5.4-' +
'12-12V172c0-6.6 5.4-12 12-12h680c6.6 0 12 5.4' +
' 12 12v680c0 6.6-5.4 12-12 12z';
return (
<svg {...props} viewBox="0 0 1024 1024">
<path d={path} />
</svg>
);
};
export const TwoToneIcon: React.FC = props => {
const path =
'M16 512c0 273.932 222.066 496 496 49' +
'6s496-222.068 496-496S785.932 16 512 16 16 238.' +
'066 16 512z m496 368V144c203.41 0 368 164.622 3' +
'68 368 0 203.41-164.622 368-368 368z';
return (
<svg {...props} viewBox="0 0 1024 1024">
<path d={path} />
</svg>
);
};

@ -0,0 +1,136 @@
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
import { useEmotionCss } from '@ant-design/use-emotion-css';
// @ts-ignore
import { history, useModel } from '@umijs/max';
import { Spin } from 'antd';
import { stringify } from 'querystring';
import type { MenuInfo } from 'rc-menu/lib/interface';
import React, { useCallback } from 'react';
import { flushSync } from 'react-dom';
import HeaderDropdown from '../HeaderDropdown';
import {postJwtJsonInBlacklist} from "@/services/system/Jwt";
export type GlobalHeaderRightProps = {
menu?: boolean;
children?: React.ReactNode;
};
export const AvatarName = () => {
const { initialState } = useModel('@@initialState');
const { currentUser } = initialState || {};
return <span className="anticon">{currentUser?.nickName}</span>;
};
export const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu, children }) => {
/**
* 退 url
*/
const loginOut = async () => {
await postJwtJsonInBlacklist()
// await UserLogOut();
localStorage.removeItem('access')
const { search, pathname } = window.location;
const urlParams = new URL(window.location.href).searchParams;
/** 此方法会跳转到 redirect 参数所在的位置 */
const redirect = urlParams.get('redirect');
// Note: There may be security issues, please note
if (window.location.pathname !== '/showInfo' && !redirect) {
history.replace({
pathname: '/showInfo',
search: stringify({
redirect: pathname + search,
}),
});
}
};
const actionClassName = useEmotionCss(({ token }) => {
return {
display: 'flex',
height: '48px',
marginLeft: 'auto',
overflow: 'hidden',
alignItems: 'center',
padding: '0 8px',
cursor: 'pointer',
borderRadius: token.borderRadius,
'&:hover': {
backgroundColor: token.colorBgTextHover,
},
};
});
const { initialState, setInitialState } = useModel('@@initialState');
const onMenuClick = useCallback(
(event: MenuInfo) => {
const { key } = event;
if (key === 'logout') {
flushSync(() => {
setInitialState((s) => ({ ...s, currentUser: undefined, menuData: undefined }));
});
loginOut().then(() => {});
return;
}
history.push(`/account/${key}`);
},
[setInitialState],
);
const loading = (
<span className={actionClassName}>
<Spin
size="small"
style={{
marginLeft: 8,
marginRight: 8,
}}
/>
</span>
);
console.log(initialState)
if (!initialState) {
return loading;
}
const { currentUser } = initialState;
if (!currentUser || !currentUser.nickName) {
return loading;
}
const menuItems = [
...(menu
? [
{
key: 'center',
icon: <UserOutlined />,
label: '个人中心',
},
{
key: 'settings',
icon: <SettingOutlined />,
label: '个人设置',
},
{
type: 'divider' as const,
},
]
: []),
{
key: 'logout',
icon: <LogoutOutlined />,
label: '退出登录',
},
];
return (
<HeaderDropdown
menu={{
selectedKeys: [],
onClick: onMenuClick,
items: menuItems,
}}
>
{children}
</HeaderDropdown>
);
};

@ -0,0 +1,66 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-28 11:34:00
* @FilePath: \general-ai-platform-web\src\components\RightContent\index.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { QuestionCircleOutlined } from '@ant-design/icons';
import { SelectLang as UmiSelectLang } from '@umijs/max';
import React from 'react';
import { Select } from 'antd';
import {useModel} from "@@/exports";
export type SiderTheme = 'light' | 'dark';
import {postUserSetUserRole} from "@/services/system/User";
export const SelectLang = () => {
return (
<UmiSelectLang
style={{
padding: 4,
}}
/>
);
};
export const Question = () => {
return (
<div
style={{
display: 'flex',
height: 26,
}}
onClick={() => {
window.open('https://pro.ant.design/docs/getting-started');
}}
>
<QuestionCircleOutlined />
</div>
);
};
export const SelectRole = () => {
const { initialState } = useModel('@@initialState');
const { currentUser } = initialState || {};
return (
<span className='gn'>
{
currentUser && (
<Select
defaultValue={currentUser.roleId}
options={currentUser?.roles || []}
onSelect={value => {
postUserSetUserRole({roleId: value}).then((resp) => {
console.log(resp)
})
}}
/>
)
}
</span>
);
};

@ -0,0 +1,68 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-14 15:49:36
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-16 15:10:41
* @FilePath: \general-ai-platform-web\src\components\TableActionCard\index.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { DownOutlined } from '@ant-design/icons';
import { Dropdown } from 'antd';
import React from 'react';
//TODO 表单的操作按钮集合 key的报错未解决
type actionsProps = {
key: string;
renderDom: any
}
export type TableActionItemProps = {
renderActions: actionsProps[];
};
const TableActionCard: React.FC<TableActionItemProps> = (props) => {
const { renderActions } = props;
const maxActionCount = 3;
let prevActions: any[] = [];
const moreActions: { key: string; label: any }[] = [];
if (renderActions.length <= maxActionCount) {
prevActions = renderActions;
} else {
// eslint-disable-next-line array-callback-return
renderActions.map((item, index) => {
if (index < maxActionCount - 1) {
prevActions.push(item);
} else {
moreActions.push({
key: index + '',
label: item.renderDom,
});
}
// eslint-disable-next-line react/jsx-key
});
}
return (
<div>
{prevActions.map((item) => {
return (
<span style={{ paddingRight: 8 }} key={item.key}>
{item.renderDom}
</span>
);
})}
{moreActions.length ? (
<Dropdown menu={{ items: moreActions }}>
<a>
<DownOutlined />
</a>
</Dropdown>
) : (
<></>
)}
</div>
);
};
export default TableActionCard;

@ -0,0 +1,55 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-16 14:30:15
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-16 16:22:15
* @FilePath: \general-ai-platform-web\src\components\BatchOperation\isBatchDelete.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// import { useIntl } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Popconfirm } from 'antd';
import { FormattedMessage } from 'react-intl';
type isConfirmActionProps = {
// eslint-disable-next-line @typescript-eslint/ban-types
confirmAction: Function;
title: string;
description?: string;
buttonText?: string;
buttonFormatText?: string;
};
const IsConfirmAction: React.FC<isConfirmActionProps> = (props) => {
const intl = useIntl();
const description = props.description || `确认${props.title}吗?`;
return (
<Popconfirm
title={props.title}
description={description}
onConfirm={() => {
props.confirmAction();
}}
onCancel={() => {}}
okText={intl.formatMessage({ id: 'common.yes', defaultMessage: '$$$' })}
cancelText={intl.formatMessage({ id: 'common.no', defaultMessage: '$$$' })}
>
<Button
type="link"
size="small"
onClick={() => {
// setPublishModalOpen(true);
}}
>
{/* 自定义文案优先 */}
{props.buttonText ? (
props.buttonText
) : (
<FormattedMessage id={props.buttonFormatText} defaultMessage="$$$" />
)}
</Button>
</Popconfirm>
);
};
export default IsConfirmAction;

@ -0,0 +1,44 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-16 14:30:15
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-16 14:56:27
* @FilePath: \general-ai-platform-web\src\components\BatchOperation\isBatchDelete.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// import { useIntl } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Popconfirm } from 'antd';
import { FormattedMessage } from 'react-intl';
type IsDeleteProps = {
// eslint-disable-next-line @typescript-eslint/ban-types
deleteApi: Function;
};
const IsDelete: React.FC<IsDeleteProps> = (props) => {
const intl = useIntl();
return (
<Popconfirm
key="destroy"
placement="topLeft"
title={intl.formatMessage({ id: 'common.tip.title', defaultMessage: '$$$' })}
description={intl.formatMessage({
id: 'common.modal.table.delete.content',
defaultMessage: '$$$',
})}
okText={intl.formatMessage({ id: 'common.yes', defaultMessage: '$$$' })}
cancelText={intl.formatMessage({ id: 'common.no', defaultMessage: '$$$' })}
onConfirm={() => {
props.deleteApi();
}}
>
<Button type="link" size="small" danger>
<FormattedMessage id="pages.searchTable.destroy" defaultMessage="Destroy" />
</Button>
</Popconfirm>
);
};
export default IsDelete;

@ -0,0 +1,39 @@
/**
* 使
*/
import { TableDropdown } from '@ant-design/pro-components';
import React from 'react';
export type TablePaginationCardProps = {
total: number;
pageSize: number;
current: number;
// eslint-disable-next-line @typescript-eslint/ban-types
onChange: Function
};
// 分页器
const TablePaginationCard: React.FC<TablePaginationCardProps> = (props) => {
const { total, pageSize, current, onChange } = props;
const totalPage = Math.ceil(total / pageSize);
const handleChange = (page: number, pageSize: number) => {
onChange(page, pageSize);
};
return (
<div>
<span>
Total {total} items, {totalPage} pages
</span>
<TableDropdown
total={totalPage as number}
current={current}
pageSize={pageSize}
onClick={(e) => handleChange(e, pageSize)}
/>
</div>
);
};
export default TablePaginationCard;

@ -0,0 +1,54 @@
import React from 'react';
import videojs from 'video.js';
import './video.css';
import './videojs-new-markers.js'
export const VideoJS = (props) => {
const videoRef = React.useRef(null);
const playerRef = React.useRef(null);
const {options, onReady} = props;
React.useEffect(() => {
// Make sure Video.js player is only initialized once
if (!playerRef.current) {
// The Video.js player needs to be _inside_ the component el for React 18 Strict Mode.
const videoElement = document.createElement("video-js");
videoElement.classList.add('vjs-big-play-centered');
videoRef.current.appendChild(videoElement);
const player = playerRef.current = videojs(videoElement, options, () => {
videojs.log('player is ready');
onReady && onReady(player);
});
// You could update an existing player in the `else` block here
// on prop change, for example:
} else {
const player = playerRef.current;
player.autoplay(options.autoplay);
player.src(options.sources);
}
}, [options, videoRef]);
// Dispose the Video.js player when the functional component unmounts
React.useEffect(() => {
const player = playerRef.current;
return () => {
if (player && !player.isDisposed()) {
player.dispose();
playerRef.current = null;
}
};
}, [playerRef]);
return (
<div data-vjs-player={true}>
<div ref={videoRef} />
</div>
);
}
export default VideoJS;

File diff suppressed because one or more lines are too long

@ -0,0 +1,172 @@
import videojs from 'video.js';
const Plugin = videojs.getPlugin('plugin');
let is_jump = false;
class Advanced extends Plugin {
constructor(player, options) {
super(player, options);
this.on(player, ['playing', 'pause'], this.updateState);
this.on('statechanged', this.logState);
player.ready(()=>{
player.controlBar.progressControl.on('keyup', (event) => {
const keyCode = event.which || event.keyCode;
// 检查是否按下左箭头键
if (keyCode === 37) {
// 处理左箭头键事件
console.log('左箭头键被按下');
// 在这里执行你的逻辑
}
// 检查是否按下右箭头键
if (keyCode === 39) {
// 处理右箭头键事件
console.log('右箭头键被按下');
// 在这里执行你的逻辑
}
})
player.controlBar.progressControl.on('mousemove', (event) => {
is_jump = false;
})
player.controlBar.progressControl.on('mouseup', (event) => {
is_jump = true;
})
})
this.player.on('loadedmetadata', () => {
// 获取视频的持续时间
let markers = []
if (options && 'video_config_options' in options) {
markers = Object.values(options['video_config_options'].result).map((v) => {
return {
time: Math.floor(v.time/options['video_config_options'].info.fps),
duration: Math.ceil(v.duration/options['video_config_options'].info.fps),
}
})
}
const duration = this.player.duration();
markers.forEach((v)=>{
let redBlock = document.createElement("div");
let tooltip = document.createElement('div');
let markerBlock = document.createElement('div');
let tooltip_text = document.createElement('div');
markerBlock.style.height= '200px'
markerBlock.appendChild(tooltip);
markerBlock.appendChild(redBlock);
// 将文本提示添加到红色块
redBlock.style.position = "absolute";
redBlock.style.width = "10px";
redBlock.style.height = "20px";
redBlock.style.backgroundColor = "rgba(219,55, 4, 0.6)";
// 计算红色块的位置
const left = (v.time / this.player.duration()) * 100;
const width = ((v.time + v.duration)/ this.player.duration()) * 100 - left;
const zIndex = 100 - Math.floor(width) || 100;
let progress = this.player.controlBar.progressControl.el();
let progressBar = progress.querySelector(".vjs-progress-holder");
let progressBarWidth = progressBar.offsetWidth;
let leftPosition = (50 / this.player.duration()) * progressBarWidth - 5;
// 设置红色块的位置
redBlock.style.left = left+"%";
redBlock.style.width = width +'%';
redBlock.style.zIndex = 1;
redBlock.style.top = "-8px";
redBlock.style.borderRadius = '2px'
redBlock.addEventListener('click', () => {
// 弹出警报
// if (is_jump) {
// this.player.currentTime(v.time);
// }
});
tooltip.className = 'tooltip';
tooltip.style.height = '20px'
tooltip.style.display = 'flex'
tooltip.style.justifyContent = 'center'
tooltip.style.alignItems = 'center'
tooltip_text.className='bubble'
tooltip_text.style.height = '30px'
tooltip_text.style.width = '80px'
tooltip_text.style.padding = '6px'
tooltip_text.style.height = '30px'
tooltip_text.textContent = options?.error_type
tooltip.appendChild(tooltip_text)
tooltip.style.position = "absolute";
tooltip.style.top = "-76px";
tooltip.style.left = left+"%";
tooltip.style.display = 'none';
redBlock.addEventListener('mouseenter', function () {
tooltip.style.display = 'block';
redBlock.style.transform = 'scale(1.1)';
});
// 鼠标移出红色块时隐藏文本提示
redBlock.addEventListener('mouseleave', function () {
tooltip.style.display = 'none';
redBlock.style.transform = 'scale(1)';
});
// 将红色块添加到进度条中
progressBar.appendChild(markerBlock);
})
// 在这里可以执行其他与视频持续时间相关的操作
});
}
updateOverlay() {
// console.log(22222222)
// const overlayPosition = 5; // 在5秒处显示红色块
//
// if (currentTime >= overlayPosition && currentTime <= overlayPosition + 5) {
// // 创建一个覆盖层
// const overlay = document.createElement('div');
// overlay.className = 'overlay';
// overlay.style.position = 'absolute';
// overlay.style.left = '50%';
// overlay.style.transform = 'translateX(-50%)';
// overlay.style.top = '50%';
// overlay.style.transform = 'translateY(-50%)';
// overlay.style.width = '10px';
// overlay.style.height = '10px';
// overlay.style.backgroundColor = 'red';
//
// // 将覆盖层添加到视频容器中
// this.player().el().appendChild(overlay);
// } else {
// // 如果不在5秒处移除覆盖层
// const overlay = this.player().el().querySelector('.overlay');
// if (overlay) {
// overlay.remove();
// }
// }
}
dispose() {
super.dispose();
videojs.log('the advanced plugin is being disposed');
}
updateState() {
this.setState({playing: !this.player.paused()});
}
logState(changed) {
videojs.log(`the player is now ${this.state.playing ? 'playing' : 'paused'}`);
}
}
videojs.registerPlugin('advanced', Advanced);

@ -0,0 +1,32 @@
import React, {useEffect} from 'react';
// @ts-ignore
import WebRtcStreamer from 'webrtc-streamer/html/webrtcstreamer.js';
export type Props = {
stream_url?: string;
server_url: string;
is_open: boolean;
};
const WebRTCStreamer : React.FC<Props> = (props) =>{
let webRtcServer: { connect: (arg0: string) => void; disconnect: () => void; } | null = null;
useEffect(() => {
if (props.is_open) {
webRtcServer = new WebRtcStreamer("video", props.server_url);
if (webRtcServer && props.stream_url) {
webRtcServer.connect(props.stream_url);
}
}
if (webRtcServer) {
webRtcServer.disconnect();
}
}, [props.is_open, props.server_url, props.stream_url]);
return (
<div style={{height: '100%', width: '100%'}}>
<video style={{height: '100%', width: '100%'}} id="video" muted={true} controls={true} autoPlay={true} />
</div>
);
}
export default WebRTCStreamer;

@ -0,0 +1,12 @@
/**
*
* 便
*/
/**
*
*/
import Footer from './Footer';
import { Question, SelectLang } from './RightContent';
import { AvatarDropdown, AvatarName } from './RightContent/AvatarDropdown';
export { Footer, Question, SelectLang, AvatarDropdown, AvatarName };

@ -0,0 +1,9 @@
// 是否启用
export const isEnableEnum = {
'0' : {
color: '#999999',
},
'1' : {
color: '#52C41A',
}
}

@ -0,0 +1,280 @@
html,
body,
#root {
height: 100%;
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
}
.colorWeak {
filter: invert(80%);
}
.ant-layout {
min-height: 100vh;
}
.ant-pro-sider.ant-layout-sider.ant-pro-sider-fixed {
left: unset;
}
canvas {
display: block;
}
body {
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
ul,
ol {
list-style: none;
}
@media (max-width: 768px) {
.ant-table {
width: 100%;
overflow-x: auto;
}
.ant-table-thead > tr > th,
.ant-table-tbody > tr > th,
.ant-table-thead > tr > td,
.ant-table-tbody > tr > td {
white-space: pre;
}
.ant-table-thead > tr > th > span,
.ant-table-tbody > tr > th > span,
.ant-table-thead > tr > td > span,
.ant-table-tbody > tr > td > span {
display: block;
}
}
.keep-alive-tabs .ant-tabs-nav {
margin: 0;
}
.ant-pro .ant-pro-layout .ant-pro-layout-content {
padding: 0;
}
.ant-pro-form-login-page-left {
max-width: none !important;
}
.ant-pro-card-col.ant-pro-card-split-vertical {
border-inline-end: none;
}
.ant-pro-card-col.ant-pro-card-split-horizontal {
border-block-end: none;
}
/* 1108 update 全局样式新增调整 */
.ant-table-cell .ant-btn.ant-btn-sm {
padding: 0;
}
.ant-pro-table-search .ant-form-item .ant-form-item-label {
text-align: left;
}
.ant-btn-link {
color: #155BD4;
}
.ant-pro-card .ant-pro-card-title {
color: #333333;
font-weight: 700;
font-size: 16px;
}
.ant-modal .ant-modal-content {
padding: 20px 24px;
}
.ant-modal-header {
padding-bottom: 10px;
}
/* 单行文本溢出显示省略号 */
.single_line {
white-space: nowrap;
/* 防止文本换行 */
overflow: hidden;
/* 隐藏溢出的文本 */
text-overflow: ellipsis;
/* 显示省略号 */
}
/* 多行文本溢出显示省略号 */
.two_line {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
/* 限制显示的行数 */
overflow: hidden;
/* 隐藏溢出的文本 */
}
* {
padding: 0;
margin: 0;
}
/* 颜色 */
.theme_color,
.ant-table-cell > a,
.ant-descriptions-item-content > a,
a.ant-dropdown-trigger {
color: #155BD4;
}
.theme_bg_color {
background-color: #155BD4;
}
.ant-btn-link.ant-btn-dangerous,
.ant-btn-default.ant-btn-dangerous {
color: #E80D0D;
}
.ant-btn-default.ant-btn-dangerous {
border-color: #E80D0D;
}
.ant-menu-light .ant-menu-item-selected,
.ant-menu-light > .ant-menu .ant-menu-item-selected {
background-color: #e8effb;
}
.ant-select-dropdown .ant-select-item-option-active:not(.ant-select-item-option-disabled) {
background-color: #e8effb;
}
.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected,
.ant-tree .ant-tree-checkbox + span.ant-tree-node-selected {
background-color: #e8effb;
color: #155BD4;
}
.ant-steps .ant-steps-item-active > .ant-steps-item-container > .ant-steps-item-content > .ant-steps-item-title {
color: #155BD4;
}
.ant-steps .ant-steps-item-active > .ant-steps-item-container > .ant-steps-item-content > .ant-steps-item-description {
color: #155BD4;
}
/* 表单 */
.ant-form-item {
margin-bottom: 16px;
}
.ant-steps .ant-steps-item-finish .ant-steps-item-icon {
background-color: rgba(21, 91, 212, 0.1);
border-color: #155BD4;
}
.ant-pro-form-group-container {
gap: 0px 16px !important;
}
.ant-modal .ant-modal-title {
font-size: 18px;
}
.ant-modal-body .ant-pro-steps-form-steps-container {
max-width: 1900px !important;
}
/* 列表table && proTable */
.ant-pro-table .ant-pro-table-list-toolbar-left {
flex: 0.3;
}
.ant-pro-table .ant-pro-table-search .ant-form .ant-pro-query-filter-row-split {
padding-right: 0 !important;
}
.rc-virtual-list-scrollbar-thumb {
display: none;
}
/* ant-descriptions */
.ant-descriptions .ant-descriptions-row > th,
.ant-descriptions .ant-descriptions-row > td {
padding-right: 12px;
}
::-webkit-scrollbar-track-piece {
-webkit-border-radius: 0;
}
::-webkit-scrollbar {
width: 5px;
height: 10px;
}
::-webkit-scrollbar-thumb {
height: 50px;
background-color: #CCC;
-webkit-border-radius: 6px;
outline-offset: -2px;
-moz-opacity: 0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
}
::-webkit-scrollbar-thumb:hover {
height: 50px;
background-color: #878987;
-webkit-border-radius: 6px;
}
.gn {
/* UI // update 使
*/
}
.gn .ant-pro-checkcard-content {
padding-inline: 0;
padding-block: 0;
}
.gn .ant-table-wrapper table tr th.ant-table-selection-column,
.gn .ant-table-wrapper table tr td.ant-table-selection-column,
.gn .ant-table-wrapper .ant-table-selection-column {
text-align: left;
}
.gn .ant-transfer-customize-list .ant-table-wrapper .ant-table-small .ant-table-selection-column {
padding-left: 12px;
}
.gn .ant-tabs > .ant-tabs-nav .ant-tabs-nav-wrap .ant-tabs-nav-list {
padding: 0 24px;
margin-block-start: 0;
}
.gn .ant-tabs > .ant-tabs-nav .ant-tabs-nav-wrap .ant-tabs-nav-list .ant-tabs-tab-active {
font-weight: 700;
}
.gn .ant-pro-table-list-toolbar-container {
padding-block: 8px;
}
.gn .ant-pro-global-header-header-actions-item > * {
padding-block: 0;
}
.gn .ant-radio-group-large .ant-radio-button-wrapper {
height: 32px;
line-height: 32px;
}
.gn .ant-input-affix-wrapper-lg {
height: 32px;
line-height: 32px;
font-size: 14px;
}
.gn .ant-btn.ant-btn-lg {
font-size: 14px;
height: 32px;
border-radius: 4px;
}
.gn .ant-input-search .ant-input-group .ant-input-affix-wrapper:not(:last-child) {
border-start-start-radius: 4px;
border-end-start-radius: 4px;
}
.gn.h2 {
font-size: 18px;
}
.gn.h3 {
font-weight: 600;
}
.gn.h4 {
font-size: 14px;
font-weight: 700;
line-height: 18px;
color: #333333;
}
.gn .des_1 {
font-size: 12px;
font-weight: 400;
line-height: 22px;
color: #666666;
}
.gn .border_bottom_1 {
border-bottom: 1px solid #E0E0E0;
}
.gn.themeBgHover:hover {
background-color: #155BD4;
}
.showInfoDemo_wrap .ant-upload-wrapper .ant-upload-list.ant-upload-list-picture .ant-upload-list-item .ant-upload-list-item-thumbnail {
width: 100px;
height: auto;
}
.showInfoDemo_wrap .ant-upload-wrapper .ant-upload-list.ant-upload-list-picture .ant-upload-list-item {
height: auto;
}
.showInfoDemo_wrap .ant-upload-list-item-name {
display: none;
}
.showInfoDemo_wrap .ant-upload-extra {
padding: 0 !important;
}

@ -0,0 +1,358 @@
html,
body,
#root {
height: 100%;
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
}
.colorWeak {
filter: invert(80%);
}
.ant-layout {
min-height: 100vh;
}
.ant-pro-sider.ant-layout-sider.ant-pro-sider-fixed {
left: unset;
}
canvas {
display: block;
}
body {
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
ul,
ol {
list-style: none;
}
@media (max-width: 768px) {
.ant-table {
width: 100%;
overflow-x: auto;
&-thead > tr,
&-tbody > tr {
> th,
> td {
white-space: pre;
> span {
display: block;
}
}
}
}
}
.keep-alive-tabs {
.ant-tabs-nav {
margin: 0;
}
}
.ant-pro .ant-pro-layout .ant-pro-layout-content {
padding: 0;
}
.ant-pro-form-login-page-left{
max-width: none !important;
}
.ant-pro-card-col.ant-pro-card-split-vertical {
border-inline-end: none;
}
.ant-pro-card-col.ant-pro-card-split-horizontal {
border-block-end: none;
}
/* 1108 update 全局样式新增调整 */
// TODO_update 全局小尺寸按钮,统一间距 (列表操作栏位按钮)
.ant-table-cell .ant-btn.ant-btn-sm{
padding: 0;
}
// 更多
.ant-pro-table-search .ant-form-item .ant-form-item-label{
text-align: left
}
.ant-btn-link{
color: #155BD4;
}
.ant-pro-card .ant-pro-card-title {
color: #333333;
font-weight: 700;
font-size: 16px;
}
// 弹出框
.ant-modal .ant-modal-content{
padding: 20px 24px;
}
.ant-modal-header{
padding-bottom: 10px;
}
// TODO_update 自定义样式块
/* 单行文本溢出显示省略号 */
.single_line {
white-space: nowrap; /* 防止文本换行 */
overflow: hidden; /* 隐藏溢出的文本 */
text-overflow: ellipsis; /* 显示省略号 */
}
/* 多行文本溢出显示省略号 */
.two_line {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2; /* 限制显示的行数 */
overflow: hidden; /* 隐藏溢出的文本 */
}
* {
padding: 0;
margin: 0;
}
/* 颜色 */
.theme_color, .ant-table-cell>a,
.ant-descriptions-item-content>a,
a.ant-dropdown-trigger{
color: #155BD4;
}
.theme_bg_color{
background-color: #155BD4;
}
.ant-btn-link.ant-btn-dangerous, .ant-btn-default.ant-btn-dangerous {
color: #E80D0D;
}
.ant-btn-default.ant-btn-dangerous{
border-color: #E80D0D;
}
.ant-menu-light .ant-menu-item-selected, .ant-menu-light>.ant-menu .ant-menu-item-selected {
background-color: #e8effb;
}
.ant-select-dropdown .ant-select-item-option-active:not(.ant-select-item-option-disabled) {
background-color: #e8effb;
}
.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected, .ant-tree .ant-tree-checkbox+span.ant-tree-node-selected {
background-color: #e8effb;
color: #155BD4;
}
.ant-steps .ant-steps-item-active>.ant-steps-item-container>.ant-steps-item-content{
&> .ant-steps-item-title{
color: #155BD4;
}
&> .ant-steps-item-description{
color: #155BD4;
// color: #155cd5;
}
}
/* 表单 */
.ant-form-item {
margin-bottom: 16px;
}
// 分步表单步骤条
.ant-steps .ant-steps-item-finish .ant-steps-item-icon{
background-color: rgba(#155BD4, 0.1);
border-color: #155BD4;
}
// 表单项之间间距
.ant-pro-form-group-container{
gap: 0px 16px !important;
}
.ant-modal .ant-modal-title{
font-size: 18px;
}
.ant-modal-body .ant-pro-steps-form-steps-container{
max-width: 1900px !important;
}
/* 列表table && proTable */
// proTable
.ant-pro-table{
// 标题栏左侧文字最大弹性占比
.ant-pro-table-list-toolbar-left{
flex: 0.3
}
// 筛选表单
.ant-pro-table-search{
.ant-form{
.ant-pro-query-filter-row-split{
padding-right: 0 !important;
}
}
}
}
.rc-virtual-list-scrollbar-thumb{
display: none
}
/* ant-descriptions */
.ant-descriptions{
.ant-descriptions-row >th,
.ant-descriptions-row >td {
padding-right: 12px;
}
}
// 美化滚动条
::-webkit-scrollbar-track-piece {
-webkit-border-radius: 0
}
::-webkit-scrollbar {
width: 5px;
height: 10px
}
::-webkit-scrollbar-thumb {
height: 50px;
background-color: #CCC;
-webkit-border-radius: 6px;
outline-offset: -2px;
-moz-opacity: 0.5;
-khtml-opacity: 0.5;
opacity: 0.5
}
::-webkit-scrollbar-thumb:hover {
height: 50px;
background-color: #878987;
-webkit-border-radius: 6px
}
.gn {
// TODO_update 重置覆盖默认样式使用统一类名gn + 需要覆盖的类名
.ant-pro-checkcard-content {
padding-inline: 0;
padding-block: 0;
}
.ant-table-wrapper table tr th.ant-table-selection-column,
.ant-table-wrapper table tr td.ant-table-selection-column,
.ant-table-wrapper .ant-table-selection-column{
text-align: left;
}
.ant-transfer-customize-list .ant-table-wrapper .ant-table-small .ant-table-selection-column{
padding-left: 12px;
}
.ant-tabs >.ant-tabs-nav .ant-tabs-nav-wrap{
.ant-tabs-nav-list{
padding: 0 24px;
margin-block-start: 0;
.ant-tabs-tab-active{
font-weight: 700
}
}
}
.ant-pro-table-list-toolbar-container {
padding-block: 8px;
}
.ant-pro-global-header-header-actions-item >*{
padding-block: 0;
}
.ant-radio-group-large .ant-radio-button-wrapper {
height: 32px;
line-height: 32px;
}
.ant-input-affix-wrapper-lg{
height: 32px;
line-height: 32px;
font-size: 14px;
}
.ant-btn.ant-btn-lg {
font-size: 14px;
height: 32px;
border-radius: 4px;
}
.ant-input-search .ant-input-group .ant-input-affix-wrapper:not(:last-child) {
border-start-start-radius: 4px;
border-end-start-radius: 4px;
}
/* UI 规范表 // update 使用中
适用说明
字体大小、颜色、粗细
页面间距
*/
// &.p1 {
// line-height: ;
// font-weight: 600;
// }
&.h2{
font-size: 18px;
}
&.h3{
font-weight: 600;
}
&.h4{
font-size: 14px;
font-weight: 700;
line-height: 18px;
color: rgba(51, 51, 51, 1);
}
.des_1{
font-size: 12px;
font-weight: 400;
line-height: 22px;
color: rgba(102, 102, 102, 1)
}
// 边框
.border_bottom_1 {
border-bottom: 1px solid #E0E0E0
}
&.themeBgHover:hover{
background-color: #155BD4;
}
}
// .p1{
// }
.showInfoDemo_wrap{
.ant-upload-wrapper .ant-upload-list.ant-upload-list-picture .ant-upload-list-item .ant-upload-list-item-thumbnail{
width: 100px;
height: auto;
}
.ant-upload-wrapper .ant-upload-list.ant-upload-list-picture .ant-upload-list-item{
height: auto;
}
.ant-upload-list-item-name{
display: none;
}
.ant-upload-extra{
padding: 0 !important;
}
}

@ -0,0 +1,91 @@
import { useIntl } from '@umijs/max';
import { Button, message, notification } from 'antd';
import defaultSettings from '../config/defaultSettings';
const { pwa } = defaultSettings;
const isHttps = document.location.protocol === 'https:';
const clearCache = () => {
// remove all caches
if (window.caches) {
caches
.keys()
.then((keys) => {
keys.forEach((key) => {
caches.delete(key);
});
})
.catch((e) => console.log(e));
}
};
// if pwa is true
if (pwa) {
// Notify user if offline now
window.addEventListener('sw.offline', () => {
message.warning(useIntl().formatMessage({ id: 'app.pwa.offline' }));
});
// Pop up a prompt on the page asking the user if they want to use the latest version
window.addEventListener('sw.updated', (event: Event) => {
const e = event as CustomEvent;
const reloadSW = async () => {
// Check if there is sw whose state is waiting in ServiceWorkerRegistration
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration
const worker = e.detail && e.detail.waiting;
if (!worker) {
return true;
}
// Send skip-waiting event to waiting SW with MessageChannel
await new Promise((resolve, reject) => {
const channel = new MessageChannel();
channel.port1.onmessage = (msgEvent) => {
if (msgEvent.data.error) {
reject(msgEvent.data.error);
} else {
resolve(msgEvent.data);
}
};
worker.postMessage({ type: 'skip-waiting' }, [channel.port2]);
});
clearCache();
window.location.reload();
return true;
};
const key = `open${Date.now()}`;
const btn = (
<Button
type="primary"
onClick={() => {
notification.destroy(key);
reloadSW();
}}
>
{useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated.ok' })}
</Button>
);
notification.open({
message: useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated' }),
description: useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated.hint' }),
btn,
key,
onClose: async () => null,
});
});
} else if ('serviceWorker' in navigator && isHttps) {
// unregister service worker
const { serviceWorker } = navigator;
if (serviceWorker.getRegistrations) {
serviceWorker.getRegistrations().then((sws) => {
sws.forEach((sw) => {
sw.unregister();
});
});
}
serviceWorker.getRegistration().then((sw) => {
if (sw) sw.unregister();
});
clearCache();
}

@ -0,0 +1,15 @@
import { v4 as uuidv4 } from 'uuid';
export type useUuidProps = {
fetchUuid: () => string;
};
export const useUuid = (): useUuidProps => {
const fetchUuid = () => {
const id = uuidv4();
console.log(id);
return id;
};
return {
fetchUuid,
};
};

@ -0,0 +1,20 @@
import { createContext } from 'react'
interface KeepAliveTabContextType {
refreshTab: (path?: string) => void;
closeTab: (path?: string) => void;
closeOtherTab: (path?: string) => void;
onShow: (cb: () => void) => void;
onHidden: (cb: () => void) => void;
}
const defaultValue = {
refreshTab: () => { },
closeTab: () => { },
closeOtherTab: () => { },
onShow: () => { },
onHidden: () => { },
}
export const KeepAliveTabContext = createContext<KeepAliveTabContextType>(defaultValue);

@ -0,0 +1,138 @@
import { Dropdown, Tabs } from 'antd';
import { useCallback, useMemo } from 'react';
import { history } from '@umijs/max';
import { KeepAliveTab, useKeepAliveTabs } from './useKeepAliveTabs';
import type { ItemType, MenuInfo } from 'rc-menu/lib/interface';
import { KeepAliveTabContext } from './context';
enum OperationType {
REFRESH = 'refresh',
CLOSE = 'close',
CLOSEOTHER = 'close-other',
}
type MenuItemType = ItemType & { key: OperationType } | null;
const KeepAliveLayout = () => {
const {
keepAliveTabs,
activeTabRoutePath,
closeTab,
refreshTab,
closeOtherTab,
onHidden,
onShow,
} = useKeepAliveTabs();
const menuItems: MenuItemType[] = useMemo(() => [
{
label: '刷新',
key: OperationType.REFRESH,
},
keepAliveTabs.length <= 1 ? null : {
label: '关闭',
key: OperationType.CLOSE,
},
keepAliveTabs.length <= 1 ? null : {
label: '关闭其他',
key: OperationType.CLOSEOTHER,
},
].filter(o => o), [keepAliveTabs]);
const menuClick = useCallback(({ key, domEvent }: MenuInfo, tab: KeepAliveTab) => {
domEvent.stopPropagation();
if (key === OperationType.REFRESH) {
refreshTab(tab.routePath);
} else if (key === OperationType.CLOSE) {
closeTab(tab.routePath);
} else if (key === OperationType.CLOSEOTHER) {
closeOtherTab(tab.routePath);
}
}, [closeOtherTab, closeTab, refreshTab]);
const renderTabTitle = useCallback((tab: KeepAliveTab) => {
return (
<Dropdown
menu={{ items: menuItems, onClick: (e) => menuClick(e, tab) }}
trigger={['contextMenu']}
>
<div style={{ margin: '-12px 0', padding: '12px 0' }}>
{/*{tab.icon}*/}
{tab.title}
</div>
</Dropdown>
)
}, [menuItems]);
const tabItems = useMemo(() => {
let finalKeepAliveTabs = keepAliveTabs
// .filter(item => !item?.isHideTab)
return finalKeepAliveTabs.map(tab => {
console.log(tab,'tabItems')
// TODO 未找到合适办法只去除tab标题栏位保留页面内容
return {
key: tab.routePath,
label: renderTabTitle(tab),
children: (
<div
key={tab.key}
style={{ height: 'calc(100vh - 232px)', overflow: 'auto' }}
>
{tab.children}
</div>
),
// style: {display: 'none'},
closable: keepAliveTabs.length > 1,
forceRender: true
}
})
}, [keepAliveTabs]);
const onTabsChange = useCallback((tabRoutePath: string) => {
const curTab = keepAliveTabs.find(o => o.routePath === tabRoutePath);
if (curTab) {
history.push(curTab?.pathname);
}
}, [keepAliveTabs]);
const onTabEdit = (
targetKey: React.MouseEvent | React.KeyboardEvent | string,
action: 'add' | 'remove',
) => {
if (action === 'remove') {
closeTab(targetKey as string);
}
};
const keepAliveContextValue = useMemo(
() => ({
closeTab,
closeOtherTab,
refreshTab,
onHidden,
onShow,
}),
[closeTab, closeOtherTab, refreshTab, onHidden, onShow]
);
return (
<KeepAliveTabContext.Provider value={keepAliveContextValue}>
<Tabs
type="editable-card"
items={tabItems}
activeKey={activeTabRoutePath}
onChange={onTabsChange}
className='keep-alive-tabs'
hideAdd
animated={false}
onEdit={onTabEdit}
/>
</KeepAliveTabContext.Provider>
)
}
export default KeepAliveLayout;

@ -0,0 +1,69 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-21 13:42:31
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-24 16:01:20
* @FilePath: \general-ai-platform-web\src\layouts\treeAndTableList.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { ProCard } from '@ant-design/pro-components';
import { CardProps } from 'antd';
// 此模块使用的 ProCardType
export interface ProCardTypeProps extends CardProps {
colSpan?: string;
headerBordered?: boolean;
}
// 当前组件类型
type TreeAndTableListProps = {
leftCard?: ProCardTypeProps;
rightCard?: ProCardTypeProps;
leftDom: any;
rightDom: any;
};
const TreeAndTableList: React.FC<TreeAndTableListProps> = (props) => {
// 业务层接收
const { leftCard, rightCard, leftDom, rightDom } = props;
// 统一配置
let finalLeftCard: ProCardTypeProps = {
// 左侧卡片
headStyle: { paddingTop: 24, paddingLeft: 20, paddingRight: 20, paddingBottom:12 ,borderBottom: '1px solid #E0E0E0' },
bodyStyle: {paddingLeft: 20, paddingRight: 20},
colSpan: '22%',
};
let finalRightCard: ProCardTypeProps = {
headStyle: { padding: 0, margin: 0, background: 'transparent' },
bodyStyle: { padding: 0, margin: 0 },
headerBordered: true,
// 右侧卡片
colSpan: '76.5%',
};
if (leftCard) {
Object.assign(finalLeftCard, leftCard);
}
if (rightCard) {
Object.assign(finalRightCard, rightCard);
}
return (
<>
<ProCard
style={{ display: 'flex', width: '100%', background: 'transparent' }}
bodyStyle={{
padding: 0,
margin: 0,
display: 'flex',
justifyContent: 'space-between',
}}
>
{/* 后续依据业务需要动态调整 */}
<ProCard {...finalLeftCard}>{leftDom}</ProCard>
<ProCard {...finalRightCard}>{rightDom}</ProCard>
</ProCard>
</>
);
};
export default TreeAndTableList;

@ -0,0 +1,152 @@
import { useCallback, useEffect, useState, useRef } from 'react';
import { useMatchRoute } from './useMatchRoute';
import { history } from '@umijs/max';
export interface KeepAliveTab {
isHideTab: any;
title: string;
routePath: string;
key: string; // 这个key后面刷新有用到它
pathname: string;
icon?: any;
children: any;
}
function getKey() {
return new Date().getTime().toString();
}
export function useKeepAliveTabs() {
const [keepAliveTabs, setKeepAliveTabs] = useState<KeepAliveTab[]>([]);
const [activeTabRoutePath, setActiveTabRoutePath] = useState<string>('');
const keepAliveShowEvents = useRef<Record<string, Array<() => void>>>({});
const keepAliveHiddenEvents = useRef<Record<string, Array<() => void>>>({});
const matchRoute = useMatchRoute();
const onShow = useCallback((cb: () => void) => {
if (!keepAliveShowEvents.current[activeTabRoutePath]) {
keepAliveShowEvents.current[activeTabRoutePath] = [];
}
keepAliveShowEvents.current[activeTabRoutePath].push(cb);
}, [activeTabRoutePath])
const onHidden = useCallback((cb: () => void) => {
if (!keepAliveHiddenEvents.current[activeTabRoutePath]) {
keepAliveHiddenEvents.current[activeTabRoutePath] = [];
}
keepAliveHiddenEvents.current[activeTabRoutePath].push(cb);
}, [activeTabRoutePath])
// 关闭tab
const closeTab = useCallback(
(routePath: string = activeTabRoutePath) => {
const index = keepAliveTabs.findIndex(o => o.routePath === routePath);
if (keepAliveTabs[index].routePath === activeTabRoutePath) {
if (index > 0) {
history.push(keepAliveTabs[index - 1].routePath);
} else {
history.push(keepAliveTabs[index + 1].routePath);
}
}
keepAliveTabs.splice(index, 1);
delete keepAliveHiddenEvents.current[routePath];
delete keepAliveShowEvents.current[routePath];
setKeepAliveTabs([...keepAliveTabs]);
},
[activeTabRoutePath],
);
// 关闭其他
const closeOtherTab = useCallback((routePath: string = activeTabRoutePath) => {
const toCloseTabs = keepAliveTabs.filter(o => o.routePath !== routePath);
// 清除被关闭的tab注册的onShow事件和onHidden事件
toCloseTabs.forEach(tab => {
delete keepAliveHiddenEvents.current[tab.routePath];
delete keepAliveShowEvents.current[tab.routePath];
});
setKeepAliveTabs(prev => prev.filter(o => o.routePath === routePath));
}, [activeTabRoutePath]);
// 刷新tab
const refreshTab = useCallback((routePath: string = activeTabRoutePath) => {
setKeepAliveTabs(prev => {
const index = prev.findIndex(tab => tab.routePath === routePath);
if (index >= 0) {
// 这个react的特性key变了组件会卸载重新渲染
prev[index].key = getKey();
}
delete keepAliveHiddenEvents.current[prev[index].routePath];
delete keepAliveShowEvents.current[prev[index].routePath];
return [...prev];
});
}, [activeTabRoutePath]);
useEffect(() => {
if (!matchRoute) return;
const existKeepAliveTab = keepAliveTabs.find(o => o.routePath === matchRoute?.routePath);
setActiveTabRoutePath(matchRoute.routePath);
// 如果不存在则需要插入
if (!existKeepAliveTab) {
setKeepAliveTabs(prev => [...prev, {
title: matchRoute.title,
key: getKey(),
routePath: matchRoute.routePath,
pathname: matchRoute.pathname,
children: matchRoute.children,
icon: matchRoute.icon,
isHideTab: matchRoute.isHideTab
}]);
} else if (existKeepAliveTab.pathname !== matchRoute.pathname) {
// 如果是同一个路由但是参数不同我们只需要刷新当前页签并且把pathname设置为新的pathname children设置为新的children
setKeepAliveTabs(prev => {
const index = prev.findIndex(tab => tab.routePath === matchRoute.routePath);
if (index >= 0) {
prev[index].key = getKey();
prev[index].pathname = matchRoute.pathname;
prev[index].children = matchRoute.children;
}
delete keepAliveHiddenEvents.current[prev[index].routePath];
delete keepAliveShowEvents.current[prev[index].routePath];
return [...prev];
});
} else {
// 如果存在触发组件的onShow的回调
(keepAliveShowEvents.current[existKeepAliveTab.routePath] || []).forEach(cb => {
cb();
});
}
// 路由改变执行上一个tab的onHidden事件
(keepAliveHiddenEvents.current[activeTabRoutePath] || []).forEach(cb => {
cb();
});
}, [matchRoute])
return {
keepAliveTabs,
activeTabRoutePath,
closeTab,
refreshTab,
closeOtherTab,
onShow,
onHidden,
}
}

@ -0,0 +1,88 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33
* @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-10 11:26:54
* @FilePath: \general-ai-platform-web\src\layouts\useMatchRoute.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { IRoute, history, useAppData, useIntl, useLocation, useOutlet, useSelectedRoutes } from '@umijs/max';
import { useEffect, useState } from 'react';
type CustomIRoute = IRoute & {
name: string;
}
interface MatchRouteType {
title: string;
pathname: string; // /user/1
children: any;
routePath: string; // /user/:id
icon?: any;
isHideTab?: boolean
}
export function useMatchRoute() {
// 获取匹配到的路由
const selectedRoutes = useSelectedRoutes();
// 获取路由组件实例
const children = useOutlet();
// 获取所有路由
const { routes } = useAppData();
// 获取当前url
const { pathname } = useLocation();
// 国际化方法,因为默认菜单做了国际化,所以需要把菜单转成中文
const { formatMessage } = useIntl();
const [matchRoute, setMatchRoute] = useState<MatchRouteType | undefined>();
// 处理菜单名称
const getMenuTitle = (lastRoute: any) => {
let curRoute = lastRoute.route;
let names = ['menu'];
while (curRoute.parentId && !curRoute.isLayout) {
if ((routes[curRoute.parentId] as CustomIRoute).name) {
names.push((routes[curRoute.parentId] as CustomIRoute).name);
} else {
break;
}
curRoute = routes[curRoute.parentId];
}
names.push(lastRoute.route.name);
return formatMessage({ id: names.join('.') });
}
// 监听pathname变了说明路由有变化重新匹配返回新路由信息
useEffect(() => {
// 获取当前匹配的路由
const lastRoute = selectedRoutes.at(-1);
if (!lastRoute?.route?.path) return;
const routeDetail = routes[(lastRoute.route as any).id];
// 如果匹配的路由需要重定向,这里直接重定向
if (routeDetail?.redirect) {
history.replace(routeDetail?.redirect);
return;
}
// 获取菜单名称
const title = getMenuTitle(lastRoute);
console.log(lastRoute,'lastRoute')
setMatchRoute({
title,
pathname,
children,
routePath: lastRoute.route.path,
icon: (lastRoute.route as any).icon, // icon是拓展出来的字段
isHideTab: (lastRoute.route as any)?.isHideTab || false, //isHideTab 是否在tab栏位中隐藏
});
}, [pathname])
return matchRoute;
}

@ -0,0 +1,26 @@
import component from './bn-BD/component';
import globalHeader from './bn-BD/globalHeader';
import menu from './bn-BD/menu';
import pages from './bn-BD/pages';
import pwa from './bn-BD/pwa';
import settingDrawer from './bn-BD/settingDrawer';
import settings from './bn-BD/settings';
export default {
'navBar.lang': 'ভাষা',
'layout.user.link.help': 'সহায়তা',
'layout.user.link.privacy': 'গোপনীয়তা',
'layout.user.link.terms': 'শর্তাদি',
'app.copyright.produced': 'প্রযোজনা করেছেন অ্যান্ট ফিনান্সিয়াল এক্সপেরিয়েন্স ডিপার্টমেন্ট',
'app.preview.down.block': 'আপনার স্থানীয় প্রকল্পে এই পৃষ্ঠাটি ডাউনলোড করুন',
'app.welcome.link.fetch-blocks': 'সমস্ত ব্লক পান',
'app.welcome.link.block-list':
'`block` ডেভেলপমেন্ট এর উপর ভিত্তি করে দ্রুত স্ট্যান্ডার্ড, পৃষ্ঠাসমূহ তৈরি করুন।',
...globalHeader,
...menu,
...settingDrawer,
...settings,
...pwa,
...component,
...pages,
};

@ -0,0 +1,5 @@
export default {
'component.tagSelect.expand': 'বিস্তৃত',
'component.tagSelect.collapse': 'সঙ্কুচিত',
'component.tagSelect.all': 'সব',
};

@ -0,0 +1,17 @@
export default {
'component.globalHeader.search': 'অনুসন্ধান করুন',
'component.globalHeader.search.example1': 'অনুসন্ধান উদাহরণ ১',
'component.globalHeader.search.example2': 'অনুসন্ধান উদাহরণ ২',
'component.globalHeader.search.example3': 'অনুসন্ধান উদাহরণ ৩',
'component.globalHeader.help': 'সহায়তা',
'component.globalHeader.notification': 'বিজ্ঞপ্তি',
'component.globalHeader.notification.empty': 'আপনি সমস্ত বিজ্ঞপ্তি দেখেছেন।',
'component.globalHeader.message': 'বার্তা',
'component.globalHeader.message.empty': 'আপনি সমস্ত বার্তা দেখেছেন।',
'component.globalHeader.event': 'ঘটনা',
'component.globalHeader.event.empty': 'আপনি সমস্ত ইভেন্ট দেখেছেন।',
'component.noticeIcon.clear': 'সাফ',
'component.noticeIcon.cleared': 'সাফ করা হয়েছে',
'component.noticeIcon.empty': 'বিজ্ঞপ্তি নেই',
'component.noticeIcon.view-more': 'আরো দেখুন',
};

@ -0,0 +1,52 @@
export default {
'menu.welcome': 'স্বাগতম',
'menu.more-blocks': 'আরও ব্লক',
'menu.home': 'নীড়',
'menu.admin': 'অ্যাডমিন',
'menu.admin.sub-page': 'উপ-পৃষ্ঠা',
'menu.login': 'প্রবেশ',
'menu.register': 'নিবন্ধন',
'menu.register-result': 'নিবন্ধনে ফলাফল',
'menu.dashboard': 'ড্যাশবোর্ড',
'menu.dashboard.analysis': 'বিশ্লেষণ',
'menu.dashboard.monitor': 'নিরীক্ষণ',
'menu.dashboard.workplace': 'কর্মক্ষেত্র',
'menu.exception.403': '403',
'menu.exception.404': '404',
'menu.exception.500': '500',
'menu.form': 'ফর্ম',
'menu.form.basic-form': 'বেসিক ফর্ম',
'menu.form.step-form': 'পদক্ষেপ ফর্ম',
'menu.form.step-form.info': 'পদক্ষেপ ফর্ম (স্থানান্তর তথ্য লিখুন)',
'menu.form.step-form.confirm': 'পদক্ষেপ ফর্ম (স্থানান্তর তথ্য নিশ্চিত করুন)',
'menu.form.step-form.result': 'পদক্ষেপ ফর্ম (সমাপ্ত)',
'menu.form.advanced-form': 'উন্নত ফর্ম',
'menu.list': 'তালিকা',
'menu.list.table-list': 'অনুসন্ধানের টেবিল',
'menu.list.basic-list': 'বেসিক তালিকা',
'menu.list.card-list': 'কার্ডের তালিকা',
'menu.list.search-list': 'অনুসন্ধানের তালিকা',
'menu.list.search-list.articles': 'অনুসন্ধানের তালিকা (নিবন্ধসমূহ)',
'menu.list.search-list.projects': 'অনুসন্ধানের তালিকা (প্রকল্পগুলি)',
'menu.list.search-list.applications': 'অনুসন্ধানের তালিকা (অ্যাপ্লিকেশন)',
'menu.profile': 'প্রোফাইল',
'menu.profile.basic': 'বেসিক প্রোফাইল',
'menu.profile.advanced': 'উন্নত প্রোফাইল',
'menu.result': 'ফলাফল',
'menu.result.success': 'সাফল্য',
'menu.result.fail': 'ব্যর্থ',
'menu.exception': 'ব্যতিক্রম',
'menu.exception.not-permission': '403',
'menu.exception.not-find': '404',
'menu.exception.server-error': '500',
'menu.exception.trigger': 'ট্রিগার',
'menu.account': 'হিসাব',
'menu.account.center': 'অ্যাকাউন্ট কেন্দ্র',
'menu.account.settings': 'অ্যাকাউন্ট সেটিংস',
'menu.account.trigger': 'ট্রিগার ত্রুটি',
'menu.account.logout': 'প্রস্থান',
'menu.editor': 'গ্রাফিক সম্পাদক',
'menu.editor.flow': 'ফ্লো এডিটর',
'menu.editor.mind': 'মাইন্ড এডিটর',
'menu.editor.koni': 'কোনি সম্পাদক',
};

@ -0,0 +1,68 @@
export default {
'pages.layouts.userLayout.title':
'পিঁপড়া ডিজাইন হচ্ছে সিহু জেলার সবচেয়ে প্রভাবশালী ওয়েব ডিজাইনের স্পেসিফিকেশন',
'pages.login.accountLogin.tab': 'অ্যাকাউন্টে লগইন',
'pages.login.accountLogin.errorMessage': 'ভুল ব্যবহারকারীর নাম/পাসওয়ার্ড(admin/ant.design)',
'pages.login.failure': 'লগইন ব্যর্থ হয়েছে। আবার চেষ্টা করুন!',
'pages.login.success': 'সফল লগইন!',
'pages.login.username.placeholder': 'ব্যবহারকারীর নাম: admin or user',
'pages.login.username.required': 'আপনার ব্যবহারকারীর নাম ইনপুট করুন!',
'pages.login.password.placeholder': 'পাসওয়ার্ড: ant.design',
'pages.login.password.required': 'আপনার পাসওয়ার্ড ইনপুট করুন!',
'pages.login.phoneLogin.tab': 'ফোন লগইন',
'pages.login.phoneLogin.errorMessage': 'যাচাইকরণ কোড ত্রুটি',
'pages.login.phoneNumber.placeholder': 'ফোন নম্বর',
'pages.login.phoneNumber.required': 'আপনার ফোন নম্বর ইনপুট করুন!',
'pages.login.phoneNumber.invalid': 'ফোন নম্বরটি সঠিক নয়!',
'pages.login.captcha.placeholder': 'যাচাইকরণের কোড',
'pages.login.captcha.required': 'দয়া করে ভেরিফিকেশন কোডটি ইনপুট করুন!',
'pages.login.phoneLogin.getVerificationCode': 'কোড পান',
'pages.getCaptchaSecondText': 'সেকেন্ড',
'pages.login.rememberMe': 'আমাকে মনে রাখুন',
'pages.login.forgotPassword': 'পাসওয়ার্ড ভুলে গেছেন?',
'pages.login.submit': 'প্রবেশ করুন',
'pages.login.loginWith': 'লগইন করতে পারেন:',
'pages.login.registerAccount': 'অ্যাকাউন্ট নিবন্ধন করুন',
'pages.welcome.link': 'স্বাগতম',
'pages.welcome.alertMessage': 'দ্রুত এবং শক্তিশালী ভারী শুল্ক উপাদান প্রকাশ করা হয়েছে।',
'pages.admin.subPage.title': 'এই পৃষ্ঠাটি কেবল অ্যাডমিন দ্বারা দেখা যাবে',
'pages.admin.subPage.alertMessage':
'UMI UI এখন প্রকাশিত হয়েছে, অভিজ্ঞতা শুরু করতে npm run ui ব্যবহার করতে স্বাগতম।',
'pages.searchTable.createForm.newRule': 'নতুন বিধি',
'pages.searchTable.updateForm.ruleConfig': 'বিধি কনফিগারেশন',
'pages.searchTable.updateForm.basicConfig': 'মৌলিক তথ্য',
'pages.searchTable.updateForm.ruleName.nameLabel': 'বিধি নাম',
'pages.searchTable.updateForm.ruleName.nameRules': 'বিধির নাম লিখুন!',
'pages.searchTable.updateForm.ruleDesc.descLabel': 'বিধির বিবরণ',
'pages.searchTable.updateForm.ruleDesc.descPlaceholder': 'কমপক্ষে পাঁচটি অক্ষর লিখুন',
'pages.searchTable.updateForm.ruleDesc.descRules':
'কমপক্ষে পাঁচটি অক্ষরের একটি বিধান বিবরণ লিখুন!',
'pages.searchTable.updateForm.ruleProps.title': 'বৈশিষ্ট্য কনফিগার করুন',
'pages.searchTable.updateForm.object': 'নিরীক্ষণ অবজেক্ট',
'pages.searchTable.updateForm.ruleProps.templateLabel': 'বিধি টেম্পলেট',
'pages.searchTable.updateForm.ruleProps.typeLabel': 'বিধি প্রকার',
'pages.searchTable.updateForm.schedulingPeriod.title': 'সময়সূচী নির্ধারণ করুন',
'pages.searchTable.updateForm.schedulingPeriod.timeLabel': 'শুরুর সময়',
'pages.searchTable.updateForm.schedulingPeriod.timeRules': 'একটি শুরুর সময় চয়ন করুন!',
'pages.searchTable.titleDesc': 'বর্ণনা',
'pages.searchTable.ruleName': 'বিধি নাম প্রয়োজন',
'pages.searchTable.titleCallNo': 'পরিষেবা কল সংখ্যা',
'pages.searchTable.titleStatus': 'অবস্থা',
'pages.searchTable.nameStatus.default': 'ডিফল্ট',
'pages.searchTable.nameStatus.running': 'চলমান',
'pages.searchTable.nameStatus.online': 'অনলাইন',
'pages.searchTable.nameStatus.abnormal': 'অস্বাভাবিক',
'pages.searchTable.titleUpdatedAt': 'সর্বশেষ নির্ধারিত',
'pages.searchTable.exception': 'ব্যতিক্রম জন্য কারণ লিখুন!',
'pages.searchTable.titleOption': 'অপশন',
'pages.searchTable.config': 'কনফিগারেশন',
'pages.searchTable.subscribeAlert': 'সতর্কতা সাবস্ক্রাইব করুন',
'pages.searchTable.title': 'ইনকয়েরি ফরম',
'pages.searchTable.new': 'নতুন',
'pages.searchTable.chosen': 'নির্বাচিত',
'pages.searchTable.item': 'আইটেম',
'pages.searchTable.totalServiceCalls': 'পরিষেবা কলগুলির মোট সংখ্যা',
'pages.searchTable.tenThousand': '000',
'pages.searchTable.batchDeletion': 'একসাখে ডিলিট',
'pages.searchTable.batchApproval': 'একসাখে অনুমোদন',
};

@ -0,0 +1,7 @@
export default {
'app.pwa.offline': 'আপনি এখন অফলাইন',
'app.pwa.serviceworker.updated': 'নতুন সামগ্রী উপলব্ধ',
'app.pwa.serviceworker.updated.hint':
'বর্তমান পৃষ্ঠাটি পুনরায় লোড করতে দয়া করে "রিফ্রেশ" বোতাম টিপুন',
'app.pwa.serviceworker.updated.ok': 'রিফ্রেশ',
};

@ -0,0 +1,31 @@
export default {
'app.setting.pagestyle': 'পৃষ্ঠা স্টাইল সেটিং',
'app.setting.pagestyle.dark': 'ডার্ক স্টাইল',
'app.setting.pagestyle.light': 'লাইট স্টাইল',
'app.setting.content-width': 'সামগ্রীর প্রস্থ',
'app.setting.content-width.fixed': 'স্থির',
'app.setting.content-width.fluid': 'প্রবাহী',
'app.setting.themecolor': 'থিম রঙ',
'app.setting.themecolor.dust': 'ডাস্ট রেড',
'app.setting.themecolor.volcano': 'আগ্নেয়গিরি',
'app.setting.themecolor.sunset': 'সানসেট কমলা',
'app.setting.themecolor.cyan': 'সবুজাভ নীল',
'app.setting.themecolor.green': 'পোলার সবুজ',
'app.setting.themecolor.daybreak': 'দিবস ব্রেক ব্লু (ডিফল্ট)',
'app.setting.themecolor.geekblue': 'গিক আঠালো',
'app.setting.themecolor.purple': 'গোল্ডেন বেগুনি',
'app.setting.navigationmode': 'নেভিগেশন মোড',
'app.setting.sidemenu': 'সাইড মেনু লেআউট',
'app.setting.topmenu': 'টপ মেনু লেআউট',
'app.setting.fixedheader': 'স্থির হেডার',
'app.setting.fixedsidebar': 'স্থির সাইডবার',
'app.setting.fixedsidebar.hint': 'সাইড মেনু বিন্যাসে কাজ করে',
'app.setting.hideheader': 'স্ক্রোল করার সময় হেডার লুকানো',
'app.setting.hideheader.hint': 'লুকানো হেডার সক্ষম থাকলে কাজ করে',
'app.setting.othersettings': 'অন্যান্য সেটিংস্',
'app.setting.weakmode': 'দুর্বল মোড',
'app.setting.copy': 'সেটিং কপি করুন',
'app.setting.copyinfo': 'সাফল্যের অনুলিপি করুন - প্রতিস্থাপন করুন: src/models/setting.js',
'app.setting.production.hint':
'কেবল বিকাশের পরিবেশে প্যানেল শো সেট করা হচ্ছে, দয়া করে ম্যানুয়ালি সংশোধন করুন',
};

@ -0,0 +1,59 @@
export default {
'app.settings.menuMap.basic': 'মৌলিক বৈশিষ্ট্যসহ',
'app.settings.menuMap.security': 'নিরাপত্তা বিন্যাস',
'app.settings.menuMap.binding': 'অ্যাকাউন্ট বাঁধাই',
'app.settings.menuMap.notification': 'নতুন বার্তা বিজ্ঞপ্তি',
'app.settings.basic.avatar': 'অবতার',
'app.settings.basic.change-avatar': 'অবতার পরিবর্তন করুন',
'app.settings.basic.email': 'ইমেইল',
'app.settings.basic.email-message': 'আপনার ইমেইল ইনপুট করুন!',
'app.settings.basic.nickname': 'ডাক নাম',
'app.settings.basic.nickname-message': 'আপনার ডাকনামটি ইনপুট করুন!',
'app.settings.basic.profile': 'ব্যক্তিগত প্রোফাইল',
'app.settings.basic.profile-message': 'আপনার ব্যক্তিগত প্রোফাইল ইনপুট করুন!',
'app.settings.basic.profile-placeholder': 'নিজের সাথে সংক্ষিপ্ত পরিচয়',
'app.settings.basic.country': 'দেশ/অঞ্চল',
'app.settings.basic.country-message': 'আপনার দেশ ইনপুট করুন!',
'app.settings.basic.geographic': 'প্রদেশ বা শহর',
'app.settings.basic.geographic-message': 'আপনার ভৌগলিক তথ্য ইনপুট করুন!',
'app.settings.basic.address': 'রাস্তার ঠিকানা',
'app.settings.basic.address-message': 'দয়া করে আপনার ঠিকানা ইনপুট করুন!',
'app.settings.basic.phone': 'ফোন নম্বর',
'app.settings.basic.phone-message': 'আপনার ফোন ইনপুট করুন!',
'app.settings.basic.update': 'তথ্য হালনাগাদ',
'app.settings.security.strong': 'শক্তিশালী',
'app.settings.security.medium': 'মধ্যম',
'app.settings.security.weak': 'দুর্বল',
'app.settings.security.password': 'অ্যাকাউন্টের পাসওয়ার্ড',
'app.settings.security.password-description': 'বর্তমান পাসওয়ার্ড শক্তি',
'app.settings.security.phone': 'সুরক্ষা ফোন',
'app.settings.security.phone-description': 'আবদ্ধ ফোন',
'app.settings.security.question': 'নিরাপত্তা প্রশ্ন',
'app.settings.security.question-description':
'সুরক্ষা প্রশ্ন সেট করা নেই, এবং সুরক্ষা নীতি কার্যকরভাবে অ্যাকাউন্ট সুরক্ষা রক্ষা করতে পারে',
'app.settings.security.email': 'ব্যাকআপ ইমেইল',
'app.settings.security.email-description': 'বাউন্ড ইমেইল',
'app.settings.security.mfa': 'MFA ডিভাইস',
'app.settings.security.mfa-description':
"আনবাউন্ড এমএফএ ডিভাইস, বাঁধাইয়ের পরে, দু'বার নিশ্চিত করা যায়",
'app.settings.security.modify': 'পরিবর্তন করুন',
'app.settings.security.set': 'সেট',
'app.settings.security.bind': 'বাঁধাই',
'app.settings.binding.taobao': 'বাঁধাই তাওবাও',
'app.settings.binding.taobao-description': 'বর্তমানে আনবাউন্ড তাওবাও অ্যাকাউন্ট',
'app.settings.binding.alipay': 'বাইন্ডিং আলিপে',
'app.settings.binding.alipay-description': 'বর্তমানে আনবাউন্ড আলিপে অ্যাকাউন্ট',
'app.settings.binding.dingding': 'বাঁধাই ডিঙ্গটালক',
'app.settings.binding.dingding-description': 'বর্তমানে আনবাউন্ড ডিঙ্গটাল অ্যাকাউন্ট',
'app.settings.binding.bind': 'বাঁধাই',
'app.settings.notification.password': 'অ্যাকাউন্টের পাসওয়ার্ড',
'app.settings.notification.password-description':
'অন্যান্য ব্যবহারকারীর বার্তাগুলি স্টেশন চিঠি আকারে জানানো হবে',
'app.settings.notification.messages': 'সিস্টেম বার্তা',
'app.settings.notification.messages-description':
'সিস্টেম বার্তাগুলি স্টেশন চিঠির আকারে জানানো হবে',
'app.settings.notification.todo': 'করণীয় বিজ্ঞপ্তি',
'app.settings.notification.todo-description': 'করণীয় তালিকাটি স্টেশন থেকে চিঠি আকারে জানানো হবে',
'app.settings.open': 'খোলা',
'app.settings.close': 'বন্ধ',
};

@ -0,0 +1,29 @@
import component from './en-US/component';
import globalHeader from './en-US/globalHeader';
import menu from './en-US/menu';
import pages from './en-US/pages';
import pwa from './en-US/pwa';
import settingDrawer from './en-US/settingDrawer';
import settings from './en-US/settings';
import * as deviceEn from "@/locales/en-US/device";
import * as resourceEn from "@/locales/en-US/resource";
export default {
'navBar.lang': 'Languages',
'layout.user.link.help': 'Help',
'layout.user.link.privacy': 'Privacy',
'layout.user.link.terms': 'Terms',
'app.copyright.produced': 'Produced by Ant Financial Experience Department',
'app.preview.down.block': 'Download this page to your local project',
'app.welcome.link.fetch-blocks': 'Get all block',
'app.welcome.link.block-list': 'Quickly build standard, pages based on `block` development',
...globalHeader,
...menu,
...settingDrawer,
...settings,
...pwa,
...component,
...pages,
...Object.assign({}, ...Object.values(deviceEn)),
...Object.assign({}, ...Object.values(resourceEn)),
};

@ -0,0 +1,5 @@
export default {
'component.tagSelect.expand': 'Expand',
'component.tagSelect.collapse': 'Collapse',
'component.tagSelect.all': 'All',
};

@ -0,0 +1,4 @@
export const device: {[key: string]: string} = {'device.device.table.list.id': 'id', 'device.device.table.list.name': 'name', 'device.device.table.list.code': 'code', 'device.device.table.list.position': 'position', 'device.device.table.list.param': 'param', 'device.device.table.list.spec': 'spec', 'device.device.table.list.categoryFkId': 'category_fk_id', 'device.device.table.list.groupFkId': 'group_fk_id', 'device.device.table.list.isEnable': 'is_enable', 'device.device.table.list.remark': 'remark', 'device.device.table.list.createTime': 'create_time', 'device.device.table.list.updateTime': 'update_time', 'device.device.table.rule.required.name': 'name is required', 'device.device.table.rule.required.code': 'code is required'}
export const device_category: {[key: string]: string} = {'device.device_category.table.list.id': 'id', 'device.device_category.table.list.name': 'name', 'device.device_category.table.list.code': 'code', 'device.device_category.table.list.remark': 'remark', 'device.device_category.table.list.createTime': 'create_time', 'device.device_category.table.list.updateTime': 'update_time', 'device.device_category.table.rule.required.name': 'name is required', 'device.device_category.table.rule.required.code': 'code is required'}
export const device_group: {[key: string]: string} = {'device.device_group.table.list.id': 'id', 'device.device_group.table.list.name': 'name', 'device.device_group.table.list.code': 'code', 'device.device_group.table.list.address': 'address', 'device.device_group.table.list.telephone': 'telephone', 'device.device_group.table.list.lon': 'lon', 'device.device_group.table.list.lat': 'lat', 'device.device_group.table.list.managerName': 'manager_name', 'device.device_group.table.list.managerPhone': 'manager_phone', 'device.device_group.table.list.isEnable': 'is_enable', 'device.device_group.table.list.parentFkId': 'parent_fk_id', 'device.device_group.table.list.remark': 'remark', 'device.device_group.table.list.createTime': 'create_time', 'device.device_group.table.list.updateTime': 'update_time', 'device.device_group.table.rule.required.name': 'name is required', 'device.device_group.table.rule.required.code': 'code is required', 'device.device_group.table.rule.required.managerName': 'manager_name is required', 'device.device_group.table.rule.required.managerPhone': 'manager_phone is required', 'device.device_group.table.rule.required.parentFkId': 'parent_fk_id is required'}
export const device_relation: {[key: string]: string} = {'device.device_relation.table.list.id': 'id', 'device.device_relation.table.list.deviceParentFkId': 'device_parent_fk_id', 'device.device_relation.table.list.deviceSonFkId': 'device_son_fk_id', 'device.device_relation.table.list.createTime': 'create_time', 'device.device_relation.table.list.updateTime': 'update_time', 'device.device_relation.table.rule.required.deviceParentFkId': 'device_parent_fk_id is required', 'device.device_relation.table.rule.required.deviceSonFkId': 'device_son_fk_id is required'}

@ -0,0 +1,17 @@
export default {
'component.globalHeader.search': 'Search',
'component.globalHeader.search.example1': 'Search example 1',
'component.globalHeader.search.example2': 'Search example 2',
'component.globalHeader.search.example3': 'Search example 3',
'component.globalHeader.help': 'Help',
'component.globalHeader.notification': 'Notification',
'component.globalHeader.notification.empty': 'You have viewed all notifications.',
'component.globalHeader.message': 'Message',
'component.globalHeader.message.empty': 'You have viewed all messsages.',
'component.globalHeader.event': 'Event',
'component.globalHeader.event.empty': 'You have viewed all events.',
'component.noticeIcon.clear': 'Clear',
'component.noticeIcon.cleared': 'Cleared',
'component.noticeIcon.empty': 'No notifications',
'component.noticeIcon.view-more': 'View more',
};

@ -0,0 +1,52 @@
export default {
'menu.welcome': 'Welcome',
'menu.more-blocks': 'More Blocks',
'menu.home': 'Home',
'menu.admin': 'Admin',
'menu.admin.sub-page': 'Sub-Page',
'menu.login': 'Login',
'menu.register': 'Register',
'menu.register-result': 'Register Result',
'menu.dashboard': 'Dashboard',
'menu.dashboard.analysis': 'Analysis',
'menu.dashboard.monitor': 'Monitor',
'menu.dashboard.workplace': 'Workplace',
'menu.exception.403': '403',
'menu.exception.404': '404',
'menu.exception.500': '500',
'menu.form': 'Form',
'menu.form.basic-form': 'Basic Form',
'menu.form.step-form': 'Step Form',
'menu.form.step-form.info': 'Step Form(write transfer information)',
'menu.form.step-form.confirm': 'Step Form(confirm transfer information)',
'menu.form.step-form.result': 'Step Form(finished)',
'menu.form.advanced-form': 'Advanced Form',
'menu.list': 'List',
'menu.list.table-list': 'Search Table',
'menu.list.basic-list': 'Basic List',
'menu.list.card-list': 'Card List',
'menu.list.search-list': 'Search List',
'menu.list.search-list.articles': 'Search List(articles)',
'menu.list.search-list.projects': 'Search List(projects)',
'menu.list.search-list.applications': 'Search List(applications)',
'menu.profile': 'Profile',
'menu.profile.basic': 'Basic Profile',
'menu.profile.advanced': 'Advanced Profile',
'menu.result': 'Result',
'menu.result.success': 'Success',
'menu.result.fail': 'Fail',
'menu.exception': 'Exception',
'menu.exception.not-permission': '403',
'menu.exception.not-find': '404',
'menu.exception.server-error': '500',
'menu.exception.trigger': 'Trigger',
'menu.account': 'Account',
'menu.account.center': 'Account Center',
'menu.account.settings': 'Account Settings',
'menu.account.trigger': 'Trigger Error',
'menu.account.logout': 'Logout',
'menu.editor': 'Graphic Editor',
'menu.editor.flow': 'Flow Editor',
'menu.editor.mind': 'Mind Editor',
'menu.editor.koni': 'Koni Editor',
};

@ -0,0 +1,68 @@
export default {
'pages.layouts.userLayout.title':
'Ant Design is the most influential web design specification in Xihu district',
'pages.login.accountLogin.tab': 'Account Login',
'pages.login.accountLogin.errorMessage': 'Incorrect username/password(admin/ant.design)',
'pages.login.failure': 'Login failed, please try again!',
'pages.login.success': 'Login successful!',
'pages.login.username.placeholder': 'Username: admin or user',
'pages.login.username.required': 'Please input your username!',
'pages.login.password.placeholder': 'Password: ant.design',
'pages.login.password.required': 'Please input your password!',
'pages.login.phoneLogin.tab': 'Phone Login',
'pages.login.phoneLogin.errorMessage': 'Verification Code Error',
'pages.login.phoneNumber.placeholder': 'Phone Number',
'pages.login.phoneNumber.required': 'Please input your phone number!',
'pages.login.phoneNumber.invalid': 'Phone number is invalid!',
'pages.login.captcha.placeholder': 'Verification Code',
'pages.login.captcha.required': 'Please input verification code!',
'pages.login.phoneLogin.getVerificationCode': 'Get Code',
'pages.getCaptchaSecondText': 'sec(s)',
'pages.login.rememberMe': 'Remember me',
'pages.login.forgotPassword': 'Forgot Password ?',
'pages.login.submit': 'Login',
'pages.login.loginWith': 'Login with :',
'pages.login.registerAccount': 'Register Account',
'pages.welcome.link': 'Welcome',
'pages.welcome.alertMessage': 'Faster and stronger heavy-duty components have been released.',
'pages.admin.subPage.title': 'This page can only be viewed by Admin',
'pages.admin.subPage.alertMessage':
'Umi ui is now released, welcome to use npm run ui to start the experience.',
'pages.searchTable.createForm.newRule': 'New Rule',
'pages.searchTable.updateForm.ruleConfig': 'Rule configuration',
'pages.searchTable.updateForm.basicConfig': 'Basic Information',
'pages.searchTable.updateForm.ruleName.nameLabel': 'Rule Name',
'pages.searchTable.updateForm.ruleName.nameRules': 'Please enter the rule name!',
'pages.searchTable.updateForm.ruleDesc.descLabel': 'Rule Description',
'pages.searchTable.updateForm.ruleDesc.descPlaceholder': 'Please enter at least five characters',
'pages.searchTable.updateForm.ruleDesc.descRules':
'Please enter a rule description of at least five characters!',
'pages.searchTable.updateForm.ruleProps.title': 'Configure Properties',
'pages.searchTable.updateForm.object': 'Monitoring Object',
'pages.searchTable.updateForm.ruleProps.templateLabel': 'Rule Template',
'pages.searchTable.updateForm.ruleProps.typeLabel': 'Rule Type',
'pages.searchTable.updateForm.schedulingPeriod.title': 'Set Scheduling Period',
'pages.searchTable.updateForm.schedulingPeriod.timeLabel': 'Starting Time',
'pages.searchTable.updateForm.schedulingPeriod.timeRules': 'Please choose a start time!',
'pages.searchTable.titleDesc': 'Description',
'pages.searchTable.ruleName': 'Rule name is required',
'pages.searchTable.titleCallNo': 'Number of Service Calls',
'pages.searchTable.titleStatus': 'Status',
'pages.searchTable.nameStatus.default': 'default',
'pages.searchTable.nameStatus.running': 'running',
'pages.searchTable.nameStatus.online': 'online',
'pages.searchTable.nameStatus.abnormal': 'abnormal',
'pages.searchTable.titleUpdatedAt': 'Last Scheduled at',
'pages.searchTable.exception': 'Please enter the reason for the exception!',
'pages.searchTable.titleOption': 'Option',
'pages.searchTable.config': 'Configuration',
'pages.searchTable.subscribeAlert': 'Subscribe to alerts',
'pages.searchTable.title': 'Enquiry Form',
'pages.searchTable.new': 'New',
'pages.searchTable.chosen': 'chosen',
'pages.searchTable.item': 'item',
'pages.searchTable.totalServiceCalls': 'Total Number of Service Calls',
'pages.searchTable.tenThousand': '0000',
'pages.searchTable.batchDeletion': 'batch deletion',
'pages.searchTable.batchApproval': 'batch approval',
};

@ -0,0 +1,6 @@
export default {
'app.pwa.offline': 'You are offline now',
'app.pwa.serviceworker.updated': 'New content is available',
'app.pwa.serviceworker.updated.hint': 'Please press the "Refresh" button to reload current page',
'app.pwa.serviceworker.updated.ok': 'Refresh',
};

@ -0,0 +1,3 @@
export const algorithm_model: {[key: string]: string} = {'resource.algorithm_model.table.list.id': 'id', 'resource.algorithm_model.table.list.name': 'name', 'resource.algorithm_model.table.list.type': 'type', 'resource.algorithm_model.table.list.remark': 'remark', 'resource.algorithm_model.table.list.createTime': 'create_time', 'resource.algorithm_model.table.list.updateTime': 'update_time', 'resource.algorithm_model.table.rule.required.name': 'name is required'}
export const container_image: {[key: string]: string} = {'resource.container_image.table.list.id': 'id', 'resource.container_image.table.list.name': 'name', 'resource.container_image.table.list.version': 'version', 'resource.container_image.table.list.path': 'path', 'resource.container_image.table.list.startCode': 'start_code', 'resource.container_image.table.list.type': 'type', 'resource.container_image.table.list.remark': 'remark', 'resource.container_image.table.list.createTime': 'create_time', 'resource.container_image.table.list.updateTime': 'update_time', 'resource.container_image.table.rule.required.name': 'name is required', 'resource.container_image.table.rule.required.version': 'version is required'}
export const model_version: {[key: string]: string} = {'resource.model_version.table.list.id': 'id', 'resource.model_version.table.list.modelFkId': 'model_fk_id', 'resource.model_version.table.list.version': 'version', 'resource.model_version.table.list.path': 'path', 'resource.model_version.table.list.startCode': 'start_code', 'resource.model_version.table.list.isEnable': 'is_enable', 'resource.model_version.table.list.remark': 'remark', 'resource.model_version.table.list.createTime': 'create_time', 'resource.model_version.table.list.updateTime': 'update_time', 'resource.model_version.table.rule.required.modelFkId': 'model_fk_id is required', 'resource.model_version.table.rule.required.path': 'path is required'}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save