From 40c6b5ea00db1ca8ca79846068c841d90c493fc9 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Tue, 23 Apr 2024 09:37:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E9=95=9C=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/config/config.ts | 5 +- react-ui/src/app.tsx | 12 +- .../src/components/CommonTableCell/index.tsx | 5 + .../src/components/DateTableCell/index.tsx | 13 ++ react-ui/src/components/KFRadio/index.less | 5 + react-ui/src/components/PageTitle/index.less | 2 +- react-ui/src/global.less | 9 +- .../components/MirrorStatusCell/index.tsx | 9 +- react-ui/src/pages/Mirror/create.less | 2 +- react-ui/src/pages/Mirror/create.tsx | 139 ++++++++++++++---- react-ui/src/pages/Mirror/info.less | 2 +- react-ui/src/pages/Mirror/info.tsx | 104 ++++++++++--- react-ui/src/pages/Mirror/list.less | 9 +- react-ui/src/pages/Mirror/list.tsx | 108 +++++++++++--- .../src/pages/Pipeline/editPipeline/props.jsx | 2 +- react-ui/src/services/mirror/index.ts | 22 ++- react-ui/src/utils/index.ts | 34 ----- react-ui/src/utils/sessionKeys.ts | 2 + react-ui/src/utils/ui.tsx | 19 ++- 19 files changed, 356 insertions(+), 147 deletions(-) create mode 100644 react-ui/src/components/CommonTableCell/index.tsx create mode 100644 react-ui/src/components/DateTableCell/index.tsx create mode 100644 react-ui/src/utils/sessionKeys.ts diff --git a/react-ui/config/config.ts b/react-ui/config/config.ts index d0830923..961f0025 100644 --- a/react-ui/config/config.ts +++ b/react-ui/config/config.ts @@ -1,14 +1,12 @@ // https://umijs.org/config/ import { defineConfig } from '@umijs/max'; -import { join, resolve } from 'path'; +import { join } from 'path'; import defaultSettings from './defaultSettings'; import proxy from './proxy'; import routes from './routes'; const { REACT_APP_ENV = 'dev' } = process.env; -console.log('zzz', resolve(__dirname, '../src/styles/theme.less')); - export default defineConfig({ /** * @name 开启 hash 模式 @@ -42,7 +40,6 @@ export default defineConfig({ // 如果不想要 configProvide 动态设置主题需要把这个设置为 default // 只有设置为 variable, 才能使用 configProvide 动态设置主色调 // 'root-entry-name': 'variable', - 'kf-success-color': '#ff0000', }, /** * @name moment 的国际化配置 diff --git a/react-ui/src/app.tsx b/react-ui/src/app.tsx index cd88f984..1d11a6e6 100644 --- a/react-ui/src/app.tsx +++ b/react-ui/src/app.tsx @@ -193,7 +193,6 @@ export const antd: RuntimeAntdConfig = (memo) => { colorSuccess: themes['successColor'], colorError: themes['errorColor'], colorWarning: themes['warningColor'], - // fontSize: themes['fontSize'], }; memo.theme.components ??= {}; memo.theme.components.Tabs = {}; @@ -207,20 +206,19 @@ export const antd: RuntimeAntdConfig = (memo) => { defaultActiveBg: 'rgba(22, 100, 255, 0.12)', defaultActiveBorderColor: 'rgba(22, 100, 255, 0.75)', defaultActiveColor: themes['primaryColor'], - contentFontSize: themes['fontSize'], - paddingBlock: 4, - paddingInline: 15, + contentFontSize: parseInt(themes['fontSize']), controlHeight: 34, }; memo.theme.components.Input = { - inputFontSize: themes['fontSize'], - paddingBlock: 4, - paddingInline: 15, + inputFontSize: parseInt(themes['fontSize']), }; memo.theme.components.Table = { headerBg: 'rgba(242, 244, 247, 0.36)', headerBorderRadius: 4, }; + memo.theme.components.Tabs = { + titleFontSize: 16, + }; memo.theme.cssVar = true; // memo.theme.hashed = false; diff --git a/react-ui/src/components/CommonTableCell/index.tsx b/react-ui/src/components/CommonTableCell/index.tsx new file mode 100644 index 00000000..6493899e --- /dev/null +++ b/react-ui/src/components/CommonTableCell/index.tsx @@ -0,0 +1,5 @@ +function CommonTableCell(text?: string | null) { + return {text ?? '--'}; +} + +export default CommonTableCell; diff --git a/react-ui/src/components/DateTableCell/index.tsx b/react-ui/src/components/DateTableCell/index.tsx new file mode 100644 index 00000000..1b7d785c --- /dev/null +++ b/react-ui/src/components/DateTableCell/index.tsx @@ -0,0 +1,13 @@ +import dayjs from 'dayjs'; + +function DateTableCell(text?: string | null) { + if (text === undefined || text === null || text === '') { + return --; + } + if (!dayjs(text).isValid()) { + return 日期无效; + } + return {dayjs(text).format('YYYY-MM-DD HH:mm:ss')}; +} + +export default DateTableCell; diff --git a/react-ui/src/components/KFRadio/index.less b/react-ui/src/components/KFRadio/index.less index 7a941188..0155142d 100644 --- a/react-ui/src/components/KFRadio/index.less +++ b/react-ui/src/components/KFRadio/index.less @@ -17,6 +17,11 @@ border: 1px solid @primary-color-hover; } + &:active { + color: @primary-color; + border: 1px solid @primary-color; + } + &--active { color: @primary-color; border: 1px solid @primary-color; diff --git a/react-ui/src/components/PageTitle/index.less b/react-ui/src/components/PageTitle/index.less index 071bb711..80d18169 100644 --- a/react-ui/src/components/PageTitle/index.less +++ b/react-ui/src/components/PageTitle/index.less @@ -1,7 +1,7 @@ .kf-page-title { display: flex; align-items: center; - height: 49px; + height: 50px; padding-left: 30px; background-image: url('../../assets/img/page-title-bg.png'); } diff --git a/react-ui/src/global.less b/react-ui/src/global.less index 43894072..cdc68cf3 100644 --- a/react-ui/src/global.less +++ b/react-ui/src/global.less @@ -4,6 +4,7 @@ body, height: 100%; margin: 0; padding: 0; + overflow-y: hidden; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; @@ -181,13 +182,13 @@ body { margin-left: 20px; } .ant-pagination .ant-pagination-item-active a { - color: #fff; + // color: #fff; border-radius: 6px; } .ant-pagination .ant-pagination-item-active:hover { - color: #fff; - background: rgba(22, 100, 255, 0.8); - border-color: rgba(22, 100, 255, 0.8); + // color: #fff; + // background: rgba(22, 100, 255, 0.8); + // border-color: rgba(22, 100, 255, 0.8); border-radius: 6px; } .ant-pagination .ant-pagination-item { diff --git a/react-ui/src/pages/Mirror/components/MirrorStatusCell/index.tsx b/react-ui/src/pages/Mirror/components/MirrorStatusCell/index.tsx index bf0522ed..3702825f 100644 --- a/react-ui/src/pages/Mirror/components/MirrorStatusCell/index.tsx +++ b/react-ui/src/pages/Mirror/components/MirrorStatusCell/index.tsx @@ -6,10 +6,6 @@ import { MirrorVersionStatus } from '@/enums'; import styles from './index.less'; -type MirrorStatusCellProps = { - status: MirrorVersionStatus; -}; - type MirrorVersionStatusKeys = keyof typeof MirrorVersionStatus; type MirrorVersionStatusValues = (typeof MirrorVersionStatus)[MirrorVersionStatusKeys]; @@ -33,7 +29,10 @@ const statusInfo: Record = { }, }; -function MirrorStatusCell({ status }: MirrorStatusCellProps) { +function MirrorStatusCell(status: MirrorVersionStatus) { + if (status === null || status === undefined || !statusInfo[status]) { + return --; + } return {statusInfo[status].text}; } diff --git a/react-ui/src/pages/Mirror/create.less b/react-ui/src/pages/Mirror/create.less index baf2e6c0..0c3943eb 100644 --- a/react-ui/src/pages/Mirror/create.less +++ b/react-ui/src/pages/Mirror/create.less @@ -4,7 +4,7 @@ height: 100%; &__content { - height: calc(100% - 59px); + height: calc(100% - 60px); margin-top: 10px; padding: 30px 30px 10px; overflow: auto; diff --git a/react-ui/src/pages/Mirror/create.tsx b/react-ui/src/pages/Mirror/create.tsx index 4a87edbb..9f23c838 100644 --- a/react-ui/src/pages/Mirror/create.tsx +++ b/react-ui/src/pages/Mirror/create.tsx @@ -3,15 +3,20 @@ * @Date: 2024-04-16 13:58:08 * @Description: 创建镜像 */ +import { getAccessToken } from '@/access'; import KFIcon from '@/components/KFIcon'; import KFRadio, { type KFRadioItem } from '@/components/KFRadio'; import PageTitle from '@/components/PageTitle'; import SubAreaTitle from '@/components/SubAreaTitle'; import { CommonTabKeys } from '@/enums'; -import { createPrivateMirrorReq, createPublicMirrorReq } from '@/services/mirror'; +import { createMirrorReq } from '@/services/mirror'; import { to } from '@/utils/promise'; -import { useNavigate, useSearchParams } from '@umijs/max'; -import { Button, Col, Form, Input, Row, message } from 'antd'; +import { mirrorNameKey } from '@/utils/sessionKeys'; +import { getFileListFromEvent } from '@/utils/ui'; +import { useNavigate } from '@umijs/max'; +import { Button, Col, Form, Input, Row, Upload, UploadFile, message, type UploadProps } from 'antd'; +import { omit } from 'lodash'; +import { useEffect, useState } from 'react'; import styles from './create.less'; type FormData = { @@ -19,7 +24,8 @@ type FormData = { tag: string; description: string; path?: string; - type: string; + upload_type: string; + fileList?: UploadFile[]; }; const mirrorRadioItems: KFRadioItem[] = [ @@ -37,15 +43,64 @@ const mirrorRadioItems: KFRadioItem[] = [ function MirrorCreate() { const navgite = useNavigate(); - const [seachParams] = useSearchParams(); const [form] = Form.useForm(); - const isPublic = seachParams.get('isPublic') === 'true'; + const [nameDisabled, setNameDisabled] = useState(false); + + const uploadProps: UploadProps = { + action: '/api/mmp/image/upload', + headers: { + Authorization: getAccessToken() || '', + }, + maxCount: 1, + defaultFileList: [], + }; + + useEffect(() => { + const name = sessionStorage.getItem(mirrorNameKey); + if (name) { + form.setFieldValue('name', name); + setNameDisabled(true); + } + return () => { + sessionStorage.removeItem(mirrorNameKey); + }; + }, []); // 创建公网、本地镜像 - const createPublicMirror = async (params: FormData) => { - // createPrivateMirrorReq - const req = isPublic ? createPublicMirrorReq : createPrivateMirrorReq; - const [res] = await to(req(params)); + const createPublicMirror = async (formData: FormData) => { + const upload_type = formData['upload_type']; + let params; + if (upload_type === CommonTabKeys.Public) { + params = { + ...omit(formData, ['upload_type']), + upload_type: 0, + image_type: 0, + }; + } else { + const fileList = formData['fileList'] ?? []; + if (fileList.length === 0) { + message.error('请上传文件'); + return; + } + const file = fileList[0]; + if (file.status === 'uploading') { + message.error('请等待文件上传完成'); + return; + } else if (file.status === 'error') { + message.error('文件上传失败,请重新上传文件'); + return; + } + + params = { + ...omit(formData, ['fileList', 'upload_type']), + path: file.response.data.url, + file_size: file.response.data.fileSize, + upload_type: 1, + image_type: 0, + }; + } + + const [res] = await to(createMirrorReq(params)); if (res) { message.success('创建成功'); navgite(-1); @@ -54,13 +109,26 @@ function MirrorCreate() { // 提交 const handleSubmit = (values: FormData) => { - console.log(values); createPublicMirror(values); }; + // 取消 + const cancel = () => { + navgite(-1); + }; + + const beforeUpload: UploadProps['beforeUpload'] = () => { + const fileList = form.getFieldValue('fileList'); + if (fileList.length >= 1) { + message.error('只允许上传一个文件'); + return Upload.LIST_IGNORE; + } + return true; + }; + return (
- +
- + prevValues.type !== curValues.type} + shouldUpdate={(prevValues, curValues) => + prevValues.upload_type !== curValues.upload_type + } > {({ getFieldValue }) => { - const type = getFieldValue('type'); + const type = getFieldValue('upload_type'); if (type === CommonTabKeys.Public) { return ( <> @@ -199,7 +275,9 @@ function MirrorCreate() { - {/* - - */} + @@ -233,7 +303,12 @@ function MirrorCreate() { - diff --git a/react-ui/src/pages/Mirror/info.less b/react-ui/src/pages/Mirror/info.less index 61d034d8..eb6ecbaa 100644 --- a/react-ui/src/pages/Mirror/info.less +++ b/react-ui/src/pages/Mirror/info.less @@ -23,7 +23,7 @@ } &__content { - height: calc(100% - 59px); + height: calc(100% - 60px); margin-top: 10px; padding: 30px 30px 0; background-color: white; diff --git a/react-ui/src/pages/Mirror/info.tsx b/react-ui/src/pages/Mirror/info.tsx index 8785f586..ee461c2b 100644 --- a/react-ui/src/pages/Mirror/info.tsx +++ b/react-ui/src/pages/Mirror/info.tsx @@ -3,16 +3,33 @@ * @Date: 2024-04-16 13:58:08 * @Description: 镜像详情 */ +import CommonTableCell from '@/components/CommonTableCell'; +import DateTableCell from '@/components/DateTableCell'; import KFIcon from '@/components/KFIcon'; import PageTitle from '@/components/PageTitle'; import SubAreaTitle from '@/components/SubAreaTitle'; -import { MirrorVersionStatus } from '@/enums'; import { useDomSize } from '@/hooks'; -import { getMirrorInfoReq, getMirrorVersionListReq } from '@/services/mirror'; +import { + deleteMirrorVersionReq, + getMirrorInfoReq, + getMirrorVersionListReq, +} from '@/services/mirror'; import themes from '@/styles/theme.less'; import { to } from '@/utils/promise'; -import { useParams, useSearchParams } from '@umijs/max'; -import { Button, Col, ConfigProvider, Row, Table, TablePaginationConfig, TableProps } from 'antd'; +import { mirrorNameKey } from '@/utils/sessionKeys'; +import { modalConfirm } from '@/utils/ui'; +import { useNavigate, useParams, useSearchParams } from '@umijs/max'; +import { + Button, + Col, + ConfigProvider, + Flex, + Row, + Table, + message, + type TablePaginationConfig, + type TableProps, +} from 'antd'; import classNames from 'classnames'; import dayjs from 'dayjs'; import { useEffect, useState } from 'react'; @@ -27,6 +44,7 @@ type MirrorInfoData = { }; type MirrorVersionData = { + id: number; version: string; url: string; status: string; @@ -35,8 +53,9 @@ type MirrorVersionData = { }; function MirrorInfo() { + const navigate = useNavigate(); const urlParams = useParams(); - const [seachParams] = useSearchParams(); + const [searchParams] = useSearchParams(); const [mirrorInfo, setMirrorInfo] = useState({}); const [tableData, setTableData] = useState([]); const [topRef, { height: topHeight }] = useDomSize(0, 0, [mirrorInfo]); @@ -47,7 +66,7 @@ function MirrorInfo() { current: 1, pageSize: 10, }); - const isPublic = seachParams.get('isPublic') === 'true'; + const isPublic = searchParams.get('isPublic') === 'true'; useEffect(() => { getMirrorInfo(); }, []); @@ -61,7 +80,8 @@ function MirrorInfo() { const [res] = await to(getMirrorInfoReq(id)); if (res && res.data) { const { name = '', description = '', version_count = '', create_time: time } = res.data; - const create_time = time ? dayjs(time).format('YYYY-MM-DD HH:mm:ss') : ''; + let create_time = + time && dayjs(time).isValid() ? dayjs(time).format('YYYY-MM-DD HH:mm:ss') : '--'; setMirrorInfo({ name, description, @@ -87,6 +107,25 @@ function MirrorInfo() { } }; + // 删除镜像版本 + const deleteMirrorVersion = async (id: number) => { + const [res] = await to(deleteMirrorVersionReq(id)); + if (res) { + message.success('删除成功'); + // 如果是一页的唯一数据,删除时,请求第一页的数据 + // 否则直接刷新这一页的数据 + // 避免回到第一页 + if (tableData.length > 1) { + setPagination((prev) => ({ + ...prev, + current: 1, + })); + } else { + getMirrorVersionList(); + } + } + }; + // 分页切换 const handleTableChange: TableProps['onChange'] = (pagination, filters, sorter, { action }) => { if (action === 'paginate') { @@ -94,8 +133,21 @@ function MirrorInfo() { } }; - const downloadVersion = (record: MirrorVersionData) => {}; - const removeVersion = (record: MirrorVersionData) => {}; + // 处理删除 + const handleVersionDelete = (record: MirrorVersionData) => { + modalConfirm({ + title: '删除后,该镜像版本将不可恢复', + content: '是否确认删除?', + onOk: () => { + deleteMirrorVersion(record.id); + }, + }); + }; + + const createMirrorVersion = () => { + navigate(`/dataset/mirror/create`); + sessionStorage.setItem(mirrorNameKey, mirrorInfo.name || ''); + }; const columns: TableProps['columns'] = [ { @@ -103,31 +155,34 @@ function MirrorInfo() { dataIndex: 'tag_name', key: 'tag_name', width: '25%', + render: CommonTableCell, }, { title: '镜像地址', dataIndex: 'url', key: 'url', + render: CommonTableCell, }, { title: '状态', dataIndex: 'status', key: 'status', width: 150, - render: (text: string) => , + render: MirrorStatusCell, }, { title: '镜像大小', dataIndex: 'file_size', key: 'file_size', width: 150, + render: CommonTableCell, }, { title: '创建时间', dataIndex: 'create_time', key: 'create_time', width: 200, - render: (text: string) => {dayjs(text).format('YYYY-MM-DD HH:mm:ss')}, + render: DateTableCell, }, { title: '操作', @@ -135,7 +190,7 @@ function MirrorInfo() { width: 150, key: 'operation', hidden: isPublic, - render: (_: any, record: any) => ( + render: (_: any, record: MirrorVersionData) => (
{!isPublic && ( } - onClick={() => removeVersion(record)} + onClick={() => handleVersionDelete(record)} > 删除 @@ -182,7 +237,7 @@ function MirrorInfo() {
版本数:
-
{mirrorInfo.version_count || '--'}
+
{mirrorInfo.version_count ?? '--'}
@@ -201,12 +256,21 @@ function MirrorInfo() {
- - + + + {!isPublic && ( + + )} +
( + isPrivate ? CommonTabKeys.Private : CommonTabKeys.Public, + ); const [searchText, setSearchText] = useState(''); const [tableData, setTableData] = useState([]); const [total, setTotal] = useState(0); @@ -55,19 +64,37 @@ function MirrorList() { current: 1, pageSize: 10, }); + useEffect(() => { getMirrorList(); }, [activeTab, pagination]); + // 切换 Tab,重置数据 + const hanleTabChange: TabsProps['onChange'] = (value) => { + setSearchText(''); + setPagination({ + showSizeChanger: true, + showQuickJumper: true, + current: 1, + pageSize: 10, + }); + setTotal(0); + setTableData([]); + setActiveTab(value); + setSearchParams([['isPublic', value === CommonTabKeys.Public ? 'true' : 'false']], { + replace: true, + }); + }; // 获取镜像列表 - const getMirrorList = async () => { - const params = { + const getMirrorList = async (params?: Record) => { + const reqParams = { page: pagination.current! - 1, size: pagination.pageSize, name: searchText, image_type: activeTab === CommonTabKeys.Public ? 1 : 0, + ...params, }; - const [res] = await to(getMirrorListReq(params)); + const [res] = await to(getMirrorListReq(reqParams)); if (res && res.data) { const { content = [], totalElements = 0 } = res.data; setTableData(content); @@ -75,25 +102,57 @@ function MirrorList() { } }; + // 删除镜像 + const deleteMirror = async (id: number) => { + const [res] = await to(deleteMirrorReq(id)); + if (res) { + message.success('删除成功'); + // 如果是一页的唯一数据,删除时,请求第一页的数据 + // 否则直接刷新这一页的数据 + // 避免回到第一页 + if (tableData.length > 1) { + setPagination((prev) => ({ + ...prev, + current: 1, + })); + } else { + getMirrorList(); + } + } + }; + // 搜索 - const onSearch = () => { - getMirrorList(); + const onSearch: SearchProps['onSearch'] = (value) => { + // 带参数是为了点清除时,searchText 更新不及时的问题 + getMirrorList({ + name: value, + }); }; // 查看详情 const toDetail = (record: MirrorData) => { console.log('record', record); - navgite({ - pathname: `/dataset/mirror/${record.id}?isPublic=${activeTab === CommonTabKeys.Public}`, + navigate(`/dataset/mirror/${record.id}?isPublic=${activeTab === CommonTabKeys.Public}`, { + state: { + isPublic: activeTab === CommonTabKeys.Public, + }, }); }; - // 删除镜像 - const deleteMirror = (record: MirrorData) => {}; + // 处理删除 + const handleMirrorDelete = (record: MirrorData) => { + modalConfirm({ + title: '删除后,该镜像将不可恢复', + content: '是否确认删除?', + onOk: () => { + deleteMirror(record.id); + }, + }); + }; // 创建镜像 const createMirror = () => { - navgite({ pathname: `/dataset/mirror/create?isPublic=${activeTab === CommonTabKeys.Public}` }); + navigate(`/dataset/mirror/create`); }; // 分页切换 @@ -101,7 +160,7 @@ function MirrorList() { if (action === 'paginate') { setPagination(pagination); } - console.log(pagination, filters, sorter, action); + // console.log(pagination, filters, sorter, action); }; const columns: TableProps['columns'] = [ @@ -110,32 +169,35 @@ function MirrorList() { dataIndex: 'name', key: 'name', width: '30%', + render: CommonTableCell, }, { title: '版本数据', dataIndex: 'version_count', key: 'version_count', width: 100, + render: CommonTableCell, }, { title: '镜像描述', dataIndex: 'description', key: 'description', - //ellipsis: true, + render: CommonTableCell, + ellipsis: true, }, { title: '创建时间', dataIndex: 'create_time', key: 'create_time', width: 200, - render: (text: string) => {dayjs(text).format('YYYY-MM-DD HH:mm:ss')}, + render: DateTableCell, }, { title: '操作', dataIndex: 'operation', width: activeTab === CommonTabKeys.Private ? 200 : 150, key: 'operation', - render: (_: any, record: any) => ( + render: (_: any, record: MirrorData) => (
@@ -176,7 +238,7 @@ function MirrorList() {
diff --git a/react-ui/src/pages/Pipeline/editPipeline/props.jsx b/react-ui/src/pages/Pipeline/editPipeline/props.jsx index 1756855d..58127381 100644 --- a/react-ui/src/pages/Pipeline/editPipeline/props.jsx +++ b/react-ui/src/pages/Pipeline/editPipeline/props.jsx @@ -1,9 +1,9 @@ import KFIcon from '@/components/KFIcon'; import { getComputingResourceReq } from '@/services/pipeline'; -import { pick } from '@/utils/index'; import { openAntdModal } from '@/utils/modal'; import { to } from '@/utils/promise'; import { Button, Drawer, Form, Input, Select } from 'antd'; +import { pick } from 'lodash'; import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; import ResourceSelectorModal, { ResourceSelectorType } from '../components/ResourceSelectorModal'; import Styles from './editPipeline.less'; diff --git a/react-ui/src/services/mirror/index.ts b/react-ui/src/services/mirror/index.ts index 544d63d4..331408a2 100644 --- a/react-ui/src/services/mirror/index.ts +++ b/react-ui/src/services/mirror/index.ts @@ -28,18 +28,24 @@ export function getMirrorVersionListReq(params: any) { }); } -// 创建公网镜像 -export function createPublicMirrorReq(data: any) { - return request(`/api/mmp/image/net`, { +// 创建镜像 +export function createMirrorReq(data: any) { + return request(`/api/mmp/image/addImageAndVersion`, { method: 'POST', data, }); } -// 创建本地镜像 -export function createPrivateMirrorReq(data: any) { - return request(`/api/mmp/image/local`, { - method: 'POST', - data, +// 删除镜像 +export function deleteMirrorReq(id: number) { + return request(`/api/mmp/image/${id}`, { + method: 'DELETE', + }); +} + +// 删除镜像 +export function deleteMirrorVersionReq(id: number) { + return request(`/api/mmp/imageVersion/${id}`, { + method: 'DELETE', }); } diff --git a/react-ui/src/utils/index.ts b/react-ui/src/utils/index.ts index e0cd2d7e..d7d2fc41 100644 --- a/react-ui/src/utils/index.ts +++ b/react-ui/src/utils/index.ts @@ -14,37 +14,3 @@ export function getNameByCode(list: any[], code: any) { }); return name; } - -/** - * Picks specified properties from an object and returns a new object with only those properties. - * - * @param obj - The object to pick properties from. - * @param properties - An array of property names to pick from the object. - * @return A new object with only the picked properties. - */ -export function pick(obj: T, properties: K[]): Pick { - const picked: Partial = {}; - for (const key of properties) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - picked[key] = obj[key]; - } - } - return picked as Pick; -} - -/** - * Omit properties from an object and return a new object without those properties. - * - * @param obj - The object to omit properties from. - * @param properties - An array of property names to omit from the object. - * @return A new object without the omitted properties. - */ -export function omit(obj: T, properties: K[]): Omit { - const omitted: Partial = { ...obj }; - for (const key of properties) { - if (Object.prototype.hasOwnProperty.call(omitted, key)) { - delete omitted[key]; - } - } - return omitted as Omit; -} diff --git a/react-ui/src/utils/sessionKeys.ts b/react-ui/src/utils/sessionKeys.ts new file mode 100644 index 00000000..522ce516 --- /dev/null +++ b/react-ui/src/utils/sessionKeys.ts @@ -0,0 +1,2 @@ +// 用于新建镜像 +export const mirrorNameKey = 'mirror-name'; diff --git a/react-ui/src/utils/ui.tsx b/react-ui/src/utils/ui.tsx index 79a4c1f8..544d2063 100644 --- a/react-ui/src/utils/ui.tsx +++ b/react-ui/src/utils/ui.tsx @@ -4,7 +4,7 @@ * @Description: UI 公共方法 */ import themes from '@/styles/theme.less'; -import { Modal, type ModalFuncProps } from 'antd'; +import { Modal, type ModalFuncProps, type UploadFile } from 'antd'; // 自定义 Confirm 弹框 export function modalConfirm({ title, content, onOk, ...rest }: ModalFuncProps) { @@ -26,3 +26,20 @@ export function modalConfirm({ title, content, onOk, ...rest }: ModalFuncProps) onOk: onOk, }); } + +// 从事件中获取上传文件列表,用于 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; + }); +};