first commit
This commit is contained in:
157
frontend/src/pages/Users/Users.tsx
Normal file
157
frontend/src/pages/Users/Users.tsx
Normal file
@@ -0,0 +1,157 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Table, Button, Tag, Space, message, Modal, Form, Input, Select } from 'antd'
|
||||
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'
|
||||
import axios from 'axios'
|
||||
|
||||
interface User {
|
||||
id: number
|
||||
username: string
|
||||
email: string
|
||||
role: string
|
||||
is_active: boolean
|
||||
created_at: string
|
||||
}
|
||||
|
||||
function Users() {
|
||||
const [users, setUsers] = useState<User[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [modalVisible, setModalVisible] = useState(false)
|
||||
const [editingUser, setEditingUser] = useState<User | null>(null)
|
||||
const [form] = Form.useForm()
|
||||
|
||||
const fetchUsers = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await axios.get('/api/v1/users')
|
||||
setUsers(res.data.data || [])
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchUsers()
|
||||
}, [])
|
||||
|
||||
const handleAdd = () => {
|
||||
setEditingUser(null)
|
||||
form.resetFields()
|
||||
setModalVisible(true)
|
||||
}
|
||||
|
||||
const handleEdit = (user: User) => {
|
||||
setEditingUser(user)
|
||||
form.setFieldsValue(user)
|
||||
setModalVisible(true)
|
||||
}
|
||||
|
||||
const handleDelete = async (id: number) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确定要删除此用户吗?',
|
||||
onOk: async () => {
|
||||
await axios.delete(`/api/v1/users/${id}`)
|
||||
message.success('删除成功')
|
||||
fetchUsers()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const handleSubmit = async (values: Record<string, unknown>) => {
|
||||
try {
|
||||
if (editingUser) {
|
||||
await axios.put(`/api/v1/users/${editingUser.id}`, values)
|
||||
message.success('更新成功')
|
||||
} else {
|
||||
await axios.post('/api/v1/users', values)
|
||||
message.success('创建成功')
|
||||
}
|
||||
setModalVisible(false)
|
||||
fetchUsers()
|
||||
} catch (error: unknown) {
|
||||
const err = error as { response?: { data?: { detail?: string } } }
|
||||
message.error(err.response?.data?.detail || '操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{ title: 'ID', dataIndex: 'id', key: 'id', width: 80 },
|
||||
{ title: '用户名', dataIndex: 'username', key: 'username' },
|
||||
{ title: '邮箱', dataIndex: 'email', key: 'email' },
|
||||
{
|
||||
title: '角色',
|
||||
dataIndex: 'role',
|
||||
key: 'role',
|
||||
render: (role: string) => {
|
||||
const colors: Record<string, string> = {
|
||||
super_admin: 'red',
|
||||
admin: 'orange',
|
||||
operator: 'blue',
|
||||
viewer: 'green',
|
||||
}
|
||||
return <Tag color={colors[role] || 'default'}>{role}</Tag>
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'is_active',
|
||||
key: 'is_active',
|
||||
render: (active: boolean) => (
|
||||
<Tag color={active ? 'green' : 'red'}>{active ? '活跃' : '禁用'}</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
render: (_: unknown, record: User) => (
|
||||
<Space>
|
||||
<Button type="link" icon={<EditOutlined />} onClick={() => handleEdit(record)}>编辑</Button>
|
||||
<Button type="link" danger icon={<DeleteOutlined />} onClick={() => handleDelete(record.id)}>删除</Button>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between' }}>
|
||||
<h2>用户管理</h2>
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>添加用户</Button>
|
||||
</div>
|
||||
<Table columns={columns} dataSource={users} rowKey="id" loading={loading} />
|
||||
<Modal
|
||||
title={editingUser ? '编辑用户' : '添加用户'}
|
||||
open={modalVisible}
|
||||
onCancel={() => setModalVisible(false)}
|
||||
footer={null}
|
||||
>
|
||||
<Form form={form} onFinish={handleSubmit} layout="vertical">
|
||||
<Form.Item name="username" label="用户名" rules={[{ required: true }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="email" label="邮箱" rules={[{ required: true, type: 'email' }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
{!editingUser && (
|
||||
<Form.Item name="password" label="密码" rules={[{ required: true, min: 8 }]}>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item name="role" label="角色" rules={[{ required: true }]}>
|
||||
<Select>
|
||||
<Select.Option value="super_admin">超级管理员</Select.Option>
|
||||
<Select.Option value="admin">管理员</Select.Option>
|
||||
<Select.Option value="operator">操作员</Select.Option>
|
||||
<Select.Option value="viewer">只读用户</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" block>提交</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Users
|
||||
Reference in New Issue
Block a user