Files
goalfylearning-admin-web/src/pages/SystemConfigs.tsx

284 lines
7.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from 'react';
import {
Table,
Button,
Modal,
Form,
Input,
Tag,
Space,
Popconfirm,
message,
Row,
Col,
Card,
} from 'antd';
import {
PlusOutlined,
EditOutlined,
DeleteOutlined,
CheckCircleOutlined,
StopOutlined,
} from '@ant-design/icons';
import type { SystemConfig } from '../types/systemConfig';
import {
getSystemConfigList,
createSystemConfig,
updateSystemConfig,
deleteSystemConfig,
updateSystemConfigStatus,
} from '../services/systemConfigApi';
export default function SystemConfigs() {
const [loading, setLoading] = useState(false);
const [list, setList] = useState<SystemConfig[]>([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [size, setSize] = useState(10);
const [editOpen, setEditOpen] = useState(false);
const [editing, setEditing] = useState<SystemConfig | null>(null);
const [createOpen, setCreateOpen] = useState(false);
const [form] = Form.useForm();
const [createForm] = Form.useForm();
const fetchList = async () => {
setLoading(true);
try {
const res = await getSystemConfigList({ page, size });
setList(res?.data ?? []);
setTotal(res?.total ?? 0);
} catch (e) {
message.error('获取列表失败');
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchList();
}, [page, size]);
const openEdit = (config: SystemConfig) => {
setEditing(config);
form.setFieldsValue({
name: config.name,
value: config.value,
type: config.type,
desc: config.desc,
});
setEditOpen(true);
};
const submitEdit = async () => {
try {
const values = await form.validateFields();
if (!editing) return;
await updateSystemConfig(editing.id, values);
message.success('更新成功');
setEditOpen(false);
fetchList();
} catch (error) {
message.error('更新失败');
}
};
const openCreate = () => {
createForm.resetFields();
setCreateOpen(true);
};
const submitCreate = async () => {
try {
const values = await createForm.validateFields();
await createSystemConfig(values);
message.success('创建成功');
setCreateOpen(false);
fetchList();
} catch (error: any) {
message.error(error?.response?.data?.message || '创建失败');
}
};
const handleDelete = async (config: SystemConfig) => {
try {
await deleteSystemConfig(config.id);
message.success('删除成功');
fetchList();
} catch (error) {
message.error('删除失败');
}
};
const handleToggleStatus = async (config: SystemConfig) => {
try {
const newStatus = config.status === 1 ? 0 : 1;
await updateSystemConfigStatus(config.id, { status: newStatus });
message.success(newStatus === 1 ? '已启用' : '已禁用');
fetchList();
} catch (error) {
message.error('状态更新失败');
}
};
const columns = [
{
title: '配置标识',
dataIndex: 'key',
key: 'key',
width: 200,
},
{
title: '配置名称',
dataIndex: 'name',
key: 'name',
width: 150,
},
{
title: '配置值',
dataIndex: 'value',
key: 'value',
ellipsis: true,
},
{
title: '配置描述',
dataIndex: 'desc',
key: 'desc',
ellipsis: true,
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 80,
render: (value: number) =>
value === 1 ? <Tag color="green"></Tag> : <Tag color="red"></Tag>,
},
{
title: '操作',
key: 'action',
width: 250,
render: (_: any, config: SystemConfig) => (
<Space>
<Button type="link" icon={<EditOutlined />} onClick={() => openEdit(config)}>
</Button>
<Button
type="link"
icon={config.status === 1 ? <StopOutlined /> : <CheckCircleOutlined />}
onClick={() => handleToggleStatus(config)}
>
{config.status === 1 ? '禁用' : '启用'}
</Button>
<Popconfirm title="确定删除该配置?" onConfirm={() => handleDelete(config)}>
<Button type="link" danger icon={<DeleteOutlined />}>
</Button>
</Popconfirm>
</Space>
),
},
];
return (
<div>
<Row gutter={16} style={{ marginBottom: 16 }}>
<Col span={24}>
<Card>
<div style={{ marginBottom: 16 }}>
<Button type="primary" icon={<PlusOutlined />} onClick={openCreate}>
</Button>
</div>
<Table
dataSource={list}
columns={columns}
rowKey="id"
loading={loading}
pagination={{
current: page,
pageSize: size,
total: total,
onChange: (p, s) => {
setPage(p);
setSize(s);
},
}}
/>
</Card>
</Col>
</Row>
{/* 编辑弹窗 */}
<Modal
title="编辑配置"
open={editOpen}
onOk={submitEdit}
onCancel={() => setEditOpen(false)}
width={600}
>
<Form form={form} layout="vertical">
<Form.Item
name="name"
label="配置名称"
rules={[{ required: true, message: '请输入配置名称' }]}
>
<Input placeholder="请输入配置名称" />
</Form.Item>
<Form.Item
name="value"
label="配置值"
rules={[{ required: true, message: '请输入配置值' }]}
>
<Input.TextArea rows={4} placeholder="请输入配置值" />
</Form.Item>
<Form.Item name="type" label="配置类型">
<Input placeholder="请输入配置类型string, int, bool, json" />
</Form.Item>
<Form.Item name="desc" label="配置描述">
<Input.TextArea rows={3} placeholder="请输入配置描述" />
</Form.Item>
</Form>
</Modal>
{/* 创建弹窗 */}
<Modal
title="新建配置"
open={createOpen}
onOk={submitCreate}
onCancel={() => setCreateOpen(false)}
width={600}
>
<Form form={createForm} layout="vertical">
<Form.Item
name="key"
label="配置标识"
rules={[{ required: true, message: '请输入配置标识' }]}
>
<Input placeholder="请输入配置标识唯一app_name" />
</Form.Item>
<Form.Item
name="name"
label="配置名称"
rules={[{ required: true, message: '请输入配置名称' }]}
>
<Input placeholder="请输入配置名称" />
</Form.Item>
<Form.Item
name="value"
label="配置值"
rules={[{ required: true, message: '请输入配置值' }]}
>
<Input.TextArea rows={4} placeholder="请输入配置值" />
</Form.Item>
<Form.Item name="type" label="配置类型">
<Input placeholder="请输入配置类型string, int, bool, json" />
</Form.Item>
<Form.Item name="desc" label="配置描述">
<Input.TextArea rows={3} placeholder="请输入配置描述" />
</Form.Item>
</Form>
</Modal>
</div>
);
}