From 85eeceb5c56ca2bfacb6012f876fcc26ebc68023 Mon Sep 17 00:00:00 2001 From: zichun Date: Fri, 8 May 2026 11:38:22 +0800 Subject: [PATCH] feat(usr): 用户列表搜索表单 + 分页表格 REQ-USR-003 --- frontend/src/api/usr.ts | 33 +++++++++++++++++++++++++++++++++ frontend/src/pages/usr/UserListPage.tsx | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ frontend/src/test/UserListPage.test.tsx | 26 +++++++++++++++++++++++++- 3 files changed, 140 insertions(+), 7 deletions(-) diff --git a/frontend/src/api/usr.ts b/frontend/src/api/usr.ts index e2a309a..91c3086 100644 --- a/frontend/src/api/usr.ts +++ b/frontend/src/api/usr.ts @@ -39,3 +39,36 @@ export function getPermissionGroups(): Promise { export function createUser(req: UserCreateReq): Promise { return request.post('/usr/users', req) } + +export interface UserListQueryReq { + queryField?: string + matchType?: string + queryValue?: string + page?: number + pageSize?: number +} + +export interface UserListItemVO { + sId: string + sUsername: string + sUserCode: string + sUserType: string + sLanguage: string + bIsDisabled: number + tLastLoginDate: string | null + sCreatorUsername: string | null + tCreateDate: string + sStaffName: string | null + sDepartment: string | null +} + +export interface PageVO { + total: number + page: number + pageSize: number + list: T[] +} + +export function getUserList(params?: UserListQueryReq): Promise> { + return request.get('/usr/users', { params }) +} diff --git a/frontend/src/pages/usr/UserListPage.tsx b/frontend/src/pages/usr/UserListPage.tsx index 94c3963..f782673 100644 --- a/frontend/src/pages/usr/UserListPage.tsx +++ b/frontend/src/pages/usr/UserListPage.tsx @@ -1,14 +1,80 @@ -import { useState } from 'react' -import { Table } from 'antd' +import { useState, useEffect } from 'react' +import { Table, Select, Input, Button, Space } from 'antd' +import type { ColumnsType } from 'antd/es/table' import { PermButton } from '../../components/PermButton' import UserFormDrawer from './UserFormDrawer' +import { getUserList } from '../../api/usr' +import type { PageVO, UserListItemVO } from '../../api/usr' + +const QUERY_FIELDS = [ + { value: 'username', label: '用户名' }, + { value: 'staffName', label: '员工名' }, + { value: 'userCode', label: '用户号' }, + { value: 'department', label: '部门' }, + { value: 'userType', label: '用户类型' }, + { value: 'disabled', label: '作废' }, + { value: 'lastLoginDate', label: '登录日期' }, + { value: 'creator', label: '制单人' }, +] + +const MATCH_TYPES = [ + { value: 'contains', label: '包含' }, + { value: 'notContains', label: '不包含' }, + { value: 'equals', label: '等于' }, +] + +const columns: ColumnsType = [ + { title: '用户名', dataIndex: 'sUsername' }, + { title: '员工名', dataIndex: 'sStaffName' }, + { title: '用户号', dataIndex: 'sUserCode' }, + { title: '部门', dataIndex: 'sDepartment' }, + { title: '用户类型', dataIndex: 'sUserType' }, + { title: '语言', dataIndex: 'sLanguage' }, + { title: '作废', dataIndex: 'bIsDisabled', render: (v: number) => v ? '是' : '否' }, + { title: '登录日期', dataIndex: 'tLastLoginDate' }, + { title: '制单人', dataIndex: 'sCreatorUsername' }, + { title: '制单日期', dataIndex: 'tCreateDate' }, +] export default function UserListPage() { const [drawerOpen, setDrawerOpen] = useState(false) + const [data, setData] = useState | null>(null) + const [queryField, setQueryField] = useState('username') + const [matchType, setMatchType] = useState('contains') + const [queryValue, setQueryValue] = useState('') + const [currentPage, setCurrentPage] = useState(1) + + const load = (pg = 1) => { + setCurrentPage(pg) + getUserList({ queryField, matchType, queryValue, page: pg, pageSize: 20 }).then(setData) + } + + useEffect(() => { + load() + }, []) return (
-
+ + + setQueryValue(e.target.value)} + placeholder="查询值" + style={{ width: 160 }} + /> + 新增 -
- + +
setDrawerOpen(false)} - onSuccess={() => setDrawerOpen(false)} + onSuccess={() => { setDrawerOpen(false); load(1) }} /> ) diff --git a/frontend/src/test/UserListPage.test.tsx b/frontend/src/test/UserListPage.test.tsx index 2a26bfa..17b0823 100644 --- a/frontend/src/test/UserListPage.test.tsx +++ b/frontend/src/test/UserListPage.test.tsx @@ -10,7 +10,8 @@ import UserListPage from '../pages/usr/UserListPage' vi.mock('../api/usr', () => ({ getStaffs: vi.fn().mockResolvedValue([]), getPermissionGroups: vi.fn().mockResolvedValue([]), - createUser: vi.fn() + createUser: vi.fn(), + getUserList: vi.fn().mockResolvedValue({ total: 0, page: 1, pageSize: 20, list: [] }) })) vi.mock('../api/request', () => ({ @@ -61,4 +62,27 @@ describe('UserListPage', () => { await userEvent.click(screen.getByRole('button', { name: /新\s*增/ })) await waitFor(() => expect(screen.getByText('新增用户')).toBeInTheDocument()) }) + + it('initialLoad_rendersTableRows', async () => { + const { getUserList } = await import('../api/usr') + vi.mocked(getUserList).mockResolvedValueOnce({ + total: 1, page: 1, pageSize: 20, + list: [{ + sId: 'u1', sUsername: 'alice', sUserCode: 'UC001', sUserType: '普通用户', + sLanguage: '中文', bIsDisabled: 0, tLastLoginDate: null, + sCreatorUsername: 'admin', tCreateDate: '2026-01-01T00:00:00', + sStaffName: '张三', sDepartment: '研发部' + }] + }) + renderPage('超级管理员') + await waitFor(() => expect(screen.getByText('alice')).toBeInTheDocument()) + expect(screen.getByText('张三')).toBeInTheDocument() + }) + + it('searchButton_callsGetUserList', async () => { + const { getUserList } = await import('../api/usr') + renderPage('超级管理员') + await userEvent.click(screen.getByRole('button', { name: /搜\s*索|搜索/ })) + await waitFor(() => expect(vi.mocked(getUserList)).toHaveBeenCalledTimes(2)) + }) }) -- libgit2 0.22.2