265 lines
9.3 KiB
TypeScript
265 lines
9.3 KiB
TypeScript
/**
|
|
* 字典管理页面
|
|
* 与 GVA 保持一致的功能
|
|
*/
|
|
import { PlusOutlined, DeleteOutlined, EditOutlined, DownloadOutlined, UploadOutlined } from '@ant-design/icons';
|
|
import { PageContainer, ProTable, ModalForm, ProFormText, ProFormSwitch } from '@ant-design/pro-components';
|
|
import type { ProColumns, ActionType } from '@ant-design/pro-components';
|
|
import { Button, message, Popconfirm, Space, Card, Row, Col, Upload, Switch } from 'antd';
|
|
import { useRef, useState } from 'react';
|
|
import {
|
|
getSysDictionaryList,
|
|
createSysDictionary,
|
|
updateSysDictionary,
|
|
deleteSysDictionary,
|
|
exportSysDictionary,
|
|
importSysDictionary,
|
|
} from '@/services/system/dictionary';
|
|
import {
|
|
getSysDictionaryDetailList,
|
|
createSysDictionaryDetail,
|
|
updateSysDictionaryDetail,
|
|
deleteSysDictionaryDetail,
|
|
} from '@/services/system/dictionaryDetail';
|
|
|
|
const DictionaryPage: React.FC = () => {
|
|
const actionRef = useRef<ActionType>();
|
|
const detailActionRef = useRef<ActionType>();
|
|
const [modalVisible, setModalVisible] = useState(false);
|
|
const [detailModalVisible, setDetailModalVisible] = useState(false);
|
|
const [currentRow, setCurrentRow] = useState<API.Dictionary>();
|
|
const [currentDetail, setCurrentDetail] = useState<API.DictionaryDetail>();
|
|
const [isEdit, setIsEdit] = useState(false);
|
|
const [isDetailEdit, setIsDetailEdit] = useState(false);
|
|
const [selectedDict, setSelectedDict] = useState<API.Dictionary>();
|
|
|
|
const handleDelete = async (id: number) => {
|
|
const res = await deleteSysDictionary({ ID: id });
|
|
if (res.code === 0) {
|
|
message.success('删除成功');
|
|
actionRef.current?.reload();
|
|
}
|
|
};
|
|
|
|
const handleDeleteDetail = async (id: number) => {
|
|
const res = await deleteSysDictionaryDetail({ ID: id });
|
|
if (res.code === 0) {
|
|
message.success('删除成功');
|
|
detailActionRef.current?.reload();
|
|
}
|
|
};
|
|
|
|
const handleExport = async (id: number) => {
|
|
const res = await exportSysDictionary({ ID: id });
|
|
if (res.code === 0 && res.data) {
|
|
const blob = new Blob([JSON.stringify(res.data, null, 2)], { type: 'application/json' });
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = `dictionary_${id}.json`;
|
|
a.click();
|
|
message.success('导出成功');
|
|
}
|
|
};
|
|
|
|
const handleImport = async (file: File) => {
|
|
const reader = new FileReader();
|
|
reader.onload = async (e) => {
|
|
try {
|
|
const data = JSON.parse(e.target?.result as string);
|
|
const res = await importSysDictionary(data);
|
|
if (res.code === 0) {
|
|
message.success('导入成功');
|
|
actionRef.current?.reload();
|
|
}
|
|
} catch {
|
|
message.error('文件格式错误');
|
|
}
|
|
};
|
|
reader.readAsText(file);
|
|
return false;
|
|
};
|
|
|
|
const dictColumns: ProColumns<API.Dictionary>[] = [
|
|
{ title: 'ID', dataIndex: 'ID', search: false },
|
|
{ title: '字典名称', dataIndex: 'name' },
|
|
{ title: '字典类型', dataIndex: 'type' },
|
|
{ title: '描述', dataIndex: 'desc', search: false },
|
|
{
|
|
title: '状态',
|
|
dataIndex: 'status',
|
|
search: false,
|
|
render: (_, record) => <Switch checked={record.status} disabled />,
|
|
},
|
|
{
|
|
title: '操作',
|
|
valueType: 'option',
|
|
render: (_, record) => (
|
|
<Space>
|
|
<Button type="link" onClick={() => setSelectedDict(record)}>详情</Button>
|
|
<Button type="link" icon={<EditOutlined />} onClick={() => {
|
|
setCurrentRow(record);
|
|
setIsEdit(true);
|
|
setModalVisible(true);
|
|
}}>编辑</Button>
|
|
<Button type="link" icon={<DownloadOutlined />} onClick={() => handleExport(record.ID!)}>导出</Button>
|
|
<Popconfirm title="确定删除?" onConfirm={() => handleDelete(record.ID!)}>
|
|
<Button type="link" danger icon={<DeleteOutlined />}>删除</Button>
|
|
</Popconfirm>
|
|
</Space>
|
|
),
|
|
},
|
|
];
|
|
|
|
const detailColumns: ProColumns<API.DictionaryDetail>[] = [
|
|
{ title: 'ID', dataIndex: 'ID' },
|
|
{ title: '标签', dataIndex: 'label' },
|
|
{ title: '值', dataIndex: 'value' },
|
|
{ title: '扩展', dataIndex: 'extend' },
|
|
{ title: '排序', dataIndex: 'sort' },
|
|
{
|
|
title: '状态',
|
|
dataIndex: 'status',
|
|
render: (_, record) => <Switch checked={record.status} disabled />,
|
|
},
|
|
{
|
|
title: '操作',
|
|
valueType: 'option',
|
|
render: (_, record) => (
|
|
<Space>
|
|
<Button type="link" icon={<EditOutlined />} onClick={() => {
|
|
setCurrentDetail(record);
|
|
setIsDetailEdit(true);
|
|
setDetailModalVisible(true);
|
|
}}>编辑</Button>
|
|
<Popconfirm title="确定删除?" onConfirm={() => handleDeleteDetail(record.ID!)}>
|
|
<Button type="link" danger icon={<DeleteOutlined />}>删除</Button>
|
|
</Popconfirm>
|
|
</Space>
|
|
),
|
|
},
|
|
];
|
|
|
|
|
|
return (
|
|
<PageContainer>
|
|
<Row gutter={16}>
|
|
<Col span={12}>
|
|
<ProTable<API.Dictionary>
|
|
headerTitle="字典列表"
|
|
actionRef={actionRef}
|
|
rowKey="ID"
|
|
columns={dictColumns}
|
|
toolBarRender={() => [
|
|
<Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => {
|
|
setCurrentRow(undefined);
|
|
setIsEdit(false);
|
|
setModalVisible(true);
|
|
}}>新增字典</Button>,
|
|
<Upload key="import" accept=".json" showUploadList={false} beforeUpload={handleImport}>
|
|
<Button icon={<UploadOutlined />}>导入</Button>
|
|
</Upload>,
|
|
]}
|
|
request={async (params) => {
|
|
const res = await getSysDictionaryList({ page: params.current, pageSize: params.pageSize, ...params });
|
|
return {
|
|
data: res.data?.list || [],
|
|
total: res.data?.total || 0,
|
|
success: res.code === 0,
|
|
};
|
|
}}
|
|
/>
|
|
</Col>
|
|
<Col span={12}>
|
|
{selectedDict && (
|
|
<Card title={`字典详情 - ${selectedDict.name}`}>
|
|
<ProTable<API.DictionaryDetail>
|
|
actionRef={detailActionRef}
|
|
rowKey="ID"
|
|
columns={detailColumns}
|
|
search={false}
|
|
toolBarRender={() => [
|
|
<Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => {
|
|
setCurrentDetail({ sysDictionaryID: selectedDict.ID });
|
|
setIsDetailEdit(false);
|
|
setDetailModalVisible(true);
|
|
}}>新增详情</Button>,
|
|
]}
|
|
request={async (params) => {
|
|
const res = await getSysDictionaryDetailList({
|
|
page: params.current,
|
|
pageSize: params.pageSize,
|
|
sysDictionaryID: selectedDict.ID,
|
|
});
|
|
return {
|
|
data: res.data?.list || [],
|
|
total: res.data?.total || 0,
|
|
success: res.code === 0,
|
|
};
|
|
}}
|
|
/>
|
|
</Card>
|
|
)}
|
|
</Col>
|
|
</Row>
|
|
|
|
<ModalForm
|
|
title={isEdit ? '编辑字典' : '新增字典'}
|
|
open={modalVisible}
|
|
onOpenChange={setModalVisible}
|
|
initialValues={currentRow}
|
|
onFinish={async (values) => {
|
|
let res;
|
|
if (isEdit) {
|
|
res = await updateSysDictionary({ ...currentRow, ...values });
|
|
} else {
|
|
res = await createSysDictionary(values);
|
|
}
|
|
if (res.code === 0) {
|
|
message.success(isEdit ? '编辑成功' : '创建成功');
|
|
setModalVisible(false);
|
|
actionRef.current?.reload();
|
|
return true;
|
|
}
|
|
return false;
|
|
}}
|
|
>
|
|
<ProFormText name="name" label="字典名称" rules={[{ required: true }]} />
|
|
<ProFormText name="type" label="字典类型" rules={[{ required: true }]} />
|
|
<ProFormText name="desc" label="描述" />
|
|
<ProFormSwitch name="status" label="状态" initialValue={true} />
|
|
</ModalForm>
|
|
|
|
<ModalForm
|
|
title={isDetailEdit ? '编辑详情' : '新增详情'}
|
|
open={detailModalVisible}
|
|
onOpenChange={setDetailModalVisible}
|
|
initialValues={currentDetail}
|
|
onFinish={async (values) => {
|
|
let res;
|
|
if (isDetailEdit) {
|
|
res = await updateSysDictionaryDetail({ ...currentDetail, ...values });
|
|
} else {
|
|
res = await createSysDictionaryDetail({ ...currentDetail, ...values });
|
|
}
|
|
if (res.code === 0) {
|
|
message.success(isDetailEdit ? '编辑成功' : '创建成功');
|
|
setDetailModalVisible(false);
|
|
detailActionRef.current?.reload();
|
|
return true;
|
|
}
|
|
return false;
|
|
}}
|
|
>
|
|
<ProFormText name="label" label="标签" rules={[{ required: true }]} />
|
|
<ProFormText name="value" label="值" rules={[{ required: true }]} />
|
|
<ProFormText name="extend" label="扩展" />
|
|
<ProFormText name="sort" label="排序" initialValue={0} />
|
|
<ProFormSwitch name="status" label="状态" initialValue={true} />
|
|
</ModalForm>
|
|
</PageContainer>
|
|
);
|
|
};
|
|
|
|
export default DictionaryPage;
|