fix(镜像管理): 国际化配置+layout布局适应+修改逻辑+样式
parent
c6361112fa
commit
4348cfffea
|
@ -8,6 +8,11 @@ export default defineConfig({
|
||||||
request: {},
|
request: {},
|
||||||
layout: false,
|
layout: false,
|
||||||
outputPath: 'serve/dist',
|
outputPath: 'serve/dist',
|
||||||
|
locale: {
|
||||||
|
default: 'zh-CN',
|
||||||
|
antd: true, // 启用 antd 国际化
|
||||||
|
baseNavigator: true,
|
||||||
|
},
|
||||||
// 路由配置
|
// 路由配置
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
|
@ -31,9 +36,9 @@ export default defineConfig({
|
||||||
component: '@/pages/userList',
|
component: '@/pages/userList',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path:"/terminal",
|
path: '/terminal',
|
||||||
component: '@/pages/terminal',
|
component: '@/pages/terminal',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"@ant-design/pro-components": "^2.4.4",
|
"@ant-design/pro-components": "^2.4.4",
|
||||||
"@umijs/max": "^4.4.11",
|
"@umijs/max": "^4.4.11",
|
||||||
"antd": "^5.4.0",
|
"antd": "^5.4.0",
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"spark-md5": "^3.0.2",
|
"spark-md5": "^3.0.2",
|
||||||
"uuid": "^11.1.0"
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -117,7 +117,10 @@ const MainLayout: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
<Content className="main-content">
|
<Content
|
||||||
|
className="main-content"
|
||||||
|
style={{ height: 'calc(100vh - 64px)', overflow: 'auto' }}
|
||||||
|
>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</Content>
|
</Content>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { IMAGES_TYPE_MAP } from '@/constants/images.constants';
|
||||||
import { uploadChunkAPI } from '@/services/images';
|
import { uploadChunkAPI } from '@/services/images';
|
||||||
import { Alert, Button, message, Modal, Progress, Upload } from 'antd';
|
import { Alert, Button, message, Modal, Progress, Upload } from 'antd';
|
||||||
import { UploadProps } from 'antd/lib/upload';
|
import { UploadProps } from 'antd/lib/upload';
|
||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState, useEffect } from 'react';
|
||||||
import SparkMD5 from 'spark-md5';
|
import SparkMD5 from 'spark-md5';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
@ -92,6 +92,33 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
const fileSize = useRef<number>(0); // 文件大小
|
const fileSize = useRef<number>(0); // 文件大小
|
||||||
const abortController = useRef<AbortController | null>(null); // 用于取消上传
|
const abortController = useRef<AbortController | null>(null); // 用于取消上传
|
||||||
|
|
||||||
|
// 添加重置状态函数
|
||||||
|
const resetState = () => {
|
||||||
|
setUploadProgress(0);
|
||||||
|
setIsUploading(false);
|
||||||
|
setUploadStatus('ready');
|
||||||
|
setUploadMessage('');
|
||||||
|
completedChunks.current = 0;
|
||||||
|
totalChunks.current = 0;
|
||||||
|
fileId.current = '';
|
||||||
|
fileName.current = '';
|
||||||
|
fileSize.current = 0;
|
||||||
|
uploadQueue.current = [];
|
||||||
|
|
||||||
|
// 如果有正在进行的上传,先中止
|
||||||
|
if (abortController.current) {
|
||||||
|
abortController.current.abort();
|
||||||
|
abortController.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 当弹窗关闭时重置状态
|
||||||
|
useEffect(() => {
|
||||||
|
if (!visible) {
|
||||||
|
resetState();
|
||||||
|
}
|
||||||
|
}, [visible]);
|
||||||
|
|
||||||
// 5. 分块计算文件MD5
|
// 5. 分块计算文件MD5
|
||||||
const calculateMD5InChunks = (
|
const calculateMD5InChunks = (
|
||||||
file: Blob,
|
file: Blob,
|
||||||
|
@ -158,8 +185,6 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
formData.append('shard_index', index.toString());
|
formData.append('shard_index', index.toString());
|
||||||
formData.append('shard_total', totalChunks.current.toString());
|
formData.append('shard_total', totalChunks.current.toString());
|
||||||
|
|
||||||
// 这里应该调用实际的上传API
|
|
||||||
// 示例: await uploadChunkAPI(formData);
|
|
||||||
await uploadChunkAPI(formData, abortController.current?.signal);
|
await uploadChunkAPI(formData, abortController.current?.signal);
|
||||||
// 模拟上传过程
|
// 模拟上传过程
|
||||||
// await new Promise((resolve) =>
|
// await new Promise((resolve) =>
|
||||||
|
@ -186,6 +211,7 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
// 3. 处理上传队列:每次处理最多 MAX_CONCURRENT 个分片
|
// 3. 处理上传队列:每次处理最多 MAX_CONCURRENT 个分片
|
||||||
const processUploadQueue = async () => {
|
const processUploadQueue = async () => {
|
||||||
const promises: Promise<void>[] = [];
|
const promises: Promise<void>[] = [];
|
||||||
|
let hasError = false; // 添加错误标记
|
||||||
|
|
||||||
// 同时处理最多 MAX_CONCURRENT 个分片
|
// 同时处理最多 MAX_CONCURRENT 个分片
|
||||||
for (
|
for (
|
||||||
|
@ -196,13 +222,17 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
const processChunk = async () => {
|
const processChunk = async () => {
|
||||||
while (
|
while (
|
||||||
uploadQueue.current.length > 0 &&
|
uploadQueue.current.length > 0 &&
|
||||||
!abortController.current?.signal.aborted
|
!abortController.current?.signal.aborted &&
|
||||||
|
!hasError // 添加错误检查,出错时停止处理新分片
|
||||||
) {
|
) {
|
||||||
const chunkItem = uploadQueue.current.shift();
|
const chunkItem = uploadQueue.current.shift();
|
||||||
if (chunkItem) {
|
if (chunkItem) {
|
||||||
const { chunk, index } = chunkItem;
|
const { chunk, index } = chunkItem;
|
||||||
const success = await uploadChunk(chunk, index);
|
const success = await uploadChunk(chunk, index);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
// 只有在没有错误的情况下才更新进度
|
||||||
|
if (!hasError) {
|
||||||
completedChunks.current += 1;
|
completedChunks.current += 1;
|
||||||
const progress = Math.round(
|
const progress = Math.round(
|
||||||
(completedChunks.current / totalChunks.current) * 100,
|
(completedChunks.current / totalChunks.current) * 100,
|
||||||
|
@ -213,17 +243,28 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
if (completedChunks.current === totalChunks.current) {
|
if (completedChunks.current === totalChunks.current) {
|
||||||
setIsUploading(false);
|
setIsUploading(false);
|
||||||
setUploadStatus('success');
|
setUploadStatus('success');
|
||||||
setUploadMessage('文件上传成功!正在处理中,请稍后查看列表。');
|
setUploadMessage(
|
||||||
message.success('文件上传成功!系统正在处理,请稍后查看列表。');
|
'文件上传成功!正在处理中,请稍后查看列表。',
|
||||||
|
);
|
||||||
|
message.success(
|
||||||
|
'文件上传成功!系统正在处理,请稍后查看列表。',
|
||||||
|
);
|
||||||
onImportSuccess?.();
|
onImportSuccess?.();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 上传失败处理
|
// 上传失败处理
|
||||||
if (!abortController.current?.signal.aborted) {
|
if (!abortController.current?.signal.aborted && !hasError) {
|
||||||
|
hasError = true; // 设置错误标记
|
||||||
setIsUploading(false);
|
setIsUploading(false);
|
||||||
setUploadStatus('error');
|
setUploadStatus('error');
|
||||||
setUploadMessage('文件上传失败,请重试');
|
setUploadMessage('文件上传失败,请重试');
|
||||||
message.error('文件上传失败');
|
message.error('文件上传失败');
|
||||||
|
|
||||||
|
// 中止其他正在进行的上传
|
||||||
|
if (abortController.current) {
|
||||||
|
abortController.current.abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -253,7 +294,8 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
totalChunks.current = Math.ceil(file.size / CHUNK_SIZE);
|
totalChunks.current = Math.ceil(file.size / CHUNK_SIZE);
|
||||||
uploadQueue.current = [];
|
uploadQueue.current = [];
|
||||||
|
|
||||||
setUploadMessage(`正在分析文件... 共 ${totalChunks.current} 个分片`);
|
setUploadMessage(`正在分析文件... `);
|
||||||
|
// setUploadMessage(`正在分析文件... 共 ${totalChunks.current} 个分片`);
|
||||||
|
|
||||||
// 创建分片并添加到队列
|
// 创建分片并添加到队列
|
||||||
for (let i = 0; i < totalChunks.current; i++) {
|
for (let i = 0; i < totalChunks.current; i++) {
|
||||||
|
@ -263,7 +305,8 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
uploadQueue.current.push({ chunk, index: i });
|
uploadQueue.current.push({ chunk, index: i });
|
||||||
}
|
}
|
||||||
|
|
||||||
setUploadMessage(`开始上传文件,共 ${totalChunks.current} 个分片`);
|
setUploadMessage(`开始上传文件... `);
|
||||||
|
// setUploadMessage(`开始上传文件,共 ${totalChunks.current} 个分片`);
|
||||||
|
|
||||||
// 创建新的AbortController
|
// 创建新的AbortController
|
||||||
abortController.current = new AbortController();
|
abortController.current = new AbortController();
|
||||||
|
@ -328,10 +371,7 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
message="重要提示"
|
message="重要提示"
|
||||||
description={
|
description={
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>1. 文件上传需要时间,请耐心等待。</div>
|
||||||
1.
|
|
||||||
文件上传需要时间,请耐心等待。
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
2. 文件上传中请勿刷新或者离开页面,否则会导致文件上传失败。
|
2. 文件上传中请勿刷新或者离开页面,否则会导致文件上传失败。
|
||||||
</div>
|
</div>
|
||||||
|
@ -368,23 +408,32 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>上传进度</span>
|
<span style={{ width: '70px' }}>上传进度</span>
|
||||||
<span>{uploadProgress}%</span>
|
<div style={{ flex: 1, marginRight: 10 }}>
|
||||||
</div>
|
|
||||||
<Progress
|
<Progress
|
||||||
percent={uploadProgress}
|
percent={uploadProgress}
|
||||||
status={uploadStatus === 'error' ? 'exception' : 'normal'}
|
status={
|
||||||
|
uploadStatus === 'error'
|
||||||
|
? 'exception'
|
||||||
|
: uploadStatus === 'success'
|
||||||
|
? 'success'
|
||||||
|
: 'normal'
|
||||||
|
}
|
||||||
|
format={(percent) => `${percent}%`}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{uploadMessage && (
|
{uploadMessage && (
|
||||||
<div style={{ marginTop: 8, textAlign: 'center' }}>
|
<div style={{ marginTop: 8, textAlign: 'center' }}>
|
||||||
<span>{uploadMessage}</span>
|
<span>{uploadMessage}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* {isUploading && (
|
{isUploading && (
|
||||||
<div style={{ marginTop: 12, textAlign: 'center' }}>
|
<div style={{ marginTop: 12, textAlign: 'center' }}>
|
||||||
<Button onClick={cancelUpload}>取消上传</Button>
|
<Button onClick={cancelUpload}>取消上传</Button>
|
||||||
</div>
|
</div>
|
||||||
)} */}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -397,6 +446,9 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
if (isUploading) {
|
if (isUploading) {
|
||||||
cancelUpload();
|
cancelUpload();
|
||||||
|
} else {
|
||||||
|
// 如果不是上传状态,直接重置状态
|
||||||
|
resetState();
|
||||||
}
|
}
|
||||||
onCancel();
|
onCancel();
|
||||||
}}
|
}}
|
||||||
|
@ -406,6 +458,8 @@ const ImportModal: React.FC<ImportModalProps> = ({
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isUploading) {
|
if (isUploading) {
|
||||||
cancelUpload();
|
cancelUpload();
|
||||||
|
} else {
|
||||||
|
resetState();
|
||||||
}
|
}
|
||||||
onCancel();
|
onCancel();
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -15,7 +15,76 @@
|
||||||
|
|
||||||
// 镜像列表样式
|
// 镜像列表样式
|
||||||
.image-list {
|
.image-list {
|
||||||
padding: 10px;
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 16px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
.search-box {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
.search-input {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.images-list-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
.images-list-table {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 表格适应样式
|
||||||
|
.ant-table-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-spin-nested-loading {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-spin-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-table {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-table-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-table-body {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto !important;
|
||||||
|
|
||||||
|
table {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.image-detail {
|
.image-detail {
|
||||||
.detail-item {
|
.detail-item {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import type { TableProps } from 'antd';
|
import type { TableProps } from 'antd';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
|
@ -19,7 +20,7 @@ import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { ModalDetailShow, ImportModal } from './components/modalShow/modalShow';
|
import { ImportModal, ModalDetailShow } from './components/modalShow/modalShow';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
import { ReactComponent as RefreshIcon } from '@/assets/icons/refresh.svg';
|
import { ReactComponent as RefreshIcon } from '@/assets/icons/refresh.svg';
|
||||||
|
@ -62,6 +63,12 @@ const ImageList: React.FC = () => {
|
||||||
JSON.stringify(tableParams.filters),
|
JSON.stringify(tableParams.filters),
|
||||||
JSON.stringify(tableParams.keywords),
|
JSON.stringify(tableParams.keywords),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格参数转换
|
||||||
|
* @param params - 表格参数对象,包含分页、过滤、排序等信息
|
||||||
|
* @returns 转换后的接口参数对象
|
||||||
|
*/
|
||||||
const getRandomuserParams = (params: IMAGES.TableParams) => {
|
const getRandomuserParams = (params: IMAGES.TableParams) => {
|
||||||
const {
|
const {
|
||||||
pagination,
|
pagination,
|
||||||
|
@ -111,11 +118,14 @@ const ImageList: React.FC = () => {
|
||||||
if (imagesRes.error_code === ERROR_CODE) {
|
if (imagesRes.error_code === ERROR_CODE) {
|
||||||
setImages(imagesRes.data.data || []);
|
setImages(imagesRes.data.data || []);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
// 直接使用后端返回的分页信息
|
||||||
setTableParams((prev) => ({
|
setTableParams((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
pagination: {
|
pagination: {
|
||||||
...prev.pagination,
|
...prev.pagination,
|
||||||
|
current: imagesRes.data.paging.page_num || 1,
|
||||||
total: imagesRes.data.paging.total || 0,
|
total: imagesRes.data.paging.total || 0,
|
||||||
|
pageSize: imagesRes.data.paging.page_size || 10,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
|
@ -268,6 +278,7 @@ const ImageList: React.FC = () => {
|
||||||
dataIndex: 'create_time',
|
dataIndex: 'create_time',
|
||||||
key: 'create_time',
|
key: 'create_time',
|
||||||
width: 180,
|
width: 180,
|
||||||
|
render:(text:string)=><Tooltip>{dayjs(text).format('YYYY-MM-DD HH:mm:ss')}</Tooltip>,
|
||||||
...(visibleColumns['create_time'] ? {} : { hidden: true }),
|
...(visibleColumns['create_time'] ? {} : { hidden: true }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -297,6 +308,7 @@ const ImageList: React.FC = () => {
|
||||||
},
|
},
|
||||||
].filter((column) => !column.hidden);
|
].filter((column) => !column.hidden);
|
||||||
|
|
||||||
|
// 处理表格分页、过滤和排序变化
|
||||||
const handleTableChange: TableProps<IMAGES.ImageItem>['onChange'] = (
|
const handleTableChange: TableProps<IMAGES.ImageItem>['onChange'] = (
|
||||||
pagination,
|
pagination,
|
||||||
filters,
|
filters,
|
||||||
|
@ -323,28 +335,27 @@ const ImageList: React.FC = () => {
|
||||||
loadImages();
|
loadImages();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导入成功后的回调
|
// 导入镜像成功后的回调
|
||||||
const handleImportSuccess = () => {
|
const handleImportSuccess = () => {
|
||||||
// 可以在这里添加导入成功后的处理逻辑
|
|
||||||
// 例如:刷新列表或显示提示信息
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loadImages(); // 一段时间后刷新列表查看是否有新导入的镜像
|
loadImages();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 自定义分页配置
|
||||||
|
const paginationConfig = {
|
||||||
|
...tableParams.pagination,
|
||||||
|
showTotal: (total: number) => `共 ${total} 条记录`,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100'],
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="image-list">
|
<div className="image-list">
|
||||||
<div
|
<div className="search-box">
|
||||||
style={{
|
|
||||||
marginBottom: 16,
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<Button onClick={() => setImportModalVisible(true)}>导入</Button>
|
<Button onClick={() => setImportModalVisible(true)}>导入</Button>
|
||||||
</div>
|
<div className="search-input">
|
||||||
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
|
||||||
<Input.Search
|
<Input.Search
|
||||||
placeholder="镜像名称"
|
placeholder="镜像名称"
|
||||||
value={searchText}
|
value={searchText}
|
||||||
|
@ -378,21 +389,19 @@ const ImageList: React.FC = () => {
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="images-list-container">
|
||||||
|
<div className="images-list-table">
|
||||||
<Table
|
<Table
|
||||||
columns={filteredColumns}
|
columns={filteredColumns}
|
||||||
dataSource={images}
|
dataSource={images}
|
||||||
rowKey="image_id"
|
rowKey="image_id"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
pagination={tableParams.pagination}
|
pagination={paginationConfig}
|
||||||
onChange={handleTableChange}
|
onChange={handleTableChange}
|
||||||
// pagination={{
|
scroll={{ y: '100%' }}
|
||||||
// total: images.length,
|
|
||||||
// pageSize: 10,
|
|
||||||
// showSizeChanger: true,
|
|
||||||
// showQuickJumper: true,
|
|
||||||
// showTotal: (total) => `共 ${total} 条记录`,
|
|
||||||
// }}
|
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{detailVisible ? (
|
{detailVisible ? (
|
||||||
<ModalDetailShow
|
<ModalDetailShow
|
||||||
|
|
|
@ -3827,7 +3827,7 @@ date-fns@2.x:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.21.0"
|
"@babel/runtime" "^7.21.0"
|
||||||
|
|
||||||
dayjs@1.x, dayjs@^1.11.10, dayjs@^1.11.11, dayjs@^1.11.7:
|
dayjs@1.x, dayjs@^1.11.10, dayjs@^1.11.11, dayjs@^1.11.13, dayjs@^1.11.7:
|
||||||
version "1.11.13"
|
version "1.11.13"
|
||||||
resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
|
resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
|
||||||
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
|
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
|
||||||
|
@ -9412,16 +9412,7 @@ string-convert@^0.2.0:
|
||||||
resolved "https://registry.npmmirror.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97"
|
resolved "https://registry.npmmirror.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97"
|
||||||
integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==
|
integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==
|
||||||
|
|
||||||
"string-width-cjs@npm:string-width@^4.2.0":
|
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||||
version "4.2.3"
|
|
||||||
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
|
||||||
dependencies:
|
|
||||||
emoji-regex "^8.0.0"
|
|
||||||
is-fullwidth-code-point "^3.0.0"
|
|
||||||
strip-ansi "^6.0.1"
|
|
||||||
|
|
||||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
|
@ -9511,14 +9502,7 @@ string_decoder@~1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.1.0"
|
safe-buffer "~5.1.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
version "6.0.1"
|
|
||||||
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^5.0.1"
|
|
||||||
|
|
||||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
|
@ -10276,16 +10260,7 @@ word-wrap@^1.2.5:
|
||||||
resolved "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
|
resolved "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
|
||||||
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
|
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
|
||||||
|
|
||||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
||||||
version "7.0.0"
|
|
||||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
|
||||||
dependencies:
|
|
||||||
ansi-styles "^4.0.0"
|
|
||||||
string-width "^4.1.0"
|
|
||||||
strip-ansi "^6.0.0"
|
|
||||||
|
|
||||||
wrap-ansi@^7.0.0:
|
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||||
|
|
Loading…
Reference in New Issue