import axios from 'axios' import { unwrapApiResponse, unwrapNullableApiResponse } from '@/utils/api-response' import { request } from '@/utils/request' import type { ApiResponse, PageResult } from '@/types/common' import type { BackendCollection, BackendPage, CreateUserRequest, UpdateUserRequest, UserListResponse, UserQuery, UserRecord, UserResponseDto, } from './types' const useMockData = import.meta.env.VITE_USE_MOCK !== 'false' export const isUserMockEnabled = useMockData const mockRecords: UserRecord[] = [ { id: 'user-001', name: '张文静', account: 'zhangwenjing', department: '医务管理', role: '系统管理员', status: 'enabled', lastLoginAt: '2026-08-27 08:12', }, { id: 'user-002', name: '王医生', account: 'wangdoctor', department: '消化内科', role: '医生', status: 'enabled', lastLoginAt: '2026-08-27 08:35', }, { id: 'user-003', name: '李护士', account: 'linurse', department: '儿科急诊', role: '护士', status: 'disabled', lastLoginAt: '2026-08-20 14:26', }, ] function formatDateTime(value: string | null | undefined) { if (!value) { return '—' } const date = new Date(value) if (Number.isNaN(date.getTime())) { return value .replace('T', ' ') .replace(/\.\d+Z$/, '') .replace(/Z$/, '') } const pad = (part: number) => String(part).padStart(2, '0') return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad( date.getHours(), )}:${pad(date.getMinutes())}` } function normalizeStatus(value: string | null | undefined): UserRecord['status'] { return value === 'DISABLED' || value === 'INACTIVE' ? 'disabled' : 'enabled' } function mapUser(dto: UserResponseDto): UserRecord { return { id: dto.id, name: dto.displayName, account: dto.username, department: dto.departmentId ?? '未指定科室', role: '未分配角色', status: normalizeStatus(dto.status), lastLoginAt: formatDateTime(dto.lastLoginAt), employeeNo: dto.employeeNo, phone: dto.phone, email: dto.email, campusId: dto.campusId, departmentId: dto.departmentId, dataScope: dto.dataScope ?? '—', } } function normalizePage( data: BackendPage | T[], fallbackPage: number, fallbackPageSize: number, ): PageResult { const records = Array.isArray(data) ? data : (data.records ?? data.items ?? data.content ?? []) return { records, total: Array.isArray(data) ? records.length : (data.total ?? records.length), page: Array.isArray(data) ? fallbackPage : (data.page ?? fallbackPage), pageSize: Array.isArray(data) ? fallbackPageSize : (data.size ?? fallbackPageSize), } } function toBackendQuery(query: UserQuery) { const params: Record = { page: Math.max(query.page, 1), size: Math.min(Math.max(query.pageSize, 1), 200), } if (query.keyword?.trim()) { params.keyword = query.keyword.trim() } return params } export function getUsers(query: UserQuery): Promise { if (!useMockData) { return request .get>>('/v1/users', { params: toBackendQuery(query), }) .then((response) => { const page = normalizePage(unwrapApiResponse(response), query.page, query.pageSize) return { ...page, records: page.records.map(mapUser), } }) } const keyword = query.keyword?.trim().toLowerCase() const filteredRecords = mockRecords.filter((record) => { const matchesKeyword = !keyword || [record.name, record.account].join(' ').toLowerCase().includes(keyword) const matchesDepartment = !query.department || record.department === query.department const matchesStatus = !query.status || query.status === 'all' || record.status === query.status return matchesKeyword && matchesDepartment && matchesStatus }) const page = Math.max(query.page, 1) const pageSize = Math.max(query.pageSize, 1) const start = (page - 1) * pageSize return Promise.resolve({ records: filteredRecords.slice(start, start + pageSize), total: filteredRecords.length, page, pageSize, }) } export async function getUserDetail(id: string): Promise { if (useMockData) { const record = mockRecords.find((item) => item.id === id) return record ? { ...record } : null } try { const response = await request.get>( `/v1/users/${encodeURIComponent(id)}`, ) return mapUser(unwrapApiResponse(response)) } catch (error) { if (axios.isAxiosError(error) && error.response?.status === 404) { return null } throw error } } export function createUser(payload: CreateUserRequest): Promise { if (useMockData) { return Promise.reject(new Error('Mock 模式不执行用户写操作')) } return request .post>('/v1/users', payload) .then(unwrapApiResponse) .then(mapUser) } export function updateUser(id: string, payload: UpdateUserRequest): Promise { if (useMockData) { return Promise.reject(new Error('Mock 模式不执行用户写操作')) } return request .put>(`/v1/users/${encodeURIComponent(id)}`, payload) .then(unwrapApiResponse) .then(mapUser) } export function deleteUser(id: string): Promise { if (useMockData) { return Promise.reject(new Error('Mock 模式不执行用户写操作')) } return request .delete>(`/v1/users/${encodeURIComponent(id)}`) .then((response) => { unwrapNullableApiResponse(response) }) }