From 3090964b21361d39e3b63aa18667095020c7d01f Mon Sep 17 00:00:00 2001 From: zichun Date: Fri, 8 May 2026 11:02:13 +0800 Subject: [PATCH] feat(usr): 前端 UserListPage + UserFormDrawer + usr.ts + PermButton REQ-USR-001 --- frontend/src/App.tsx | 2 ++ frontend/src/api/usr.ts | 41 +++++++++++++++++++++++++++++++++++++++++ frontend/src/components/PermButton.tsx | 12 ++++++++++++ frontend/src/pages/usr/UserFormDrawer.tsx | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ frontend/src/pages/usr/UserListPage.tsx | 28 ++++++++++++++++++++++++++++ frontend/src/test/UserListPage.test.tsx | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 270 insertions(+), 0 deletions(-) create mode 100644 frontend/src/api/usr.ts create mode 100644 frontend/src/components/PermButton.tsx create mode 100644 frontend/src/pages/usr/UserFormDrawer.tsx create mode 100644 frontend/src/pages/usr/UserListPage.tsx create mode 100644 frontend/src/test/UserListPage.test.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index fdbe5e1..e91309e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,6 +1,7 @@ import { Navigate, Route, Routes } from 'react-router-dom' import { useAppSelector } from './store/hooks' import LoginPage from './pages/usr/LoginPage' +import UserListPage from './pages/usr/UserListPage' function PrivateRoute({ children }: { children: React.ReactNode }) { const accessToken = useAppSelector(s => s.auth.accessToken) @@ -12,6 +13,7 @@ export default function App() { } />
主页(待实现)
} /> + } /> } />
) diff --git a/frontend/src/api/usr.ts b/frontend/src/api/usr.ts new file mode 100644 index 0000000..e2a309a --- /dev/null +++ b/frontend/src/api/usr.ts @@ -0,0 +1,41 @@ +import request from './request' + +export interface StaffVO { + sId: string + sStaffName: string +} + +export interface PermissionGroupVO { + sId: string + sGroupCode: string + sGroupName: string + sCategory: string | null +} + +export interface UserCreateReq { + userCode: string + username: string + userType: '普通用户' | '超级管理员' + language: '中文' | '英文' | '繁体' + canEditDoc?: boolean + employeeId?: string | null + permGroupIds?: string[] +} + +export interface UserCreateResp { + userId: string + userCode: string + username: string +} + +export function getStaffs(): Promise { + return request.get('/usr/users/staffs') +} + +export function getPermissionGroups(): Promise { + return request.get('/usr/users/permission-groups') +} + +export function createUser(req: UserCreateReq): Promise { + return request.post('/usr/users', req) +} diff --git a/frontend/src/components/PermButton.tsx b/frontend/src/components/PermButton.tsx new file mode 100644 index 0000000..f6e4e8a --- /dev/null +++ b/frontend/src/components/PermButton.tsx @@ -0,0 +1,12 @@ +import { Button, ButtonProps } from 'antd' +import { useAppSelector } from '../store/hooks' + +interface PermButtonProps extends ButtonProps { + permission: string +} + +export function PermButton({ permission: _permission, children, ...props }: PermButtonProps) { + const userType = useAppSelector(s => s.auth.userInfo?.userType) + if (userType !== '超级管理员') return null + return +} diff --git a/frontend/src/pages/usr/UserFormDrawer.tsx b/frontend/src/pages/usr/UserFormDrawer.tsx new file mode 100644 index 0000000..9d2b503 --- /dev/null +++ b/frontend/src/pages/usr/UserFormDrawer.tsx @@ -0,0 +1,123 @@ +import { useEffect, useState } from 'react' +import { + Drawer, Form, Input, Select, Checkbox, Button, message, Table +} from 'antd' +import type { ColumnsType } from 'antd/es/table' +import { getStaffs, getPermissionGroups, createUser, StaffVO, PermissionGroupVO, UserCreateReq } from '../../api/usr' + +interface Props { + open: boolean + onClose: () => void + onSuccess: () => void +} + +export default function UserFormDrawer({ open, onClose, onSuccess }: Props) { + const [form] = Form.useForm() + const [staffs, setStaffs] = useState([]) + const [permGroups, setPermGroups] = useState([]) + const [selectedPermIds, setSelectedPermIds] = useState([]) + const [submitting, setSubmitting] = useState(false) + + useEffect(() => { + if (open) { + getStaffs().then(setStaffs).catch(() => {}) + getPermissionGroups().then(setPermGroups).catch(() => {}) + } + }, [open]) + + const permColumns: ColumnsType = [ + { + title: '', + key: 'select', + width: 40, + render: (_, record) => ( + { + setSelectedPermIds(prev => + e.target.checked ? [...prev, record.sId] : prev.filter(id => id !== record.sId) + ) + }} + /> + ) + }, + { title: '权限组', dataIndex: 'sGroupName' }, + { title: '分类', dataIndex: 'sCategory' } + ] + + async function handleSubmit() { + try { + const values = await form.validateFields() + setSubmitting(true) + const req: UserCreateReq = { + userCode: values.userCode, + username: values.username, + userType: values.userType, + language: values.language, + canEditDoc: values.canEditDoc ?? false, + employeeId: values.employeeId ?? null, + permGroupIds: selectedPermIds + } + await createUser(req) + message.success('新增用户成功') + form.resetFields() + setSelectedPermIds([]) + onSuccess() + } catch (e: unknown) { + if (e instanceof Error) { + message.error(e.message) + } + } finally { + setSubmitting(false) + } + } + + return ( + + + + + } + > +
+ + + + + + + + + + + 可编辑文档 + + +