| @@ -17,7 +17,7 @@ const filterResourceStandard: SelectProps<string, ComputingResource>['filterOpti | |||
| const convertId = (item: any) => ({ | |||
| ...item, | |||
| id: JSON.stringify({ | |||
| id: item.id, | |||
| id: `${item.id}`, | |||
| name: item.name, | |||
| identifier: item.identifier, | |||
| owner: item.owner, | |||
| @@ -37,7 +37,7 @@ export const paramSelectConfig: Record<string, SelectPropsConfig> = { | |||
| const res = await getDatasetList({ | |||
| page: 0, | |||
| size: 1000, | |||
| available_range: 0, | |||
| is_public: false, | |||
| }); | |||
| return res?.data?.content?.map(convertId) ?? []; | |||
| }, | |||
| @@ -52,7 +52,7 @@ export const paramSelectConfig: Record<string, SelectPropsConfig> = { | |||
| const res = await getModelList({ | |||
| page: 0, | |||
| size: 1000, | |||
| available_range: 0, | |||
| is_public: false, | |||
| }); | |||
| return res?.data?.content?.map(convertId) ?? []; | |||
| }, | |||
| @@ -101,15 +101,18 @@ body { | |||
| ::-webkit-scrollbar { | |||
| width: 8px; | |||
| height: 8px; | |||
| background: transparent; | |||
| } | |||
| ::-webkit-scrollbar-thumb { | |||
| width: 8px; | |||
| height: 8px; | |||
| background: rgba(0, 0, 0, 0.5); | |||
| border-radius: 99px; | |||
| } | |||
| ::-webkit-scrollbar-track { | |||
| width: 8px; | |||
| height: 8px; | |||
| background: transparent; | |||
| } | |||
| ul, | |||
| @@ -14,35 +14,43 @@ | |||
| } | |||
| &__name { | |||
| position: relative; | |||
| display: inline-block; | |||
| height: 24px; | |||
| margin: 0 10px 0 0 !important; | |||
| margin-right: 10px; | |||
| margin-bottom: 0 !important; | |||
| color: @text-color; | |||
| font-size: 16px; | |||
| } | |||
| &__tag { | |||
| padding: 4px; | |||
| color: @primary-color; | |||
| padding: 2px 11px; | |||
| font-size: 12px; | |||
| background-color: .addAlpha(@primary-color, 0.1) []; | |||
| border-radius: 4px; | |||
| border-radius: 1000px; | |||
| &--public { | |||
| color: @primary-color; | |||
| background-color: .addAlpha(@primary-color, 0.08) []; | |||
| border-color: .addAlpha(@primary-color, 0.5) []; | |||
| } | |||
| &--private { | |||
| color: @warning-color; | |||
| background-color: .addAlpha(@warning-color, 0.08) []; | |||
| border-color: .addAlpha(@warning-color, 0.5) []; | |||
| } | |||
| } | |||
| &__url { | |||
| margin-bottom: 10px; | |||
| color: @text-color-secondary; | |||
| font-size: 14px; | |||
| } | |||
| &__description { | |||
| height: 44px; | |||
| &__branch { | |||
| margin-bottom: 20px; | |||
| color: @text-color-secondary; | |||
| color: @text-color-tertiary; | |||
| font-size: 14px; | |||
| .multiLine(2); | |||
| } | |||
| &__user, | |||
| &__time { | |||
| display: flex; | |||
| flex: 0 1 content; | |||
| @@ -55,21 +63,9 @@ | |||
| &:hover { | |||
| border-color: @primary-color; | |||
| box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1); | |||
| .resource-item__name { | |||
| color: @primary-color; | |||
| } | |||
| } | |||
| } | |||
| .resource-item__name { | |||
| &::after { | |||
| position: absolute; | |||
| top: 14px; | |||
| left: 0; | |||
| width: 100%; | |||
| height: 6px; | |||
| background: linear-gradient(to right, rgba(22, 100, 255, 0.3) 0, rgba(22, 100, 255, 0) 100%); | |||
| content: ''; | |||
| &:hover &__name { | |||
| color: @primary-color; | |||
| } | |||
| } | |||
| @@ -5,6 +5,7 @@ import { AvailableRange } from '@/enums'; | |||
| import { type CodeConfigData } from '@/pages/CodeConfig/List'; | |||
| import { formatDate } from '@/utils/date'; | |||
| import { Button, Flex, Typography } from 'antd'; | |||
| import classNames from 'classnames'; | |||
| import styles from './index.less'; | |||
| type CodeConfigItemProps = { | |||
| @@ -24,10 +25,16 @@ function CodeConfigItem({ item, onClick, onEdit, onRemove }: CodeConfigItemProps | |||
| > | |||
| {item.code_repo_name} | |||
| </Typography.Paragraph> | |||
| <div className={styles['code-config-item__tag']}> | |||
| <div | |||
| className={classNames( | |||
| styles['code-config-item__tag'], | |||
| item.code_repo_vis === AvailableRange.Public | |||
| ? styles['code-config-item__tag--public'] | |||
| : styles['code-config-item__tag--private'], | |||
| )} | |||
| > | |||
| {item.code_repo_vis === AvailableRange.Public ? '公开' : '私有'} | |||
| </div> | |||
| <Button | |||
| type="text" | |||
| shape="circle" | |||
| @@ -54,15 +61,12 @@ function CodeConfigItem({ item, onClick, onEdit, onRemove }: CodeConfigItemProps | |||
| <Typography.Paragraph | |||
| className={styles['code-config-item__url']} | |||
| ellipsis={{ tooltip: item.git_url }} | |||
| style={{ marginBottom: '8px' }} | |||
| > | |||
| {item.git_url} | |||
| </Typography.Paragraph> | |||
| <div className={styles['code-config-item__url']} style={{ marginBottom: '20px' }}> | |||
| {item.git_branch} | |||
| </div> | |||
| <div className={styles['code-config-item__branch']}>{item.git_branch}</div> | |||
| <Flex justify="space-between"> | |||
| <div className={styles['code-config-item__time']}> | |||
| <div className={styles['code-config-item__user']}> | |||
| <img | |||
| style={{ width: '17px', marginRight: '6px' }} | |||
| src={creatByImg} | |||
| @@ -1,7 +1,7 @@ | |||
| import { getAccessToken } from '@/access'; | |||
| import KFIcon from '@/components/KFIcon'; | |||
| import KFModal from '@/components/KFModal'; | |||
| import { CategoryData, ResourceType, resourceConfig } from '@/pages/Dataset/config'; | |||
| import { CategoryData, DataSource, ResourceType, resourceConfig } from '@/pages/Dataset/config'; | |||
| import { addDataset } from '@/services/dataset/index.js'; | |||
| import { to } from '@/utils/promise'; | |||
| import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; | |||
| @@ -67,6 +67,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||
| if (validateUploadFiles(fileList)) { | |||
| const params = { | |||
| ...omit(formData, ['fileList']), | |||
| dataset_source: DataSource.Create, | |||
| dataset_version_vos: fileList.map((item) => { | |||
| const data = item.response?.data?.[0] ?? {}; | |||
| return { | |||
| @@ -120,6 +121,10 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||
| required: true, | |||
| message: '请输入数据集版本', | |||
| }, | |||
| { | |||
| pattern: /^[a-zA-Z0-9._-]+$/, | |||
| message: '版本只支持字母、数字、下划线、点、横杠', | |||
| }, | |||
| { | |||
| validator: (_rule, value) => { | |||
| if (value === 'master') { | |||
| @@ -1,7 +1,7 @@ | |||
| import { getAccessToken } from '@/access'; | |||
| import KFIcon from '@/components/KFIcon'; | |||
| import KFModal from '@/components/KFModal'; | |||
| import { CategoryData, ResourceType, resourceConfig } from '@/pages/Dataset/config'; | |||
| import { CategoryData, DataSource, ResourceType, resourceConfig } from '@/pages/Dataset/config'; | |||
| import { addModel } from '@/services/dataset/index.js'; | |||
| import { to } from '@/utils/promise'; | |||
| import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; | |||
| @@ -54,6 +54,7 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||
| if (validateUploadFiles(fileList)) { | |||
| const params = { | |||
| ...omit(formData, ['fileList']), | |||
| model_source: DataSource.Create, | |||
| model_version_vos: fileList.map((item) => { | |||
| const data = item.response?.data?.[0] ?? {}; | |||
| return { | |||
| @@ -105,6 +106,10 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps) | |||
| required: true, | |||
| message: '请输入模型版本', | |||
| }, | |||
| { | |||
| pattern: /^[a-zA-Z0-9._-]+$/, | |||
| message: '版本只支持字母、数字、下划线、点、横杠', | |||
| }, | |||
| { | |||
| validator: (_rule, value) => { | |||
| if (value === 'master') { | |||
| @@ -1,7 +1,7 @@ | |||
| import { getAccessToken } from '@/access'; | |||
| import KFIcon from '@/components/KFIcon'; | |||
| import KFModal from '@/components/KFModal'; | |||
| import { ResourceType, resourceConfig } from '@/pages/Dataset/config'; | |||
| import { DataSource, ResourceType, resourceConfig } from '@/pages/Dataset/config'; | |||
| import { to } from '@/utils/promise'; | |||
| import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; | |||
| import { | |||
| @@ -73,6 +73,7 @@ function AddVersionModal({ | |||
| identifier, | |||
| [config.filePropKey]: version_vos, | |||
| ...omit(formData, 'fileList'), | |||
| [config.sourceParamKey]: DataSource.Create, | |||
| }; | |||
| createDatasetVersion(params); | |||
| } | |||
| @@ -120,6 +121,10 @@ function AddVersionModal({ | |||
| required: true, | |||
| message: `请输入${name}版本`, | |||
| }, | |||
| { | |||
| pattern: /^[a-zA-Z0-9._-]+$/, | |||
| message: '版本只支持字母、数字、下划线、点、横杠', | |||
| }, | |||
| { | |||
| validator: (_rule, value) => { | |||
| if (value === 'master') { | |||
| @@ -145,7 +150,7 @@ function AddVersionModal({ | |||
| <Input.TextArea | |||
| placeholder="请输入版本描述" | |||
| autoSize={{ minRows: 2, maxRows: 6 }} | |||
| maxLength={256} | |||
| maxLength={200} | |||
| showCount | |||
| allowClear | |||
| /> | |||
| @@ -16,9 +16,11 @@ | |||
| color: @text-color; | |||
| font-weight: 500; | |||
| font-size: 20px; | |||
| .singleLine(); | |||
| } | |||
| &__tag { | |||
| flex: none; | |||
| padding: 4px 10px; | |||
| color: @primary-color; | |||
| font-size: 14px; | |||
| @@ -24,7 +24,12 @@ function ResourceVersion({ resourceType, info }: ResourceVersionProps) { | |||
| // 全部导出 | |||
| const handleExport = async () => { | |||
| const url = config.downloadAllAction; | |||
| downLoadZip(url, { name: info.name, id: info.id, version: info.version }); | |||
| downLoadZip(url, { | |||
| name: info.name, | |||
| id: info.id, | |||
| version: info.version, | |||
| identifier: info.identifier, | |||
| }); | |||
| }; | |||
| // 单个导出 | |||
| @@ -21,6 +21,11 @@ export enum ResourceType { | |||
| Dataset = 'Dataset', // 数据集 | |||
| } | |||
| export enum DataSource { | |||
| Export = 'export', // 导出 | |||
| Create = 'add', // 新增 | |||
| } | |||
| type ResourceTypeInfo = { | |||
| getList: (params: any) => Promise<any>; // 获取资源列表 | |||
| getVersions: (params: any) => Promise<any>; // 获取版本列表 | |||
| @@ -32,6 +37,7 @@ type ResourceTypeInfo = { | |||
| typeParamKey: 'data_type' | 'model_type'; // 类型参数名称,获取资源列表接口使用 | |||
| tagParamKey: 'data_tag' | 'model_tag'; // 标签参数名称,获取资源列表接口使用 | |||
| filePropKey: 'dataset_version_vos' | 'model_version_vos'; // 文件列表属性 | |||
| sourceParamKey: 'dataset_source' | 'model_source'; // 来源参数名称 | |||
| tabItems: TabsProps['items']; // tab 列表 | |||
| typeTitle: string; // 类型标题 | |||
| tagTitle: string; // 标签标题 | |||
| @@ -58,6 +64,7 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| typeParamKey: 'data_type', | |||
| tagParamKey: 'data_tag', | |||
| filePropKey: 'dataset_version_vos', | |||
| sourceParamKey: 'dataset_source', | |||
| tabItems: [ | |||
| { | |||
| key: CommonTabKeys.Public, | |||
| @@ -80,7 +87,7 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| uploadAction: '/api/mmp/newdataset/upload', | |||
| uploadAccept: '.zip,.tgz', | |||
| downloadAllAction: '/api/mmp/newdataset/downloadAllFiles', | |||
| downloadSingleAction: '/api/mmp/newdataset/downloadSinggerFile', | |||
| downloadSingleAction: '/api/mmp/newdataset/downloadSingleFile', | |||
| }, | |||
| [ResourceType.Model]: { | |||
| getList: getModelList, | |||
| @@ -93,6 +100,7 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||
| typeParamKey: 'model_type', | |||
| tagParamKey: 'model_tag', | |||
| filePropKey: 'model_version_vos', | |||
| sourceParamKey: 'model_source', | |||
| tabItems: [ | |||
| { | |||
| key: CommonTabKeys.Public, | |||
| @@ -1,6 +1,6 @@ | |||
| import editExperimentIcon from '@/assets/img/edit-experiment.png'; | |||
| import KFModal from '@/components/KFModal'; | |||
| import { type ResourceData } from '@/pages/Dataset/config'; | |||
| import { ResourceVersionData, type ResourceData } from '@/pages/Dataset/config'; | |||
| import { | |||
| addModelVersion, | |||
| exportModelReq, | |||
| @@ -10,6 +10,7 @@ import { | |||
| import { to } from '@/utils/promise'; | |||
| import { InfoCircleOutlined } from '@ant-design/icons'; | |||
| import { Form, Input, ModalProps, Select } from 'antd'; | |||
| import { pick } from 'lodash'; | |||
| import { useEffect, useState } from 'react'; | |||
| import styles from './index.less'; | |||
| @@ -40,7 +41,7 @@ interface ExportModelModalProps extends Omit<ModalProps, 'onOk'> { | |||
| function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) { | |||
| const [form] = Form.useForm(); | |||
| const [models, setModels] = useState<ResourceData[]>([]); | |||
| const [versions, setVersions] = useState<string[]>([]); | |||
| const [versions, setVersions] = useState<ResourceVersionData[]>([]); | |||
| const [uuid] = useState(Date.now()); | |||
| const layout = { | |||
| @@ -56,8 +57,9 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) { | |||
| const getTooltip = () => { | |||
| const id = form.getFieldValue('models_id'); | |||
| const name = models.find((item) => item.id === id)?.name ?? ''; | |||
| const versionNames = versions.map((item: ResourceVersionData) => item.name).join('、'); | |||
| const tooltip = | |||
| versions.length > 0 ? `${name}有以下版本:\n${versions.join('、')}\n注意不能重复` : undefined; | |||
| versions.length > 0 ? `${name}有以下版本:\n${versionNames}\n注意不能重复` : undefined; | |||
| return tooltip; | |||
| }; | |||
| @@ -75,7 +77,7 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) { | |||
| const params = { | |||
| page: 0, | |||
| size: 1000, | |||
| available_range: 0, // 个人 | |||
| is_public: false, // 个人 | |||
| }; | |||
| const [res] = await to(getModelList(params)); | |||
| if (res && res.data) { | |||
| @@ -85,7 +87,11 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) { | |||
| // 获取模型版本列表 | |||
| const getModelVersions = async (id: number) => { | |||
| const [res] = await to(getModelVersionList(id)); | |||
| const model = models.find((item) => item.id === id); | |||
| if (!model) { | |||
| return; | |||
| } | |||
| const [res] = await to(getModelVersionList(pick(model, ['identifier', 'owner']))); | |||
| if (res && res.data) { | |||
| setVersions(res.data); | |||
| } | |||
| @@ -175,7 +181,7 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) { | |||
| { required: true, message: '请输入模型版本' }, | |||
| { | |||
| validator: (_, value) => { | |||
| if (value && versions.includes(value)) { | |||
| if (value && versions.map((item) => item.name).includes(value)) { | |||
| return Promise.reject('模型版本已存在'); | |||
| } else { | |||
| return Promise.resolve(); | |||
| @@ -1,68 +1,56 @@ | |||
| .code-config-item { | |||
| position: relative; | |||
| padding: 20px; | |||
| background: white; | |||
| border: 1px solid #eaeaea; | |||
| width: calc(25% - 7.5px); | |||
| padding: 15px; | |||
| background-color: .addAlpha(@primary-color, 0.04) []; | |||
| border: 1px solid transparent; | |||
| border-radius: 4px; | |||
| cursor: pointer; | |||
| &__name { | |||
| position: relative; | |||
| display: inline-block; | |||
| height: 24px; | |||
| margin: 0 10px 0 0 !important; | |||
| margin-right: 8px; | |||
| margin-bottom: 0 !important; | |||
| color: @text-color; | |||
| font-size: 16px; | |||
| font-size: 14px; | |||
| } | |||
| &__tag { | |||
| padding: 4px; | |||
| color: @primary-color; | |||
| flex: none; | |||
| padding: 2px 11px; | |||
| font-size: 12px; | |||
| background-color: .addAlpha(@primary-color, 0.1) []; | |||
| border-radius: 4px; | |||
| } | |||
| border-radius: 1000px; | |||
| &__url { | |||
| color: @text-color-secondary; | |||
| font-size: 14px; | |||
| &--public { | |||
| color: @primary-color; | |||
| background-color: .addAlpha(@primary-color, 0.08) []; | |||
| border-color: .addAlpha(@primary-color, 0.5) []; | |||
| } | |||
| &--private { | |||
| color: @warning-color; | |||
| background-color: .addAlpha(@warning-color, 0.08) []; | |||
| border-color: .addAlpha(@warning-color, 0.5) []; | |||
| } | |||
| } | |||
| &__description { | |||
| height: 44px; | |||
| margin-bottom: 20px; | |||
| &__url { | |||
| height: 40px; | |||
| margin-bottom: 10px !important; | |||
| color: @text-color-secondary; | |||
| font-size: 14px; | |||
| .multiLine(2); | |||
| font-size: 13px; | |||
| } | |||
| &__time { | |||
| display: flex; | |||
| flex: 0 1 content; | |||
| align-items: center; | |||
| width: 100%; | |||
| color: #808080; | |||
| font-size: 13px; | |||
| &__branch { | |||
| color: @text-color-tertiary; | |||
| font-size: 12px; | |||
| } | |||
| &:hover { | |||
| border-color: @primary-color; | |||
| box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1); | |||
| .resource-item__name { | |||
| color: @primary-color; | |||
| } | |||
| } | |||
| } | |||
| .resource-item__name { | |||
| &::after { | |||
| position: absolute; | |||
| top: 14px; | |||
| left: 0; | |||
| width: 100%; | |||
| height: 6px; | |||
| background: linear-gradient(to right, rgba(22, 100, 255, 0.3) 0, rgba(22, 100, 255, 0) 100%); | |||
| content: ''; | |||
| &:hover &__name { | |||
| color: @primary-color; | |||
| } | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| import { AvailableRange } from '@/enums'; | |||
| import { type CodeConfigData } from '@/pages/CodeConfig/List'; | |||
| import { Flex, Typography } from 'antd'; | |||
| import classNames from 'classnames'; | |||
| import styles from './index.less'; | |||
| type CodeConfigItemProps = { | |||
| @@ -11,27 +12,31 @@ type CodeConfigItemProps = { | |||
| function CodeConfigItem({ item, onClick }: CodeConfigItemProps) { | |||
| return ( | |||
| <div className={styles['code-config-item']} onClick={() => onClick?.(item)}> | |||
| <Flex justify="space-between" align="center" style={{ marginBottom: '20px', height: '32px' }}> | |||
| <Flex justify="space-between" align="center" style={{ marginBottom: '15px' }}> | |||
| <Typography.Paragraph | |||
| className={styles['code-config-item__name']} | |||
| ellipsis={{ tooltip: item.code_repo_name }} | |||
| > | |||
| {item.code_repo_name} | |||
| </Typography.Paragraph> | |||
| <div className={styles['code-config-item__tag']}> | |||
| <div | |||
| className={classNames( | |||
| styles['code-config-item__tag'], | |||
| item.code_repo_vis === AvailableRange.Public | |||
| ? styles['code-config-item__tag--public'] | |||
| : styles['code-config-item__tag--private'], | |||
| )} | |||
| > | |||
| {item.code_repo_vis === AvailableRange.Public ? '公开' : '私有'} | |||
| </div> | |||
| </Flex> | |||
| <Typography.Paragraph | |||
| className={styles['code-config-item__url']} | |||
| ellipsis={{ tooltip: item.git_url }} | |||
| style={{ marginBottom: '8px' }} | |||
| ellipsis={{ rows: 2, tooltip: item.git_url }} | |||
| > | |||
| {item.git_url} | |||
| </Typography.Paragraph> | |||
| <div className={styles['code-config-item__url']} style={{ marginBottom: '20px' }}> | |||
| {item.git_branch} | |||
| </div> | |||
| <div className={styles['code-config-item__branch']}>{item.git_branch}</div> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -2,28 +2,53 @@ | |||
| width: 100%; | |||
| height: 100%; | |||
| &__search { | |||
| width: 100%; | |||
| } | |||
| :global { | |||
| .ant-input-affix-wrapper .ant-input-prefix { | |||
| margin-inline-end: 12px; | |||
| .ant-input-affix-wrapper { | |||
| border-radius: 23px !important; | |||
| .ant-input-prefix { | |||
| margin-inline-end: 12px; | |||
| } | |||
| .ant-input-suffix { | |||
| margin-inline-end: 12px; | |||
| } | |||
| .ant-input-clear-icon { | |||
| font-size: 16px; | |||
| } | |||
| } | |||
| .ant-pagination { | |||
| text-align: right; | |||
| text-align: center; | |||
| } | |||
| .ant-input-group-addon { | |||
| display: none; | |||
| } | |||
| .ant-pagination { | |||
| .ant-select-single { | |||
| height: 32px !important; | |||
| } | |||
| } | |||
| } | |||
| &__content { | |||
| display: grid; | |||
| grid-template-columns: repeat(3, minmax(0, 1fr)); | |||
| gap: 20px; | |||
| display: flex; | |||
| flex-direction: row; | |||
| flex-wrap: wrap; | |||
| gap: 10px; | |||
| width: 100%; | |||
| margin-top: 30px; | |||
| max-height: 50vh; | |||
| margin-top: 24px; | |||
| margin-bottom: 30px; | |||
| overflow-x: hidden; | |||
| overflow-y: auto; | |||
| } | |||
| &__empty { | |||
| padding-top: 40px; | |||
| } | |||
| } | |||
| @@ -8,6 +8,7 @@ import KFModal from '@/components/KFModal'; | |||
| import { type CodeConfigData } from '@/pages/CodeConfig/List'; | |||
| import { getCodeConfigListReq } from '@/services/codeConfig'; | |||
| import { to } from '@/utils/promise'; | |||
| import { Icon } from '@umijs/max'; | |||
| import type { ModalProps, PaginationProps } from 'antd'; | |||
| import { Empty, Input, Pagination } from 'antd'; | |||
| import { useEffect, useState } from 'react'; | |||
| @@ -74,15 +75,17 @@ function CodeSelectorModal({ onOk, ...rest }: CodeSelectorModalProps) { | |||
| > | |||
| <div className={styles['code-selector']}> | |||
| <Input.Search | |||
| className={styles['code-selector__search']} | |||
| placeholder="按代码仓库名称筛选" | |||
| allowClear | |||
| onSearch={handleSearch} | |||
| style={{ | |||
| width: '100%', | |||
| }} | |||
| size="large" | |||
| onChange={(e) => setInputText(e.target.value)} | |||
| suffix={null} | |||
| value={inputText} | |||
| prefix={ | |||
| <Icon icon="local:magnifying-glass" style={{ marginLeft: '10px', marginTop: '2px' }} /> | |||
| } | |||
| /> | |||
| {dataList?.length !== 0 ? ( | |||
| <> | |||
| @@ -103,7 +106,7 @@ function CodeSelectorModal({ onOk, ...rest }: CodeSelectorModalProps) { | |||
| </> | |||
| ) : ( | |||
| <div className={styles['code-selector__empty']}> | |||
| <Empty></Empty> | |||
| <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}></Empty> | |||
| </div> | |||
| )} | |||
| </div> | |||
| @@ -50,10 +50,12 @@ | |||
| border-radius: 8px; | |||
| &__title { | |||
| height: 46px; | |||
| margin-bottom: 15px; | |||
| padding: 3px 0 6px; | |||
| color: @text-color; | |||
| font-size: @font-size; | |||
| line-height: 46px; | |||
| border-bottom: 1px solid @border-color-secondary; | |||
| } | |||
| &__files { | |||
| @@ -48,7 +48,7 @@ | |||
| &__count { | |||
| width: 24px; | |||
| height: 24px; | |||
| color: #8a8a8a; | |||
| color: @text-color-tertiary; | |||
| font-size: 12px; | |||
| line-height: 24px; | |||
| text-align: center; | |||
| @@ -3,7 +3,14 @@ | |||
| * @Date: 2024-03-25 13:52:54 | |||
| * @Description: 网络请求配置,详情请参考 https://umijs.org/docs/max/request | |||
| */ | |||
| import type { AxiosRequestConfig, AxiosResponse, RequestConfig, RequestOptions } from '@umijs/max'; | |||
| import type { | |||
| AxiosError, | |||
| AxiosRequestConfig, | |||
| AxiosResponse, | |||
| RequestConfig, | |||
| RequestError, | |||
| RequestOptions, | |||
| } from '@umijs/max'; | |||
| import { message } from 'antd'; | |||
| import { clearSessionToken, getAccessToken } from './access'; | |||
| import { setRemoteMenu } from './services/session'; | |||
| @@ -12,13 +19,12 @@ import { gotoLoginPage } from './utils/ui'; | |||
| // [antd: Notification] You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead. | |||
| const popupError = (error: string, skipErrorHandler: boolean | undefined = false) => { | |||
| if (skipErrorHandler) { | |||
| return; | |||
| if (!skipErrorHandler) { | |||
| // 直接调用 message.error 有时候不弹出来 | |||
| setTimeout(() => { | |||
| message.error(error); | |||
| }, 100); | |||
| } | |||
| // 直接调用 message.error 有时候不弹出来 | |||
| setTimeout(() => { | |||
| message.error(error); | |||
| }, 100); | |||
| }; | |||
| /** | |||
| @@ -32,22 +38,29 @@ export const requestConfig: RequestConfig = { | |||
| const headers = options.headers ?? {}; | |||
| const authHeader = headers['Authorization']; | |||
| const isToken = headers['isToken']; | |||
| const skipLoading = (options as RequestOptions)?.skipLoading; | |||
| if (!authHeader && isToken !== false) { | |||
| const accessToken = getAccessToken(); | |||
| if (accessToken) { | |||
| headers['Authorization'] = `Bearer ${accessToken}`; | |||
| } | |||
| } | |||
| Loading.show(); | |||
| if (!skipLoading) { | |||
| Loading.show(); | |||
| } | |||
| return { url, options }; | |||
| }, | |||
| ], | |||
| responseInterceptors: [ | |||
| [ | |||
| (response: AxiosResponse) => { | |||
| Loading.hide(); | |||
| const { status, data, config } = response || {}; | |||
| const skipErrorHandler = (config as RequestOptions)?.skipErrorHandler; | |||
| const options = config as RequestOptions; | |||
| const skipErrorHandler = options?.skipErrorHandler; | |||
| const skipLoading = options?.skipLoading; | |||
| if (!skipLoading) { | |||
| Loading.hide(); | |||
| } | |||
| if (status >= 200 && status < 300) { | |||
| if (data && (data instanceof Blob || data.code === 200)) { | |||
| return response; | |||
| @@ -66,9 +79,14 @@ export const requestConfig: RequestConfig = { | |||
| return Promise.reject(response); | |||
| } | |||
| }, | |||
| (error: Error) => { | |||
| Loading.hide(); | |||
| popupError(error.message ?? '请求失败'); | |||
| (error: RequestError) => { | |||
| const options = (error as AxiosError).config as RequestOptions; | |||
| const skipErrorHandler = options?.skipErrorHandler; | |||
| const skipLoading = options?.skipLoading; | |||
| if (!skipLoading) { | |||
| Loading.hide(); | |||
| } | |||
| popupError(error.message ?? '请求失败', skipErrorHandler); | |||
| return Promise.reject(error); | |||
| }, | |||
| ], | |||
| @@ -67,14 +67,6 @@ export function downloadAllFiles(params) { | |||
| }); | |||
| } | |||
| // 下载数据集单个文件 | |||
| export function downloadSingleFile(params) { | |||
| return request(`/api/mmp/newdataset/downloadSinggerFile`, { | |||
| method: 'GET', | |||
| params, | |||
| }); | |||
| } | |||
| // 删除数据集版本 | |||
| export function deleteDatasetVersion(params) { | |||
| return request(`/api/mmp/newdataset/deleteDatasetVersion`, { | |||
| @@ -103,7 +103,7 @@ export function putExperiment(data) { | |||
| }); | |||
| } | |||
| // 启动tensorBoard | |||
| // 启动 tensorBoard | |||
| export function runTensorBoardReq(data) { | |||
| return request(`/api/mmp/tensorBoard/run`, { | |||
| method: 'POST', | |||
| @@ -111,11 +111,12 @@ export function runTensorBoardReq(data) { | |||
| }); | |||
| } | |||
| // 启动tensorBoard | |||
| // 获取 tensorBoard 状态 | |||
| export function getTensorBoardStatusReq(data) { | |||
| return request(`/api/mmp/tensorBoard/getStatus`, { | |||
| method: 'POST', | |||
| data, | |||
| skipLoading: true, | |||
| }); | |||
| } | |||
| @@ -11,6 +11,7 @@ | |||
| @background-color: #f9fafb; // 页面背景颜色 | |||
| @text-color: #1d1d20; | |||
| @text-color-secondary: #575757; | |||
| @text-color-tertiary: #8a8a8a; | |||
| @success-color: #6ac21d; | |||
| @error-color: #c73131; | |||
| @warning-color: #f98e1b; | |||
| @@ -18,6 +19,7 @@ | |||
| @pending-color: #ecb934; | |||
| @underline-color: #5d93ff; | |||
| @border-color-base: #eaeaea; | |||
| @border-color: rgba(22, 100, 255, 0.3); | |||
| @border-color-secondary: rgba(22, 100, 255, 0.1); | |||
| @background-color-primary: rgba(22, 100, 255, 0.03); | |||
| @@ -25,7 +27,7 @@ | |||
| @heading-color: rgba(0, 0, 0, 0.85); | |||
| @input-icon-hover-color: rgba(0, 0, 0, 0.85); | |||
| @border-color-base: #d9d9d9; | |||
| @link-hover-color: #69b1ff; | |||
| @sider-background-color: #f2f5f7; | |||
| @@ -74,6 +76,7 @@ | |||
| warningColor: @warning-color; | |||
| textColor: @text-color; | |||
| textColorSecondary: @text-color-secondary; | |||
| textColorTertiary: @text-color-tertiary; | |||
| fontSize: @font-size; | |||
| fontSizeTitle: @font-size-title; | |||
| fontSizeContent: @font-size-content; | |||