| @@ -45,7 +45,7 @@ function AddVersionModal({ | |||
| // 上传请求 | |||
| const createDatasetVersion = async (params: any) => { | |||
| const request = resourceConfig[resourceType].addVersionReq; | |||
| const request = resourceConfig[resourceType].addVersion; | |||
| const [res] = await to(request(params)); | |||
| if (res) { | |||
| message.success('创建成功'); | |||
| @@ -20,13 +20,13 @@ function CategoryItem({ resourceType, item, isSelected, onClick }: CategoryItemP | |||
| <img | |||
| className={styles['category-item__icon']} | |||
| style={{ width: '22px' }} | |||
| src={`/assets/images/${resourceConfig[resourceType].iconPathPrefix}/${item.path}.png`} | |||
| src={`/assets/images/${resourceConfig[resourceType].prefix}/${item.path}.png`} | |||
| alt="" | |||
| /> | |||
| <img | |||
| className={styles['category-item__active-icon']} | |||
| style={{ width: '22px' }} | |||
| src={`/assets/images/${resourceConfig[resourceType].iconPathPrefix}/${item.path}-hover.png`} | |||
| src={`/assets/images/${resourceConfig[resourceType].prefix}/${item.path}-hover.png`} | |||
| alt="" | |||
| /> | |||
| <span className={styles['category-item__name']}>{item.name}</span> | |||
| @@ -0,0 +1,52 @@ | |||
| .resource-intro { | |||
| height: 100%; | |||
| &__top { | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-between; | |||
| width: 100%; | |||
| height: 110px; | |||
| margin-bottom: 10px; | |||
| padding: 25px 30px; | |||
| background-image: url(/assets/images/dataset-back.png); | |||
| background-repeat: no-repeat; | |||
| background-position: top center; | |||
| background-size: 100% 100%; | |||
| &__name { | |||
| margin-bottom: 12px; | |||
| color: @text-color; | |||
| font-size: 20; | |||
| } | |||
| &__tag { | |||
| margin-right: 10px; | |||
| padding: 4px 10px; | |||
| color: @primary-color; | |||
| font-size: 14px; | |||
| background: rgba(22, 100, 255, 0.1); | |||
| border-radius: 4px; | |||
| } | |||
| } | |||
| &__bottom { | |||
| height: calc(100% - 120px); | |||
| padding: 8px 30px 20px; | |||
| background: #ffffff; | |||
| border-radius: 10px; | |||
| box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09); | |||
| } | |||
| &__title { | |||
| margin: 30px 0 10px; | |||
| color: @text-color; | |||
| font-weight: 500; | |||
| font-size: @font-size; | |||
| } | |||
| &__intro { | |||
| color: @text-color-secondary; | |||
| font-size: 14px; | |||
| } | |||
| } | |||
| @@ -0,0 +1,86 @@ | |||
| import { to } from '@/utils/promise'; | |||
| import { useParams, useSearchParams } from '@umijs/max'; | |||
| import { Flex, Tabs } from 'antd'; | |||
| import { useEffect, useState } from 'react'; | |||
| import { ResourceData, ResourceType, resourceConfig } from '../../config'; | |||
| import ResourceVersion from '../ResourceVersion'; | |||
| import styles from './index.less'; | |||
| type ResourceIntroProps = { | |||
| resourceType: ResourceType; | |||
| }; | |||
| const ResourceIntro = ({ resourceType }: ResourceIntroProps) => { | |||
| const [info, setInfo] = useState<ResourceData>({} as ResourceData); | |||
| const locationParams = useParams(); //新版本获取路由参数接口 | |||
| const [searchParams] = useSearchParams(); | |||
| const isPublic = searchParams.get('isPublic') === 'true'; | |||
| const resourceId = Number(locationParams.id); | |||
| const name = resourceConfig[resourceType].name; | |||
| useEffect(() => { | |||
| getModelByDetail(); | |||
| }, []); | |||
| // 获取详情 | |||
| const getModelByDetail = async () => { | |||
| const request = resourceConfig[resourceType].getInfo; | |||
| const [res] = await to(request(resourceId)); | |||
| if (res) { | |||
| setInfo(res.data); | |||
| } | |||
| }; | |||
| const items = [ | |||
| { | |||
| key: '1', | |||
| label: `${name}简介`, | |||
| children: ( | |||
| <> | |||
| <div className={styles['resource-intro__title']}>简介</div> | |||
| <div className={styles['resource-intro__intro']}>{info.description}</div> | |||
| </> | |||
| ), | |||
| }, | |||
| { | |||
| key: '2', | |||
| label: `${name}文件/版本`, | |||
| children: ( | |||
| <ResourceVersion | |||
| resourceType={resourceType} | |||
| resourceId={resourceId} | |||
| resourceName={info.name} | |||
| isPublic={isPublic} | |||
| ></ResourceVersion> | |||
| ), | |||
| }, | |||
| ]; | |||
| const infoTypePropertyName = resourceConfig[resourceType] | |||
| .infoTypePropertyName as keyof ResourceData; | |||
| const infoTagPropertyName = resourceConfig[resourceType] | |||
| .infoTagPropertyName as keyof ResourceData; | |||
| return ( | |||
| <div className={styles['resource-intro']}> | |||
| <div className={styles['resource-intro__top']}> | |||
| <span className={styles['resource-intro__top__name']}>{info.name}</span> | |||
| <Flex align="center"> | |||
| <div className={styles['resource-intro__top__tag']}> | |||
| {name} id:{info.id} | |||
| </div> | |||
| <div className={styles['resource-intro__top__tag']}> | |||
| {info[infoTypePropertyName] || '--'} | |||
| </div> | |||
| <div className={styles['resource-intro__top__tag']}> | |||
| {info[infoTagPropertyName] || '--'} | |||
| </div> | |||
| </Flex> | |||
| </div> | |||
| <div className={styles['resource-intro__bottom']}> | |||
| <Tabs defaultActiveKey="1" items={items}></Tabs> | |||
| </div> | |||
| </div> | |||
| ); | |||
| }; | |||
| export default ResourceIntro; | |||
| @@ -129,11 +129,8 @@ function ResourceList( | |||
| activeType: dataType, | |||
| activeTag: dataTag, | |||
| }); | |||
| if (resourceType === ResourceType.Dataset) { | |||
| navigate(`/dataset/dataset/${record.id}?isPublic=${isPublic}`); | |||
| } else { | |||
| navigate(`/dataset/model/${record.id}?isPublic=${isPublic}`); | |||
| } | |||
| const prefix = resourceConfig[resourceType].prefix; | |||
| navigate(`/dataset/${prefix}/${record.id}?isPublic=${isPublic}`); | |||
| }; | |||
| // 分页切换 | |||
| @@ -0,0 +1,4 @@ | |||
| .resource-version { | |||
| color: @text-color; | |||
| font-size: @font-size-content; | |||
| } | |||
| @@ -0,0 +1,236 @@ | |||
| import CommonTableCell from '@/components/CommonTableCell'; | |||
| import DateTableCell from '@/components/DateTableCell'; | |||
| import KFIcon from '@/components/KFIcon'; | |||
| import AddVersionModal from '@/pages/Dataset/components/AddVersionModal'; | |||
| import { ResourceType } from '@/pages/Dataset/config'; | |||
| import { downLoadZip } from '@/utils/downloadfile'; | |||
| import { openAntdModal } from '@/utils/modal'; | |||
| import { to } from '@/utils/promise'; | |||
| import { modalConfirm } from '@/utils/ui'; | |||
| import { App, Button, Flex, Select, Table } from 'antd'; | |||
| import { useEffect, useState } from 'react'; | |||
| import { ResourceFileData, resourceConfig } from '../../config'; | |||
| import styles from './index.less'; | |||
| type ResourceVersionProps = { | |||
| resourceType: ResourceType; | |||
| resourceId: number; | |||
| resourceName: string; | |||
| isPublic: boolean; | |||
| }; | |||
| function ResourceVersion({ | |||
| resourceType, | |||
| resourceId, | |||
| resourceName, | |||
| isPublic, | |||
| }: ResourceVersionProps) { | |||
| const [versionList, setVersionList] = useState([]); | |||
| const [version, setVersion] = useState<string | undefined>(undefined); | |||
| const [fileList, setFileList] = useState<ResourceFileData[]>([]); | |||
| const { message } = App.useApp(); | |||
| useEffect(() => { | |||
| getVersionList(); | |||
| }, []); | |||
| // 获取版本列表 | |||
| const getVersionList = async () => { | |||
| const request = resourceConfig[resourceType].getVersions; | |||
| const [res] = await to(request(resourceId)); | |||
| if (res && res.data && res.data.length > 0) { | |||
| setVersionList( | |||
| res.data.map((item: string) => { | |||
| return { | |||
| label: item, | |||
| value: item, | |||
| }; | |||
| }), | |||
| ); | |||
| setVersion(res.data[0]); | |||
| getFileList(res.data[0]); | |||
| } else { | |||
| setVersion(undefined); | |||
| setFileList([]); | |||
| } | |||
| }; | |||
| // 获取版本下的文件列表 | |||
| const getFileList = async (version: string) => { | |||
| const params = { | |||
| version, | |||
| [resourceConfig[resourceType].fileReqParamKey]: resourceId, | |||
| }; | |||
| const request = resourceConfig[resourceType].getFiles; | |||
| const [res] = await to(request(params)); | |||
| if (res) { | |||
| setFileList(res?.data?.content ?? []); | |||
| } | |||
| }; | |||
| // 删除版本 | |||
| const deleteVersion = async () => { | |||
| const request = resourceConfig[resourceType].deleteVersion; | |||
| const params = { | |||
| [resourceConfig[resourceType].idParamKey]: resourceId, | |||
| version, | |||
| }; | |||
| const [res] = await to(request(params)); | |||
| if (res) { | |||
| getVersionList(); | |||
| message.success('删除成功'); | |||
| } | |||
| }; | |||
| // 新建版本 | |||
| const showModal = () => { | |||
| const { close } = openAntdModal(AddVersionModal, { | |||
| resourceType: resourceType, | |||
| resourceId: resourceId, | |||
| initialName: resourceName, | |||
| onOk: () => { | |||
| getVersionList(); | |||
| close(); | |||
| }, | |||
| }); | |||
| }; | |||
| // 处理删除 | |||
| const hanldeDelete = () => { | |||
| modalConfirm({ | |||
| title: '删除后,该版本将不可恢复', | |||
| content: '是否确认删除?', | |||
| okText: '确认', | |||
| cancelText: '取消', | |||
| onOk: () => { | |||
| deleteVersion(); | |||
| }, | |||
| }); | |||
| }; | |||
| // 全部导出 | |||
| const handleExport = async () => { | |||
| const url = resourceConfig[resourceType].downloadAllAction; | |||
| downLoadZip(url, { models_id: resourceId, version }); | |||
| }; | |||
| // 单个导出 | |||
| const downloadAlone = (record: ResourceFileData) => { | |||
| const url = resourceConfig[resourceType].downloadSingleAction; | |||
| downLoadZip(`${url}/${record.id}`); | |||
| }; | |||
| // 版本变化 | |||
| const handleChange = (value: string) => { | |||
| if (value) { | |||
| getFileList(value); | |||
| setVersion(value); | |||
| } else { | |||
| setVersion(undefined); | |||
| } | |||
| }; | |||
| const columns = [ | |||
| { | |||
| title: '序号', | |||
| dataIndex: 'index', | |||
| key: 'index', | |||
| width: 80, | |||
| render(text: string, record: ResourceFileData, index: number) { | |||
| return <span>{index + 1}</span>; | |||
| }, | |||
| }, | |||
| { | |||
| title: '文件名称', | |||
| dataIndex: 'file_name', | |||
| key: 'file_name', | |||
| render: (text: string, record: ResourceFileData) => ( | |||
| <a onClick={() => downloadAlone(record)}>{text}</a> | |||
| ), | |||
| }, | |||
| { | |||
| title: '版本号', | |||
| dataIndex: 'version', | |||
| key: 'version', | |||
| render: CommonTableCell(), | |||
| }, | |||
| { | |||
| title: '文件大小', | |||
| dataIndex: 'file_size', | |||
| key: 'file_size', | |||
| render: CommonTableCell(), | |||
| }, | |||
| { | |||
| title: '更新时间', | |||
| dataIndex: 'update_time', | |||
| key: 'update_time', | |||
| render: DateTableCell, | |||
| }, | |||
| { | |||
| title: '操作', | |||
| dataIndex: 'option', | |||
| width: '100px', | |||
| key: 'option', | |||
| render: (_: any, record: ResourceFileData) => [ | |||
| <Button | |||
| type="link" | |||
| size="small" | |||
| key="download" | |||
| icon={<KFIcon type="icon-xiazai" />} | |||
| onClick={() => downloadAlone(record)} | |||
| > | |||
| 下载 | |||
| </Button>, | |||
| ], | |||
| }, | |||
| ]; | |||
| return ( | |||
| <div className={styles['resource-version']}> | |||
| <Flex justify="space-between" align="center" style={{ margin: '30px 0' }}> | |||
| <Flex align="center"> | |||
| <span style={{ marginRight: '10px' }}>版本号:</span> | |||
| <Select | |||
| placeholder="请选择版本号" | |||
| style={{ width: '160px', marginRight: '20px' }} | |||
| value={version} | |||
| allowClear | |||
| onChange={handleChange} | |||
| options={versionList} | |||
| /> | |||
| <Button type="default" onClick={showModal} icon={<KFIcon type="icon-xinjian2" />}> | |||
| 创建新版本 | |||
| </Button> | |||
| </Flex> | |||
| <Flex align="center"> | |||
| {!isPublic && ( | |||
| <Button | |||
| type="default" | |||
| style={{ marginRight: '20px' }} | |||
| onClick={hanldeDelete} | |||
| icon={<KFIcon type="icon-shanchu" />} | |||
| > | |||
| 删除 | |||
| </Button> | |||
| )} | |||
| <Button | |||
| type="default" | |||
| disabled={!version} | |||
| onClick={handleExport} | |||
| icon={<KFIcon type="icon-xiazai" />} | |||
| > | |||
| 下载 | |||
| </Button> | |||
| </Flex> | |||
| </Flex> | |||
| <div style={{ marginBottom: '30px', fontSize: '15px' }}> | |||
| {fileList.length > 0 && fileList[0].description | |||
| ? '版本描述:' + fileList[0].description | |||
| : null} | |||
| </div> | |||
| <Table columns={columns} dataSource={fileList} pagination={false} rowKey="id" /> | |||
| </div> | |||
| ); | |||
| } | |||
| export default ResourceVersion; | |||
| @@ -4,10 +4,14 @@ import { | |||
| addDatasetVersionDetail, | |||
| addModelsVersionDetail, | |||
| deleteDataset, | |||
| deleteDatasetVersion, | |||
| deleteModel, | |||
| deleteModelVersion, | |||
| getDatasetById, | |||
| getDatasetList, | |||
| getDatasetVersionIdList, | |||
| getDatasetVersionsById, | |||
| getModelById, | |||
| getModelList, | |||
| getModelVersionIdList, | |||
| getModelVersionsById, | |||
| @@ -24,6 +28,9 @@ type ResourceTypeInfo = { | |||
| getVersions: (params: any) => Promise<any>; | |||
| getFiles: (params: any) => Promise<any>; | |||
| deleteRecord: (params: any) => Promise<any>; | |||
| addVersion: (params: any) => Promise<any>; | |||
| deleteVersion: (params: any) => Promise<any>; | |||
| getInfo: (params: any) => Promise<any>; | |||
| name: string; | |||
| typeParamKey: string; | |||
| tagParamKey: string; | |||
| @@ -33,13 +40,16 @@ type ResourceTypeInfo = { | |||
| tagTitle: string; | |||
| typeValue: number; // 从 getAssetIcon 接口获取特定值的数据为 type 分类 (category_id === typeValue) | |||
| tagValue: number; // 从 getAssetIcon 接口获取特定值的数据为 tag 分类(category_id === tagValue) | |||
| iconPathPrefix: string; // 图标路径前缀 | |||
| prefix: string; // 前缀 | |||
| deleteModalTitle: string; // 删除弹框的title | |||
| addBtnTitle: string; // 新增按钮的title | |||
| addVersionReq: (params: any) => Promise<any>; | |||
| idParamKey: string; | |||
| idParamKey: 'models_id' | 'dataset_id'; | |||
| uploadAction: string; | |||
| uploadAccept?: string; | |||
| downloadAllAction: string; | |||
| downloadSingleAction: string; | |||
| infoTypePropertyName: string; | |||
| infoTagPropertyName: string; | |||
| }; | |||
| export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| @@ -48,6 +58,9 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| getVersions: getDatasetVersionsById, | |||
| getFiles: getDatasetVersionIdList, | |||
| deleteRecord: deleteDataset, | |||
| addVersion: addDatasetVersionDetail, | |||
| deleteVersion: deleteDatasetVersion, | |||
| getInfo: getDatasetById, | |||
| name: '数据集', | |||
| typeParamKey: 'data_type', | |||
| tagParamKey: 'data_tag', | |||
| @@ -68,19 +81,25 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| tagTitle: '研究方向/应用领域', | |||
| typeValue: 1, | |||
| tagValue: 2, | |||
| iconPathPrefix: 'dataset', | |||
| prefix: 'dataset', | |||
| deleteModalTitle: '确定删除该条数据集实例吗?', | |||
| addBtnTitle: '新建数据集', | |||
| addVersionReq: addDatasetVersionDetail, | |||
| idParamKey: 'dataset_id', | |||
| uploadAction: '/api/mmp/dataset/upload', | |||
| uploadAccept: '.zip,.tgz', | |||
| downloadAllAction: '/api/mmp/dataset/downloadAllFilesl', | |||
| downloadSingleAction: '/api/mmp/dataset/download', | |||
| infoTypePropertyName: 'dataset_type_name', | |||
| infoTagPropertyName: 'dataset_tag_name', | |||
| }, | |||
| [ResourceType.Model]: { | |||
| getList: getModelList, | |||
| getVersions: getModelVersionsById, | |||
| getFiles: getModelVersionIdList, | |||
| deleteRecord: deleteModel, | |||
| addVersion: addModelsVersionDetail, | |||
| deleteVersion: deleteModelVersion, | |||
| getInfo: getModelById, | |||
| name: '模型', | |||
| typeParamKey: 'model_type', | |||
| tagParamKey: 'model_tag', | |||
| @@ -101,13 +120,16 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| tagTitle: '模型能力', | |||
| typeValue: 3, | |||
| tagValue: 4, | |||
| iconPathPrefix: 'model', | |||
| prefix: 'model', | |||
| deleteModalTitle: '确定删除该条模型实例吗?', | |||
| addBtnTitle: '新建模型', | |||
| addVersionReq: addModelsVersionDetail, | |||
| idParamKey: 'models_id', | |||
| uploadAction: '/api/mmp/models/upload', | |||
| uploadAccept: undefined, | |||
| downloadAllAction: '/api/mmp/models/downloadAllFiles', | |||
| downloadSingleAction: '/api/mmp/models/download_model', | |||
| infoTypePropertyName: 'model_type_name', | |||
| infoTagPropertyName: 'model_tag_name', | |||
| }, | |||
| }; | |||
| @@ -119,11 +141,29 @@ export type CategoryData = { | |||
| path: string; | |||
| }; | |||
| // 数据类型 | |||
| // 资源数据 | |||
| export type ResourceData = { | |||
| id: number; | |||
| name: string; | |||
| description: string; | |||
| create_by: string; | |||
| update_time: string; | |||
| model_type_name?: string; | |||
| model_tag_name?: string; | |||
| dataset_type_name?: string; | |||
| dataset_tag_name?: string; | |||
| }; | |||
| // 版本文件数据 | |||
| export type ResourceFileData = { | |||
| id: number; | |||
| file_name: string; | |||
| file_size: string; | |||
| description: string; | |||
| create_by: string; | |||
| create_time: string; | |||
| update_by: string; | |||
| update_time: string; | |||
| url: string; | |||
| version: string; | |||
| }; | |||
| @@ -1,263 +0,0 @@ | |||
| import KFIcon from '@/components/KFIcon'; | |||
| import { ResourceType } from '@/pages/Dataset/config'; | |||
| import { | |||
| deleteDatasetVersion, | |||
| getDatasetById, | |||
| getDatasetVersionIdList, | |||
| getDatasetVersionsById, | |||
| } from '@/services/dataset/index.js'; | |||
| import { formatDate } from '@/utils/date'; | |||
| import { downLoadZip } from '@/utils/downloadfile'; | |||
| import { openAntdModal } from '@/utils/modal'; | |||
| import { modalConfirm } from '@/utils/ui'; | |||
| import { useParams, useSearchParams } from '@umijs/max'; | |||
| import { App, Button, Input, Select, Table, Tabs } from 'antd'; | |||
| import { useEffect, useRef, useState } from 'react'; | |||
| import AddVersionModal from './components/AddVersionModal'; | |||
| import Styles from './intro.less'; | |||
| const { Search } = Input; | |||
| const { TabPane } = Tabs; | |||
| const Dataset = () => { | |||
| const { message } = App.useApp(); | |||
| const [formList, setFormList] = useState([]); | |||
| const [datasetDetailObj, setDatasetDetailObj] = useState({}); | |||
| const [version, setVersion] = useState(null); | |||
| const [versionList, setVersionList] = useState([]); | |||
| const locationParams = useParams(); //新版本获取路由参数接口 | |||
| const [searchParams] = useSearchParams(); | |||
| const [wordList, setWordList] = useState([]); | |||
| const [activeTabKey, setActiveTabKey] = useState('1'); | |||
| const isPublic = searchParams.get('isPublic') === 'true'; | |||
| const getDatasetByDetail = () => { | |||
| getDatasetById(locationParams.id).then((ret) => { | |||
| console.log(ret); | |||
| setDatasetDetailObj(ret.data); | |||
| }); | |||
| }; | |||
| // 获取数据集版本 | |||
| const getDatasetVersionList = () => { | |||
| getDatasetVersionsById(locationParams.id).then((ret) => { | |||
| console.log(ret); | |||
| if (ret.data && ret.data.length > 0) { | |||
| setVersionList( | |||
| ret.data.map((item) => { | |||
| return { | |||
| label: item, | |||
| value: item, | |||
| }; | |||
| }), | |||
| ); | |||
| setVersion(ret.data[0]); | |||
| getDatasetVersions({ version: ret.data[0], dataset_id: locationParams.id }); | |||
| } else { | |||
| setVersion(null); | |||
| setWordList([]); | |||
| } | |||
| }); | |||
| }; | |||
| useEffect(() => { | |||
| getDatasetByDetail(); | |||
| getDatasetVersionList(); | |||
| return () => {}; | |||
| }, []); | |||
| const showModal = () => { | |||
| const { close } = openAntdModal(AddVersionModal, { | |||
| resourceType: ResourceType.Dataset, | |||
| resourceId: locationParams.id, | |||
| initialName: datasetDetailObj.name, | |||
| onOk: () => { | |||
| getDatasetVersionList(); | |||
| close(); | |||
| }, | |||
| }); | |||
| }; | |||
| const deleteDataset = () => { | |||
| modalConfirm({ | |||
| title: '删除后,该数据集版本将不可恢复', | |||
| content: '是否确认删除?', | |||
| onOk: () => { | |||
| deleteDatasetVersion({ dataset_id: locationParams.id, version }).then((ret) => { | |||
| getDatasetVersionList(); | |||
| message.success('删除成功'); | |||
| }); | |||
| }, | |||
| }); | |||
| }; | |||
| // 获取版本下的文件列表 | |||
| const getDatasetVersions = (params) => { | |||
| getDatasetVersionIdList(params).then((res) => { | |||
| setWordList(res?.data?.content ?? []); | |||
| }); | |||
| }; | |||
| const handleExport = async () => { | |||
| const hide = message.loading('正在下载'); | |||
| hide(); | |||
| downLoadZip(`/api/mmp/dataset/downloadAllFiles`, { dataset_id: locationParams.id, version }); | |||
| }; | |||
| const downloadAlone = (e, record) => { | |||
| console.log(record); | |||
| const hide = message.loading('正在下载'); | |||
| hide(); | |||
| downLoadZip(`/api/mmp/dataset/download/${record.id}`); | |||
| }; | |||
| const handleChange = (value) => { | |||
| console.log(value); | |||
| if (value) { | |||
| getDatasetVersions({ version: value, dataset_id: locationParams.id }); | |||
| setVersion(value); | |||
| } else { | |||
| setVersion(null); | |||
| } | |||
| }; | |||
| const columns = [ | |||
| { | |||
| title: '序号', | |||
| dataIndex: 'index', | |||
| key: 'index', | |||
| width: 80, | |||
| render(text, record, index) { | |||
| return <span>{(pageOption.current.page - 1) * 10 + index + 1}</span>; | |||
| }, | |||
| // render: (text, record, index) => `${((curPage-1)*10)+(index+1)}`, | |||
| }, | |||
| { | |||
| title: '文件名称', | |||
| dataIndex: 'file_name', | |||
| key: 'file_name', | |||
| render: (text, record) => <a onClick={(e) => downloadAlone(e, record)}>{text}</a>, | |||
| }, | |||
| { | |||
| title: '版本号', | |||
| dataIndex: 'version', | |||
| key: 'version', | |||
| }, | |||
| { | |||
| title: '文件大小', | |||
| dataIndex: 'file_size', | |||
| key: 'file_size', | |||
| }, | |||
| { | |||
| title: '更新时间', | |||
| dataIndex: 'update_time', | |||
| key: 'update_time', | |||
| render: (text) => <span>{formatDate(text)}</span>, | |||
| }, | |||
| { | |||
| title: '操作', | |||
| dataIndex: 'option', | |||
| width: '100px', | |||
| key: 'option', | |||
| render: (_, record) => [ | |||
| <Button | |||
| type="link" | |||
| size="small" | |||
| key="download" | |||
| icon={<KFIcon type="icon-xiazai" />} | |||
| onClick={(e) => downloadAlone(e, record)} | |||
| > | |||
| 下载 | |||
| </Button>, | |||
| ], | |||
| }, | |||
| ]; | |||
| const pageOption = useRef({ page: 1, size: 10 }); | |||
| // 当前页面切换 | |||
| const paginationChange = async (current, size) => { | |||
| console.log('page', current, size); | |||
| pageOption.current = { | |||
| page: current, | |||
| size: size, | |||
| }; | |||
| // getList() | |||
| }; | |||
| return ( | |||
| <div className={Styles.datasetBox}> | |||
| <div className={Styles.datasetIntroTopBox}> | |||
| <span style={{ color: '#1d1d20', fontSize: '20px' }}>{datasetDetailObj.name}</span> | |||
| <div className={Styles.smallTagBox}> | |||
| <div className={Styles.tagItem}>数据集 id:{datasetDetailObj.id}</div> | |||
| <div className={Styles.tagItem}>{datasetDetailObj.dataset_type_name || '...'}</div> | |||
| <div className={Styles.tagItem}>{datasetDetailObj.dataset_tag_name || '...'}</div> | |||
| </div> | |||
| </div> | |||
| <div className={Styles.datasetIntroCneterBox}> | |||
| <Tabs activeKey={activeTabKey} onChange={(key) => setActiveTabKey(key)}> | |||
| <TabPane tab="数据集简介" key="1"> | |||
| <div className={Styles.datasetIntroTitle}>简介</div> | |||
| <div className={Styles.datasetIntroText}>{datasetDetailObj.description}</div> | |||
| </TabPane> | |||
| <TabPane tab="数据集文件/版本" key="2"> | |||
| <div className={Styles.dataListBox}> | |||
| <div>数据集文件列表</div> | |||
| <div className={Styles.dataButtonList}> | |||
| <div | |||
| style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }} | |||
| > | |||
| <span style={{ marginRight: '10px' }}>版本号:</span> | |||
| <Select | |||
| placeholder="请选择版本号" | |||
| style={{ | |||
| width: 160, | |||
| }} | |||
| allowClear | |||
| value={version} | |||
| onChange={handleChange} | |||
| options={versionList} | |||
| /> | |||
| <Button | |||
| type="default" | |||
| className={Styles.plusButton} | |||
| onClick={showModal} | |||
| icon={<KFIcon type="icon-xinjian2" />} | |||
| > | |||
| 创建新版本 | |||
| </Button> | |||
| </div> | |||
| <div | |||
| style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }} | |||
| > | |||
| {!isPublic && ( | |||
| <Button | |||
| type="default" | |||
| className={Styles.plusButton} | |||
| style={{ margin: '0 20px 0 0' }} | |||
| onClick={deleteDataset} | |||
| icon={<KFIcon type="icon-shanchu" />} | |||
| > | |||
| 删除 | |||
| </Button> | |||
| )} | |||
| <Button | |||
| type="default" | |||
| disabled={!version} | |||
| className={Styles.plusButton} | |||
| style={{ margin: '0 20px 0 0' }} | |||
| onClick={handleExport} | |||
| icon={<KFIcon type="icon-xiazai" />} | |||
| > | |||
| 下载 | |||
| </Button> | |||
| </div> | |||
| </div> | |||
| <div style={{ marginBottom: '10px', fontSize: '14px' }}> | |||
| {wordList.length > 0 && wordList[0].description | |||
| ? '版本描述:' + wordList[0].description | |||
| : null} | |||
| </div> | |||
| <Table columns={columns} dataSource={wordList} pagination={false} rowKey="id" /> | |||
| </div> | |||
| </TabPane> | |||
| </Tabs> | |||
| </div> | |||
| </div> | |||
| ); | |||
| }; | |||
| export default Dataset; | |||
| @@ -1,82 +0,0 @@ | |||
| .datasetIntroTopBox { | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-between; | |||
| width: 100%; | |||
| height: 110px; | |||
| margin-bottom: 10px; | |||
| padding: 25px 30px; | |||
| background-image: url(/assets/images/dataset-back.png); | |||
| background-repeat: no-repeat; | |||
| background-position: top center; | |||
| background-size: 100% 100%; | |||
| .smallTagBox { | |||
| display: flex; | |||
| align-items: center; | |||
| color: #1664ff; | |||
| font-size: 14px; | |||
| .tagItem { | |||
| margin-right: 20px; | |||
| padding: 4px 10px; | |||
| background: rgba(22, 100, 255, 0.1); | |||
| border-radius: 4px; | |||
| } | |||
| } | |||
| } | |||
| .dataListBox { | |||
| padding: 20px 30px; | |||
| color: #1d1d20; | |||
| font-size: 16px; | |||
| font-family: alibaba; | |||
| background: #ffffff; | |||
| border-radius: 10px; | |||
| box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09); | |||
| .dataButtonList { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| height: 32px; | |||
| margin: 24px 0 30px 0; | |||
| color: #575757; | |||
| font-size: 16px; | |||
| } | |||
| } | |||
| .datasetIntroCneterBox { | |||
| height: 77vh; | |||
| padding: 20px 30px; | |||
| background: #ffffff; | |||
| border-radius: 10px; | |||
| box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09); | |||
| } | |||
| .datasetIntroTitle { | |||
| margin: 37px 0 10px 0; | |||
| color: #1d1d20; | |||
| font-size: 15px; | |||
| } | |||
| .datasetIntroText { | |||
| margin-bottom: 30px; | |||
| color: #575757; | |||
| font-size: 14px; | |||
| } | |||
| .datasetBox { | |||
| background: #f9fafb; | |||
| :global { | |||
| .ant-tabs-top > .ant-tabs-nav { | |||
| margin: 0; | |||
| } | |||
| .ant-pagination { | |||
| text-align: right; | |||
| } | |||
| } | |||
| } | |||
| .plusButton { | |||
| margin: 0 18px 0 20px; | |||
| } | |||
| .tipContent { | |||
| margin-top: 5px; | |||
| color: #c73131; | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| import ResourceIntro from '@/pages/Dataset/components/ResourceIntro'; | |||
| import { ResourceType } from '@/pages/Dataset/config'; | |||
| function DatasetIntro() { | |||
| return <ResourceIntro resourceType={ResourceType.Dataset} />; | |||
| } | |||
| export default DatasetIntro; | |||
| @@ -86,7 +86,7 @@ | |||
| } | |||
| .experimentBox { | |||
| height: calc(100% - 20px); | |||
| height: 100%; | |||
| .experimentTable { | |||
| height: calc(100% - 60px); | |||
| :global { | |||
| @@ -1,262 +0,0 @@ | |||
| import KFIcon from '@/components/KFIcon'; | |||
| import AddVersionModal from '@/pages/Dataset/components/AddVersionModal'; | |||
| import { ResourceType } from '@/pages/Dataset/config'; | |||
| import { | |||
| deleteModelVersion, | |||
| getModelById, | |||
| getModelVersionIdList, | |||
| getModelVersionsById, | |||
| } from '@/services/dataset/index.js'; | |||
| import { formatDate } from '@/utils/date'; | |||
| import { downLoadZip } from '@/utils/downloadfile'; | |||
| import { openAntdModal } from '@/utils/modal'; | |||
| import { modalConfirm } from '@/utils/ui'; | |||
| import { useParams, useSearchParams } from '@umijs/max'; | |||
| import { App, Button, Input, Select, Table, Tabs } from 'antd'; | |||
| import { useEffect, useRef, useState } from 'react'; | |||
| import Styles from './intro.less'; | |||
| const { Search } = Input; | |||
| const { TabPane } = Tabs; | |||
| const Dataset = () => { | |||
| const [formList, setFormList] = useState([]); | |||
| const [datasetDetailObj, setDatasetDetailObj] = useState({}); | |||
| const [version, setVersion] = useState(null); | |||
| const [versionList, setVersionList] = useState([]); | |||
| const locationParams = useParams(); //新版本获取路由参数接口 | |||
| const [searchParams] = useSearchParams(); | |||
| const [wordList, setWordList] = useState([]); | |||
| const { message } = App.useApp(); | |||
| const isPublic = searchParams.get('isPublic') === 'true'; | |||
| const getModelByDetail = () => { | |||
| getModelById(locationParams.id).then((ret) => { | |||
| console.log(ret); | |||
| setDatasetDetailObj(ret.data); | |||
| }); | |||
| }; | |||
| const getModelVersionsList = () => { | |||
| getModelVersionsById(locationParams.id).then((ret) => { | |||
| console.log(ret); | |||
| if (ret && ret.data && ret.data.length > 0) { | |||
| setVersionList( | |||
| ret.data.map((item) => { | |||
| return { | |||
| label: item, | |||
| value: item, | |||
| }; | |||
| }), | |||
| ); | |||
| setVersion(ret.data[0]); | |||
| getModelVersions({ version: ret.data[0], models_id: locationParams.id }); | |||
| } else { | |||
| setVersion(null); | |||
| setWordList([]); | |||
| } | |||
| }); | |||
| }; | |||
| useEffect(() => { | |||
| getModelByDetail(); | |||
| getModelVersionsList(); | |||
| return () => {}; | |||
| }, []); | |||
| const showModal = () => { | |||
| const { close } = openAntdModal(AddVersionModal, { | |||
| resourceType: ResourceType.Model, | |||
| resourceId: locationParams.id, | |||
| initialName: datasetDetailObj.name, | |||
| onOk: () => { | |||
| getModelVersionsList(); | |||
| close(); | |||
| }, | |||
| }); | |||
| }; | |||
| const deleteDataset = () => { | |||
| modalConfirm({ | |||
| title: '删除后,该版本将不可恢复', | |||
| content: '是否确认删除?', | |||
| okText: '确认', | |||
| cancelText: '取消', | |||
| onOk: () => { | |||
| deleteModelVersion({ models_id: locationParams.id, version }).then((ret) => { | |||
| getModelVersionsList(); | |||
| message.success('删除成功'); | |||
| }); | |||
| }, | |||
| }); | |||
| }; | |||
| const getModelVersions = (params) => { | |||
| getModelVersionIdList(params).then((ret) => { | |||
| setWordList(ret?.data?.content ?? []); | |||
| }); | |||
| }; | |||
| const handleExport = async () => { | |||
| const hide = message.loading('正在下载'); | |||
| hide(); | |||
| downLoadZip(`/api/mmp/models/downloadAllFiles`, { models_id: locationParams.id, version }); | |||
| }; | |||
| const downloadAlone = (e, record) => { | |||
| console.log(record); | |||
| const hide = message.loading('正在下载'); | |||
| hide(); | |||
| downLoadZip(`/api/mmp/models/download_model/${record.id}`); | |||
| }; | |||
| const handleChange = (value) => { | |||
| console.log(value); | |||
| if (value) { | |||
| getModelVersions({ version: value, models_id: locationParams.id }); | |||
| setVersion(value); | |||
| } else { | |||
| setVersion(''); | |||
| } | |||
| }; | |||
| const columns = [ | |||
| { | |||
| title: '序号', | |||
| dataIndex: 'index', | |||
| key: 'index', | |||
| width: 80, | |||
| render(text, record, index) { | |||
| return <span>{(pageOption.current.page - 1) * 10 + index + 1}</span>; | |||
| }, | |||
| // render: (text, record, index) => `${((curPage-1)*10)+(index+1)}`, | |||
| }, | |||
| { | |||
| title: '文件名称', | |||
| dataIndex: 'file_name', | |||
| key: 'file_name', | |||
| render: (text, record) => <a onClick={(e) => downloadAlone(e, record)}>{text}</a>, | |||
| }, | |||
| { | |||
| title: '版本号', | |||
| dataIndex: 'version', | |||
| key: 'version', | |||
| }, | |||
| { | |||
| title: '文件大小', | |||
| dataIndex: 'file_size', | |||
| key: 'file_size', | |||
| }, | |||
| { | |||
| title: '更新时间', | |||
| dataIndex: 'update_time', | |||
| key: 'update_time', | |||
| render: (text) => <span>{formatDate(text)}</span>, | |||
| }, | |||
| { | |||
| title: '操作', | |||
| dataIndex: 'option', | |||
| width: '100px', | |||
| key: 'option', | |||
| render: (_, record) => [ | |||
| <Button | |||
| type="link" | |||
| size="small" | |||
| key="download" | |||
| icon={<KFIcon type="icon-xiazai" />} | |||
| onClick={(e) => downloadAlone(e, record)} | |||
| > | |||
| 下载 | |||
| </Button>, | |||
| ], | |||
| }, | |||
| ]; | |||
| const pageOption = useRef({ page: 1, size: 10 }); | |||
| // 当前页面切换 | |||
| const paginationChange = async (current, size) => { | |||
| console.log('page', current, size); | |||
| pageOption.current = { | |||
| page: current, | |||
| size: size, | |||
| }; | |||
| // getList() | |||
| }; | |||
| return ( | |||
| <div className={Styles.datasetBox}> | |||
| <div className={Styles.datasetIntroTopBox}> | |||
| <span style={{ color: '#1d1d20', fontSize: '20px' }}>{datasetDetailObj.name}</span> | |||
| <div className={Styles.smallTagBox}> | |||
| <div className={Styles.tagItem}>模型 id:{datasetDetailObj.id}</div> | |||
| <div className={Styles.tagItem}>{datasetDetailObj.model_type_name || '...'}</div> | |||
| <div className={Styles.tagItem}>{datasetDetailObj.model_tag_name || '...'}</div> | |||
| </div> | |||
| </div> | |||
| <div className={Styles.datasetIntroCneterBox}> | |||
| <Tabs defaultActiveKey="1"> | |||
| <TabPane tab="模型简介" key="1"> | |||
| <div className={Styles.datasetIntroTitle}>简介</div> | |||
| <div className={Styles.datasetIntroText}>{datasetDetailObj.description}</div> | |||
| </TabPane> | |||
| <TabPane tab="模型文件/版本" key="2"> | |||
| <div className={Styles.dataListBox}> | |||
| <div>模型列表</div> | |||
| <div className={Styles.dataButtonList}> | |||
| <div | |||
| style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }} | |||
| > | |||
| <span style={{ marginRight: '10px' }}>版本号:</span> | |||
| <Select | |||
| placeholder="请选择版本号" | |||
| style={{ | |||
| width: 160, | |||
| }} | |||
| value={version} | |||
| allowClear | |||
| onChange={handleChange} | |||
| options={versionList} | |||
| /> | |||
| <Button | |||
| type="default" | |||
| className={Styles.plusButton} | |||
| onClick={showModal} | |||
| icon={<KFIcon type="icon-xinjian2" />} | |||
| > | |||
| 创建新版本 | |||
| </Button> | |||
| </div> | |||
| <div | |||
| style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }} | |||
| > | |||
| {!isPublic && ( | |||
| <Button | |||
| type="default" | |||
| className={Styles.plusButton} | |||
| style={{ margin: '0 20px 0 0' }} | |||
| onClick={deleteDataset} | |||
| icon={<KFIcon type="icon-shanchu" />} | |||
| > | |||
| 删除 | |||
| </Button> | |||
| )} | |||
| <Button | |||
| type="default" | |||
| className={Styles.plusButton} | |||
| disabled={!version} | |||
| style={{ margin: '0 20px 0 0' }} | |||
| onClick={handleExport} | |||
| icon={<KFIcon type="icon-xiazai" />} | |||
| > | |||
| 下载 | |||
| </Button> | |||
| </div> | |||
| </div> | |||
| <div style={{ marginBottom: '10px', fontSize: '14px' }}> | |||
| {wordList.length > 0 && wordList[0].description | |||
| ? '版本描述:' + wordList[0].description | |||
| : null} | |||
| </div> | |||
| <Table columns={columns} dataSource={wordList} pagination={false} rowKey="id" /> | |||
| </div> | |||
| </TabPane> | |||
| </Tabs> | |||
| </div> | |||
| </div> | |||
| ); | |||
| }; | |||
| export default Dataset; | |||
| @@ -1,80 +0,0 @@ | |||
| .datasetIntroTopBox { | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-between; | |||
| width: 100%; | |||
| height: 110px; | |||
| margin-bottom: 10px; | |||
| padding: 25px 30px; | |||
| background-image: url(/assets/images/dataset-back.png); | |||
| background-repeat: no-repeat; | |||
| background-position: top center; | |||
| background-size: 100% 100%; | |||
| .smallTagBox { | |||
| display: flex; | |||
| align-items: center; | |||
| color: #1664ff; | |||
| font-size: 14px; | |||
| .tagItem { | |||
| margin-right: 20px; | |||
| padding: 4px 10px; | |||
| background: rgba(22, 100, 255, 0.1); | |||
| border-radius: 4px; | |||
| } | |||
| } | |||
| } | |||
| .dataListBox { | |||
| padding: 20px 30px; | |||
| color: #1d1d20; | |||
| font-size: 16px; | |||
| background: #ffffff; | |||
| border-radius: 10px; | |||
| box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09); | |||
| .dataButtonList { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| height: 32px; | |||
| margin: 24px 0 30px 0; | |||
| color: #575757; | |||
| font-size: 16px; | |||
| } | |||
| } | |||
| .datasetIntroCneterBox { | |||
| height: 77vh; | |||
| padding: 20px 30px; | |||
| background: #ffffff; | |||
| border-radius: 10px; | |||
| box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09); | |||
| } | |||
| .datasetIntroTitle { | |||
| margin: 37px 0 10px 0; | |||
| color: #1d1d20; | |||
| font-size: 15px; | |||
| } | |||
| .datasetIntroText { | |||
| margin-bottom: 30px; | |||
| color: #575757; | |||
| font-size: 14px; | |||
| } | |||
| .datasetBox { | |||
| font-family: 'Alibaba'; | |||
| background: #f9fafb; | |||
| :global { | |||
| .ant-tabs-top > .ant-tabs-nav { | |||
| margin: 0; | |||
| } | |||
| .ant-pagination { | |||
| text-align: right; | |||
| } | |||
| } | |||
| } | |||
| .plusButton { | |||
| margin: 0 18px 0 20px; | |||
| } | |||
| .tipContent { | |||
| margin-top: 5px; | |||
| color: #c73131; | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| import ResourceIntro from '@/pages/Dataset/components/ResourceIntro'; | |||
| import { ResourceType } from '@/pages/Dataset/config'; | |||
| function ModelIntro() { | |||
| return <ResourceIntro resourceType={ResourceType.Model} />; | |||
| } | |||
| export default ModelIntro; | |||
| @@ -13,7 +13,7 @@ | |||
| } | |||
| .PipelineBox { | |||
| height: calc(100% - 20px); | |||
| height: 100%; | |||
| .PipelineTable { | |||
| height: calc(100% - 60px); | |||
| :global { | |||
| @@ -29,7 +29,7 @@ export function resolveBlob(res: any, mimeType: string) { | |||
| document.body.removeChild(aLink); | |||
| } | |||
| export function downLoadZip(url: string, params: any) { | |||
| export function downLoadZip(url: string, params?: any) { | |||
| request(url, { | |||
| method: 'GET', | |||
| params, | |||