| @@ -5,31 +5,40 @@ | |||
| gap: 20px 40px; | |||
| align-items: flex-start; | |||
| 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; | |||
| } | |||
| } | |||
| @@ -1,27 +1,73 @@ | |||
| import { isEmptyString } from '@/utils'; | |||
| import { Link } from '@umijs/max'; | |||
| import classNames from 'classnames'; | |||
| import './index.less'; | |||
| export type BasicInfoData = { | |||
| label: string; | |||
| value?: any; | |||
| format?: (_value: any) => string; | |||
| link?: string; | |||
| externalLink?: string; | |||
| format?: (_value?: any) => string | undefined; | |||
| }; | |||
| type BasicInfoProps = { | |||
| datas: BasicInfoData[]; | |||
| className?: string; | |||
| style?: React.CSSProperties; | |||
| labelWidth?: number; | |||
| }; | |||
| function BasicInfo({ datas }: BasicInfoProps) { | |||
| function BasicInfo({ datas, className, style, labelWidth = 100 }: BasicInfoProps) { | |||
| return ( | |||
| <div className="kf-basic-info"> | |||
| <div className={classNames('kf-basic-info', className)} style={style}> | |||
| {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> | |||
| ); | |||
| } | |||
| 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; | |||
| @@ -7,7 +7,6 @@ | |||
| &__image { | |||
| width: 475px; | |||
| height: 292px; | |||
| } | |||
| &__title { | |||
| @@ -15,7 +14,6 @@ | |||
| color: @text-color; | |||
| font-weight: 500; | |||
| font-size: 30px; | |||
| letter-spacing: 5px; | |||
| text-align: center; | |||
| } | |||
| @@ -32,6 +30,7 @@ | |||
| align-items: center; | |||
| justify-content: center; | |||
| margin-top: 20px; | |||
| margin-bottom: 30px; | |||
| &__back-btn { | |||
| height: 32px; | |||
| @@ -16,8 +16,8 @@ type EmptyProps = { | |||
| content?: string; | |||
| hasFooter?: boolean; | |||
| footer?: () => React.ReactNode; | |||
| backTitle?: string; | |||
| onBack?: () => void; | |||
| buttonTitle?: string; | |||
| onRefresh?: () => void; | |||
| }; | |||
| function getEmptyImage(type: EmptyType) { | |||
| @@ -39,8 +39,8 @@ function KFEmpty({ | |||
| content, | |||
| hasFooter = false, | |||
| footer, | |||
| backTitle = '返回', | |||
| onBack, | |||
| buttonTitle = '刷新', | |||
| onRefresh, | |||
| }: EmptyProps) { | |||
| const image = getEmptyImage(type); | |||
| @@ -54,8 +54,8 @@ function KFEmpty({ | |||
| {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> | |||
| )} | |||
| </div> | |||
| @@ -14,7 +14,7 @@ const filterResourceStandard: SelectProps<string, ComputingResource>['filterOpti | |||
| }; | |||
| // 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 = { | |||
| getOptions: () => Promise<any>; // 获取下拉数据 | |||
| @@ -11,8 +11,8 @@ const NoFoundPage = () => { | |||
| title="404" | |||
| content={'很抱歉,您访问的页面地址有误,\n或者该页面不存在。'} | |||
| hasFooter={true} | |||
| backTitle="返回首页" | |||
| onBack={() => navigate('/')} | |||
| buttonTitle="返回首页" | |||
| onRefresh={() => navigate('/')} | |||
| ></KFEmpty> | |||
| ); | |||
| }; | |||
| @@ -171,6 +171,9 @@ function CodeConfigList() { | |||
| className={styles['code-config-list__empty']} | |||
| type={EmptyType.NoData} | |||
| title="暂无数据" | |||
| content={'很抱歉,没有搜索到您想要的内容\n建议刷新试试'} | |||
| hasFooter={true} | |||
| onRefresh={getDataList} | |||
| /> | |||
| )} | |||
| </div> | |||
| @@ -1,7 +1,8 @@ | |||
| import { getAccessToken } from '@/access'; | |||
| import KFIcon from '@/components/KFIcon'; | |||
| 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 { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; | |||
| import { | |||
| @@ -18,7 +19,6 @@ import { | |||
| } from 'antd'; | |||
| import { omit } from 'lodash'; | |||
| import { useState } from 'react'; | |||
| import { CategoryData } from '../../config'; | |||
| import styles from './index.less'; | |||
| interface AddDatasetModalProps extends Omit<ModalProps, 'onOk'> { | |||
| @@ -37,7 +37,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||
| // 上传组件参数 | |||
| const uploadProps: UploadProps = { | |||
| action: '/api/mmp/newdataset/upload', | |||
| action: resourceConfig[ResourceType.Dataset].uploadAction, | |||
| headers: { | |||
| Authorization: getAccessToken() || '', | |||
| }, | |||
| @@ -54,7 +54,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||
| // 上传请求 | |||
| const createDataset = async (params: any) => { | |||
| const [res] = await to(addDateset(params)); | |||
| const [res] = await to(addDataset(params)); | |||
| if (res) { | |||
| message.success('创建成功'); | |||
| onOk?.(); | |||
| @@ -120,6 +120,14 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||
| required: true, | |||
| message: '请输入数据集版本', | |||
| }, | |||
| { | |||
| validator: (_rule, value) => { | |||
| if (value === 'master') { | |||
| return Promise.reject(`版本不能为 master`); | |||
| } | |||
| return Promise.resolve(); | |||
| }, | |||
| }, | |||
| ]} | |||
| > | |||
| <Input placeholder="请输入数据集版本" showCount allowClear maxLength={64} /> | |||
| @@ -1,7 +1,7 @@ | |||
| import { getAccessToken } from '@/access'; | |||
| import KFIcon from '@/components/KFIcon'; | |||
| 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 { to } from '@/utils/promise'; | |||
| import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; | |||
| @@ -9,6 +9,7 @@ import { | |||
| Button, | |||
| Form, | |||
| Input, | |||
| Radio, | |||
| Select, | |||
| Upload, | |||
| UploadFile, | |||
| @@ -31,7 +32,7 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||
| // 上传组件参数 | |||
| const uploadProps: UploadProps = { | |||
| action: '/api/mmp/models/upload', | |||
| action: resourceConfig[ResourceType.Model].uploadAction, | |||
| headers: { | |||
| Authorization: getAccessToken() || '', | |||
| }, | |||
| @@ -53,7 +54,7 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||
| if (validateUploadFiles(fileList)) { | |||
| const params = { | |||
| ...omit(formData, ['fileList']), | |||
| models_version_vos: fileList.map((item) => { | |||
| model_version_vos: fileList.map((item) => { | |||
| const data = item.response?.data?.[0] ?? {}; | |||
| return { | |||
| file_name: data.fileName, | |||
| @@ -77,7 +78,13 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||
| 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 | |||
| label="模型名称" | |||
| 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 | |||
| label="模型版本" | |||
| name="version" | |||
| @@ -99,40 +105,24 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||
| required: true, | |||
| 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 label="可见范围" name="available_range"> | |||
| <Radio.Group> | |||
| <Radio value="0">仅自己可见</Radio> | |||
| <Radio value="1">工作空间可见</Radio> | |||
| </Radio.Group> | |||
| </Form.Item> */} | |||
| <Form.Item label="模型框架" name="model_type"> | |||
| <Select | |||
| allowClear | |||
| placeholder="请选择模型类型" | |||
| options={typeList} | |||
| fieldNames={{ label: 'name', value: 'id' }} | |||
| fieldNames={{ label: 'name', value: 'name' }} | |||
| optionFilterProp="name" | |||
| showSearch | |||
| /> | |||
| @@ -142,11 +132,39 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||
| allowClear | |||
| placeholder="请选择模型标签" | |||
| options={tagList} | |||
| fieldNames={{ label: 'name', value: 'id' }} | |||
| fieldNames={{ label: 'name', value: 'name' }} | |||
| optionFilterProp="name" | |||
| showSearch | |||
| /> | |||
| </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 | |||
| label="模型文件" | |||
| name="fileList" | |||
| @@ -60,7 +60,7 @@ function AddVersionModal({ | |||
| const onFinish = (formData: any) => { | |||
| const fileList: UploadFile[] = formData['fileList'] ?? []; | |||
| if (validateUploadFiles(fileList)) { | |||
| const dataset_version_vos = fileList.map((item) => { | |||
| const version_vos = fileList.map((item) => { | |||
| const data = item.response?.data?.[0] ?? {}; | |||
| return { | |||
| file_name: data.fileName, | |||
| @@ -71,7 +71,7 @@ function AddVersionModal({ | |||
| const params = { | |||
| id: resourceId, | |||
| identifier, | |||
| dataset_version_vos, | |||
| [config.filePropKey]: version_vos, | |||
| ...omit(formData, 'fileList'), | |||
| }; | |||
| createDatasetVersion(params); | |||
| @@ -123,7 +123,7 @@ function AddVersionModal({ | |||
| { | |||
| validator: (_rule, value) => { | |||
| if (value === 'master') { | |||
| return Promise.reject(`版本号不能为 master`); | |||
| return Promise.reject(`版本不能为 master`); | |||
| } | |||
| return Promise.resolve(); | |||
| }, | |||
| @@ -127,14 +127,12 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||
| const deleteVersion = async () => { | |||
| const request = config.deleteVersion; | |||
| const params = { | |||
| identifier: info.identifier, | |||
| owner: info.owner, | |||
| ...pick(info, ['id', 'owner', 'identifier', 'relative_paths']), | |||
| version, | |||
| }; | |||
| const [res] = await to(request(params)); | |||
| if (res) { | |||
| message.success('删除成功'); | |||
| setVersion(undefined); | |||
| getVersionList(pick(info, ['owner', 'identifier'])); | |||
| } | |||
| }; | |||
| @@ -175,8 +173,8 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||
| children: ( | |||
| <ModelEvolution | |||
| resourceId={resourceId} | |||
| versionList={versionList} | |||
| version={version} | |||
| identifier={info.identifier} | |||
| isActive={activeTab === ResourceInfoTabKeys.Evolution} | |||
| onVersionChange={handleVersionChange} | |||
| ></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 ( | |||
| <div className={styles['resource-info']}> | |||
| <div className={styles['resource-info__top']}> | |||
| <Flex align="center" gap={10} style={{ marginBottom: '20px' }}> | |||
| <div className={styles['resource-info__top__name']}>{info.name}</div> | |||
| {info[infoTypePropertyName] && ( | |||
| {info[typePropertyName] && ( | |||
| <div className={styles['resource-info__top__tag']}> | |||
| {(info[infoTypePropertyName] as string) || '--'} | |||
| {(info[typePropertyName] as string) || '--'} | |||
| </div> | |||
| )} | |||
| {info[infoTagPropertyName] && ( | |||
| {info[tagPropertyName] && ( | |||
| <div className={styles['resource-info__top__tag']}> | |||
| {(info[infoTagPropertyName] as string) || '--'} | |||
| {(info[tagPropertyName] as string) || '--'} | |||
| </div> | |||
| )} | |||
| </Flex> | |||
| @@ -8,8 +8,24 @@ type ResourceIntroProps = { | |||
| 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: '数据集名称', | |||
| 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 ( | |||
| <div className={styles['resource-intro']}> | |||
| <SubAreaTitle | |||
| @@ -60,7 +150,7 @@ function ResourceIntro({ info }: ResourceIntroProps) { | |||
| style={{ marginBottom: '26px' }} | |||
| ></SubAreaTitle> | |||
| <div className={styles['resource-intro__basic']}> | |||
| <BasicInfo datas={basicDatas}></BasicInfo> | |||
| <BasicInfo datas={basicDatas} labelWidth={86}></BasicInfo> | |||
| </div> | |||
| <SubAreaTitle | |||
| title="实例用法" | |||
| @@ -40,7 +40,7 @@ function ResourceItem({ item, isPublic, onClick, onRemove }: ResourceItemProps) | |||
| <Flex justify="space-between"> | |||
| <div className={styles['resource-item__time']}> | |||
| <img style={{ width: '17px', marginRight: '6px' }} src={creatByImg} alt="" /> | |||
| <span>{item.create_by}</span> | |||
| <span>{item.create_by ?? ''}</span> | |||
| </div> | |||
| <div className={styles['resource-item__time']}> | |||
| <img style={{ width: '12px', marginRight: '5px' }} src={clock} alt="" /> | |||
| @@ -87,15 +87,11 @@ function ResourceList( | |||
| const params: Record<string, any> = { | |||
| page: pagination.current! - 1, | |||
| size: pagination.pageSize, | |||
| is_public: isPublic, | |||
| [config.typeParamKey]: dataType, | |||
| [config.tagParamKey]: dataTag, | |||
| name: searchText !== '' ? searchText : undefined, | |||
| }; | |||
| if (resourceType === ResourceType.Dataset) { | |||
| params['is_public'] = isPublic; | |||
| } else { | |||
| params['available_range'] = isPublic ? 1 : 0; | |||
| } | |||
| const request = config.getList; | |||
| const [res] = await to(request(params)); | |||
| 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 [res] = await to(request(params)); | |||
| if (res) { | |||
| @@ -127,7 +123,7 @@ function ResourceList( | |||
| modalConfirm({ | |||
| title: config.deleteModalTitle, | |||
| onOk: () => { | |||
| deleteRecord(pick(record, ['owner', 'identifier'])); | |||
| deleteRecord(pick(record, ['owner', 'identifier', 'id'])); | |||
| }, | |||
| }); | |||
| }; | |||
| @@ -223,6 +219,9 @@ function ResourceList( | |||
| className={styles['resource-list__empty']} | |||
| type={EmptyType.NoData} | |||
| title="暂无数据" | |||
| content={'很抱歉,没有搜索到您想要的内容\n建议刷新试试'} | |||
| hasFooter={true} | |||
| onRefresh={getDataList} | |||
| /> | |||
| )} | |||
| </div> | |||
| @@ -17,7 +17,8 @@ type ResourceVersionProps = { | |||
| }; | |||
| function ResourceVersion({ resourceType, info }: ResourceVersionProps) { | |||
| 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)); | |||
| // 全部导出 | |||
| @@ -97,7 +98,7 @@ function ResourceVersion({ resourceType, info }: ResourceVersionProps) { | |||
| </Button> | |||
| </Flex> | |||
| </Flex> | |||
| <Table columns={columns} dataSource={fileList} pagination={false} rowKey="id" /> | |||
| <Table columns={columns} dataSource={fileList} pagination={false} rowKey="url" /> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -2,7 +2,7 @@ import KFIcon from '@/components/KFIcon'; | |||
| import { CommonTabKeys } from '@/enums'; | |||
| import { | |||
| addDatasetVersion, | |||
| addModelsVersionDetail, | |||
| addModelVersion, | |||
| deleteDataset, | |||
| deleteDatasetVersion, | |||
| deleteModel, | |||
| @@ -10,9 +10,9 @@ import { | |||
| getDatasetInfo, | |||
| getDatasetList, | |||
| getDatasetVersionList, | |||
| getModelById, | |||
| getModelInfo, | |||
| getModelList, | |||
| getModelVersionsById, | |||
| getModelVersionList, | |||
| } from '@/services/dataset/index.js'; | |||
| import type { TabsProps } from 'antd'; | |||
| @@ -31,7 +31,7 @@ type ResourceTypeInfo = { | |||
| name: string; // 名称 | |||
| typeParamKey: string; // 类型参数名称,获取资源列表接口使用 | |||
| tagParamKey: string; // 标签参数名称,获取资源列表接口使用 | |||
| fileReqParamKey: 'models_id' | 'dataset_id'; // 文件请求参数名称,获取文件列表接口使用 | |||
| filePropKey: string; | |||
| tabItems: TabsProps['items']; // tab 列表 | |||
| typeTitle: string; // 类型标题 | |||
| tagTitle: string; // 标签标题 | |||
| @@ -40,13 +40,10 @@ type ResourceTypeInfo = { | |||
| prefix: string; // 图片资源、详情 url 的前缀 | |||
| deleteModalTitle: string; // 删除弹框的title | |||
| addBtnTitle: string; // 新增按钮的title | |||
| idParamKey: 'models_id' | 'dataset_id'; // 新建版本、删除版本接口,版本 id 的参数名称 | |||
| uploadAction: string; // 上传接口 url | |||
| uploadAccept?: string; // 上传文件类型 | |||
| downloadAllAction: string; // 批量下载接口 url | |||
| downloadSingleAction: string; // 单个下载接口 url | |||
| infoTypePropertyName: string; // 详情数据中,类型属性名称 | |||
| infoTagPropertyName: string; // 详情数据中,标签属性名称 | |||
| }; | |||
| export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| @@ -60,7 +57,7 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| name: '数据集', | |||
| typeParamKey: 'data_type', | |||
| tagParamKey: 'data_tag', | |||
| fileReqParamKey: 'dataset_id', | |||
| filePropKey: 'dataset_version_vos', | |||
| tabItems: [ | |||
| { | |||
| key: CommonTabKeys.Public, | |||
| @@ -80,25 +77,22 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| prefix: 'dataset', | |||
| deleteModalTitle: '确定删除该条数据集实例吗?', | |||
| addBtnTitle: '新建数据集', | |||
| idParamKey: 'dataset_id', | |||
| uploadAction: '/api/mmp/newdataset/upload', | |||
| uploadAccept: '.zip,.tgz', | |||
| downloadAllAction: '/api/mmp/newdataset/downloadAllFiles', | |||
| downloadSingleAction: '/api/mmp/newdataset/downloadSinggerFile', | |||
| infoTypePropertyName: 'data_type', | |||
| infoTagPropertyName: 'data_tag', | |||
| }, | |||
| [ResourceType.Model]: { | |||
| getList: getModelList, | |||
| getVersions: getModelVersionsById, | |||
| getVersions: getModelVersionList, | |||
| deleteRecord: deleteModel, | |||
| addVersion: addModelsVersionDetail, | |||
| addVersion: addModelVersion, | |||
| deleteVersion: deleteModelVersion, | |||
| getInfo: getModelById, | |||
| getInfo: getModelInfo, | |||
| name: '模型', | |||
| typeParamKey: 'model_type', | |||
| tagParamKey: 'model_tag', | |||
| fileReqParamKey: 'models_id', | |||
| filePropKey: 'model_version_vos', | |||
| tabItems: [ | |||
| { | |||
| key: CommonTabKeys.Public, | |||
| @@ -118,13 +112,10 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| prefix: 'model', | |||
| deleteModalTitle: '确定删除该条模型实例吗?', | |||
| addBtnTitle: '新建模型', | |||
| idParamKey: 'models_id', | |||
| uploadAction: '/api/mmp/models/upload', | |||
| uploadAction: '/api/mmp/newmodel/upload', | |||
| 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; | |||
| }; | |||
| // 资源数据 | |||
| // 数据集、模型列表数据 | |||
| export type ResourceData = { | |||
| id: number; | |||
| name: string; | |||
| identifier: string; | |||
| description: string; | |||
| create_by: string; | |||
| owner: string; | |||
| update_time: string; | |||
| time_ago: string; | |||
| version: string; | |||
| 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; | |||
| processing_code?: string; | |||
| dataset_source?: string; | |||
| usage?: string; | |||
| relative_paths?: string; | |||
| // 数据集 | |||
| data_type?: string; // 数据集分类 | |||
| data_tag?: string; // 研究方向 | |||
| processing_code?: string; // 处理代码 | |||
| dataset_source?: string; // 数据来源 | |||
| 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[]; | |||
| }; | |||
| // 版本数据 | |||
| @@ -2,10 +2,10 @@ import editExperimentIcon from '@/assets/img/edit-experiment.png'; | |||
| import KFModal from '@/components/KFModal'; | |||
| import { type ResourceData } from '@/pages/Dataset/config'; | |||
| import { | |||
| addModelsVersionDetail, | |||
| addModelVersion, | |||
| exportModelReq, | |||
| getModelList, | |||
| getModelVersionsById, | |||
| getModelVersionList, | |||
| } from '@/services/dataset'; | |||
| import { to } from '@/utils/promise'; | |||
| import { InfoCircleOutlined } from '@ant-design/icons'; | |||
| @@ -85,7 +85,7 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) { | |||
| // 获取模型版本列表 | |||
| const getModelVersions = async (id: number) => { | |||
| const [res] = await to(getModelVersionsById(id)); | |||
| const [res] = await to(getModelVersionList(id)); | |||
| if (res && res.data) { | |||
| setVersions(res.data); | |||
| } | |||
| @@ -118,7 +118,7 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) { | |||
| // 创建模型版本 | |||
| const createModelVersion = async (params: CreateModelVersionParams[]) => { | |||
| const [res] = await to(addModelsVersionDetail(params)); | |||
| const [res] = await to(addModelVersion(params)); | |||
| if (res) { | |||
| onOk(); | |||
| } | |||
| @@ -5,13 +5,11 @@ | |||
| */ | |||
| import { useEffectWhen } from '@/hooks'; | |||
| import { ResourceVersionData } from '@/pages/Dataset/config'; | |||
| import { getModelAtlasReq } from '@/services/dataset/index.js'; | |||
| import themes from '@/styles/theme.less'; | |||
| import { to } from '@/utils/promise'; | |||
| 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 GraphLegend from '../GraphLegend'; | |||
| import NodeTooltips from '../NodeTooltips'; | |||
| @@ -29,7 +27,7 @@ import { | |||
| type modeModelEvolutionProps = { | |||
| resourceId: number; | |||
| versionList: ResourceVersionData[]; | |||
| identifier: string; | |||
| version?: string; | |||
| isActive: boolean; | |||
| onVersionChange: (version: string) => void; | |||
| @@ -38,7 +36,7 @@ type modeModelEvolutionProps = { | |||
| let graph: Graph; | |||
| function ModelEvolution({ | |||
| resourceId, | |||
| versionList, | |||
| identifier, | |||
| version, | |||
| isActive, | |||
| onVersionChange, | |||
| @@ -217,7 +215,8 @@ function ModelEvolution({ | |||
| // 获取模型依赖 | |||
| const getModelAtlas = async () => { | |||
| const params = { | |||
| current_model_id: resourceId, | |||
| id: resourceId, | |||
| identifier, | |||
| version, | |||
| }; | |||
| const [res] = await to(getModelAtlasReq(params)); | |||
| @@ -250,15 +249,6 @@ function ModelEvolution({ | |||
| return ( | |||
| <div className={styles['model-evolution']}> | |||
| <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> | |||
| </Flex> | |||
| <div className={styles['model-evolution__graph']} id="canvas" ref={graphRef}></div> | |||
| @@ -1,8 +1,8 @@ | |||
| import ResourceIntro from '@/pages/Dataset/components/ResourceIntro'; | |||
| import ResourceInfo from '@/pages/Dataset/components/ResourceInfo'; | |||
| 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; | |||
| @@ -9,9 +9,9 @@ import { | |||
| getDatasetInfo, | |||
| getDatasetList, | |||
| getDatasetVersionList, | |||
| getModelInfo, | |||
| getModelList, | |||
| getModelVersionIdList, | |||
| getModelVersionsById, | |||
| getModelVersionList, | |||
| } from '@/services/dataset/index.js'; | |||
| import { getMirrorListReq, getMirrorVersionListReq } from '@/services/mirror'; | |||
| import type { TabsProps, TreeDataNode } from 'antd'; | |||
| @@ -121,7 +121,7 @@ const convertMirrorVersionToTreeData = ( | |||
| // export const selectorTypeConfig: Record<ResourceSelectorType, SelectorTypeInfo> = { | |||
| // [ResourceSelectorType.Model]: { | |||
| // getList: getModelList, | |||
| // getVersions: getModelVersionsById, | |||
| // getVersions: getModelVersionList, | |||
| // getFiles: getModelVersionIdList, | |||
| // name: '模型', | |||
| @@ -226,7 +226,6 @@ export class DatasetSelector implements SelectorTypeInfo { | |||
| } | |||
| } | |||
| async getVersions(parentKey: string, parentNode: ResourceData) { | |||
| // const obj = parseDatasetVersionId(id); | |||
| const res = await getDatasetVersionList(pick(parentNode, ['owner', 'identifier'])); | |||
| if (res && res.data) { | |||
| const list = res.data; | |||
| @@ -237,7 +236,6 @@ export class DatasetSelector implements SelectorTypeInfo { | |||
| } | |||
| async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) { | |||
| //const obj = parseDatasetVersionId(parentKey); | |||
| const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version']); | |||
| const res = await getDatasetInfo(params); | |||
| if (res && res.data) { | |||
| @@ -275,32 +273,31 @@ export class ModelSelector implements SelectorTypeInfo { | |||
| const list = res.data.content || []; | |||
| return convertDatasetToTreeData(list); | |||
| } else { | |||
| return Promise.reject('获取数据集列表失败'); | |||
| return Promise.reject('获取模型列表失败'); | |||
| } | |||
| } | |||
| 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) { | |||
| const list = res.data.content || []; | |||
| const list = res.data; | |||
| return convertDatasetVersionToTreeData(key, parentNode, list); | |||
| } else { | |||
| return Promise.reject('获取数据集版本列表失败'); | |||
| return Promise.reject('获取模型版本列表失败'); | |||
| } | |||
| } | |||
| async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) { | |||
| // const obj = parseDatasetVersionId(id); | |||
| const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version']); | |||
| const res = await getModelVersionsById(params); | |||
| const res = await getModelInfo(params); | |||
| 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 { | |||
| path: res.data.path || '', | |||
| path, | |||
| content: list, | |||
| }; | |||
| } 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; | |||
| return { | |||
| path: url, | |||
| content: [ | |||
| { | |||
| id: parentKey, | |||
| url: url, | |||
| file_name: `${url}`, | |||
| }, | |||
| ], | |||
| @@ -34,6 +34,11 @@ | |||
| border-bottom: 1px solid @border-color-secondary; | |||
| border-radius: 0; | |||
| } | |||
| &__tree-title { | |||
| display: inline-block; | |||
| .singleLine(); | |||
| } | |||
| } | |||
| &__right { | |||
| @@ -67,8 +72,3 @@ | |||
| } | |||
| } | |||
| } | |||
| .kf-tree-title { | |||
| display: inline-block; | |||
| .singleLine(); | |||
| } | |||
| @@ -6,6 +6,7 @@ | |||
| import KFModal from '@/components/KFModal'; | |||
| import { CommonTabKeys } from '@/enums'; | |||
| import { ResourceFileData } from '@/pages/Dataset/config'; | |||
| import { to } from '@/utils/promise'; | |||
| import { Icon } from '@umijs/max'; | |||
| import type { GetRef, ModalProps, TreeDataNode, TreeProps } from 'antd'; | |||
| @@ -24,11 +25,6 @@ export type ResourceSelectorResponse = { | |||
| activeTab: CommonTabKeys; // 是我的还是公开的 | |||
| }; | |||
| type ResourceFile = { | |||
| id: number; // 文件 id | |||
| file_name: string; // 文件 name | |||
| }; | |||
| export interface ResourceSelectorModalProps extends Omit<ModalProps, 'onOk'> { | |||
| type: ResourceSelectorType; // 数据集\模型\镜像 | |||
| defaultExpandedKeys?: React.Key[]; | |||
| @@ -76,7 +72,7 @@ function ResourceSelectorModal({ | |||
| const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]); | |||
| const [loadedKeys, setLoadedKeys] = useState<React.Key[]>([]); | |||
| const [originTreeData, setOriginTreeData] = useState<TreeDataNode[]>([]); | |||
| const [files, setFiles] = useState<ResourceFile[]>([]); | |||
| const [files, setFiles] = useState<ResourceFileData[]>([]); | |||
| const [versionPath, setVersionPath] = useState(''); | |||
| const [searchText, setSearchText] = useState(''); | |||
| const [firstLoadList, setFirstLoadList] = useState(false); | |||
| @@ -175,6 +171,7 @@ function ResourceSelectorModal({ | |||
| const lastNode = checkedNodes[checkedNodes.length - 1]; | |||
| getFiles(last, lastNode); | |||
| } else { | |||
| setVersionPath(''); | |||
| setFiles([]); | |||
| } | |||
| }; | |||
| @@ -278,26 +275,24 @@ function ResourceSelectorModal({ | |||
| loadedKeys={loadedKeys} | |||
| expandedKeys={expandedKeys} | |||
| onExpand={onExpand} | |||
| checkable | |||
| titleRender={(nodeData) => { | |||
| console.log(nodeData); | |||
| return ( | |||
| <span | |||
| className={styles['kf-tree-title']} | |||
| className={styles['model-selector__left__tree-title']} | |||
| style={{ width: nodeData.isLeaf ? '370px' : '420px' }} | |||
| > | |||
| {nodeData.title as string} | |||
| </span> | |||
| ); | |||
| }} | |||
| checkable | |||
| /> | |||
| </div> | |||
| <div className={styles['model-selector__right']}> | |||
| <div className={styles['model-selector__right__title']}>{fileTitle}</div> | |||
| <div className={styles['model-selector__right__files']}> | |||
| {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} | |||
| </div> | |||
| ))} | |||
| @@ -11,8 +11,8 @@ const MissingPage = () => { | |||
| title="敬请期待~" | |||
| content={'很抱歉,您访问的正在开发中,\n请耐心等待。'} | |||
| hasFooter={true} | |||
| backTitle="返回首页" | |||
| onBack={() => navigate('/')} | |||
| buttonTitle="返回首页" | |||
| onRefresh={() => navigate('/')} | |||
| ></KFEmpty> | |||
| ); | |||
| }; | |||
| @@ -26,6 +26,7 @@ const popupError = (error: string, skipErrorHandler: boolean | undefined = false | |||
| * @doc https://umijs.org/docs/max/request#配置 | |||
| */ | |||
| export const requestConfig: RequestConfig = { | |||
| timeout: 120 * 1000, | |||
| requestInterceptors: [ | |||
| (url: string, options: AxiosRequestConfig) => { | |||
| const headers = options.headers ?? {}; | |||
| @@ -27,12 +27,9 @@ export function getDatasetInfo(params) { | |||
| } | |||
| // 新增数据集 | |||
| export function addDateset(data) { | |||
| export function addDataset(data) { | |||
| return request(`/api/mmp/newdataset/addDatasetAndVersion`, { | |||
| method: 'POST', | |||
| headers: { | |||
| 'Content-Type': 'application/json;charset=UTF-8', | |||
| }, | |||
| 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) { | |||
| return request(`/api/mmp/newdataset/addVersion`, { | |||
| method: 'POST', | |||
| headers: { | |||
| 'Content-Type': 'application/json;charset=UTF-8', | |||
| }, | |||
| data, | |||
| }); | |||
| } | |||
| @@ -101,7 +87,7 @@ export function deleteDatasetVersion(params) { | |||
| // 分页查询模型列表 | |||
| export function getModelList(params) { | |||
| return request(`/api/mmp/models`, { | |||
| return request(`/api/mmp/newmodel/queryModels`, { | |||
| method: 'GET', | |||
| params, | |||
| }); | |||
| @@ -109,68 +95,59 @@ export function getModelList(params) { | |||
| // 新增模型 | |||
| export function addModel(data) { | |||
| return request(`/api/mmp/models/addModelAndVersion`, { | |||
| return request(`/api/mmp/newmodel/addModel`, { | |||
| method: 'POST', | |||
| headers: { | |||
| 'Content-Type': 'application/json;charset=UTF-8', | |||
| }, | |||
| 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', | |||
| params, | |||
| }); | |||
| } | |||
| // 根据版本查询文件列表 | |||
| export function getModelVersionIdList(params) { | |||
| return request(`/api/mmp/modelsVersion/versions`, { | |||
| // 查询模型版本列表 | |||
| export function getModelVersionList(params) { | |||
| return request(`/api/mmp/newmodel/getVersionList`, { | |||
| method: 'GET', | |||
| params, | |||
| }); | |||
| } | |||
| // 新增模型版本 | |||
| export function addModelsVersionDetail(data) { | |||
| return request(`/api/mmp/modelsVersion/addModelVersions`, { | |||
| export function addModelVersion(data) { | |||
| return request(`/api/mmp/newmodel/addVersion`, { | |||
| method: 'POST', | |||
| headers: { | |||
| 'Content-Type': 'application/json;charset=UTF-8', | |||
| }, | |||
| data, | |||
| }); | |||
| } | |||
| // 删除模型 | |||
| export function deleteModel(id) { | |||
| return request(`/api/mmp/models/${id}`, { | |||
| method: 'DELETE', | |||
| }); | |||
| } | |||
| // 删除模型版本 | |||
| export function deleteModelVersion(params) { | |||
| return request(`/api/mmp/modelsVersion/deleteVersion`, { | |||
| return request(`/api/mmp/newmodel/deleteVersion`, { | |||
| method: 'DELETE', | |||
| 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 | |||
| }); | |||
| } | |||
| @@ -190,3 +190,13 @@ export const fittingString = (str: string, maxWidth: number, fontSize: number) = | |||
| }); | |||
| 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; | |||
| }; | |||