35ee138f29
antd 新版本将 destroyOnClose 重命名为 destroyOnHidden, 消除控制台废弃警告。涉及 user、menu、notify、dict、config 页面。
109 lines
6.8 KiB
TypeScript
109 lines
6.8 KiB
TypeScript
import { useState, useEffect } from 'react'
|
|
import { Table, Button, Modal, Form, Input, InputNumber, Select, Tag, Space, message, Popconfirm, Card, Row, Col } from 'antd'
|
|
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'
|
|
import type { ColumnsType } from 'antd/es/table'
|
|
import { dictApi } from '@/api/dict'
|
|
import type { DictType, DictData, CreateDictTypeRequest, CreateDictDataRequest, UpdateDictTypeRequest, UpdateDictDataRequest } from '@/api/dict'
|
|
|
|
export default function DictManagement() {
|
|
const [dictTypes, setDictTypes] = useState<DictType[]>([])
|
|
const [dictData, setDictData] = useState<DictData[]>([])
|
|
const [selectedType, setSelectedType] = useState<string>('')
|
|
const [loading, setLoading] = useState(false)
|
|
const [typeModalOpen, setTypeModalOpen] = useState(false)
|
|
const [dataModalOpen, setDataModalOpen] = useState(false)
|
|
const [editingType, setEditingType] = useState<DictType | null>(null)
|
|
const [editingData, setEditingData] = useState<DictData | null>(null)
|
|
const [typeForm] = Form.useForm()
|
|
const [dataForm] = Form.useForm()
|
|
|
|
useEffect(() => { loadDictTypes() }, [])
|
|
|
|
async function loadDictTypes() {
|
|
try { const res = await dictApi.getTypes(); setDictTypes(Array.isArray(res) ? res : []) } catch { /* ignored */ }
|
|
}
|
|
async function loadDictData(dictType: string) {
|
|
setLoading(true)
|
|
try { const res = await dictApi.getDataByType(dictType); setDictData(Array.isArray(res) ? res : []) } catch { /* ignored */ }
|
|
finally { setLoading(false) }
|
|
}
|
|
|
|
function handleSelectType(type: string) { setSelectedType(type); loadDictData(type) }
|
|
|
|
async function handleTypeSubmit() {
|
|
try {
|
|
const values = await typeForm.validateFields()
|
|
if (editingType) { await dictApi.updateType(editingType.id, values as UpdateDictTypeRequest); message.success('更新成功') }
|
|
else { await dictApi.createType(values as CreateDictTypeRequest); message.success('创建成功') }
|
|
setTypeModalOpen(false); loadDictTypes()
|
|
} catch { /* ignored */ }
|
|
}
|
|
async function handleDataSubmit() {
|
|
try {
|
|
const values = await dataForm.validateFields()
|
|
if (editingData) { await dictApi.updateData(editingData.id, { ...values, dictType: selectedType } as UpdateDictDataRequest); message.success('更新成功') }
|
|
else { await dictApi.createData({ ...values, dictType: selectedType } as CreateDictDataRequest); message.success('创建成功') }
|
|
setDataModalOpen(false); loadDictData(selectedType)
|
|
} catch { /* ignored */ }
|
|
}
|
|
|
|
const typeColumns: ColumnsType<DictType> = [
|
|
{ title: '字典名称', dataIndex: 'dictName', key: 'dictName' },
|
|
{ title: '字典类型', dataIndex: 'dictType', key: 'dictType', render: (v: string) => <a onClick={() => handleSelectType(v)}>{v}</a> },
|
|
{ title: '状态', dataIndex: 'status', key: 'status', render: (v: number) => <Tag color={v === 1 ? 'green' : 'red'}>{v === 1 ? '正常' : '停用'}</Tag> },
|
|
{ title: '操作', key: 'action', render: (_, record) => (
|
|
<Space>
|
|
<Button type="link" icon={<EditOutlined />} onClick={() => { setEditingType(record); typeForm.setFieldsValue(record); setTypeModalOpen(true) }} />
|
|
<Popconfirm title="确认删除?" onConfirm={async () => { await dictApi.deleteType(record.id); message.success('删除成功'); loadDictTypes() }}><Button type="link" danger icon={<DeleteOutlined />} /></Popconfirm>
|
|
</Space>
|
|
)},
|
|
]
|
|
const dataColumns: ColumnsType<DictData> = [
|
|
{ title: '字典标签', dataIndex: 'dictLabel', key: 'dictLabel' },
|
|
{ title: '字典值', dataIndex: 'dictValue', key: 'dictValue' },
|
|
{ title: '排序', dataIndex: 'sort', key: 'sort', width: 80 },
|
|
{ title: '状态', dataIndex: 'status', key: 'status', render: (v: number) => <Tag color={v === 1 ? 'green' : 'red'}>{v === 1 ? '正常' : '停用'}</Tag> },
|
|
{ title: '操作', key: 'action', render: (_, record) => (
|
|
<Space>
|
|
<Button type="link" icon={<EditOutlined />} onClick={() => { setEditingData(record); dataForm.setFieldsValue(record); setDataModalOpen(true) }} />
|
|
<Popconfirm title="确认删除?" onConfirm={async () => { await dictApi.deleteData(record.id); message.success('删除成功'); loadDictData(selectedType) }}><Button type="link" danger icon={<DeleteOutlined />} /></Popconfirm>
|
|
</Space>
|
|
)},
|
|
]
|
|
|
|
return (
|
|
<div style={{ padding: 24 }}>
|
|
<Row gutter={16}>
|
|
<Col span={10}>
|
|
<Card title="字典类型" extra={<Button type="primary" icon={<PlusOutlined />} onClick={() => { setEditingType(null); typeForm.resetFields(); setTypeModalOpen(true) }}>新增</Button>}>
|
|
<Table<DictType> rowKey="id" columns={typeColumns} dataSource={dictTypes} pagination={false} size="small" />
|
|
</Card>
|
|
</Col>
|
|
<Col span={14}>
|
|
<Card title={`字典数据 ${selectedType ? `- ${selectedType}` : ''}`} extra={selectedType ? <Button type="primary" icon={<PlusOutlined />} onClick={() => { setEditingData(null); dataForm.resetFields(); setDataModalOpen(true) }}>新增</Button> : null}>
|
|
{selectedType ? <Table<DictData> rowKey="id" columns={dataColumns} dataSource={dictData} loading={loading} pagination={false} size="small" /> : <p style={{ color: '#999', textAlign: 'center' }}>请选择左侧字典类型</p>}
|
|
</Card>
|
|
</Col>
|
|
</Row>
|
|
|
|
<Modal title={editingType ? '编辑字典类型' : '新增字典类型'} open={typeModalOpen} onOk={handleTypeSubmit} onCancel={() => setTypeModalOpen(false)} destroyOnHidden>
|
|
<Form form={typeForm} layout="vertical">
|
|
<Form.Item name="dictName" label="字典名称" rules={[{ required: true }]}><Input /></Form.Item>
|
|
<Form.Item name="dictType" label="字典类型" rules={[{ required: true }]}><Input /></Form.Item>
|
|
<Form.Item name="status" label="状态" initialValue={1}><Select options={[{ label: '正常', value: 1 }, { label: '停用', value: 0 }]} /></Form.Item>
|
|
<Form.Item name="remark" label="备注"><Input.TextArea /></Form.Item>
|
|
</Form>
|
|
</Modal>
|
|
<Modal title={editingData ? '编辑字典数据' : '新增字典数据'} open={dataModalOpen} onOk={handleDataSubmit} onCancel={() => setDataModalOpen(false)} destroyOnHidden>
|
|
<Form form={dataForm} layout="vertical">
|
|
<Form.Item name="dictLabel" label="字典标签" rules={[{ required: true }]}><Input /></Form.Item>
|
|
<Form.Item name="dictValue" label="字典值" rules={[{ required: true }]}><Input /></Form.Item>
|
|
<Form.Item name="sort" label="排序" initialValue={0}><InputNumber min={0} style={{ width: '100%' }} /></Form.Item>
|
|
<Form.Item name="status" label="状态" initialValue={1}><Select options={[{ label: '正常', value: 1 }, { label: '停用', value: 0 }]} /></Form.Item>
|
|
<Form.Item name="remark" label="备注"><Input.TextArea /></Form.Item>
|
|
</Form>
|
|
</Modal>
|
|
</div>
|
|
)
|
|
}
|