/* eslint-disable @typescript-eslint/no-use-before-define */ import { CODE, STATUS_MAP } from '@/constants/images.constants'; import { delImagesAPI, getImagesList } from '@/services/images'; import { DeleteOutlined, EyeOutlined, SettingOutlined, PlusOutlined } from '@ant-design/icons'; import { Button, Checkbox, Input, message, Modal, Popconfirm, Popover, Space, Table, Tag, Tooltip, } from 'antd'; import dayjs from 'dayjs'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { ModalDetailShow } from './components/modalShow/modalShow'; import { ImportModal } from './components/uploadFileModal/uploadFileModal'; import useTableParams from './hook/hook'; import './index.less'; import { ReactComponent as RefreshIcon } from '@/assets/icons/refresh.svg'; // interface ImagesProps { // activeTabKey?: string; // } // 列配置定义 type ColumnConfig = { key: string; title: string; dataIndex?: string; width: number; render?: (text: any, record: any, index: number) => React.ReactNode; fixed?: 'left' | 'right'; align?: 'left' | 'center' | 'right'; defaultVisible: boolean; // 默认是否显示 alwaysVisible?: boolean; // 始终显示的列 ellipsis?: boolean; // 是否启用省略号 filters?: { text: string; value: string }[]; filterMultiple?: boolean; // 是否多选过滤 filterDropdown?: (props: any) => React.ReactNode; defaultFilteredValue?: string[]; // 默认过滤值 onFilter?: (value: string, record: any) => boolean; }; type TableColumn = { title: string; dataIndex?: string; key: string; width: number; render?: any; fixed?: 'left' | 'right'; hidden?: boolean; }; // 在组件顶部添加防抖函数(支持取消) // 增强版防抖函数 const debounce = (func: Function, delay: number, immediate = false) => { let timer: NodeJS.Timeout | null = null; const debounced = (...args: any[]) => { if (timer) clearTimeout(timer); if (immediate && !timer) { func(...args); } timer = setTimeout(() => { if (!immediate) { func(...args); } timer = null; }, delay); }; debounced.cancel = () => { if (timer) { clearTimeout(timer); timer = null; } }; return debounced; }; const ImageList: React.FC = (props) => { const { activeTabKey } = props; const [images, setImages] = useState([]); const [loading, setLoading] = useState(false); const [selectedImage, setSelectedImage] = useState( null, ); const [detailVisible, setDetailVisible] = useState(false); const [importModalVisible, setImportModalVisible] = useState(false); const [searchText, setSearchText] = useState(''); // 添加本地搜索状态 const searchInputRef = useRef(''); // 保存已发送请求的搜索文本 const { tableParams, getApiParams, updateParams, handleTableChange } = useTableParams({ pagination: { current: 1, pageSize: 10, }, search: {}, // 初始化搜索参数 }); // 在组件顶部添加一个 ref 来保存最新的 tableParams const tableParamsRef = useRef(tableParams); tableParamsRef.current = tableParams; // 每次渲染时更新 ref 的值 const [columnSettingsVisible, setColumnSettingsVisible] = useState(false); const loadImages = async () => { setLoading(true); try { // 将搜索文本合并到API参数中 const apiParams = { ...getApiParams(), }; const imagesRes = await getImagesList(apiParams); if (imagesRes.code == CODE) { setImages(imagesRes.data?.data || []); setLoading(false); // 正确处理后端返回的分页信息 updateParams({ pagination: { ...tableParams.pagination, current: imagesRes.data?.page_num || 1, total: imagesRes.data?.total || 0, pageSize: tableParams.pagination?.pageSize || 10, }, }); } else { message.error(imagesRes.message || '获取镜像列表失败'); setLoading(false); } } catch (err) { message.error('获取镜像列表失败'); setLoading(false); } }; // 表格参数变化 获取镜像列表 useEffect(() => { if (activeTabKey === '1') { loadImages(); } }, [ tableParams.pagination?.current, tableParams.pagination?.pageSize, tableParams?.sortOrder, tableParams?.sortField, JSON.stringify(tableParams.filters), // 表格搜索参数 JSON.stringify(tableParams.search), // 搜索参数依赖 activeTabKey, ]); // 定义所有列的配置 const columnConfigs: ColumnConfig[] = [ { key: 'index', title: '序号', width: 60, render: (text: any, row: any, index: number) => (tableParams.pagination?.current - 1) * tableParams.pagination?.pageSize + index + 1, defaultVisible: true, alwaysVisible: true, }, { key: 'image_name', // title: '镜像名称', title: '名称', dataIndex: 'image_name', width: 150, defaultVisible: true, alwaysVisible: true, ellipsis: true, render: (text: string) => text ? ( {text} ) : ( '--' ), }, { key: 'os_version', title: '操作系统', dataIndex: 'os_version', width: 100, defaultVisible: true, ellipsis: true, render: (text: string) => text ? {text} : '--', }, { key: 'image_version', // title: '镜像版本', title: '版本', dataIndex: 'image_version', width: 100, defaultVisible: true, ellipsis: true, render: (text: string) => text ? {text} : '--', }, { key: 'storage_path', // title: '模板存放路径', title: '存储位置', dataIndex: 'storage_path', width: 140, defaultVisible: true, ellipsis: true, render: (text: string) => text ? ( {text} ) : ( '--' ), }, // { // key: 'image_file_name', // title: '镜像文件', // dataIndex: 'image_file_name', // width: 150, // defaultVisible: true, // alwaysVisible: true, // ellipsis: true, // render: (text: string) => // text ? ( // // {text} // // ) : ( // '--' // ), // }, // { // key: 'image_type', // title: '桌面类型', // dataIndex: 'image_type', // width: 120, // render: (text: number) => { // const key = text as keyof typeof IMAGES_TYPE_MAP; // return text ? IMAGES_TYPE_MAP[key] : '--'; // }, // defaultVisible: true, // filterDropdown: ({ setSelectedKeys, selectedKeys, confirm }) => ( // 0 ? selectedKeys : ['全部']} // onClick={({ key }) => { // setSelectedKeys(key === '全部' ? [] : [key]); // confirm({ closeDropdown: true }); // 立即触发筛选并关闭下拉菜单 // }} // items={[ // { key: '全部', label: '全部' }, // ...Object.entries(IMAGES_TYPE_MAP).map(([key, value]) => ({ // key, // label: value, // })), // ]} // /> // ), // filterMultiple: false, // defaultFilteredValue: ['全部'], // }, // { // key: 'bt_path', // title: 'BT路径', // dataIndex: 'bt_path', // width: 140, // defaultVisible: true, // ellipsis: true, // render: (text: string) => // text ? ( // // {text} // // ) : ( // '--' // ), // }, // { // key: 'image_status', // title: '镜像状态', // dataIndex: 'image_status', // width: 90, // render: (text: number) => (text ? getStatusTag(text) : '--'), // defaultVisible: true, // }, { key: 'create_time', title: '上传时间', dataIndex: 'create_time', width: 160, render: (text: string) => text ? ( {text ? dayjs(text).format('YYYY-MM-DD HH:mm:ss') : '--'} ) : ( '--' ), defaultVisible: true, ellipsis: true, }, { key: 'action', title: '操作', width: 90, align: 'center', fixed: 'right' as 'right', render: (_: any, record: IMAGES.ImageItem) => ( {/* handleDelete(record)} okText="确定" cancelText="取消" > {/* ), defaultVisible: true, }, ]; // 初始化 visibleColumns 状态 const initialVisibleColumns = columnConfigs.reduce>( (acc, column) => { if (!column.alwaysVisible) { acc[column.key] = column.defaultVisible; } return acc; }, {}, ); const [visibleColumns, setVisibleColumns] = useState>( initialVisibleColumns, ); // 重置列设置 const resetColumns = () => { setVisibleColumns(initialVisibleColumns); }; const getStatusTag = (status: number) => { const config = STATUS_MAP[status as keyof typeof STATUS_MAP]; return {config.text}; }; const handleViewDetail = (record: IMAGES.ImageItem) => { setSelectedImage(record); setDetailVisible(true); }; const handleDelete = (record: IMAGES.ImageItem) => { Modal.confirm({ title: '确认删除', content: `确定要删除镜像 "${record.image_name}" 吗?`, onOk: () => { delImagesAPI({ id: record.id }).then((res) => { if (res.code == CODE) { message.success('删除成功'); loadImages(); } else { message.error(res.message || '删除失败'); } }); }, }); }; // 列设置相关函数 const handleColumnChange = (columnKey: string, checked: boolean) => { setVisibleColumns((prev) => ({ ...prev, [columnKey]: checked, })); }; // 列设置内容 const columnSettingsContent = (
{columnConfigs .filter((config) => !config.alwaysVisible) // 只显示可控制的列 .map((config) => (
handleColumnChange(config.key, e.target.checked)} > {config.title}
))}
); // 根据visibleColumns过滤显示的列 const filteredColumns = columnConfigs .map((config) => { // 对于始终显示的列 if (config.alwaysVisible) { return { ...config, hidden: undefined, }; } // 对于可控制显示/隐藏的列 return { ...config, ...(visibleColumns[config.key] ? {} : { hidden: true }), }; }) .filter((column) => !column.hidden) as TableColumn[]; const handleRefresh = () => { loadImages(); }; // 导入镜像成功后的回调 const handleImportSuccess = () => { setTimeout(() => { loadImages(); }, 5000); }; // 自定义分页配置 const paginationConfig = { ...tableParams.pagination, showTotal: (total: number) => `共 ${total} 条记录`, showSizeChanger: true, showQuickJumper: true, pageSizeOptions: ['10', '20', '50', '100'], }; const handleSearch = useCallback( (searchValue: string) => { const currentTableParams = tableParamsRef.current; updateParams({ search: { image_name: searchValue, }, pagination: { current: 1, pageSize: currentTableParams.pagination?.pageSize || 10, }, }); }, [updateParams], ); // 防抖版本(500ms延迟,不立即执行) const debouncedSearch = useRef(debounce(handleSearch, 500)).current; // 立即执行版本(用于清空时立即搜索) const immediateSearch = useRef(debounce(handleSearch, 0, true)).current; const handleSearchChange = (value: string) => { setSearchText(value); // 取消所有未执行的防抖请求 debouncedSearch.cancel(); immediateSearch.cancel(); // 清空时立即触发搜索 if (value === '') { immediateSearch(''); return; } // 正常输入时使用防抖 debouncedSearch(value); }; // 修改回车搜索处理 const handleEnterSearch = (value: string) => { // 回车搜索时取消未执行的防抖 debouncedSearch.cancel(); immediateSearch.cancel(); // 直接执行搜索 handleSearch(value); }; return (
handleSearchChange(e.target.value)} style={{ width: 300 }} onSearch={handleEnterSearch} />
{detailVisible ? ( ) : null} {/* 导入弹窗 */} setImportModalVisible(false)} onImportSuccess={handleImportSuccess} /> ); }; export default ImageList;