Browse Source

feat: 完成模型改造

pull/128/head
cp3hnu 1 year ago
parent
commit
b7d81b000b
28 changed files with 383 additions and 239 deletions
  1. +30
    -21
      react-ui/src/components/BasicInfo/index.less
  2. +55
    -9
      react-ui/src/components/BasicInfo/index.tsx
  3. +0
    -0
      react-ui/src/components/ErrorBoundary/index.less
  4. +0
    -0
      react-ui/src/components/ErrorBoundary/index.tsx
  5. +1
    -2
      react-ui/src/components/KFEmpty/index.less
  6. +6
    -6
      react-ui/src/components/KFEmpty/index.tsx
  7. +1
    -1
      react-ui/src/components/ParameterSelect/config.tsx
  8. +2
    -2
      react-ui/src/pages/404.tsx
  9. +3
    -0
      react-ui/src/pages/CodeConfig/List/index.tsx
  10. +12
    -4
      react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx
  11. +49
    -31
      react-ui/src/pages/Dataset/components/AddModelModal/index.tsx
  12. +3
    -3
      react-ui/src/pages/Dataset/components/AddVersionModal/index.tsx
  13. +8
    -10
      react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx
  14. +93
    -3
      react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx
  15. +1
    -1
      react-ui/src/pages/Dataset/components/ResourceItem/index.tsx
  16. +6
    -7
      react-ui/src/pages/Dataset/components/ResourceList/index.tsx
  17. +3
    -2
      react-ui/src/pages/Dataset/components/ResourceVersion/index.tsx
  18. +36
    -33
      react-ui/src/pages/Dataset/config.tsx
  19. +4
    -4
      react-ui/src/pages/Experiment/components/ExportModelModal/index.tsx
  20. +5
    -15
      react-ui/src/pages/Model/components/ModelEvolution/index.tsx
  21. +4
    -4
      react-ui/src/pages/Model/intro.tsx
  22. +14
    -17
      react-ui/src/pages/Pipeline/components/ResourceSelectorModal/config.tsx
  23. +5
    -5
      react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.less
  24. +6
    -11
      react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.tsx
  25. +2
    -2
      react-ui/src/pages/missingPage.jsx
  26. +1
    -0
      react-ui/src/requestConfig.ts
  27. +23
    -46
      react-ui/src/services/dataset/index.js
  28. +10
    -0
      react-ui/src/utils/index.ts

+ 30
- 21
react-ui/src/components/BasicInfo/index.less View File

@@ -5,31 +5,40 @@
gap: 20px 40px; gap: 20px 40px;
align-items: flex-start; align-items: flex-start;
width: 80%; width: 80%;
}


&__item {
display: flex;
align-items: flex-start;
width: calc(50% - 20px);
font-size: 16px;
line-height: 1.6;
.kf-basic-info-item {
display: flex;
align-items: flex-start;
width: calc(50% - 20px);
font-size: 16px;
line-height: 1.6;


&__label {
width: 100px;
color: @text-color-secondary;
text-align: justify;
text-align-last: justify;
&__label {
position: relative;
color: @text-color-secondary;
text-align: justify;
text-align-last: justify;

&::after {
position: absolute;
content: ':';
} }
}


&__value {
display: flex;
flex: 1;
color: @text-color;
word-break: break-all;
&__value {
flex: 1;
margin-left: 16px;
white-space: pre-line;
word-break: break-all;
}


&::before {
margin-right: 16px;
content: ':';
}
}
&__text {
color: @text-color;
}

&__link:hover {
text-decoration: underline @underline-color;
text-underline-offset: 3px;
} }
} }

+ 55
- 9
react-ui/src/components/BasicInfo/index.tsx View File

@@ -1,27 +1,73 @@
import { isEmptyString } from '@/utils';
import { Link } from '@umijs/max';
import classNames from 'classnames';
import './index.less'; import './index.less';

export type BasicInfoData = { export type BasicInfoData = {
label: string; label: string;
value?: any; value?: any;
format?: (_value: any) => string;
link?: string;
externalLink?: string;
format?: (_value?: any) => string | undefined;
}; };


type BasicInfoProps = { type BasicInfoProps = {
datas: BasicInfoData[]; datas: BasicInfoData[];
className?: string;
style?: React.CSSProperties;
labelWidth?: number;
}; };


function BasicInfo({ datas }: BasicInfoProps) {
function BasicInfo({ datas, className, style, labelWidth = 100 }: BasicInfoProps) {
return ( return (
<div className="kf-basic-info">
<div className={classNames('kf-basic-info', className)} style={style}>
{datas.map((item) => ( {datas.map((item) => (
<div className="kf-basic-info__item" key={item.label}>
<div className="kf-basic-info__item__label">{item.label}</div>
<div className="kf-basic-info__item__value">
{item.format ? item.format(item.value) ?? '--' : item.value ?? '--'}
</div>
</div>
<BasicInfoItem key={item.label} data={item} labelWidth={labelWidth} />
))} ))}
</div> </div>
); );
} }


type BasicInfoItemProps = {
data: BasicInfoData;
labelWidth?: number;
};
function BasicInfoItem({ data, labelWidth = 100 }: BasicInfoItemProps) {
const { label, value, externalLink, link, format } = data;
const showValue = format ? format(value) : value;
let valueComponent = undefined;
if (externalLink && showValue) {
valueComponent = (
<a
className="kf-basic-info-item__value kf-basic-info-item__link"
href={externalLink}
target="_blank"
rel="noopener noreferrer"
>
{showValue}
</a>
);
} else if (link && showValue) {
valueComponent = (
<Link to={link} className="kf-basic-info-item__value kf-basic-info-item__link">
{showValue}
</Link>
);
} else {
valueComponent = (
<div className="kf-basic-info-item__value kf-basic-info-item__text">
{isEmptyString(showValue) ? '--' : showValue}
</div>
);
}
return (
<div className="kf-basic-info-item" key={label}>
<div className="kf-basic-info-item__label" style={{ width: labelWidth }}>
{label}
</div>
{valueComponent}
</div>
);
}

export default BasicInfo; export default BasicInfo;

+ 0
- 0
react-ui/src/components/ErrorBoundary/index.less View File


+ 0
- 0
react-ui/src/components/ErrorBoundary/index.tsx View File


+ 1
- 2
react-ui/src/components/KFEmpty/index.less View File

@@ -7,7 +7,6 @@


&__image { &__image {
width: 475px; width: 475px;
height: 292px;
} }


&__title { &__title {
@@ -15,7 +14,6 @@
color: @text-color; color: @text-color;
font-weight: 500; font-weight: 500;
font-size: 30px; font-size: 30px;
letter-spacing: 5px;
text-align: center; text-align: center;
} }


@@ -32,6 +30,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin-top: 20px; margin-top: 20px;
margin-bottom: 30px;


&__back-btn { &__back-btn {
height: 32px; height: 32px;


+ 6
- 6
react-ui/src/components/KFEmpty/index.tsx View File

@@ -16,8 +16,8 @@ type EmptyProps = {
content?: string; content?: string;
hasFooter?: boolean; hasFooter?: boolean;
footer?: () => React.ReactNode; footer?: () => React.ReactNode;
backTitle?: string;
onBack?: () => void;
buttonTitle?: string;
onRefresh?: () => void;
}; };


function getEmptyImage(type: EmptyType) { function getEmptyImage(type: EmptyType) {
@@ -39,8 +39,8 @@ function KFEmpty({
content, content,
hasFooter = false, hasFooter = false,
footer, footer,
backTitle = '返回',
onBack,
buttonTitle = '刷新',
onRefresh,
}: EmptyProps) { }: EmptyProps) {
const image = getEmptyImage(type); const image = getEmptyImage(type);


@@ -54,8 +54,8 @@ function KFEmpty({
{footer ? ( {footer ? (
footer() footer()
) : ( ) : (
<Button className="kf-empty__footer__back-btn" type="primary" onClick={onBack}>
{backTitle}
<Button className="kf-empty__footer__back-btn" type="primary" onClick={onRefresh}>
{buttonTitle}
</Button> </Button>
)} )}
</div> </div>


+ 1
- 1
react-ui/src/components/ParameterSelect/config.tsx View File

@@ -14,7 +14,7 @@ const filterResourceStandard: SelectProps<string, ComputingResource>['filterOpti
}; };


// id 从 number 转换为 string // id 从 number 转换为 string
const convertId = (item: any) => ({ ...item, id: String(item.id) });
const convertId = (item: any) => ({ ...item, id: `${item.id}-${item.identifier}` });


export type SelectPropsConfig = { export type SelectPropsConfig = {
getOptions: () => Promise<any>; // 获取下拉数据 getOptions: () => Promise<any>; // 获取下拉数据


+ 2
- 2
react-ui/src/pages/404.tsx View File

@@ -11,8 +11,8 @@ const NoFoundPage = () => {
title="404" title="404"
content={'很抱歉,您访问的页面地址有误,\n或者该页面不存在。'} content={'很抱歉,您访问的页面地址有误,\n或者该页面不存在。'}
hasFooter={true} hasFooter={true}
backTitle="返回首页"
onBack={() => navigate('/')}
buttonTitle="返回首页"
onRefresh={() => navigate('/')}
></KFEmpty> ></KFEmpty>
); );
}; };


+ 3
- 0
react-ui/src/pages/CodeConfig/List/index.tsx View File

@@ -171,6 +171,9 @@ function CodeConfigList() {
className={styles['code-config-list__empty']} className={styles['code-config-list__empty']}
type={EmptyType.NoData} type={EmptyType.NoData}
title="暂无数据" title="暂无数据"
content={'很抱歉,没有搜索到您想要的内容\n建议刷新试试'}
hasFooter={true}
onRefresh={getDataList}
/> />
)} )}
</div> </div>


+ 12
- 4
react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx View File

@@ -1,7 +1,8 @@
import { getAccessToken } from '@/access'; import { getAccessToken } from '@/access';
import KFIcon from '@/components/KFIcon'; import KFIcon from '@/components/KFIcon';
import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import { addDateset } from '@/services/dataset/index.js';
import { CategoryData, ResourceType, resourceConfig } from '@/pages/Dataset/config';
import { addDataset } from '@/services/dataset/index.js';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui';
import { import {
@@ -18,7 +19,6 @@ import {
} from 'antd'; } from 'antd';
import { omit } from 'lodash'; import { omit } from 'lodash';
import { useState } from 'react'; import { useState } from 'react';
import { CategoryData } from '../../config';
import styles from './index.less'; import styles from './index.less';


interface AddDatasetModalProps extends Omit<ModalProps, 'onOk'> { interface AddDatasetModalProps extends Omit<ModalProps, 'onOk'> {
@@ -37,7 +37,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr


// 上传组件参数 // 上传组件参数
const uploadProps: UploadProps = { const uploadProps: UploadProps = {
action: '/api/mmp/newdataset/upload',
action: resourceConfig[ResourceType.Dataset].uploadAction,
headers: { headers: {
Authorization: getAccessToken() || '', Authorization: getAccessToken() || '',
}, },
@@ -54,7 +54,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr


// 上传请求 // 上传请求
const createDataset = async (params: any) => { const createDataset = async (params: any) => {
const [res] = await to(addDateset(params));
const [res] = await to(addDataset(params));
if (res) { if (res) {
message.success('创建成功'); message.success('创建成功');
onOk?.(); onOk?.();
@@ -120,6 +120,14 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr
required: true, required: true,
message: '请输入数据集版本', message: '请输入数据集版本',
}, },
{
validator: (_rule, value) => {
if (value === 'master') {
return Promise.reject(`版本不能为 master`);
}
return Promise.resolve();
},
},
]} ]}
> >
<Input placeholder="请输入数据集版本" showCount allowClear maxLength={64} /> <Input placeholder="请输入数据集版本" showCount allowClear maxLength={64} />


+ 49
- 31
react-ui/src/pages/Dataset/components/AddModelModal/index.tsx View File

@@ -1,7 +1,7 @@
import { getAccessToken } from '@/access'; import { getAccessToken } from '@/access';
import KFIcon from '@/components/KFIcon'; import KFIcon from '@/components/KFIcon';
import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import { CategoryData } from '@/pages/Dataset/config';
import { CategoryData, ResourceType, resourceConfig } from '@/pages/Dataset/config';
import { addModel } from '@/services/dataset/index.js'; import { addModel } from '@/services/dataset/index.js';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui';
@@ -9,6 +9,7 @@ import {
Button, Button,
Form, Form,
Input, Input,
Radio,
Select, Select,
Upload, Upload,
UploadFile, UploadFile,
@@ -31,7 +32,7 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps)


// 上传组件参数 // 上传组件参数
const uploadProps: UploadProps = { const uploadProps: UploadProps = {
action: '/api/mmp/models/upload',
action: resourceConfig[ResourceType.Model].uploadAction,
headers: { headers: {
Authorization: getAccessToken() || '', Authorization: getAccessToken() || '',
}, },
@@ -53,7 +54,7 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps)
if (validateUploadFiles(fileList)) { if (validateUploadFiles(fileList)) {
const params = { const params = {
...omit(formData, ['fileList']), ...omit(formData, ['fileList']),
models_version_vos: fileList.map((item) => {
model_version_vos: fileList.map((item) => {
const data = item.response?.data?.[0] ?? {}; const data = item.response?.data?.[0] ?? {};
return { return {
file_name: data.fileName, file_name: data.fileName,
@@ -77,7 +78,13 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps)
form: 'form', form: 'form',
}} }}
> >
<Form name="form" layout="vertical" onFinish={onFinish} autoComplete="off">
<Form
name="form"
layout="vertical"
onFinish={onFinish}
autoComplete="off"
initialValues={{ is_public: false }}
>
<Form.Item <Form.Item
label="模型名称" label="模型名称"
name="name" name="name"
@@ -88,9 +95,8 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps)
}, },
]} ]}
> >
<Input placeholder="请输入模型名称" showCount allowClear maxLength={64} />
<Input placeholder="请输入模型名称" showCount allowClear maxLength={50} />
</Form.Item> </Form.Item>

<Form.Item <Form.Item
label="模型版本" label="模型版本"
name="version" name="version"
@@ -99,40 +105,24 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps)
required: true, required: true,
message: '请输入模型版本', message: '请输入模型版本',
}, },
]}
>
<Input placeholder="请输入模型版本" allowClear maxLength={64} />
</Form.Item>
<Form.Item
label="模型简介"
name="description"
rules={[
{ {
required: true,
message: '请输入模型简介',
validator: (_rule, value) => {
if (value === 'master') {
return Promise.reject(`版本不能为 master`);
}
return Promise.resolve();
},
}, },
]} ]}
> >
<Input.TextArea
placeholder="请输入模型简介"
showCount
maxLength={256}
autoSize={{ minRows: 2, maxRows: 6 }}
allowClear
/>
<Input placeholder="请输入模型版本" showCount allowClear maxLength={64} />
</Form.Item> </Form.Item>
{/* <Form.Item label="可见范围" name="available_range">
<Radio.Group>
<Radio value="0">仅自己可见</Radio>
<Radio value="1">工作空间可见</Radio>
</Radio.Group>
</Form.Item> */}
<Form.Item label="模型框架" name="model_type"> <Form.Item label="模型框架" name="model_type">
<Select <Select
allowClear allowClear
placeholder="请选择模型类型" placeholder="请选择模型类型"
options={typeList} options={typeList}
fieldNames={{ label: 'name', value: 'id' }}
fieldNames={{ label: 'name', value: 'name' }}
optionFilterProp="name" optionFilterProp="name"
showSearch showSearch
/> />
@@ -142,11 +132,39 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps)
allowClear allowClear
placeholder="请选择模型标签" placeholder="请选择模型标签"
options={tagList} options={tagList}
fieldNames={{ label: 'name', value: 'id' }}
fieldNames={{ label: 'name', value: 'name' }}
optionFilterProp="name" optionFilterProp="name"
showSearch showSearch
/> />
</Form.Item> </Form.Item>
<Form.Item
label="模型简介"
name="description"
rules={[
{
required: true,
message: '请输入模型简介',
},
]}
>
<Input.TextArea
placeholder="请输入模型简介"
maxLength={200}
autoSize={{ minRows: 2, maxRows: 6 }}
showCount
allowClear
/>
</Form.Item>
<Form.Item
label="可见性"
name="is_public"
rules={[{ required: true, message: '请选择可见性' }]}
>
<Radio.Group>
<Radio value={false}>私有</Radio>
<Radio value={true}>公开</Radio>
</Radio.Group>
</Form.Item>
<Form.Item <Form.Item
label="模型文件" label="模型文件"
name="fileList" name="fileList"


+ 3
- 3
react-ui/src/pages/Dataset/components/AddVersionModal/index.tsx View File

@@ -60,7 +60,7 @@ function AddVersionModal({
const onFinish = (formData: any) => { const onFinish = (formData: any) => {
const fileList: UploadFile[] = formData['fileList'] ?? []; const fileList: UploadFile[] = formData['fileList'] ?? [];
if (validateUploadFiles(fileList)) { if (validateUploadFiles(fileList)) {
const dataset_version_vos = fileList.map((item) => {
const version_vos = fileList.map((item) => {
const data = item.response?.data?.[0] ?? {}; const data = item.response?.data?.[0] ?? {};
return { return {
file_name: data.fileName, file_name: data.fileName,
@@ -71,7 +71,7 @@ function AddVersionModal({
const params = { const params = {
id: resourceId, id: resourceId,
identifier, identifier,
dataset_version_vos,
[config.filePropKey]: version_vos,
...omit(formData, 'fileList'), ...omit(formData, 'fileList'),
}; };
createDatasetVersion(params); createDatasetVersion(params);
@@ -123,7 +123,7 @@ function AddVersionModal({
{ {
validator: (_rule, value) => { validator: (_rule, value) => {
if (value === 'master') { if (value === 'master') {
return Promise.reject(`版本不能为 master`);
return Promise.reject(`版本不能为 master`);
} }
return Promise.resolve(); return Promise.resolve();
}, },


+ 8
- 10
react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx View File

@@ -127,14 +127,12 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
const deleteVersion = async () => { const deleteVersion = async () => {
const request = config.deleteVersion; const request = config.deleteVersion;
const params = { const params = {
identifier: info.identifier,
owner: info.owner,
...pick(info, ['id', 'owner', 'identifier', 'relative_paths']),
version, version,
}; };
const [res] = await to(request(params)); const [res] = await to(request(params));
if (res) { if (res) {
message.success('删除成功'); message.success('删除成功');
setVersion(undefined);
getVersionList(pick(info, ['owner', 'identifier'])); getVersionList(pick(info, ['owner', 'identifier']));
} }
}; };
@@ -175,8 +173,8 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
children: ( children: (
<ModelEvolution <ModelEvolution
resourceId={resourceId} resourceId={resourceId}
versionList={versionList}
version={version} version={version}
identifier={info.identifier}
isActive={activeTab === ResourceInfoTabKeys.Evolution} isActive={activeTab === ResourceInfoTabKeys.Evolution}
onVersionChange={handleVersionChange} onVersionChange={handleVersionChange}
></ModelEvolution> ></ModelEvolution>
@@ -184,22 +182,22 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
}); });
} }


const infoTypePropertyName = config.infoTypePropertyName as keyof ResourceData;
const infoTagPropertyName = config.infoTagPropertyName as keyof ResourceData;
const typePropertyName = config.typeParamKey as keyof ResourceData;
const tagPropertyName = config.tagParamKey as keyof ResourceData;


return ( return (
<div className={styles['resource-info']}> <div className={styles['resource-info']}>
<div className={styles['resource-info__top']}> <div className={styles['resource-info__top']}>
<Flex align="center" gap={10} style={{ marginBottom: '20px' }}> <Flex align="center" gap={10} style={{ marginBottom: '20px' }}>
<div className={styles['resource-info__top__name']}>{info.name}</div> <div className={styles['resource-info__top__name']}>{info.name}</div>
{info[infoTypePropertyName] && (
{info[typePropertyName] && (
<div className={styles['resource-info__top__tag']}> <div className={styles['resource-info__top__tag']}>
{(info[infoTypePropertyName] as string) || '--'}
{(info[typePropertyName] as string) || '--'}
</div> </div>
)} )}
{info[infoTagPropertyName] && (
{info[tagPropertyName] && (
<div className={styles['resource-info__top__tag']}> <div className={styles['resource-info__top__tag']}>
{(info[infoTagPropertyName] as string) || '--'}
{(info[tagPropertyName] as string) || '--'}
</div> </div>
)} )}
</Flex> </Flex>


+ 93
- 3
react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx View File

@@ -8,8 +8,24 @@ type ResourceIntroProps = {
info: ResourceData; info: ResourceData;
}; };


function ResourceIntro({ info }: ResourceIntroProps) {
const basicDatas: BasicInfoData[] = [
const formatArray = (arr?: string[]) => {
if (!arr || arr.length === 0) {
return '--';
}
return arr.join('\n');
};

const formatMap = (map?: Record<string, string>) => {
if (!map || Object.keys(map).length === 0) {
return '--';
}
return Object.entries(map)
.map(([key, value]) => `${key} = ${value}`)
.join('\n');
};

function ResourceIntro({ resourceType, info }: ResourceIntroProps) {
const datasetDatas: BasicInfoData[] = [
{ {
label: '数据集名称', label: '数据集名称',
value: info.name, value: info.name,
@@ -52,6 +68,80 @@ function ResourceIntro({ info }: ResourceIntroProps) {
}, },
]; ];


const modelDatas: BasicInfoData[] = [
{
label: '模型名称',
value: info.name,
},
{
label: '版本',
value: info.version,
},
{
label: '创建人',
value: info.create_by,
},
{
label: '更新时间',
value: info.update_time,
},
{
label: '训练镜像',
value: info.image,
},
{
label: '训练代码',
value: info.code,
},
{
label: '训练数据集',
value: info.train_datasets,
format: formatArray,
},
{
label: '测试数据集',
value: info.test_datasets,
format: formatArray,
},
{
label: '参数',
value: info.params,
format: formatMap,
},
{
label: '指标',
value: info.metrics,
format: formatMap,
},
{
label: '训练任务',
value: info.train_task,
},
{
label: '模型来源',
value: info.model_source,
},
{
label: '模型框架',
value: info.model_type,
},
{
label: '模型能力',
value: info.model_tag,
},
{
label: '模型描述',
value: info.description,
},
{
label: '版本描述',
value: info.version_desc,
},
];

const basicDatas: BasicInfoData[] =
resourceType === ResourceType.Dataset ? datasetDatas : modelDatas;

return ( return (
<div className={styles['resource-intro']}> <div className={styles['resource-intro']}>
<SubAreaTitle <SubAreaTitle
@@ -60,7 +150,7 @@ function ResourceIntro({ info }: ResourceIntroProps) {
style={{ marginBottom: '26px' }} style={{ marginBottom: '26px' }}
></SubAreaTitle> ></SubAreaTitle>
<div className={styles['resource-intro__basic']}> <div className={styles['resource-intro__basic']}>
<BasicInfo datas={basicDatas}></BasicInfo>
<BasicInfo datas={basicDatas} labelWidth={86}></BasicInfo>
</div> </div>
<SubAreaTitle <SubAreaTitle
title="实例用法" title="实例用法"


+ 1
- 1
react-ui/src/pages/Dataset/components/ResourceItem/index.tsx View File

@@ -40,7 +40,7 @@ function ResourceItem({ item, isPublic, onClick, onRemove }: ResourceItemProps)
<Flex justify="space-between"> <Flex justify="space-between">
<div className={styles['resource-item__time']}> <div className={styles['resource-item__time']}>
<img style={{ width: '17px', marginRight: '6px' }} src={creatByImg} alt="" /> <img style={{ width: '17px', marginRight: '6px' }} src={creatByImg} alt="" />
<span>{item.create_by}</span>
<span>{item.create_by ?? ''}</span>
</div> </div>
<div className={styles['resource-item__time']}> <div className={styles['resource-item__time']}>
<img style={{ width: '12px', marginRight: '5px' }} src={clock} alt="" /> <img style={{ width: '12px', marginRight: '5px' }} src={clock} alt="" />


+ 6
- 7
react-ui/src/pages/Dataset/components/ResourceList/index.tsx View File

@@ -87,15 +87,11 @@ function ResourceList(
const params: Record<string, any> = { const params: Record<string, any> = {
page: pagination.current! - 1, page: pagination.current! - 1,
size: pagination.pageSize, size: pagination.pageSize,
is_public: isPublic,
[config.typeParamKey]: dataType, [config.typeParamKey]: dataType,
[config.tagParamKey]: dataTag, [config.tagParamKey]: dataTag,
name: searchText !== '' ? searchText : undefined, name: searchText !== '' ? searchText : undefined,
}; };
if (resourceType === ResourceType.Dataset) {
params['is_public'] = isPublic;
} else {
params['available_range'] = isPublic ? 1 : 0;
}
const request = config.getList; const request = config.getList;
const [res] = await to(request(params)); const [res] = await to(request(params));
if (res && res.data && res.data.content) { if (res && res.data && res.data.content) {
@@ -108,7 +104,7 @@ function ResourceList(
}; };


// 删除请求 // 删除请求
const deleteRecord = async (params: { owner: string; identifier: string }) => {
const deleteRecord = async (params: { owner: string; identifier: string; repo_id?: number }) => {
const request = config.deleteRecord; const request = config.deleteRecord;
const [res] = await to(request(params)); const [res] = await to(request(params));
if (res) { if (res) {
@@ -127,7 +123,7 @@ function ResourceList(
modalConfirm({ modalConfirm({
title: config.deleteModalTitle, title: config.deleteModalTitle,
onOk: () => { onOk: () => {
deleteRecord(pick(record, ['owner', 'identifier']));
deleteRecord(pick(record, ['owner', 'identifier', 'id']));
}, },
}); });
}; };
@@ -223,6 +219,9 @@ function ResourceList(
className={styles['resource-list__empty']} className={styles['resource-list__empty']}
type={EmptyType.NoData} type={EmptyType.NoData}
title="暂无数据" title="暂无数据"
content={'很抱歉,没有搜索到您想要的内容\n建议刷新试试'}
hasFooter={true}
onRefresh={getDataList}
/> />
)} )}
</div> </div>


+ 3
- 2
react-ui/src/pages/Dataset/components/ResourceVersion/index.tsx View File

@@ -17,7 +17,8 @@ type ResourceVersionProps = {
}; };
function ResourceVersion({ resourceType, info }: ResourceVersionProps) { function ResourceVersion({ resourceType, info }: ResourceVersionProps) {
const config = resourceConfig[resourceType]; const config = resourceConfig[resourceType];
const fileList = info.dataset_version_vos ?? [];
const filePropKey = config.filePropKey as keyof ResourceData;
const fileList = (info[filePropKey] ?? []) as ResourceFileData[];
fileList.forEach((item) => (item.update_time = info.update_time)); fileList.forEach((item) => (item.update_time = info.update_time));


// 全部导出 // 全部导出
@@ -97,7 +98,7 @@ function ResourceVersion({ resourceType, info }: ResourceVersionProps) {
</Button> </Button>
</Flex> </Flex>
</Flex> </Flex>
<Table columns={columns} dataSource={fileList} pagination={false} rowKey="id" />
<Table columns={columns} dataSource={fileList} pagination={false} rowKey="url" />
</div> </div>
); );
} }


+ 36
- 33
react-ui/src/pages/Dataset/config.tsx View File

@@ -2,7 +2,7 @@ import KFIcon from '@/components/KFIcon';
import { CommonTabKeys } from '@/enums'; import { CommonTabKeys } from '@/enums';
import { import {
addDatasetVersion, addDatasetVersion,
addModelsVersionDetail,
addModelVersion,
deleteDataset, deleteDataset,
deleteDatasetVersion, deleteDatasetVersion,
deleteModel, deleteModel,
@@ -10,9 +10,9 @@ import {
getDatasetInfo, getDatasetInfo,
getDatasetList, getDatasetList,
getDatasetVersionList, getDatasetVersionList,
getModelById,
getModelInfo,
getModelList, getModelList,
getModelVersionsById,
getModelVersionList,
} from '@/services/dataset/index.js'; } from '@/services/dataset/index.js';
import type { TabsProps } from 'antd'; import type { TabsProps } from 'antd';


@@ -31,7 +31,7 @@ type ResourceTypeInfo = {
name: string; // 名称 name: string; // 名称
typeParamKey: string; // 类型参数名称,获取资源列表接口使用 typeParamKey: string; // 类型参数名称,获取资源列表接口使用
tagParamKey: string; // 标签参数名称,获取资源列表接口使用 tagParamKey: string; // 标签参数名称,获取资源列表接口使用
fileReqParamKey: 'models_id' | 'dataset_id'; // 文件请求参数名称,获取文件列表接口使用
filePropKey: string;
tabItems: TabsProps['items']; // tab 列表 tabItems: TabsProps['items']; // tab 列表
typeTitle: string; // 类型标题 typeTitle: string; // 类型标题
tagTitle: string; // 标签标题 tagTitle: string; // 标签标题
@@ -40,13 +40,10 @@ type ResourceTypeInfo = {
prefix: string; // 图片资源、详情 url 的前缀 prefix: string; // 图片资源、详情 url 的前缀
deleteModalTitle: string; // 删除弹框的title deleteModalTitle: string; // 删除弹框的title
addBtnTitle: string; // 新增按钮的title addBtnTitle: string; // 新增按钮的title
idParamKey: 'models_id' | 'dataset_id'; // 新建版本、删除版本接口,版本 id 的参数名称
uploadAction: string; // 上传接口 url uploadAction: string; // 上传接口 url
uploadAccept?: string; // 上传文件类型 uploadAccept?: string; // 上传文件类型
downloadAllAction: string; // 批量下载接口 url downloadAllAction: string; // 批量下载接口 url
downloadSingleAction: string; // 单个下载接口 url downloadSingleAction: string; // 单个下载接口 url
infoTypePropertyName: string; // 详情数据中,类型属性名称
infoTagPropertyName: string; // 详情数据中,标签属性名称
}; };


export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = {
@@ -60,7 +57,7 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = {
name: '数据集', name: '数据集',
typeParamKey: 'data_type', typeParamKey: 'data_type',
tagParamKey: 'data_tag', tagParamKey: 'data_tag',
fileReqParamKey: 'dataset_id',
filePropKey: 'dataset_version_vos',
tabItems: [ tabItems: [
{ {
key: CommonTabKeys.Public, key: CommonTabKeys.Public,
@@ -80,25 +77,22 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = {
prefix: 'dataset', prefix: 'dataset',
deleteModalTitle: '确定删除该条数据集实例吗?', deleteModalTitle: '确定删除该条数据集实例吗?',
addBtnTitle: '新建数据集', addBtnTitle: '新建数据集',
idParamKey: 'dataset_id',
uploadAction: '/api/mmp/newdataset/upload', uploadAction: '/api/mmp/newdataset/upload',
uploadAccept: '.zip,.tgz', uploadAccept: '.zip,.tgz',
downloadAllAction: '/api/mmp/newdataset/downloadAllFiles', downloadAllAction: '/api/mmp/newdataset/downloadAllFiles',
downloadSingleAction: '/api/mmp/newdataset/downloadSinggerFile', downloadSingleAction: '/api/mmp/newdataset/downloadSinggerFile',
infoTypePropertyName: 'data_type',
infoTagPropertyName: 'data_tag',
}, },
[ResourceType.Model]: { [ResourceType.Model]: {
getList: getModelList, getList: getModelList,
getVersions: getModelVersionsById,
getVersions: getModelVersionList,
deleteRecord: deleteModel, deleteRecord: deleteModel,
addVersion: addModelsVersionDetail,
addVersion: addModelVersion,
deleteVersion: deleteModelVersion, deleteVersion: deleteModelVersion,
getInfo: getModelById,
getInfo: getModelInfo,
name: '模型', name: '模型',
typeParamKey: 'model_type', typeParamKey: 'model_type',
tagParamKey: 'model_tag', tagParamKey: 'model_tag',
fileReqParamKey: 'models_id',
filePropKey: 'model_version_vos',
tabItems: [ tabItems: [
{ {
key: CommonTabKeys.Public, key: CommonTabKeys.Public,
@@ -118,13 +112,10 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = {
prefix: 'model', prefix: 'model',
deleteModalTitle: '确定删除该条模型实例吗?', deleteModalTitle: '确定删除该条模型实例吗?',
addBtnTitle: '新建模型', addBtnTitle: '新建模型',
idParamKey: 'models_id',
uploadAction: '/api/mmp/models/upload',
uploadAction: '/api/mmp/newmodel/upload',
uploadAccept: undefined, uploadAccept: undefined,
downloadAllAction: '/api/mmp/models/downloadAllFiles',
downloadSingleAction: '/api/mmp/models/download_model',
infoTypePropertyName: 'model_type_name',
infoTagPropertyName: 'model_tag_name',
downloadAllAction: '/api/mmp/newmodel/downloadAllFiles',
downloadSingleAction: '/api/mmp/newmodel/downloadSingleFile',
}, },
}; };


@@ -136,27 +127,39 @@ export type CategoryData = {
path: string; path: string;
}; };


// 资源数据
// 数据集、模型列表数据
export type ResourceData = { export type ResourceData = {
id: number; id: number;
name: string; name: string;
identifier: string; identifier: string;
description: string;
create_by: string;
owner: string; owner: string;
update_time: string;
time_ago: string;
version: string;
is_public: boolean; is_public: boolean;
model_type_name?: string;
model_tag_name?: string;
data_type?: string;
data_tag?: string;
version?: string;
description?: string;
create_by?: string;
update_time?: string;
time_ago?: string;
version_desc?: string; version_desc?: string;
processing_code?: string;
dataset_source?: string;
usage?: string; usage?: string;
relative_paths?: string;
// 数据集
data_type?: string; // 数据集分类
data_tag?: string; // 研究方向
processing_code?: string; // 处理代码
dataset_source?: string; // 数据来源
dataset_version_vos: ResourceFileData[]; dataset_version_vos: ResourceFileData[];
// 模型
model_type?: string; // 模型框架
model_tag?: string; // 模型能力
image?: string; // 训练镜像
code?: string; // 训练镜像
train_datasets?: string[]; // 训练数据集
test_datasets?: string[]; // 测试数据集
params?: Record<string, string>; // 参数
metrics?: Record<string, string>; // 指标
train_task?: string; // 训练任务
model_source?: string; // 模型来源
model_version_vos: ResourceFileData[];
}; };


// 版本数据 // 版本数据


+ 4
- 4
react-ui/src/pages/Experiment/components/ExportModelModal/index.tsx View File

@@ -2,10 +2,10 @@ import editExperimentIcon from '@/assets/img/edit-experiment.png';
import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import { type ResourceData } from '@/pages/Dataset/config'; import { type ResourceData } from '@/pages/Dataset/config';
import { import {
addModelsVersionDetail,
addModelVersion,
exportModelReq, exportModelReq,
getModelList, getModelList,
getModelVersionsById,
getModelVersionList,
} from '@/services/dataset'; } from '@/services/dataset';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { InfoCircleOutlined } from '@ant-design/icons'; import { InfoCircleOutlined } from '@ant-design/icons';
@@ -85,7 +85,7 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) {


// 获取模型版本列表 // 获取模型版本列表
const getModelVersions = async (id: number) => { const getModelVersions = async (id: number) => {
const [res] = await to(getModelVersionsById(id));
const [res] = await to(getModelVersionList(id));
if (res && res.data) { if (res && res.data) {
setVersions(res.data); setVersions(res.data);
} }
@@ -118,7 +118,7 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) {


// 创建模型版本 // 创建模型版本
const createModelVersion = async (params: CreateModelVersionParams[]) => { const createModelVersion = async (params: CreateModelVersionParams[]) => {
const [res] = await to(addModelsVersionDetail(params));
const [res] = await to(addModelVersion(params));
if (res) { if (res) {
onOk(); onOk();
} }


+ 5
- 15
react-ui/src/pages/Model/components/ModelEvolution/index.tsx View File

@@ -5,13 +5,11 @@
*/ */


import { useEffectWhen } from '@/hooks'; import { useEffectWhen } from '@/hooks';
import { ResourceVersionData } from '@/pages/Dataset/config';
import { getModelAtlasReq } from '@/services/dataset/index.js'; import { getModelAtlasReq } from '@/services/dataset/index.js';
import themes from '@/styles/theme.less'; import themes from '@/styles/theme.less';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import G6, { G6GraphEvent, Graph, INode } from '@antv/g6'; import G6, { G6GraphEvent, Graph, INode } from '@antv/g6';
// @ts-ignore
import { Flex, Select } from 'antd';
import { Flex } from 'antd';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import GraphLegend from '../GraphLegend'; import GraphLegend from '../GraphLegend';
import NodeTooltips from '../NodeTooltips'; import NodeTooltips from '../NodeTooltips';
@@ -29,7 +27,7 @@ import {


type modeModelEvolutionProps = { type modeModelEvolutionProps = {
resourceId: number; resourceId: number;
versionList: ResourceVersionData[];
identifier: string;
version?: string; version?: string;
isActive: boolean; isActive: boolean;
onVersionChange: (version: string) => void; onVersionChange: (version: string) => void;
@@ -38,7 +36,7 @@ type modeModelEvolutionProps = {
let graph: Graph; let graph: Graph;
function ModelEvolution({ function ModelEvolution({
resourceId, resourceId,
versionList,
identifier,
version, version,
isActive, isActive,
onVersionChange, onVersionChange,
@@ -217,7 +215,8 @@ function ModelEvolution({
// 获取模型依赖 // 获取模型依赖
const getModelAtlas = async () => { const getModelAtlas = async () => {
const params = { const params = {
current_model_id: resourceId,
id: resourceId,
identifier,
version, version,
}; };
const [res] = await to(getModelAtlasReq(params)); const [res] = await to(getModelAtlasReq(params));
@@ -250,15 +249,6 @@ function ModelEvolution({
return ( return (
<div className={styles['model-evolution']}> <div className={styles['model-evolution']}>
<Flex align="center" className={styles['model-evolution__top']}> <Flex align="center" className={styles['model-evolution__top']}>
<span style={{ marginRight: '10px' }}>版本号:</span>
<Select
placeholder="请选择版本号"
style={{ width: '160px', marginRight: '20px' }}
value={version}
allowClear
onChange={onVersionChange}
options={versionList}
/>
<GraphLegend style={{ marginRight: 0, marginLeft: 'auto' }}></GraphLegend> <GraphLegend style={{ marginRight: 0, marginLeft: 'auto' }}></GraphLegend>
</Flex> </Flex>
<div className={styles['model-evolution__graph']} id="canvas" ref={graphRef}></div> <div className={styles['model-evolution__graph']} id="canvas" ref={graphRef}></div>


+ 4
- 4
react-ui/src/pages/Model/intro.tsx View File

@@ -1,8 +1,8 @@
import ResourceIntro from '@/pages/Dataset/components/ResourceIntro';
import ResourceInfo from '@/pages/Dataset/components/ResourceInfo';
import { ResourceType } from '@/pages/Dataset/config'; import { ResourceType } from '@/pages/Dataset/config';


function ModelIntro() {
return <ResourceIntro resourceType={ResourceType.Model} />;
function ModelInfo() {
return <ResourceInfo resourceType={ResourceType.Model} />;
} }


export default ModelIntro;
export default ModelInfo;

+ 14
- 17
react-ui/src/pages/Pipeline/components/ResourceSelectorModal/config.tsx View File

@@ -9,9 +9,9 @@ import {
getDatasetInfo, getDatasetInfo,
getDatasetList, getDatasetList,
getDatasetVersionList, getDatasetVersionList,
getModelInfo,
getModelList, getModelList,
getModelVersionIdList,
getModelVersionsById,
getModelVersionList,
} from '@/services/dataset/index.js'; } from '@/services/dataset/index.js';
import { getMirrorListReq, getMirrorVersionListReq } from '@/services/mirror'; import { getMirrorListReq, getMirrorVersionListReq } from '@/services/mirror';
import type { TabsProps, TreeDataNode } from 'antd'; import type { TabsProps, TreeDataNode } from 'antd';
@@ -121,7 +121,7 @@ const convertMirrorVersionToTreeData = (
// export const selectorTypeConfig: Record<ResourceSelectorType, SelectorTypeInfo> = { // export const selectorTypeConfig: Record<ResourceSelectorType, SelectorTypeInfo> = {
// [ResourceSelectorType.Model]: { // [ResourceSelectorType.Model]: {
// getList: getModelList, // getList: getModelList,
// getVersions: getModelVersionsById,
// getVersions: getModelVersionList,
// getFiles: getModelVersionIdList, // getFiles: getModelVersionIdList,


// name: '模型', // name: '模型',
@@ -226,7 +226,6 @@ export class DatasetSelector implements SelectorTypeInfo {
} }
} }
async getVersions(parentKey: string, parentNode: ResourceData) { async getVersions(parentKey: string, parentNode: ResourceData) {
// const obj = parseDatasetVersionId(id);
const res = await getDatasetVersionList(pick(parentNode, ['owner', 'identifier'])); const res = await getDatasetVersionList(pick(parentNode, ['owner', 'identifier']));
if (res && res.data) { if (res && res.data) {
const list = res.data; const list = res.data;
@@ -237,7 +236,6 @@ export class DatasetSelector implements SelectorTypeInfo {
} }


async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) { async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) {
//const obj = parseDatasetVersionId(parentKey);
const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version']); const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version']);
const res = await getDatasetInfo(params); const res = await getDatasetInfo(params);
if (res && res.data) { if (res && res.data) {
@@ -275,32 +273,31 @@ export class ModelSelector implements SelectorTypeInfo {
const list = res.data.content || []; const list = res.data.content || [];
return convertDatasetToTreeData(list); return convertDatasetToTreeData(list);
} else { } else {
return Promise.reject('获取数据集列表失败');
return Promise.reject('获取模型列表失败');
} }
} }
async getVersions(key: string, parentNode: ResourceData) { async getVersions(key: string, parentNode: ResourceData) {
//const obj = parseDatasetVersionId(id);
const res = await getModelVersionIdList(pick(parentNode, ['owner', 'identifier']));
const res = await getModelVersionList(pick(parentNode, ['owner', 'identifier']));
if (res && res.data) { if (res && res.data) {
const list = res.data.content || [];
const list = res.data;
return convertDatasetVersionToTreeData(key, parentNode, list); return convertDatasetVersionToTreeData(key, parentNode, list);
} else { } else {
return Promise.reject('获取数据集版本列表失败');
return Promise.reject('获取模型版本列表失败');
} }
} }


async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) { async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) {
// const obj = parseDatasetVersionId(id);
const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version']); const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version']);
const res = await getModelVersionsById(params);
const res = await getModelInfo(params);
if (res && res.data) { if (res && res.data) {
const list = res.data.dataset_version_vos || [];
const path = res.data.relative_paths || '';
const list = res.data.model_version_vos || [];
return { return {
path: res.data.path || '',
path,
content: list, content: list,
}; };
} else { } else {
return Promise.reject('获取数据集文件列表失败');
return Promise.reject('获取模型文件列表失败');
} }
} }
} }
@@ -348,13 +345,13 @@ export class MirrorSelector implements SelectorTypeInfo {
} }
} }


async getFiles(parentKey: string, parentNode: MirrorVersionData) {
async getFiles(_parentKey: string, parentNode: MirrorVersionData) {
const { url } = parentNode; const { url } = parentNode;
return { return {
path: url, path: url,
content: [ content: [
{ {
id: parentKey,
url: url,
file_name: `${url}`, file_name: `${url}`,
}, },
], ],


+ 5
- 5
react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.less View File

@@ -34,6 +34,11 @@
border-bottom: 1px solid @border-color-secondary; border-bottom: 1px solid @border-color-secondary;
border-radius: 0; border-radius: 0;
} }

&__tree-title {
display: inline-block;
.singleLine();
}
} }


&__right { &__right {
@@ -67,8 +72,3 @@
} }
} }
} }

.kf-tree-title {
display: inline-block;
.singleLine();
}

+ 6
- 11
react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.tsx View File

@@ -6,6 +6,7 @@


import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import { CommonTabKeys } from '@/enums'; import { CommonTabKeys } from '@/enums';
import { ResourceFileData } from '@/pages/Dataset/config';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { Icon } from '@umijs/max'; import { Icon } from '@umijs/max';
import type { GetRef, ModalProps, TreeDataNode, TreeProps } from 'antd'; import type { GetRef, ModalProps, TreeDataNode, TreeProps } from 'antd';
@@ -24,11 +25,6 @@ export type ResourceSelectorResponse = {
activeTab: CommonTabKeys; // 是我的还是公开的 activeTab: CommonTabKeys; // 是我的还是公开的
}; };


type ResourceFile = {
id: number; // 文件 id
file_name: string; // 文件 name
};

export interface ResourceSelectorModalProps extends Omit<ModalProps, 'onOk'> { export interface ResourceSelectorModalProps extends Omit<ModalProps, 'onOk'> {
type: ResourceSelectorType; // 数据集\模型\镜像 type: ResourceSelectorType; // 数据集\模型\镜像
defaultExpandedKeys?: React.Key[]; defaultExpandedKeys?: React.Key[];
@@ -76,7 +72,7 @@ function ResourceSelectorModal({
const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]); const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
const [loadedKeys, setLoadedKeys] = useState<React.Key[]>([]); const [loadedKeys, setLoadedKeys] = useState<React.Key[]>([]);
const [originTreeData, setOriginTreeData] = useState<TreeDataNode[]>([]); const [originTreeData, setOriginTreeData] = useState<TreeDataNode[]>([]);
const [files, setFiles] = useState<ResourceFile[]>([]);
const [files, setFiles] = useState<ResourceFileData[]>([]);
const [versionPath, setVersionPath] = useState(''); const [versionPath, setVersionPath] = useState('');
const [searchText, setSearchText] = useState(''); const [searchText, setSearchText] = useState('');
const [firstLoadList, setFirstLoadList] = useState(false); const [firstLoadList, setFirstLoadList] = useState(false);
@@ -175,6 +171,7 @@ function ResourceSelectorModal({
const lastNode = checkedNodes[checkedNodes.length - 1]; const lastNode = checkedNodes[checkedNodes.length - 1];
getFiles(last, lastNode); getFiles(last, lastNode);
} else { } else {
setVersionPath('');
setFiles([]); setFiles([]);
} }
}; };
@@ -278,26 +275,24 @@ function ResourceSelectorModal({
loadedKeys={loadedKeys} loadedKeys={loadedKeys}
expandedKeys={expandedKeys} expandedKeys={expandedKeys}
onExpand={onExpand} onExpand={onExpand}
checkable
titleRender={(nodeData) => { titleRender={(nodeData) => {
console.log(nodeData);

return ( return (
<span <span
className={styles['kf-tree-title']}
className={styles['model-selector__left__tree-title']}
style={{ width: nodeData.isLeaf ? '370px' : '420px' }} style={{ width: nodeData.isLeaf ? '370px' : '420px' }}
> >
{nodeData.title as string} {nodeData.title as string}
</span> </span>
); );
}} }}
checkable
/> />
</div> </div>
<div className={styles['model-selector__right']}> <div className={styles['model-selector__right']}>
<div className={styles['model-selector__right__title']}>{fileTitle}</div> <div className={styles['model-selector__right__title']}>{fileTitle}</div>
<div className={styles['model-selector__right__files']}> <div className={styles['model-selector__right__files']}>
{files.map((v) => ( {files.map((v) => (
<div key={v.id} className={styles['model-selector__right__files__file']}>
<div key={v.url} className={styles['model-selector__right__files__file']}>
{v.file_name} {v.file_name}
</div> </div>
))} ))}


+ 2
- 2
react-ui/src/pages/missingPage.jsx View File

@@ -11,8 +11,8 @@ const MissingPage = () => {
title="敬请期待~" title="敬请期待~"
content={'很抱歉,您访问的正在开发中,\n请耐心等待。'} content={'很抱歉,您访问的正在开发中,\n请耐心等待。'}
hasFooter={true} hasFooter={true}
backTitle="返回首页"
onBack={() => navigate('/')}
buttonTitle="返回首页"
onRefresh={() => navigate('/')}
></KFEmpty> ></KFEmpty>
); );
}; };


+ 1
- 0
react-ui/src/requestConfig.ts View File

@@ -26,6 +26,7 @@ const popupError = (error: string, skipErrorHandler: boolean | undefined = false
* @doc https://umijs.org/docs/max/request#配置 * @doc https://umijs.org/docs/max/request#配置
*/ */
export const requestConfig: RequestConfig = { export const requestConfig: RequestConfig = {
timeout: 120 * 1000,
requestInterceptors: [ requestInterceptors: [
(url: string, options: AxiosRequestConfig) => { (url: string, options: AxiosRequestConfig) => {
const headers = options.headers ?? {}; const headers = options.headers ?? {};


+ 23
- 46
react-ui/src/services/dataset/index.js View File

@@ -27,12 +27,9 @@ export function getDatasetInfo(params) {
} }


// 新增数据集 // 新增数据集
export function addDateset(data) {
export function addDataset(data) {
return request(`/api/mmp/newdataset/addDatasetAndVersion`, { return request(`/api/mmp/newdataset/addDatasetAndVersion`, {
method: 'POST', method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
data, data,
}); });
} }
@@ -54,21 +51,10 @@ export function getDatasetVersionList(params) {
}); });
} }


// 查询数据集版本文件列表
// export function getDatasetVersionFiles(params) {
// return request(`/api/mmp/datasetVersion/versions`, {
// method: 'GET',
// params,
// });
// }

// 新增数据集版本 // 新增数据集版本
export function addDatasetVersion(data) { export function addDatasetVersion(data) {
return request(`/api/mmp/newdataset/addVersion`, { return request(`/api/mmp/newdataset/addVersion`, {
method: 'POST', method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
data, data,
}); });
} }
@@ -101,7 +87,7 @@ export function deleteDatasetVersion(params) {


// 分页查询模型列表 // 分页查询模型列表
export function getModelList(params) { export function getModelList(params) {
return request(`/api/mmp/models`, {
return request(`/api/mmp/newmodel/queryModels`, {
method: 'GET', method: 'GET',
params, params,
}); });
@@ -109,68 +95,59 @@ export function getModelList(params) {


// 新增模型 // 新增模型
export function addModel(data) { export function addModel(data) {
return request(`/api/mmp/models/addModelAndVersion`, {
return request(`/api/mmp/newmodel/addModel`, {
method: 'POST', method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
data, data,
}); });
} }


// 查询模型简介
export function getModelById(id) {
return request(`/api/mmp/models/${id}`, {
method: 'GET',
// 删除模型
export function deleteModel(params) {
return request(`/api/mmp/newmodel/delete`, {
method: 'DELETE',
params,
}); });
} }


// 查询模型版本列表
export function getModelVersionsById(id) {
return request(`/api/mmp/models/versions/${id}`, {

// 查询模型详情
export function getModelInfo(params) {
return request(`/api/mmp/newmodel/getModelDetail`, {
method: 'GET', method: 'GET',
params,
}); });
} }


// 根据版本查询文件列表
export function getModelVersionIdList(params) {
return request(`/api/mmp/modelsVersion/versions`, {
// 查询模型版本列表
export function getModelVersionList(params) {
return request(`/api/mmp/newmodel/getVersionList`, {
method: 'GET', method: 'GET',
params, params,
}); });
} }


// 新增模型版本 // 新增模型版本
export function addModelsVersionDetail(data) {
return request(`/api/mmp/modelsVersion/addModelVersions`, {
export function addModelVersion(data) {
return request(`/api/mmp/newmodel/addVersion`, {
method: 'POST', method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
data, data,
}); });
} }


// 删除模型
export function deleteModel(id) {
return request(`/api/mmp/models/${id}`, {
method: 'DELETE',
});
}


// 删除模型版本 // 删除模型版本
export function deleteModelVersion(params) { export function deleteModelVersion(params) {
return request(`/api/mmp/modelsVersion/deleteVersion`, {
return request(`/api/mmp/newmodel/deleteVersion`, {
method: 'DELETE', method: 'DELETE',
params, params,
}); });
} }


// 获取模型依赖 // 获取模型依赖
export function getModelAtlasReq(data) {
return request(`/api/mmp/modelDependency/queryModelAtlas`, {
method: 'POST',
data
export function getModelAtlasReq(params) {
return request(`/api/mmp/newmodel/getModelDependencyTree`, {
method: 'GET',
params
}); });
} }




+ 10
- 0
react-ui/src/utils/index.ts View File

@@ -190,3 +190,13 @@ export const fittingString = (str: string, maxWidth: number, fontSize: number) =
}); });
return res; return res;
}; };

/**
* Checks if a given string is empty, undefined, or null.
*
* @param {any} str - the string to be checked
* @return {boolean} true if the string is empty, undefined, or null, false otherwise
*/
export const isEmptyString = (str: any): boolean => {
return str === '' || str === undefined || str === null;
};

Loading…
Cancel
Save