diff --git a/react-ui/src/components/BasicTableInfo/index.tsx b/react-ui/src/components/BasicTableInfo/index.tsx
index 104bc2bb..571c4b5b 100644
--- a/react-ui/src/components/BasicTableInfo/index.tsx
+++ b/react-ui/src/components/BasicTableInfo/index.tsx
@@ -32,9 +32,9 @@ export default function BasicTableInfo({
return (
- {showDatas.map((item) => (
+ {showDatas.map((item, index) => (
= {
page: pagination.current! - 1,
size: pagination.pageSize,
- ml_name: searchText,
+ ml_name: searchText || undefined,
};
const [res] = await to(getAutoMLListReq(params));
if (res && res.data) {
@@ -76,6 +76,10 @@ function AutoMLList() {
// 搜索
const onSearch: SearchProps['onSearch'] = (value) => {
setSearchText(value);
+ setPagination((prev) => ({
+ ...prev,
+ current: 1,
+ }));
};
// 删除模型部署
diff --git a/react-ui/src/pages/CodeConfig/List/index.tsx b/react-ui/src/pages/CodeConfig/List/index.tsx
index e8a2557f..2efef04c 100644
--- a/react-ui/src/pages/CodeConfig/List/index.tsx
+++ b/react-ui/src/pages/CodeConfig/List/index.tsx
@@ -59,7 +59,7 @@ function CodeConfigList() {
const params = {
page: pagination.current! - 1,
size: pagination.pageSize,
- code_repo_name: searchText !== '' ? searchText : undefined,
+ code_repo_name: searchText || undefined,
};
const [res] = await to(getCodeConfigListReq(params));
if (res && res.data && res.data.content) {
@@ -83,6 +83,10 @@ function CodeConfigList() {
// 搜索
const handleSearch = (value: string) => {
setSearchText(value);
+ setPagination((prev) => ({
+ ...prev,
+ current: 1,
+ }));
};
// 删除
diff --git a/react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx b/react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx
index 87d215bd..e592f740 100644
--- a/react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx
+++ b/react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx
@@ -4,7 +4,7 @@ import KFModal from '@/components/KFModal';
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';
+import { getFileListFromEvent, limitUploadFileType, validateUploadFiles } from '@/utils/ui';
import {
Button,
Form,
@@ -42,6 +42,8 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr
Authorization: getAccessToken() || '',
},
defaultFileList: [],
+ accept: '.zip,.tgz',
+ beforeUpload: limitUploadFileType('zip,tgz'),
};
// 获取集群版本数据
@@ -200,7 +202,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr
},
]}
>
-
+
);
}
diff --git a/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx b/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx
index 106df228..1037e1b9 100644
--- a/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx
+++ b/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx
@@ -119,6 +119,7 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
resourceType: resourceType,
resourceId: resourceId,
resoureName: info.name,
+ owner: info.owner,
identifier: info.identifier,
is_public: info.is_public,
onOk: () => {
diff --git a/react-ui/src/pages/Dataset/components/ResourceList/index.tsx b/react-ui/src/pages/Dataset/components/ResourceList/index.tsx
index 9e872aca..6f2c7523 100644
--- a/react-ui/src/pages/Dataset/components/ResourceList/index.tsx
+++ b/react-ui/src/pages/Dataset/components/ResourceList/index.tsx
@@ -89,7 +89,7 @@ function ResourceList(
is_public: isPublic,
[config.typeParamKey]: dataType,
[config.tagParamKey]: dataTag,
- name: searchText !== '' ? searchText : undefined,
+ name: searchText || undefined,
};
const request = config.getList;
const [res] = await to(request(params));
@@ -115,6 +115,10 @@ function ResourceList(
// 搜索
const handleSearch = (value: string) => {
setSearchText(value);
+ setPagination((prev) => ({
+ ...prev,
+ current: 1,
+ }));
};
// 删除
diff --git a/react-ui/src/pages/Dataset/config.tsx b/react-ui/src/pages/Dataset/config.tsx
index 2ae165bc..c5b53afb 100644
--- a/react-ui/src/pages/Dataset/config.tsx
+++ b/react-ui/src/pages/Dataset/config.tsx
@@ -14,7 +14,8 @@ import {
getModelList,
getModelVersionList,
} from '@/services/dataset/index.js';
-import type { TabsProps } from 'antd';
+import { limitUploadFileType } from '@/utils/ui';
+import type { TabsProps, UploadFile } from 'antd';
export enum ResourceType {
Model = 'Model', // 模型
@@ -49,6 +50,7 @@ type ResourceTypeInfo = {
addBtnTitle: string; // 新增按钮的title
uploadAction: string; // 上传接口 url
uploadAccept?: string; // 上传文件类型
+ beforeUpload?: (file: UploadFile) => boolean | string;
downloadAllAction: string; // 批量下载接口 url
downloadSingleAction: string; // 单个下载接口 url
};
@@ -87,6 +89,7 @@ export const resourceConfig: Record = {
addBtnTitle: '新建数据集',
uploadAction: '/api/mmp/newdataset/upload',
uploadAccept: '.zip,.tgz',
+ beforeUpload: limitUploadFileType('zip,tgz'),
downloadAllAction: '/api/mmp/newdataset/downloadAllFiles',
downloadSingleAction: '/api/mmp/newdataset/downloadSingleFile',
},
diff --git a/react-ui/src/pages/Mirror/List/index.tsx b/react-ui/src/pages/Mirror/List/index.tsx
index 76f289b7..629563d4 100644
--- a/react-ui/src/pages/Mirror/List/index.tsx
+++ b/react-ui/src/pages/Mirror/List/index.tsx
@@ -87,7 +87,7 @@ function MirrorList() {
const params: Record = {
page: pagination.current! - 1,
size: pagination.pageSize,
- name: searchText,
+ name: searchText || undefined,
image_type: activeTab === CommonTabKeys.Public ? 1 : 0,
};
const [res] = await to(getMirrorListReq(params));
@@ -120,6 +120,10 @@ function MirrorList() {
// 搜索
const onSearch: SearchProps['onSearch'] = (value) => {
setSearchText(value);
+ setPagination((prev) => ({
+ ...prev,
+ current: 1,
+ }));
};
// 查看详情
diff --git a/react-ui/src/pages/ModelDeployment/List/index.tsx b/react-ui/src/pages/ModelDeployment/List/index.tsx
index 6e61c3ab..0632e547 100644
--- a/react-ui/src/pages/ModelDeployment/List/index.tsx
+++ b/react-ui/src/pages/ModelDeployment/List/index.tsx
@@ -69,7 +69,7 @@ function ModelDeployment() {
const params: Record = {
page: pagination.current! - 1,
size: pagination.pageSize,
- service_name: searchText,
+ service_name: searchText || undefined,
service_type: serviceType,
};
const [res] = await to(getServiceListReq(params));
@@ -102,6 +102,10 @@ function ModelDeployment() {
// 搜索
const onSearch: SearchProps['onSearch'] = (value) => {
setSearchText(value);
+ setPagination((prev) => ({
+ ...prev,
+ current: 1,
+ }));
};
// 处理删除
diff --git a/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx b/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx
index f57c86cb..037bbb72 100644
--- a/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx
+++ b/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx
@@ -110,7 +110,7 @@ function ServiceInfo() {
const params: Record = {
page: pagination.current! - 1,
size: pagination.pageSize,
- version: searchText,
+ version: searchText || undefined,
run_state: serviceStatus,
service_id: serviceId,
};
@@ -159,6 +159,10 @@ function ServiceInfo() {
// 搜索
const onSearch: SearchProps['onSearch'] = (value) => {
setSearchText(value);
+ setPagination((prev) => ({
+ ...prev,
+ current: 1,
+ }));
};
// 处理删除
diff --git a/react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx b/react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx
index 24a54293..13198a78 100644
--- a/react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx
+++ b/react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx
@@ -40,7 +40,7 @@ function CodeSelectorModal({ onOk, ...rest }: CodeSelectorModalProps) {
const params = {
page: pagination.current! - 1,
size: pagination.pageSize,
- code_repo_name: searchText !== '' ? searchText : undefined,
+ code_repo_name: searchText || undefined,
};
const [res] = await to(getCodeConfigListReq(params));
if (res && res.data && res.data.content) {
@@ -52,6 +52,10 @@ function CodeSelectorModal({ onOk, ...rest }: CodeSelectorModalProps) {
// 搜索
const handleSearch = (value: string) => {
setSearchText(value);
+ setPagination((prev) => ({
+ ...prev,
+ current: 1,
+ }));
};
const handleClick = (item: CodeConfigData) => {
diff --git a/react-ui/src/pages/Pipeline/components/ResourceSelectorModal/config.tsx b/react-ui/src/pages/Pipeline/components/ResourceSelectorModal/config.tsx
index c4e8af4a..80e3ab3c 100644
--- a/react-ui/src/pages/Pipeline/components/ResourceSelectorModal/config.tsx
+++ b/react-ui/src/pages/Pipeline/components/ResourceSelectorModal/config.tsx
@@ -44,14 +44,14 @@ const convertMirrorToTreeData = (list: MirrorData[]): TreeDataNode[] => {
}));
};
-// 数据集版本列表转为树形结构
-const convertDatasetVersionToTreeData = (
+// 数据集、模型版本列表转为树形结构
+const convertResourceVersionToTreeData = (
parentId: string,
info: ResourceData,
list: ResourceVersionData[],
): TreeDataNode[] => {
return list.map((item: ResourceVersionData) => ({
- ...pick(info, ['id', 'name', 'owner', 'identifier']),
+ ...pick(info, ['id', 'name', 'owner', 'identifier', 'is_public']),
version: item.name,
title: item.name,
key: `${parentId}-${item.name}`,
@@ -85,6 +85,7 @@ interface SelectorTypeInfo {
readonly buttontTitle: string; // 按钮 title
}
+// 数据集选择
export class DatasetSelector implements SelectorTypeInfo {
readonly name = '数据集';
readonly modalIcon = datasetImg;
@@ -114,14 +115,14 @@ export class DatasetSelector implements SelectorTypeInfo {
const res = await getDatasetVersionList(pick(parentNode, ['owner', 'identifier']));
if (res && res.data) {
const list = res.data;
- return convertDatasetVersionToTreeData(parentKey, parentNode, list);
+ return convertResourceVersionToTreeData(parentKey, parentNode, list);
} else {
return Promise.reject('获取数据集版本列表失败');
}
}
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);
if (res && res.data) {
const path = res.data.relative_paths || '';
@@ -136,6 +137,7 @@ export class DatasetSelector implements SelectorTypeInfo {
}
}
+// 模型选择
export class ModelSelector implements SelectorTypeInfo {
readonly name = '模型';
readonly modalIcon = modelImg;
@@ -165,14 +167,14 @@ export class ModelSelector implements SelectorTypeInfo {
const res = await getModelVersionList(pick(parentNode, ['owner', 'identifier']));
if (res && res.data) {
const list = res.data;
- return convertDatasetVersionToTreeData(key, parentNode, list);
+ return convertResourceVersionToTreeData(key, parentNode, list);
} else {
return Promise.reject('获取模型版本列表失败');
}
}
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);
if (res && res.data) {
const path = res.data.relative_paths || '';
@@ -187,6 +189,7 @@ export class ModelSelector implements SelectorTypeInfo {
}
}
+// 镜像选择
export class MirrorSelector implements SelectorTypeInfo {
readonly name = '镜像';
readonly modalIcon = mirrorImg;
diff --git a/react-ui/src/pages/System/User/edit.tsx b/react-ui/src/pages/System/User/edit.tsx
index 8d24b539..71252d51 100644
--- a/react-ui/src/pages/System/User/edit.tsx
+++ b/react-ui/src/pages/System/User/edit.tsx
@@ -221,7 +221,7 @@ const UserForm: React.FC = (props) => {
allowClear
rules={[
{
- required: false,
+ required: true,
message: ,
},
]}
diff --git a/react-ui/src/utils/ui.tsx b/react-ui/src/utils/ui.tsx
index c3d2c44a..a3a214ec 100644
--- a/react-ui/src/utils/ui.tsx
+++ b/react-ui/src/utils/ui.tsx
@@ -8,7 +8,7 @@ import { removeAllPageCacheState } from '@/hooks/pageCacheState';
import themes from '@/styles/theme.less';
import { type ClientInfo } from '@/types';
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 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 是否跳转到首页
@@ -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;
};
+// 限制上传文件类型
+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;
+ };
+};
+
/**
* 滚动到底部
*