| @@ -32,9 +32,9 @@ export default function BasicTableInfo({ | |||||
| return ( | return ( | ||||
| <div className={classNames('kf-basic-table-info', className)} style={style}> | <div className={classNames('kf-basic-table-info', className)} style={style}> | ||||
| {showDatas.map((item) => ( | |||||
| {showDatas.map((item, index) => ( | |||||
| <BasicInfoItem | <BasicInfoItem | ||||
| key={item.label} | |||||
| key={`${item.label}-${index}`} | |||||
| data={item} | data={item} | ||||
| labelWidth={labelWidth} | labelWidth={labelWidth} | ||||
| classPrefix="kf-basic-table-info" | classPrefix="kf-basic-table-info" | ||||
| @@ -63,7 +63,7 @@ function AutoMLList() { | |||||
| const params: Record<string, any> = { | const params: Record<string, any> = { | ||||
| page: pagination.current! - 1, | page: pagination.current! - 1, | ||||
| size: pagination.pageSize, | size: pagination.pageSize, | ||||
| ml_name: searchText, | |||||
| ml_name: searchText || undefined, | |||||
| }; | }; | ||||
| const [res] = await to(getAutoMLListReq(params)); | const [res] = await to(getAutoMLListReq(params)); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| @@ -76,6 +76,10 @@ function AutoMLList() { | |||||
| // 搜索 | // 搜索 | ||||
| const onSearch: SearchProps['onSearch'] = (value) => { | const onSearch: SearchProps['onSearch'] = (value) => { | ||||
| setSearchText(value); | setSearchText(value); | ||||
| setPagination((prev) => ({ | |||||
| ...prev, | |||||
| current: 1, | |||||
| })); | |||||
| }; | }; | ||||
| // 删除模型部署 | // 删除模型部署 | ||||
| @@ -59,7 +59,7 @@ function CodeConfigList() { | |||||
| const params = { | const params = { | ||||
| page: pagination.current! - 1, | page: pagination.current! - 1, | ||||
| size: pagination.pageSize, | size: pagination.pageSize, | ||||
| code_repo_name: searchText !== '' ? searchText : undefined, | |||||
| code_repo_name: searchText || undefined, | |||||
| }; | }; | ||||
| const [res] = await to(getCodeConfigListReq(params)); | const [res] = await to(getCodeConfigListReq(params)); | ||||
| if (res && res.data && res.data.content) { | if (res && res.data && res.data.content) { | ||||
| @@ -83,6 +83,10 @@ function CodeConfigList() { | |||||
| // 搜索 | // 搜索 | ||||
| const handleSearch = (value: string) => { | const handleSearch = (value: string) => { | ||||
| setSearchText(value); | setSearchText(value); | ||||
| setPagination((prev) => ({ | |||||
| ...prev, | |||||
| current: 1, | |||||
| })); | |||||
| }; | }; | ||||
| // 删除 | // 删除 | ||||
| @@ -4,7 +4,7 @@ import KFModal from '@/components/KFModal'; | |||||
| import { CategoryData, DataSource, ResourceType, resourceConfig } from '@/pages/Dataset/config'; | import { CategoryData, DataSource, ResourceType, resourceConfig } from '@/pages/Dataset/config'; | ||||
| import { addDataset } from '@/services/dataset/index.js'; | import { addDataset } from '@/services/dataset/index.js'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; | |||||
| import { getFileListFromEvent, limitUploadFileType, validateUploadFiles } from '@/utils/ui'; | |||||
| import { | import { | ||||
| Button, | Button, | ||||
| Form, | Form, | ||||
| @@ -42,6 +42,8 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||||
| Authorization: getAccessToken() || '', | Authorization: getAccessToken() || '', | ||||
| }, | }, | ||||
| defaultFileList: [], | defaultFileList: [], | ||||
| accept: '.zip,.tgz', | |||||
| beforeUpload: limitUploadFileType('zip,tgz'), | |||||
| }; | }; | ||||
| // 获取集群版本数据 | // 获取集群版本数据 | ||||
| @@ -200,7 +202,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Upload {...uploadProps} data={{ uuid: uuid }} accept=".zip,.tgz"> | |||||
| <Upload {...uploadProps} data={{ uuid: uuid }}> | |||||
| <Button | <Button | ||||
| className={styles['upload-button']} | className={styles['upload-button']} | ||||
| type="default" | type="default" | ||||
| @@ -21,8 +21,9 @@ import styles from '../AddDatasetModal/index.less'; | |||||
| interface AddVersionModalProps extends Omit<ModalProps, 'onOk'> { | interface AddVersionModalProps extends Omit<ModalProps, 'onOk'> { | ||||
| resourceType: ResourceType; | resourceType: ResourceType; | ||||
| resourceId: number; | resourceId: number; | ||||
| identifier: string; | |||||
| resoureName: string; | resoureName: string; | ||||
| owner: string; | |||||
| identifier: string; | |||||
| is_public: boolean; | is_public: boolean; | ||||
| onOk: () => void; | onOk: () => void; | ||||
| } | } | ||||
| @@ -31,6 +32,7 @@ function AddVersionModal({ | |||||
| resourceType, | resourceType, | ||||
| resourceId, | resourceId, | ||||
| resoureName, | resoureName, | ||||
| owner, | |||||
| identifier, | identifier, | ||||
| is_public, | is_public, | ||||
| onOk, | onOk, | ||||
| @@ -46,6 +48,8 @@ function AddVersionModal({ | |||||
| Authorization: getAccessToken() || '', | Authorization: getAccessToken() || '', | ||||
| }, | }, | ||||
| defaultFileList: [], | defaultFileList: [], | ||||
| beforeUpload: config.beforeUpload, | |||||
| accept: config.uploadAccept, | |||||
| }; | }; | ||||
| // 上传请求 | // 上传请求 | ||||
| @@ -74,6 +78,7 @@ function AddVersionModal({ | |||||
| id: resourceId, | id: resourceId, | ||||
| identifier, | identifier, | ||||
| is_public, | is_public, | ||||
| owner, | |||||
| [config.filePropKey]: version_vos, | [config.filePropKey]: version_vos, | ||||
| ...omit(formData, 'fileList'), | ...omit(formData, 'fileList'), | ||||
| [config.sourceParamKey]: DataSource.Create, | [config.sourceParamKey]: DataSource.Create, | ||||
| @@ -83,7 +88,7 @@ function AddVersionModal({ | |||||
| }; | }; | ||||
| const name = config.name; | const name = config.name; | ||||
| const accept = config.uploadAccept; | |||||
| return ( | return ( | ||||
| <KFModal | <KFModal | ||||
| {...rest} | {...rest} | ||||
| @@ -170,7 +175,7 @@ function AddVersionModal({ | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Upload {...uploadProps} data={{ uuid: uuid }} accept={accept}> | |||||
| <Upload {...uploadProps} data={{ uuid: uuid }}> | |||||
| <Button | <Button | ||||
| className={styles['upload-button']} | className={styles['upload-button']} | ||||
| type="default" | type="default" | ||||
| @@ -179,7 +184,7 @@ function AddVersionModal({ | |||||
| 上传文件 | 上传文件 | ||||
| </Button> | </Button> | ||||
| {resourceType === ResourceType.Dataset && ( | {resourceType === ResourceType.Dataset && ( | ||||
| <div className={styles['upload-tip']}>只允许上传 .zip 格式文件</div> | |||||
| <div className={styles['upload-tip']}>只允许上传 .zip 和 .tgz 格式文件</div> | |||||
| )} | )} | ||||
| </Upload> | </Upload> | ||||
| </Form.Item> | </Form.Item> | ||||
| @@ -3,8 +3,7 @@ | |||||
| flex-direction: column; | flex-direction: column; | ||||
| align-items: center; | align-items: center; | ||||
| width: 92px; | width: 92px; | ||||
| height: 62px; | |||||
| padding: 11px 8px 7px; | |||||
| padding: 10px 8px 8px; | |||||
| color: @text-color; | color: @text-color; | ||||
| font-size: 12px; | font-size: 12px; | ||||
| border: 1px solid rgba(22, 100, 255, 0.05); | border: 1px solid rgba(22, 100, 255, 0.05); | ||||
| @@ -17,14 +16,6 @@ | |||||
| &__active-icon { | &__active-icon { | ||||
| display: none; | display: none; | ||||
| } | } | ||||
| &__name { | |||||
| width: 100%; | |||||
| margin-top: 4px; | |||||
| overflow: hidden; | |||||
| white-space: nowrap; | |||||
| text-align: center; | |||||
| text-overflow: ellipsis; | |||||
| } | |||||
| &:hover, | &:hover, | ||||
| &--active { | &--active { | ||||
| @@ -1,3 +1,4 @@ | |||||
| import { Typography } from 'antd'; | |||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { CategoryData, ResourceType, resourceConfig } from '../../config'; | import { CategoryData, ResourceType, resourceConfig } from '../../config'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -32,7 +33,13 @@ function CategoryItem({ resourceType, item, isSelected, onClick }: CategoryItemP | |||||
| alt="" | alt="" | ||||
| draggable={false} | draggable={false} | ||||
| /> | /> | ||||
| <span className={styles['category-item__name']}>{item.name}</span> | |||||
| <Typography.Text | |||||
| ellipsis={{ tooltip: item.name }} | |||||
| style={{ color: 'inherit', marginTop: '4px' }} | |||||
| > | |||||
| {item.name} | |||||
| </Typography.Text> | |||||
| {/* <span className={styles['category-item__name']}>{item.name}</span> */} | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -119,6 +119,7 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||||
| resourceType: resourceType, | resourceType: resourceType, | ||||
| resourceId: resourceId, | resourceId: resourceId, | ||||
| resoureName: info.name, | resoureName: info.name, | ||||
| owner: info.owner, | |||||
| identifier: info.identifier, | identifier: info.identifier, | ||||
| is_public: info.is_public, | is_public: info.is_public, | ||||
| onOk: () => { | onOk: () => { | ||||
| @@ -89,7 +89,7 @@ function ResourceList( | |||||
| is_public: isPublic, | is_public: isPublic, | ||||
| [config.typeParamKey]: dataType, | [config.typeParamKey]: dataType, | ||||
| [config.tagParamKey]: dataTag, | [config.tagParamKey]: dataTag, | ||||
| name: searchText !== '' ? searchText : undefined, | |||||
| name: searchText || undefined, | |||||
| }; | }; | ||||
| const request = config.getList; | const request = config.getList; | ||||
| const [res] = await to(request(params)); | const [res] = await to(request(params)); | ||||
| @@ -115,6 +115,10 @@ function ResourceList( | |||||
| // 搜索 | // 搜索 | ||||
| const handleSearch = (value: string) => { | const handleSearch = (value: string) => { | ||||
| setSearchText(value); | setSearchText(value); | ||||
| setPagination((prev) => ({ | |||||
| ...prev, | |||||
| current: 1, | |||||
| })); | |||||
| }; | }; | ||||
| // 删除 | // 删除 | ||||
| @@ -14,7 +14,8 @@ import { | |||||
| getModelList, | getModelList, | ||||
| getModelVersionList, | getModelVersionList, | ||||
| } from '@/services/dataset/index.js'; | } from '@/services/dataset/index.js'; | ||||
| import type { TabsProps } from 'antd'; | |||||
| import { limitUploadFileType } from '@/utils/ui'; | |||||
| import type { TabsProps, UploadFile } from 'antd'; | |||||
| export enum ResourceType { | export enum ResourceType { | ||||
| Model = 'Model', // 模型 | Model = 'Model', // 模型 | ||||
| @@ -49,6 +50,7 @@ type ResourceTypeInfo = { | |||||
| addBtnTitle: string; // 新增按钮的title | addBtnTitle: string; // 新增按钮的title | ||||
| uploadAction: string; // 上传接口 url | uploadAction: string; // 上传接口 url | ||||
| uploadAccept?: string; // 上传文件类型 | uploadAccept?: string; // 上传文件类型 | ||||
| beforeUpload?: (file: UploadFile) => boolean | string; | |||||
| downloadAllAction: string; // 批量下载接口 url | downloadAllAction: string; // 批量下载接口 url | ||||
| downloadSingleAction: string; // 单个下载接口 url | downloadSingleAction: string; // 单个下载接口 url | ||||
| }; | }; | ||||
| @@ -87,6 +89,7 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = { | |||||
| addBtnTitle: '新建数据集', | addBtnTitle: '新建数据集', | ||||
| uploadAction: '/api/mmp/newdataset/upload', | uploadAction: '/api/mmp/newdataset/upload', | ||||
| uploadAccept: '.zip,.tgz', | uploadAccept: '.zip,.tgz', | ||||
| beforeUpload: limitUploadFileType('zip,tgz'), | |||||
| downloadAllAction: '/api/mmp/newdataset/downloadAllFiles', | downloadAllAction: '/api/mmp/newdataset/downloadAllFiles', | ||||
| downloadSingleAction: '/api/mmp/newdataset/downloadSingleFile', | downloadSingleAction: '/api/mmp/newdataset/downloadSingleFile', | ||||
| }, | }, | ||||
| @@ -87,7 +87,7 @@ function MirrorList() { | |||||
| const params: Record<string, any> = { | const params: Record<string, any> = { | ||||
| page: pagination.current! - 1, | page: pagination.current! - 1, | ||||
| size: pagination.pageSize, | size: pagination.pageSize, | ||||
| name: searchText, | |||||
| name: searchText || undefined, | |||||
| image_type: activeTab === CommonTabKeys.Public ? 1 : 0, | image_type: activeTab === CommonTabKeys.Public ? 1 : 0, | ||||
| }; | }; | ||||
| const [res] = await to(getMirrorListReq(params)); | const [res] = await to(getMirrorListReq(params)); | ||||
| @@ -120,6 +120,10 @@ function MirrorList() { | |||||
| // 搜索 | // 搜索 | ||||
| const onSearch: SearchProps['onSearch'] = (value) => { | const onSearch: SearchProps['onSearch'] = (value) => { | ||||
| setSearchText(value); | setSearchText(value); | ||||
| setPagination((prev) => ({ | |||||
| ...prev, | |||||
| current: 1, | |||||
| })); | |||||
| }; | }; | ||||
| // 查看详情 | // 查看详情 | ||||
| @@ -69,7 +69,7 @@ function ModelDeployment() { | |||||
| const params: Record<string, any> = { | const params: Record<string, any> = { | ||||
| page: pagination.current! - 1, | page: pagination.current! - 1, | ||||
| size: pagination.pageSize, | size: pagination.pageSize, | ||||
| service_name: searchText, | |||||
| service_name: searchText || undefined, | |||||
| service_type: serviceType, | service_type: serviceType, | ||||
| }; | }; | ||||
| const [res] = await to(getServiceListReq(params)); | const [res] = await to(getServiceListReq(params)); | ||||
| @@ -102,6 +102,10 @@ function ModelDeployment() { | |||||
| // 搜索 | // 搜索 | ||||
| const onSearch: SearchProps['onSearch'] = (value) => { | const onSearch: SearchProps['onSearch'] = (value) => { | ||||
| setSearchText(value); | setSearchText(value); | ||||
| setPagination((prev) => ({ | |||||
| ...prev, | |||||
| current: 1, | |||||
| })); | |||||
| }; | }; | ||||
| // 处理删除 | // 处理删除 | ||||
| @@ -110,7 +110,7 @@ function ServiceInfo() { | |||||
| const params: Record<string, any> = { | const params: Record<string, any> = { | ||||
| page: pagination.current! - 1, | page: pagination.current! - 1, | ||||
| size: pagination.pageSize, | size: pagination.pageSize, | ||||
| version: searchText, | |||||
| version: searchText || undefined, | |||||
| run_state: serviceStatus, | run_state: serviceStatus, | ||||
| service_id: serviceId, | service_id: serviceId, | ||||
| }; | }; | ||||
| @@ -159,6 +159,10 @@ function ServiceInfo() { | |||||
| // 搜索 | // 搜索 | ||||
| const onSearch: SearchProps['onSearch'] = (value) => { | const onSearch: SearchProps['onSearch'] = (value) => { | ||||
| setSearchText(value); | setSearchText(value); | ||||
| setPagination((prev) => ({ | |||||
| ...prev, | |||||
| current: 1, | |||||
| })); | |||||
| }; | }; | ||||
| // 处理删除 | // 处理删除 | ||||
| @@ -40,7 +40,7 @@ function CodeSelectorModal({ onOk, ...rest }: CodeSelectorModalProps) { | |||||
| const params = { | const params = { | ||||
| page: pagination.current! - 1, | page: pagination.current! - 1, | ||||
| size: pagination.pageSize, | size: pagination.pageSize, | ||||
| code_repo_name: searchText !== '' ? searchText : undefined, | |||||
| code_repo_name: searchText || undefined, | |||||
| }; | }; | ||||
| const [res] = await to(getCodeConfigListReq(params)); | const [res] = await to(getCodeConfigListReq(params)); | ||||
| if (res && res.data && res.data.content) { | if (res && res.data && res.data.content) { | ||||
| @@ -52,6 +52,10 @@ function CodeSelectorModal({ onOk, ...rest }: CodeSelectorModalProps) { | |||||
| // 搜索 | // 搜索 | ||||
| const handleSearch = (value: string) => { | const handleSearch = (value: string) => { | ||||
| setSearchText(value); | setSearchText(value); | ||||
| setPagination((prev) => ({ | |||||
| ...prev, | |||||
| current: 1, | |||||
| })); | |||||
| }; | }; | ||||
| const handleClick = (item: CodeConfigData) => { | const handleClick = (item: CodeConfigData) => { | ||||
| @@ -44,14 +44,14 @@ const convertMirrorToTreeData = (list: MirrorData[]): TreeDataNode[] => { | |||||
| })); | })); | ||||
| }; | }; | ||||
| // 数据集版本列表转为树形结构 | |||||
| const convertDatasetVersionToTreeData = ( | |||||
| // 数据集、模型版本列表转为树形结构 | |||||
| const convertResourceVersionToTreeData = ( | |||||
| parentId: string, | parentId: string, | ||||
| info: ResourceData, | info: ResourceData, | ||||
| list: ResourceVersionData[], | list: ResourceVersionData[], | ||||
| ): TreeDataNode[] => { | ): TreeDataNode[] => { | ||||
| return list.map((item: ResourceVersionData) => ({ | return list.map((item: ResourceVersionData) => ({ | ||||
| ...pick(info, ['id', 'name', 'owner', 'identifier']), | |||||
| ...pick(info, ['id', 'name', 'owner', 'identifier', 'is_public']), | |||||
| version: item.name, | version: item.name, | ||||
| title: item.name, | title: item.name, | ||||
| key: `${parentId}-${item.name}`, | key: `${parentId}-${item.name}`, | ||||
| @@ -85,6 +85,7 @@ interface SelectorTypeInfo { | |||||
| readonly buttontTitle: string; // 按钮 title | readonly buttontTitle: string; // 按钮 title | ||||
| } | } | ||||
| // 数据集选择 | |||||
| export class DatasetSelector implements SelectorTypeInfo { | export class DatasetSelector implements SelectorTypeInfo { | ||||
| readonly name = '数据集'; | readonly name = '数据集'; | ||||
| readonly modalIcon = datasetImg; | readonly modalIcon = datasetImg; | ||||
| @@ -114,14 +115,14 @@ export class DatasetSelector implements SelectorTypeInfo { | |||||
| const res = await getDatasetVersionList(pick(parentNode, ['owner', 'identifier'])); | const res = await getDatasetVersionList(pick(parentNode, ['owner', 'identifier'])); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const list = res.data; | const list = res.data; | ||||
| return convertDatasetVersionToTreeData(parentKey, parentNode, list); | |||||
| return convertResourceVersionToTreeData(parentKey, parentNode, list); | |||||
| } else { | } else { | ||||
| return Promise.reject('获取数据集版本列表失败'); | return Promise.reject('获取数据集版本列表失败'); | ||||
| } | } | ||||
| } | } | ||||
| async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) { | async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) { | ||||
| const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version']); | |||||
| const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version', 'is_public']); | |||||
| const res = await getDatasetInfo(params); | const res = await getDatasetInfo(params); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const path = res.data.relative_paths || ''; | const path = res.data.relative_paths || ''; | ||||
| @@ -136,6 +137,7 @@ export class DatasetSelector implements SelectorTypeInfo { | |||||
| } | } | ||||
| } | } | ||||
| // 模型选择 | |||||
| export class ModelSelector implements SelectorTypeInfo { | export class ModelSelector implements SelectorTypeInfo { | ||||
| readonly name = '模型'; | readonly name = '模型'; | ||||
| readonly modalIcon = modelImg; | readonly modalIcon = modelImg; | ||||
| @@ -165,14 +167,14 @@ export class ModelSelector implements SelectorTypeInfo { | |||||
| const res = await getModelVersionList(pick(parentNode, ['owner', 'identifier'])); | const res = await getModelVersionList(pick(parentNode, ['owner', 'identifier'])); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const list = res.data; | const list = res.data; | ||||
| return convertDatasetVersionToTreeData(key, parentNode, list); | |||||
| return convertResourceVersionToTreeData(key, parentNode, list); | |||||
| } else { | } else { | ||||
| return Promise.reject('获取模型版本列表失败'); | return Promise.reject('获取模型版本列表失败'); | ||||
| } | } | ||||
| } | } | ||||
| async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) { | async getFiles(_parentKey: string, parentNode: ResourceData & ResourceVersionData) { | ||||
| const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version']); | |||||
| const params = pick(parentNode, ['owner', 'identifier', 'id', 'name', 'version', 'is_public']); | |||||
| const res = await getModelInfo(params); | const res = await getModelInfo(params); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const path = res.data.relative_paths || ''; | const path = res.data.relative_paths || ''; | ||||
| @@ -187,6 +189,7 @@ export class ModelSelector implements SelectorTypeInfo { | |||||
| } | } | ||||
| } | } | ||||
| // 镜像选择 | |||||
| export class MirrorSelector implements SelectorTypeInfo { | export class MirrorSelector implements SelectorTypeInfo { | ||||
| readonly name = '镜像'; | readonly name = '镜像'; | ||||
| readonly modalIcon = mirrorImg; | readonly modalIcon = mirrorImg; | ||||
| @@ -221,7 +221,7 @@ const UserForm: React.FC<UserFormProps> = (props) => { | |||||
| allowClear | allowClear | ||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: false, | |||||
| required: true, | |||||
| message: <FormattedMessage id="请输入密码!" defaultMessage="请输入密码!" />, | message: <FormattedMessage id="请输入密码!" defaultMessage="请输入密码!" />, | ||||
| }, | }, | ||||
| ]} | ]} | ||||
| @@ -8,7 +8,7 @@ import { removeAllPageCacheState } from '@/hooks/pageCacheState'; | |||||
| import themes from '@/styles/theme.less'; | import themes from '@/styles/theme.less'; | ||||
| import { type ClientInfo } from '@/types'; | import { type ClientInfo } from '@/types'; | ||||
| import { history } from '@umijs/max'; | import { history } from '@umijs/max'; | ||||
| import { Modal, message, type ModalFuncProps, type UploadFile } from 'antd'; | |||||
| import { Modal, Upload, message, type ModalFuncProps, type UploadFile } from 'antd'; | |||||
| import { closeAllModals } from './modal'; | import { closeAllModals } from './modal'; | ||||
| import SessionStorage from './sessionStorage'; | import SessionStorage from './sessionStorage'; | ||||
| @@ -52,23 +52,6 @@ export function modalConfirm({ | |||||
| }); | }); | ||||
| } | } | ||||
| // 从事件中获取上传文件列表,用于 Upload + Form 中 | |||||
| export const getFileListFromEvent = (e: any) => { | |||||
| const fileList: UploadFile[] = (Array.isArray(e) ? e : e?.fileList) || []; | |||||
| return fileList.map((item) => { | |||||
| if (item.status === 'done') { | |||||
| const { response } = item; | |||||
| if (response?.code !== 200) { | |||||
| return { | |||||
| ...item, | |||||
| status: 'error', | |||||
| }; | |||||
| } | |||||
| } | |||||
| return item; | |||||
| }); | |||||
| }; | |||||
| /** | /** | ||||
| * 跳转到登录页 | * 跳转到登录页 | ||||
| * @param toHome 是否跳转到首页 | * @param toHome 是否跳转到首页 | ||||
| @@ -97,6 +80,23 @@ export const gotoOAuth2 = () => { | |||||
| } | } | ||||
| }; | }; | ||||
| // 从事件中获取上传文件列表,用于 Upload + Form 中 | |||||
| export const getFileListFromEvent = (e: any) => { | |||||
| const fileList: UploadFile[] = (Array.isArray(e) ? e : e?.fileList) || []; | |||||
| return fileList.map((item) => { | |||||
| if (item.status === 'done') { | |||||
| const { response } = item; | |||||
| if (response?.code !== 200) { | |||||
| return { | |||||
| ...item, | |||||
| status: 'error', | |||||
| }; | |||||
| } | |||||
| } | |||||
| return item; | |||||
| }); | |||||
| }; | |||||
| /** | /** | ||||
| * 验证文件上传 | * 验证文件上传 | ||||
| * | * | ||||
| @@ -128,6 +128,20 @@ export const validateUploadFiles = (files: UploadFile[], required: boolean = tru | |||||
| return !hasError; | return !hasError; | ||||
| }; | }; | ||||
| // 限制上传文件类型 | |||||
| export const limitUploadFileType = (type: string) => { | |||||
| return (file: UploadFile): boolean | string => { | |||||
| const acceptTypes = type.split(',').map((item) => item.trim()); | |||||
| const fileType = file.name.split('.').pop()?.trim(); | |||||
| if (!(fileType && acceptTypes.includes(fileType))) { | |||||
| message.error(`文件类型不正确,只支持 "${acceptTypes.join('、')}" 类型的文件`); | |||||
| file.status = 'error'; | |||||
| return Upload.LIST_IGNORE; | |||||
| } | |||||
| return true; | |||||
| }; | |||||
| }; | |||||
| /** | /** | ||||
| * 滚动到底部 | * 滚动到底部 | ||||
| * | * | ||||