From d99294790f017f0248397414c7321f2ef4f25400 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Thu, 9 May 2024 11:42:45 +0800 Subject: [PATCH 01/14] =?UTF-8?q?style:=20=E4=BF=AE=E6=94=B9=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/config/defaultSettings.ts | 2 +- react-ui/src/app.tsx | 11 +++++-- react-ui/src/components/KFModal/index.less | 2 +- react-ui/src/components/KFRadio/index.less | 5 +++ react-ui/src/overrides.less | 31 ++++++++++++------- .../experimentText/addExperimentModal.less | 13 -------- .../experimentText/addExperimentModal.tsx | 1 + react-ui/src/pages/Mirror/create.less | 6 ++-- react-ui/src/pages/Mirror/create.tsx | 6 ++-- react-ui/src/pages/Mirror/list.less | 2 +- react-ui/src/pages/Model/index.less | 14 ++++----- react-ui/src/pages/Model/modelIntro.jsx | 2 +- .../editPipeline/globalParamsDrawer.tsx | 1 - .../components/AssetsManagement/index.tsx | 13 ++++---- .../components/ExperimentChart/index.less | 2 +- .../components/ExperimentTable/index.less | 2 +- .../components/TotalStatistics/index.less | 2 +- .../Workspace/components/UserSpace/index.less | 8 +---- .../Workspace/components/UserSpace/index.tsx | 20 +++++++++--- react-ui/src/pages/Workspace/index.less | 1 + react-ui/src/requestConfig.ts | 17 ++-------- react-ui/src/styles/theme.less | 6 ++++ 22 files changed, 87 insertions(+), 80 deletions(-) diff --git a/react-ui/config/defaultSettings.ts b/react-ui/config/defaultSettings.ts index 7c1cfbd5..ada98f3e 100644 --- a/react-ui/config/defaultSettings.ts +++ b/react-ui/config/defaultSettings.ts @@ -19,7 +19,7 @@ const Settings: ProLayoutProps & { title: '智能软件开发平台', pwa: true, logo: '/assets/images/left-top-logo.png', - iconfontUrl: '//at.alicdn.com/t/c/font_4511326_1cmi0j3dj1x.js', + iconfontUrl: '//at.alicdn.com/t/c/font_4511326_t634djsqobs.js', token: { // 参见ts声明,demo 见文档,通过token 修改样式 //https://procomponents.ant.design/components/layout#%E9%80%9A%E8%BF%87-token-%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F diff --git a/react-ui/src/app.tsx b/react-ui/src/app.tsx index a4642589..a8ac8966 100644 --- a/react-ui/src/app.tsx +++ b/react-ui/src/app.tsx @@ -215,6 +215,7 @@ export const antd: RuntimeAntdConfig = (memo) => { colorError: themes['errorColor'], colorWarning: themes['warningColor'], colorLink: themes['primaryColor'], + colorText: themes['textColor'], }; memo.theme.components ??= {}; memo.theme.components.Tabs = {}; @@ -229,10 +230,11 @@ export const antd: RuntimeAntdConfig = (memo) => { defaultActiveBorderColor: 'rgba(22, 100, 255, 0.75)', defaultActiveColor: themes['primaryColor'], contentFontSize: parseInt(themes['fontSize']), - controlHeight: 34, }; memo.theme.components.Input = { - inputFontSize: parseInt(themes['fontSize']), + inputFontSize: parseInt(themes['fontSizeInput']), + inputFontSizeLG: parseInt(themes['fontSizeInputLg']), + paddingBlockLG: 10, }; memo.theme.components.Table = { headerBg: 'rgba(242, 244, 247, 0.36)', @@ -241,6 +243,11 @@ export const antd: RuntimeAntdConfig = (memo) => { memo.theme.components.Tabs = { titleFontSize: 16, }; + + memo.theme.components.Form = { + labelColor: 'rgba(29, 29, 32, 0.8);', + }; + memo.theme.cssVar = true; // memo.theme.hashed = false; diff --git a/react-ui/src/components/KFModal/index.less b/react-ui/src/components/KFModal/index.less index 57153a58..d2810cab 100644 --- a/react-ui/src/components/KFModal/index.less +++ b/react-ui/src/components/KFModal/index.less @@ -17,7 +17,7 @@ margin-top: 40px; .ant-btn { - height: 40px; + height: 42px; padding: 0 30px; font-size: @font-size-content; border-radius: 10px; diff --git a/react-ui/src/components/KFRadio/index.less b/react-ui/src/components/KFRadio/index.less index aff74e90..455492a4 100644 --- a/react-ui/src/components/KFRadio/index.less +++ b/react-ui/src/components/KFRadio/index.less @@ -23,6 +23,11 @@ &--active { color: @primary-color; border: 1px solid @primary-color; + + &:hover { + color: @primary-color; + border: 1px solid @primary-color; + } } & + & { diff --git a/react-ui/src/overrides.less b/react-ui/src/overrides.less index e962088a..eb4722e9 100644 --- a/react-ui/src/overrides.less +++ b/react-ui/src/overrides.less @@ -57,11 +57,6 @@ overflow-y: auto; } -// Input -.ant-input-textarea-affix-wrapper.ant-input-affix-wrapper { - padding: 0; -} - // Modal .ant-modal { .ant-modal-close { @@ -81,18 +76,24 @@ } } + .ant-form-item .ant-form-item-label > label { + font-size: @font-size; + } + + // 输入框高度为46px .ant-input-affix-wrapper { - height: 46px; - padding: 1px 11px; + padding-top: 2px; + padding-bottom: 2px; + + .ant-input { + height: 40px; + } } + // 选择框高度为46px .ant-select-single { height: 46px; } - - .ant-select-single .ant-select-selector .ant-select-selection-placeholder { - line-height: 46px; - } } // Confirm Modal @@ -137,3 +138,11 @@ } } } + +.ant-form-large { + .ant-form-item-label { + label { + font-size: @font-size; + } + } +} diff --git a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less index e8be2e5f..eec152a7 100644 --- a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less +++ b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less @@ -1,17 +1,4 @@ .modal { - :global { - // .ant-input { - // height: 30px; - // border-color: #e6e6e6; - // } - // .ant-select-single { - // height: 40px; - // } - .ant-form-item .ant-form-item-label > label { - color: rgba(29, 29, 32, 0.8); - } - } - .global_param_item { max-height: 230px; padding: 24px 12px 0; diff --git a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx index f5b2bfc4..5c853c42 100644 --- a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx +++ b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx @@ -132,6 +132,7 @@ function AddExperimentModal({ {...layout} labelAlign="left" labelWrap + size="large" > { const fileList = form.getFieldValue('fileList'); if (Array.isArray(fileList) && fileList.length >= 1) { @@ -134,12 +135,13 @@ function MirrorCreate() {
- 公网 + 公网 diff --git a/react-ui/src/pages/Mirror/list.less b/react-ui/src/pages/Mirror/list.less index 9eb8009a..372b9893 100644 --- a/react-ui/src/pages/Mirror/list.less +++ b/react-ui/src/pages/Mirror/list.less @@ -20,7 +20,7 @@ } &__table { - height: calc(100% - 34px - 28px); + height: calc(100% - 32px - 28px); margin-top: 28px; } } diff --git a/react-ui/src/pages/Model/index.less b/react-ui/src/pages/Model/index.less index defa446f..4442e66a 100644 --- a/react-ui/src/pages/Model/index.less +++ b/react-ui/src/pages/Model/index.less @@ -190,8 +190,8 @@ flex: 1; flex-direction: column; height: 100%; - overflow-y: auto; padding: 22px 30px 26px 30px; + overflow-y: auto; background: #ffffff; box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09); .dataSource { @@ -212,17 +212,17 @@ .dataItem { position: relative; width: 23.8%; - height:164px; + height: 164px; margin: 0 20px 25px 0; background: #ffffff; border: 1px solid; border-color: #eaeaea; border-radius: 4px; cursor: pointer; - .dropdown{ + .dropdown { position: absolute; - right: 20px; top: 15px; + right: 20px; } .itemText { position: absolute; @@ -281,9 +281,9 @@ } } } -.tipContent{ - color: #c73131; +.tipContent { margin-top: 5px; + color: #c73131; } .modal { :global { @@ -314,7 +314,7 @@ } .ant-btn { width: 110px; - height: 40px; + height: 42px; font-size: 18px; background: rgba(22, 100, 255, 0.06); border-color: transparent; diff --git a/react-ui/src/pages/Model/modelIntro.jsx b/react-ui/src/pages/Model/modelIntro.jsx index 5cc9477d..af27f292 100644 --- a/react-ui/src/pages/Model/modelIntro.jsx +++ b/react-ui/src/pages/Model/modelIntro.jsx @@ -19,7 +19,7 @@ const { TabPane } = Tabs; const Dataset = () => { const props = { - action: '/api/mmp/dataset/upload', + action: '/api/mmp/models/upload', // headers: { // 'X-Requested-With': null // }, diff --git a/react-ui/src/pages/Pipeline/editPipeline/globalParamsDrawer.tsx b/react-ui/src/pages/Pipeline/editPipeline/globalParamsDrawer.tsx index 7ab95f5d..817d6dc6 100644 --- a/react-ui/src/pages/Pipeline/editPipeline/globalParamsDrawer.tsx +++ b/react-ui/src/pages/Pipeline/editPipeline/globalParamsDrawer.tsx @@ -162,7 +162,6 @@ const GlobalParamsDrawer = forwardRef( )} - {/* //{contextHolder} */} ); }, diff --git a/react-ui/src/pages/Workspace/components/AssetsManagement/index.tsx b/react-ui/src/pages/Workspace/components/AssetsManagement/index.tsx index dc1af6c9..1a734e57 100644 --- a/react-ui/src/pages/Workspace/components/AssetsManagement/index.tsx +++ b/react-ui/src/pages/Workspace/components/AssetsManagement/index.tsx @@ -35,10 +35,10 @@ function AssetsManagement() { title: '组件', value: component, }, - { - title: '代码配置', - value: 0, - }, + // { + // title: '代码配置', + // value: 0, + // }, { title: '流水线模版', value: workflow, @@ -64,9 +64,8 @@ function AssetsManagement() { ]} /> - -
今日新增数量:5
- + {/*
今日新增数量:5
*/} + {assetCounts.map((item, index) => (
{item.title}
diff --git a/react-ui/src/pages/Workspace/components/ExperimentChart/index.less b/react-ui/src/pages/Workspace/components/ExperimentChart/index.less index 3891b3f4..a723c650 100644 --- a/react-ui/src/pages/Workspace/components/ExperimentChart/index.less +++ b/react-ui/src/pages/Workspace/components/ExperimentChart/index.less @@ -2,6 +2,6 @@ width: 295px; min-width: 295px; height: 140px; - background-color: @workspace-background; + background: @workspace-background; border-radius: 4px; } diff --git a/react-ui/src/pages/Workspace/components/ExperimentTable/index.less b/react-ui/src/pages/Workspace/components/ExperimentTable/index.less index 85c5e42d..f40613e6 100644 --- a/react-ui/src/pages/Workspace/components/ExperimentTable/index.less +++ b/react-ui/src/pages/Workspace/components/ExperimentTable/index.less @@ -3,7 +3,7 @@ min-width: 500px; height: 140px; padding: 12px 24px; - background-color: @workspace-background; + background: @workspace-background; border-radius: 4px; &__header { diff --git a/react-ui/src/pages/Workspace/components/TotalStatistics/index.less b/react-ui/src/pages/Workspace/components/TotalStatistics/index.less index aec9945b..23e4fec2 100644 --- a/react-ui/src/pages/Workspace/components/TotalStatistics/index.less +++ b/react-ui/src/pages/Workspace/components/TotalStatistics/index.less @@ -4,7 +4,7 @@ justify-content: center; width: 400px; height: 140px; - background-color: @workspace-background; + background: @workspace-background; border-radius: 4px; &__icon { diff --git a/react-ui/src/pages/Workspace/components/UserSpace/index.less b/react-ui/src/pages/Workspace/components/UserSpace/index.less index b95fdf6d..1c36f6b3 100644 --- a/react-ui/src/pages/Workspace/components/UserSpace/index.less +++ b/react-ui/src/pages/Workspace/components/UserSpace/index.less @@ -20,8 +20,7 @@ &__avatar { position: relative; top: -28px; - width: 56px; - height: 56px; + background-color: white; } &__name { @@ -56,10 +55,5 @@ background-color: rgba(153, 153, 153, 0.13); border-radius: 50%; } - - &__user { - width: 36px; - height: 36px; - } } } diff --git a/react-ui/src/pages/Workspace/components/UserSpace/index.tsx b/react-ui/src/pages/Workspace/components/UserSpace/index.tsx index 503ea9fc..bd4bf323 100644 --- a/react-ui/src/pages/Workspace/components/UserSpace/index.tsx +++ b/react-ui/src/pages/Workspace/components/UserSpace/index.tsx @@ -1,5 +1,5 @@ import { useModel } from '@umijs/max'; -import { Divider, Flex, Space } from 'antd'; +import { Avatar, Divider, Flex, Space } from 'antd'; import styles from './index.less'; type UserSpaceProps = { @@ -14,7 +14,14 @@ function UserSpace({ users = [] }: UserSpaceProps) {
工作空间管理
- + } + >
{currentUser?.nickName}
{currentUser?.roleNames?.[0]?.roleName}
{users?.map((item, index) => { return ( - + icon={ + + } + > ); })} diff --git a/react-ui/src/pages/Workspace/index.less b/react-ui/src/pages/Workspace/index.less index 1a454f38..30b1f1a5 100644 --- a/react-ui/src/pages/Workspace/index.less +++ b/react-ui/src/pages/Workspace/index.less @@ -5,6 +5,7 @@ background-color: linear-gradient(#ecf2fe, #f9fafb); &__overview { + gap: 15px; margin-bottom: 16px; padding: 20px 30px; background-color: white; diff --git a/react-ui/src/requestConfig.ts b/react-ui/src/requestConfig.ts index 2a9d6413..74cb5c43 100644 --- a/react-ui/src/requestConfig.ts +++ b/react-ui/src/requestConfig.ts @@ -25,21 +25,6 @@ export const requestConfig: RequestConfig = { if (accessToken) { headers['Authorization'] = `Bearer ${accessToken}`; } - // const expireTime = getTokenExpireTime(); - // if (expireTime) { - // const left = Number(expireTime) - new Date().getTime(); - // const refreshToken = getRefreshToken(); - // if (left < 0 && refreshToken) { - // clearSessionToken(); - // } else { - // const accessToken = getAccessToken(); - // if (accessToken) { - // headers['Authorization'] = `Bearer ${accessToken}`; - // } - // } - // } else { - // clearSessionToken(); - // } } return { url, options }; }, @@ -55,6 +40,8 @@ export const requestConfig: RequestConfig = { clearSessionToken(); setRemoteMenu(null); gotoLoginPage(false); + message.error(data?.msg ?? '请重新登录'); + return Promise.reject(response); } else { message.error(data?.msg ?? '请求失败'); return Promise.reject(response); diff --git a/react-ui/src/styles/theme.less b/react-ui/src/styles/theme.less index c6514915..bb9f34aa 100644 --- a/react-ui/src/styles/theme.less +++ b/react-ui/src/styles/theme.less @@ -36,6 +36,8 @@ @font-size: 15px; @font-size-title: 18px; @font-size-content: 16px; +@font-size-input: 14px; +@font-size-input-lg: 16px; // 函数 .addAlpha(@color, @alpha) { @@ -55,5 +57,9 @@ textColor: @text-color; textColorSecondary: @text-color-secondary; fontSize: @font-size; + fontSizeTitle: @font-size-title; + fontSizeContent: @font-size-content; + fontSizeInput: @font-size-input; + fontSizeInputLg: @font-size-input-lg; siderBGColor: @sider-background-color; } From 808b97aa4f9a8b37204f7a35a4500b6fd9e0f3db Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Thu, 9 May 2024 14:33:59 +0800 Subject: [PATCH 02/14] =?UTF-8?q?fix:=20=E5=85=AC=E5=BC=80=E7=9A=84?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=9B=86=E5=92=8C=E6=A8=A1=E5=9E=8B=E4=B8=8D?= =?UTF-8?q?=E5=85=81=E8=AE=B8=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/config/defaultSettings.ts | 2 +- react-ui/src/components/KFModal/index.less | 4 +- react-ui/src/overrides.less | 3 +- react-ui/src/pages/Dataset/datasetIntro.jsx | 24 +++++---- react-ui/src/pages/Dataset/personalData.jsx | 2 +- react-ui/src/pages/Dataset/publicData.jsx | 28 +--------- .../pages/Experiment/experimentText/props.jsx | 4 +- react-ui/src/pages/Model/modelIntro.jsx | 25 +++++---- react-ui/src/pages/Model/personalData.jsx | 4 +- react-ui/src/pages/Model/publicData.jsx | 30 ++--------- react-ui/src/pages/Pipeline/index.jsx | 21 +++----- react-ui/src/pages/Pipeline/index.less | 51 ++----------------- 12 files changed, 54 insertions(+), 144 deletions(-) diff --git a/react-ui/config/defaultSettings.ts b/react-ui/config/defaultSettings.ts index ada98f3e..65b0fcf5 100644 --- a/react-ui/config/defaultSettings.ts +++ b/react-ui/config/defaultSettings.ts @@ -19,7 +19,7 @@ const Settings: ProLayoutProps & { title: '智能软件开发平台', pwa: true, logo: '/assets/images/left-top-logo.png', - iconfontUrl: '//at.alicdn.com/t/c/font_4511326_t634djsqobs.js', + iconfontUrl: '//at.alicdn.com/t/c/font_4511326_a182r7rksx5.js', token: { // 参见ts声明,demo 见文档,通过token 修改样式 //https://procomponents.ant.design/components/layout#%E9%80%9A%E8%BF%87-token-%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F diff --git a/react-ui/src/components/KFModal/index.less b/react-ui/src/components/KFModal/index.less index d2810cab..5e1f1239 100644 --- a/react-ui/src/components/KFModal/index.less +++ b/react-ui/src/components/KFModal/index.less @@ -17,14 +17,12 @@ margin-top: 40px; .ant-btn { - height: 42px; + height: 40px; padding: 0 30px; font-size: @font-size-content; border-radius: 10px; } .ant-btn-default { - color: @text-color; - background: rgba(22, 100, 255, 0.06); border-color: transparent; } .ant-btn + .ant-btn { diff --git a/react-ui/src/overrides.less b/react-ui/src/overrides.less index eb4722e9..4072038f 100644 --- a/react-ui/src/overrides.less +++ b/react-ui/src/overrides.less @@ -129,8 +129,6 @@ border-radius: 10px; } .ant-btn-default { - color: @text-color; - background: rgba(22, 100, 255, 0.06); border-color: transparent; } .ant-btn + .ant-btn { @@ -139,6 +137,7 @@ } } +// 表单类型为large时,font-size为15px .ant-form-large { .ant-form-item-label { label { diff --git a/react-ui/src/pages/Dataset/datasetIntro.jsx b/react-ui/src/pages/Dataset/datasetIntro.jsx index 91aee652..b43ddd32 100644 --- a/react-ui/src/pages/Dataset/datasetIntro.jsx +++ b/react-ui/src/pages/Dataset/datasetIntro.jsx @@ -9,10 +9,10 @@ import { } from '@/services/dataset/index.js'; import { downLoadZip } from '@/utils/downloadfile'; import { UploadOutlined } from '@ant-design/icons'; +import { useParams, useSearchParams } from '@umijs/max'; import { Button, Form, Input, Modal, Select, Table, Tabs, Upload, message } from 'antd'; import moment from 'moment'; import { useEffect, useRef, useState } from 'react'; -import { useParams } from 'react-router-dom'; import Styles from './index.less'; const { Search } = Input; const { TabPane } = Tabs; @@ -53,9 +53,11 @@ const Dataset = () => { const [version, setVersion] = useState(null); const [versionList, setVersionList] = useState([]); const locationParams = useParams(); //新版本获取路由参数接口 + 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); @@ -264,15 +266,17 @@ const Dataset = () => {
- + {!isPublic && ( + + )} + {!isPublic && ( + + )} +
*/} - ,
{item.description}
+
{item.description}
{ const routeToIntro = (e, record) => { e.stopPropagation(); console.log(record); - navgite({ pathname: `/dataset/model/${record.id}` }); + navgite({ pathname: `/dataset/model/${record.id}?isPublic=true` }); }; const onFinishFailed = (errorInfo) => { console.log('Failed:', errorInfo); @@ -233,28 +231,6 @@ const PublicData = () => { }} > {item.name} - { - e.stopPropagation(); - modalConfirm({ - title: '确定删除该条模型实例吗?', - onOk: () => { - deleteModel(item.id).then((ret) => { - if (ret.code === 200) { - message.success('删除成功'); - getModelLists(queryFlow); - } else { - message.error(ret.msg); - } - }); - }, - }); - }} - className={Styles.dropdown} - style={{ width: '17px', marginRight: '6px' }} - src={deleteIcon} - alt="" - />
{item.description}
{ const [form] = Form.useForm(); @@ -254,17 +256,10 @@ const Pipeline = () => { scroll={{ y: 'calc(100% - 55px)' }} />
- - - {dialogTitle} -
- } + { /> - +
); }; diff --git a/react-ui/src/pages/Pipeline/index.less b/react-ui/src/pages/Pipeline/index.less index bff7318c..102a37ef 100644 --- a/react-ui/src/pages/Pipeline/index.less +++ b/react-ui/src/pages/Pipeline/index.less @@ -8,60 +8,17 @@ padding-right: 30px; background-image: url(/assets/images/pipeline-back.png); background-size: 100% 100%; - } -.modal { - :global { - .ant-modal-content { - width: 825px; - padding: 20px 67px; - background-image: url(/assets/images/modal-back.png); - background-repeat: no-repeat; - background-position: top center; - background-size: 100%; - border-radius: 21px; - } - .ant-modal-header { - margin: 20px 0; - background-color: transparent; - } - .ant-input { - height: 40px; - border-color: #e6e6e6; - } - .ant-form-item .ant-form-item-label > label { - color: rgba(29, 29, 32, 0.8); - } - .ant-modal-footer { - display: flex; - justify-content: center; - margin: 40px 0 30px 0; - } - .ant-btn { - width: 110px; - height: 40px; - font-size: 18px; - background: rgba(22, 100, 255, 0.06); - border-color: transparent; - border-radius: 10px; - } - .ant-btn-primary { - background: #1664ff; - } - } -} -.PipelineBox{ +.PipelineBox { height: calc(100% - 20px); - .PipelineTable{ + .PipelineTable { height: calc(100% - 60px); - :global{ - .ant-table-wrapper .ant-table{ + :global { + .ant-table-wrapper .ant-table { // overflow-y: auto; height: calc(100% - 48px); } } } - } - From 2cd8e600aa24387b487823baa5416c4acb75ebcc Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Fri, 10 May 2024 09:32:52 +0800 Subject: [PATCH 03/14] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=AF=BC?= =?UTF-8?q?=E8=88=AA=E8=8F=9C=E5=8D=95=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/src/app.tsx | 36 ++++------- react-ui/src/overrides.less | 8 +++ .../components/TotalStatistics/index.less | 6 +- react-ui/src/pages/Workspace/index.less | 2 +- react-ui/src/styles/menu.less | 59 +++++++++++++++++++ react-ui/src/styles/theme.less | 1 - react-ui/src/utils/menuRender.tsx | 31 ++++++++++ 7 files changed, 110 insertions(+), 33 deletions(-) create mode 100644 react-ui/src/styles/menu.less create mode 100644 react-ui/src/utils/menuRender.tsx diff --git a/react-ui/src/app.tsx b/react-ui/src/app.tsx index a8ac8966..66005f50 100644 --- a/react-ui/src/app.tsx +++ b/react-ui/src/app.tsx @@ -17,9 +17,10 @@ import { patchRouteWithRemoteMenus, setRemoteMenu, } from './services/session'; +import './styles/menu.less'; export { requestConfig as request } from './requestConfig'; // const isDev = process.env.NODE_ENV === 'development'; - +import { menuItemRender } from '@/utils/menuRender'; /** * @see https://umijs.org/zh-CN/plugins/plugin-initial-state * */ @@ -139,10 +140,8 @@ export const layout: RuntimeConfig['layout'] = ({ initialState }) => { onClick: () => { // 点击菜单项,删除所有的页面 state 缓存 removeAllPageCacheState(); + // console.log('click menu'); }, - // onSelect: (e) => { - // console.log(e); - // }, }, ...initialState?.settings, token: { @@ -150,51 +149,36 @@ export const layout: RuntimeConfig['layout'] = ({ initialState }) => { colorTextMenu: themes['textColor'], colorTextMenuSelected: themes['primaryColor'], colorTextMenuActive: themes['primaryColor'], + colorTextMenuItemHover: themes['primaryColor'], colorBgMenuItemSelected: 'rgba(197, 232, 255, 0.8)', colorMenuBackground: themes['siderBGColor'], }, }, - // menuItemRender: (itemProps, defaultDom, props) => { - // console.log('menuItemProps', itemProps); - // console.log('defaultDom', defaultDom); - // console.log('props', props); - - // const { pathname } = window.location; - // const isSelected = pathname === itemProps.path; - - // // 根据菜单项的状态动态显示不同的 icon - // const icon = isSelected ? 'icon-developmentEnvironment-icon' : 'icon-kaifahuanjing'; - // return ( - // - // - // {itemProps.name} - // - // ); - // }, + menuItemRender: menuItemRender(false), + subMenuItemRender: menuItemRender(true), }; }; export const onRouteChange: RuntimeConfig['onRouteChange'] = async (e) => { const { location } = e; const menus = getRemoteMenu(); - console.log('onRouteChange', e); + // console.log('onRouteChange', e); if (menus === null && location.pathname !== PageEnum.LOGIN) { - console.log('refresh'); history.go(0); } }; export const patchRoutes: RuntimeConfig['patchRoutes'] = (e) => { - console.log('patchRoutes', e); + //console.log('patchRoutes', e); }; export const patchClientRoutes: RuntimeConfig['patchClientRoutes'] = (e) => { - console.log('patchClientRoutes', e); + //console.log('patchClientRoutes', e); patchRouteWithRemoteMenus(e.routes); }; export function render(oldRender: () => void) { - console.log('render'); + //console.log('render'); const token = getAccessToken(); if (!token || token?.length === 0) { oldRender(); diff --git a/react-ui/src/overrides.less b/react-ui/src/overrides.less index 4072038f..61102f12 100644 --- a/react-ui/src/overrides.less +++ b/react-ui/src/overrides.less @@ -145,3 +145,11 @@ } } } + +// 取消 hover 颜色变化 +.ant-menu .ant-menu-title-content { + transition: color 0s; + a { + transition: color 0s; + } +} diff --git a/react-ui/src/pages/Workspace/components/TotalStatistics/index.less b/react-ui/src/pages/Workspace/components/TotalStatistics/index.less index 23e4fec2..d8943328 100644 --- a/react-ui/src/pages/Workspace/components/TotalStatistics/index.less +++ b/react-ui/src/pages/Workspace/components/TotalStatistics/index.less @@ -26,11 +26,7 @@ left: 0; width: 79px; height: 6px; - background-color: linear-gradient( - 87.07deg, - rgba(22, 100, 255, 0.6) 0%, - rgba(22, 100, 255, 0) 100% - ); + background: linear-gradient(87.07deg, rgba(22, 100, 255, 0.6) 0%, rgba(22, 100, 255, 0) 100%); } &__count { diff --git a/react-ui/src/pages/Workspace/index.less b/react-ui/src/pages/Workspace/index.less index 30b1f1a5..f7f95a24 100644 --- a/react-ui/src/pages/Workspace/index.less +++ b/react-ui/src/pages/Workspace/index.less @@ -2,7 +2,7 @@ height: 100%; padding: 20px 30px 10px; overflow-y: auto; - background-color: linear-gradient(#ecf2fe, #f9fafb); + background: linear-gradient(#ecf2fe, #f9fafb); &__overview { gap: 15px; diff --git a/react-ui/src/styles/menu.less b/react-ui/src/styles/menu.less new file mode 100644 index 00000000..29e3ed61 --- /dev/null +++ b/react-ui/src/styles/menu.less @@ -0,0 +1,59 @@ +.ant-menu-item, +.ant-menu-submenu { + .kf-menu-item { + display: flex; + align-items: center; + justify-content: flex-start; + font-size: 16px; + + .anticon.kf-menu-item__default-icon { + display: inline !important; + opacity: 1; + } + + .anticon.kf-menu-item__active-icon { + display: none !important; + margin-left: 0 !important; + } + + &:hover { + .anticon.kf-menu-item__default-icon { + display: none !important; + } + .anticon.kf-menu-item__active-icon { + display: inline !important; + opacity: 1; + } + } + } +} + +.ant-menu-item.ant-menu-item-selected, +.ant-menu-submenu.ant-menu-submenu-selected { + .kf-menu-item { + .anticon.kf-menu-item__default-icon { + display: none !important; + } + + .anticon.kf-menu-item__active-icon { + display: inline !important; + opacity: 1; + } + } +} + +.ant-pro-base-menu-vertical-collapsed { + .kf-menu-item { + justify-content: center; + + .kf-menu-item__name { + display: none !important; + } + } +} + +.ant-menu-submenu { + .ant-menu-submenu-title:hover { + color: #1664ff !important; + } +} diff --git a/react-ui/src/styles/theme.less b/react-ui/src/styles/theme.less index bb9f34aa..d97b3ef8 100644 --- a/react-ui/src/styles/theme.less +++ b/react-ui/src/styles/theme.less @@ -44,7 +44,6 @@ @red: red(@color); @green: green(@color); @blue: blue(@color); - @result: rgba(@red, @green, @blue, @alpha); } diff --git a/react-ui/src/utils/menuRender.tsx b/react-ui/src/utils/menuRender.tsx new file mode 100644 index 00000000..fc0b70dd --- /dev/null +++ b/react-ui/src/utils/menuRender.tsx @@ -0,0 +1,31 @@ +import KFIcon from '@/components/KFIcon'; +import { MenuDataItem } from '@ant-design/pro-components'; +import { Link } from '@umijs/max'; + +export const menuItemRender = (isSubMenu: boolean) => { + return (item: MenuDataItem) => { + const defaultIcon: string = item.icon as string; + const activeIcon = defaultIcon + '-active'; + const hasParent = item.pro_layout_parentKeys?.length > 0; + const childen = ( + <> + {!hasParent && defaultIcon && ( + <> + + + + )} + {item.name} + + ); + if (isSubMenu) { + return
{childen}
; + } else { + return ( + + {childen} + + ); + } + }; +}; From ba42d808631c593d828640594c83d49a476aa3d9 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Sat, 11 May 2024 15:14:57 +0800 Subject: [PATCH 04/14] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E5=92=8C=E6=95=B0=E6=8D=AE=E9=9B=86=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/src/components/PageTitle/index.less | 2 +- react-ui/src/hooks/index.ts | 10 + react-ui/src/iconfont/iconfont.js | 2 +- .../components/AddDatasetModal/index.less | 9 + .../components/AddDatasetModal/index.tsx | 202 +++++++ .../components/CategoryItem/index.less | 41 ++ .../Dataset/components/CategoryItem/index.tsx | 37 ++ .../components/CategoryList/index.less | 22 + .../Dataset/components/CategoryList/index.tsx | 71 +++ .../components/ResourceList/index.less | 39 ++ .../Dataset/components/ResourceList/index.tsx | 210 +++++++ .../components/ResourcePage/index.less | 8 + .../Dataset/components/ResourcePage/index.tsx | 113 ++++ .../Dataset/components/Resourcetem/index.less | 61 ++ .../Dataset/components/Resourcetem/index.tsx | 54 ++ react-ui/src/pages/Dataset/datasetIntro.jsx | 42 +- react-ui/src/pages/Dataset/index.jsx | 93 +--- react-ui/src/pages/Dataset/index.less | 264 +-------- react-ui/src/pages/Dataset/personalData.jsx | 479 ---------------- react-ui/src/pages/Dataset/publicData.jsx | 260 --------- react-ui/src/pages/Dataset/type.tsx | 118 ++++ .../experimentText/addExperimentModal.tsx | 1 - react-ui/src/pages/Mirror/list.less | 2 +- react-ui/src/pages/Mirror/list.tsx | 7 +- .../Model/components/AddModelModal/index.less | 4 + .../Model/components/AddModelModal/index.tsx | 180 ++++++ react-ui/src/pages/Model/index.jsx | 92 +-- react-ui/src/pages/Model/index.less | 249 --------- react-ui/src/pages/Model/modelIntro.jsx | 40 +- react-ui/src/pages/Model/personalData.jsx | 525 ------------------ react-ui/src/pages/Model/publicData.jsx | 360 ------------ .../ResourceSelectorModal/index.tsx | 4 - .../src/pages/Pipeline/editPipeline/props.jsx | 60 +- react-ui/src/pages/Pipeline/index.jsx | 2 +- .../components/ExperimentChart/index.tsx | 11 +- .../components/ExperimentTable/index.less | 6 +- react-ui/src/requestConfig.ts | 2 +- react-ui/src/styles/theme.less | 16 + react-ui/src/utils/ui.tsx | 28 +- 39 files changed, 1306 insertions(+), 2420 deletions(-) create mode 100644 react-ui/src/pages/Dataset/components/AddDatasetModal/index.less create mode 100644 react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx create mode 100644 react-ui/src/pages/Dataset/components/CategoryItem/index.less create mode 100644 react-ui/src/pages/Dataset/components/CategoryItem/index.tsx create mode 100644 react-ui/src/pages/Dataset/components/CategoryList/index.less create mode 100644 react-ui/src/pages/Dataset/components/CategoryList/index.tsx create mode 100644 react-ui/src/pages/Dataset/components/ResourceList/index.less create mode 100644 react-ui/src/pages/Dataset/components/ResourceList/index.tsx create mode 100644 react-ui/src/pages/Dataset/components/ResourcePage/index.less create mode 100644 react-ui/src/pages/Dataset/components/ResourcePage/index.tsx create mode 100644 react-ui/src/pages/Dataset/components/Resourcetem/index.less create mode 100644 react-ui/src/pages/Dataset/components/Resourcetem/index.tsx delete mode 100644 react-ui/src/pages/Dataset/personalData.jsx delete mode 100644 react-ui/src/pages/Dataset/publicData.jsx create mode 100644 react-ui/src/pages/Dataset/type.tsx create mode 100644 react-ui/src/pages/Model/components/AddModelModal/index.less create mode 100644 react-ui/src/pages/Model/components/AddModelModal/index.tsx delete mode 100644 react-ui/src/pages/Model/personalData.jsx delete mode 100644 react-ui/src/pages/Model/publicData.jsx diff --git a/react-ui/src/components/PageTitle/index.less b/react-ui/src/components/PageTitle/index.less index 80d18169..8ab36193 100644 --- a/react-ui/src/components/PageTitle/index.less +++ b/react-ui/src/components/PageTitle/index.less @@ -3,5 +3,5 @@ align-items: center; height: 50px; padding-left: 30px; - background-image: url('../../assets/img/page-title-bg.png'); + background-image: url(@/assets/img/page-title-bg.png); } diff --git a/react-ui/src/hooks/index.ts b/react-ui/src/hooks/index.ts index 1d56a24d..4dccabb7 100644 --- a/react-ui/src/hooks/index.ts +++ b/react-ui/src/hooks/index.ts @@ -126,3 +126,13 @@ export const useResetFormOnCloseModal = (form: FormInstance, open: boolean) => { } }, [form, prevOpen, open]); }; + +export const useInputModel = (initialValue: T) => { + const [value, setValue] = useState(initialValue); + + const updateValue = useCallback((e: any) => { + setValue(e.target?.value); + }, []); + + return [value, updateValue]; +}; diff --git a/react-ui/src/iconfont/iconfont.js b/react-ui/src/iconfont/iconfont.js index 77f8486f..80008ba1 100644 --- a/react-ui/src/iconfont/iconfont.js +++ b/react-ui/src/iconfont/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_4511447='',function(t){var a=(a=document.getElementsByTagName("script"))[a.length-1],h=a.getAttribute("data-injectcss"),a=a.getAttribute("data-disable-injectsvg");if(!a){var l,i,v,o,z,m=function(a,h){h.parentNode.insertBefore(a,h)};if(h&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}l=function(){var a,h=document.createElement("div");h.innerHTML=t._iconfont_svg_string_4511447,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?m(h,a.firstChild):a.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),l()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(v=l,o=t.document,z=!1,p(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,n())})}function n(){z||(z=!0,v())}function p(){try{o.documentElement.doScroll("left")}catch(a){return void setTimeout(p,50)}n()}}(window); \ No newline at end of file +window._iconfont_svg_string_4511447='',function(t){var a=(a=document.getElementsByTagName("script"))[a.length-1],h=a.getAttribute("data-injectcss"),a=a.getAttribute("data-disable-injectsvg");if(!a){var v,l,i,z,o,m=function(a,h){h.parentNode.insertBefore(a,h)};if(h&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}v=function(){var a,h=document.createElement("div");h.innerHTML=t._iconfont_svg_string_4511447,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?m(h,a.firstChild):a.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(v,0):(l=function(){document.removeEventListener("DOMContentLoaded",l,!1),v()},document.addEventListener("DOMContentLoaded",l,!1)):document.attachEvent&&(i=v,z=t.document,o=!1,n(),z.onreadystatechange=function(){"complete"==z.readyState&&(z.onreadystatechange=null,p())})}function p(){o||(o=!0,i())}function n(){try{z.documentElement.doScroll("left")}catch(a){return void setTimeout(n,50)}p()}}(window); \ No newline at end of file diff --git a/react-ui/src/pages/Dataset/components/AddDatasetModal/index.less b/react-ui/src/pages/Dataset/components/AddDatasetModal/index.less new file mode 100644 index 00000000..529521af --- /dev/null +++ b/react-ui/src/pages/Dataset/components/AddDatasetModal/index.less @@ -0,0 +1,9 @@ +.upload-tip { + margin-top: 5px; + color: @error-color; +} + +.upload-button { + height: 48px; + 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 new file mode 100644 index 00000000..c83d5143 --- /dev/null +++ b/react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx @@ -0,0 +1,202 @@ +import { getAccessToken } from '@/access'; +import { DictValueEnumObj } from '@/components/DictTag'; +import KFIcon from '@/components/KFIcon'; +import KFModal from '@/components/KFModal'; +import { addDatesetAndVesion } from '@/services/dataset/index.js'; +import { getDictSelectOption } from '@/services/system/dict'; +import { to } from '@/utils/promise'; +import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; +import { + Button, + Form, + Input, + Radio, + Select, + Upload, + UploadFile, + message, + type ModalProps, + type UploadProps, +} from 'antd'; +import { omit } from 'lodash'; +import { useEffect, useState } from 'react'; +import { CategoryData } from '../../type'; +import styles from './index.less'; + +interface AddDatasetModalProps extends ModalProps { + typeList: CategoryData[]; + tagList: CategoryData[]; + onOk: () => void; +} + +function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalProps) { + const [uuid] = useState(Date.now()); + const [clusterOptions, setClusterOptions] = useState([]); + + useEffect(() => { + getClusterOptions(); + }, []); + + // 上传组件参数 + const uploadProps: UploadProps = { + action: '/api/mmp/dataset/upload', + headers: { + Authorization: getAccessToken() || '', + }, + defaultFileList: [], + }; + + // 获取集群版本数据 + const getClusterOptions = async () => { + const [res] = await to(getDictSelectOption('available_cluster')); + if (res) { + setClusterOptions(res); + } + }; + + // 上传请求 + const createDataset = async (params: any) => { + const [res] = await to(addDatesetAndVesion(params)); + if (res) { + message.success('创建成功'); + onOk?.(); + } + }; + + // 提交 + const onFinish = (formData: any) => { + const fileList: UploadFile[] = formData['fileList'] ?? []; + if (validateUploadFiles(fileList)) { + const params = { + ...omit(formData, ['fileList']), + dataset_version_vos: fileList.map((item) => { + const data = item.response?.data?.[0] ?? {}; + return { + file_name: data.fileName, + file_size: data.fileSize, + url: data.url, + }; + }), + }; + createDataset(params); + } + }; + + return ( + +
+ + + + + + + + + + + - - - - - - { - return { value: item.id, label: item.name }; - })} - /> - - - - - - - 仅自己可见 - 工作空间可见 - - - - - -
只允许上传.zip,.tgz格式文件
-
-
-
- - - ); -}); -export default PublicData; diff --git a/react-ui/src/pages/Dataset/publicData.jsx b/react-ui/src/pages/Dataset/publicData.jsx deleted file mode 100644 index 8e97a936..00000000 --- a/react-ui/src/pages/Dataset/publicData.jsx +++ /dev/null @@ -1,260 +0,0 @@ -import clock from '@/assets/img/clock.png'; -import creatByImg from '@/assets/img/creatBy.png'; -import { getAssetIcon, getDatasetList } from '@/services/dataset/index.js'; -import { Form, Input, Pagination } from 'antd'; -import moment from 'moment'; -import { useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import Styles from './index.less'; -const { Search } = Input; -const leftdataList = [1, 2, 3]; - -const PublicData = () => { - const [queryFlow, setQueryFlow] = useState({ - page: 0, - size: 10, - name: null, - available_range: 1, - }); - const [iconParams, setIconParams] = useState({ - name: null, - page: 0, - size: 10000, - }); - const navgite = useNavigate(); - const [datasetTypeList, setDatasetTypeList] = useState([]); - const [datasetDirectionList, setDatasetDirectionList] = useState([]); - const [activeType, setActiveType] = useState(null); - const [activeTag, setActiveTag] = useState(null); - const [isModalOpen, setIsModalOpen] = useState(false); - const [datasetList, setDatasetList] = useState([]); - const [total, setTotal] = useState(0); - const [form] = Form.useForm(); - const [dialogTitle, setDialogTitle] = useState('新建数据'); - const getDatasetlist = (queryFlow) => { - getDatasetList(queryFlow).then((ret) => { - console.log(ret); - if (ret.code == 200) { - setDatasetList(ret.data.content); - setTotal(ret.data.totalElements); - } - }); - }; - const onSearch = (values) => { - console.log(values); - getAssetIconList({ ...iconParams, name: values }); - }; - const getAssetIconList = (params) => { - getAssetIcon(params).then((ret) => { - console.log(ret); - if (ret.code == 200 && ret.data.content && ret.data.content.length > 0) { - setDatasetTypeList(ret.data.content.filter((item) => item.category_id == 1)); - setDatasetDirectionList(ret.data.content.filter((item) => item.category_id == 2)); - } else { - setDatasetTypeList([]); - setDatasetDirectionList([]); - } - }); - }; - const nameSearch = (values) => { - console.log(values); - getDatasetlist({ ...queryFlow, name: values }); - }; - const showModal = () => { - form.resetFields(); - setDialogTitle('新建数据集'); - setIsModalOpen(true); - }; - const handleOk = () => { - console.log(1111); - setIsModalOpen(false); - }; - const handleCancel = () => { - setIsModalOpen(false); - }; - const chooseDatasetType = (val, item) => { - console.log(val, item); - if (item.id == queryFlow.data_type) { - setActiveType(''); - setQueryFlow({ ...queryFlow, data_type: null }); - getDatasetlist({ ...queryFlow, data_type: null }); - } else { - setActiveType(item.id); - setQueryFlow({ ...queryFlow, data_type: item.id }); - getDatasetlist({ ...queryFlow, data_type: item.id }); - } - // setQueryFlow({...queryFlow,data_type:item.path},()=>{ - // getDatasetlist() - // }) - }; - const chooseDatasetTag = (val, item) => { - console.log(val, item); - if (item.id == queryFlow.data_tag) { - setActiveTag(''); - setQueryFlow({ ...queryFlow, data_tag: null }); - getDatasetlist({ ...queryFlow, data_tag: null }); - } else { - setActiveTag(item.id); - setQueryFlow({ ...queryFlow, data_tag: item.id }); - getDatasetlist({ ...queryFlow, data_tag: item.id }); - } - // setQueryFlow({...queryFlow,data_type:item.path},()=>{ - // getDatasetlist() - // }) - }; - - const routeToIntro = (e, record) => { - e.stopPropagation(); - console.log(record); - navgite({ pathname: `/dataset/dataset/${record.id}?isPublic=true` }); - }; - const onFinishFailed = (errorInfo) => { - console.log('Failed:', errorInfo); - }; - const onPageChange = (pageNum, pageSize) => { - console.log(pageNum, pageSize); - setQueryFlow({ ...queryFlow, page: pageNum - 1, size: pageSize }); - getDatasetlist({ ...queryFlow, page: pageNum - 1, size: pageSize }); - }; - useEffect(() => { - getAssetIconList(iconParams); - getDatasetlist(queryFlow); - return () => {}; - }, []); - return ( - <> -
-
-
- -
分类
-
- {datasetTypeList && datasetTypeList.length > 0 - ? datasetTypeList.map((item) => { - return ( -
-
{ - chooseDatasetType(e, item); - }} - > - - - {item.name} -
-
- ); - }) - : ''} -
-
研究方向/应用领域
-
- {datasetDirectionList && datasetDirectionList.length > 0 - ? datasetDirectionList.map((item) => { - return ( -
-
{ - chooseDatasetTag(e, item); - }} - > - - - {item.name} -
-
- ); - }) - : ''} -
-
-
-
-
- 数据总数:{total}个 -
- -
-
-
- {datasetList && datasetList.length > 0 - ? datasetList.map((item) => { - return ( -
routeToIntro(e, item)}> - {item.name} -
{item.description}
-
- - {item.create_by} -
-
- - 最近更新: {moment(item.update_time).format('YYYY-MM-DD')} -
-
- ); - }) - : ''} - {/* Demo */} -
- -
-
- - ); -}; -export default PublicData; diff --git a/react-ui/src/pages/Dataset/type.tsx b/react-ui/src/pages/Dataset/type.tsx new file mode 100644 index 00000000..91808ea2 --- /dev/null +++ b/react-ui/src/pages/Dataset/type.tsx @@ -0,0 +1,118 @@ +import KFIcon from '@/components/KFIcon'; +import { CommonTabKeys } from '@/enums'; +import { + deleteDataset, + deleteModel, + getDatasetList, + getDatasetVersionIdList, + getDatasetVersionsById, + getModelList, + getModelVersionIdList, + getModelVersionsById, +} from '@/services/dataset/index.js'; +import type { TabsProps } from 'antd'; + +export enum ResourceType { + Model = 'Model', // 模型 + Dataset = 'Dataset', // 数据集 +} + +type ResourceTypeKeys = keyof typeof ResourceType; +type ResourceTypeValues = (typeof ResourceType)[ResourceTypeKeys]; + +export type ResourceTypeInfo = { + getList: (params: any) => Promise; + getVersions: (params: any) => Promise; + getFiles: (params: any) => Promise; + deleteRecord: (params: any) => Promise; + name: string; + typeParamKey: string; + tagParamKey: string; + fileReqParamKey: 'models_id' | 'dataset_id'; + tabItems: TabsProps['items']; + typeTitle: string; + tagTitle: string; + typeValue: number; // 从 getAssetIcon 接口获取特定值的数据为 type 分类 (category_id === typeValue) + tagValue: number; // 从 getAssetIcon 接口获取特定值的数据为 tag 分类(category_id === tagValue) + iconPathPrefix: string; // 图标路径前缀 + deleteModalTitle: string; // 删除弹框的title + addBtnTitle: string; // 新增按钮的title +}; + +export const resourceConfig: Record = { + [ResourceType.Dataset]: { + getList: getDatasetList, + getVersions: getDatasetVersionsById, + getFiles: getDatasetVersionIdList, + deleteRecord: deleteDataset, + name: '数据集', + typeParamKey: 'data_type', + tagParamKey: 'data_tag', + fileReqParamKey: 'dataset_id', + tabItems: [ + { + key: CommonTabKeys.Public, + label: '数据广场', + icon: , + }, + { + key: CommonTabKeys.Private, + label: '个人数据', + icon: , + }, + ], + typeTitle: '分类', + tagTitle: '研究方向/应用领域', + typeValue: 1, + tagValue: 2, + iconPathPrefix: 'dataset', + deleteModalTitle: '确定删除该条数据集实例吗?', + addBtnTitle: '新建数据集', + }, + [ResourceType.Model]: { + getList: getModelList, + getVersions: getModelVersionsById, + getFiles: getModelVersionIdList, + deleteRecord: deleteModel, + name: '模型', + typeParamKey: 'model_type', + tagParamKey: 'model_tag', + fileReqParamKey: 'models_id', + tabItems: [ + { + key: CommonTabKeys.Public, + label: '模型广场', + icon: , + }, + { + key: CommonTabKeys.Private, + label: '个人模型', + icon: , + }, + ], + typeTitle: '模型框架', + tagTitle: '模型能力', + typeValue: 3, + tagValue: 4, + iconPathPrefix: 'model', + deleteModalTitle: '确定删除该条模型实例吗?', + addBtnTitle: '新建模型', + }, +}; + +// 分类数据 +export type CategoryData = { + id: number; + category_id: number; + name: string; + path: string; +}; + +// 数据类型 +export type ResourceData = { + id: number; + name: string; + description: string; + create_by: string; + update_time: string; +}; diff --git a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx index 5c853c42..f5b2bfc4 100644 --- a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx +++ b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx @@ -132,7 +132,6 @@ function AddExperimentModal({ {...layout} labelAlign="left" labelWrap - size="large" >
- +
diff --git a/react-ui/src/pages/Model/components/AddModelModal/index.less b/react-ui/src/pages/Model/components/AddModelModal/index.less new file mode 100644 index 00000000..bb520221 --- /dev/null +++ b/react-ui/src/pages/Model/components/AddModelModal/index.less @@ -0,0 +1,4 @@ +.upload-button { + height: 48px; + font-size: 15px; +} diff --git a/react-ui/src/pages/Model/components/AddModelModal/index.tsx b/react-ui/src/pages/Model/components/AddModelModal/index.tsx new file mode 100644 index 00000000..e04b1ba1 --- /dev/null +++ b/react-ui/src/pages/Model/components/AddModelModal/index.tsx @@ -0,0 +1,180 @@ +import { getAccessToken } from '@/access'; +import KFIcon from '@/components/KFIcon'; +import KFModal from '@/components/KFModal'; +import { CategoryData } from '@/pages/Dataset/type'; +import { addModel } from '@/services/dataset/index.js'; +import { to } from '@/utils/promise'; +import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; +import { + Button, + Form, + Input, + Select, + Upload, + UploadFile, + message, + type ModalProps, + type UploadProps, +} from 'antd'; +import { omit } from 'lodash'; +import { useState } from 'react'; +import styles from './index.less'; + +interface AddModelModalProps extends ModalProps { + typeList: CategoryData[]; + tagList: CategoryData[]; + onOk: () => void; +} + +function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) { + const [uuid] = useState(Date.now()); + // 上传组件参数 + const uploadProps: UploadProps = { + action: '/api/mmp/models/upload', + headers: { + Authorization: getAccessToken() || '', + }, + defaultFileList: [], + }; + + // 上传请求 + const createModel = async (params: any) => { + const [res] = await to(addModel(params)); + if (res) { + message.success('创建成功'); + onOk?.(); + } + }; + + // 提交 + const onFinish = (formData: any) => { + const fileList: UploadFile[] = formData['fileList'] ?? []; + if (validateUploadFiles(fileList)) { + const params = { + ...omit(formData, ['fileList']), + models_version_vos: fileList.map((item) => { + const data = item.response?.data?.[0] ?? {}; + return { + file_name: data.fileName, + file_size: data.fileSize, + url: data.url, + }; + }), + }; + createModel(params); + } + }; + + return ( + +
+ + + + + + + + + + + {/* + + 仅自己可见 + 工作空间可见 + + */} + + + + + + + + +
+
+ ); +} + +export default AddModelModal; diff --git a/react-ui/src/pages/Model/index.jsx b/react-ui/src/pages/Model/index.jsx index 310823f4..f8add51f 100644 --- a/react-ui/src/pages/Model/index.jsx +++ b/react-ui/src/pages/Model/index.jsx @@ -1,89 +1,7 @@ -import { Form, Input, Tabs } from 'antd'; -import { useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import Styles from './index.less'; -import PersonalData from './personalData'; -import PublicData from './publicData'; -// import {getModelList} from '@/services/dataset/index.js' -const { Search } = Input; -const { TabPane } = Tabs; -const leftdataList = [1, 2, 3]; +import ResourcePage from '@/pages/Dataset/components/ResourcePage'; +import { ResourceType } from '@/pages/Dataset/type'; -const Dataset = () => { - const [queryFlow, setQueryFlow] = useState({ - page: 0, - size: 10, - name: null, - }); - const navgite = useNavigate(); - const [isModalOpen, setIsModalOpen] = useState(false); - const [datasetList, setDatasetList] = useState([]); - const [total, setTotal] = useState(0); - const [form] = Form.useForm(); - const [dialogTitle, setDialogTitle] = useState('新建数据'); - // const getModelLists=()=>{ - // getModelList(queryFlow).then(ret=>{ - // console.log(ret); - // if(ret.code==200){ - // setDatasetList(ret.data.content) - // setTotal(ret.data.totalElements) - // } - // }) - // } - - const showModal = () => { - form.resetFields(); - setDialogTitle('新建数据集'); - setIsModalOpen(true); - }; - const handleOk = () => { - console.log(1111); - setIsModalOpen(false); - }; - const handleCancel = () => { - setIsModalOpen(false); - }; - const onFinish = (values) => {}; - const routeToIntro = (e, record) => { - e.stopPropagation(); - navgite({ pathname: '/dataset/dataset' }); - }; - const onFinishFailed = (errorInfo) => { - console.log('Failed:', errorInfo); - }; - useEffect(() => { - return () => {}; - }, []); - return ( -
-
-
- - - - -
-
- ); +const ModelPage = () => { + return ; }; -export default Dataset; +export default ModelPage; diff --git a/react-ui/src/pages/Model/index.less b/react-ui/src/pages/Model/index.less index 4442e66a..596c64d7 100644 --- a/react-ui/src/pages/Model/index.less +++ b/react-ui/src/pages/Model/index.less @@ -1,13 +1,3 @@ -.datasetTopBox { - display: flex; - align-items: center; - width: 100%; - height: 49px; - padding: 0 30px; - padding-right: 30px; - background-image: url(/assets/images/pipeline-back.png); - background-size: 100% 100%; -} .datasetIntroTopBox { display: flex; flex-direction: column; @@ -78,250 +68,11 @@ } } } -.datasetAllBox { - :global { - .ant-tabs-nav .ant-tabs-nav-wrap { - margin: -48px 0 0 30px; - } - } -} .plusButton { margin: 0 18px 0 20px; } -.datasetCneterBox { - display: flex; - justify-content: space-between; - width: 100%; - height: 87.5vh; - - .datasetCneterLeftBox { - width: 340px; - height: 100%; - margin-right: 10px; - padding-top: 15px; - background: #ffffff; - box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09); - .custTab { - display: flex; - height: 32px; - border-bottom: 1px solid #e0eaff; - .tabItem { - width: 52px; - height: 100%; - color: #808080; - font-size: 15px; - text-align: center; - cursor: pointer; - } - } - .leftContentBox { - max-height: 80vh; - padding: 15px 20px; - overflow-x: hidden; - overflow-y: auto; - .itemTitle { - margin-bottom: 15px; - color: #1d1d20; - font-size: 14px; - } - .itemBox { - display: flex; - flex-wrap: wrap; - align-content: start; - width: 110%; - .messageBox { - display: flex; - flex-direction: column; - align-items: center; - justify-content: space-between; - width: 92px; - height: 62px; - margin: 0 12px 20px 0; - padding: 11px 0px 7px 0px; - color: #1d1d20; - font-size: 12px; - border: 1px solid; - border-color: rgba(22, 100, 255, 0.05); - border-radius: 4px; - cursor: pointer; - .ptIcon { - display: block; - } - .hoverIcon { - display: none; - } - .messageText { - width: 65px; - overflow: hidden; - white-space: nowrap; - text-align: center; - text-overflow: ellipsis; - transition: all 0.2s; - } - } - .messageBox:hover { - background: rgba(22, 100, 255, 0.03); - border: 1px solid; - border-color: #1664ff; - .ptIcon { - display: none; - } - .hoverIcon { - display: block; - } - } - .active { - background: rgba(22, 100, 255, 0.03) !important; - border: 1px solid !important; - border-color: #1664ff !important; - .ptIcon { - display: none !important; - } - .hoverIcon { - display: block !important; - } - } - } - } - } - .datasetCneterRightBox { - display: flex; - flex: 1; - flex-direction: column; - height: 100%; - padding: 22px 30px 26px 30px; - overflow-y: auto; - background: #ffffff; - box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09); - .dataSource { - display: flex; - align-items: center; - justify-content: space-between; - height: 32px; - margin-bottom: 30px; - color: rgba(29, 29, 32, 0.8); - font-size: 15px; - } - .dataContent { - display: flex; - flex: 1; - flex-wrap: wrap; - align-content: flex-start; - width: 100%; - .dataItem { - position: relative; - width: 23.8%; - height: 164px; - margin: 0 20px 25px 0; - background: #ffffff; - border: 1px solid; - border-color: #eaeaea; - border-radius: 4px; - cursor: pointer; - .dropdown { - position: absolute; - top: 15px; - right: 20px; - } - .itemText { - position: absolute; - top: 20px; - left: 20px; - height: 6px; - color: #1d1d20; - font-size: 16px; - font-family: 'Alibaba'; - line-height: 0px; - background: linear-gradient( - to right, - rgba(22, 100, 255, 0.3) 0, - rgba(22, 100, 255, 0) 100% - ); - } - .itemDescripition { - position: absolute; - top: 57px; - left: 20px; - display: -webkit-box; - padding-right: 28px; - overflow: hidden; - color: #575757; - font-size: 14px; - word-break: break-all; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - } - .itemTime { - position: absolute; - bottom: 22px; - left: 20px; - display: flex; - align-items: center; - color: #808080; - font-size: 13px; - } - .itemIcon { - position: absolute; - right: 20px; - bottom: 22px; - display: flex; - align-items: center; - color: #808080; - font-size: 13px; - } - } - .dataItem:hover { - border-color: #1664ff; - box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1); - } - .dataItem:hover .itemText { - color: #1664ff; - } - } - } -} .tipContent { margin-top: 5px; color: #c73131; } -.modal { - :global { - .ant-modal-content { - width: 825px; - padding: 20px 67px; - background-image: url(/assets/images/modal-back.png); - background-repeat: no-repeat; - background-position: top center; - background-size: 100%; - border-radius: 21px; - } - .ant-modal-header { - margin: 20px 0; - background-color: transparent; - } - .ant-input { - height: 40px; - border-color: #e6e6e6; - } - .ant-form-item .ant-form-item-label > label { - color: rgba(29, 29, 32, 0.8); - } - .ant-modal-footer { - display: flex; - justify-content: center; - margin: 40px 0 30px 0; - } - .ant-btn { - width: 110px; - height: 42px; - font-size: 18px; - background: rgba(22, 100, 255, 0.06); - border-color: transparent; - border-radius: 10px; - } - .ant-btn-primary { - background: #1664ff; - } - } -} diff --git a/react-ui/src/pages/Model/modelIntro.jsx b/react-ui/src/pages/Model/modelIntro.jsx index dfc76e53..d978f15e 100644 --- a/react-ui/src/pages/Model/modelIntro.jsx +++ b/react-ui/src/pages/Model/modelIntro.jsx @@ -1,5 +1,6 @@ import { getAccessToken } from '@/access'; import KFIcon from '@/components/KFIcon'; +import KFModal from '@/components/KFModal'; import { addModelsVersionDetail, deleteModelVersion, @@ -8,9 +9,10 @@ import { getModelVersionsById, } from '@/services/dataset/index.js'; import { downLoadZip } from '@/utils/downloadfile'; +import { modalConfirm } from '@/utils/ui'; import { UploadOutlined } from '@ant-design/icons'; import { useParams, useSearchParams } from '@umijs/max'; -import { Button, Form, Input, Modal, Select, Table, Tabs, Upload, message } from 'antd'; +import { Button, Form, Input, Select, Table, Tabs, Upload, message } from 'antd'; import moment from 'moment'; import { useEffect, useRef, useState } from 'react'; import Styles from './index.less'; @@ -78,6 +80,9 @@ const Dataset = () => { ); setVersion(ret.data[0]); getModelVersions({ version: ret.data[0], models_id: locationParams.id }); + } else { + setVersion(null); + setWordList([]); } }); }; @@ -98,18 +103,9 @@ const Dataset = () => { setIsModalOpen(false); }; const deleteDataset = () => { - Modal.confirm({ - title: ( -
- -
删除后,该模型版本将不可恢复
-
- ), - content:
是否确认删除?
, + modalConfirm({ + title: '删除后,该版本将不可恢复', + content: '是否确认删除?', okText: '确认', cancelText: '取消', @@ -298,19 +294,11 @@ const Dataset = () => {
- - - {dialogTitle} -
- } + {
- +
); }; diff --git a/react-ui/src/pages/Model/personalData.jsx b/react-ui/src/pages/Model/personalData.jsx deleted file mode 100644 index e44816d7..00000000 --- a/react-ui/src/pages/Model/personalData.jsx +++ /dev/null @@ -1,525 +0,0 @@ -import { getAccessToken } from '@/access'; -import clock from '@/assets/img/clock.png'; -import creatByImg from '@/assets/img/creatBy.png'; -import deleteIcon from '@/assets/img/delete-icon.png'; -import KFIcon from '@/components/KFIcon'; -import { addModel, deleteModel, getAssetIcon, getModelList } from '@/services/dataset/index.js'; -import { modalConfirm } from '@/utils/ui'; -import { UploadOutlined } from '@ant-design/icons'; -import { Button, Form, Input, Modal, Pagination, Select, Upload, message } from 'antd'; -import moment from 'moment'; -import { useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import Styles from './index.less'; -const { Search } = Input; - -const leftdataList = [1, 2, 3]; - -const PublicData = () => { - 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); - form.setFieldsValue({ - models_version_vos: fileList.map((item) => { - const data = item.response.data[0]; - return { - file_name: data.fileName, - file_size: data.fileSize, - url: data.url, - }; - }), - }); - } - }, - defaultFileList: [], - }; - const [queryFlow, setQueryFlow] = useState({ - page: 0, - size: 20, - name: null, - available_range: 0, - }); - const navgite = useNavigate(); - const [iconParams, setIconParams] = useState({ - name: null, - page: 0, - size: 10000, - }); - const [activeType, setActiveType] = useState(null); - const [activeTag, setActiveTag] = useState(null); - const [modelTypeList, setmodelTypeList] = useState([]); - const [modelDirectionList, setmodelDirectionList] = useState([]); - const [isModalOpen, setIsModalOpen] = useState(false); - const [datasetList, setDatasetList] = useState([]); - const [total, setTotal] = useState(0); - const [form] = Form.useForm(); - const [dialogTitle, setDialogTitle] = useState('新建模型'); - const [uuid, setUuid] = useState(Date.now()); - const getModelLists = (queryFlow) => { - getModelList(queryFlow).then((ret) => { - console.log(ret); - if (ret.code == 200) { - setDatasetList(ret.data.content); - setTotal(ret.data.totalElements); - } - }); - }; - - const showModal = () => { - form.resetFields(); - setDialogTitle('新建模型'); - setUuid(Date.now()); - setIsModalOpen(true); - }; - const getAssetIconList = (params) => { - getAssetIcon(params).then((ret) => { - console.log(ret); - if (ret.code == 200 && ret.data.content && ret.data.content.length > 0) { - setmodelTypeList(ret.data.content.filter((item) => item.category_id == 3)); - setmodelDirectionList(ret.data.content.filter((item) => item.category_id == 4)); - } else { - setmodelTypeList([]); - setmodelDirectionList([]); - } - }); - }; - const onSearch = (values) => { - console.log(values); - getAssetIconList({ ...iconParams, name: values }); - }; - const nameSearch = (values) => { - console.log(values); - getModelLists({ ...queryFlow, name: values }); - }; - const handleOk = () => { - console.log(1111); - setIsModalOpen(false); - }; - const handleCancel = () => { - setIsModalOpen(false); - }; - const onFinish = (values) => { - const params = { - ...values, - available_range: 0, - }; - addModel(values).then((ret) => { - console.log(ret); - getModelLists(queryFlow); - setIsModalOpen(false); - }); - }; - - const chooseModelType = (val, item) => { - console.log(val, item); - if (item.id == queryFlow.model_type) { - setActiveType(''); - setQueryFlow({ ...queryFlow, model_type: null }); - getModelLists({ ...queryFlow, model_type: null }); - } else { - setActiveType(item.id); - setQueryFlow({ ...queryFlow, model_type: item.id }); - getModelLists({ ...queryFlow, model_type: item.id }); - } - - // setQueryFlow({...queryFlow,data_type:item.path},()=>{ - // getDatasetlist() - // }) - }; - const chooseModelTag = (val, item) => { - if (item.id == queryFlow.model_tag) { - setActiveTag(''); - setQueryFlow({ ...queryFlow, model_tag: null }); - getModelLists({ ...queryFlow, model_tag: null }); - } else { - setActiveTag(item.id); - setQueryFlow({ ...queryFlow, model_tag: item.id }); - getModelLists({ ...queryFlow, model_tag: item.id }); - } - // setQueryFlow({...queryFlow,data_type:item.path},()=>{ - // getDatasetlist() - // }) - }; - const routeToIntro = (e, record) => { - e.stopPropagation(); - console.log(record); - navgite({ pathname: `/dataset/model/${record.id}?isPublic=false` }); - }; - const onFinishFailed = (errorInfo) => { - console.log('Failed:', errorInfo); - }; - const onPageChange = (pageNum, pageSize) => { - console.log(pageNum, pageSize); - setQueryFlow({ ...queryFlow, page: pageNum - 1, size: pageSize }); - getModelLists({ ...queryFlow, page: pageNum - 1, size: pageSize }); - }; - useEffect(() => { - getAssetIconList(iconParams); - getModelLists(queryFlow); - return () => {}; - }, []); - return ( - <> -
-
-
- -
模型框架
-
- {modelTypeList && modelTypeList.length > 0 - ? modelTypeList.map((item) => { - return ( -
-
{ - chooseModelType(e, item); - }} - > - - - { - chooseModelTag(e, item); - }} - > - {item.name} - -
-
- ); - }) - : ''} -
-
模型能力
-
- {modelDirectionList && modelDirectionList.length > 0 - ? modelDirectionList.map((item) => { - return ( -
-
{ - chooseModelTag(e, item); - }} - > - - - {item.name} -
-
- ); - }) - : ''} -
-
-
-
-
- 数据总数:{total}个 -
- - -
-
-
- {datasetList && datasetList.length > 0 - ? datasetList.map((item) => { - return ( -
{ - routeToIntro(e, item); - }} - > - {item.name} - { - e.stopPropagation(); - modalConfirm({ - title: '确定删除该条模型实例吗?', - onOk: () => { - deleteModel(item.id).then((ret) => { - if (ret.code === 200) { - message.success('删除成功'); - getModelLists(queryFlow); - } else { - message.error(ret.msg); - } - }); - }, - }); - }} - className={Styles.dropdown} - style={{ width: '17px', marginRight: '6px' }} - src={deleteIcon} - alt="" - /> - {/* { - console.log(e); - if (e.key === 'detail') { - routeToIntro(e, item); - } else if (e.key === 'delete') { - modalConfirm({ - title: '确定删除该条模型实例吗?', - onOk: () => { - deleteModel(item.id).then((ret) => { - if (ret.code === 200) { - message.success('删除成功'); - getModelLists(queryFlow); - } else { - message.error(ret.msg); - } - }); - }, - }); - } - }, - }} - > -
- -
-
*/} -
{item.description}
-
- - {item.create_by} -
-
- - 最近更新: {moment(item.update_time).format('YYYY-MM-DD')} -
-
- ); - }) - : ''} - {/* Demo */} -
- -
-
- - - {dialogTitle} -
- } - open={isModalOpen} - className={Styles.modal} - okButtonProps={{ - htmlType: 'submit', - form: 'form', - }} - onCancel={handleCancel} - > -
- - - - - - - - - - - - {/* - - 仅自己可见 - 工作空间可见 - - */} - - { - return { value: item.id, label: item.name }; - })} - /> - - - - - - -
- - - ); -}; -export default PublicData; diff --git a/react-ui/src/pages/Model/publicData.jsx b/react-ui/src/pages/Model/publicData.jsx deleted file mode 100644 index 62790d17..00000000 --- a/react-ui/src/pages/Model/publicData.jsx +++ /dev/null @@ -1,360 +0,0 @@ -import clock from '@/assets/img/clock.png'; -import creatByImg from '@/assets/img/creatBy.png'; -import { getAssetIcon, getModelList } from '@/services/dataset/index.js'; -import { Form, Input, Modal, Pagination, Radio } from 'antd'; -import moment from 'moment'; -import { useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import Styles from './index.less'; -const { Search } = Input; -const leftdataList = [1, 2, 3]; - -const PublicData = () => { - const [queryFlow, setQueryFlow] = useState({ - page: 0, - size: 20, - name: null, - available_range: 1, - }); - const [iconParams, setIconParams] = useState({ - name: null, - page: 0, - size: 10000, - }); - const [activeType, setActiveType] = useState(null); - const [activeTag, setActiveTag] = useState(null); - const [datasetTypeList, setDatasetTypeList] = useState([]); - const [datasetDirectionList, setDatasetDirectionList] = useState([]); - const navgite = useNavigate(); - const [isModalOpen, setIsModalOpen] = useState(false); - const [datasetList, setDatasetList] = useState([]); - const [total, setTotal] = useState(0); - const [form] = Form.useForm(); - const [dialogTitle, setDialogTitle] = useState('新建数据'); - const getModelLists = (queryFlow) => { - getModelList(queryFlow).then((ret) => { - console.log(ret); - if (ret.code == 200) { - setDatasetList(ret.data.content); - setTotal(ret.data.totalElements); - } - }); - }; - - const showModal = () => { - form.resetFields(); - setDialogTitle('新建数据集'); - setIsModalOpen(true); - }; - const nameSearch = (values) => { - console.log(values); - getModelLists({ ...queryFlow, name: values }); - }; - const getAssetIconList = (params) => { - getAssetIcon(params).then((ret) => { - console.log(ret); - if (ret.code == 200 && ret.data.content && ret.data.content.length > 0) { - setDatasetTypeList(ret.data.content.filter((item) => item.category_id == 3)); - setDatasetDirectionList(ret.data.content.filter((item) => item.category_id == 4)); - } else { - setDatasetTypeList([]); - setDatasetDirectionList([]); - } - }); - }; - const onSearch = (values) => { - console.log(values); - getAssetIconList({ ...iconParams, name: values }); - }; - const handleOk = () => { - console.log(1111); - setIsModalOpen(false); - }; - const handleCancel = () => { - setIsModalOpen(false); - }; - const chooseModelType = (val, item) => { - console.log(val, item); - if (item.id == queryFlow.model_type) { - setActiveType(''); - setQueryFlow({ ...queryFlow, model_type: null }); - getModelLists({ ...queryFlow, model_type: null }); - } else { - setActiveType(item.id); - setQueryFlow({ ...queryFlow, model_type: item.id }); - getModelLists({ ...queryFlow, model_type: item.id }); - } - - // setQueryFlow({...queryFlow,data_type:item.path},()=>{ - // getDatasetlist() - // }) - }; - const chooseModelTag = (val, item) => { - if (item.id == queryFlow.model_tag) { - setActiveTag(''); - setQueryFlow({ ...queryFlow, model_tag: null }); - getModelLists({ ...queryFlow, model_tag: null }); - } else { - setActiveTag(item.id); - setQueryFlow({ ...queryFlow, model_tag: item.id }); - getModelLists({ ...queryFlow, model_tag: item.id }); - } - // setQueryFlow({...queryFlow,data_type:item.path},()=>{ - // getDatasetlist() - // }) - }; - const onFinish = (values) => {}; - const routeToIntro = (e, record) => { - e.stopPropagation(); - console.log(record); - navgite({ pathname: `/dataset/model/${record.id}?isPublic=true` }); - }; - const onFinishFailed = (errorInfo) => { - console.log('Failed:', errorInfo); - }; - const onPageChange = (pageNum, pageSize) => { - console.log(pageNum, pageSize); - setQueryFlow({ ...queryFlow, page: pageNum - 1, size: pageSize }); - getModelLists({ ...queryFlow, page: pageNum - 1, size: pageSize }); - }; - useEffect(() => { - getAssetIconList(iconParams); - getModelLists(queryFlow); - return () => {}; - }, []); - return ( - <> -
-
-
- -
模型框架
-
- {datasetTypeList && datasetTypeList.length > 0 - ? datasetTypeList.map((item) => { - return ( -
-
{ - chooseModelType(e, item); - }} - > - - - {item.name} -
-
- ); - }) - : ''} -
-
模型能力
-
- {datasetDirectionList && datasetDirectionList.length > 0 - ? datasetDirectionList.map((item) => { - return ( -
-
{ - chooseModelTag(e, item); - }} - > - - - {item.name} -
-
- ); - }) - : ''} -
-
-
-
-
- 数据总数:{total}个 -
- -
-
-
- {datasetList && datasetList.length > 0 - ? datasetList.map((item) => { - return ( -
{ - routeToIntro(e, item); - }} - > - {item.name} -
{item.description}
-
- - {item.create_by} -
-
- - 最近更新: {moment(item.update_time).format('YYYY-MM-DD')} -
-
- ); - }) - : ''} - {/* Demo */} -
- -
-
- - - {dialogTitle} -
- } - open={isModalOpen} - className={Styles.modal} - okButtonProps={{ - htmlType: 'submit', - form: 'form', - }} - onCancel={handleCancel} - > -
- - - - - - - - - - - - 仅自己可见 - 工作空间可见 - - - - - -
- - - ); -}; -export default PublicData; diff --git a/react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.tsx b/react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.tsx index e073a449..20c265f2 100644 --- a/react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.tsx +++ b/react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.tsx @@ -40,7 +40,6 @@ export type SelectorTypeInfo = { getFiles: (params: any) => Promise; handleVersionResponse: (res: any) => any[]; modalIcon: string; - buttonIcon: string; name: string; litReqParamKey: 'available_range' | 'image_type'; fileReqParamKey: 'models_id' | 'dataset_id'; @@ -71,7 +70,6 @@ export const selectorTypeData: Record res.data || [], name: '模型', modalIcon: modelImg, - buttonIcon: 'local:model-select-button', litReqParamKey: 'available_range', fileReqParamKey: 'models_id', tabItems: [ @@ -92,7 +90,6 @@ export const selectorTypeData: Record res.data || [], name: '数据集', modalIcon: datasetImg, - buttonIcon: 'local:dataset-select-button', litReqParamKey: 'available_range', fileReqParamKey: 'dataset_id', tabItems: [ @@ -115,7 +112,6 @@ export const selectorTypeData: Record { type = ResourceSelectorType.Mirror; break; } - const { close } = openAntdModal( - ResourceSelectorModal, - { - type, - defaultExpandedKeys: resource ? [resource.id] : [], - defaultCheckedKeys: resource ? [`${resource.id}-${resource.version}`] : [], - defaultActiveTab: resource?.activeTab, - onOk: (res) => { - if (res) { - if (type === ResourceSelectorType.Mirror) { - form.setFieldValue(name, res); - } else { - const jsonObj = pick(res, ['id', 'version', 'path']); - const value = JSON.stringify(jsonObj); - form.setFieldValue(name, value); - } - - if (type === ResourceSelectorType.Dataset) { - setSelectedDataset(res); - } else if (type === ResourceSelectorType.Model) { - setSelectedModel(res); - } + const { close } = openAntdModal(ResourceSelectorModal, { + type, + defaultExpandedKeys: resource ? [resource.id] : [], + defaultCheckedKeys: resource ? [`${resource.id}-${resource.version}`] : [], + defaultActiveTab: resource?.activeTab, + onOk: (res) => { + if (res) { + if (type === ResourceSelectorType.Mirror) { + form.setFieldValue(name, res); } else { - if (type === ResourceSelectorType.Dataset) { - setSelectedDataset(null); - } else if (type === ResourceSelectorType.Model) { - setSelectedModel(null); - } - form.setFieldValue(name, ''); + const jsonObj = pick(res, ['id', 'version', 'path']); + const value = JSON.stringify(jsonObj); + form.setFieldValue(name, value); + } + + if (type === ResourceSelectorType.Dataset) { + setSelectedDataset(res); + } else if (type === ResourceSelectorType.Model) { + setSelectedModel(res); } - close(); - }, + } else { + if (type === ResourceSelectorType.Dataset) { + setSelectedDataset(null); + } else if (type === ResourceSelectorType.Model) { + setSelectedModel(null); + } + form.setFieldValue(name, ''); + } + close(); }, - true, - ); + }); }; // 获取选择数据集、模型后面按钮 icon diff --git a/react-ui/src/pages/Pipeline/index.jsx b/react-ui/src/pages/Pipeline/index.jsx index 51728c3c..fcbdc03e 100644 --- a/react-ui/src/pages/Pipeline/index.jsx +++ b/react-ui/src/pages/Pipeline/index.jsx @@ -170,7 +170,7 @@ const Pipeline = () => { key="clone" icon={} onClick={async () => { - Modal.confirm({ + modalConfirm({ title: '复制', content: '确定复制该条流水线吗?', okText: '确认', diff --git a/react-ui/src/pages/Workspace/components/ExperimentChart/index.tsx b/react-ui/src/pages/Workspace/components/ExperimentChart/index.tsx index f4d30fe1..89c1f34d 100644 --- a/react-ui/src/pages/Workspace/components/ExperimentChart/index.tsx +++ b/react-ui/src/pages/Workspace/components/ExperimentChart/index.tsx @@ -140,6 +140,7 @@ function ExperimentChart({ chartData, style }: ExperimentChartProps) { itemStyle: { borderRadius: 3, }, + minAngle: 5, label: { show: false, }, @@ -152,11 +153,11 @@ function ExperimentChart({ chartData, style }: ExperimentChartProps) { show: false, }, data: [ - { value: chartData.Failed, name: '失败' }, - { value: chartData.Succeeded, name: '成功' }, - { value: chartData.Terminated, name: '中止' }, - { value: chartData.Pending, name: '等待' }, - { value: chartData.Running, name: '运行中' }, + { value: chartData.Failed > 0 ? chartData.Failed : null, name: '失败' }, + { value: chartData.Succeeded > 0 ? chartData.Succeeded : null, name: '成功' }, + { value: chartData.Terminated > 0 ? chartData.Terminated : null, name: '中止' }, + { value: chartData.Pending > 0 ? chartData.Pending : null, name: '等待' }, + { value: chartData.Running > 0 ? chartData.Running : null, name: '运行中' }, ], }, { diff --git a/react-ui/src/pages/Workspace/components/ExperimentTable/index.less b/react-ui/src/pages/Workspace/components/ExperimentTable/index.less index f40613e6..fc83b21d 100644 --- a/react-ui/src/pages/Workspace/components/ExperimentTable/index.less +++ b/react-ui/src/pages/Workspace/components/ExperimentTable/index.less @@ -36,15 +36,15 @@ } &__duration { - width: 25%; + width: 30%; } &__date { - width: 35%; + width: calc(50% - 60px); } &__operation { - width: 20%; + width: 60px; :global { .ant-btn-link { diff --git a/react-ui/src/requestConfig.ts b/react-ui/src/requestConfig.ts index 74cb5c43..fe9cd44d 100644 --- a/react-ui/src/requestConfig.ts +++ b/react-ui/src/requestConfig.ts @@ -40,7 +40,7 @@ export const requestConfig: RequestConfig = { clearSessionToken(); setRemoteMenu(null); gotoLoginPage(false); - message.error(data?.msg ?? '请重新登录'); + message.error('请重新登录'); return Promise.reject(response); } else { message.error(data?.msg ?? '请求失败'); diff --git a/react-ui/src/styles/theme.less b/react-ui/src/styles/theme.less index d97b3ef8..65a5a32e 100644 --- a/react-ui/src/styles/theme.less +++ b/react-ui/src/styles/theme.less @@ -47,6 +47,22 @@ @result: rgba(@red, @green, @blue, @alpha); } +// 混合 +.singleLine() { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + word-break: break-all; +} + +.multiLine(@line) { + display: -webkit-box; + overflow: hidden; + word-break: break-all; + -webkit-box-orient: vertical; + -webkit-line-clamp: @line; +} + // 导出变量 :export { primaryColor: @primary-color; diff --git a/react-ui/src/utils/ui.tsx b/react-ui/src/utils/ui.tsx index 108bc8c0..8f8bde3f 100644 --- a/react-ui/src/utils/ui.tsx +++ b/react-ui/src/utils/ui.tsx @@ -6,7 +6,7 @@ import { PageEnum } from '@/enums/pagesEnums'; import themes from '@/styles/theme.less'; import { history } from '@umijs/max'; -import { Modal, type ModalFuncProps, type UploadFile } from 'antd'; +import { Modal, message, type ModalFuncProps, type UploadFile } from 'antd'; // 自定义 Confirm 弹框 export function modalConfirm({ title, content, onOk, ...rest }: ModalFuncProps) { @@ -54,6 +54,7 @@ export const gotoLoginPage = (toHome: boolean = true) => { const urlParams = new URLSearchParams(); urlParams.append('redirect', pathname + search); const newSearch = toHome && pathname && pathname !== PageEnum.LOGIN ? '' : urlParams.toString(); + console.log('gotoLoginPage', pathname, search); if (window.location.pathname !== PageEnum.LOGIN) { history.replace({ pathname: PageEnum.LOGIN, @@ -61,3 +62,28 @@ export const gotoLoginPage = (toHome: boolean = true) => { }); } }; + +// 上传文件校验 +export const validateUploadFiles = (files: UploadFile[], required: boolean = true): boolean => { + if (required && files.length === 0) { + message.error('请上传文件'); + return false; + } + + const hasError = files.some((file) => { + if (file.status === 'uploading') { + message.error('请等待文件上传完成'); + return true; + } + if (file.status === 'error') { + message.error('存在上传失败的文件,请删除后重新上传文件'); + return true; + } + if (!file.response || file.response.code !== 200 || !file.response.data) { + message.error('存在上传失败的文件,请删除后重新上传文件'); + return true; + } + return false; + }); + return !hasError; +}; From b2e3d86a3187ccaa6cb23ff31dee6338665b97c4 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Sat, 11 May 2024 15:32:30 +0800 Subject: [PATCH 05/14] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E9=95=9C?= =?UTF-8?q?=E5=83=8F=E5=88=97=E8=A1=A8=E6=90=9C=E7=B4=A2=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dataset/components/ResourceList/index.tsx | 4 +-- react-ui/src/pages/Mirror/create.tsx | 34 ++++++------------- react-ui/src/pages/Mirror/list.tsx | 21 ++++++------ 3 files changed, 22 insertions(+), 37 deletions(-) diff --git a/react-ui/src/pages/Dataset/components/ResourceList/index.tsx b/react-ui/src/pages/Dataset/components/ResourceList/index.tsx index eb470356..b07cb5bf 100644 --- a/react-ui/src/pages/Dataset/components/ResourceList/index.tsx +++ b/react-ui/src/pages/Dataset/components/ResourceList/index.tsx @@ -78,7 +78,7 @@ function ResourceList( // 获取数据请求 const getDataList = async () => { - const reqParams = { + const params = { page: pagination.current! - 1, size: pagination.pageSize, [resourceConfig[resourceType].typeParamKey]: dataType, @@ -87,7 +87,7 @@ function ResourceList( name: searchText !== '' ? searchText : undefined, }; const request = resourceConfig[resourceType].getList; - const [res] = await to(request(reqParams)); + const [res] = await to(request(params)); if (res && res.data && res.data.content) { setDataList(res.data.content); setTotal(res.data.totalElements); diff --git a/react-ui/src/pages/Mirror/create.tsx b/react-ui/src/pages/Mirror/create.tsx index c4032358..f2d1f86f 100644 --- a/react-ui/src/pages/Mirror/create.tsx +++ b/react-ui/src/pages/Mirror/create.tsx @@ -12,7 +12,7 @@ import { CommonTabKeys } from '@/enums'; import { createMirrorReq } from '@/services/mirror'; import { to } from '@/utils/promise'; import { getSessionItemThenRemove, mirrorNameKey } from '@/utils/sessionStorage'; -import { getFileListFromEvent } from '@/utils/ui'; +import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; import { useNavigate } from '@umijs/max'; import { Button, Col, Form, Input, Row, Upload, UploadFile, message, type UploadProps } from 'antd'; import { omit } from 'lodash'; @@ -75,30 +75,16 @@ function MirrorCreate() { }; } else { const fileList = formData['fileList'] ?? []; - if (fileList.length === 0) { - message.error('请上传文件'); - return; + 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 file = fileList[0]; - if (file.status === 'uploading') { - message.error('请等待文件上传完成'); - return; - } else if (file.status === 'error') { - message.error('文件上传失败,请重新上传文件'); - return; - } - if (!file.response || !file.response.data) { - message.error('文件上传失败,请重新上传文件'); - return; - } - - 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)); diff --git a/react-ui/src/pages/Mirror/list.tsx b/react-ui/src/pages/Mirror/list.tsx index e94d79dc..24932f6d 100644 --- a/react-ui/src/pages/Mirror/list.tsx +++ b/react-ui/src/pages/Mirror/list.tsx @@ -54,6 +54,7 @@ function MirrorList() { const [cacheState, setCacheState] = useCacheState(); const [activeTab, setActiveTab] = useState(cacheState?.activeTab ?? CommonTabKeys.Public); 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( @@ -65,11 +66,12 @@ function MirrorList() { useEffect(() => { getMirrorList(); - }, [activeTab, pagination]); + }, [activeTab, pagination, searchText]); // 切换 Tab,重置数据 const hanleTabChange: TabsProps['onChange'] = (value) => { setSearchText(''); + setInputText(''); setPagination({ current: 1, pageSize: 10, @@ -78,16 +80,16 @@ function MirrorList() { setTableData([]); setActiveTab(value); }; + // 获取镜像列表 - const getMirrorList = async (params?: Record) => { - const reqParams = { + const getMirrorList = async () => { + const params: Record = { page: pagination.current! - 1, size: pagination.pageSize, name: searchText, image_type: activeTab === CommonTabKeys.Public ? 1 : 0, - ...params, }; - const [res] = await to(getMirrorListReq(reqParams)); + const [res] = await to(getMirrorListReq(params)); if (res && res.data) { const { content = [], totalElements = 0 } = res.data; setTableData(content); @@ -116,10 +118,7 @@ function MirrorList() { // 搜索 const onSearch: SearchProps['onSearch'] = (value) => { - // 带参数是为了点清除时,searchText 更新不及时的问题 - getMirrorList({ - name: value, - }); + setSearchText(value); }; // 查看详情 @@ -241,9 +240,9 @@ function MirrorList() { placeholder="按数据集名称筛选" allowClear onSearch={onSearch} - onChange={(e) => setSearchText(e.target.value)} + onChange={(e) => setInputText(e.target.value)} style={{ width: 300 }} - value={searchText} + value={inputText} /> {activeTab === CommonTabKeys.Private && ( + {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 07/14] =?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 08/14] =?UTF-8?q?feat:=20table=20column=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=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 09/14] =?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 10/14] =?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 11/14] =?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 12/14] =?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 13/14] =?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 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

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); + }} + /> + } + > + - - -