初步增加 web 界面

This commit is contained in:
yml2213
2026-06-22 13:11:15 +08:00
parent 4c924375aa
commit 347edb8103
66 changed files with 6816 additions and 21 deletions
+164
View File
@@ -0,0 +1,164 @@
import { useEffect, useState } from 'react';
import {
Table, Button, Modal, Form, Input, Select, Tag, Popconfirm, message, Space,
} from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
import { userApi, type UserInfo } from '../api/modules';
const ROLE_OPTIONS = [
{ value: 'super_admin', label: '超级管理员' },
{ value: 'operation', label: '运营' },
{ value: 'support', label: '客服' },
];
const ROLE_COLORS: Record<string, string> = {
super_admin: 'red',
operation: 'blue',
support: 'green',
};
export default function UsersPage() {
const [users, setUsers] = useState<UserInfo[]>([]);
const [loading, setLoading] = useState(false);
const [modalOpen, setModalOpen] = useState(false);
const [editing, setEditing] = useState<UserInfo | null>(null);
const [form] = Form.useForm();
const loadUsers = async () => {
setLoading(true);
try {
const data = await userApi.list();
setUsers(data);
} catch (e: any) {
message.error(e.message);
} finally {
setLoading(false);
}
};
useEffect(() => {
loadUsers();
}, []);
const handleCreate = () => {
setEditing(null);
form.resetFields();
form.setFieldsValue({ role: 'support' });
setModalOpen(true);
};
const handleEdit = (user: UserInfo) => {
setEditing(user);
form.setFieldsValue({
username: user.username,
role: user.role,
remark: user.remark,
});
setModalOpen(true);
};
const handleSave = async () => {
try {
const values = await form.validateFields();
if (editing) {
const updateData: any = { role: values.role, remark: values.remark };
if (values.password) updateData.password = values.password;
await userApi.update(editing.id, updateData);
message.success('已更新');
} else {
await userApi.create(values);
message.success('已创建');
}
setModalOpen(false);
loadUsers();
} catch (e: any) {
message.error(e.message);
}
};
const handleDelete = async (id: number) => {
try {
await userApi.delete(id);
message.success('已删除');
loadUsers();
} catch (e: any) {
message.error(e.message);
}
};
const columns = [
{ title: 'ID', dataIndex: 'id', width: 60 },
{ title: '用户名', dataIndex: 'username' },
{
title: '角色',
dataIndex: 'role',
render: (role: string) => {
const label = ROLE_OPTIONS.find((r) => r.value === role)?.label || role;
return <Tag color={ROLE_COLORS[role] || 'default'}>{label}</Tag>;
},
},
{
title: '状态',
dataIndex: 'is_active',
render: (active: boolean) => active ? <Tag color="green"></Tag> : <Tag></Tag>,
},
{ title: '备注', dataIndex: 'remark' },
{
title: '操作',
width: 160,
render: (_: any, record: UserInfo) => (
<Space>
<Button size="small" icon={<EditOutlined />} onClick={() => handleEdit(record)}></Button>
{record.role !== 'super_admin' && (
<Popconfirm title="确认删除?" onConfirm={() => handleDelete(record.id)}>
<Button danger size="small" icon={<DeleteOutlined />}></Button>
</Popconfirm>
)}
</Space>
),
},
];
return (
<div>
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between' }}>
<h2></h2>
<Button type="primary" icon={<PlusOutlined />} onClick={handleCreate}></Button>
</div>
<Table
columns={columns}
dataSource={users}
rowKey="id"
loading={loading}
size="small"
pagination={{ pageSize: 20 }}
/>
<Modal
title={editing ? '编辑用户' : '新建用户'}
open={modalOpen}
onCancel={() => setModalOpen(false)}
onOk={handleSave}
okText="保存"
>
<Form form={form} layout="vertical">
<Form.Item name="username" label="用户名" rules={[{ required: true, message: '请输入用户名' }]}>
<Input disabled={!!editing} />
</Form.Item>
<Form.Item
name="password"
label={editing ? '新密码(留空不修改)' : '密码'}
rules={editing ? [] : [{ required: true, message: '请输入密码' }]}
>
<Input.Password />
</Form.Item>
<Form.Item name="role" label="角色" rules={[{ required: true }]}>
<Select options={ROLE_OPTIONS} />
</Form.Item>
<Form.Item name="remark" label="备注">
<Input />
</Form.Item>
</Form>
</Modal>
</div>
);
}