| @@ -131,7 +131,7 @@ export default [ | |||||
| { | { | ||||
| name: '数据集简介', | name: '数据集简介', | ||||
| path: ':id', | path: ':id', | ||||
| component: './Dataset/datasetIntro', | |||||
| component: './Dataset/intro', | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| @@ -147,7 +147,7 @@ export default [ | |||||
| { | { | ||||
| name: '模型简介', | name: '模型简介', | ||||
| path: ':id', | path: ':id', | ||||
| component: './Model/modelIntro', | |||||
| component: './Model/intro', | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| @@ -188,14 +188,23 @@ export default [ | |||||
| ], | ], | ||||
| }, | }, | ||||
| { | { | ||||
| name: 'modelDseployment', | |||||
| path: '/modelDseployment', | |||||
| name: 'modelDeployment', | |||||
| path: '/modelDeployment', | |||||
| routes: [ | routes: [ | ||||
| { | { | ||||
| name: '模型部署', | |||||
| name: '模型列表', | |||||
| path: '', | path: '', | ||||
| key: 'modelDseployment', | |||||
| component: './missingPage.jsx', | |||||
| component: './ModelDeployment/list', | |||||
| }, | |||||
| { | |||||
| name: '镜像详情', | |||||
| path: ':id', | |||||
| component: './ModelDeployment/info', | |||||
| }, | |||||
| { | |||||
| name: '创建镜像', | |||||
| path: 'create', | |||||
| component: './ModelDeployment/create', | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| @@ -184,10 +184,14 @@ export function render(oldRender: () => void) { | |||||
| oldRender(); | oldRender(); | ||||
| return; | return; | ||||
| } | } | ||||
| getRoutersInfo().then((res) => { | |||||
| setRemoteMenu(res); | |||||
| oldRender(); | |||||
| }); | |||||
| getRoutersInfo() | |||||
| .then((res) => { | |||||
| setRemoteMenu(res); | |||||
| oldRender(); | |||||
| }) | |||||
| .catch(() => { | |||||
| oldRender(); | |||||
| }); | |||||
| } | } | ||||
| // 主题修改 | // 主题修改 | ||||
| @@ -4,8 +4,18 @@ | |||||
| * @Description: 自定义 Table 单元格,没有数据时展示 -- | * @Description: 自定义 Table 单元格,没有数据时展示 -- | ||||
| */ | */ | ||||
| function CommonTableCell(text?: string | null) { | |||||
| import { Tooltip } from 'antd'; | |||||
| function renderCell(text?: string | null) { | |||||
| return <span>{text ?? '--'}</span>; | return <span>{text ?? '--'}</span>; | ||||
| } | } | ||||
| function CommonTableCell(ellipsis: boolean = false) { | |||||
| if (ellipsis) { | |||||
| return (text?: string | null) => <Tooltip title={text}>{renderCell(text)}</Tooltip>; | |||||
| } else { | |||||
| return renderCell; | |||||
| } | |||||
| } | |||||
| export default CommonTableCell; | export default CommonTableCell; | ||||
| @@ -4,6 +4,7 @@ | |||||
| * @Description: 自定义 Table 日期类单元格 | * @Description: 自定义 Table 日期类单元格 | ||||
| */ | */ | ||||
| import { formatDate } from '@/utils/date'; | |||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||
| function DateTableCell(text?: string | null) { | function DateTableCell(text?: string | null) { | ||||
| @@ -13,7 +14,7 @@ function DateTableCell(text?: string | null) { | |||||
| if (!dayjs(text).isValid()) { | if (!dayjs(text).isValid()) { | ||||
| return <span>无效的日期</span>; | return <span>无效的日期</span>; | ||||
| } | } | ||||
| return <span>{dayjs(text).format('YYYY-MM-DD HH:mm:ss')}</span>; | |||||
| return <span>{formatDate(text)}</span>; | |||||
| } | } | ||||
| export default DateTableCell; | export default DateTableCell; | ||||
| @@ -12,11 +12,12 @@ import './index.less'; | |||||
| export interface KFModalProps extends ModalProps { | export interface KFModalProps extends ModalProps { | ||||
| image?: string; | image?: string; | ||||
| } | } | ||||
| function KFModal({ title, image, children, className = '', ...rest }: KFModalProps) { | |||||
| function KFModal({ title, image, children, className = '', centered, ...rest }: KFModalProps) { | |||||
| return ( | return ( | ||||
| <Modal | <Modal | ||||
| className={classNames(['kf-modal', className])} | className={classNames(['kf-modal', className])} | ||||
| {...rest} | {...rest} | ||||
| centered={centered ?? true} | |||||
| title={<ModalTitle title={title} image={image}></ModalTitle>} | title={<ModalTitle title={title} image={image}></ModalTitle>} | ||||
| > | > | ||||
| {children} | {children} | ||||
| @@ -2,6 +2,7 @@ import { useEmotionCss } from '@ant-design/use-emotion-css'; | |||||
| import { useModel } from '@umijs/max'; | import { useModel } from '@umijs/max'; | ||||
| import React from 'react'; | import React from 'react'; | ||||
| import Avatar from './AvatarDropdown'; | import Avatar from './AvatarDropdown'; | ||||
| // import { SelectLang } from '@umijs/max'; | |||||
| export type SiderTheme = 'light' | 'dark'; | export type SiderTheme = 'light' | 'dark'; | ||||
| @@ -4,6 +4,6 @@ | |||||
| } | } | ||||
| .upload-button { | .upload-button { | ||||
| height: 48px; | |||||
| height: 46px; | |||||
| font-size: 15px; | font-size: 15px; | ||||
| } | } | ||||
| @@ -23,7 +23,7 @@ import { useEffect, useState } from 'react'; | |||||
| import { CategoryData } from '../../type'; | import { CategoryData } from '../../type'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| interface AddDatasetModalProps extends ModalProps { | |||||
| interface AddDatasetModalProps extends Omit<ModalProps, 'onOk'> { | |||||
| typeList: CategoryData[]; | typeList: CategoryData[]; | ||||
| tagList: CategoryData[]; | tagList: CategoryData[]; | ||||
| onOk: () => void; | onOk: () => void; | ||||
| @@ -94,15 +94,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||||
| }} | }} | ||||
| destroyOnClose | destroyOnClose | ||||
| > | > | ||||
| <Form | |||||
| name="form" | |||||
| layout="vertical" | |||||
| initialValues={{ | |||||
| remember: true, | |||||
| }} | |||||
| onFinish={onFinish} | |||||
| autoComplete="off" | |||||
| > | |||||
| <Form name="form" layout="vertical" onFinish={onFinish} autoComplete="off"> | |||||
| <Form.Item | <Form.Item | ||||
| label="数据集名称" | label="数据集名称" | ||||
| name="name" | name="name" | ||||
| @@ -134,6 +126,8 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||||
| placeholder="请选择数据集分类" | placeholder="请选择数据集分类" | ||||
| options={typeList} | options={typeList} | ||||
| fieldNames={{ label: 'name', value: 'id' }} | fieldNames={{ label: 'name', value: 'id' }} | ||||
| optionFilterProp="name" | |||||
| showSearch | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item label="研究方向/应用领域" name="data_tag"> | <Form.Item label="研究方向/应用领域" name="data_tag"> | ||||
| @@ -142,6 +136,8 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||||
| placeholder="请选择研究方向/应用领域" | placeholder="请选择研究方向/应用领域" | ||||
| options={tagList} | options={tagList} | ||||
| fieldNames={{ label: 'name', value: 'id' }} | fieldNames={{ label: 'name', value: 'id' }} | ||||
| optionFilterProp="name" | |||||
| showSearch | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item label="集群版本" name="available_cluster"> | <Form.Item label="集群版本" name="available_cluster"> | ||||
| @@ -18,9 +18,9 @@ import { | |||||
| } from 'antd'; | } from 'antd'; | ||||
| import { omit } from 'lodash'; | import { omit } from 'lodash'; | ||||
| import { useState } from 'react'; | import { useState } from 'react'; | ||||
| import styles from './index.less'; | |||||
| import styles from '../AddDatasetModal/index.less'; | |||||
| interface AddModelModalProps extends ModalProps { | |||||
| interface AddModelModalProps extends Omit<ModalProps, 'onOk'> { | |||||
| typeList: CategoryData[]; | typeList: CategoryData[]; | ||||
| tagList: CategoryData[]; | tagList: CategoryData[]; | ||||
| onOk: () => void; | onOk: () => void; | ||||
| @@ -76,15 +76,7 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||||
| form: 'form', | form: 'form', | ||||
| }} | }} | ||||
| > | > | ||||
| <Form | |||||
| name="form" | |||||
| layout="vertical" | |||||
| initialValues={{ | |||||
| remember: true, | |||||
| }} | |||||
| onFinish={onFinish} | |||||
| autoComplete="off" | |||||
| > | |||||
| <Form name="form" layout="vertical" onFinish={onFinish} autoComplete="off"> | |||||
| <Form.Item | <Form.Item | ||||
| label="模型名称" | label="模型名称" | ||||
| name="name" | name="name" | ||||
| @@ -140,6 +132,8 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||||
| placeholder="请选择模型类型" | placeholder="请选择模型类型" | ||||
| options={typeList} | options={typeList} | ||||
| fieldNames={{ label: 'name', value: 'id' }} | fieldNames={{ label: 'name', value: 'id' }} | ||||
| optionFilterProp="name" | |||||
| showSearch | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item label="模型能力" name="model_tag"> | <Form.Item label="模型能力" name="model_tag"> | ||||
| @@ -148,6 +142,8 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||||
| placeholder="请选择模型标签" | placeholder="请选择模型标签" | ||||
| options={tagList} | options={tagList} | ||||
| fieldNames={{ label: 'name', value: 'id' }} | fieldNames={{ label: 'name', value: 'id' }} | ||||
| optionFilterProp="name" | |||||
| showSearch | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item | <Form.Item | ||||
| @@ -0,0 +1,169 @@ | |||||
| import { getAccessToken } from '@/access'; | |||||
| import KFIcon from '@/components/KFIcon'; | |||||
| import KFModal from '@/components/KFModal'; | |||||
| import { ResourceType, resourceConfig } from '@/pages/Dataset/type'; | |||||
| import { to } from '@/utils/promise'; | |||||
| import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; | |||||
| import { | |||||
| Button, | |||||
| Form, | |||||
| Input, | |||||
| Upload, | |||||
| UploadFile, | |||||
| message, | |||||
| type ModalProps, | |||||
| type UploadProps, | |||||
| } from 'antd'; | |||||
| import { omit } from 'lodash'; | |||||
| import { useState } from 'react'; | |||||
| import styles from '../AddDatasetModal/index.less'; | |||||
| interface AddVersionModalProps extends Omit<ModalProps, 'onOk'> { | |||||
| resourceType: ResourceType; | |||||
| resourceId: number; | |||||
| initialName: string; | |||||
| onOk: () => void; | |||||
| } | |||||
| function AddVersionModal({ | |||||
| resourceType, | |||||
| resourceId, | |||||
| initialName, | |||||
| onOk, | |||||
| ...rest | |||||
| }: AddVersionModalProps) { | |||||
| const [uuid] = useState(Date.now()); | |||||
| // 上传组件参数 | |||||
| const uploadProps: UploadProps = { | |||||
| action: resourceConfig[resourceType].uploadAction, | |||||
| headers: { | |||||
| Authorization: getAccessToken() || '', | |||||
| }, | |||||
| defaultFileList: [], | |||||
| }; | |||||
| // 上传请求 | |||||
| const createDatasetVersion = async (params: any) => { | |||||
| const request = resourceConfig[resourceType].addVersionReq; | |||||
| const [res] = await to(request(params)); | |||||
| if (res) { | |||||
| message.success('创建成功'); | |||||
| onOk?.(); | |||||
| } | |||||
| }; | |||||
| // 提交 | |||||
| const onFinish = (formData: any) => { | |||||
| const fileList: UploadFile[] = formData['fileList'] ?? []; | |||||
| if (validateUploadFiles(fileList)) { | |||||
| const otherParams = omit(formData, ['fileList']); | |||||
| const params = fileList.map((item) => { | |||||
| const data = item.response?.data?.[0] ?? {}; | |||||
| return { | |||||
| ...otherParams, | |||||
| [resourceConfig[resourceType].idParamKey]: resourceId, | |||||
| file_name: data.fileName, | |||||
| file_size: data.fileSize, | |||||
| url: data.url, | |||||
| }; | |||||
| }); | |||||
| createDatasetVersion(params); | |||||
| } | |||||
| }; | |||||
| const name = resourceConfig[resourceType].name; | |||||
| const accept = resourceConfig[resourceType].uploadAccept; | |||||
| return ( | |||||
| <KFModal | |||||
| {...rest} | |||||
| title="创建新版本" | |||||
| image={require('@/assets/img/create-experiment.png')} | |||||
| width={825} | |||||
| okButtonProps={{ | |||||
| htmlType: 'submit', | |||||
| form: 'form', | |||||
| }} | |||||
| > | |||||
| <Form | |||||
| name="form" | |||||
| layout="vertical" | |||||
| initialValues={{ | |||||
| name: initialName, | |||||
| }} | |||||
| onFinish={onFinish} | |||||
| autoComplete="off" | |||||
| > | |||||
| <Form.Item | |||||
| label={`${name}名称`} | |||||
| name="name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: `请输入${name}名称`, | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input disabled placeholder={`请输入${name}名称`} /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| label={`${name}版本`} | |||||
| name="version" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: `请输入${name}版本`, | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input placeholder={`请输入${name}版本`} maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| label="版本描述" | |||||
| name="description" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入版本描述', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input.TextArea | |||||
| placeholder="请输入版本描述" | |||||
| autoSize={{ minRows: 2, maxRows: 6 }} | |||||
| maxLength={256} | |||||
| showCount | |||||
| allowClear | |||||
| /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| label={`${name}文件`} | |||||
| name="fileList" | |||||
| valuePropName="fileList" | |||||
| getValueFromEvent={getFileListFromEvent} | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: `请上传${name}文件`, | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Upload {...uploadProps} data={{ uuid: uuid }} accept={accept}> | |||||
| <Button | |||||
| className={styles['upload-button']} | |||||
| type="default" | |||||
| icon={<KFIcon type="icon-shangchuan" />} | |||||
| > | |||||
| 上传文件 | |||||
| </Button> | |||||
| {resourceType === ResourceType.Dataset && ( | |||||
| <div className={styles['upload-tip']}>只允许上传.zip格式文件</div> | |||||
| )} | |||||
| </Upload> | |||||
| </Form.Item> | |||||
| </Form> | |||||
| </KFModal> | |||||
| ); | |||||
| } | |||||
| export default AddVersionModal; | |||||
| @@ -1,6 +1,6 @@ | |||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import { CommonTabKeys } from '@/enums'; | import { CommonTabKeys } from '@/enums'; | ||||
| import AddModelModal from '@/pages/Model/components/AddModelModal'; | |||||
| import AddModelModal from '@/pages/Dataset/components/AddModelModal'; | |||||
| import { openAntdModal } from '@/utils/modal'; | import { openAntdModal } from '@/utils/modal'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| @@ -1,56 +1,25 @@ | |||||
| import { getAccessToken } from '@/access'; | |||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import KFModal from '@/components/KFModal'; | |||||
| import { ResourceType } from '@/pages/Dataset/type'; | |||||
| import { | import { | ||||
| addDatasetVersionDetail, | |||||
| deleteDatasetVersion, | deleteDatasetVersion, | ||||
| getDatasetById, | getDatasetById, | ||||
| getDatasetVersionIdList, | getDatasetVersionIdList, | ||||
| getDatasetVersionsById, | getDatasetVersionsById, | ||||
| } from '@/services/dataset/index.js'; | } from '@/services/dataset/index.js'; | ||||
| import { formatDate } from '@/utils/date'; | |||||
| import { downLoadZip } from '@/utils/downloadfile'; | import { downLoadZip } from '@/utils/downloadfile'; | ||||
| import { openAntdModal } from '@/utils/modal'; | |||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| import { UploadOutlined } from '@ant-design/icons'; | |||||
| import { useParams, useSearchParams } from '@umijs/max'; | import { useParams, useSearchParams } from '@umijs/max'; | ||||
| import { Button, Form, Input, Select, Table, Tabs, Upload, message } from 'antd'; | |||||
| import moment from 'moment'; | |||||
| import { Button, Input, Select, Table, Tabs, message } from 'antd'; | |||||
| import { useEffect, useRef, useState } from 'react'; | 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 { Search } = Input; | ||||
| const { TabPane } = Tabs; | const { TabPane } = Tabs; | ||||
| const Dataset = () => { | 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 [formList, setFormList] = useState([]); | ||||
| const [dialogTitle, setDialogTitle] = useState('新建版本'); | |||||
| const [isModalOpen, setIsModalOpen] = useState(false); | |||||
| const [datasetDetailObj, setDatasetDetailObj] = useState({}); | const [datasetDetailObj, setDatasetDetailObj] = useState({}); | ||||
| const [version, setVersion] = useState(null); | const [version, setVersion] = useState(null); | ||||
| const [versionList, setVersionList] = useState([]); | const [versionList, setVersionList] = useState([]); | ||||
| @@ -58,8 +27,8 @@ const Dataset = () => { | |||||
| const [searchParams] = useSearchParams(); | const [searchParams] = useSearchParams(); | ||||
| const [wordList, setWordList] = useState([]); | const [wordList, setWordList] = useState([]); | ||||
| const [activeTabKey, setActiveTabKey] = useState('1'); | const [activeTabKey, setActiveTabKey] = useState('1'); | ||||
| const [uuid, setUuid] = useState(Date.now()); | |||||
| const isPublic = searchParams.get('isPublic') === 'true'; | const isPublic = searchParams.get('isPublic') === 'true'; | ||||
| const getDatasetByDetail = () => { | const getDatasetByDetail = () => { | ||||
| getDatasetById(locationParams.id).then((ret) => { | getDatasetById(locationParams.id).then((ret) => { | ||||
| console.log(ret); | console.log(ret); | ||||
| @@ -93,21 +62,17 @@ const Dataset = () => { | |||||
| return () => {}; | return () => {}; | ||||
| }, []); | }, []); | ||||
| const showModal = () => { | 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 = () => { | const deleteDataset = () => { | ||||
| modalConfirm({ | modalConfirm({ | ||||
| title: '删除后,该数据集版本将不可恢复', | title: '删除后,该数据集版本将不可恢复', | ||||
| @@ -120,19 +85,26 @@ const Dataset = () => { | |||||
| }, | }, | ||||
| }); | }); | ||||
| }; | }; | ||||
| const onFinish = (values) => { | |||||
| addDatasetVersionDetail(formList).then((ret) => { | |||||
| getDatasetVersionList(); | |||||
| setIsModalOpen(false); | |||||
| message.success('创建成功'); | |||||
| }); | |||||
| }; | |||||
| // 获取版本下的文件列表 | // 获取版本下的文件列表 | ||||
| const getDatasetVersions = (params) => { | const getDatasetVersions = (params) => { | ||||
| getDatasetVersionIdList(params).then((res) => { | getDatasetVersionIdList(params).then((res) => { | ||||
| setWordList(res?.data?.content ?? []); | 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) => { | const handleChange = (value) => { | ||||
| console.log(value); | console.log(value); | ||||
| if (value) { | if (value) { | ||||
| @@ -142,15 +114,7 @@ const Dataset = () => { | |||||
| setVersion(null); | 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 = [ | const columns = [ | ||||
| { | { | ||||
| title: '序号', | title: '序号', | ||||
| @@ -182,7 +146,7 @@ const Dataset = () => { | |||||
| title: '更新时间', | title: '更新时间', | ||||
| dataIndex: 'update_time', | dataIndex: 'update_time', | ||||
| key: 'update_time', | key: 'update_time', | ||||
| render: (text) => <span>{moment(text).format('YYYY-MM-DD HH:mm:ss')}</span>, | |||||
| render: (text) => <span>{formatDate(text)}</span>, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '操作', | title: '操作', | ||||
| @@ -292,98 +256,6 @@ const Dataset = () => { | |||||
| </TabPane> | </TabPane> | ||||
| </Tabs> | </Tabs> | ||||
| </div> | </div> | ||||
| <KFModal | |||||
| title={dialogTitle} | |||||
| width={825} | |||||
| image={require('@/assets/img/create-experiment.png')} | |||||
| open={isModalOpen} | |||||
| className={Styles.modal} | |||||
| okButtonProps={{ | |||||
| htmlType: 'submit', | |||||
| form: 'form', | |||||
| }} | |||||
| onCancel={handleCancel} | |||||
| > | |||||
| <Form | |||||
| name="form" | |||||
| form={form} | |||||
| layout="vertical" | |||||
| initialValues={{ | |||||
| remember: true, | |||||
| }} | |||||
| onFinish={onFinish} | |||||
| onFinishFailed={onFinishFailed} | |||||
| autoComplete="off" | |||||
| > | |||||
| <Form.Item | |||||
| label="数据集名称" | |||||
| name="name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入数据集名称', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input disabled placeholder="请输入数据集名称" /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| label="数据集版本" | |||||
| name="version" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入数据集版本', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input placeholder="请输入数据集版本" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| label="版本描述" | |||||
| name="description" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入版本描述', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input.TextArea | |||||
| placeholder="请输入版本描述" | |||||
| autoSize={{ minRows: 2, maxRows: 6 }} | |||||
| maxLength={256} | |||||
| showCount | |||||
| allowClear | |||||
| /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| label="数据集文件" | |||||
| name="dataset_version_vos" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请上传数据集文件', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Upload {...props} data={{ uuid: uuid }} accept=".zip,.tgz"> | |||||
| <Button | |||||
| style={{ | |||||
| fontSize: '14px', | |||||
| border: '1px solid', | |||||
| borderColor: '#1664ff', | |||||
| background: '#fff', | |||||
| }} | |||||
| icon={<UploadOutlined style={{ color: '#1664ff' }} />} | |||||
| > | |||||
| 上传文件 | |||||
| </Button> | |||||
| <div className={Styles.tipContent}>只允许上传.zip,.tgz格式文件</div> | |||||
| </Upload> | |||||
| </Form.Item> | |||||
| </Form> | |||||
| </KFModal> | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| }; | }; | ||||
| @@ -1,6 +1,8 @@ | |||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import { CommonTabKeys } from '@/enums'; | import { CommonTabKeys } from '@/enums'; | ||||
| import { | import { | ||||
| addDatasetVersionDetail, | |||||
| addModelsVersionDetail, | |||||
| deleteDataset, | deleteDataset, | ||||
| deleteModel, | deleteModel, | ||||
| getDatasetList, | getDatasetList, | ||||
| @@ -18,9 +20,9 @@ export enum ResourceType { | |||||
| } | } | ||||
| type ResourceTypeKeys = keyof typeof 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<any>; | getList: (params: any) => Promise<any>; | ||||
| getVersions: (params: any) => Promise<any>; | getVersions: (params: any) => Promise<any>; | ||||
| getFiles: (params: any) => Promise<any>; | getFiles: (params: any) => Promise<any>; | ||||
| @@ -37,6 +39,10 @@ export type ResourceTypeInfo = { | |||||
| iconPathPrefix: string; // 图标路径前缀 | iconPathPrefix: string; // 图标路径前缀 | ||||
| deleteModalTitle: string; // 删除弹框的title | deleteModalTitle: string; // 删除弹框的title | ||||
| addBtnTitle: string; // 新增按钮的title | addBtnTitle: string; // 新增按钮的title | ||||
| addVersionReq: (params: any) => Promise<any>; | |||||
| idParamKey: string; | |||||
| uploadAction: string; | |||||
| uploadAccept?: string; | |||||
| }; | }; | ||||
| export const resourceConfig: Record<ResourceTypeValues, ResourceTypeInfo> = { | export const resourceConfig: Record<ResourceTypeValues, ResourceTypeInfo> = { | ||||
| @@ -68,6 +74,10 @@ export const resourceConfig: Record<ResourceTypeValues, ResourceTypeInfo> = { | |||||
| iconPathPrefix: 'dataset', | iconPathPrefix: 'dataset', | ||||
| deleteModalTitle: '确定删除该条数据集实例吗?', | deleteModalTitle: '确定删除该条数据集实例吗?', | ||||
| addBtnTitle: '新建数据集', | addBtnTitle: '新建数据集', | ||||
| addVersionReq: addDatasetVersionDetail, | |||||
| idParamKey: 'dataset_id', | |||||
| uploadAction: '/api/mmp/dataset/upload', | |||||
| uploadAccept: '.zip,.tgz', | |||||
| }, | }, | ||||
| [ResourceType.Model]: { | [ResourceType.Model]: { | ||||
| getList: getModelList, | getList: getModelList, | ||||
| @@ -97,6 +107,10 @@ export const resourceConfig: Record<ResourceTypeValues, ResourceTypeInfo> = { | |||||
| iconPathPrefix: 'model', | iconPathPrefix: 'model', | ||||
| deleteModalTitle: '确定删除该条模型实例吗?', | deleteModalTitle: '确定删除该条模型实例吗?', | ||||
| addBtnTitle: '新建模型', | addBtnTitle: '新建模型', | ||||
| addVersionReq: addModelsVersionDetail, | |||||
| idParamKey: 'models_id', | |||||
| uploadAction: '/api/mmp/models/upload', | |||||
| uploadAccept: undefined, | |||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -4,7 +4,7 @@ import KFModal from '@/components/KFModal'; | |||||
| import { type PipelineGlobalParam } from '@/types'; | import { type PipelineGlobalParam } from '@/types'; | ||||
| import { Form, Input, Radio, Select, type FormRule } from 'antd'; | import { Form, Input, Radio, Select, type FormRule } from 'antd'; | ||||
| import { useState } from 'react'; | import { useState } from 'react'; | ||||
| import styles from './addExperimentModal.less'; | |||||
| import styles from './index.less'; | |||||
| type FormData = { | type FormData = { | ||||
| name?: string; | name?: string; | ||||
| @@ -6,8 +6,8 @@ | |||||
| import parameterImg from '@/assets/img/modal-parameter.png'; | import parameterImg from '@/assets/img/modal-parameter.png'; | ||||
| import KFModal from '@/components/KFModal'; | import KFModal from '@/components/KFModal'; | ||||
| import { type PipelineGlobalParam } from '@/types'; | 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 = { | type ParamsModalProps = { | ||||
| open: boolean; | open: boolean; | ||||
| @@ -24,6 +24,7 @@ function ParamsModal({ open, onCancel, globalParam = [] }: ParamsModalProps) { | |||||
| onOk={onCancel} | onOk={onCancel} | ||||
| onCancel={onCancel} | onCancel={onCancel} | ||||
| cancelButtonProps={{ style: { display: 'none' } }} | cancelButtonProps={{ style: { display: 'none' } }} | ||||
| width={825} | |||||
| > | > | ||||
| <div className={styles.params_container}> | <div className={styles.params_container}> | ||||
| {globalParam?.map((item) => ( | {globalParam?.map((item) => ( | ||||
| @@ -1,17 +1,16 @@ | |||||
| import { useVisible } from '@/hooks'; | import { useVisible } from '@/hooks'; | ||||
| import { getExperimentIns } from '@/services/experiment/index.js'; | import { getExperimentIns } from '@/services/experiment/index.js'; | ||||
| import { getWorkflowById } from '@/services/pipeline/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 { useEmotionCss } from '@ant-design/use-emotion-css'; | ||||
| import G6 from '@antv/g6'; | import G6 from '@antv/g6'; | ||||
| import { Button } from 'antd'; | import { Button } from 'antd'; | ||||
| import momnet from 'moment'; | |||||
| import { useEffect, useRef, useState } from 'react'; | import { useEffect, useRef, useState } from 'react'; | ||||
| import { useNavigate, useParams } from 'react-router-dom'; | import { useNavigate, useParams } from 'react-router-dom'; | ||||
| import { s8 } from '../../../utils'; | import { s8 } from '../../../utils'; | ||||
| import ParamsModal from '../components/ViewParamsModal'; | |||||
| import { experimentStatusInfo } from '../status'; | import { experimentStatusInfo } from '../status'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| import ParamsModal from './paramsModal'; | |||||
| import Props from './props'; | import Props from './props'; | ||||
| function ExperimentText() { | function ExperimentText() { | ||||
| @@ -389,9 +388,7 @@ function ExperimentText() { | |||||
| <div className={pipelineContainer}> | <div className={pipelineContainer}> | ||||
| <div className={styles.centerContainer}> | <div className={styles.centerContainer}> | ||||
| <div className={styles.buttonList}> | <div className={styles.buttonList}> | ||||
| <div className={styles.allMessageItem}> | |||||
| 启动时间:{momnet(message.create_time).format('YYYY-MM-DD HH:mm:ss')} | |||||
| </div> | |||||
| <div className={styles.allMessageItem}>启动时间:{formatDate(message.create_time)}</div> | |||||
| <div className={styles.allMessageItem}> | <div className={styles.allMessageItem}> | ||||
| 执行时长: | 执行时长: | ||||
| {message.finish_time | {message.finish_time | ||||
| @@ -1,5 +1,5 @@ | |||||
| import { getNodeResult, getQueryByExperimentLog } from '@/services/experiment/index.js'; | 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 { downLoadZip } from '@/utils/downloadfile'; | ||||
| import { DatabaseOutlined, ProfileOutlined } from '@ant-design/icons'; | import { DatabaseOutlined, ProfileOutlined } from '@ant-design/icons'; | ||||
| import { Drawer, Form, Input, Tabs, message } from 'antd'; | import { Drawer, Form, Input, Tabs, message } from 'antd'; | ||||
| @@ -419,7 +419,7 @@ const Props = forwardRef(({ onParentChange }, ref) => { | |||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| <div className={Styles.detailBox}> | <div className={Styles.detailBox}> | ||||
| 启动时间:{moment(stagingItem.experimentStartTime).format('YYYY-MM-DD HH:mm:ss')} | |||||
| 启动时间:{formatDate(stagingItem.experimentStartTime)} | |||||
| </div> | </div> | ||||
| <div className={Styles.detailBox}> | <div className={Styles.detailBox}> | ||||
| 耗时: | 耗时: | ||||
| @@ -14,16 +14,15 @@ import { | |||||
| } from '@/services/experiment/index.js'; | } from '@/services/experiment/index.js'; | ||||
| import { getWorkflow } from '@/services/pipeline/index.js'; | import { getWorkflow } from '@/services/pipeline/index.js'; | ||||
| import themes from '@/styles/theme.less'; | import themes from '@/styles/theme.less'; | ||||
| import { elapsedTime } from '@/utils/date'; | |||||
| import { elapsedTime, formatDate } from '@/utils/date'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| import { Button, ConfigProvider, Space, Table, message } from 'antd'; | import { Button, ConfigProvider, Space, Table, message } from 'antd'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import momnet from 'moment'; | |||||
| import { useEffect, useRef, useState } from 'react'; | import { useEffect, useRef, useState } from 'react'; | ||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||
| import AddExperimentModal from './components/AddExperimentModal'; | |||||
| import TensorBoardStatus, { TensorBoardStatusEnum } from './components/TensorBoardStatus'; | import TensorBoardStatus, { TensorBoardStatusEnum } from './components/TensorBoardStatus'; | ||||
| import AddExperimentModal from './experimentText/addExperimentModal'; | |||||
| import Styles from './index.less'; | import Styles from './index.less'; | ||||
| import { experimentStatusInfo } from './status'; | import { experimentStatusInfo } from './status'; | ||||
| @@ -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(item.finish_time)) | ||||
| : elapsedTime(new Date(item.create_time), new Date())} | : elapsedTime(new Date(item.create_time), new Date())} | ||||
| </div> | </div> | ||||
| <div style={{ width: '50%' }}> | |||||
| {momnet(item.create_time).format('YYYY-MM-DD HH:mm:ss')} | |||||
| </div> | |||||
| <div style={{ width: '50%' }}>{formatDate(item.create_time)}</div> | |||||
| </div> | </div> | ||||
| <div className={Styles.statusBox}> | <div className={Styles.statusBox}> | ||||
| <img | <img | ||||
| @@ -16,6 +16,7 @@ import { | |||||
| getMirrorVersionListReq, | getMirrorVersionListReq, | ||||
| } from '@/services/mirror'; | } from '@/services/mirror'; | ||||
| import themes from '@/styles/theme.less'; | import themes from '@/styles/theme.less'; | ||||
| import { formatDate } from '@/utils/date'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { mirrorNameKey, setSessionStorageItem } from '@/utils/sessionStorage'; | import { mirrorNameKey, setSessionStorageItem } from '@/utils/sessionStorage'; | ||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| @@ -32,7 +33,6 @@ import { | |||||
| type TableProps, | type TableProps, | ||||
| } from 'antd'; | } from 'antd'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import dayjs from 'dayjs'; | |||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import MirrorStatusCell from './components/MirrorStatusCell'; | import MirrorStatusCell from './components/MirrorStatusCell'; | ||||
| import styles from './info.less'; | import styles from './info.less'; | ||||
| @@ -83,8 +83,7 @@ function MirrorInfo() { | |||||
| const [res] = await to(getMirrorInfoReq(id)); | const [res] = await to(getMirrorInfoReq(id)); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const { name = '', description = '', version_count = '', create_time: time } = 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({ | setMirrorInfo({ | ||||
| name, | name, | ||||
| description, | description, | ||||
| @@ -161,13 +160,13 @@ function MirrorInfo() { | |||||
| dataIndex: 'tag_name', | dataIndex: 'tag_name', | ||||
| key: 'tag_name', | key: 'tag_name', | ||||
| width: '25%', | width: '25%', | ||||
| render: CommonTableCell, | |||||
| render: CommonTableCell(), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '镜像地址', | title: '镜像地址', | ||||
| dataIndex: 'url', | dataIndex: 'url', | ||||
| key: 'url', | key: 'url', | ||||
| render: CommonTableCell, | |||||
| render: CommonTableCell(), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '状态', | title: '状态', | ||||
| @@ -181,7 +180,7 @@ function MirrorInfo() { | |||||
| dataIndex: 'file_size', | dataIndex: 'file_size', | ||||
| key: 'file_size', | key: 'file_size', | ||||
| width: 150, | width: 150, | ||||
| render: CommonTableCell, | |||||
| render: CommonTableCell(), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '创建时间', | title: '创建时间', | ||||
| @@ -166,21 +166,21 @@ function MirrorList() { | |||||
| dataIndex: 'name', | dataIndex: 'name', | ||||
| key: 'name', | key: 'name', | ||||
| width: '30%', | width: '30%', | ||||
| render: CommonTableCell, | |||||
| render: CommonTableCell(), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '版本数据', | title: '版本数据', | ||||
| dataIndex: 'version_count', | dataIndex: 'version_count', | ||||
| key: 'version_count', | key: 'version_count', | ||||
| width: 100, | width: 100, | ||||
| render: CommonTableCell, | |||||
| render: CommonTableCell(), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '镜像描述', | title: '镜像描述', | ||||
| dataIndex: 'description', | dataIndex: 'description', | ||||
| key: 'description', | key: 'description', | ||||
| render: CommonTableCell, | |||||
| ellipsis: true, | |||||
| render: CommonTableCell(true), | |||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '创建时间', | title: '创建时间', | ||||
| @@ -1,4 +0,0 @@ | |||||
| .upload-button { | |||||
| height: 48px; | |||||
| font-size: 15px; | |||||
| } | |||||
| @@ -1,65 +1,33 @@ | |||||
| import { getAccessToken } from '@/access'; | |||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import KFModal from '@/components/KFModal'; | |||||
| import AddVersionModal from '@/pages/Dataset/components/AddVersionModal'; | |||||
| import { ResourceType } from '@/pages/Dataset/type'; | |||||
| import { | import { | ||||
| addModelsVersionDetail, | |||||
| deleteModelVersion, | deleteModelVersion, | ||||
| getModelById, | getModelById, | ||||
| getModelVersionIdList, | getModelVersionIdList, | ||||
| getModelVersionsById, | getModelVersionsById, | ||||
| } from '@/services/dataset/index.js'; | } from '@/services/dataset/index.js'; | ||||
| import { formatDate } from '@/utils/date'; | |||||
| import { downLoadZip } from '@/utils/downloadfile'; | import { downLoadZip } from '@/utils/downloadfile'; | ||||
| import { openAntdModal } from '@/utils/modal'; | |||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| import { UploadOutlined } from '@ant-design/icons'; | |||||
| import { useParams, useSearchParams } from '@umijs/max'; | import { useParams, useSearchParams } from '@umijs/max'; | ||||
| import { Button, Form, Input, Select, Table, Tabs, Upload, message } from 'antd'; | |||||
| import moment from 'moment'; | |||||
| import { Button, Input, Select, Table, Tabs, message } from 'antd'; | |||||
| import { useEffect, useRef, useState } from 'react'; | import { useEffect, useRef, useState } from 'react'; | ||||
| import Styles from './index.less'; | |||||
| import Styles from './intro.less'; | |||||
| const { Search } = Input; | const { Search } = Input; | ||||
| const { TabPane } = Tabs; | const { TabPane } = Tabs; | ||||
| const Dataset = () => { | 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 [formList, setFormList] = useState([]); | ||||
| const [dialogTitle, setDialogTitle] = useState('新建版本'); | |||||
| const [isModalOpen, setIsModalOpen] = useState(false); | |||||
| const [datasetDetailObj, setDatasetDetailObj] = useState({}); | const [datasetDetailObj, setDatasetDetailObj] = useState({}); | ||||
| const [version, setVersion] = useState(null); | const [version, setVersion] = useState(null); | ||||
| const [versionList, setVersionList] = useState([]); | const [versionList, setVersionList] = useState([]); | ||||
| const locationParams = useParams(); //新版本获取路由参数接口 | const locationParams = useParams(); //新版本获取路由参数接口 | ||||
| const [searchParams] = useSearchParams(); | const [searchParams] = useSearchParams(); | ||||
| console.log(locationParams); | |||||
| const [wordList, setWordList] = useState([]); | const [wordList, setWordList] = useState([]); | ||||
| const [uuid, setUuid] = useState(Date.now()); | |||||
| const isPublic = searchParams.get('isPublic') === 'true'; | const isPublic = searchParams.get('isPublic') === 'true'; | ||||
| const getModelByDetail = () => { | const getModelByDetail = () => { | ||||
| getModelById(locationParams.id).then((ret) => { | getModelById(locationParams.id).then((ret) => { | ||||
| console.log(ret); | console.log(ret); | ||||
| @@ -92,16 +60,17 @@ const Dataset = () => { | |||||
| return () => {}; | return () => {}; | ||||
| }, []); | }, []); | ||||
| const showModal = () => { | 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 = () => { | const deleteDataset = () => { | ||||
| modalConfirm({ | modalConfirm({ | ||||
| title: '删除后,该版本将不可恢复', | title: '删除后,该版本将不可恢复', | ||||
| @@ -117,13 +86,7 @@ const Dataset = () => { | |||||
| }, | }, | ||||
| }); | }); | ||||
| }; | }; | ||||
| const onFinish = () => { | |||||
| addModelsVersionDetail(formList).then((ret) => { | |||||
| getModelVersionsList(); | |||||
| setIsModalOpen(false); | |||||
| message.success('创建成功'); | |||||
| }); | |||||
| }; | |||||
| const getModelVersions = (params) => { | const getModelVersions = (params) => { | ||||
| getModelVersionIdList(params).then((ret) => { | getModelVersionIdList(params).then((ret) => { | ||||
| setWordList(ret?.data?.content ?? []); | setWordList(ret?.data?.content ?? []); | ||||
| @@ -149,9 +112,7 @@ const Dataset = () => { | |||||
| setVersion(''); | setVersion(''); | ||||
| } | } | ||||
| }; | }; | ||||
| const onFinishFailed = (errorInfo) => { | |||||
| console.log('Failed:', errorInfo); | |||||
| }; | |||||
| const columns = [ | const columns = [ | ||||
| { | { | ||||
| title: '序号', | title: '序号', | ||||
| @@ -183,7 +144,7 @@ const Dataset = () => { | |||||
| title: '更新时间', | title: '更新时间', | ||||
| dataIndex: 'update_time', | dataIndex: 'update_time', | ||||
| key: 'update_time', | key: 'update_time', | ||||
| render: (text) => <span>{moment(text).format('YYYY-MM-DD HH:mm:ss')}</span>, | |||||
| render: (text) => <span>{formatDate(text)}</span>, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '操作', | title: '操作', | ||||
| @@ -294,96 +255,6 @@ const Dataset = () => { | |||||
| </TabPane> | </TabPane> | ||||
| </Tabs> | </Tabs> | ||||
| </div> | </div> | ||||
| <KFModal | |||||
| title={dialogTitle} | |||||
| image={require('@/assets/img/create-experiment.png')} | |||||
| width={825} | |||||
| open={isModalOpen} | |||||
| okButtonProps={{ | |||||
| htmlType: 'submit', | |||||
| form: 'form', | |||||
| }} | |||||
| onCancel={handleCancel} | |||||
| > | |||||
| <Form | |||||
| name="form" | |||||
| form={form} | |||||
| layout="vertical" | |||||
| initialValues={{ | |||||
| remember: true, | |||||
| }} | |||||
| onFinish={onFinish} | |||||
| onFinishFailed={onFinishFailed} | |||||
| autoComplete="off" | |||||
| > | |||||
| <Form.Item | |||||
| label="模型名称" | |||||
| name="name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入模型名称', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input disabled placeholder="请输入模型名称" /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| label="模型版本" | |||||
| name="version" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入模型版本', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input placeholder="请输入模型版本" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| label="版本描述" | |||||
| name="description" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入版本描述', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input.TextArea | |||||
| placeholder="请输入版本描述" | |||||
| autoSize={{ minRows: 2, maxRows: 6 }} | |||||
| maxLength={256} | |||||
| showCount | |||||
| allowClear | |||||
| /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| label="模型文件" | |||||
| name="dataset_version_vos" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请上传模型文件', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Upload {...props} data={{ uuid: uuid }}> | |||||
| <Button | |||||
| style={{ | |||||
| fontSize: '14px', | |||||
| border: '1px solid', | |||||
| borderColor: '#1664ff', | |||||
| background: '#fff', | |||||
| }} | |||||
| icon={<UploadOutlined style={{ color: '#1664ff' }} />} | |||||
| > | |||||
| 上传文件 | |||||
| </Button> | |||||
| </Upload> | |||||
| </Form.Item> | |||||
| </Form> | |||||
| </KFModal> | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| }; | }; | ||||
| @@ -0,0 +1,11 @@ | |||||
| .mirror-status-cell { | |||||
| color: @text-color; | |||||
| &--success { | |||||
| color: @success-color; | |||||
| } | |||||
| &--error { | |||||
| color: @error-color; | |||||
| } | |||||
| } | |||||
| @@ -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<MirrorVersionStatusValues, MirrorVersionStatusInfo> = { | |||||
| [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 <span>--</span>; | |||||
| } | |||||
| return <span className={statusInfo[status].classname}>{statusInfo[status].text}</span>; | |||||
| } | |||||
| export default MirrorStatusCell; | |||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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 ( | |||||
| <div className={styles['model-deployment-create']}> | |||||
| <PageTitle title="创建推理服务"></PageTitle> | |||||
| <div className={styles['model-deployment-create__content']}> | |||||
| <div> | |||||
| <Form | |||||
| name="model-deployment-create" | |||||
| labelCol={{ flex: '130px' }} | |||||
| wrapperCol={{ flex: 1 }} | |||||
| labelAlign="left" | |||||
| form={form} | |||||
| initialValues={{ upload_type: CommonTabKeys.Public }} | |||||
| onFinish={handleSubmit} | |||||
| size="large" | |||||
| > | |||||
| <SubAreaTitle | |||||
| title="基本信息" | |||||
| image={require('@/assets/img/mirror-basic.png')} | |||||
| style={{ marginBottom: '26px' }} | |||||
| ></SubAreaTitle> | |||||
| <Row gutter={10}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="服务名称" | |||||
| name="name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入服务名称', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input | |||||
| placeholder="请输入服务名称" | |||||
| maxLength={64} | |||||
| disabled={nameDisabled} | |||||
| showCount | |||||
| allowClear | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={10}> | |||||
| <Col span={20}> | |||||
| <Form.Item | |||||
| label="描 述" | |||||
| name="description" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入描述', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input.TextArea | |||||
| autoSize={{ minRows: 2, maxRows: 6 }} | |||||
| placeholder="请输入描述,最长128字符" | |||||
| maxLength={128} | |||||
| showCount | |||||
| allowClear | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <SubAreaTitle | |||||
| title="部署构建" | |||||
| image={require('@/assets/img/mirror-version.png')} | |||||
| style={{ marginTop: '20px', marginBottom: '24px' }} | |||||
| ></SubAreaTitle> | |||||
| <Row gutter={10}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="选择模型" | |||||
| name="name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入模型', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input | |||||
| placeholder="请输入模型" | |||||
| maxLength={64} | |||||
| disabled={nameDisabled} | |||||
| showCount | |||||
| allowClear | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={10}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="选择镜像" | |||||
| name="name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入镜像', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input | |||||
| placeholder="请输入镜像" | |||||
| maxLength={64} | |||||
| disabled={nameDisabled} | |||||
| showCount | |||||
| allowClear | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={10}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="资源规格" | |||||
| name="name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请选择资源规格', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Select | |||||
| showSearch | |||||
| placeholder="请选择资源规格" | |||||
| filterOption={filterResourceStandard} | |||||
| options={resourceStandardList} | |||||
| fieldNames={{ | |||||
| label: 'description', | |||||
| value: 'standard', | |||||
| }} | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={10}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="副本数量" | |||||
| name="name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入副本数量', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input | |||||
| placeholder="请输入副本数量" | |||||
| maxLength={64} | |||||
| disabled={nameDisabled} | |||||
| showCount | |||||
| allowClear | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={10}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="环境变量" name="name"> | |||||
| <Button type="link" style={{ padding: '0' }}> | |||||
| 添加环境变量 | |||||
| </Button> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Form.Item wrapperCol={{ offset: 0, span: 16 }}> | |||||
| <Button type="primary" htmlType="submit"> | |||||
| 确定 | |||||
| </Button> | |||||
| <Button | |||||
| type="default" | |||||
| htmlType="button" | |||||
| onClick={cancel} | |||||
| style={{ marginLeft: '20px' }} | |||||
| > | |||||
| 取消 | |||||
| </Button> | |||||
| </Form.Item> | |||||
| </Form> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| ); | |||||
| } | |||||
| export default ModelDeploymentCreate; | |||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,148 @@ | |||||
| /* | |||||
| * @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 { formatDate } from '@/utils/date'; | |||||
| import { to } from '@/utils/promise'; | |||||
| import { useNavigate, useParams } from '@umijs/max'; | |||||
| import { Col, Row, Tabs, type TabsProps } from 'antd'; | |||||
| 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: <KFIcon type="icon-yuce" />, | |||||
| }, | |||||
| { | |||||
| key: '2', | |||||
| label: '调用指南', | |||||
| icon: <KFIcon type="icon-tiaoyongzhinan" />, | |||||
| }, | |||||
| { | |||||
| key: '3', | |||||
| label: '服务日志', | |||||
| icon: <KFIcon type="icon-fuwurizhi" />, | |||||
| }, | |||||
| ]; | |||||
| function ModelDeploymentInfo() { | |||||
| const navigate = useNavigate(); | |||||
| const urlParams = useParams(); | |||||
| const [mirrorInfo, setMirrorInfo] = useState<MirrorInfoData>({}); | |||||
| const [activeTab, setActiveTab] = useState<string>('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; | |||||
| const create_time = formatDate(time); | |||||
| setMirrorInfo({ | |||||
| name, | |||||
| description, | |||||
| version_count, | |||||
| create_time, | |||||
| }); | |||||
| } | |||||
| }; | |||||
| // 切换 Tab,重置数据 | |||||
| const hanleTabChange: TabsProps['onChange'] = (value) => { | |||||
| setActiveTab(value); | |||||
| }; | |||||
| return ( | |||||
| <div className={styles['model-deployment-info']}> | |||||
| <PageTitle title="服务详情"></PageTitle> | |||||
| <div className={styles['model-deployment-info__content']}> | |||||
| <div> | |||||
| <SubAreaTitle | |||||
| title="基本信息" | |||||
| image={require('@/assets/img/mirror-basic.png')} | |||||
| style={{ marginBottom: '26px' }} | |||||
| ></SubAreaTitle> | |||||
| <div className={styles['model-deployment-info__basic']}> | |||||
| <Row gutter={40} style={{ marginBottom: '20px' }}> | |||||
| <Col span={10}> | |||||
| <div className={styles['model-deployment-info__basic__item']}> | |||||
| <div className={styles['label']}>服务名称:</div> | |||||
| <div className={styles['value']}>{mirrorInfo.name}</div> | |||||
| </div> | |||||
| </Col> | |||||
| <Col span={10}> | |||||
| <div className={styles['model-deployment-info__basic__item']}> | |||||
| <div className={styles['label']}>镜像:</div> | |||||
| <div className={styles['value']}>{mirrorInfo.version_count ?? '--'}</div> | |||||
| </div> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={40} style={{ marginBottom: '20px' }}> | |||||
| <Col span={10}> | |||||
| <div className={styles['model-deployment-info__basic__item']}> | |||||
| <div className={styles['label']}>状态:</div> | |||||
| <div className={styles['value']}>{mirrorInfo.name}</div> | |||||
| </div> | |||||
| </Col> | |||||
| <Col span={10}> | |||||
| <div className={styles['model-deployment-info__basic__item']}> | |||||
| <div className={styles['label']}>模型:</div> | |||||
| <div className={styles['value']}>{mirrorInfo.version_count ?? '--'}</div> | |||||
| </div> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={40} style={{ marginBottom: '20px' }}> | |||||
| <Col span={10}> | |||||
| <div className={styles['model-deployment-info__basic__item']}> | |||||
| <div className={styles['label']}>环境变量:</div> | |||||
| <div className={styles['value']}>{mirrorInfo.name}</div> | |||||
| </div> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={40}> | |||||
| <Col span={24}> | |||||
| <div className={styles['model-deployment-info__basic__item']}> | |||||
| <div className={styles['label']}>描述:</div> | |||||
| <div className={styles['value']}>{mirrorInfo.description}</div> | |||||
| </div> | |||||
| </Col> | |||||
| </Row> | |||||
| </div> | |||||
| <div> | |||||
| <Tabs activeKey={activeTab} items={tabItems} onChange={hanleTabChange} /> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| ); | |||||
| } | |||||
| export default ModelDeploymentInfo; | |||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| } | |||||