| @@ -1,8 +1,8 @@ | |||||
| module.exports = { | module.exports = { | ||||
| extends: [ | extends: [ | ||||
| require.resolve('@umijs/lint/dist/config/eslint'), | |||||
| 'plugin:react/recommended', | |||||
| "plugin:react-hooks/recommended" | |||||
| require.resolve('@umijs/lint/dist/config/eslint'), | |||||
| 'plugin:react/recommended', | |||||
| 'plugin:react-hooks/recommended', | |||||
| ], | ], | ||||
| globals: { | globals: { | ||||
| page: true, | page: true, | ||||
| @@ -11,6 +11,6 @@ module.exports = { | |||||
| rules: { | rules: { | ||||
| '@typescript-eslint/no-use-before-define': 'off', | '@typescript-eslint/no-use-before-define': 'off', | ||||
| 'react/react-in-jsx-scope': 'off', | 'react/react-in-jsx-scope': 'off', | ||||
| 'react/display-name': 'off' | |||||
| 'react/display-name': 'off', | |||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -20,3 +20,4 @@ yarn-error.log | |||||
| CNAME | CNAME | ||||
| /build | /build | ||||
| /public | /public | ||||
| /src/iconfont/ | |||||
| @@ -1,4 +1,4 @@ | |||||
| export default function(babel) { | |||||
| export default function (babel) { | |||||
| const { types: t } = babel; | const { types: t } = babel; | ||||
| return { | return { | ||||
| visitor: { | visitor: { | ||||
| @@ -6,10 +6,10 @@ export default function(babel) { | |||||
| const source = path.node.source.value; | const source = path.node.source.value; | ||||
| if (source.endsWith('.less')) { | if (source.endsWith('.less')) { | ||||
| if (path.node.specifiers.length > 0) { | if (path.node.specifiers.length > 0) { | ||||
| path.node.source.value += "?modules"; | |||||
| path.node.source.value += '?modules'; | |||||
| } | } | ||||
| } | } | ||||
| }, | }, | ||||
| }, | }, | ||||
| }; | }; | ||||
| }; | |||||
| } | |||||
| @@ -6,7 +6,7 @@ export const createWebSocketMock = () => { | |||||
| this.listeners = {}; | this.listeners = {}; | ||||
| this.count = 0; | this.count = 0; | ||||
| console.log("Mock WebSocket connected to:", url); | |||||
| console.log('Mock WebSocket connected to:', url); | |||||
| // 模拟服务器推送消息 | // 模拟服务器推送消息 | ||||
| this.intervalId = setInterval(() => { | this.intervalId = setInterval(() => { | ||||
| @@ -21,8 +21,8 @@ export const createWebSocketMock = () => { | |||||
| } | } | ||||
| sendMessage(data) { | sendMessage(data) { | ||||
| if (this.listeners["message"]) { | |||||
| this.listeners["message"].forEach((callback) => callback({ data })); | |||||
| if (this.listeners['message']) { | |||||
| this.listeners['message'].forEach((callback) => callback({ data })); | |||||
| } | } | ||||
| } | } | ||||
| @@ -41,7 +41,7 @@ export const createWebSocketMock = () => { | |||||
| close() { | close() { | ||||
| this.readyState = WebSocket.CLOSED; | this.readyState = WebSocket.CLOSED; | ||||
| console.log("Mock WebSocket closed"); | |||||
| console.log('Mock WebSocket closed'); | |||||
| } | } | ||||
| } | } | ||||
| @@ -89,4 +89,4 @@ export const logStreamData = { | |||||
| ], | ], | ||||
| }, | }, | ||||
| ], | ], | ||||
| }; | |||||
| }; | |||||
| @@ -1 +1 @@ | |||||
| # Documentation | |||||
| # Documentation | |||||
| @@ -1,5 +1,5 @@ | |||||
| import { message } from 'antd'; | |||||
| import ClipboardJS from 'clipboard'; | import ClipboardJS from 'clipboard'; | ||||
| import { message } from "antd"; | |||||
| const clipboard = new ClipboardJS('#copying'); | const clipboard = new ClipboardJS('#copying'); | ||||
| @@ -9,4 +9,4 @@ clipboard.on('success', () => { | |||||
| clipboard.on('error', () => { | clipboard.on('error', () => { | ||||
| message.error('复制失败'); | message.error('复制失败'); | ||||
| }); | |||||
| }); | |||||
| @@ -86,6 +86,19 @@ export const serviceTypeOptions = [ | |||||
| { label: '文本', value: ServiceType.Text }, | { label: '文本', value: ServiceType.Text }, | ||||
| ]; | ]; | ||||
| // 自动化类型 | |||||
| export enum AutoMLType { | |||||
| Table = 'auto_ml', | |||||
| Text = 'text_classification', | |||||
| Video = 'video_classification', | |||||
| } | |||||
| export const autoMLTypeOptions = [ | |||||
| { label: '表格', value: AutoMLType.Table }, | |||||
| { label: '文本分类', value: AutoMLType.Text }, | |||||
| { label: '视频分类', value: AutoMLType.Video }, | |||||
| ]; | |||||
| // 自动化任务类型 | // 自动化任务类型 | ||||
| export enum AutoMLTaskType { | export enum AutoMLTaskType { | ||||
| Classification = 'classification', | Classification = 'classification', | ||||
| @@ -148,4 +161,5 @@ export enum AutoMLTrailStatus { | |||||
| CRASHED = 'CRASHED', // 崩溃 | CRASHED = 'CRASHED', // 崩溃 | ||||
| STOP = 'STOP', // 停止 | STOP = 'STOP', // 停止 | ||||
| CANCELLED = 'CANCELLED', // 取消 | CANCELLED = 'CANCELLED', // 取消 | ||||
| MEMOUT = 'MEMOUT', // 内存溢出 | |||||
| } | } | ||||
| @@ -30,27 +30,26 @@ function CreateActiveLearn() { | |||||
| const isCopy = pathname.includes('copy'); | const isCopy = pathname.includes('copy'); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| // 获取服务详情 | |||||
| const getActiveLearnInfo = async (id: number) => { | |||||
| const [res] = await to(getActiveLearnInfoReq({ id })); | |||||
| if (res && res.data) { | |||||
| const info: ActiveLearnData = res.data; | |||||
| const { name: name_str, ...rest } = info; | |||||
| const name = isCopy ? `${name_str}-copy` : name_str; | |||||
| const formData = { | |||||
| ...rest, | |||||
| name, | |||||
| }; | |||||
| form.setFieldsValue(formData); | |||||
| } | |||||
| }; | |||||
| // 编辑,复制 | // 编辑,复制 | ||||
| if (id && !Number.isNaN(id)) { | if (id && !Number.isNaN(id)) { | ||||
| getActiveLearnInfo(id); | getActiveLearnInfo(id); | ||||
| } | } | ||||
| }, [id]); | |||||
| // 获取服务详情 | |||||
| const getActiveLearnInfo = async (id: number) => { | |||||
| const [res] = await to(getActiveLearnInfoReq({ id })); | |||||
| if (res && res.data) { | |||||
| const info: ActiveLearnData = res.data; | |||||
| const { name: name_str, ...rest } = info; | |||||
| const name = isCopy ? `${name_str}-copy` : name_str; | |||||
| const formData = { | |||||
| ...rest, | |||||
| name, | |||||
| }; | |||||
| form.setFieldsValue(formData); | |||||
| } | |||||
| }; | |||||
| }, [id, isCopy, form]); | |||||
| // 创建、更新、复制实验 | // 创建、更新、复制实验 | ||||
| const createExperiment = async (formData: FormData) => { | const createExperiment = async (formData: FormData) => { | ||||
| @@ -19,18 +19,17 @@ function ActiveLearnInfo() { | |||||
| const [info, setInfo] = useState<ActiveLearnData | undefined>(undefined); | const [info, setInfo] = useState<ActiveLearnData | undefined>(undefined); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| // 获取详情 | |||||
| const getActiveLearnInfo = async () => { | |||||
| const [res] = await to(getActiveLearnInfoReq({ id: id })); | |||||
| if (res && res.data) { | |||||
| setInfo(res.data); | |||||
| } | |||||
| }; | |||||
| if (id) { | if (id) { | ||||
| getActiveLearnInfo(); | getActiveLearnInfo(); | ||||
| } | } | ||||
| }, []); | |||||
| // 获取详情 | |||||
| const getActiveLearnInfo = async () => { | |||||
| const [res] = await to(getActiveLearnInfoReq({ id: id })); | |||||
| if (res && res.data) { | |||||
| setInfo(res.data); | |||||
| } | |||||
| }; | |||||
| }, [id]); | |||||
| return ( | return ( | ||||
| <div className={styles['auto-ml-info']}> | <div className={styles['auto-ml-info']}> | ||||
| @@ -245,7 +245,7 @@ function BasicInfo({ info, className, runStatus, isInstance = false }: BasicInfo | |||||
| ellipsis: true, | ellipsis: true, | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| }, [runStatus]); | |||||
| }, [runStatus, info]); | |||||
| return ( | return ( | ||||
| <div className={classNames(styles['active-learn-basic'], className)}> | <div className={classNames(styles['active-learn-basic'], className)}> | ||||
| @@ -39,7 +39,7 @@ export const regressorAlgorithms = [ | |||||
| { | { | ||||
| label: 'gaussian_process(高斯回归)', | label: 'gaussian_process(高斯回归)', | ||||
| value: 'gaussian_process', | value: 'gaussian_process', | ||||
| } | |||||
| }, | |||||
| ]; | ]; | ||||
| // 框架类型 | // 框架类型 | ||||
| @@ -65,7 +65,6 @@ export const frameworkTypeOptions = [ | |||||
| }, | }, | ||||
| ]; | ]; | ||||
| // 查询策略 | // 查询策略 | ||||
| export const queryStrategies = [ | export const queryStrategies = [ | ||||
| { | { | ||||
| @@ -87,6 +86,5 @@ export const queryStrategies = [ | |||||
| { | { | ||||
| label: 'upper_confidence_bound', | label: 'upper_confidence_bound', | ||||
| value: 'upper_confidence_bound', | value: 'upper_confidence_bound', | ||||
| } | |||||
| }, | |||||
| ]; | ]; | ||||
| @@ -1,7 +1,7 @@ | |||||
| import { type ParameterInputObject } from '@/components/ResourceSelect'; | import { type ParameterInputObject } from '@/components/ResourceSelect'; | ||||
| import { type NodeStatus } from '@/types'; | |||||
| import { AutoMLTaskType } from '@/enums'; | import { AutoMLTaskType } from '@/enums'; | ||||
| import { HyperParameterFile } from '@/pages/HyperParameter/types'; | import { HyperParameterFile } from '@/pages/HyperParameter/types'; | ||||
| import { type NodeStatus } from '@/types'; | |||||
| // 操作类型 | // 操作类型 | ||||
| export enum OperationType { | export enum OperationType { | ||||
| @@ -39,7 +39,6 @@ export type FormData = { | |||||
| batch_size: number; // batch_size | batch_size: number; // batch_size | ||||
| epochs: number; // epochs | epochs: number; // epochs | ||||
| lr: number; // 学习率 | lr: number; // 学习率 | ||||
| }; | }; | ||||
| // 主动学习 | // 主动学习 | ||||
| @@ -75,8 +74,8 @@ export type ActiveLearnInstanceData = { | |||||
| update_time: string; | update_time: string; | ||||
| finish_time: string; | finish_time: string; | ||||
| nodeStatus?: NodeStatus; | nodeStatus?: NodeStatus; | ||||
| data: string, | |||||
| trial_list?: ActiveLearnTrial[] | |||||
| data: string; | |||||
| trial_list?: ActiveLearnTrial[]; | |||||
| }; | }; | ||||
| export type ActiveLearnTrial = { | export type ActiveLearnTrial = { | ||||
| @@ -85,8 +84,8 @@ export type ActiveLearnTrial = { | |||||
| data_num?: number; | data_num?: number; | ||||
| accuracy?: number; | accuracy?: number; | ||||
| mse?: number; | mse?: number; | ||||
| query_idx?: string | |||||
| query_idx?: string; | |||||
| file?: HyperParameterFile; | file?: HyperParameterFile; | ||||
| }; | }; | ||||
| export {type HyperParameterFile} | |||||
| export { type HyperParameterFile }; | |||||
| @@ -4,17 +4,19 @@ | |||||
| * @Description: 创建实验 | * @Description: 创建实验 | ||||
| */ | */ | ||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import { AutoMLEnsembleClass, AutoMLTaskType } from '@/enums'; | |||||
| import { AutoMLEnsembleClass, AutoMLTaskType, AutoMLType } from '@/enums'; | |||||
| import { addAutoMLReq, getAutoMLInfoReq, updateAutoMLReq } from '@/services/autoML'; | import { addAutoMLReq, getAutoMLInfoReq, updateAutoMLReq } from '@/services/autoML'; | ||||
| import { convertEmptyStringToUndefined, parseJsonText, trimCharacter } from '@/utils'; | import { convertEmptyStringToUndefined, parseJsonText, trimCharacter } from '@/utils'; | ||||
| import { safeInvoke } from '@/utils/functional'; | import { safeInvoke } from '@/utils/functional'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useLocation, useNavigate, useParams } from '@umijs/max'; | import { useLocation, useNavigate, useParams } from '@umijs/max'; | ||||
| import { App, Button, Form } from 'antd'; | import { App, Button, Form } from 'antd'; | ||||
| import { omit } from 'lodash'; | |||||
| import { useEffect } from 'react'; | import { useEffect } from 'react'; | ||||
| import BasicConfig from '../components/CreateForm/BasicConfig'; | import BasicConfig from '../components/CreateForm/BasicConfig'; | ||||
| import DatasetConfig from '../components/CreateForm/DatasetConfig'; | import DatasetConfig from '../components/CreateForm/DatasetConfig'; | ||||
| import ExecuteConfig from '../components/CreateForm/ExecuteConfig'; | import ExecuteConfig from '../components/CreateForm/ExecuteConfig'; | ||||
| import TextExecuteConfig from '../components/CreateForm/TextExecuteConfig'; | |||||
| import TrialConfig from '../components/CreateForm/TrialConfig'; | import TrialConfig from '../components/CreateForm/TrialConfig'; | ||||
| import { AutoMLData, FormData } from '../types'; | import { AutoMLData, FormData } from '../types'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -27,6 +29,7 @@ function CreateAutoML() { | |||||
| const id = safeInvoke(Number)(params.id); | const id = safeInvoke(Number)(params.id); | ||||
| const { pathname } = useLocation(); | const { pathname } = useLocation(); | ||||
| const isCopy = pathname.includes('copy'); | const isCopy = pathname.includes('copy'); | ||||
| const type = Form.useWatch('type', form); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| // 获取服务详情 | // 获取服务详情 | ||||
| @@ -34,6 +37,8 @@ function CreateAutoML() { | |||||
| const [res] = await to(getAutoMLInfoReq({ id })); | const [res] = await to(getAutoMLInfoReq({ id })); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const autoMLInfo: AutoMLData = res.data; | const autoMLInfo: AutoMLData = res.data; | ||||
| const { name: name_str, description, type, param } = autoMLInfo; | |||||
| const paramObj = parseJsonText(param); | |||||
| const { | const { | ||||
| include_classifier: include_classifier_str, | include_classifier: include_classifier_str, | ||||
| include_feature_preprocessor: include_feature_preprocessor_str, | include_feature_preprocessor: include_feature_preprocessor_str, | ||||
| @@ -42,9 +47,8 @@ function CreateAutoML() { | |||||
| exclude_feature_preprocessor: exclude_feature_preprocessor_str, | exclude_feature_preprocessor: exclude_feature_preprocessor_str, | ||||
| exclude_regressor: exclude_regressor_str, | exclude_regressor: exclude_regressor_str, | ||||
| metrics: metrics_str, | metrics: metrics_str, | ||||
| ml_name: ml_name_str, | |||||
| ...rest | ...rest | ||||
| } = autoMLInfo; | |||||
| } = paramObj; | |||||
| const include_classifier = include_classifier_str?.split(',').filter(Boolean); | const include_classifier = include_classifier_str?.split(',').filter(Boolean); | ||||
| const include_feature_preprocessor = include_feature_preprocessor_str | const include_feature_preprocessor = include_feature_preprocessor_str | ||||
| ?.split(',') | ?.split(',') | ||||
| @@ -60,7 +64,7 @@ function CreateAutoML() { | |||||
| name: key, | name: key, | ||||
| value, | value, | ||||
| })); | })); | ||||
| const ml_name = isCopy ? `${ml_name_str}-copy` : ml_name_str; | |||||
| const name = isCopy ? `${name_str}-copy` : name_str; | |||||
| const formData = { | const formData = { | ||||
| ...rest, | ...rest, | ||||
| @@ -71,7 +75,9 @@ function CreateAutoML() { | |||||
| exclude_feature_preprocessor, | exclude_feature_preprocessor, | ||||
| exclude_regressor, | exclude_regressor, | ||||
| metrics, | metrics, | ||||
| ml_name, | |||||
| name, | |||||
| description, | |||||
| type, | |||||
| }; | }; | ||||
| form.setFieldsValue(formData); | form.setFieldsValue(formData); | ||||
| @@ -81,11 +87,15 @@ function CreateAutoML() { | |||||
| // 编辑,复制 | // 编辑,复制 | ||||
| if (id && !Number.isNaN(id)) { | if (id && !Number.isNaN(id)) { | ||||
| getAutoMLInfo(id); | getAutoMLInfo(id); | ||||
| } else { | |||||
| // 新建,不设置 form 的 type 初始值,是为了编辑和复制的时候,form 跳动 | |||||
| form.setFieldValue('type', AutoMLType.Table); | |||||
| } | } | ||||
| }, [id, form, isCopy]); | }, [id, form, isCopy]); | ||||
| // 创建、更新、复制实验 | // 创建、更新、复制实验 | ||||
| const createExperiment = async (formData: FormData) => { | const createExperiment = async (formData: FormData) => { | ||||
| const { name, description, type } = formData; | |||||
| const include_classifier = formData['include_classifier']?.join(','); | const include_classifier = formData['include_classifier']?.join(','); | ||||
| const include_feature_preprocessor = formData['include_feature_preprocessor']?.join(','); | const include_feature_preprocessor = formData['include_feature_preprocessor']?.join(','); | ||||
| const include_regressor = formData['include_regressor']?.join(','); | const include_regressor = formData['include_regressor']?.join(','); | ||||
| @@ -104,8 +114,8 @@ function CreateAutoML() { | |||||
| const target_columns = trimCharacter(formData['target_columns'], ','); | const target_columns = trimCharacter(formData['target_columns'], ','); | ||||
| // 根据后台要求,修改表单数据 | // 根据后台要求,修改表单数据 | ||||
| const object = { | |||||
| ...formData, | |||||
| const param = { | |||||
| ...omit(formData, ['name', 'description', 'type']), | |||||
| include_classifier: convertEmptyStringToUndefined(include_classifier), | include_classifier: convertEmptyStringToUndefined(include_classifier), | ||||
| include_feature_preprocessor: convertEmptyStringToUndefined(include_feature_preprocessor), | include_feature_preprocessor: convertEmptyStringToUndefined(include_feature_preprocessor), | ||||
| include_regressor: convertEmptyStringToUndefined(include_regressor), | include_regressor: convertEmptyStringToUndefined(include_regressor), | ||||
| @@ -116,6 +126,13 @@ function CreateAutoML() { | |||||
| target_columns, | target_columns, | ||||
| }; | }; | ||||
| const object = { | |||||
| name, | |||||
| description, | |||||
| type, | |||||
| param: JSON.stringify(param), | |||||
| }; | |||||
| const params = | const params = | ||||
| id && !isCopy | id && !isCopy | ||||
| ? { | ? { | ||||
| @@ -186,9 +203,16 @@ function CreateAutoML() { | |||||
| }} | }} | ||||
| > | > | ||||
| <BasicConfig /> | <BasicConfig /> | ||||
| <ExecuteConfig /> | |||||
| <TrialConfig /> | |||||
| <DatasetConfig /> | |||||
| {type === AutoMLType.Table ? ( | |||||
| <> | |||||
| <ExecuteConfig /> | |||||
| <TrialConfig /> | |||||
| <DatasetConfig /> | |||||
| </> | |||||
| ) : type === AutoMLType.Text ? ( | |||||
| <TextExecuteConfig /> | |||||
| ) : null} | |||||
| <Form.Item wrapperCol={{ offset: 0, span: 16 }} style={{ marginTop: '40px' }}> | <Form.Item wrapperCol={{ offset: 0, span: 16 }} style={{ marginTop: '40px' }}> | ||||
| <Button type="primary" htmlType="submit"> | <Button type="primary" htmlType="submit"> | ||||
| @@ -5,6 +5,7 @@ | |||||
| */ | */ | ||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import { getAutoMLInfoReq } from '@/services/autoML'; | import { getAutoMLInfoReq } from '@/services/autoML'; | ||||
| import { parseJsonText } from '@/utils'; | |||||
| import { safeInvoke } from '@/utils/functional'; | import { safeInvoke } from '@/utils/functional'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useParams } from '@umijs/max'; | import { useParams } from '@umijs/max'; | ||||
| @@ -23,7 +24,14 @@ function AutoMLInfo() { | |||||
| const getAutoMLInfo = async () => { | const getAutoMLInfo = async () => { | ||||
| const [res] = await to(getAutoMLInfoReq({ id: autoMLId })); | const [res] = await to(getAutoMLInfoReq({ id: autoMLId })); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| setAutoMLInfo(res.data); | |||||
| const info = res.data; | |||||
| const param = info.param; | |||||
| setAutoMLInfo({ | |||||
| ...info, | |||||
| param: undefined, | |||||
| ...parseJsonText(param), | |||||
| }); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -48,13 +48,14 @@ function AutoMLInstance() { | |||||
| const [res] = await to(getExperimentInsReq(instanceId)); | const [res] = await to(getExperimentInsReq(instanceId)); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const info = res.data as AutoMLInstanceData; | const info = res.data as AutoMLInstanceData; | ||||
| const { param, node_status, argo_ins_name, argo_ins_ns, status, create_time } = info; | |||||
| const { param, node_status, argo_ins_name, argo_ins_ns, status, create_time, type } = info; | |||||
| // 解析配置参数 | // 解析配置参数 | ||||
| const paramJson = parseJsonText(param); | const paramJson = parseJsonText(param); | ||||
| if (paramJson) { | if (paramJson) { | ||||
| setAutoMLInfo({ | setAutoMLInfo({ | ||||
| ...paramJson, | |||||
| ...paramJson.data, | |||||
| create_time, | create_time, | ||||
| type, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -1,5 +1,11 @@ | |||||
| import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo'; | import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo'; | ||||
| import { AutoMLTaskType, autoMLEnsembleClassOptions, autoMLTaskTypeOptions } from '@/enums'; | |||||
| import { | |||||
| AutoMLTaskType, | |||||
| AutoMLType, | |||||
| autoMLEnsembleClassOptions, | |||||
| autoMLTaskTypeOptions, | |||||
| } from '@/enums'; | |||||
| import { useComputingResource } from '@/hooks/useComputingResource'; | |||||
| import { AutoMLData } from '@/pages/AutoML/types'; | import { AutoMLData } from '@/pages/AutoML/types'; | ||||
| import { experimentStatusInfo } from '@/pages/Experiment/status'; | import { experimentStatusInfo } from '@/pages/Experiment/status'; | ||||
| import { type NodeStatus } from '@/types'; | import { type NodeStatus } from '@/types'; | ||||
| @@ -37,6 +43,7 @@ type AutoMLBasicProps = { | |||||
| }; | }; | ||||
| function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLBasicProps) { | function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLBasicProps) { | ||||
| const getResourceDescription = useComputingResource()[1]; | |||||
| const basicDatas: BasicInfoData[] = useMemo(() => { | const basicDatas: BasicInfoData[] = useMemo(() => { | ||||
| if (!info) { | if (!info) { | ||||
| return []; | return []; | ||||
| @@ -45,11 +52,11 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB | |||||
| return [ | return [ | ||||
| { | { | ||||
| label: '实验名称', | label: '实验名称', | ||||
| value: info.ml_name, | |||||
| value: info.name, | |||||
| }, | }, | ||||
| { | { | ||||
| label: '实验描述', | label: '实验描述', | ||||
| value: info.ml_description, | |||||
| value: info.description, | |||||
| }, | }, | ||||
| { | { | ||||
| label: '创建人', | label: '创建人', | ||||
| @@ -72,103 +79,136 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB | |||||
| if (!info) { | if (!info) { | ||||
| return []; | return []; | ||||
| } | } | ||||
| return [ | |||||
| { | |||||
| label: '任务类型', | |||||
| value: info.task_type, | |||||
| format: formatEnum(autoMLTaskTypeOptions), | |||||
| }, | |||||
| { | |||||
| label: '特征预处理算法', | |||||
| value: info.include_feature_preprocessor, | |||||
| }, | |||||
| { | |||||
| label: '排除的特征预处理算法', | |||||
| value: info.exclude_feature_preprocessor, | |||||
| }, | |||||
| { | |||||
| label: info.task_type === AutoMLTaskType.Regression ? '回归算法' : '分类算法', | |||||
| value: | |||||
| info.task_type === AutoMLTaskType.Regression | |||||
| ? info.include_regressor | |||||
| : info.include_classifier, | |||||
| }, | |||||
| { | |||||
| label: info.task_type === AutoMLTaskType.Regression ? '排除的回归算法' : '排除的分类算法', | |||||
| value: | |||||
| info.task_type === AutoMLTaskType.Regression | |||||
| ? info.exclude_regressor | |||||
| : info.exclude_classifier, | |||||
| }, | |||||
| { | |||||
| label: '集成方式', | |||||
| value: info.ensemble_class, | |||||
| format: formatEnum(autoMLEnsembleClassOptions), | |||||
| }, | |||||
| { | |||||
| label: '集成模型数量', | |||||
| value: info.ensemble_size, | |||||
| }, | |||||
| { | |||||
| label: '集成最佳模型数量', | |||||
| value: info.ensemble_nbest, | |||||
| }, | |||||
| { | |||||
| label: '最大数量', | |||||
| value: info.max_models_on_disc, | |||||
| }, | |||||
| { | |||||
| label: '内存限制(MB)', | |||||
| value: info.memory_limit, | |||||
| }, | |||||
| { | |||||
| label: '单次时间限制(秒)', | |||||
| value: info.per_run_time_limit, | |||||
| }, | |||||
| { | |||||
| label: '搜索时间限制(秒)', | |||||
| value: info.time_left_for_this_task, | |||||
| }, | |||||
| { | |||||
| label: '重采样策略', | |||||
| value: info.resampling_strategy, | |||||
| }, | |||||
| { | |||||
| label: '交叉验证折数', | |||||
| value: info.folds, | |||||
| }, | |||||
| { | |||||
| label: '是否打乱', | |||||
| value: info.shuffle, | |||||
| format: formatBoolean, | |||||
| }, | |||||
| { | |||||
| label: '训练集比率', | |||||
| value: info.train_size, | |||||
| }, | |||||
| { | |||||
| label: '测试集比率', | |||||
| value: info.test_size, | |||||
| }, | |||||
| { | |||||
| label: '计算指标', | |||||
| value: info.scoring_functions, | |||||
| }, | |||||
| { | |||||
| label: '随机种子', | |||||
| value: info.seed, | |||||
| }, | |||||
| { | |||||
| label: '数据集', | |||||
| value: info.dataset, | |||||
| format: formatDataset, | |||||
| }, | |||||
| { | |||||
| label: '预测目标列', | |||||
| value: info.target_columns, | |||||
| }, | |||||
| ]; | |||||
| }, [info]); | |||||
| if (info.type === AutoMLType.Table) { | |||||
| return [ | |||||
| { | |||||
| label: '任务类型', | |||||
| value: info.task_type, | |||||
| format: formatEnum(autoMLTaskTypeOptions), | |||||
| }, | |||||
| { | |||||
| label: '特征预处理算法', | |||||
| value: info.include_feature_preprocessor, | |||||
| }, | |||||
| { | |||||
| label: '排除的特征预处理算法', | |||||
| value: info.exclude_feature_preprocessor, | |||||
| }, | |||||
| { | |||||
| label: info.task_type === AutoMLTaskType.Regression ? '回归算法' : '分类算法', | |||||
| value: | |||||
| info.task_type === AutoMLTaskType.Regression | |||||
| ? info.include_regressor | |||||
| : info.include_classifier, | |||||
| }, | |||||
| { | |||||
| label: info.task_type === AutoMLTaskType.Regression ? '排除的回归算法' : '排除的分类算法', | |||||
| value: | |||||
| info.task_type === AutoMLTaskType.Regression | |||||
| ? info.exclude_regressor | |||||
| : info.exclude_classifier, | |||||
| }, | |||||
| { | |||||
| label: '集成方式', | |||||
| value: info.ensemble_class, | |||||
| format: formatEnum(autoMLEnsembleClassOptions), | |||||
| }, | |||||
| { | |||||
| label: '集成模型数量', | |||||
| value: info.ensemble_size, | |||||
| }, | |||||
| { | |||||
| label: '集成最佳模型数量', | |||||
| value: info.ensemble_nbest, | |||||
| }, | |||||
| { | |||||
| label: '最大数量', | |||||
| value: info.max_models_on_disc, | |||||
| }, | |||||
| { | |||||
| label: '内存限制(MB)', | |||||
| value: info.memory_limit, | |||||
| }, | |||||
| { | |||||
| label: '单次时间限制(秒)', | |||||
| value: info.per_run_time_limit, | |||||
| }, | |||||
| { | |||||
| label: '搜索时间限制(秒)', | |||||
| value: info.time_left_for_this_task, | |||||
| }, | |||||
| { | |||||
| label: '重采样策略', | |||||
| value: info.resampling_strategy, | |||||
| }, | |||||
| { | |||||
| label: '交叉验证折数', | |||||
| value: info.folds, | |||||
| }, | |||||
| { | |||||
| label: '是否打乱', | |||||
| value: info.shuffle, | |||||
| format: formatBoolean, | |||||
| }, | |||||
| { | |||||
| label: '训练集比率', | |||||
| value: info.train_size, | |||||
| }, | |||||
| { | |||||
| label: '测试集比率', | |||||
| value: info.test_size, | |||||
| }, | |||||
| { | |||||
| label: '计算指标', | |||||
| value: info.scoring_functions, | |||||
| }, | |||||
| { | |||||
| label: '随机种子', | |||||
| value: info.seed, | |||||
| }, | |||||
| { | |||||
| label: '数据集', | |||||
| value: info.dataset, | |||||
| format: formatDataset, | |||||
| }, | |||||
| { | |||||
| label: '预测目标列', | |||||
| value: info.target_columns, | |||||
| }, | |||||
| ]; | |||||
| } else if (info.type === AutoMLType.Text) { | |||||
| return [ | |||||
| { | |||||
| label: '模型', | |||||
| value: info.model_type, | |||||
| }, | |||||
| { | |||||
| label: '数据集', | |||||
| value: info.dataset, | |||||
| format: formatDataset, | |||||
| }, | |||||
| { | |||||
| label: '资源规格', | |||||
| value: info.computing_resource_id, | |||||
| format: getResourceDescription, | |||||
| }, | |||||
| { | |||||
| label: 'batch_size', | |||||
| value: info.batch_size, | |||||
| }, | |||||
| { | |||||
| label: 'epochs', | |||||
| value: info.epochs, | |||||
| }, | |||||
| { | |||||
| label: '学习率', | |||||
| value: info.lr, | |||||
| }, | |||||
| ]; | |||||
| } else { | |||||
| return []; | |||||
| } | |||||
| }, [info, getResourceDescription]); | |||||
| const metricsData = useMemo(() => { | const metricsData = useMemo(() => { | ||||
| if (!info) { | if (!info) { | ||||
| @@ -229,7 +269,7 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB | |||||
| ), | ), | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| }, [runStatus]); | |||||
| }, [runStatus, info]); | |||||
| return ( | return ( | ||||
| <div className={classNames(styles['auto-ml-basic'], className)}> | <div className={classNames(styles['auto-ml-basic'], className)}> | ||||
| @@ -255,7 +295,9 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB | |||||
| labelWidth={150} | labelWidth={150} | ||||
| style={{ marginBottom: '20px' }} | style={{ marginBottom: '20px' }} | ||||
| /> | /> | ||||
| <ConfigInfo title="优化指标" datas={metricsData} labelWidth={70} /> | |||||
| {info?.type === AutoMLType.Table && ( | |||||
| <ConfigInfo title="优化指标" datas={metricsData} labelWidth={70} /> | |||||
| )} | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -1,5 +1,7 @@ | |||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { Col, Form, Input, Row } from 'antd'; | |||||
| import { autoMLTypeOptions } from '@/enums'; | |||||
| import { Col, Form, Input, Radio, Row } from 'antd'; | |||||
| function BasicConfig() { | function BasicConfig() { | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| @@ -12,7 +14,7 @@ function BasicConfig() { | |||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="实验名称" | label="实验名称" | ||||
| name="ml_name" | |||||
| name="name" | |||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| @@ -32,7 +34,7 @@ function BasicConfig() { | |||||
| <Col span={20}> | <Col span={20}> | ||||
| <Form.Item | <Form.Item | ||||
| label="实验描述" | label="实验描述" | ||||
| name="ml_description" | |||||
| name="description" | |||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| @@ -50,6 +52,14 @@ function BasicConfig() { | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="类型" name="type" rules={[{ required: true, message: '请选择类型' }]}> | |||||
| <Radio.Group options={autoMLTypeOptions}></Radio.Group> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| </> | </> | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -0,0 +1,137 @@ | |||||
| import ParameterSelect from '@/components/ParameterSelect'; | |||||
| import ResourceSelect, { | |||||
| ResourceSelectorType, | |||||
| requiredValidator, | |||||
| } from '@/components/ResourceSelect'; | |||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | |||||
| import { Col, Form, InputNumber, Row, Select } from 'antd'; | |||||
| // 模型 | |||||
| const modelTypeOptions = [ | |||||
| 'TextCNN', | |||||
| 'TextRNN', | |||||
| 'FasetText', | |||||
| 'TextRCNN', | |||||
| 'TextRNN_Att', | |||||
| 'DPCNN', | |||||
| 'Transformer', | |||||
| ].map((name) => ({ label: name, value: name })); | |||||
| function TextExecuteConfig() { | |||||
| return ( | |||||
| <> | |||||
| <SubAreaTitle | |||||
| title="执行配置" | |||||
| image={require('@/assets/img/model-deployment.png')} | |||||
| style={{ marginTop: '20px', marginBottom: '24px' }} | |||||
| ></SubAreaTitle> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="模型" | |||||
| name="model_type" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请选择模型', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Select allowClear placeholder="请选择模型" options={modelTypeOptions} showSearch /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="数据集" | |||||
| name="dataset" | |||||
| rules={[ | |||||
| { | |||||
| validator: requiredValidator, | |||||
| message: '请选择数据集', | |||||
| }, | |||||
| ]} | |||||
| required | |||||
| > | |||||
| <ResourceSelect | |||||
| type={ResourceSelectorType.Dataset} | |||||
| placeholder="请选择数据集" | |||||
| canInput={false} | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="资源规格" | |||||
| name="computing_resource_id" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请选择资源规格', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <ParameterSelect dataType="resource" placeholder="请选择资源规格" /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="batch_size" | |||||
| name="batch_size" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入 batch_size', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <InputNumber placeholder="请输入 batch_size" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="epochs" | |||||
| name="epochs" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入epochs', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <InputNumber placeholder="请输入epochs" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="学习率" | |||||
| name="lr" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入学习率', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <InputNumber placeholder="请输入学习率" min={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| </> | |||||
| ); | |||||
| } | |||||
| export default TextExecuteConfig; | |||||
| @@ -55,7 +55,7 @@ function ExperimentHistory({ calcMetrics, fileUrl, isClassification }: Experimen | |||||
| if (fileUrl) { | if (fileUrl) { | ||||
| getHistoryFile(); | getHistoryFile(); | ||||
| } | } | ||||
| }, [fileUrl, isClassification]); | |||||
| }, [fileUrl, isClassification, calcMetrics]); | |||||
| const columns: TableProps<TableData>['columns'] = [ | const columns: TableProps<TableData>['columns'] = [ | ||||
| { | { | ||||
| @@ -64,9 +64,9 @@ export const experimentListConfig: Record<ExperimentListType, ExperimentListInfo | |||||
| stopInsReq: stopExperimentInsReq, | stopInsReq: stopExperimentInsReq, | ||||
| title: '自主机器学习', | title: '自主机器学习', | ||||
| pathPrefix: 'automl', | pathPrefix: 'automl', | ||||
| nameProperty: 'ml_name', | |||||
| descProperty: 'ml_description', | |||||
| idProperty: 'autoMlId', | |||||
| nameProperty: 'name', | |||||
| descProperty: 'description', | |||||
| idProperty: 'machineLearnId', | |||||
| }, | }, | ||||
| [ExperimentListType.HyperParameter]: { | [ExperimentListType.HyperParameter]: { | ||||
| getListReq: getRayListReq, | getListReq: getRayListReq, | ||||
| @@ -6,7 +6,7 @@ | |||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import { ExperimentStatus } from '@/enums'; | |||||
| import { ExperimentStatus, autoMLTypeOptions } from '@/enums'; | |||||
| import { useCacheState } from '@/hooks/useCacheState'; | import { useCacheState } from '@/hooks/useCacheState'; | ||||
| import { AutoMLData } from '@/pages/AutoML/types'; | import { AutoMLData } from '@/pages/AutoML/types'; | ||||
| import { experimentStatusInfo } from '@/pages/Experiment/status'; | import { experimentStatusInfo } from '@/pages/Experiment/status'; | ||||
| @@ -244,6 +244,20 @@ function ExperimentList({ type }: ExperimentListProps) { | |||||
| } | } | ||||
| }; | }; | ||||
| const typeColumns = [ | |||||
| { | |||||
| title: '类型', | |||||
| dataIndex: 'type', | |||||
| key: 'type', | |||||
| width: 120, | |||||
| render: tableCellRender(false, TableCellValueType.Enum, { | |||||
| options: autoMLTypeOptions, | |||||
| }), | |||||
| }, | |||||
| ]; | |||||
| const diffColumns = type === ExperimentListType.AutoML ? typeColumns : []; | |||||
| const columns: TableProps<AutoMLData>['columns'] = [ | const columns: TableProps<AutoMLData>['columns'] = [ | ||||
| { | { | ||||
| title: '实验名称', | title: '实验名称', | ||||
| @@ -260,6 +274,7 @@ function ExperimentList({ type }: ExperimentListProps) { | |||||
| key: 'description', | key: 'description', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| }, | }, | ||||
| ...diffColumns, | |||||
| { | { | ||||
| title: '创建时间', | title: '创建时间', | ||||
| dataIndex: 'update_time', | dataIndex: 'update_time', | ||||
| @@ -9,8 +9,9 @@ export enum OperationType { | |||||
| // 表单数据 | // 表单数据 | ||||
| export type FormData = { | export type FormData = { | ||||
| ml_name: string; // 实验名称 | |||||
| ml_description: string; // 实验描述 | |||||
| name: string; // 实验名称 | |||||
| description: string; // 实验描述 | |||||
| type: string; // 类型 | |||||
| ensemble_class?: string; // 集成方式 | ensemble_class?: string; // 集成方式 | ||||
| ensemble_nbest?: string; // 集成最佳模型数量 | ensemble_nbest?: string; // 集成最佳模型数量 | ||||
| ensemble_size?: number; // 集成模型数量 | ensemble_size?: number; // 集成模型数量 | ||||
| @@ -37,6 +38,11 @@ export type FormData = { | |||||
| metrics?: { name: string; value: number }[]; // 指标权重 | metrics?: { name: string; value: number }[]; // 指标权重 | ||||
| dataset: ParameterInputObject; // 数据集 | dataset: ParameterInputObject; // 数据集 | ||||
| target_columns: string; // 预测目标列 | target_columns: string; // 预测目标列 | ||||
| model_type?: string; // 文本模型 | |||||
| computing_resource_id?: number; // 资源规格 | |||||
| batch_size?: number; | |||||
| epochs?: number; | |||||
| lr?: number; | |||||
| }; | }; | ||||
| export type AutoMLData = { | export type AutoMLData = { | ||||
| @@ -57,6 +63,7 @@ export type AutoMLData = { | |||||
| update_by?: string; | update_by?: string; | ||||
| update_time?: string; | update_time?: string; | ||||
| status_list: string; // 最近五次运行状态 | status_list: string; // 最近五次运行状态 | ||||
| param: string; // 参数json字符串 | |||||
| } & Omit< | } & Omit< | ||||
| FormData, | FormData, | ||||
| 'metrics|dataset|include_classifier|include_feature_preprocessor|include_regressor|exclude_classifier|exclude_feature_preprocessor|exclude_regressor' | 'metrics|dataset|include_classifier|include_feature_preprocessor|include_regressor|exclude_classifier|exclude_feature_preprocessor|exclude_regressor' | ||||
| @@ -82,4 +89,5 @@ export type AutoMLInstanceData = { | |||||
| update_time: string; | update_time: string; | ||||
| finish_time: string; | finish_time: string; | ||||
| nodeStatus?: NodeStatus; | nodeStatus?: NodeStatus; | ||||
| type: string; | |||||
| }; | }; | ||||
| @@ -55,4 +55,4 @@ | |||||
| .table-best-row { | .table-best-row { | ||||
| color: @success-color; | color: @success-color; | ||||
| font-weight: bold; | font-weight: bold; | ||||
| } | |||||
| } | |||||
| @@ -182,7 +182,7 @@ function HyperParameterBasic({ | |||||
| ellipsis: true, | ellipsis: true, | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| }, [runStatus]); | |||||
| }, [runStatus, info]); | |||||
| return ( | return ( | ||||
| <div className={classNames(styles['hyper-parameter-basic'], className)}> | <div className={classNames(styles['hyper-parameter-basic'], className)}> | ||||
| @@ -1,15 +1,14 @@ | |||||
| .trail-file-tree { | .trail-file-tree { | ||||
| :global { | |||||
| .ant-tree-node-selected { | |||||
| .trail-file-tree__icon { | |||||
| color: white; | |||||
| } | |||||
| } | |||||
| :global { | |||||
| .ant-tree-node-selected { | |||||
| .trail-file-tree__icon { | .trail-file-tree__icon { | ||||
| margin-left: 8px; | |||||
| color: @primary-color; | |||||
| color: white; | |||||
| } | } | ||||
| } | } | ||||
| .trail-file-tree__icon { | |||||
| margin-left: 8px; | |||||
| color: @primary-color; | |||||
| } | |||||
| } | } | ||||
| } | |||||
| @@ -31,7 +31,7 @@ type ModelMetricsProps = { | |||||
| version: string; // 当前版本 | version: string; // 当前版本 | ||||
| }; | }; | ||||
| function ModelMetrics({ resourceId, identifier, owner, version, refreshTag }: ModelMetricsProps) { | |||||
| function ModelMetrics({ resourceId, identifier, owner, version }: ModelMetricsProps) { | |||||
| const [pagination, setPagination] = useState<TablePaginationConfig>({ | const [pagination, setPagination] = useState<TablePaginationConfig>({ | ||||
| current: 1, | current: 1, | ||||
| pageSize: 10, | pageSize: 10, | ||||
| @@ -9,6 +9,7 @@ import { serviceTypeOptions } from '@/enums'; | |||||
| import { useCacheState } from '@/hooks/useCacheState'; | import { useCacheState } from '@/hooks/useCacheState'; | ||||
| import { deleteServiceReq, getServiceListReq } from '@/services/modelDeployment'; | import { deleteServiceReq, getServiceListReq } from '@/services/modelDeployment'; | ||||
| import themes from '@/styles/theme.less'; | import themes from '@/styles/theme.less'; | ||||
| import { ServiceCreatedMessage } from '@/utils/constant'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import SessionStorage from '@/utils/sessionStorage'; | import SessionStorage from '@/utils/sessionStorage'; | ||||
| import tableCellRender, { TableCellValueType } from '@/utils/table'; | import tableCellRender, { TableCellValueType } from '@/utils/table'; | ||||
| @@ -27,13 +28,8 @@ import { | |||||
| import { type SearchProps } from 'antd/es/input'; | import { type SearchProps } from 'antd/es/input'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { useCallback, useEffect, useState } from 'react'; | import { useCallback, useEffect, useState } from 'react'; | ||||
| import { | |||||
| CreateServiceVersionFrom, | |||||
| ServiceData, | |||||
| ServiceOperationType, | |||||
| } from '../types'; | |||||
| import { CreateServiceVersionFrom, ServiceData, ServiceOperationType } from '../types'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| import { ServiceCreatedMessage } from '@/utils/constant'; | |||||
| const allServiceTypeOptions = [{ label: '全部', value: '' }, ...serviceTypeOptions]; | const allServiceTypeOptions = [{ label: '全部', value: '' }, ...serviceTypeOptions]; | ||||
| @@ -8,9 +8,13 @@ | |||||
| color: white; | color: white; | ||||
| white-space: pre-wrap; | white-space: pre-wrap; | ||||
| background-color: rgba(0, 0, 0, 0.85); | background-color: rgba(0, 0, 0, 0.85); | ||||
| font-family: 'Roboto Mono', 'Menlo', 'Consolas', 'Monaco', monospace; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: center; | |||||
| &__more { | &__more { | ||||
| padding: 10px 0; | |||||
| padding: 20px 0; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -79,7 +79,7 @@ function VersionCompareModal({ version1, version2, ...rest }: VersionCompareModa | |||||
| }, | }, | ||||
| }, | }, | ||||
| { | { | ||||
| key: 'resource', | |||||
| key: 'computing_resource_id', | |||||
| text: '资源规格', | text: '资源规格', | ||||
| format: getResourceDescription, | format: getResourceDescription, | ||||
| }, | }, | ||||
| @@ -168,7 +168,7 @@ const JobForm: React.FC<JobFormProps> = (props) => { | |||||
| captchaTextRender={() => '生成表达式'} | captchaTextRender={() => '生成表达式'} | ||||
| onGetCaptcha={() => { | onGetCaptcha={() => { | ||||
| // form.setFieldValue('cronExpression', '0/20 * * * * ?'); | // form.setFieldValue('cronExpression', '0/20 * * * * ?'); | ||||
| return new Promise((resolve, reject) => { | |||||
| return new Promise((_resolve, reject) => { | |||||
| reject(); | reject(); | ||||
| }); | }); | ||||
| }} | }} | ||||
| @@ -2,7 +2,6 @@ import KFModal from '@/components/KFModal'; | |||||
| import { Key, ProForm, ProFormDigit, ProFormSelect, ProFormText } from '@ant-design/pro-components'; | import { Key, ProForm, ProFormDigit, ProFormSelect, ProFormText } from '@ant-design/pro-components'; | ||||
| import { FormattedMessage, useIntl } from '@umijs/max'; | import { FormattedMessage, useIntl } from '@umijs/max'; | ||||
| import { Checkbox, Col, Form, Row, Tree } from 'antd'; | import { Checkbox, Col, Form, Row, Tree } from 'antd'; | ||||
| import { CheckboxValueType } from 'antd/es/checkbox/Group'; | |||||
| import { DataNode } from 'antd/es/tree'; | import { DataNode } from 'antd/es/tree'; | ||||
| import React, { useEffect, useState } from 'react'; | import React, { useEffect, useState } from 'react'; | ||||
| /* * | /* * | ||||
| @@ -74,7 +73,7 @@ const DataScopeForm: React.FC<DataScopeFormProps> = (props) => { | |||||
| const deptAllNodes = getAllDeptNode(deptTree); | const deptAllNodes = getAllDeptNode(deptTree); | ||||
| const onDeptOptionChange = (checkedValues: CheckboxValueType[]) => { | |||||
| const onDeptOptionChange = (checkedValues: any[]) => { | |||||
| if (checkedValues.includes('deptExpand')) { | if (checkedValues.includes('deptExpand')) { | ||||
| setDeptTreeExpandKey(deptAllNodes); | setDeptTreeExpandKey(deptAllNodes); | ||||
| } else { | } else { | ||||
| @@ -188,7 +187,7 @@ const DataScopeForm: React.FC<DataScopeFormProps> = (props) => { | |||||
| ]} | ]} | ||||
| fieldProps={{ | fieldProps={{ | ||||
| onChange: (value) => { | onChange: (value) => { | ||||
| setDataScopeType(value); | |||||
| setDataScopeType(value as any); | |||||
| }, | }, | ||||
| }} | }} | ||||
| /> | /> | ||||
| @@ -30,7 +30,7 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => { | |||||
| props.onSubmit({ password: values.password, userId, originPassword } as FormValueType); | props.onSubmit({ password: values.password, userId, originPassword } as FormValueType); | ||||
| }; | }; | ||||
| const checkPassword = (rule: any, value: string) => { | |||||
| const checkPassword = (_rule: any, value: string) => { | |||||
| if (value === loginPassword) { | if (value === loginPassword) { | ||||
| // 校验条件自定义 | // 校验条件自定义 | ||||
| return Promise.resolve(); | return Promise.resolve(); | ||||
| @@ -32,7 +32,7 @@ export type UserFormProps = { | |||||
| const UserForm: React.FC<UserFormProps> = (props) => { | const UserForm: React.FC<UserFormProps> = (props) => { | ||||
| const [form] = Form.useForm(); | const [form] = Form.useForm(); | ||||
| const userId = Form.useWatch('userId', form); | |||||
| // const userId = Form.useWatch('userId', form); | |||||
| const { sexOptions, statusOptions } = props; | const { sexOptions, statusOptions } = props; | ||||
| const { roles, posts, depts } = props; | const { roles, posts, depts } = props; | ||||
| const formLayout = { | const formLayout = { | ||||
| @@ -252,10 +252,10 @@ const ColumnInfo: React.FC<ColumnInfoProps> = (props) => { | |||||
| type: 'multiple', | type: 'multiple', | ||||
| editableKeys, | editableKeys, | ||||
| onChange: setEditableRowKeys, | onChange: setEditableRowKeys, | ||||
| actionRender: (row, config, defaultDoms) => { | |||||
| actionRender: (_row, _config, defaultDoms) => { | |||||
| return [defaultDoms.delete]; | return [defaultDoms.delete]; | ||||
| }, | }, | ||||
| onValuesChange: (record, recordList) => { | |||||
| onValuesChange: (_record, recordList) => { | |||||
| setDataSource(recordList); | setDataSource(recordList); | ||||
| }, | }, | ||||
| }} | }} | ||||
| @@ -105,7 +105,7 @@ const GenInfo: React.FC<GenInfoProps> = (props) => { | |||||
| <ProFormSelect | <ProFormSelect | ||||
| fieldProps={{ | fieldProps={{ | ||||
| onChange: (val) => { | onChange: (val) => { | ||||
| setTlpType(val); | |||||
| setTlpType(val as string); | |||||
| }, | }, | ||||
| }} | }} | ||||
| valueEnum={{ | valueEnum={{ | ||||
| @@ -17,7 +17,7 @@ const ResetPassword: React.FC = () => { | |||||
| } | } | ||||
| }; | }; | ||||
| const checkPassword = (rule: any, value: string) => { | |||||
| const checkPassword = (_rule: any, value: string) => { | |||||
| const login_password = form.getFieldValue('newPassword'); | const login_password = form.getFieldValue('newPassword'); | ||||
| if (value === login_password) { | if (value === login_password) { | ||||
| return Promise.resolve(); | return Promise.resolve(); | ||||
| @@ -6,7 +6,6 @@ | |||||
| import { request } from '@umijs/max'; | import { request } from '@umijs/max'; | ||||
| // 分页查询超参数自动寻优 | // 分页查询超参数自动寻优 | ||||
| export function getActiveLearnListReq(params) { | export function getActiveLearnListReq(params) { | ||||
| return request(`/api/mmp/activeLearn`, { | return request(`/api/mmp/activeLearn`, { | ||||
| @@ -87,7 +86,6 @@ export function deleteActiveLearnInsReq(id) { | |||||
| export function batchDeleteActiveLearnInsReq(data) { | export function batchDeleteActiveLearnInsReq(data) { | ||||
| return request(`/api/mmp/activeLearnIns/batchDelete`, { | return request(`/api/mmp/activeLearnIns/batchDelete`, { | ||||
| method: 'DELETE', | method: 'DELETE', | ||||
| data | |||||
| data, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -13,4 +13,4 @@ export function getClientInfoReq() { | |||||
| return request(`/api/auth/oauth2ClientInfo`, { | return request(`/api/auth/oauth2ClientInfo`, { | ||||
| method: 'GET', | method: 'GET', | ||||
| }); | }); | ||||
| } | |||||
| } | |||||
| @@ -6,10 +6,9 @@ | |||||
| import { request } from '@umijs/max'; | import { request } from '@umijs/max'; | ||||
| // 分页查询自动学习 | // 分页查询自动学习 | ||||
| export function getAutoMLListReq(params) { | export function getAutoMLListReq(params) { | ||||
| return request(`/api/mmp/autoML`, { | |||||
| return request(`/api/mmp/machineLearn`, { | |||||
| method: 'GET', | method: 'GET', | ||||
| params, | params, | ||||
| }); | }); | ||||
| @@ -17,7 +16,7 @@ export function getAutoMLListReq(params) { | |||||
| // 查询自动学习详情 | // 查询自动学习详情 | ||||
| export function getAutoMLInfoReq(params) { | export function getAutoMLInfoReq(params) { | ||||
| return request(`/api/mmp/autoML/getAutoMlDetail`, { | |||||
| return request(`/api/mmp/machineLearn/getMLDetail`, { | |||||
| method: 'GET', | method: 'GET', | ||||
| params, | params, | ||||
| }); | }); | ||||
| @@ -25,7 +24,7 @@ export function getAutoMLInfoReq(params) { | |||||
| // 新增自动学习 | // 新增自动学习 | ||||
| export function addAutoMLReq(data) { | export function addAutoMLReq(data) { | ||||
| return request(`/api/mmp/autoML`, { | |||||
| return request(`/api/mmp/machineLearn`, { | |||||
| method: 'POST', | method: 'POST', | ||||
| data, | data, | ||||
| }); | }); | ||||
| @@ -33,7 +32,7 @@ export function addAutoMLReq(data) { | |||||
| // 编辑自动学习 | // 编辑自动学习 | ||||
| export function updateAutoMLReq(data) { | export function updateAutoMLReq(data) { | ||||
| return request(`/api/mmp/autoML`, { | |||||
| return request(`/api/mmp/machineLearn`, { | |||||
| method: 'PUT', | method: 'PUT', | ||||
| data, | data, | ||||
| }); | }); | ||||
| @@ -41,14 +40,14 @@ export function updateAutoMLReq(data) { | |||||
| // 删除自动学习 | // 删除自动学习 | ||||
| export function deleteAutoMLReq(id) { | export function deleteAutoMLReq(id) { | ||||
| return request(`/api/mmp/autoML/${id}`, { | |||||
| return request(`/api/mmp/machineLearn/${id}`, { | |||||
| method: 'DELETE', | method: 'DELETE', | ||||
| }); | }); | ||||
| } | } | ||||
| // 运行自动学习 | // 运行自动学习 | ||||
| export function runAutoMLReq(id) { | export function runAutoMLReq(id) { | ||||
| return request(`/api/mmp/autoML/run/${id}`, { | |||||
| return request(`/api/mmp/machineLearn/run/${id}`, { | |||||
| method: 'POST', | method: 'POST', | ||||
| }); | }); | ||||
| } | } | ||||
| @@ -56,7 +55,7 @@ export function runAutoMLReq(id) { | |||||
| // ----------------------- 实验实例 ----------------------- | // ----------------------- 实验实例 ----------------------- | ||||
| // 获取实验实例列表 | // 获取实验实例列表 | ||||
| export function getExperimentInsListReq(params) { | export function getExperimentInsListReq(params) { | ||||
| return request(`/api/mmp/autoMLIns`, { | |||||
| return request(`/api/mmp/machineLearnIns`, { | |||||
| method: 'GET', | method: 'GET', | ||||
| params, | params, | ||||
| }); | }); | ||||
| @@ -64,30 +63,29 @@ export function getExperimentInsListReq(params) { | |||||
| // 查询实验实例详情 | // 查询实验实例详情 | ||||
| export function getExperimentInsReq(id) { | export function getExperimentInsReq(id) { | ||||
| return request(`/api/mmp/autoMLIns/${id}`, { | |||||
| return request(`/api/mmp/machineLearnIns/${id}`, { | |||||
| method: 'GET', | method: 'GET', | ||||
| }); | }); | ||||
| } | } | ||||
| // 停止实验实例 | // 停止实验实例 | ||||
| export function stopExperimentInsReq(id) { | export function stopExperimentInsReq(id) { | ||||
| return request(`/api/mmp/autoMLIns/${id}`, { | |||||
| return request(`/api/mmp/machineLearnIns/${id}`, { | |||||
| method: 'PUT', | method: 'PUT', | ||||
| }); | }); | ||||
| } | } | ||||
| // 删除实验实例 | // 删除实验实例 | ||||
| export function deleteExperimentInsReq(id) { | export function deleteExperimentInsReq(id) { | ||||
| return request(`/api/mmp/autoMLIns/${id}`, { | |||||
| return request(`/api/mmp/machineLearnIns/${id}`, { | |||||
| method: 'DELETE', | method: 'DELETE', | ||||
| }); | }); | ||||
| } | } | ||||
| // 批量删除实验实例 | // 批量删除实验实例 | ||||
| export function batchDeleteExperimentInsReq(data) { | export function batchDeleteExperimentInsReq(data) { | ||||
| return request(`/api/mmp/autoMLIns/batchDelete`, { | |||||
| return request(`/api/mmp/machineLearnIns/batchDelete`, { | |||||
| method: 'DELETE', | method: 'DELETE', | ||||
| data | |||||
| data, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -34,6 +34,6 @@ export function deleteCodeConfigReq(id) { | |||||
| // 查询代码配置详情 | // 查询代码配置详情 | ||||
| export function getCodeConfigDetailReq(id) { | export function getCodeConfigDetailReq(id) { | ||||
| return request(`/api/mmp/codeConfig/${id}`, { | return request(`/api/mmp/codeConfig/${id}`, { | ||||
| method: 'GET' | |||||
| method: 'GET', | |||||
| }); | }); | ||||
| } | |||||
| } | |||||
| @@ -42,7 +42,6 @@ export function deleteDataset(params) { | |||||
| }); | }); | ||||
| } | } | ||||
| // 查询数据集版本列表 | // 查询数据集版本列表 | ||||
| export function getDatasetVersionList(params) { | export function getDatasetVersionList(params) { | ||||
| return request(`/api/mmp/newdataset/getVersionList`, { | return request(`/api/mmp/newdataset/getVersionList`, { | ||||
| @@ -63,7 +62,7 @@ export function addDatasetVersion(data) { | |||||
| export function downloadAllFiles(params) { | export function downloadAllFiles(params) { | ||||
| return request(`/api/mmp/newdataset/downloadAllFiles`, { | return request(`/api/mmp/newdataset/downloadAllFiles`, { | ||||
| method: 'GET', | method: 'GET', | ||||
| params | |||||
| params, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -109,7 +108,6 @@ export function deleteModel(params) { | |||||
| }); | }); | ||||
| } | } | ||||
| // 查询模型详情 | // 查询模型详情 | ||||
| export function getModelInfo(params) { | export function getModelInfo(params) { | ||||
| return request(`/api/mmp/newmodel/getModelDetail`, { | return request(`/api/mmp/newmodel/getModelDetail`, { | ||||
| @@ -134,7 +132,6 @@ export function addModelVersion(data) { | |||||
| }); | }); | ||||
| } | } | ||||
| // 删除模型版本 | // 删除模型版本 | ||||
| export function deleteModelVersion(params) { | export function deleteModelVersion(params) { | ||||
| return request(`/api/mmp/newmodel/deleteVersion`, { | return request(`/api/mmp/newmodel/deleteVersion`, { | ||||
| @@ -147,7 +144,7 @@ export function deleteModelVersion(params) { | |||||
| export function getModelAtlasReq(params) { | export function getModelAtlasReq(params) { | ||||
| return request(`/api/mmp/newmodel/getModelDependencyTree`, { | return request(`/api/mmp/newmodel/getModelDependencyTree`, { | ||||
| method: 'GET', | method: 'GET', | ||||
| params | |||||
| params, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -155,7 +152,7 @@ export function getModelAtlasReq(params) { | |||||
| export function exportModelReq(data) { | export function exportModelReq(data) { | ||||
| return request(`/api/mmp/models/exportModel`, { | return request(`/api/mmp/models/exportModel`, { | ||||
| method: 'POST', | method: 'POST', | ||||
| data | |||||
| data, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -163,7 +160,7 @@ export function exportModelReq(data) { | |||||
| export function getModelPageVersionsReq(params) { | export function getModelPageVersionsReq(params) { | ||||
| return request(`/api/mmp/newmodel/queryVersions`, { | return request(`/api/mmp/newmodel/queryVersions`, { | ||||
| method: 'GET', | method: 'GET', | ||||
| params | |||||
| params, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -171,7 +168,7 @@ export function getModelPageVersionsReq(params) { | |||||
| export function getModelVersionsMetricsReq(data) { | export function getModelVersionsMetricsReq(data) { | ||||
| return request(`/api/mmp/newmodel/queryVersionsMetrics`, { | return request(`/api/mmp/newmodel/queryVersionsMetrics`, { | ||||
| method: 'POST', | method: 'POST', | ||||
| data | |||||
| data, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -183,7 +180,6 @@ export function compareModelVersion(data) { | |||||
| }); | }); | ||||
| } | } | ||||
| // 删除上传的文件 | // 删除上传的文件 | ||||
| export function deleteUploadFileReq(params) { | export function deleteUploadFileReq(params) { | ||||
| return request(`/api/mmp/newdataset/deleteFile`, { | return request(`/api/mmp/newdataset/deleteFile`, { | ||||
| @@ -132,7 +132,7 @@ export function getTensorBoardStatusReq(data) { | |||||
| export function getExpEvaluateInfosReq(experimentId, params) { | export function getExpEvaluateInfosReq(experimentId, params) { | ||||
| return request(`/api/mmp/aim/getExpEvaluateInfos/${experimentId}`, { | return request(`/api/mmp/aim/getExpEvaluateInfos/${experimentId}`, { | ||||
| method: 'GET', | method: 'GET', | ||||
| params | |||||
| params, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -140,7 +140,7 @@ export function getExpEvaluateInfosReq(experimentId, params) { | |||||
| export function getExpTrainInfosReq(experimentId, params) { | export function getExpTrainInfosReq(experimentId, params) { | ||||
| return request(`/api/mmp/aim/getExpTrainInfos/${experimentId}`, { | return request(`/api/mmp/aim/getExpTrainInfos/${experimentId}`, { | ||||
| method: 'GET', | method: 'GET', | ||||
| params | |||||
| params, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -148,6 +148,6 @@ export function getExpTrainInfosReq(experimentId, params) { | |||||
| export function getExpMetricsReq(data) { | export function getExpMetricsReq(data) { | ||||
| return request(`/api/mmp/aim/getExpMetrics`, { | return request(`/api/mmp/aim/getExpMetrics`, { | ||||
| method: 'POST', | method: 'POST', | ||||
| data | |||||
| data, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -4,7 +4,6 @@ | |||||
| * @Description: 请求文件,比如 json 文件 | * @Description: 请求文件,比如 json 文件 | ||||
| */ | */ | ||||
| import { request } from '@umijs/max'; | import { request } from '@umijs/max'; | ||||
| // 获取文件,不需要token,非结构化数据 | // 获取文件,不需要token,非结构化数据 | ||||
| @@ -15,6 +14,6 @@ export function getFileReq(url, config) { | |||||
| isToken: false, | isToken: false, | ||||
| }, | }, | ||||
| skipValidating: true, | skipValidating: true, | ||||
| ...config | |||||
| ...config, | |||||
| }); | }); | ||||
| } | |||||
| } | |||||
| @@ -6,7 +6,6 @@ | |||||
| import { request } from '@umijs/max'; | import { request } from '@umijs/max'; | ||||
| // 分页查询超参数自动寻优 | // 分页查询超参数自动寻优 | ||||
| export function getRayListReq(params) { | export function getRayListReq(params) { | ||||
| return request(`/api/mmp/ray`, { | return request(`/api/mmp/ray`, { | ||||
| @@ -87,7 +86,7 @@ export function deleteRayInsReq(id) { | |||||
| export function batchDeleteRayInsReq(data) { | export function batchDeleteRayInsReq(data) { | ||||
| return request(`/api/mmp/rayIns/batchDelete`, { | return request(`/api/mmp/rayIns/batchDelete`, { | ||||
| method: 'DELETE', | method: 'DELETE', | ||||
| data | |||||
| data, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -95,6 +94,6 @@ export function batchDeleteRayInsReq(data) { | |||||
| export function getExpMetricsReq(data) { | export function getExpMetricsReq(data) { | ||||
| return request(`/api/mmp/rayIns/getExpMetrics`, { | return request(`/api/mmp/rayIns/getExpMetrics`, { | ||||
| method: 'POST', | method: 'POST', | ||||
| data | |||||
| data, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| /* | /* | ||||
| * @Author: 赵伟 | * @Author: 赵伟 | ||||
| * @Date: 2024-03-25 13:52:54 | * @Date: 2024-03-25 13:52:54 | ||||
| * @Description: | |||||
| * @Description: | |||||
| */ | */ | ||||
| import { request } from '@umijs/max'; | import { request } from '@umijs/max'; | ||||
| // 查询流水线列表 | // 查询流水线列表 | ||||
| @@ -73,6 +73,6 @@ export function getWorkflowById(id) { | |||||
| export function getComputingResourceReq(params) { | export function getComputingResourceReq(params) { | ||||
| return request(`/api/mmp/computingResource`, { | return request(`/api/mmp/computingResource`, { | ||||
| method: 'GET', | method: 'GET', | ||||
| params | |||||
| params, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -14,7 +14,6 @@ export function createIcon(icon: string | any): React.ReactNode | string { | |||||
| } | } | ||||
| const ele = allIcons[icon]; | const ele = allIcons[icon]; | ||||
| if (ele) { | if (ele) { | ||||
| return React.createElement(allIcons[icon]); | return React.createElement(allIcons[icon]); | ||||
| } | } | ||||
| return ''; | return ''; | ||||
| @@ -4,15 +4,15 @@ import { request } from '@umijs/max'; | |||||
| export enum MimeType { | export enum MimeType { | ||||
| XLSX = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | XLSX = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | ||||
| ZIP = 'application/zip', | ZIP = 'application/zip', | ||||
| JSON = 'application/json' | |||||
| }; | |||||
| JSON = 'application/json', | |||||
| } | |||||
| /** | /** | ||||
| * 解析blob响应内容并下载 | * 解析blob响应内容并下载 | ||||
| * @param res - blob响应内容 | * @param res - blob响应内容 | ||||
| * @param mimeType - MIME类型 | * @param mimeType - MIME类型 | ||||
| */ | */ | ||||
| export function resolveBlob(res: any, mimeType: string, specifiedFileName: string = "file") { | |||||
| export function resolveBlob(res: any, mimeType: string, specifiedFileName: string = 'file') { | |||||
| const aLink = document.createElement('a'); | const aLink = document.createElement('a'); | ||||
| const blob = new Blob([res.data], { type: mimeType }); | const blob = new Blob([res.data], { type: mimeType }); | ||||
| // 从response的headers中获取filename, | // 从response的headers中获取filename, | ||||
| @@ -77,7 +77,13 @@ export async function downloadXlsx( | |||||
| * @param method - 请求方法 | * @param method - 请求方法 | ||||
| * @param options - 请求选项 | * @param options - 请求选项 | ||||
| */ | */ | ||||
| export function downloadCommonFile(url: string, type: string, fileName: string = "file", method: string = 'GET', options?: Record<string, any>) { | |||||
| export function downloadCommonFile( | |||||
| url: string, | |||||
| type: string, | |||||
| fileName: string = 'file', | |||||
| method: string = 'GET', | |||||
| options?: Record<string, any>, | |||||
| ) { | |||||
| request(url, { | request(url, { | ||||
| method: method, | method: method, | ||||
| headers: { | headers: { | ||||
| @@ -172,7 +172,14 @@ export const formatBoolean = (value: boolean): string => { | |||||
| return value ? '是' : '否'; | return value ? '是' : '否'; | ||||
| }; | }; | ||||
| type FormatEnumFunc = (value: string | number) => React.ReactNode; | |||||
| export type FormatEnumFunc = (value: string | number) => React.ReactNode; | |||||
| // 枚举选项 | |||||
| export type EnumOptions = { | |||||
| label?: React.ReactNode; | |||||
| value?: string | number | null; | |||||
| [key: string | number]: any; | |||||
| }; | |||||
| /** | /** | ||||
| * 格式化枚举 | * 格式化枚举 | ||||
| @@ -180,9 +187,7 @@ type FormatEnumFunc = (value: string | number) => React.ReactNode; | |||||
| * @param options - 枚举选项数组 | * @param options - 枚举选项数组 | ||||
| * @return 一个函数,参数是枚举值,从选项数组中找到对应的项,然后返回该项的 label | * @return 一个函数,参数是枚举值,从选项数组中找到对应的项,然后返回该项的 label | ||||
| */ | */ | ||||
| export const formatEnum = ( | |||||
| options: { value?: string | number | null; label?: React.ReactNode }[], | |||||
| ): FormatEnumFunc => { | |||||
| export const formatEnum = (options: EnumOptions[]): FormatEnumFunc => { | |||||
| return (value: string | number) => { | return (value: string | number) => { | ||||
| const option = options.find((item) => item.value === value); | const option = options.find((item) => item.value === value); | ||||
| return option && option.label ? option.label : '--'; | return option && option.label ? option.label : '--'; | ||||
| @@ -8,6 +8,8 @@ import { isEmpty } from '@/utils'; | |||||
| import { formatDate } from '@/utils/date'; | import { formatDate } from '@/utils/date'; | ||||
| import { Tooltip, TooltipProps, Typography } from 'antd'; | import { Tooltip, TooltipProps, Typography } from 'antd'; | ||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||
| import React from 'react'; | |||||
| import { formatEnum, type EnumOptions } from './format'; | |||||
| export enum TableCellValueType { | export enum TableCellValueType { | ||||
| /** 序号 */ | /** 序号 */ | ||||
| @@ -20,6 +22,8 @@ export enum TableCellValueType { | |||||
| Array = 'Array', | Array = 'Array', | ||||
| /** 链接 */ | /** 链接 */ | ||||
| Link = 'Link', | Link = 'Link', | ||||
| /** 枚举 */ | |||||
| Enum = 'Enum', | |||||
| /** 自定义 */ | /** 自定义 */ | ||||
| Custom = 'Custom', | Custom = 'Custom', | ||||
| } | } | ||||
| @@ -35,8 +39,14 @@ export type TableCellValueOptions<T> = { | |||||
| dateFormat?: string; | dateFormat?: string; | ||||
| /** 链接点击回调,类型为 Link 时有效 */ | /** 链接点击回调,类型为 Link 时有效 */ | ||||
| onClick?: (record: T, e: React.MouseEvent) => void; | onClick?: (record: T, e: React.MouseEvent) => void; | ||||
| /** 枚举选项,类型为 Enum 时有效*/ | |||||
| options?: EnumOptions[]; | |||||
| /** 自定义函数,类型为 Custom 时有效*/ | /** 自定义函数,类型为 Custom 时有效*/ | ||||
| format?: (value: any | undefined | null, record: T, index: number) => string | undefined | null; | |||||
| format?: ( | |||||
| value: any | undefined | null, | |||||
| record?: T, | |||||
| index?: number, | |||||
| ) => React.ReactNode | undefined | null; | |||||
| /** 省略时是否可以复制 */ | /** 省略时是否可以复制 */ | ||||
| copyable?: boolean; | copyable?: boolean; | ||||
| }; | }; | ||||
| @@ -110,6 +120,11 @@ function tableCellRender<T>( | |||||
| case TableCellValueType.Array: | case TableCellValueType.Array: | ||||
| text = formatArray(options?.property)(value); | text = formatArray(options?.property)(value); | ||||
| break; | break; | ||||
| case TableCellValueType.Enum: | |||||
| if (options?.options) { | |||||
| text = formatEnum(options.options)(value); | |||||
| } | |||||
| break; | |||||
| case TableCellValueType.Custom: | case TableCellValueType.Custom: | ||||
| text = options?.format?.(value, record, index); | text = options?.format?.(value, record, index); | ||||
| break; | break; | ||||