From 14f6af35d8c95c2a3daf7e1003ead51e4f5e14f9 Mon Sep 17 00:00:00 2001 From: ZhuRui Date: Thu, 30 Jul 2026 11:16:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AF=B9=E6=8E=A5=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=AD=97=E6=AE=B5=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/users/index.ts | 53 ++++++ src/api/users/types.ts | 59 +++++++ src/config/mock/userList.ts | 177 +++++++++++++++++++ src/pages/events/users/index.tsx | 68 +++++-- src/pages/events/users/model/useUserModel.ts | 127 +++++++------ 5 files changed, 399 insertions(+), 85 deletions(-) create mode 100644 src/api/users/index.ts create mode 100644 src/api/users/types.ts create mode 100644 src/config/mock/userList.ts diff --git a/src/api/users/index.ts b/src/api/users/index.ts new file mode 100644 index 0000000..eed37dc --- /dev/null +++ b/src/api/users/index.ts @@ -0,0 +1,53 @@ +/** + * 用户管理 API + */ +import { get, post } from '@/utils/request'; +import { USE_MOCK, MOCK_DELAY } from '@/config/mock'; +import { buildMockUserListPage } from '@/config/mock/userList'; +import type { + UserListQueryParams, + UserActiveParams, + TournamentAdminUserPageVO, + PageData, + ApiResult, +} from './types'; + +export type { + TournamentAdminUserPageVO, + UserListQueryParams, + UserActiveParams, + PageData, + ApiResult, +} from './types'; + +const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +/** + * 用户管理 - 用户分页 + * GET /admin/manager/user/page → /manager/user/page + */ +export async function getUserList( + params: UserListQueryParams, +): Promise>> { + if (USE_MOCK) { + await delay(MOCK_DELAY); + const page = Number(params.page) || 1; + const limit = Number(params.limit) || 10; + return { + code: 200, + msg: 'success', + data: buildMockUserListPage(page, limit), + }; + } + return get('/manager/user/page', params as Record); +} + +/** + * 用户管理 - 启用/禁用 + * POST /admin/manager/user/active → /manager/user/active + */ +export function toggleUserActive( + params: UserActiveParams, +): Promise>> { + return post('/manager/user/active', params); +} diff --git a/src/api/users/types.ts b/src/api/users/types.ts new file mode 100644 index 0000000..c30fc2a --- /dev/null +++ b/src/api/users/types.ts @@ -0,0 +1,59 @@ +/** + * 用户管理 — 类型定义 + * 对应 OpenAPI: /admin/manager/user/page + */ + +/** 用户列表项 */ +export interface TournamentAdminUserPageVO { + /** 用户ID(接口实际返回 string) */ + id: string; + /** 昵称 */ + nickname: string; + /** 手机号 */ + phone: string; + /** 真实姓名 */ + realName: string; + /** 证件号 */ + idCard: string; + /** 证件号图片 */ + idCardImg: string; + /** 证件号图片列表 */ + idCardImgList: string[]; + /** 状态;0=禁用、1=正常(接口实际返回 string) */ + status: string; + /** 创建时间 */ + createTime: string; +} + +/** 用户列表查询参数 */ +export interface UserListQueryParams { + page?: string; + limit?: string; + /** 用户昵称 */ + nickname?: string; + /** 用户手机号 */ + phone?: string; + /** 状态;不传=全部、0=禁用、1=正常 */ + status?: string; +} + +/** 启用/禁用请求参数 */ +export interface UserActiveParams { + /** 用户ID */ + userId: string; + /** 0=禁用、1=正常 */ + status: string; +} + +/** 分页数据 */ +export interface PageData { + total: number; + list: T[]; +} + +/** 统一响应包裹 */ +export interface ApiResult { + code: number; + msg: string; + data: T; +} diff --git a/src/config/mock/userList.ts b/src/config/mock/userList.ts new file mode 100644 index 0000000..d51b3be --- /dev/null +++ b/src/config/mock/userList.ts @@ -0,0 +1,177 @@ +/** + * 用户列表页假数据 + * + * 使用页面:`src/pages/events/users/index.tsx` + * 对应接口:`GET /manager/user/page` + * 类型:`TournamentAdminUserPageVO[]` + * + * 注意:为避免循环引用(api/users/index.ts → 此文件 → api/users/types), + * 此文件不 import 任何 api 层类型,接口定义内联。 + */ + +interface MockUserVO { + id: string; + nickname: string; + phone: string; + realName: string; + idCard: string; + idCardImg: string; + idCardImgList: string[]; + status: string; + createTime: string; +} + +interface MockPageData { + total: number; + list: T[]; +} + +export const MOCK_USER_LIST: MockUserVO[] = [ + { + id: '1', + nickname: '羽毛球小将', + phone: '13800138001', + realName: '张三', + idCard: '320101199001011234', + idCardImg: '', + idCardImgList: [ + 'https://picsum.photos/seed/uid1a/96/64', + 'https://picsum.photos/seed/uid1b/96/64', + ], + status: '1', + createTime: '2026-07-20 08:11:07', + }, + { + id: '2', + nickname: '马拉松达人', + phone: '13900139002', + realName: '李四', + idCard: '320101199002022345', + idCardImg: 'https://picsum.photos/seed/uid2/96/64', + idCardImgList: [], + status: '1', + createTime: '2026-07-19 11:28:20', + }, + { + id: '3', + nickname: '健身爱好者', + phone: '13700137003', + realName: '王五', + idCard: '320101199103033456', + idCardImg: '', + idCardImgList: ['https://picsum.photos/seed/uid3a/96/64'], + status: '1', + createTime: '2026-07-18 14:45:33', + }, + { + id: '4', + nickname: '游泳健将', + phone: '13600136004', + realName: '赵六', + idCard: '320101199204044567', + idCardImg: 'https://picsum.photos/seed/uid4/96/64', + idCardImgList: [], + status: '0', + createTime: '2026-07-17 18:02:46', + }, + { + id: '5', + nickname: '羽毛球小将', + phone: '13800138005', + realName: '孙七', + idCard: '320101199305055678', + idCardImg: '', + idCardImgList: [ + 'https://picsum.photos/seed/uid5a/96/64', + 'https://picsum.photos/seed/uid5b/96/64', + ], + status: '1', + createTime: '2026-07-16 21:19:59', + }, + { + id: '6', + nickname: '马拉松达人', + phone: '13900139006', + realName: '周八', + idCard: '320101199406066789', + idCardImg: 'https://picsum.photos/seed/uid6/96/64', + idCardImgList: [], + status: '1', + createTime: '2026-07-15 00:36:12', + }, + { + id: '7', + nickname: '健身爱好者', + phone: '13700137007', + realName: '吴九', + idCard: '320101199507077890', + idCardImg: '', + idCardImgList: [], + status: '1', + createTime: '2026-07-14 03:53:25', + }, + { + id: '8', + nickname: '游泳健将', + phone: '13600136008', + realName: '郑十', + idCard: '320101199608088901', + idCardImg: 'https://picsum.photos/seed/uid8/96/64', + idCardImgList: ['https://picsum.photos/seed/uid8a/96/64'], + status: '1', + createTime: '2026-07-13 07:10:38', + }, + { + id: '9', + nickname: '羽毛球小将', + phone: '13800138009', + realName: '陈一', + idCard: '320101199709099012', + idCardImg: '', + idCardImgList: [], + status: '1', + createTime: '2026-07-12 10:27:51', + }, + { + id: '10', + nickname: '马拉松达人', + phone: '13900139010', + realName: '刘二', + idCard: '320101199810100123', + idCardImg: 'https://picsum.photos/seed/uid10/96/64', + idCardImgList: ['https://picsum.photos/seed/uid10a/96/64'], + status: '0', + createTime: '2026-07-11 13:44:04', + }, + { + id: '11', + nickname: '健身爱好者', + phone: '13700137011', + realName: '黄三', + idCard: '320101199911111234', + idCardImg: '', + idCardImgList: [], + status: '1', + createTime: '2026-07-10 17:01:17', + }, + { + id: '12', + nickname: '游泳健将', + phone: '13600136012', + realName: '林四', + idCard: '320101200012122345', + idCardImg: '', + idCardImgList: [ + 'https://picsum.photos/seed/uid12a/96/64', + 'https://picsum.photos/seed/uid12b/96/64', + ], + status: '1', + createTime: '2026-07-09 20:18:30', + }, +]; + +export function buildMockUserListPage(page: number, limit: number): MockPageData { + const start = (page - 1) * limit; + const list = MOCK_USER_LIST.slice(start, start + limit); + return { total: MOCK_USER_LIST.length, list }; +} diff --git a/src/pages/events/users/index.tsx b/src/pages/events/users/index.tsx index dcfe083..c5b9003 100644 --- a/src/pages/events/users/index.tsx +++ b/src/pages/events/users/index.tsx @@ -1,4 +1,4 @@ -import { defineComponent } from 'vue'; +import { defineComponent, onMounted } from 'vue'; import { Button, Input, @@ -9,8 +9,11 @@ import { Image, Pagination, Modal, + message, } from 'ant-design-vue'; +import { EyeOutlined } from '@ant-design/icons-vue'; import { useUserModel, USER_STATUS_OPTIONS } from './model/useUserModel'; +import { toggleUserActive } from '@/api/users'; import { useContainerSize } from '@/hooks'; import pageStyles from '@/assets/styles/pageLayout.module.less'; @@ -28,23 +31,31 @@ function renderBodyCell({ record: any; onToggleStatus: (record: any) => void; }) { - // 证件图片:有则显示,无则不显示 - if (column.dataIndex === 'idImg') { - const images = record.idImg || []; - if (images.length === 0) { - return '-'; - } + // 证件图片:优先 idCardImgList,回退 idCardImg + if (column.dataIndex === 'idCardImg') { + const urls = record.idCardImgList?.length + ? record.idCardImgList + : record.idCardImg + ? [record.idCardImg] + : []; + if (urls.length === 0) return -; return ( - {images.map((src: string) => ( - + {urls.map((src: string) => ( + }} + /> ))} ); } if (column.key === 'action') { - const isActive = record.status === 'active'; + const isActive = record.status === '1'; return (