Merge pull request 'feat: 流水线添加参数' (#46) from dev-zw into dev
|
@ -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',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 1.2 KiB |
|
@ -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();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 主题修改
|
// 主题修改
|
||||||
|
|
|
@ -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
|
<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">
|
||||||
|
|
|
@ -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
|
|
@ -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 { 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>
|
||||||
);
|
);
|
||||||
};
|
};
|
|
@ -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 { 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) => (
|
|
@ -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
|
||||||
|
|
|
@ -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%' }}>
|
<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
|
||||||
|
|
|
@ -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: '创建时间',
|
||||||
|
|
|
@ -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: '创建时间',
|
||||||
|
|
|
@ -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 { 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>
|
||||||
);
|
);
|
||||||
};
|
};
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|