first commit

This commit is contained in:
rayd1o
2026-03-05 11:46:58 +08:00
commit e7033775d8
20657 changed files with 1988940 additions and 0 deletions

View 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