import { UploadOutlined } from '@ant-design/icons'; import { ActionType, PageContainer, ProTable, } from '@ant-design/pro-components'; import { Button, Form, Input, Layout, Modal, Space, Table, Upload, message, } from 'antd'; import React, { useEffect, useRef, useState } from 'react'; import * as dictApi from '@/servers/api/dict'; const { Sider, Content } = Layout; const DictPage: React.FC = () => { // 左侧字典列表的状态 const [dicts, setDicts] = useState([]); const [loadingDicts, setLoadingDicts] = useState(false); const [searchText, setSearchText] = useState(''); const [selectedDict, setSelectedDict] = useState(null); // 添加字典 modal 状态 const [isAddDictModalVisible, setIsAddDictModalVisible] = useState(false); const [addDictName, setAddDictName] = useState(''); const [addDictTitle, setAddDictTitle] = useState(''); // 编辑字典 modal 状态 const [isEditDictModalVisible, setIsEditDictModalVisible] = useState(false); const [editDictData, setEditDictData] = useState(null); // 右侧字典项列表的状态 const [isAddDictItemModalVisible, setIsAddDictItemModalVisible] = useState(false); const [isEditDictItemModalVisible, setIsEditDictItemModalVisible] = useState(false); const [editDictItemData, setEditDictItemData] = useState(null); const [dictItemForm] = Form.useForm(); const actionRef = useRef(); // 获取字典列表 const fetchDicts = async (name = '') => { setLoadingDicts(true); try { const res = await dictApi.dictcontrollerGetdicts({ name }); setDicts(res); } catch (error) { message.error('获取字典列表失败'); } finally { setLoadingDicts(false); } }; // 搜索字典 const handleSearch = (value: string) => { fetchDicts(value); }; // 添加字典 const handleAddDict = async () => { const values = { name: addDictName, title: addDictTitle }; try { await dictApi.dictcontrollerCreatedict(values); message.success('添加成功'); setIsAddDictModalVisible(false); setAddDictName(''); setAddDictTitle(''); fetchDicts(); // 重新获取列表 } catch (error) { message.error('添加失败'); } }; // 编辑字典 const handleEditDict = async () => { if (!editDictData) return; const values = { name: editDictData.name, title: editDictData.title }; try { await dictApi.dictcontrollerUpdatedict({ id: editDictData.id }, values); message.success('更新成功'); setIsEditDictModalVisible(false); setEditDictData(null); fetchDicts(); // 重新获取列表 } catch (error) { message.error('更新失败'); } }; // 删除字典 const handleDeleteDict = async (id: number) => { try { const result = await dictApi.dictcontrollerDeletedict({ id }); if(!result.success){ throw new Error(result.message || '删除失败') } message.success('删除成功'); fetchDicts(); if (selectedDict?.id === id) { setSelectedDict(null); } } catch (error:any) { message.error(`删除失败,原因为:${error.message}`); } }; // 打开编辑字典 modal const openEditDictModal = (record: any) => { setEditDictData(record); setIsEditDictModalVisible(true); }; // 下载字典导入模板 const handleDownloadDictTemplate = async () => { try { // 使用 dictApi.dictcontrollerDownloaddicttemplate 获取字典模板 const response = await dictApi.dictcontrollerDownloaddicttemplate({ responseType: 'blob', skipErrorHandler: true, }); // 创建 blob 对象和下载链接 const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', }); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.setAttribute('download', 'dict_template.xlsx'); document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(url); } catch (error: any) { message.error('下载字典模板失败:' + (error.message || '未知错误')); } }; // 添加字典项 const handleAddDictItem = () => { dictItemForm.resetFields(); setIsAddDictItemModalVisible(true); }; // 编辑字典项 const handleEditDictItem = (record: any) => { setEditDictItemData(record); dictItemForm.setFieldsValue(record); setIsEditDictItemModalVisible(true); }; // 删除字典项 const handleDeleteDictItem = async (id: number) => { try { const result = await dictApi.dictcontrollerDeletedictitem({ id }); if(!result.success){ throw new Error(result.message || '删除失败') } message.success('删除成功'); // 强制刷新字典项列表 setTimeout(() => { actionRef.current?.reload(); }, 100); } catch (error:any) { message.error(`删除失败,原因为:${error.message}`); } }; // 添加字典项表单提交 const handleAddDictItemFormSubmit = async (values: any) => { try { const result = await dictApi.dictcontrollerCreatedictitem({ ...values, dictId: selectedDict.id }); if (!result.success) { throw new Error(result.message || '添加失败'); } message.success('添加成功'); setIsAddDictItemModalVisible(false); // 强制刷新字典项列表 setTimeout(() => { actionRef.current?.reload(); }, 100); } catch (error: any) { message.error(`添加失败:${error.message || '未知错误'}`); } }; // 编辑字典项表单提交 const handleEditDictItemFormSubmit = async (values: any) => { if (!editDictItemData) return; try { const result = await dictApi.dictcontrollerUpdatedictitem({ id: editDictItemData.id }, values); if (!result.success) { throw new Error(result.message || '更新失败'); } message.success('更新成功'); setIsEditDictItemModalVisible(false); setEditDictItemData(null); // 强制刷新字典项列表 setTimeout(() => { actionRef.current?.reload(); }, 100); } catch (error: any) { message.error(`更新失败:${error.message || '未知错误'}`); } }; // 导出字典项数据 const handleExportDictItems = async () => { if (!selectedDict) { message.warning('请先选择字典'); return; } try { // 获取当前字典的所有数据 const response = await dictApi.dictcontrollerGetdictitems({ dictId: selectedDict.id }); if (!response || response.length === 0) { message.warning('当前字典没有数据可导出'); return; } // 将数据转换为CSV格式 const headers = [ 'name', 'title', 'titleCN', 'value', 'sort', 'image', 'shortName', ]; const csvContent = [ headers.join(','), ...response.map((item: any) => headers .map((header) => { const value = item[header] || ''; // 如果值包含逗号或引号,需要转义 if ( typeof value === 'string' && (value.includes(',') || value.includes('"')) ) { return `"${value.replace(/"/g, '""')}"`; } return value; }) .join(','), ), ].join('\n'); // 创建blob并下载 const blob = new Blob(['\ufeff' + csvContent], { // 添加BOM以支持中文 type: 'text/csv;charset=utf-8', }); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.setAttribute('download', `${selectedDict.name}_dict_items.csv`); document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(url); message.success(`成功导出 ${response.length} 条数据`); } catch (error: any) { message.error('导出字典项失败:' + (error.message || '未知错误')); } }; // Effects useEffect(() => { fetchDicts(); }, []); // 左侧字典表格的列定义 const dictColumns = [ { title: '字典名称', dataIndex: 'name', key: 'name' }, { title: '操作', key: 'action', render: (_: any, record: any) => ( ), }, ]; // 右侧字典项列表的列定义 const dictItemColumns = [ { title: '名称', dataIndex: 'name', key: 'name', copyable: true, }, { title: '简称', dataIndex: 'shortName', key: 'shortName', copyable: true, }, { title: '图片', dataIndex: 'image', key: 'image', valueType: 'image', width: 80, }, { title: '标题', dataIndex: 'title', key: 'title', copyable: true, }, { title: '中文标题', dataIndex: 'titleCN', key: 'titleCN', copyable: true, }, { title: '操作', key: 'action', render: (_: any, record: any) => ( ), }, ]; return ( setSearchText(e.target.value)} enterButton allowClear /> { if (info.file.status === 'done') { message.success(`${info.file.name} 文件上传成功`); fetchDicts(); } else if (info.file.status === 'error') { message.error(`${info.file.name} 文件上传失败`); } }} > ({ onClick: () => { // 如果点击的是当前已选中的行,则取消选择 if (selectedDict?.id === record.id) { setSelectedDict(null); } else { setSelectedDict(record); } }, })} rowClassName={(record) => selectedDict?.id === record.id ? 'ant-table-row-selected' : '' } pagination={false} /> { // 当没有选择字典时,不发起请求 if (!selectedDict?.id) { return { data: [], success: true, }; } const { name, title } = params; const res = await dictApi.dictcontrollerGetdictitems({ dictId: selectedDict?.id, name, title, }); // 适配新的响应格式,检查是否有 successResponse 包裹 if (res && res.success !== undefined) { return { data: res.data || [], success: res.success, total: res.data?.length || 0, }; } // 兼容旧的响应格式(直接返回数组) return { data: res || [], success: true, }; }} rowKey="id" search={{ layout: 'vertical', }} pagination={false} options={{ reload: true, density: true, setting: true, }} size="small" key={selectedDict?.id} toolBarRender={() => [ , { const { file, onSuccess, onError } = options; try { const result = await dictApi.dictcontrollerImportdictitems( { dictId: selectedDict?.id }, [file as File] ); onSuccess?.(result); } catch (error) { onError?.(error as Error); } }} showUploadList={false} disabled={!selectedDict} onChange={(info) => { console.log(`info`,info) if (info.file.status === 'done') { message.success(`${info.file.name} 文件上传成功`); // 重新加载字典项列表 setTimeout(() => { actionRef.current?.reload(); }, 100); // 重新加载字典列表以更新字典项数量 fetchDicts(); } else if (info.file.status === 'error') { message.error(`${info.file.name} 文件上传失败`); } }} key="import" > , , ]} /> {/* 添加字典项 Modal */} dictItemForm.submit()} onCancel={() => setIsAddDictItemModalVisible(false)} >
{/* 编辑字典项 Modal */} dictItemForm.submit()} onCancel={() => { setIsEditDictItemModalVisible(false); setEditDictItemData(null); }} >
{/* 添加字典 Modal */} { setIsAddDictModalVisible(false); setAddDictName(''); setAddDictTitle(''); }} >
setAddDictName(e.target.value)} /> setAddDictTitle(e.target.value)} />
{/* 编辑字典 Modal */} { setIsEditDictModalVisible(false); setEditDictData(null); }} >
setEditDictData({ ...editDictData, name: e.target.value })} /> setEditDictData({ ...editDictData, title: e.target.value })} />
); }; export default DictPage;