Merge pull request 'feat: 流水线添加参数' (#46) from dev-zw into dev

This commit is contained in:
cp3hnu 2024-05-15 11:35:36 +08:00
commit cebc66de1f
123 changed files with 1914 additions and 1095 deletions

View File

@ -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', name: 'modelDeployment',
path: '/modelDseployment', path: '/modelDeployment',
routes: [ routes: [
{ {
name: '模型部署', name: '模型列表',
path: '', path: '',
key: 'modelDseployment', component: './ModelDeployment/list',
component: './missingPage.jsx', },
{
name: '镜像详情',
path: ':id',
component: './ModelDeployment/info',
},
{
name: '创建镜像',
path: 'create',
component: './ModelDeployment/create',
}, },
], ],
}, },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -184,10 +184,14 @@ export function render(oldRender: () => void) {
oldRender(); oldRender();
return; return;
} }
getRoutersInfo().then((res) => { getRoutersInfo()
setRemoteMenu(res); .then((res) => {
oldRender(); setRemoteMenu(res);
}); oldRender();
})
.catch(() => {
oldRender();
});
} }
// 主题修改 // 主题修改

Binary file not shown.

View File

@ -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;

View File

@ -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;

View File

@ -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}

View File

@ -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';

View File

@ -4,6 +4,6 @@
} }
.upload-button { .upload-button {
height: 48px; height: 46px;
font-size: 15px; font-size: 15px;
} }

View File

@ -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 <Form name="form" layout="vertical" onFinish={onFinish} autoComplete="off">
name="form"
layout="vertical"
initialValues={{
remember: true,
}}
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">

View File

@ -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 <Form name="form" layout="vertical" onFinish={onFinish} autoComplete="off">
name="form"
layout="vertical"
initialValues={{
remember: true,
}}
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

View File

@ -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;

View File

@ -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';

View File

@ -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 { Button, Input, Select, Table, Tabs, message } from 'antd';
import moment from 'moment';
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(); const { close } = openAntdModal(AddVersionModal, {
form.setFieldsValue({ name: datasetDetailObj.name }); resourceType: ResourceType.Dataset,
resourceId: locationParams.id,
initialName: datasetDetailObj.name,
onOk: () => {
getDatasetVersionList();
close();
},
});
};
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 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>
); );
}; };

View File

@ -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,
}, },
}; };

View File

@ -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;

View File

@ -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 { getParamType } from '../AddExperimentModal';
import styles from './paramsModal.less'; 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) => (

View File

@ -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}> <div className={styles.allMessageItem}>启动时间{formatDate(message.create_time)}</div>
启动时间{momnet(message.create_time).format('YYYY-MM-DD HH:mm:ss')}
</div>
<div className={styles.allMessageItem}> <div className={styles.allMessageItem}>
执行时长 执行时长
{message.finish_time {message.finish_time

View File

@ -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}>
耗时 耗时

View File

@ -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%' }}> <div style={{ width: '50%' }}>{formatDate(item.create_time)}</div>
{momnet(item.create_time).format('YYYY-MM-DD HH:mm:ss')}
</div>
</div> </div>
<div className={Styles.statusBox}> <div className={Styles.statusBox}>
<img <img

View File

@ -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 = const create_time = formatDate(time);
time && dayjs(time).isValid() ? dayjs(time).format('YYYY-MM-DD HH:mm:ss') : '--';
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: '创建时间',

View File

@ -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, render: CommonTableCell(true),
ellipsis: true, ellipsis: { showTitle: false },
}, },
{ {
title: '创建时间', title: '创建时间',

View File

@ -1,4 +0,0 @@
.upload-button {
height: 48px;
font-size: 15px;
}

View File

@ -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 { Button, Input, Select, Table, Tabs, message } from 'antd';
import moment from 'moment';
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(); const { close } = openAntdModal(AddVersionModal, {
form.setFieldsValue({ name: datasetDetailObj.name }); resourceType: ResourceType.Model,
resourceId: locationParams.id,
initialName: datasetDetailObj.name,
onOk: () => {
getModelVersionsList();
close();
},
});
};
setDialogTitle('创建新版本');
setUuid(Date.now());
setIsModalOpen(true);
};
const handleCancel = () => {
setIsModalOpen(false);
};
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>
); );
}; };

View File

@ -0,0 +1,11 @@
.mirror-status-cell {
color: @text-color;
&--success {
color: @success-color;
}
&--error {
color: @error-color;
}
}

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;
}
}
}
}
}
}

View File

@ -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;

View File

@ -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;
}
}
}

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