import React, { useState, useEffect, useCallback } from 'react'; import { Table, Form, Input, Select, Button, Modal, message, Space, Tag, DatePicker, Popconfirm, Radio } from 'antd'; import type { TableColumnsType } from 'antd'; import { SearchOutlined, ReloadOutlined, PlusOutlined, EditOutlined, DeleteOutlined, DownloadOutlined, ExclamationCircleOutlined, SyncOutlined } from '@ant-design/icons'; import { listDictType, getDictType, addDictType, updateDictType, delDictType, refreshCache } from '../../api/system/dict'; import { saveAs } from 'file-saver'; import dayjs from 'dayjs'; import 'dayjs/locale/zh-cn'; import zhCN from 'antd/es/date-picker/locale/zh_CN'; import { parseTime } from '../../utils/ruoyi'; import { Link } from 'react-router-dom'; const { RangePicker } = DatePicker; dayjs.locale('zh-cn'); // Mock Dictionaries const sysNormalDisableDict = [ { value: '0', label: '正常' }, { value: '1', label: '停用' }, ]; const DictPage: React.FC = () => { const [queryForm] = Form.useForm(); const [dictForm] = Form.useForm(); const [loading, setLoading] = useState(false); const [typeList, setTypeList] = useState([]); const [total, setTotal] = useState(0); const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [dateRange, setDateRange] = useState<[dayjs.Dayjs, dayjs.Dayjs] | null>(null); const [modalVisible, setModalVisible] = useState(false); const [modalTitle, setModalTitle] = useState(''); const [currentDict, setCurrentDict] = useState({}); const [queryParams, setQueryParams] = useState({ pageNum: 1, pageSize: 10, dictName: undefined, dictType: undefined, status: undefined, }); const getList = useCallback(async () => { setLoading(true); try { const formattedQueryParams = { ...queryParams }; if (dateRange && dateRange.length === 2) { formattedQueryParams['beginTime'] = dateRange[0].format('YYYY-MM-DD'); formattedQueryParams['endTime'] = dateRange[1].format('YYYY-MM-DD'); } else { formattedQueryParams['beginTime'] = undefined; formattedQueryParams['endTime'] = undefined; } const response = await listDictType(formattedQueryParams); setTypeList(response.rows); setTotal(response.total); } catch (error) { console.error('Failed to fetch dictionary type list:', error); message.error('获取字典类型列表失败'); } finally { setLoading(false); } }, [queryParams, dateRange]); useEffect(() => { getList(); }, [getList]); const handleQuery = () => { setQueryParams(prev => ({ ...prev, pageNum: 1 })); }; const resetQuery = () => { queryForm.resetFields(); setDateRange(null); setQueryParams({ pageNum: 1, pageSize: 10, dictName: undefined, dictType: undefined, status: undefined, }); getList(); }; const resetDictForm = () => { dictForm.resetFields(); setCurrentDict({}); }; const handleAdd = () => { resetDictForm(); setModalTitle('添加字典类型'); setModalVisible(true); }; const handleUpdate = async (row: any) => { resetDictForm(); try { const dictId = row.dictId || selectedRowKeys[0]; const response = await getDictType(dictId); const detail = (response && typeof response === 'object' && 'data' in response) ? response.data ?? {} : response ?? {}; setCurrentDict(detail); dictForm.setFieldsValue({ ...detail, }); setModalTitle('修改字典类型'); setModalVisible(true); } catch (error) { message.error('获取字典类型详情失败'); } }; const handleDelete = (row?: any) => { const dictIds = row?.dictId ? [row.dictId] : selectedRowKeys; if (dictIds.length === 0) { message.warning('请选择要删除的字典类型'); return; } Modal.confirm({ title: '确认删除', icon: , content: `是否确认删除字典编号为"${dictIds.join(',')}"的数据项?`, onOk: async () => { try { await delDictType(dictIds.join(',')); message.success('删除成功'); setSelectedRowKeys([]); getList(); } catch (error) { message.error('删除失败'); } }, }); }; const handleExport = async () => { const hide = message.loading('正在导出数据...', 0); try { const response = await listDictType({ ...queryParams, pageNum: undefined, pageSize: undefined }); const header = ['字典编号', '字典名称', '字典类型', '状态', '备注', '创建时间']; const data = response.rows.map((dict: any) => [ dict.dictId, dict.dictName, dict.dictType, sysNormalDisableDict.find((d) => d.value === String(dict.status ?? ''))?.label ?? '', dict.remark, parseTime(dict.createTime), ]); const csvContent = [header, ...data] .map((row) => row.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(',')) .join('\n'); const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); saveAs(blob, `dict_type_${dayjs().format('YYYYMMDDHHmmss')}.csv`); hide(); message.success('导出成功'); } catch { hide(); message.error('导出失败'); } }; const handleRefreshCache = async () => { try { await refreshCache(); message.success('刷新缓存成功'); } catch (error) { message.error('刷新缓存失败'); } }; const submitDictForm = async (values: any) => { try { const dictData = { ...currentDict, ...values }; if (dictData.dictId !== undefined) { await updateDictType(dictData); message.success('修改成功'); } else { await addDictType(dictData); message.success('新增成功'); } setModalVisible(false); getList(); } catch (error) { console.error('Submit dictionary type form failed:', error); message.error('操作失败'); } }; const columns: TableColumnsType = [ { title: '字典编号', dataIndex: 'dictId', align: 'center' }, { title: '字典名称', dataIndex: 'dictName', align: 'center', ellipsis: true }, { title: '字典类型', dataIndex: 'dictType', align: 'center', ellipsis: true, render: (text: string, record: any) => ( {text} ), }, { title: '状态', dataIndex: 'status', align: 'center', render: (text: string) => {sysNormalDisableDict.find(d => d.value === text)?.label}, }, { title: '备注', dataIndex: 'remark', align: 'center', ellipsis: true }, { title: '创建时间', dataIndex: 'createTime', align: 'center', width: 180, render: (text: string) => parseTime(text) }, { title: '操作', key: 'operation', align: 'center', width: 180, render: (_, record) => ( handleDelete(record)} okText="是" cancelText="否" > ), }, ]; return (
setDateRange(dates)} locale={zhCN} format="YYYY年MM月DD日" placeholder={['开始日期', '结束日期']} style={{ width: 240 }} />
setSelectedRowKeys(keys), }} pagination={{ current: queryParams.pageNum, pageSize: queryParams.pageSize, total: total, showSizeChanger: true, showQuickJumper: true, showTotal: (total) => `共 ${total} 条`, onChange: (page, pageSize) => { setQueryParams(prev => ({ ...prev, pageNum: page, pageSize: pageSize })); }, }} /> {/* Add/Edit Dictionary Type Modal */} setModalVisible(false)} width={500} forceRender >
{sysNormalDisableDict.map(dict => ( {dict.label} ))}
); }; export default DictPage;