From e436f28c6a0fa33ff2375d6fa1f5817dcc939c38 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Mon, 13 May 2024 10:22:38 +0800 Subject: [PATCH 1/8] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E9=9B=86=E5=92=8C=E6=A8=A1=E5=9E=8B=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/config/routes.ts | 4 +- .../src/components/RightContent/index.tsx | 1 + .../components/AddDatasetModal/index.less | 2 +- .../components/AddDatasetModal/index.tsx | 16 +- .../components/AddModelModal/index.tsx | 18 +- .../components/AddVersionModal/index.tsx | 169 ++++++++++++++++ .../Dataset/components/ResourceList/index.tsx | 2 +- .../Dataset/{datasetIntro.jsx => intro.jsx} | 190 +++--------------- .../pages/Dataset/{index.less => intro.less} | 0 react-ui/src/pages/Dataset/type.tsx | 18 +- .../Model/components/AddModelModal/index.less | 4 - .../pages/Model/{modelIntro.jsx => intro.jsx} | 165 ++------------- .../pages/Model/{index.less => intro.less} | 0 13 files changed, 252 insertions(+), 337 deletions(-) rename react-ui/src/pages/{Model => Dataset}/components/AddModelModal/index.tsx (93%) create mode 100644 react-ui/src/pages/Dataset/components/AddVersionModal/index.tsx rename react-ui/src/pages/Dataset/{datasetIntro.jsx => intro.jsx} (64%) rename react-ui/src/pages/Dataset/{index.less => intro.less} (100%) delete mode 100644 react-ui/src/pages/Model/components/AddModelModal/index.less rename react-ui/src/pages/Model/{modelIntro.jsx => intro.jsx} (64%) rename react-ui/src/pages/Model/{index.less => intro.less} (100%) diff --git a/react-ui/config/routes.ts b/react-ui/config/routes.ts index cd81e412..855ad15c 100644 --- a/react-ui/config/routes.ts +++ b/react-ui/config/routes.ts @@ -131,7 +131,7 @@ export default [ { name: '数据集简介', path: ':id', - component: './Dataset/datasetIntro', + component: './Dataset/intro', }, ], }, @@ -147,7 +147,7 @@ export default [ { name: '模型简介', path: ':id', - component: './Model/modelIntro', + component: './Model/intro', }, ], }, diff --git a/react-ui/src/components/RightContent/index.tsx b/react-ui/src/components/RightContent/index.tsx index 70e57e23..75d86186 100644 --- a/react-ui/src/components/RightContent/index.tsx +++ b/react-ui/src/components/RightContent/index.tsx @@ -2,6 +2,7 @@ import { useEmotionCss } from '@ant-design/use-emotion-css'; import { useModel } from '@umijs/max'; import React from 'react'; import Avatar from './AvatarDropdown'; +// import { SelectLang } from '@umijs/max'; export type SiderTheme = 'light' | 'dark'; diff --git a/react-ui/src/pages/Dataset/components/AddDatasetModal/index.less b/react-ui/src/pages/Dataset/components/AddDatasetModal/index.less index 529521af..66022fdd 100644 --- a/react-ui/src/pages/Dataset/components/AddDatasetModal/index.less +++ b/react-ui/src/pages/Dataset/components/AddDatasetModal/index.less @@ -4,6 +4,6 @@ } .upload-button { - height: 48px; + height: 46px; font-size: 15px; } diff --git a/react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx b/react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx index c83d5143..dbb8fc84 100644 --- a/react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx +++ b/react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx @@ -23,7 +23,7 @@ import { useEffect, useState } from 'react'; import { CategoryData } from '../../type'; import styles from './index.less'; -interface AddDatasetModalProps extends ModalProps { +interface AddDatasetModalProps extends Omit { typeList: CategoryData[]; tagList: CategoryData[]; onOk: () => void; @@ -94,15 +94,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr }} destroyOnClose > -
+ @@ -142,6 +136,8 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr placeholder="请选择研究方向/应用领域" options={tagList} fieldNames={{ label: 'name', value: 'id' }} + optionFilterProp="name" + showSearch /> diff --git a/react-ui/src/pages/Model/components/AddModelModal/index.tsx b/react-ui/src/pages/Dataset/components/AddModelModal/index.tsx similarity index 93% rename from react-ui/src/pages/Model/components/AddModelModal/index.tsx rename to react-ui/src/pages/Dataset/components/AddModelModal/index.tsx index e04b1ba1..21e76faa 100644 --- a/react-ui/src/pages/Model/components/AddModelModal/index.tsx +++ b/react-ui/src/pages/Dataset/components/AddModelModal/index.tsx @@ -18,9 +18,9 @@ import { } from 'antd'; import { omit } from 'lodash'; import { useState } from 'react'; -import styles from './index.less'; +import styles from '../AddDatasetModal/index.less'; -interface AddModelModalProps extends ModalProps { +interface AddModelModalProps extends Omit { typeList: CategoryData[]; tagList: CategoryData[]; onOk: () => void; @@ -76,15 +76,7 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) form: 'form', }} > - + @@ -148,6 +142,8 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) placeholder="请选择模型标签" options={tagList} fieldNames={{ label: 'name', value: 'id' }} + optionFilterProp="name" + showSearch /> { + resourceType: ResourceType; + resourceId: number; + initialName: string; + onOk: () => void; +} + +function AddVersionModal({ + resourceType, + resourceId, + initialName, + onOk, + ...rest +}: AddVersionModalProps) { + const [uuid] = useState(Date.now()); + + // 上传组件参数 + const uploadProps: UploadProps = { + action: resourceConfig[resourceType].uploadAction, + headers: { + Authorization: getAccessToken() || '', + }, + defaultFileList: [], + }; + + // 上传请求 + const createDatasetVersion = async (params: any) => { + const request = resourceConfig[resourceType].addVersionReq; + const [res] = await to(request(params)); + if (res) { + message.success('创建成功'); + onOk?.(); + } + }; + + // 提交 + const onFinish = (formData: any) => { + const fileList: UploadFile[] = formData['fileList'] ?? []; + if (validateUploadFiles(fileList)) { + const otherParams = omit(formData, ['fileList']); + const params = fileList.map((item) => { + const data = item.response?.data?.[0] ?? {}; + return { + ...otherParams, + [resourceConfig[resourceType].idParamKey]: resourceId, + file_name: data.fileName, + file_size: data.fileSize, + url: data.url, + }; + }); + createDatasetVersion(params); + } + }; + + const name = resourceConfig[resourceType].name; + const accept = resourceConfig[resourceType].uploadAccept; + return ( + + + + + + + + + + + + + + + {resourceType === ResourceType.Dataset && ( +
只允许上传.zip格式文件
+ )} +
+
+ +
+ ); +} + +export default AddVersionModal; diff --git a/react-ui/src/pages/Dataset/components/ResourceList/index.tsx b/react-ui/src/pages/Dataset/components/ResourceList/index.tsx index b07cb5bf..59ff87f6 100644 --- a/react-ui/src/pages/Dataset/components/ResourceList/index.tsx +++ b/react-ui/src/pages/Dataset/components/ResourceList/index.tsx @@ -1,6 +1,6 @@ import KFIcon from '@/components/KFIcon'; import { CommonTabKeys } from '@/enums'; -import AddModelModal from '@/pages/Model/components/AddModelModal'; +import AddModelModal from '@/pages/Dataset/components/AddModelModal'; import { openAntdModal } from '@/utils/modal'; import { to } from '@/utils/promise'; import { modalConfirm } from '@/utils/ui'; diff --git a/react-ui/src/pages/Dataset/datasetIntro.jsx b/react-ui/src/pages/Dataset/intro.jsx similarity index 64% rename from react-ui/src/pages/Dataset/datasetIntro.jsx rename to react-ui/src/pages/Dataset/intro.jsx index 16128aeb..66f08b9c 100644 --- a/react-ui/src/pages/Dataset/datasetIntro.jsx +++ b/react-ui/src/pages/Dataset/intro.jsx @@ -1,56 +1,25 @@ -import { getAccessToken } from '@/access'; import KFIcon from '@/components/KFIcon'; -import KFModal from '@/components/KFModal'; +import { ResourceType } from '@/pages/Dataset/type'; import { - addDatasetVersionDetail, deleteDatasetVersion, getDatasetById, getDatasetVersionIdList, getDatasetVersionsById, } from '@/services/dataset/index.js'; import { downLoadZip } from '@/utils/downloadfile'; +import { openAntdModal } from '@/utils/modal'; import { modalConfirm } from '@/utils/ui'; -import { UploadOutlined } from '@ant-design/icons'; import { useParams, useSearchParams } from '@umijs/max'; -import { Button, Form, Input, Select, Table, Tabs, Upload, message } from 'antd'; +import { Button, Input, Select, Table, Tabs, message } from 'antd'; import moment from 'moment'; import { useEffect, useRef, useState } from 'react'; -import Styles from './index.less'; +import AddVersionModal from './components/AddVersionModal'; +import Styles from './intro.less'; const { Search } = Input; const { TabPane } = Tabs; const Dataset = () => { - const props = { - action: '/api/mmp/dataset/upload', - // headers: { - // 'X-Requested-With': null - // }, - headers: { - Authorization: getAccessToken(), - 'X-Requested-With': null, - }, - onChange({ file, fileList }) { - if (file.status !== 'uploading') { - console.log(file, fileList); - setFormList( - fileList.map((item) => { - return { - ...form.getFieldsValue(), - dataset_id: locationParams.id, - file_name: item.response.code === 200 ? item.response.data[0].fileName : null, - file_size: item.response.code === 200 ? item.response.data[0].fileSize : null, - url: item.response.code === 200 ? item.response.data[0].url : null, - }; - }), - ); - } - }, - defaultFileList: [], - }; - const [form] = Form.useForm(); const [formList, setFormList] = useState([]); - const [dialogTitle, setDialogTitle] = useState('新建版本'); - const [isModalOpen, setIsModalOpen] = useState(false); const [datasetDetailObj, setDatasetDetailObj] = useState({}); const [version, setVersion] = useState(null); const [versionList, setVersionList] = useState([]); @@ -58,8 +27,8 @@ const Dataset = () => { const [searchParams] = useSearchParams(); const [wordList, setWordList] = useState([]); const [activeTabKey, setActiveTabKey] = useState('1'); - const [uuid, setUuid] = useState(Date.now()); const isPublic = searchParams.get('isPublic') === 'true'; + const getDatasetByDetail = () => { getDatasetById(locationParams.id).then((ret) => { console.log(ret); @@ -93,21 +62,17 @@ const Dataset = () => { return () => {}; }, []); const showModal = () => { - form.resetFields(); - form.setFieldsValue({ name: datasetDetailObj.name }); - - setDialogTitle('创建新版本'); - setUuid(Date.now()); - setIsModalOpen(true); - }; - const handleCancel = () => { - setIsModalOpen(false); - }; - const handleExport = async () => { - const hide = message.loading('正在下载'); - hide(); - downLoadZip(`/api/mmp/dataset/downloadAllFiles`, { dataset_id: locationParams.id, version }); + const { close } = openAntdModal(AddVersionModal, { + resourceType: ResourceType.Dataset, + resourceId: locationParams.id, + initialName: datasetDetailObj.name, + onOk: () => { + getDatasetVersionList(); + close(); + }, + }); }; + const deleteDataset = () => { modalConfirm({ title: '删除后,该数据集版本将不可恢复', @@ -120,19 +85,26 @@ const Dataset = () => { }, }); }; - const onFinish = (values) => { - addDatasetVersionDetail(formList).then((ret) => { - getDatasetVersionList(); - setIsModalOpen(false); - message.success('创建成功'); - }); - }; // 获取版本下的文件列表 const getDatasetVersions = (params) => { getDatasetVersionIdList(params).then((res) => { setWordList(res?.data?.content ?? []); }); }; + + const handleExport = async () => { + const hide = message.loading('正在下载'); + hide(); + downLoadZip(`/api/mmp/dataset/downloadAllFiles`, { dataset_id: locationParams.id, version }); + }; + + const downloadAlone = (e, record) => { + console.log(record); + const hide = message.loading('正在下载'); + hide(); + downLoadZip(`/api/mmp/dataset/download/${record.id}`); + }; + const handleChange = (value) => { console.log(value); if (value) { @@ -142,15 +114,7 @@ const Dataset = () => { setVersion(null); } }; - const onFinishFailed = (errorInfo) => { - console.log('Failed:', errorInfo); - }; - const downloadAlone = (e, record) => { - console.log(record); - const hide = message.loading('正在下载'); - hide(); - downLoadZip(`/api/mmp/dataset/download/${record.id}`); - }; + const columns = [ { title: '序号', @@ -292,98 +256,6 @@ const Dataset = () => { - -
- - - - - - - - - - - - -
只允许上传.zip,.tgz格式文件
-
-
-
-
); }; diff --git a/react-ui/src/pages/Dataset/index.less b/react-ui/src/pages/Dataset/intro.less similarity index 100% rename from react-ui/src/pages/Dataset/index.less rename to react-ui/src/pages/Dataset/intro.less diff --git a/react-ui/src/pages/Dataset/type.tsx b/react-ui/src/pages/Dataset/type.tsx index 91808ea2..3bc7f2fe 100644 --- a/react-ui/src/pages/Dataset/type.tsx +++ b/react-ui/src/pages/Dataset/type.tsx @@ -1,6 +1,8 @@ import KFIcon from '@/components/KFIcon'; import { CommonTabKeys } from '@/enums'; import { + addDatasetVersionDetail, + addModelsVersionDetail, deleteDataset, deleteModel, getDatasetList, @@ -18,9 +20,9 @@ export enum ResourceType { } type ResourceTypeKeys = keyof typeof ResourceType; -type ResourceTypeValues = (typeof ResourceType)[ResourceTypeKeys]; +export type ResourceTypeValues = (typeof ResourceType)[ResourceTypeKeys]; -export type ResourceTypeInfo = { +type ResourceTypeInfo = { getList: (params: any) => Promise; getVersions: (params: any) => Promise; getFiles: (params: any) => Promise; @@ -37,6 +39,10 @@ export type ResourceTypeInfo = { iconPathPrefix: string; // 图标路径前缀 deleteModalTitle: string; // 删除弹框的title addBtnTitle: string; // 新增按钮的title + addVersionReq: (params: any) => Promise; + idParamKey: string; + uploadAction: string; + uploadAccept?: string; }; export const resourceConfig: Record = { @@ -68,6 +74,10 @@ export const resourceConfig: Record = { iconPathPrefix: 'dataset', deleteModalTitle: '确定删除该条数据集实例吗?', addBtnTitle: '新建数据集', + addVersionReq: addDatasetVersionDetail, + idParamKey: 'dataset_id', + uploadAction: '/api/mmp/dataset/upload', + uploadAccept: '.zip,.tgz', }, [ResourceType.Model]: { getList: getModelList, @@ -97,6 +107,10 @@ export const resourceConfig: Record = { iconPathPrefix: 'model', deleteModalTitle: '确定删除该条模型实例吗?', addBtnTitle: '新建模型', + addVersionReq: addModelsVersionDetail, + idParamKey: 'models_id', + uploadAction: '/api/mmp/models/upload', + uploadAccept: undefined, }, }; diff --git a/react-ui/src/pages/Model/components/AddModelModal/index.less b/react-ui/src/pages/Model/components/AddModelModal/index.less deleted file mode 100644 index bb520221..00000000 --- a/react-ui/src/pages/Model/components/AddModelModal/index.less +++ /dev/null @@ -1,4 +0,0 @@ -.upload-button { - height: 48px; - font-size: 15px; -} diff --git a/react-ui/src/pages/Model/modelIntro.jsx b/react-ui/src/pages/Model/intro.jsx similarity index 64% rename from react-ui/src/pages/Model/modelIntro.jsx rename to react-ui/src/pages/Model/intro.jsx index d978f15e..22efc474 100644 --- a/react-ui/src/pages/Model/modelIntro.jsx +++ b/react-ui/src/pages/Model/intro.jsx @@ -1,65 +1,33 @@ -import { getAccessToken } from '@/access'; import KFIcon from '@/components/KFIcon'; -import KFModal from '@/components/KFModal'; +import AddVersionModal from '@/pages/Dataset/components/AddVersionModal'; +import { ResourceType } from '@/pages/Dataset/type'; import { - addModelsVersionDetail, deleteModelVersion, getModelById, getModelVersionIdList, getModelVersionsById, } from '@/services/dataset/index.js'; import { downLoadZip } from '@/utils/downloadfile'; +import { openAntdModal } from '@/utils/modal'; import { modalConfirm } from '@/utils/ui'; -import { UploadOutlined } from '@ant-design/icons'; import { useParams, useSearchParams } from '@umijs/max'; -import { Button, Form, Input, Select, Table, Tabs, Upload, message } from 'antd'; +import { Button, Input, Select, Table, Tabs, message } from 'antd'; import moment from 'moment'; import { useEffect, useRef, useState } from 'react'; -import Styles from './index.less'; +import Styles from './intro.less'; const { Search } = Input; const { TabPane } = Tabs; const Dataset = () => { - const props = { - action: '/api/mmp/models/upload', - // headers: { - // 'X-Requested-With': null - // }, - headers: { - Authorization: getAccessToken(), - 'X-Requested-With': null, - }, - onChange({ file, fileList }) { - if (file.status !== 'uploading') { - console.log(file, fileList); - setFormList( - fileList.map((item) => { - return { - ...form.getFieldsValue(), - models_id: locationParams.id, - file_name: item.response.code === 200 ? item.response.data[0].fileName : null, - file_size: item.response.code === 200 ? item.response.data[0].fileSize : null, - url: item.response.code === 200 ? item.response.data[0].url : null, - }; - }), - ); - } - }, - defaultFileList: [], - }; - const [form] = Form.useForm(); const [formList, setFormList] = useState([]); - const [dialogTitle, setDialogTitle] = useState('新建版本'); - const [isModalOpen, setIsModalOpen] = useState(false); const [datasetDetailObj, setDatasetDetailObj] = useState({}); const [version, setVersion] = useState(null); const [versionList, setVersionList] = useState([]); const locationParams = useParams(); //新版本获取路由参数接口 const [searchParams] = useSearchParams(); - console.log(locationParams); const [wordList, setWordList] = useState([]); - const [uuid, setUuid] = useState(Date.now()); const isPublic = searchParams.get('isPublic') === 'true'; + const getModelByDetail = () => { getModelById(locationParams.id).then((ret) => { console.log(ret); @@ -92,16 +60,17 @@ const Dataset = () => { return () => {}; }, []); const showModal = () => { - form.resetFields(); - form.setFieldsValue({ name: datasetDetailObj.name }); - - setDialogTitle('创建新版本'); - setUuid(Date.now()); - setIsModalOpen(true); - }; - const handleCancel = () => { - setIsModalOpen(false); + const { close } = openAntdModal(AddVersionModal, { + resourceType: ResourceType.Model, + resourceId: locationParams.id, + initialName: datasetDetailObj.name, + onOk: () => { + getModelVersionsList(); + close(); + }, + }); }; + const deleteDataset = () => { modalConfirm({ title: '删除后,该版本将不可恢复', @@ -117,13 +86,7 @@ const Dataset = () => { }, }); }; - const onFinish = () => { - addModelsVersionDetail(formList).then((ret) => { - getModelVersionsList(); - setIsModalOpen(false); - message.success('创建成功'); - }); - }; + const getModelVersions = (params) => { getModelVersionIdList(params).then((ret) => { setWordList(ret?.data?.content ?? []); @@ -149,9 +112,7 @@ const Dataset = () => { setVersion(''); } }; - const onFinishFailed = (errorInfo) => { - console.log('Failed:', errorInfo); - }; + const columns = [ { title: '序号', @@ -294,96 +255,6 @@ const Dataset = () => { - -
- - - - - - - - - - - - - - -
-
); }; diff --git a/react-ui/src/pages/Model/index.less b/react-ui/src/pages/Model/intro.less similarity index 100% rename from react-ui/src/pages/Model/index.less rename to react-ui/src/pages/Model/intro.less From 6c4926c7ede7f3adf0494bf7635dd1f5e65cbc67 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Mon, 13 May 2024 10:23:11 +0800 Subject: [PATCH 2/8] =?UTF-8?q?refactor:=20=E4=BF=AE=E6=94=B9=E5=AE=9E?= =?UTF-8?q?=E9=AA=8C=E4=B8=AD=E7=BB=84=E4=BB=B6=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/src/components/KFModal/index.tsx | 3 ++- .../AddExperimentModal/index.less} | 0 .../AddExperimentModal/index.tsx} | 2 +- .../ViewParamsModal/index.less} | 0 .../ViewParamsModal/index.tsx} | 5 +++-- react-ui/src/pages/Experiment/experimentText/index.jsx | 2 +- react-ui/src/pages/Experiment/index.jsx | 2 +- .../GlobalParamsDrawer/index.less} | 0 .../GlobalParamsDrawer/index.tsx} | 7 ++----- react-ui/src/pages/Pipeline/editPipeline/index.jsx | 2 +- .../pages/Workspace/components/AssetsManagement/index.tsx | 2 +- react-ui/src/utils/ui.tsx | 4 ++-- 12 files changed, 14 insertions(+), 15 deletions(-) rename react-ui/src/pages/Experiment/{experimentText/addExperimentModal.less => components/AddExperimentModal/index.less} (100%) rename react-ui/src/pages/Experiment/{experimentText/addExperimentModal.tsx => components/AddExperimentModal/index.tsx} (99%) rename react-ui/src/pages/Experiment/{experimentText/paramsModal.less => components/ViewParamsModal/index.less} (100%) rename react-ui/src/pages/Experiment/{experimentText/paramsModal.tsx => components/ViewParamsModal/index.tsx} (91%) rename react-ui/src/pages/Pipeline/{editPipeline/globalParamsDrawer.less => components/GlobalParamsDrawer/index.less} (100%) rename react-ui/src/pages/Pipeline/{editPipeline/globalParamsDrawer.tsx => components/GlobalParamsDrawer/index.tsx} (97%) diff --git a/react-ui/src/components/KFModal/index.tsx b/react-ui/src/components/KFModal/index.tsx index 0105324f..8fea54bc 100644 --- a/react-ui/src/components/KFModal/index.tsx +++ b/react-ui/src/components/KFModal/index.tsx @@ -12,11 +12,12 @@ import './index.less'; export interface KFModalProps extends ModalProps { image?: string; } -function KFModal({ title, image, children, className = '', ...rest }: KFModalProps) { +function KFModal({ title, image, children, className = '', centered, ...rest }: KFModalProps) { return ( } > {children} diff --git a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less b/react-ui/src/pages/Experiment/components/AddExperimentModal/index.less similarity index 100% rename from react-ui/src/pages/Experiment/experimentText/addExperimentModal.less rename to react-ui/src/pages/Experiment/components/AddExperimentModal/index.less diff --git a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx b/react-ui/src/pages/Experiment/components/AddExperimentModal/index.tsx similarity index 99% rename from react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx rename to react-ui/src/pages/Experiment/components/AddExperimentModal/index.tsx index f5b2bfc4..2300c0f1 100644 --- a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx +++ b/react-ui/src/pages/Experiment/components/AddExperimentModal/index.tsx @@ -4,7 +4,7 @@ import KFModal from '@/components/KFModal'; import { type PipelineGlobalParam } from '@/types'; import { Form, Input, Radio, Select, type FormRule } from 'antd'; import { useState } from 'react'; -import styles from './addExperimentModal.less'; +import styles from './index.less'; type FormData = { name?: string; diff --git a/react-ui/src/pages/Experiment/experimentText/paramsModal.less b/react-ui/src/pages/Experiment/components/ViewParamsModal/index.less similarity index 100% rename from react-ui/src/pages/Experiment/experimentText/paramsModal.less rename to react-ui/src/pages/Experiment/components/ViewParamsModal/index.less diff --git a/react-ui/src/pages/Experiment/experimentText/paramsModal.tsx b/react-ui/src/pages/Experiment/components/ViewParamsModal/index.tsx similarity index 91% rename from react-ui/src/pages/Experiment/experimentText/paramsModal.tsx rename to react-ui/src/pages/Experiment/components/ViewParamsModal/index.tsx index 1bdb0cec..f860135a 100644 --- a/react-ui/src/pages/Experiment/experimentText/paramsModal.tsx +++ b/react-ui/src/pages/Experiment/components/ViewParamsModal/index.tsx @@ -6,8 +6,8 @@ import parameterImg from '@/assets/img/modal-parameter.png'; import KFModal from '@/components/KFModal'; import { type PipelineGlobalParam } from '@/types'; -import { getParamType } from './addExperimentModal'; -import styles from './paramsModal.less'; +import { getParamType } from '../AddExperimentModal'; +import styles from './index.less'; type ParamsModalProps = { open: boolean; @@ -24,6 +24,7 @@ function ParamsModal({ open, onCancel, globalParam = [] }: ParamsModalProps) { onOk={onCancel} onCancel={onCancel} cancelButtonProps={{ style: { display: 'none' } }} + width={825} >
{globalParam?.map((item) => ( diff --git a/react-ui/src/pages/Experiment/experimentText/index.jsx b/react-ui/src/pages/Experiment/experimentText/index.jsx index a5ed2ffc..cc74eba4 100644 --- a/react-ui/src/pages/Experiment/experimentText/index.jsx +++ b/react-ui/src/pages/Experiment/experimentText/index.jsx @@ -9,9 +9,9 @@ import momnet from 'moment'; import { useEffect, useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { s8 } from '../../../utils'; +import ParamsModal from '../components/ViewParamsModal'; import { experimentStatusInfo } from '../status'; import styles from './index.less'; -import ParamsModal from './paramsModal'; import Props from './props'; function ExperimentText() { diff --git a/react-ui/src/pages/Experiment/index.jsx b/react-ui/src/pages/Experiment/index.jsx index 611c18c6..1c93f834 100644 --- a/react-ui/src/pages/Experiment/index.jsx +++ b/react-ui/src/pages/Experiment/index.jsx @@ -22,8 +22,8 @@ import classNames from 'classnames'; import momnet from 'moment'; import { useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; +import AddExperimentModal from './components/AddExperimentModal'; import TensorBoardStatus, { TensorBoardStatusEnum } from './components/TensorBoardStatus'; -import AddExperimentModal from './experimentText/addExperimentModal'; import Styles from './index.less'; import { experimentStatusInfo } from './status'; diff --git a/react-ui/src/pages/Pipeline/editPipeline/globalParamsDrawer.less b/react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.less similarity index 100% rename from react-ui/src/pages/Pipeline/editPipeline/globalParamsDrawer.less rename to react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.less diff --git a/react-ui/src/pages/Pipeline/editPipeline/globalParamsDrawer.tsx b/react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx similarity index 97% rename from react-ui/src/pages/Pipeline/editPipeline/globalParamsDrawer.tsx rename to react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx index 817d6dc6..5e619d7a 100644 --- a/react-ui/src/pages/Pipeline/editPipeline/globalParamsDrawer.tsx +++ b/react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx @@ -1,7 +1,4 @@ -import { - getParamComponent, - getParamRules, -} from '@/pages/Experiment/experimentText/addExperimentModal'; +import { getParamComponent, getParamRules } from '@/pages/Experiment/components/AddExperimentModal'; import { type PipelineGlobalParam } from '@/types'; import { to } from '@/utils/promise'; import { modalConfirm } from '@/utils/ui'; @@ -9,7 +6,7 @@ import { DeleteOutlined, PlusOutlined } from '@ant-design/icons'; import { Button, Drawer, Form, Input, Radio, Tooltip } from 'antd'; import { NamePath } from 'antd/es/form/interface'; import { forwardRef, useImperativeHandle } from 'react'; -import styles from './globalParamsDrawer.less'; +import styles from './index.less'; type GlobalParamsDrawerProps = { open: boolean; diff --git a/react-ui/src/pages/Pipeline/editPipeline/index.jsx b/react-ui/src/pages/Pipeline/editPipeline/index.jsx index be5366dd..538626aa 100644 --- a/react-ui/src/pages/Pipeline/editPipeline/index.jsx +++ b/react-ui/src/pages/Pipeline/editPipeline/index.jsx @@ -8,8 +8,8 @@ import { Button, message } from 'antd'; import { useEffect, useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { s8 } from '../../../utils'; +import GlobalParamsDrawer from '../components/GlobalParamsDrawer'; import Styles from './editPipeline.less'; -import GlobalParamsDrawer from './globalParamsDrawer'; import ModelMenus from './modelMenus'; import Props from './props'; diff --git a/react-ui/src/pages/Workspace/components/AssetsManagement/index.tsx b/react-ui/src/pages/Workspace/components/AssetsManagement/index.tsx index 1a734e57..74227506 100644 --- a/react-ui/src/pages/Workspace/components/AssetsManagement/index.tsx +++ b/react-ui/src/pages/Workspace/components/AssetsManagement/index.tsx @@ -65,7 +65,7 @@ function AssetsManagement() { /> {/*
今日新增数量:5
*/} - + {assetCounts.map((item, index) => (
{item.title}
diff --git a/react-ui/src/utils/ui.tsx b/react-ui/src/utils/ui.tsx index 8f8bde3f..b1c456e3 100644 --- a/react-ui/src/utils/ui.tsx +++ b/react-ui/src/utils/ui.tsx @@ -76,11 +76,11 @@ export const validateUploadFiles = (files: UploadFile[], required: boolean = tru return true; } if (file.status === 'error') { - message.error('存在上传失败的文件,请删除后重新上传文件'); + message.error('存在上传失败的文件,请删除后重新上传'); return true; } if (!file.response || file.response.code !== 200 || !file.response.data) { - message.error('存在上传失败的文件,请删除后重新上传文件'); + message.error('存在上传失败的文件,请删除后重新上传'); return true; } return false; From 05c7ef7403f38a3dccf0f4e22ce2dc84fc364973 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Mon, 13 May 2024 12:52:08 +0800 Subject: [PATCH 3/8] =?UTF-8?q?feat:=20table=20column=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=20ellipsis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/src/app.tsx | 12 +- .../src/components/CommonTableCell/index.tsx | 12 +- react-ui/src/pages/Mirror/info.tsx | 6 +- react-ui/src/pages/Mirror/list.tsx | 8 +- react-ui/src/pages/User/Login/index.tsx | 413 +++++++++--------- react-ui/src/pages/User/Login/login.less | 55 +-- react-ui/src/requestConfig.ts | 1 - react-ui/src/utils/ui.tsx | 6 +- 8 files changed, 266 insertions(+), 247 deletions(-) diff --git a/react-ui/src/app.tsx b/react-ui/src/app.tsx index 66005f50..becc1abc 100644 --- a/react-ui/src/app.tsx +++ b/react-ui/src/app.tsx @@ -184,10 +184,14 @@ export function render(oldRender: () => void) { oldRender(); return; } - getRoutersInfo().then((res) => { - setRemoteMenu(res); - oldRender(); - }); + getRoutersInfo() + .then((res) => { + setRemoteMenu(res); + oldRender(); + }) + .catch(() => { + oldRender(); + }); } // 主题修改 diff --git a/react-ui/src/components/CommonTableCell/index.tsx b/react-ui/src/components/CommonTableCell/index.tsx index 65a1dff2..6c2f35b0 100644 --- a/react-ui/src/components/CommonTableCell/index.tsx +++ b/react-ui/src/components/CommonTableCell/index.tsx @@ -4,8 +4,18 @@ * @Description: 自定义 Table 单元格,没有数据时展示 -- */ -function CommonTableCell(text?: string | null) { +import { Tooltip } from 'antd'; + +function renderCell(text?: string | null) { return {text ?? '--'}; } +function CommonTableCell(ellipsis: boolean = false) { + if (ellipsis) { + return (text?: string | null) => {renderCell(text)}; + } else { + return renderCell; + } +} + export default CommonTableCell; diff --git a/react-ui/src/pages/Mirror/info.tsx b/react-ui/src/pages/Mirror/info.tsx index 8f26dd9f..a2c806ab 100644 --- a/react-ui/src/pages/Mirror/info.tsx +++ b/react-ui/src/pages/Mirror/info.tsx @@ -161,13 +161,13 @@ function MirrorInfo() { dataIndex: 'tag_name', key: 'tag_name', width: '25%', - render: CommonTableCell, + render: CommonTableCell(), }, { title: '镜像地址', dataIndex: 'url', key: 'url', - render: CommonTableCell, + render: CommonTableCell(), }, { title: '状态', @@ -181,7 +181,7 @@ function MirrorInfo() { dataIndex: 'file_size', key: 'file_size', width: 150, - render: CommonTableCell, + render: CommonTableCell(), }, { title: '创建时间', diff --git a/react-ui/src/pages/Mirror/list.tsx b/react-ui/src/pages/Mirror/list.tsx index 24932f6d..16bfeb1a 100644 --- a/react-ui/src/pages/Mirror/list.tsx +++ b/react-ui/src/pages/Mirror/list.tsx @@ -166,21 +166,21 @@ function MirrorList() { dataIndex: 'name', key: 'name', width: '30%', - render: CommonTableCell, + render: CommonTableCell(), }, { title: '版本数据', dataIndex: 'version_count', key: 'version_count', width: 100, - render: CommonTableCell, + render: CommonTableCell(), }, { title: '镜像描述', dataIndex: 'description', key: 'description', - render: CommonTableCell, - ellipsis: true, + render: CommonTableCell(true), + ellipsis: { showTitle: false }, }, { title: '创建时间', diff --git a/react-ui/src/pages/User/Login/index.tsx b/react-ui/src/pages/User/Login/index.tsx index 6e043763..0dd3a282 100644 --- a/react-ui/src/pages/User/Login/index.tsx +++ b/react-ui/src/pages/User/Login/index.tsx @@ -289,216 +289,217 @@ const Login: React.FC = () => { > 账号登录
- , - // , - // ]} - onFinish={async (values) => { - await handleSubmit(values as API.LoginParams); - }} - > - {code !== 200 && loginType === 'account' && ( - - )} - {type === 'account' && ( - <> - , - }} - placeholder={intl.formatMessage({ - id: 'pages.login.username.placeholder', - defaultMessage: '用户名: admin', - })} - rules={[ - { - required: true, - message: ( - - ), - }, - ]} - /> - , - }} - placeholder={intl.formatMessage({ - id: 'pages.login.password.placeholder', - defaultMessage: '密码: admin123', +
+ , + // , + // ]} + onFinish={async (values) => { + await handleSubmit(values as API.LoginParams); + }} + > + {code !== 200 && loginType === 'account' && ( + - ), - }, - ]} /> - - - - ), - }, - ]} - /> - - - 验证码 getCaptchaCode()} - /> - - - - )} + )} + {type === 'account' && ( + <> + , + }} + placeholder={intl.formatMessage({ + id: 'pages.login.username.placeholder', + defaultMessage: '用户名: admin', + })} + rules={[ + { + required: true, + message: ( + + ), + }, + ]} + /> + , + }} + placeholder={intl.formatMessage({ + id: 'pages.login.password.placeholder', + defaultMessage: '密码: admin123', + })} + rules={[ + { + required: true, + message: ( + + ), + }, + ]} + /> + + + + ), + }, + ]} + /> + + + 验证码 getCaptchaCode()} + /> + + + + )} - {code !== 200 && loginType === 'mobile' && } - {type === 'mobile' && ( - <> - , - }} - name="mobile" - placeholder={intl.formatMessage({ - id: 'pages.login.phoneNumber.placeholder', - defaultMessage: '手机号', - })} - rules={[ - { - required: true, - message: ( - - ), - }, - { - pattern: /^1\d{10}$/, - message: ( - - ), - }, - ]} - /> - , - }} - captchaProps={{ - size: 'large', - }} - placeholder={intl.formatMessage({ - id: 'pages.login.captcha.placeholder', - defaultMessage: '请输入验证码', - })} - captchaTextRender={(timing, count) => { - if (timing) { - return `${count} ${intl.formatMessage({ - id: 'pages.getCaptchaSecondText', + {code !== 200 && loginType === 'mobile' && } + {type === 'mobile' && ( + <> + , + }} + name="mobile" + placeholder={intl.formatMessage({ + id: 'pages.login.phoneNumber.placeholder', + defaultMessage: '手机号', + })} + rules={[ + { + required: true, + message: ( + + ), + }, + { + pattern: /^1\d{10}$/, + message: ( + + ), + }, + ]} + /> + , + }} + captchaProps={{ + size: 'large', + }} + placeholder={intl.formatMessage({ + id: 'pages.login.captcha.placeholder', + defaultMessage: '请输入验证码', + })} + captchaTextRender={(timing, count) => { + if (timing) { + return `${count} ${intl.formatMessage({ + id: 'pages.getCaptchaSecondText', + defaultMessage: '获取验证码', + })}`; + } + return intl.formatMessage({ + id: 'pages.login.phoneLogin.getVerificationCode', defaultMessage: '获取验证码', - })}`; - } - return intl.formatMessage({ - id: 'pages.login.phoneLogin.getVerificationCode', - defaultMessage: '获取验证码', - }); - }} - name="captcha" - rules={[ - { - required: true, - message: ( - - ), - }, - ]} - onGetCaptcha={async (phone) => { - const result = await getFakeCaptcha({ - phone, - }); - if (!result) { - return; - } - message.success('获取验证码成功!验证码为:1234'); - }} - /> - - )} -
- - - -
-
+ }); + }} + name="captcha" + rules={[ + { + required: true, + message: ( + + ), + }, + ]} + onGetCaptcha={async (phone) => { + const result = await getFakeCaptcha({ + phone, + }); + if (!result) { + return; + } + message.success('获取验证码成功!验证码为:1234'); + }} + /> + + )} +
+ + + +
+ +
{/* diff --git a/react-ui/src/pages/User/Login/login.less b/react-ui/src/pages/User/Login/login.less index cf66dc93..88fa4035 100644 --- a/react-ui/src/pages/User/Login/login.less +++ b/react-ui/src/pages/User/Login/login.less @@ -1,28 +1,31 @@ .loginForm { - width: 520px; -} -:global .ant-pro-form-login-main { - margin: unset; -} -:global .ant-input-affix-wrapper-lg { - padding: 19px 11px; - color: rgba(29, 29, 32, 0.6); - font-size: 18px; - font-family: 'Alibaba'; - border-radius: 13px; -} -:global .ant-input-affix-wrapper { - padding: 19px 11px; - color: rgba(29, 29, 32, 0.6); - font-size: 18px; - font-family: 'Alibaba'; - border-radius: 13px; -} -:global .ant-btn.ant-btn-lg { - height: 76px; - color: #ffffff; - font-size: 20px; - font-family: 'Alibaba'; - background: #1664ff; - border-radius: 41px; + :global { + .ant-pro-form-login-main { + width: auto !important; + max-width: auto !important; + margin: unset; + } + .ant-input-affix-wrapper-lg { + padding: 19px 11px; + color: rgba(29, 29, 32, 0.6); + font-size: 18px; + font-family: 'Alibaba'; + border-radius: 13px; + } + .ant-input-affix-wrapper { + padding: 19px 11px; + color: rgba(29, 29, 32, 0.6); + font-size: 18px; + font-family: 'Alibaba'; + border-radius: 13px; + } + .ant-btn.ant-btn-lg { + height: 76px; + color: #ffffff; + font-size: 20px; + font-family: 'Alibaba'; + background: @primary-color; + border-radius: 41px; + } + } } diff --git a/react-ui/src/requestConfig.ts b/react-ui/src/requestConfig.ts index fe9cd44d..3c067e88 100644 --- a/react-ui/src/requestConfig.ts +++ b/react-ui/src/requestConfig.ts @@ -32,7 +32,6 @@ export const requestConfig: RequestConfig = { responseInterceptors: [ (response: any) => { const { status, data } = response || {}; - console.log('response2', response); if (status >= 200 && status < 300) { if (data && (data instanceof Blob || data.code === 200)) { return response; diff --git a/react-ui/src/utils/ui.tsx b/react-ui/src/utils/ui.tsx index b1c456e3..9a1ff626 100644 --- a/react-ui/src/utils/ui.tsx +++ b/react-ui/src/utils/ui.tsx @@ -53,8 +53,10 @@ export const gotoLoginPage = (toHome: boolean = true) => { const { pathname, search } = window.location; const urlParams = new URLSearchParams(); urlParams.append('redirect', pathname + search); - const newSearch = toHome && pathname && pathname !== PageEnum.LOGIN ? '' : urlParams.toString(); - console.log('gotoLoginPage', pathname, search); + const newSearch = + toHome && pathname !== PageEnum.LOGIN && pathname !== '/' ? '' : urlParams.toString(); + console.log('pathname', pathname); + console.log('search', search); if (window.location.pathname !== PageEnum.LOGIN) { history.replace({ pathname: PageEnum.LOGIN, From 4805b850ac490530b661b8448ac6917ce73fd799 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Mon, 13 May 2024 15:19:29 +0800 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20=E5=B7=A5=E4=BD=9C=E7=A9=BA?= =?UTF-8?q?=E9=97=B4=E9=80=82=E9=85=8D=E5=A4=A7=E5=B1=8F=E5=B9=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/QuickStart/index.less | 7 +- .../Workspace/components/QuickStart/index.tsx | 78 ++++++++++++------- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/react-ui/src/pages/Workspace/components/QuickStart/index.less b/react-ui/src/pages/Workspace/components/QuickStart/index.less index f5eb76f4..93ce8d54 100644 --- a/react-ui/src/pages/Workspace/components/QuickStart/index.less +++ b/react-ui/src/pages/Workspace/components/QuickStart/index.less @@ -25,14 +25,13 @@ &__canvas { position: relative; - width: 1223px; + // width: 1223px; + width: 100%; height: 610px; transform-origin: center left; &__model { position: absolute; - top: 358px; - left: 920px; display: flex; flex-direction: column; align-items: center; @@ -42,8 +41,6 @@ &__task { position: absolute; - top: 110px; - left: 603px; display: flex; align-items: center; justify-content: center; diff --git a/react-ui/src/pages/Workspace/components/QuickStart/index.tsx b/react-ui/src/pages/Workspace/components/QuickStart/index.tsx index d1995244..7e1bccf5 100644 --- a/react-ui/src/pages/Workspace/components/QuickStart/index.tsx +++ b/react-ui/src/pages/Workspace/components/QuickStart/index.tsx @@ -9,22 +9,36 @@ import styles from './index.less'; function QuickStart() { const navgite = useNavigate(); const [scale, setScale] = useState(1); + const [space, setSpace] = useState(36); useEffect(() => { const changeScale = () => { - const width = document.body.offsetWidth - 256 - 80 - 60 - 326 - 15 - 8; - const ratio = width >= 1223 ? 1 : width / 1223; - setScale(ratio); + // body 的宽度 - 菜单的宽度 - 两个 padding - 右边用户管理的宽度 - 右边用户管理的 marginLeft, + const width = document.body.offsetWidth - 256 - 80 - 60 - 326 - 15; + if (width >= 1223) { + const spaceX = (width - 192 * 5 - 60) / 7; + setSpace(spaceX); + setScale(1.0); + } else { + const ratio = width / 1223; + setScale(ratio); + } }; const debounceFunc = debounce(changeScale, 16); window.addEventListener('resize', debounceFunc); - + changeScale(); return () => { window.removeEventListener('resize', debounceFunc); }; }, []); + const arrowWidth = space - 12; + const left = space; + const taskWholeWidth = 192 - 56 + 90 + space - 143; + const taskLeftArrowWidth = taskWholeWidth * (56 / (56 + 49)); + const taskRightArrowWidth = taskWholeWidth * (49 / (56 + 49)); + return (
快速开始
@@ -37,7 +51,7 @@ function QuickStart() { content="为开发者提供数据智能标注与数据回流服务" buttonText="数据准备" buttonTop={40} - x={20} + x={left} y={309} onClick={() => navgite('/datasetPreparation/datasetAnnotation')} /> @@ -45,7 +59,7 @@ function QuickStart() { content="为开发者提供定制化编辑器,开发者可根据自己需求选择配置,保存编译器中的调试环境为镜像供训练使用" buttonText="开发环境" buttonTop={20} - x={248} + x={left + 192 + space} y={301} onClick={() => navgite('/developmentEnvironment')} /> @@ -54,7 +68,7 @@ function QuickStart() { tips="可视化建模Designer" buttonText="流水线" buttonTop={20} - x={476} + x={left + 2 * (192 + space)} y={276} onClick={() => navgite('/pipeline/pipelineText')} /> @@ -62,7 +76,7 @@ function QuickStart() { content="开发者可以在这里运行流水线模板,产生实验实例,对比实验训练过程与产生的实验训练数据" buttonText="实验" buttonTop={40} - x={699} + x={left + 3 * (192 + space)} y={295} onClick={() => navgite('/pipeline/experimentText')} /> @@ -71,70 +85,76 @@ function QuickStart() { tips="模型在线服务" buttonText="模型在线部署" buttonTop={20} - x={1010} + x={left + 4 * (192 + space) + 60 + space} y={263} onClick={() => navgite('/modelDseployment')} /> -
+
模型管理
-
+
任务自动调度
Date: Mon, 13 May 2024 15:48:23 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=E5=B7=A5=E4=BD=9C=E7=A9=BA?= =?UTF-8?q?=E9=97=B4=E9=80=82=E9=85=8D=E5=A4=A7=E5=B1=8F=E5=B9=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/Workspace/components/QuickStart/index.less | 3 +-- .../pages/Workspace/components/QuickStart/index.tsx | 12 ++++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/react-ui/src/pages/Workspace/components/QuickStart/index.less b/react-ui/src/pages/Workspace/components/QuickStart/index.less index 93ce8d54..4fba7728 100644 --- a/react-ui/src/pages/Workspace/components/QuickStart/index.less +++ b/react-ui/src/pages/Workspace/components/QuickStart/index.less @@ -25,8 +25,6 @@ &__canvas { position: relative; - // width: 1223px; - width: 100%; height: 610px; transform-origin: center left; @@ -35,6 +33,7 @@ display: flex; flex-direction: column; align-items: center; + width: 60px; color: @primary-color; font-size: @font-size; } diff --git a/react-ui/src/pages/Workspace/components/QuickStart/index.tsx b/react-ui/src/pages/Workspace/components/QuickStart/index.tsx index 7e1bccf5..d7078a6c 100644 --- a/react-ui/src/pages/Workspace/components/QuickStart/index.tsx +++ b/react-ui/src/pages/Workspace/components/QuickStart/index.tsx @@ -9,18 +9,22 @@ import styles from './index.less'; function QuickStart() { const navgite = useNavigate(); const [scale, setScale] = useState(1); - const [space, setSpace] = useState(36); + const [space, setSpace] = useState(29); + const [canvasWidth, setCanvasWidth] = useState('100%'); useEffect(() => { const changeScale = () => { - // body 的宽度 - 菜单的宽度 - 两个 padding - 右边用户管理的宽度 - 右边用户管理的 marginLeft, - const width = document.body.offsetWidth - 256 - 80 - 60 - 326 - 15; + // body 的宽度 - 菜单的宽度 - 两个 padding - 右边用户管理的宽度 - 右边用户管理的 marginLeft - 滚动条的宽度, + const width = document.body.offsetWidth - 256 - 80 - 60 - 326 - 15 - 8; if (width >= 1223) { const spaceX = (width - 192 * 5 - 60) / 7; setSpace(spaceX); + setCanvasWidth('100%'); setScale(1.0); } else { const ratio = width / 1223; + setCanvasWidth('1223px'); + setSpace(29); setScale(ratio); } }; @@ -45,7 +49,7 @@ function QuickStart() {
Date: Tue, 14 May 2024 08:55:09 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E9=83=A8=E7=BD=B2UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/config/routes.ts | 19 +- .../components/MirrorStatusCell/index.less | 11 + .../components/MirrorStatusCell/index.tsx | 39 +++ .../src/pages/ModelDeployment/create.less | 17 + react-ui/src/pages/ModelDeployment/create.tsx | 297 ++++++++++++++++++ react-ui/src/pages/ModelDeployment/info.less | 53 ++++ react-ui/src/pages/ModelDeployment/info.tsx | 149 +++++++++ react-ui/src/pages/ModelDeployment/list.less | 21 ++ react-ui/src/pages/ModelDeployment/list.tsx | 283 +++++++++++++++++ .../components/QuickStart/index.less | 2 +- .../Workspace/components/QuickStart/index.tsx | 3 +- react-ui/src/utils/modal.tsx | 10 +- 12 files changed, 895 insertions(+), 9 deletions(-) create mode 100644 react-ui/src/pages/ModelDeployment/components/MirrorStatusCell/index.less create mode 100644 react-ui/src/pages/ModelDeployment/components/MirrorStatusCell/index.tsx create mode 100644 react-ui/src/pages/ModelDeployment/create.less create mode 100644 react-ui/src/pages/ModelDeployment/create.tsx create mode 100644 react-ui/src/pages/ModelDeployment/info.less create mode 100644 react-ui/src/pages/ModelDeployment/info.tsx create mode 100644 react-ui/src/pages/ModelDeployment/list.less create mode 100644 react-ui/src/pages/ModelDeployment/list.tsx diff --git a/react-ui/config/routes.ts b/react-ui/config/routes.ts index 855ad15c..0e502c59 100644 --- a/react-ui/config/routes.ts +++ b/react-ui/config/routes.ts @@ -188,14 +188,23 @@ export default [ ], }, { - name: 'modelDseployment', - path: '/modelDseployment', + name: 'modelDeployment', + path: '/modelDeployment', routes: [ { - name: '模型部署', + name: '模型列表', path: '', - key: 'modelDseployment', - component: './missingPage.jsx', + component: './ModelDeployment/list', + }, + { + name: '镜像详情', + path: ':id', + component: './ModelDeployment/info', + }, + { + name: '创建镜像', + path: 'create', + component: './ModelDeployment/create', }, ], }, diff --git a/react-ui/src/pages/ModelDeployment/components/MirrorStatusCell/index.less b/react-ui/src/pages/ModelDeployment/components/MirrorStatusCell/index.less new file mode 100644 index 00000000..043bf411 --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/components/MirrorStatusCell/index.less @@ -0,0 +1,11 @@ +.mirror-status-cell { + color: @text-color; + + &--success { + color: @success-color; + } + + &--error { + color: @error-color; + } +} diff --git a/react-ui/src/pages/ModelDeployment/components/MirrorStatusCell/index.tsx b/react-ui/src/pages/ModelDeployment/components/MirrorStatusCell/index.tsx new file mode 100644 index 00000000..3702825f --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/components/MirrorStatusCell/index.tsx @@ -0,0 +1,39 @@ +/* + * @Author: 赵伟 + * @Date: 2024-04-18 18:35:41 + * @Description: + */ +import { MirrorVersionStatus } from '@/enums'; +import styles from './index.less'; + +type MirrorVersionStatusKeys = keyof typeof MirrorVersionStatus; +type MirrorVersionStatusValues = (typeof MirrorVersionStatus)[MirrorVersionStatusKeys]; + +export type MirrorVersionStatusInfo = { + text: string; + classname: string; +}; + +const statusInfo: Record = { + [MirrorVersionStatus.Building]: { + text: '构建中', + classname: styles['mirror-status-cell'], + }, + [MirrorVersionStatus.Available]: { + classname: styles['mirror-status-cell--success'], + text: '可用', + }, + [MirrorVersionStatus.Failed]: { + classname: styles['mirror-status-cell--error'], + text: '构建失败', + }, +}; + +function MirrorStatusCell(status: MirrorVersionStatus) { + if (status === null || status === undefined || !statusInfo[status]) { + return --; + } + return {statusInfo[status].text}; +} + +export default MirrorStatusCell; diff --git a/react-ui/src/pages/ModelDeployment/create.less b/react-ui/src/pages/ModelDeployment/create.less new file mode 100644 index 00000000..63c00764 --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/create.less @@ -0,0 +1,17 @@ +.model-deployment-create { + height: 100%; + + &__content { + height: calc(100% - 60px); + margin-top: 10px; + padding: 30px 30px 10px; + overflow: auto; + background-color: white; + border-radius: 10px; + + &__type { + color: @text-color; + font-size: @font-size-input-lg; + } + } +} diff --git a/react-ui/src/pages/ModelDeployment/create.tsx b/react-ui/src/pages/ModelDeployment/create.tsx new file mode 100644 index 00000000..cc2c43ff --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/create.tsx @@ -0,0 +1,297 @@ +/* + * @Author: 赵伟 + * @Date: 2024-04-16 13:58:08 + * @Description: 创建模型部署 + */ +import PageTitle from '@/components/PageTitle'; +import SubAreaTitle from '@/components/SubAreaTitle'; +import { CommonTabKeys } from '@/enums'; +import { createMirrorReq } from '@/services/mirror'; +import { getComputingResourceReq } from '@/services/pipeline'; +import { to } from '@/utils/promise'; +import { getSessionItemThenRemove, mirrorNameKey } from '@/utils/sessionStorage'; +import { validateUploadFiles } from '@/utils/ui'; +import { useNavigate } from '@umijs/max'; +import { Button, Col, Form, Input, Row, Select, UploadFile, message, type SelectProps } from 'antd'; +import { omit } from 'lodash'; +import { useEffect, useState } from 'react'; +import styles from './create.less'; + +type FormData = { + name: string; + tag: string; + description: string; + path?: string; + upload_type: string; + fileList?: UploadFile[]; +}; + +function ModelDeploymentCreate() { + const navgite = useNavigate(); + const [form] = Form.useForm(); + const [nameDisabled, setNameDisabled] = useState(false); + const [resourceStandardList, setResourceStandardList] = useState([]); + + useEffect(() => { + const name = getSessionItemThenRemove(mirrorNameKey); + if (name) { + form.setFieldValue('name', name); + setNameDisabled(true); + } + getComputingResource(); + }, []); + + const getComputingResource = async () => { + const params = { + page: 0, + size: 1000, + resource_type: '', + }; + const [res] = await to(getComputingResourceReq(params)); + if (res && res.data && res.data.content) { + setResourceStandardList(res.data.content); + } + }; + + const filterResourceStandard: SelectProps['filterOption'] = ( + input: string, + { computing_resource = '' }, + ) => { + return computing_resource.toLocaleLowerCase().includes(input.toLocaleLowerCase()); + }; + + // 创建公网、本地镜像 + const createPublicMirror = async (formData: FormData) => { + const upload_type = formData['upload_type']; + let params; + if (upload_type === CommonTabKeys.Public) { + params = { + ...omit(formData, ['upload_type']), + upload_type: 0, + image_type: 0, + }; + } else { + const fileList = formData['fileList'] ?? []; + if (validateUploadFiles(fileList)) { + const file = fileList[0]; + params = { + ...omit(formData, ['fileList', 'upload_type']), + path: file.response.data.url, + file_size: file.response.data.fileSize, + upload_type: 1, + image_type: 0, + }; + } + } + + const [res] = await to(createMirrorReq(params)); + if (res) { + message.success('创建成功'); + navgite(-1); + } + }; + + // 提交 + const handleSubmit = (values: FormData) => { + createPublicMirror(values); + }; + + // 取消 + const cancel = () => { + navgite(-1); + }; + + return ( +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ ); +} + +export default ModelDeploymentCreate; diff --git a/react-ui/src/pages/ModelDeployment/info.less b/react-ui/src/pages/ModelDeployment/info.less new file mode 100644 index 00000000..c77a7070 --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/info.less @@ -0,0 +1,53 @@ +.model-deployment-info { + height: 100%; + + &__basic { + &__item { + display: flex; + align-items: flex-start; + font-size: 16px; + line-height: 1.6; + + .label { + width: 80px; + color: @text-color-secondary; + } + + .value { + flex: 1; + color: @text-color; + } + } + } + + &__content { + height: calc(100% - 60px); + margin-top: 10px; + padding: 30px 30px 0; + background-color: white; + border-radius: 10px; + + &__title { + display: flex; + align-items: center; + } + + &__table { + :global { + .ant-table-wrapper { + height: 100%; + .ant-spin-nested-loading { + height: 100%; + } + .ant-spin-container { + height: 100%; + } + .ant-table { + height: calc(100% - 74px); + overflow: auto; + } + } + } + } + } +} diff --git a/react-ui/src/pages/ModelDeployment/info.tsx b/react-ui/src/pages/ModelDeployment/info.tsx new file mode 100644 index 00000000..3bc67279 --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/info.tsx @@ -0,0 +1,149 @@ +/* + * @Author: 赵伟 + * @Date: 2024-04-16 13:58:08 + * @Description: 镜像详情 + */ +import KFIcon from '@/components/KFIcon'; +import PageTitle from '@/components/PageTitle'; +import SubAreaTitle from '@/components/SubAreaTitle'; +import { getMirrorInfoReq } from '@/services/mirror'; +import { to } from '@/utils/promise'; +import { useNavigate, useParams } from '@umijs/max'; +import { Col, Row, Tabs, type TabsProps } from 'antd'; +import dayjs from 'dayjs'; +import { useEffect, useState } from 'react'; +import styles from './info.less'; + +type MirrorInfoData = { + name?: string; + description?: string; + version_count?: string; + create_time?: string; +}; + +type MirrorVersionData = { + id: number; + version: string; + url: string; + status: string; + file_size: string; + create_time: string; +}; + +const tabItems = [ + { + key: '1', + label: '预测', + icon: , + }, + { + key: '2', + label: '调用指南', + icon: , + }, + { + key: '3', + label: '服务日志', + icon: , + }, +]; + +function ModelDeploymentInfo() { + const navigate = useNavigate(); + const urlParams = useParams(); + + const [mirrorInfo, setMirrorInfo] = useState({}); + + const [activeTab, setActiveTab] = useState('1'); + useEffect(() => { + getMirrorInfo(); + }, []); + + // 获取镜像详情 + const getMirrorInfo = async () => { + const id = Number(urlParams.id); + const [res] = await to(getMirrorInfoReq(id)); + if (res && res.data) { + const { name = '', description = '', version_count = '', create_time: time } = res.data; + let create_time = + time && dayjs(time).isValid() ? dayjs(time).format('YYYY-MM-DD HH:mm:ss') : '--'; + setMirrorInfo({ + name, + description, + version_count, + create_time, + }); + } + }; + + // 切换 Tab,重置数据 + const hanleTabChange: TabsProps['onChange'] = (value) => { + setActiveTab(value); + }; + + return ( +
+ +
+
+ +
+ + +
+
服务名称:
+
{mirrorInfo.name}
+
+ + +
+
镜像:
+
{mirrorInfo.version_count ?? '--'}
+
+ +
+ + +
+
状态:
+
{mirrorInfo.name}
+
+ + +
+
模型:
+
{mirrorInfo.version_count ?? '--'}
+
+ +
+ + +
+
环境变量:
+
{mirrorInfo.name}
+
+ +
+ + +
+
描述:
+
{mirrorInfo.description}
+
+ +
+
+
+ +
+
+
+
+ ); +} + +export default ModelDeploymentInfo; diff --git a/react-ui/src/pages/ModelDeployment/list.less b/react-ui/src/pages/ModelDeployment/list.less new file mode 100644 index 00000000..9e521f70 --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/list.less @@ -0,0 +1,21 @@ +.model-deployment { + height: 100%; + &__content { + height: calc(100% - 60px); + margin-top: 10px; + padding: 20px 30px 0; + background-color: white; + border-radius: 10px; + + &__filter { + display: flex; + align-items: center; + justify-content: space-between; + } + + &__table { + height: calc(100% - 32px - 28px); + margin-top: 28px; + } + } +} diff --git a/react-ui/src/pages/ModelDeployment/list.tsx b/react-ui/src/pages/ModelDeployment/list.tsx new file mode 100644 index 00000000..bfad5a22 --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/list.tsx @@ -0,0 +1,283 @@ +/* + * @Author: 赵伟 + * @Date: 2024-04-16 13:58:08 + * @Description: 模型部署列表 + */ +import CommonTableCell from '@/components/CommonTableCell'; +import DateTableCell from '@/components/DateTableCell'; +import KFIcon from '@/components/KFIcon'; +import PageTitle from '@/components/PageTitle'; +import { useCacheState } from '@/hooks/pageCacheState'; +import { deleteMirrorReq, getMirrorListReq } from '@/services/mirror'; +import themes from '@/styles/theme.less'; +import { to } from '@/utils/promise'; +import { modalConfirm } from '@/utils/ui'; +import { useNavigate } from '@umijs/max'; +import { + App, + Button, + ConfigProvider, + Input, + Table, + type TablePaginationConfig, + type TableProps, +} from 'antd'; +import { type SearchProps } from 'antd/es/input'; +import classNames from 'classnames'; +import { useEffect, useState } from 'react'; +import styles from './list.less'; + +export type MirrorData = { + id: number; + name: string; + description: string; + create_time: string; +}; + +function ModelDeployment() { + const navigate = useNavigate(); + const { message } = App.useApp(); + const [cacheState, setCacheState] = useCacheState(); + const [searchText, setSearchText] = useState(cacheState?.searchText); + const [inputText, setInputText] = useState(cacheState?.searchText); + const [tableData, setTableData] = useState([]); + const [total, setTotal] = useState(0); + const [pagination, setPagination] = useState>( + cacheState?.pagination ?? { + current: 1, + pageSize: 10, + }, + ); + + useEffect(() => { + getMirrorList(); + }, [pagination, searchText]); + + // 获取镜像列表 + const getMirrorList = async () => { + const params: Record = { + page: pagination.current - 1, + size: pagination.pageSize, + name: searchText, + image_type: 1, + }; + const [res] = await to(getMirrorListReq(params)); + if (res && res.data) { + const { content = [], totalElements = 0 } = res.data; + setTableData(content); + setTotal(totalElements); + } + }; + + // 删除镜像 + const deleteMirror = async (id: number) => { + const [res] = await to(deleteMirrorReq(id)); + if (res) { + message.success('删除成功'); + // 如果是一页的唯一数据,删除时,请求第一页的数据 + // 否则直接刷新这一页的数据 + // 避免回到第一页 + if (tableData.length > 1) { + setPagination((prev) => ({ + ...prev, + current: 1, + })); + } else { + getMirrorList(); + } + } + }; + + // 搜索 + const onSearch: SearchProps['onSearch'] = (value) => { + setSearchText(value); + }; + + // 查看详情 + const toDetail = (record: MirrorData) => { + navigate(`/modelDeployment/${record.id}`); + setCacheState({ + pagination, + searchText, + }); + }; + + // 处理删除 + const handleMirrorDelete = (record: MirrorData) => { + modalConfirm({ + title: '删除后,该镜像将不可恢复', + content: '是否确认删除?', + onOk: () => { + deleteMirror(record.id); + }, + }); + }; + + // 创建镜像 + const createMirror = () => { + navigate(`/modelDeployment/create`); + setCacheState({ + pagination, + searchText, + }); + }; + + // 分页切换 + const handleTableChange: TableProps['onChange'] = (pagination, filters, sorter, { action }) => { + if (action === 'paginate') { + setPagination(pagination); + } + // console.log(pagination, filters, sorter, action); + }; + + const columns: TableProps['columns'] = [ + { + title: '序号', + dataIndex: 'index', + key: 'index', + width: 100, + align: 'center', + render(text, record, index) { + return {(pagination.current - 1) * pagination.pageSize + index + 1}; + }, + }, + { + title: '服务名称', + dataIndex: 'name', + key: 'name', + width: '30%', + render: CommonTableCell(), + }, + { + title: '模型', + dataIndex: 'version_count', + key: 'version_count', + width: '20%', + render: CommonTableCell(), + }, + { + title: '状态', + dataIndex: 'version_count', + key: 'version_count', + width: '10%', + render: CommonTableCell(), + }, + { + title: '创建人', + dataIndex: 'description', + key: 'description', + render: CommonTableCell(true), + width: '20%', + ellipsis: { showTitle: false }, + }, + { + title: '更新时间', + dataIndex: 'create_time', + key: 'create_time', + width: '20%', + render: DateTableCell, + }, + { + title: '操作', + dataIndex: 'operation', + width: 350, + key: 'operation', + render: (_: any, record: MirrorData) => ( +
+ + + + + + +
+ ), + }, + ]; + + return ( +
+ +
+
+ setInputText(e.target.value)} + style={{ width: 300 }} + value={inputText} + /> + +
+
+ + + + + ); +} + +export default ModelDeployment; diff --git a/react-ui/src/pages/Workspace/components/QuickStart/index.less b/react-ui/src/pages/Workspace/components/QuickStart/index.less index 4fba7728..5932d971 100644 --- a/react-ui/src/pages/Workspace/components/QuickStart/index.less +++ b/react-ui/src/pages/Workspace/components/QuickStart/index.less @@ -1,5 +1,5 @@ .quick-start { - width: calc(100% - 326px); + width: calc(100% - 326px - 15px); padding: 20px 30px; background-color: white; border-radius: 4px; diff --git a/react-ui/src/pages/Workspace/components/QuickStart/index.tsx b/react-ui/src/pages/Workspace/components/QuickStart/index.tsx index d7078a6c..c992c84a 100644 --- a/react-ui/src/pages/Workspace/components/QuickStart/index.tsx +++ b/react-ui/src/pages/Workspace/components/QuickStart/index.tsx @@ -29,9 +29,10 @@ function QuickStart() { } }; + changeScale(); + const debounceFunc = debounce(changeScale, 16); window.addEventListener('resize', debounceFunc); - changeScale(); return () => { window.removeEventListener('resize', debounceFunc); }; diff --git a/react-ui/src/utils/modal.tsx b/react-ui/src/utils/modal.tsx index 4a3b765f..577c1ec3 100644 --- a/react-ui/src/utils/modal.tsx +++ b/react-ui/src/utils/modal.tsx @@ -1,10 +1,11 @@ /* * @Author: 赵伟 * @Date: 2024-04-13 10:08:35 - * @Description: + * @Description: 以函数的方式打开 Modal */ import { ConfigProvider, type ModalProps } from 'antd'; import { globalConfig } from 'antd/es/config-provider'; +import zhCN from 'antd/locale/zh_CN'; import React, { useState } from 'react'; import { createRoot } from 'react-dom/client'; @@ -59,7 +60,12 @@ export const openAntdModal = ( ); root.render( - + {global.holderRender ? global.holderRender(dom) : dom} , ); From a695c8dc8c53b82be44e741a5db88242a919caae Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Tue, 14 May 2024 09:33:57 +0800 Subject: [PATCH 7/8] =?UTF-8?q?refactor:=20=E5=90=8C=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E6=97=A5=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/DateTableCell/index.tsx | 3 +- react-ui/src/pages/Dataset/intro.jsx | 4 +- .../pages/Experiment/experimentText/index.jsx | 7 +-- .../pages/Experiment/experimentText/props.jsx | 4 +- react-ui/src/pages/Experiment/index.jsx | 7 +-- react-ui/src/pages/Mirror/info.tsx | 5 +- react-ui/src/pages/Model/intro.jsx | 4 +- react-ui/src/pages/ModelDeployment/info.tsx | 5 +- react-ui/src/pages/Pipeline/index.jsx | 6 +-- react-ui/src/utils/date.ts | 49 ++++++++++++++++--- 10 files changed, 62 insertions(+), 32 deletions(-) diff --git a/react-ui/src/components/DateTableCell/index.tsx b/react-ui/src/components/DateTableCell/index.tsx index 0b4efe93..ea629ba7 100644 --- a/react-ui/src/components/DateTableCell/index.tsx +++ b/react-ui/src/components/DateTableCell/index.tsx @@ -4,6 +4,7 @@ * @Description: 自定义 Table 日期类单元格 */ +import { formatDate } from '@/utils/date'; import dayjs from 'dayjs'; function DateTableCell(text?: string | null) { @@ -13,7 +14,7 @@ function DateTableCell(text?: string | null) { if (!dayjs(text).isValid()) { return 无效的日期; } - return {dayjs(text).format('YYYY-MM-DD HH:mm:ss')}; + return {formatDate(text)}; } export default DateTableCell; diff --git a/react-ui/src/pages/Dataset/intro.jsx b/react-ui/src/pages/Dataset/intro.jsx index 66f08b9c..85539c9a 100644 --- a/react-ui/src/pages/Dataset/intro.jsx +++ b/react-ui/src/pages/Dataset/intro.jsx @@ -6,12 +6,12 @@ import { getDatasetVersionIdList, getDatasetVersionsById, } from '@/services/dataset/index.js'; +import { formatDate } from '@/utils/date'; import { downLoadZip } from '@/utils/downloadfile'; import { openAntdModal } from '@/utils/modal'; import { modalConfirm } from '@/utils/ui'; import { useParams, useSearchParams } from '@umijs/max'; import { Button, Input, Select, Table, Tabs, message } from 'antd'; -import moment from 'moment'; import { useEffect, useRef, useState } from 'react'; import AddVersionModal from './components/AddVersionModal'; import Styles from './intro.less'; @@ -146,7 +146,7 @@ const Dataset = () => { title: '更新时间', dataIndex: 'update_time', key: 'update_time', - render: (text) => {moment(text).format('YYYY-MM-DD HH:mm:ss')}, + render: (text) => {formatDate(text)}, }, { title: '操作', diff --git a/react-ui/src/pages/Experiment/experimentText/index.jsx b/react-ui/src/pages/Experiment/experimentText/index.jsx index cc74eba4..6d70e060 100644 --- a/react-ui/src/pages/Experiment/experimentText/index.jsx +++ b/react-ui/src/pages/Experiment/experimentText/index.jsx @@ -1,11 +1,10 @@ import { useVisible } from '@/hooks'; import { getExperimentIns } from '@/services/experiment/index.js'; import { getWorkflowById } from '@/services/pipeline/index.js'; -import { elapsedTime } from '@/utils/date'; +import { elapsedTime, formatDate } from '@/utils/date'; import { useEmotionCss } from '@ant-design/use-emotion-css'; import G6 from '@antv/g6'; import { Button } from 'antd'; -import momnet from 'moment'; import { useEffect, useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { s8 } from '../../../utils'; @@ -389,9 +388,7 @@ function ExperimentText() {
-
- 启动时间:{momnet(message.create_time).format('YYYY-MM-DD HH:mm:ss')} -
+
启动时间:{formatDate(message.create_time)}
执行时长: {message.finish_time diff --git a/react-ui/src/pages/Experiment/experimentText/props.jsx b/react-ui/src/pages/Experiment/experimentText/props.jsx index 7683c833..98ef4984 100644 --- a/react-ui/src/pages/Experiment/experimentText/props.jsx +++ b/react-ui/src/pages/Experiment/experimentText/props.jsx @@ -1,5 +1,5 @@ import { getNodeResult, getQueryByExperimentLog } from '@/services/experiment/index.js'; -import { elapsedTime } from '@/utils/date'; +import { elapsedTime, formatDate } from '@/utils/date'; import { downLoadZip } from '@/utils/downloadfile'; import { DatabaseOutlined, ProfileOutlined } from '@ant-design/icons'; import { Drawer, Form, Input, Tabs, message } from 'antd'; @@ -419,7 +419,7 @@ const Props = forwardRef(({ onParentChange }, ref) => {
- 启动时间:{moment(stagingItem.experimentStartTime).format('YYYY-MM-DD HH:mm:ss')} + 启动时间:{formatDate(stagingItem.experimentStartTime)}
耗时: diff --git a/react-ui/src/pages/Experiment/index.jsx b/react-ui/src/pages/Experiment/index.jsx index 1c93f834..43db02f9 100644 --- a/react-ui/src/pages/Experiment/index.jsx +++ b/react-ui/src/pages/Experiment/index.jsx @@ -14,12 +14,11 @@ import { } from '@/services/experiment/index.js'; import { getWorkflow } from '@/services/pipeline/index.js'; import themes from '@/styles/theme.less'; -import { elapsedTime } from '@/utils/date'; +import { elapsedTime, formatDate } from '@/utils/date'; import { to } from '@/utils/promise'; import { modalConfirm } from '@/utils/ui'; import { Button, ConfigProvider, Space, Table, message } from 'antd'; import classNames from 'classnames'; -import momnet from 'moment'; import { useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import AddExperimentModal from './components/AddExperimentModal'; @@ -442,9 +441,7 @@ function Experiment() { ? elapsedTime(new Date(item.create_time), new Date(item.finish_time)) : elapsedTime(new Date(item.create_time), new Date())}
-
- {momnet(item.create_time).format('YYYY-MM-DD HH:mm:ss')} -
+
{formatDate(item.create_time)}
{ title: '更新时间', dataIndex: 'update_time', key: 'update_time', - render: (text) => {moment(text).format('YYYY-MM-DD HH:mm:ss')}, + render: (text) => {formatDate(text)}, }, { title: '操作', diff --git a/react-ui/src/pages/ModelDeployment/info.tsx b/react-ui/src/pages/ModelDeployment/info.tsx index 3bc67279..3e4e8a81 100644 --- a/react-ui/src/pages/ModelDeployment/info.tsx +++ b/react-ui/src/pages/ModelDeployment/info.tsx @@ -7,10 +7,10 @@ import KFIcon from '@/components/KFIcon'; import PageTitle from '@/components/PageTitle'; import SubAreaTitle from '@/components/SubAreaTitle'; import { getMirrorInfoReq } from '@/services/mirror'; +import { formatDate } from '@/utils/date'; import { to } from '@/utils/promise'; import { useNavigate, useParams } from '@umijs/max'; import { Col, Row, Tabs, type TabsProps } from 'antd'; -import dayjs from 'dayjs'; import { useEffect, useState } from 'react'; import styles from './info.less'; @@ -65,8 +65,7 @@ function ModelDeploymentInfo() { const [res] = await to(getMirrorInfoReq(id)); if (res && res.data) { const { name = '', description = '', version_count = '', create_time: time } = res.data; - let create_time = - time && dayjs(time).isValid() ? dayjs(time).format('YYYY-MM-DD HH:mm:ss') : '--'; + const create_time = formatDate(time); setMirrorInfo({ name, description, diff --git a/react-ui/src/pages/Pipeline/index.jsx b/react-ui/src/pages/Pipeline/index.jsx index fcbdc03e..ee2ac6ae 100644 --- a/react-ui/src/pages/Pipeline/index.jsx +++ b/react-ui/src/pages/Pipeline/index.jsx @@ -1,3 +1,4 @@ +import DateTableCell from '@/components/DateTableCell'; import KFIcon from '@/components/KFIcon'; import KFModal from '@/components/KFModal'; import { @@ -12,7 +13,6 @@ import themes from '@/styles/theme.less'; import { modalConfirm } from '@/utils/ui'; import { Button, ConfigProvider, Form, Input, Space, Table, message } from 'antd'; import classNames from 'classnames'; -import momnet from 'moment'; import { useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import Styles from './index.less'; @@ -138,13 +138,13 @@ const Pipeline = () => { title: '创建时间', dataIndex: 'create_time', key: 'create_time', - render: (text) => {momnet(text).format('YYYY-MM-DD HH:mm:ss')}, + render: DateTableCell, }, { title: '修改时间', dataIndex: 'update_time', key: 'update_time', - render: (text) => {momnet(text).format('YYYY-MM-DD HH:mm:ss')}, + render: DateTableCell, }, { title: '操作', diff --git a/react-ui/src/utils/date.ts b/react-ui/src/utils/date.ts index eaab9f3f..be015cc6 100644 --- a/react-ui/src/utils/date.ts +++ b/react-ui/src/utils/date.ts @@ -1,4 +1,12 @@ import dayjs from 'dayjs'; + +/** + * Calculates the elapsed time between two dates and returns a formatted string representing the duration. + * + * @param {Date} beginDate - The starting date. + * @param {Date} endDate - The ending date. + * @return {string} The formatted elapsed time string. + */ export const elapsedTime = (beginDate: Date, endDate: Date): string => { if (!isValidDate(beginDate) || !isValidDate(endDate)) { return '--'; @@ -29,7 +37,12 @@ export const elapsedTime = (beginDate: Date, endDate: Date): string => { return `${minutes}分${seconds}秒`; }; -// 是否是有效的日期 +/** + * 是否是有效的日期 + * + * @param {Date} date - The date to check. + * @return {boolean} True if the date is valid, false otherwise. + */ export const isValidDate = (date: Date): boolean => { if (date instanceof Date) { return !Number.isNaN(date.getTime()); // valueOf() 也可以 @@ -37,14 +50,38 @@ export const isValidDate = (date: Date): boolean => { return false; }; -// 格式化日期 -export const formatDate = (text: Date | string, format = 'YYYY-MM-DD HH:mm:ss'): string => { - if (text === undefined || text === null || text === '') { +/** + * 能否使用 dayjs 转换成 Date + * + * @param {Date | string | number | null | undefined} date - The date to be checked. + * @return {boolean} Returns true if the date can be converted to a valid Date object, otherwise returns false. + */ +export const canBeConvertToDate = (date?: Date | string | number | null): boolean => { + if (date === undefined || date === null || date === '') { + return false; + } + const convertedDate = dayjs(date); + return convertedDate.isValid(); +}; + +/** + * 转换日期 + * + * @param {Date | string | number | null | undefined} date - The date to format. + * @param {string} [format='YYYY-MM-DD HH:mm:ss'] - The format string to use. + * @return {string} The formatted date string. + */ +export const formatDate = ( + date?: Date | string | number | null, + format: string = 'YYYY-MM-DD HH:mm:ss', +): string => { + if (date === undefined || date === null || date === '') { return '--'; } - if (!dayjs(text).isValid()) { + const convertedDate = dayjs(date); + if (!convertedDate.isValid()) { return '--'; } - return dayjs(text).format(format); + return convertedDate.format(format); }; From 18216225a41083ed23cd44b939504250bb9a3c20 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Wed, 15 May 2024 11:31:15 +0800 Subject: [PATCH 8/8] =?UTF-8?q?feat:=20=E6=B5=81=E6=B0=B4=E7=BA=BF?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../public/assets/images/compoent-icon-6.png | Bin 1520 -> 0 bytes .../public/assets/images/icon/流水线-1.png | Bin 1606 -> 0 bytes .../assets/images/mindspore模型转换.png | Bin 1907 -> 0 bytes .../public/assets/images/pipelieEditIcon.png | Bin 1112 -> 0 bytes .../assets/images/pipeline-edit-icon.png | Bin 1112 -> 0 bytes .../component-icon-1-Failed.png | Bin .../component-icon-1-Omitted.png | Bin .../component-icon-1-Pending.png | Bin .../component-icon-1-Running.png | Bin .../component-icon-1-Skipped.png | Bin .../component-icon-1-Succeeded.png | Bin .../{ => pipeline}/component-icon-1.png | Bin .../component-icon-2-Failed.png | Bin .../component-icon-2-Omitted.png | Bin .../component-icon-2-Pending.png | Bin .../component-icon-2-Running.png | Bin .../component-icon-2-Skipped.png | Bin .../component-icon-2-Succeeded.png | Bin .../{ => pipeline}/component-icon-2.png | Bin .../component-icon-3-Failed.png | Bin .../component-icon-3-Omitted.png | Bin .../component-icon-3-Pending.png | Bin .../component-icon-3-Running.png | Bin .../component-icon-3-Skipped.png | Bin .../component-icon-3-Succeeded.png | Bin .../{ => pipeline}/component-icon-3.png | Bin .../component-icon-4-Failed.png | Bin .../component-icon-4-Omitted.png | Bin .../component-icon-4-Pending.png | Bin .../component-icon-4-Running.png | Bin .../component-icon-4-Skipped.png | Bin .../component-icon-4-Succeeded.png | Bin .../{ => pipeline}/component-icon-4.png | Bin .../component-icon-5-Failed.png | Bin .../component-icon-5-Omitted.png | Bin .../component-icon-5-Pending.png | Bin .../component-icon-5-Running.png | Bin .../component-icon-5-Skipped.png | Bin .../component-icon-5-Succeeded.png | Bin .../{ => pipeline}/component-icon-5.png | Bin .../component-icon-6-Failed.png | Bin .../component-icon-6-Omitted.png | Bin .../component-icon-6-Pending.png | Bin .../component-icon-6-Running.png | Bin .../component-icon-6-Skipped.png | Bin .../component-icon-6-Succeeded.png | Bin .../{ => pipeline}/component-icon-6.png | Bin .../component-icon-7-Failed.png | Bin .../component-icon-7-Omitted.png | Bin .../component-icon-7-Pending.png | Bin .../component-icon-7-Running.png | Bin .../component-icon-7-Skipped.png | Bin .../component-icon-7-Succeeded.png | Bin .../{ => pipeline}/component-icon-7.png | Bin .../component-icon-8-Failed.png | Bin .../component-icon-8-Omitted.png | Bin .../component-icon-8-Pending.png | Bin .../component-icon-8-Running.png | Bin .../component-icon-8-Skipped.png | Bin .../component-icon-8-Succeeded.png | Bin .../{ => pipeline}/component-icon-8.png | Bin .../public/assets/images/pytorch推理.png | Bin 2293 -> 0 bytes .../public/assets/images/pytorch训练.png | Bin 4776 -> 0 bytes react-ui/public/assets/images/sjj-icon-1.png | Bin 1103 -> 0 bytes .../assets/images/tensorflow模型转换.png | Bin 4004 -> 0 bytes .../public/assets/images/发送通知.png | Bin 1199 -> 0 bytes react-ui/src/assets/img/model-deployment.zip | Bin 0 -> 1735 bytes .../components/GlobalParamsDrawer/index.tsx | 5 +- .../Pipeline/components/PropsLabel/index.less | 6 + .../Pipeline/components/PropsLabel/index.tsx | 44 +++ .../Pipeline/editPipeline/editPipeline.less | 11 + .../src/pages/Pipeline/editPipeline/index.jsx | 53 +-- .../Pipeline/editPipeline/modelMenus.jsx | 21 +- .../src/pages/Pipeline/editPipeline/props.jsx | 337 +++++++++++------- .../src/pages/Pipeline/editPipeline/utils.tsx | 79 ++++ react-ui/src/pages/User/Login/index.tsx | 268 +------------- react-ui/src/utils/formRules.ts | 0 react-ui/src/utils/index.ts | 2 +- react-ui/src/utils/menuRender.tsx | 6 + 79 files changed, 391 insertions(+), 441 deletions(-) delete mode 100644 react-ui/public/assets/images/compoent-icon-6.png delete mode 100644 react-ui/public/assets/images/icon/流水线-1.png delete mode 100644 react-ui/public/assets/images/mindspore模型转换.png delete mode 100644 react-ui/public/assets/images/pipelieEditIcon.png delete mode 100644 react-ui/public/assets/images/pipeline-edit-icon.png rename react-ui/public/assets/images/{ => pipeline}/component-icon-1-Failed.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-1-Omitted.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-1-Pending.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-1-Running.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-1-Skipped.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-1-Succeeded.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-1.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-2-Failed.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-2-Omitted.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-2-Pending.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-2-Running.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-2-Skipped.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-2-Succeeded.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-2.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-3-Failed.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-3-Omitted.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-3-Pending.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-3-Running.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-3-Skipped.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-3-Succeeded.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-3.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-4-Failed.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-4-Omitted.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-4-Pending.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-4-Running.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-4-Skipped.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-4-Succeeded.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-4.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-5-Failed.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-5-Omitted.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-5-Pending.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-5-Running.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-5-Skipped.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-5-Succeeded.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-5.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-6-Failed.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-6-Omitted.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-6-Pending.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-6-Running.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-6-Skipped.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-6-Succeeded.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-6.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-7-Failed.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-7-Omitted.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-7-Pending.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-7-Running.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-7-Skipped.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-7-Succeeded.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-7.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-8-Failed.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-8-Omitted.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-8-Pending.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-8-Running.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-8-Skipped.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-8-Succeeded.png (100%) rename react-ui/public/assets/images/{ => pipeline}/component-icon-8.png (100%) delete mode 100644 react-ui/public/assets/images/pytorch推理.png delete mode 100644 react-ui/public/assets/images/pytorch训练.png delete mode 100644 react-ui/public/assets/images/sjj-icon-1.png delete mode 100644 react-ui/public/assets/images/tensorflow模型转换.png delete mode 100644 react-ui/public/assets/images/发送通知.png create mode 100644 react-ui/src/assets/img/model-deployment.zip create mode 100644 react-ui/src/pages/Pipeline/components/PropsLabel/index.less create mode 100644 react-ui/src/pages/Pipeline/components/PropsLabel/index.tsx create mode 100644 react-ui/src/pages/Pipeline/editPipeline/utils.tsx create mode 100644 react-ui/src/utils/formRules.ts diff --git a/react-ui/public/assets/images/compoent-icon-6.png b/react-ui/public/assets/images/compoent-icon-6.png deleted file mode 100644 index 47e7fa9bcb1e464c6bc04743a88cd1c77e0daa4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1520 zcmV!llBz!gE`|-g?Y>SOnNrMvk(iju?B2^RLRSAuPG0=v-wymONyLCU>e zyE{W?+kNCr(rmVO?wxaf_kYg4GnuoB`jtT|=5*GB7aFiMHUrcEl(Z(DlG3^vYUNMRxH(xl9HW1be}?e?34AUuBuN=e zV=s z?>79jAO2ZN()lPFqsKAvuebtaw(=pIxWx`H9j6%Jri+xbjYDM!v#BoCp9)&&L9QM4 z(*U)r$vN#!TppaFnvoCHiCh4$ZspY_M91OZN*fS9yAfuMt^fsE_@GZwqXrbu_I>EQ z-tN472iN&asS~kV9aHr7NSoT9Jh0iq&moE5hrWMZn55e#y47f+{cc`nnsgkKR*wH2 z8*Wn%#s2+ zKRDY0NQd?JU^DMT-?xwmH2{jm=-c6Tx&g}`awHK9`wHzh#tl1cwX3R&2JSmXkC4r(U$J2Y@hEzCGb~ z)oB9=H1Qn(*a^TUlK-!fe`(`*ml`W7KygT0c$%t5|EBj6aBMFdcu8OxZ3lpJV+Yic z+0J9R-DD80icHa=T)@%xELeyw_DnC-^#qUu*=z$EL{9m9p=L8D<1*cjTzHwiSj>AB zvyD%BT96ZevVKuGl(Z4ntMUAn`K%k3hXd;Eh5*ViF`fZoxgJLjisa$s&)+1b670pS z$Hv(JG#KTX+k;{`aIg6_09~FPKul+GvwB6bz{%=HF-}+jC95O(Ze9STh#LX)Ka`Y@ zTm_H-%HG|)-( zYeY?jb>QWxK9mb2idnpwmLI)?t^5;SqN=l=xzG6c5sF#1&9*M(%L^&Wq0XWnV`KP$ zI-MWxd9$LriEB!H^o5slsJ)>3V&XMf6x5-r=c$nn^}09H@}qa4mG}6_D!8ez6r|sB zWqJ%%N3Xh4P}MHpP#U8T@DATPy937fEjCTBMSb*XxJ~_$AFf`S6k*G?awgG={hw1+c)SnU~wMVXwAZ7a~{N%CYkg)YFYx zu{qU-x;=ey_iipT&(kRkHn%K1x4vfe>X`JwAwOM3@2HfoIlK8`fz!aaqR`6ZohVwR z6&lVYt)AZx3)okfQBoHMtOKN(GVwyCW&gMU(@88kKaTimdphOV?z?ss3GO<-kLuCk z7Q`$g^eUZZDWBS5^8{?xWs$wHC>_O?<$E{wxd!BBuwpz%06EO601`mn0$&v5!0$hX W@*{Xrt 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 diff --git a/react-ui/public/assets/images/pipelieEditIcon.png b/react-ui/public/assets/images/pipelieEditIcon.png deleted file mode 100644 index 936bf97cf113a0dc0e4a3cdad0c7d8c820fbc609..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1112 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 diff --git a/react-ui/public/assets/images/pytorch训练.png b/react-ui/public/assets/images/pytorch训练.png deleted file mode 100644 index 81677987d445014e46abe265c4ba0ab56c84efed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4776 zcmV;Z5?AesP)ftdk(B?x8{anw{>N!va5o>Nulf2!(K)j1bS4)Ik{XXaa$T!|RPd>4ojF_!f3-Nny^ ztxK){I+P+>hl+Vst+~L2gZc8rNwZwYhP{?}F0V=CD#}pOG z!wmK~n1=x;?FC2?iOTDd5}DAp$l8{+LmnGsAYT5sRn(i+Fr1*K6vSB7MXw}vvX#mH z^q8nT(%N86%AZudQ#vRB;b(4Q&~sr{6gYTH2{EG#eywe8mYiYZ#P3A$6-54jfY0~w zPxJd5sD1^gs>Xa1BWi+4r4Bf8xXxgEc(%S}sr42AU;*`602&(evOCF^C@Q@{;ByCc& zGpu+~d8K8qd|mFh+VTxl-T^9`Vn!8~$QxD&a|)1_0qOs`qL$3UL>6T-psG4^C7N<8 zpOQeDN+c>>`#NRhhpVg)GNGAio4f)vsM;J?QYafjAsG-f+uZ8`p!+bV>P!Xnx2vo( zE78XD0Sd)RzM>+XExV)wP3p{reo&vh0yLz?TpkX~Ld>Bcz`1Jhw;j#78O>Rd^#CTD zaK&J`4m-P=KytV(IREhv08{Ml>6TO5ms!tdO+Q74J^*AwRdsS6D^F)jll6#8zp~!6 zG0Q_z5k`Z$X#1w=mTOv;Tffg_AQiRd3bgVD+75yCK<(rBu~>Iy7F*pmpq-zK-85E3 zy-c&B($mstt;&Q?-ZW@vt*J%F=Rj}-v$-Gpza1gwIf8{M>*Qqyax8xjOq^wRZ~*&0 z&z`h)%jM1YTYH0qtE@HuiZA;)BR`4nWV4OMO?v@7#OFzz{W+ct_3{X~jdSRBM2&op z_^Bydpt91Sp*7}fA)MdtCx3E@Mw>MbNc$!pajzIp4F}E4qI}*T35`}ZL zU_1S0f${%1(we&lpmwtaXgb}SvtY7=vRMePBp|Gr=?_r*dM%n@T4OY#oTbrzx zG6gClfQV;CAjoYnJk=g-0(F?a#|)mEYPrVjX3*zmK&|9ESrekt3dzTs8?5OSIQmeL zs7V~_nv*w3{lR2FXA{ZC51N~-KLrhRNS*lx8s5m{4EH~G0(F&jUDpAbwReTJGaXQA z0b(X^pwSh4j!F>)x1+vuQQte$F{`RKS0UVGn9HXV8QW=wk)3?)$KM!z)10g-X@(Uj-|A%JW@IDZi!zOyT$)VoIhg4k{9O?^1|$1; z_P2b3^!`5@T?0YXK;LN@su$0XwVIRbCz`%VPDH7y`18eq0x#cc0F@Z$ruDb`O{ zymif8a*^DNJJ0bVZJ7<9%i(i$3M*)dMCI(ZM(epm7D)hM2B*;IK?rI7nZvDOS;(Y+iDyZEl!cOUlIDdXw8c`PGnLyocDT7NbLt8pOmu^WAS7m&ilrE@pSS# z^_QbGUP~C~DC@8xrh+lUqFRe)*4Mt_zsA(akk!y^bd(FG+{Er|Q- zCw_|H8h7RGg8wyWQ#E7t0D;$*{Si5Tw=WDx1nAtb5I;CU8Q=)EIU6VZ@CZeV3^h2FrDU)aR6pF0Q{ab;T#!f3aUoSj(`0SL98i7-Emi^5|$)YE{YL1^r{(iB&HC|l9wVSX@( zx899}<&^ft*4BK0^sxeH$P9BLDgGKJ>+m?o7?n41!p9{Jc;H25_+bO&1wa}Z*WSph zX!J?{U;r7bs$Sl~Y(^z$#Os6%<5PtUL+Z_!0d=)M7D@Y$34Z`oNaQu!p zCI-5h1)w@8IP(vj#Ipvcy#P(BaPQOiea!M&%yMO4K>An!gb-&kh(@$vgl~ZD4Du%O zpt~~}AONod;0yh65`o=o%@*a1rMcIkKL!BVMKyJ{M|$AsY9VrW%M$CdOu%v0mt;Dz zm1aREY1!xZk#W-!{;-eNA4b^cWdTDzF|srZh^vZbf(F}3B$R_y|A zD^XO|A>V1a&;#^o$hX2D2SM{9pSuUf)C$#~kjIEZD>C~K`&Q<_s z=Kje8*Dj-CXJV`)TQxsh#g?kzK2b%5zM>m-9j2Pa_Z@26+bAwng@w z^`QVtCUYs6f8TTTG2tIT_{sSc9*|yx$3MF?F|)r>$p0pV{J&(&2Q!<9hDR~4$J1&M z;M~U6PQ4S-Ki{%LCdqHD{h2aF@c%>bk$%Ck@3V+|He^a8lXjTdEojjV{uLJ|dk32b zS7p*)+u(1@S+!RI&RAW^@VQ#|nw3(6h+9sD;X`}|Ya<7w9o-@mF^@l|V?1<*IX!HM za4ada`|Br48Kc1(pRRAV&(%-jH`c-HD7P>5tJhmL%fHFfme#U+y((+WIQlQ6|0i5C zqW>P^stIV4x1H2$J;>7n_PwZ++>x$GUpd3v1Hq}jrM-(;y_8v9o=)Igo-?5j;jF*q z}p!P5@>+)I58e)W3VU5tEQ zUYHkvbf8JQ4Y4ZVHjaq>ustjdve@bdpm_i^#~(S#jALYLG} z1_e&eZY!~%6e<|X5ausX^*gyg!BN^ymj7#b+NVIA4bHAK$My68!#obM?@!#M$hl}g z_+nF0TqsMBVJzcUCzo_N!rAxv{SF#-Y3m?)mdq*RI4UbZ+2=1OhT#ms;|aSY$!;Mg zlx~?nvp+0X?pbWL1nuJF43H~0rzXae;m_yu8BDJy;42uf-tY4;@zYooB4Y$fA8k+fwU=9 zzXuI1)0Q!~3ht@aDj22QD~US+5}S-9fN1+30KScjxP_wH+QiA|7Y#~eLTd6QmQRhI zV<*9Ug7&5z?ku}~ytYAlm4;@}YNVzFFgNs8Z9FId>A=vYH*~w$H)uU1PKLs{=2SMA zjcxVP)`_yIG$ToDq9kAqHU=59PXWmw4VYaedVc~ z-*%BJSJ1pgzz|wsj*u$k-XHmX2Q!@M?!-ENXC~;b;A0VPY)pLuE!oLEbRwE z(yYsJDq>2jSmZ_ejm|~}aJR1iJ&j`e$(**iN=ZYDh$J@*)rjmThcZ9Arzb`PJUd28{VU-zd+Ow4>vwcX@0 zjRS~t&~?n{V%OO@AnmiaRvN9df+VGgetfthZpTh)KBfkcp;lz~`?TKPuml8K=I^|t~Q3^Y( zGpV2ayqA~QA_(ymamJZWP38^S+OHHE8B}YkQ27_#U0i1}*Pub) zP=eISpWsW&zDdA1fJP2<%gkNNWX`3Bk17^37b$AkOM!Ep; zrTp0Dort7-->4;%Z?MY$h@#KAdoa&}k#%4^eS z2JNIK3Y!r?ZYRo{QxHVWZZP(qY<7-~0ZmNz`$Oaj4bLcg~2bXV(mfx znc2KxmlZ&se~JZ^dJsF6*{N^(PQK4IrvjVMWDN`U89{?_&52cN0e)t7wiA{UKt7H7 z6Zz7~Hc&oFP6U1%G1K+g3Y1HGa;mM^{n2r;Tg+K&RpB}OjJ|)8)72+{lp}{MKTq_n zXLE+ziKWItMh@)llHq~hM`syp5Lok_5n2i1t7WPF%zmkal+wl633AzbCvp8!80Uh!NP>?WAe4=@pcRpI* zl19_s=Cy*WGCjHGly`q-*Or|3NSuVz#C&K!fruhV{-!;fDED`U2 z;Dcrbz18e9z2pegAp$tt`T1kgnE%Nq2))rdr~uj8G}V-bOKkHw4vz9z{hSlvBu-aPg6v>dizm$P7aSz*AN zo11U=Wbe<<&#!DI4xc9Mo|7$nE^T~N8*9KjJ3DJZ5bWa9avY~72f}X~XJ=<_7J#j- zE%Lii{Cxc8;xjloIq_^JUwuM|XL+e_#Th33z*Z`xBz~ z)DZyi9={10jKeK0z#^@;E`vCne%|8_|z;K>0M!q@9V0j6M(@kfnDQHL(H;eGgw(R z7@x9@VA{j@>vHTEV3}RgEFPx%ykw9i4?LVBp=p)n7+`rxY*JNOtg3NS&0WPfn)V!&~&D3KX6!Vi_Qgj$_BSz9ZF@X7XZ`F7uGAXjw8VGGQcJ?JFM;n z9vnsSlMAP8Jf5(I-*-l70px6f&E>Tyuwojf4Fj5Knzq{24*~Kei}Ga=#L(XT?NPjl zlH(A8V3zQB02{4@vG~z}dAS#8C1W#z$%Kt`>}L5F25bXr9yU({Fv+1Z<3ooBZtzzm zQELaa>N2}4VY!Dtj-1?eN^VIk9AILWOJb%h0ZH^AiOf?<+A8K|xCAN86yj+BCLJ$7 zW3Nn9O@6VPBALK?btmX)62_H+7cH&Kpl~pff0pqm|o!YPDQ*`d)2kh37 z)~-$Liu+T>)_)#3o~^yGGZsI&%FFjbn^pd_0CZr$hKF3+%?p<7jpZd7Nd^1}%g`t? zP+2|z9G!kr3wS=OsLKCej!3{2JN+#7Aym<^k3zojkB<4*(qTB(Oi64Uve;4WyExlz zl%-3XI2iu|V8fya<0sCR##R;lw2e6%0C{ZG2BcN1if4;hGmw~uJl@Sq9=sKMESTk! zv}*0EvFkj1P3ZLHQPbD*}MUYE8HVbh0``(#3=9KOtpx;eM=jRS_7BEZQ>~5FDv7P7 zGN88UKP53V@sHLqZ5lOch4`OU7*J!4#-+A(i;CJ7cTvHO)w&MM!YshdTkh%Scjw;6 zoi}f}@6Br38y@%F<(%_7-}Bqg?~RfFA4L%`6N8U6vRoqafauwBc0`Pw7+Q*tIywL? zw~1*nsf)y9T1KR%Dke3?$YNkV&qS9n!PDS@ zD$b_>Ks7`!0lwnvZf+d`*pGPD#d$~Ck=Jch_V)Ax=)I<|XfEuo{U$qHoibdpS3~~nIGDo$vmq-$s|*%Q~@^$aRW^B zB}~*|t}~IOWb~ZkgWYnXRg%gKprldGaVt^Yk2(p?0}_oSWGa0vMVu4dPoU&ar>_KK zoCtl5oR3iu!z`djtBT?Jjtz1vtsp7fG1xzPrm;>Qg!oGf4H%I3Hom_PWy-eCOIqGc z#-tlo?(U1rLAk@E!VO))Ti4n6G?99fk?D!F)H_i*3*gSBr<0)lWN11@do4HzoLn)X>82YxHkg}B(PkQ(?GAYIRG%-^Qv>1W93#K& z+F<@!s)Nb?yy2(zTP7}lh(u*sR!t~KM&9d4;>JRo`ZF ze`o?G`HQtz*(<6Nau*_3=j$abnjA^X`G+={XG#HNRjjfA@ddx32W9+}&B$$?d*zj| z8h=vZgk^4+BIlZzTnE=&4sFw1w;(XrbiXX_y4So@Hb4QudTG3s0Q7!*_7{4#5d*zG zhGu-E2shbS{al#~5MNJ3phr9TfxQH+1{9@&$vufeGCX zdv3`%va6>Pm;SFtL7bRlxvj0MlQ{&=3(+sd^zp${r?Lqh4tkH{R7<{@h&$1Fjm(SHlAt&fnkR}l!atdYMV;^U8KtiTv>ea1GVv@vUnw_(;FC{A6}lYHI7_r<>G zWOG0oCi{T;H$55jF5lKH5#OVHK4u|~xRzApBZB6gjPW5pPFH6e0EO`S#~+|#ashal z-zo8wOi3ps;q*%)7UQf5dLxmjL()D1v!x|tWALPd0?$Y~9uo&eo=T@t-qn(fB_*lW zu&2khghxgqijxbVk<6sbwvE@=CM@GJMC|$YJI$6t&HpC>BGA4Rx8PwP6hJz!5J)2e z$kVUxILP>;z7;ETF~|M&+1J=d81#pMfp6M>r)kMYNW}oL3ZzB`t&f{MwDL^n26O(n z&$faA5wA6f*KK}NoWbS;8%*oy0<_8|qY-y^(*+16*+xF-#0ibD$^Z*4YJuz~)^|%G z?jb0dI(@PH4d?f~fTQ^NKt`7Jw3?m8hBM@YhNU|+)tYpqrMFecC{E5j^RO7sxY~Z3 zY~t@=g7boHV1%t5hvhQ4&$N{dkfu8Tsh5>`7FYeA&Nw;gJB)7Yd^wIE+s1}!Hz)lI zrt)35hRu+phx%DgT5jlQ4U?13!$E#N$QL{G(pCm}8wc$PEX9sVy{i$E%URsB;F_g{ z;yO|_Pj&Rl_rqiv@`_jxpsWJ)bQFVr0RbQAzL@$RgdN)u$8L5%y8GItTOKz9W5#9| z*{a$`sb^EMF1s&g2z#uY%mSWNYJ1#GHaPM~`yPsJLhjoS0|;(81Z&omimC$Wdbm5Q*aA`ynMg{~PF!LT9mPtxJF84GLMAAN zmpwHalXJPJl_LrI)nr&4FivE=My}`Rz@_N)rGR#AEaNgxZIS+(MH>JZW@Gpi2-ePR^C2GkOuLh{5=fxcyCJn*nhX#TP}AG=OE8f zY`oGQo2iy2w0|=|&FAA5GK5*Na)}tN_XCTgmg#Lc^Fb#`b;rHtlS;=Z2v9)hoB9

mI42U^dkKF1qB}B_tG|&Amp8*90 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 CsTA1& literal 0 HcmV?d00001 diff --git a/react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx b/react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx index 5e619d7a..e61423fd 100644 --- a/react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx +++ b/react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx @@ -19,7 +19,7 @@ const GlobalParamsDrawer = forwardRef( const [form] = Form.useForm(); useImperativeHandle(ref, () => ({ - getFieldsValue: async () => { + validateFields: async () => { const [values, error] = await to(form.validateFields()); if (!error && values) { return values; @@ -27,6 +27,9 @@ const GlobalParamsDrawer = forwardRef( return Promise.reject(error); } }, + getFieldsValue: () => { + return form.getFieldsValue(); + }, })); // 处理参数类型变化 diff --git a/react-ui/src/pages/Pipeline/components/PropsLabel/index.less b/react-ui/src/pages/Pipeline/components/PropsLabel/index.less new file mode 100644 index 00000000..2df39c02 --- /dev/null +++ b/react-ui/src/pages/Pipeline/components/PropsLabel/index.less @@ -0,0 +1,6 @@ +.props-label { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; +} diff --git a/react-ui/src/pages/Pipeline/components/PropsLabel/index.tsx b/react-ui/src/pages/Pipeline/components/PropsLabel/index.tsx new file mode 100644 index 00000000..04197b75 --- /dev/null +++ b/react-ui/src/pages/Pipeline/components/PropsLabel/index.tsx @@ -0,0 +1,44 @@ +import { Button, Dropdown, type MenuProps } from 'antd'; +import { useEffect } from 'react'; +import styles from './index.less'; + +type PropsLabelProps = { + title: string; + menuItems: MenuProps['items']; + onClick?: (key: string) => void; +}; + +function PropsLabel({ title, menuItems, onClick }: PropsLabelProps) { + useEffect(() => {}, []); + + const handleItemClick: MenuProps['onClick'] = (e) => { + const keyPath = e.keyPath.reverse(); + if (keyPath[0] === 'global') { + onClick?.(`\${${e.key}}`); + } else { + onClick?.(`{{${keyPath.join('.')}}}`); + } + }; + + return ( +

+ {title} + + + +
+ ); +} + +export default PropsLabel; diff --git a/react-ui/src/pages/Pipeline/editPipeline/editPipeline.less b/react-ui/src/pages/Pipeline/editPipeline/editPipeline.less index 68188b26..382cc587 100644 --- a/react-ui/src/pages/Pipeline/editPipeline/editPipeline.less +++ b/react-ui/src/pages/Pipeline/editPipeline/editPipeline.less @@ -3,6 +3,17 @@ width: 100%; height: 100%; } +.editPipelineProps { + :global { + label { + width: 100%; + + &::after { + display: none; + } + } + } +} .editPipelinePropsContent { display: flex; align-items: center; diff --git a/react-ui/src/pages/Pipeline/editPipeline/index.jsx b/react-ui/src/pages/Pipeline/editPipeline/index.jsx index 538626aa..0c067f58 100644 --- a/react-ui/src/pages/Pipeline/editPipeline/index.jsx +++ b/react-ui/src/pages/Pipeline/editPipeline/index.jsx @@ -1,27 +1,26 @@ import KFIcon from '@/components/KFIcon'; -import { useVisible } from '@/hooks'; +import { useStateRef, useVisible } from '@/hooks'; import { getWorkflowById, saveWorkflow } from '@/services/pipeline/index.js'; import { to } from '@/utils/promise'; import { useEmotionCss } from '@ant-design/use-emotion-css'; import G6 from '@antv/g6'; import { Button, message } from 'antd'; -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { s8 } from '../../../utils'; import GlobalParamsDrawer from '../components/GlobalParamsDrawer'; import Styles from './editPipeline.less'; import ModelMenus from './modelMenus'; import Props from './props'; +import { findAllParentNodes, findFirstDuplicate } from './utils'; let graph = null; const EditPipeline = () => { - const propsRef = useRef(); const navgite = useNavigate(); - // const [contextMenu,setContextMenu]=useState({}) let contextMenu = {}; const locationParams = useParams(); //新版本获取路由参数接口 - let sourceAnchorIdx, targetAnchorIdx; + const pipelineContainer = useEmotionCss(() => { return { display: 'flex', @@ -59,8 +58,11 @@ const EditPipeline = () => { }); const graphRef = useRef(); const paramsDrawerRef = useRef(); + const propsRef = useRef(); const [paramsDrawerOpen, openParamsDrawer, closeParamsDrawer] = useVisible(false); - const [globalParam, setGlobalParam] = useState([]); + const [globalParam, setGlobalParam, globalParamRef] = useStateRef([]); + + let sourceAnchorIdx, targetAnchorIdx; const onDragEnd = (val) => { console.log(val, 'eee'); @@ -93,17 +95,24 @@ const EditPipeline = () => { } }; const savePipeline = async (val) => { - const [res, error] = await to(paramsDrawerRef.current.getFieldsValue()); + const [res, error] = await to(paramsDrawerRef.current.validateFields()); if (error) { message.error('全局参数配置有误'); openParamsDrawer(); return; } + + const duplicateName = findFirstDuplicate(res.global_param || []); + if (duplicateName) { + message.error('全局参数配置有重复的参数名称:' + duplicateName); + openParamsDrawer(); + return; + } + const [propsRes, propsError] = await to(propsRef.current.getFieldsValue()); console.log(await to(propsRef.current.getFieldsValue())); if (propsError) { message.error('基本信息必填项需配置'); - // handlerClick(); return; } propsRef.current.propClose(); @@ -128,12 +137,19 @@ const EditPipeline = () => { }; const handlerClick = (e) => { e.stopPropagation(); - // console.log(propsRef, graph); - propsRef.current.showDrawer(e); + if (e.target.get('name') !== 'anchor-point' && e.item) { + graph.setItemState(e.item, 'nodeClicked', true); + const parentNodes = findAllParentNodes(graph, e.item); + // 如果没有打开过全局参数抽屉,获取不到全局参数 + const globalParams = + paramsDrawerRef.current.getFieldsValue().global_param || globalParamRef.current; + propsRef.current.showDrawer(e, globalParams, parentNodes); + } }; const getGraphData = (data) => { + console.log('graph', graph); if (graph) { - console.log(graph); + console.log(data); graph.data(data); graph.render(); } else { @@ -275,14 +291,13 @@ const EditPipeline = () => { if (graph && ret.data && ret.data.dag) { getGraphData(JSON.parse(ret.data.dag)); } - // graph&&graph.data(JSON.parse(ret.dag)) - // graph.render() }); }; const handlerContextMenu = (e) => { e.stopPropagation(); // this.menuType = e.item._cfg.type; }; + // 上下文菜单 const initMenu = () => { // const selectedNodes = this.selectedNodes; contextMenu = new G6.Menu({ @@ -330,8 +345,8 @@ const EditPipeline = () => { initGraph(); }; useEffect(() => { - getFirstWorkflow(locationParams.id); initMenu(); + getFirstWorkflow(locationParams.id); return () => { graph.off('node:mouseenter', (e) => { @@ -449,7 +464,7 @@ const EditPipeline = () => { }, 'rect', ); - console.log(graphRef, 'graphRef'); + graph = new G6.Graph({ container: graphRef.current, grid: true, @@ -600,13 +615,7 @@ const EditPipeline = () => { // handlerClick(e); // } // }); - graph.on('node:click', (e) => { - console.log(e.target.get('name')); - if (e.target.get('name') !== 'anchor-point' && e.item) { - graph.setItemState(e.item, 'nodeClicked', true); - handlerClick(e); - } - }); + graph.on('node:click', handlerClick); graph.on('aftercreateedge', (e) => { // update the sourceAnchor and targetAnchor for the newly added edge graph.updateItem(e.edge, { diff --git a/react-ui/src/pages/Pipeline/editPipeline/modelMenus.jsx b/react-ui/src/pages/Pipeline/editPipeline/modelMenus.jsx index deb3846a..181a4139 100644 --- a/react-ui/src/pages/Pipeline/editPipeline/modelMenus.jsx +++ b/react-ui/src/pages/Pipeline/editPipeline/modelMenus.jsx @@ -2,23 +2,6 @@ import { getComponentAll } from '@/services/pipeline/index.js'; import { Collapse } from 'antd'; import { useEffect, useState } from 'react'; import Styles from './modelMenus.less'; -const items = [ - { - key: '1', - label: 'This is panel header 1', - children: [1, 2, 3, 4, 5], - }, - { - key: '2', - label: 'This is panel header 2', - children: [1, 2, 3, 4, 5], - }, - { - key: '3', - label: 'This is panel header 3', - children: [1, 2, 3, 4, 5], - }, -]; const ModelMenus = ({ onParDragEnd }) => { const [modelMenusList, setModelMenusList] = useState([]); useEffect(() => { @@ -36,7 +19,7 @@ const ModelMenus = ({ onParDragEnd }) => { x: e.clientX, y: e.clientY, label: data.component_label, - img: `/assets/images/${data.icon_path}.png`, + img: `/assets/images/pipeline/${data.icon_path}.png`, }); }; const { Panel } = Collapse; @@ -64,7 +47,7 @@ const ModelMenus = ({ onParDragEnd }) => { > {ele.component_label} diff --git a/react-ui/src/pages/Pipeline/editPipeline/props.jsx b/react-ui/src/pages/Pipeline/editPipeline/props.jsx index df77d981..6f7d2586 100644 --- a/react-ui/src/pages/Pipeline/editPipeline/props.jsx +++ b/react-ui/src/pages/Pipeline/editPipeline/props.jsx @@ -5,22 +5,25 @@ import { to } from '@/utils/promise'; import { Button, Drawer, Form, Input, Select } from 'antd'; import { pick } from 'lodash'; import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; +import PropsLabel from '../components/PropsLabel'; import ResourceSelectorModal, { ResourceSelectorType } from '../components/ResourceSelectorModal'; import Styles from './editPipeline.less'; +import { createMenuItems } from './utils'; const { TextArea } = Input; + const Props = forwardRef(({ onParentChange }, ref) => { const [form] = Form.useForm(); - const [stagingItem, setStagingItem] = useState({}); const [open, setOpen] = useState(false); - const [selectedModel, setSelectedModel] = useState(undefined); - const [selectedDataset, setSelectedDataset] = useState(undefined); - const [resourceStandardList, setResourceStandardList] = useState([]); - + const [selectedModel, setSelectedModel] = useState(undefined); // 选择的模型,为了再次打开时恢复原来的选择 + const [selectedDataset, setSelectedDataset] = useState(undefined); // 选择的数据集,为了再次打开时恢复原来的选择 + const [resourceStandardList, setResourceStandardList] = useState([]); // 资源规模列表 + const [items, setItems] = useState([]); useEffect(() => { getComputingResource(); }, []); + // 获取资源规格列表数据 const getComputingResource = async () => { const params = { page: 0, @@ -35,49 +38,22 @@ const Props = forwardRef(({ onParentChange }, ref) => { const afterOpenChange = () => { if (!open) { - console.log(stagingItem, form.getFieldsValue()); - // 禁止校验 guard-for-in - /* eslint-disable */ - for (let i in form.getFieldsValue()) { - for (let j in stagingItem.in_parameters) { - if (i == j) { - console.log(j, i); - stagingItem.in_parameters[j].value = form.getFieldsValue()[i]; - } - } - for (let p in stagingItem.out_parameters) { - if (i == p) { - stagingItem.out_parameters[p].value = form.getFieldsValue()[i]; - } - } - for (let k in stagingItem.control_strategy) { - if (i == k) { - stagingItem.control_strategy[k].value = form.getFieldsValue()[i]; - } - } - } - /* eslint-enable */ - // setStagingItem({...stagingItem,}) - console.log(stagingItem.control_strategy); + // console.log('zzzz', stagingItem, form.getFieldsValue()); + const control_strategy = form.getFieldValue('control_strategy'); + const in_parameters = form.getFieldValue('in_parameters'); + const out_parameters = form.getFieldValue('out_parameters'); onParentChange({ ...stagingItem, - control_strategy: JSON.stringify(stagingItem.control_strategy), - in_parameters: JSON.stringify(stagingItem.in_parameters), - out_parameters: JSON.stringify(stagingItem.out_parameters), ...form.getFieldsValue(), + control_strategy: JSON.stringify(control_strategy), + in_parameters: JSON.stringify(in_parameters), + out_parameters: JSON.stringify(out_parameters), }); - // onParentChange({...stagingItem,...form.getFieldsValue()}) } }; const onClose = () => { setOpen(false); }; - const onFinish = (values) => { - console.log('Success:', values); - }; - const onFinishFailed = (errorInfo) => { - console.log('Failed:', errorInfo); - }; useImperativeHandle(ref, () => ({ getFieldsValue: async () => { const [propsRes, propsError] = await to(form.validateFields()); @@ -88,30 +64,27 @@ const Props = forwardRef(({ onParentChange }, ref) => { return Promise.reject(propsError); } }, - showDrawer(e) { + showDrawer(e, params, parentNodes) { if (e.item && e.item.getModel()) { - // console.log(e.item.getModel().in_parameters); form.resetFields(); - form.setFieldsValue({ - ...e.item.getModel(), - in_parameters: JSON.parse(e.item.getModel().in_parameters), - out_parameters: JSON.parse(e.item.getModel().out_parameters), - control_strategy: JSON.parse(e.item.getModel().control_strategy), - }); + const model = e.item.getModel(); + const nodeData = { + ...model, + in_parameters: JSON.parse(model.in_parameters), + out_parameters: JSON.parse(model.out_parameters), + control_strategy: JSON.parse(model.control_strategy), + }; setStagingItem({ - ...e.item.getModel(), - in_parameters: JSON.parse(e.item.getModel().in_parameters), - out_parameters: JSON.parse(e.item.getModel().out_parameters), - control_strategy: JSON.parse(e.item.getModel().control_strategy), + ...nodeData, + }); + form.setFieldsValue({ + ...nodeData, }); - // form.setFieldsValue({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters)}) - // setStagingItem({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters)}) - // setTimeout(() => { - // console.log(stagingItem); - // }, (500)); setSelectedModel(undefined); setSelectedDataset(undefined); setOpen(true); + + setItems(createMenuItems(params, parentNodes)); } }, propClose: async () => { @@ -119,16 +92,12 @@ const Props = forwardRef(({ onParentChange }, ref) => { const [openRes, propsError] = await to(setOpen(false)); console.log(setOpen(false)); }, - // propClose() { - - // setOpen(false); - // }, })); // 选择数据集、模型 const selectResource = (name, item) => { let type; - let resource = undefined; + let resource; switch (item.item_type) { case 'dataset': type = ResourceSelectorType.Dataset; @@ -154,7 +123,7 @@ const Props = forwardRef(({ onParentChange }, ref) => { } else { const jsonObj = pick(res, ['id', 'version', 'path']); const value = JSON.stringify(jsonObj); - form.setFieldValue(name, value); + form.setFieldValue(name, { ...item, value }); } if (type === ResourceSelectorType.Dataset) { @@ -187,16 +156,26 @@ const Props = forwardRef(({ onParentChange }, ref) => { } }; + // 筛选资源规格 const filterResourceStandard = (input, { computing_resource = '' }) => { return computing_resource.toLocaleLowerCase().includes(input.toLocaleLowerCase()); }; // 控制策略 - const controlStrategy = stagingItem.control_strategy; + const controlStrategyList = Object.entries(stagingItem.control_strategy ?? {}).map( + ([key, value]) => ({ key, value }), + ); + // 输入参数 - const inParameters = stagingItem.in_parameters; + const inParametersList = Object.entries(stagingItem.in_parameters ?? {}).map(([key, value]) => ({ + key, + value, + })); + // 输出参数 - const outParameters = stagingItem.out_parameters; + const outParametersList = Object.entries(stagingItem.out_parameters ?? {}).map( + ([key, value]) => ({ key, value }), + ); return ( <> @@ -209,15 +188,15 @@ const Props = forwardRef(({ onParentChange }, ref) => { onClose={onClose} afterOpenChange={afterOpenChange} open={open} - width={420} + width={520} + className={Styles.editPipelineProps} >
{ style={{ maxWidth: 600, }} - initialValues={{ - remember: true, - }} - onFinish={onFinish} - onFinishFailed={onFinishFailed} autoComplete="off" >
@@ -250,7 +224,7 @@ const Props = forwardRef(({ onParentChange }, ref) => { }, ]} > - + {
- +
- - + { + form.setFieldValue('working_directory', value); + }} + /> + } + > + - - -