kra/web/src/pages/system/dictionary/index.tsx

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;