refactor: API口径统一 — 统计函数/员工列表/前端服务层
后端: - /dashboard/compliance-score 改用 getHealthCheck,与体检诊断同口径 - 新增 /employees/list 端点(不分页,供各页面下拉选择) - /employees/all-lite 增加 position 字段和 status 筛选参数 - getHealthCheck 未签合同改为查无合同记录的员工(非UNSIGNED类型) 前端: - 新建 lib/api-services.ts 统一 API 服务层 - employeeApi/rosterApi/dashboardApi/attendanceApi 统一封装 - 6个页面迁移到统一 API 调用: - Attendance: employeeApi.list + rosterApi.departments - Termination: rosterApi.list + rosterApi.departments - Money: rosterApi.list + rosterApi.departments - PortalQRModal: employeeApi.list - AIAssistant: 3处 employeeApi.list 替代 /roster?pageSize=999 - Contracts: rosterApi.departments - Dashboard: rosterApi.expiringContracts + dashboardApi.healthCheck/workforceStats
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* 统一 API 服务层
|
||||
* 所有页面应通过此模块调用 API,确保口径统一
|
||||
*/
|
||||
|
||||
import api from './api'
|
||||
|
||||
/** axios 拦截器已返回 response.data,但 TS 类型仍是 AxiosResponse,用 as any 绕过 */
|
||||
const get = ((url: string, config?: any) => api.get(url, config)) as any
|
||||
const post = ((url: string, data?: any, config?: any) => api.post(url, data, config)) as any
|
||||
const put = ((url: string, data?: any, config?: any) => api.put(url, data, config)) as any
|
||||
|
||||
/** 统一响应解析:返回一个回调函数,用于 .then() 中取 data 字段 */
|
||||
function unwrap<T>(): (res: any) => T {
|
||||
return (res: any) => (res?.data ?? res) as T
|
||||
}
|
||||
|
||||
// ========== 员工相关 ==========
|
||||
|
||||
export interface EmployeeOption {
|
||||
id: string
|
||||
name: string
|
||||
department?: string
|
||||
position?: string
|
||||
phone?: string
|
||||
gender?: string
|
||||
status?: string
|
||||
}
|
||||
|
||||
export const employeeApi = {
|
||||
/** 标准员工列表(不分页,供下拉选择等) */
|
||||
list: (params?: { status?: string; department?: string }) =>
|
||||
get('/employees/list', { params }).then(unwrap<EmployeeOption[]>()),
|
||||
/** 轻量级全量员工列表(含 RESIGNED) */
|
||||
allLite: (params?: { status?: string; department?: string }) =>
|
||||
get('/employees/all-lite', { params }).then(unwrap<EmployeeOption[]>()),
|
||||
/** 员工详情 */
|
||||
detail: (id: string) =>
|
||||
get(`/employees/${id}`).then(unwrap<any>()),
|
||||
/** 员工档案(花名册) */
|
||||
profile: (id: string) =>
|
||||
get(`/roster/${id}/profile`).then(unwrap<any>()),
|
||||
}
|
||||
|
||||
// ========== 花名册相关 ==========
|
||||
|
||||
export interface RosterParams {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
search?: string
|
||||
status?: string
|
||||
department?: string
|
||||
contractStatus?: string
|
||||
}
|
||||
|
||||
export interface RosterResponse {
|
||||
data: any[]
|
||||
pagination: { page: number; pageSize: number; total: number; totalPages: number }
|
||||
globalRiskStats?: { expiring: number; expired: number; unsigned: number }
|
||||
}
|
||||
|
||||
export const rosterApi = {
|
||||
/** 花名册分页列表 */
|
||||
list: (params: RosterParams) =>
|
||||
get('/roster', { params }) as Promise<RosterResponse>,
|
||||
/** 部门列表 */
|
||||
departments: () =>
|
||||
get('/roster/departments').then(unwrap<string[]>()),
|
||||
/** 合同类型 */
|
||||
contractTypes: () =>
|
||||
get('/roster/contract-types').then(unwrap<any[]>()),
|
||||
/** 即将到期合同 */
|
||||
expiringContracts: () =>
|
||||
get('/roster/contracts/expiring').then(unwrap<any[]>()),
|
||||
/** 违纪记录 */
|
||||
disciplinary: (employeeId: string) =>
|
||||
get(`/roster/${employeeId}/disciplinary`).then(unwrap<any[]>()),
|
||||
/** 证据链 */
|
||||
evidenceChain: (employeeId: string) =>
|
||||
get(`/roster/${employeeId}/evidence-chain`).then(unwrap<any>()),
|
||||
}
|
||||
|
||||
// ========== 仪表盘相关 ==========
|
||||
|
||||
export const dashboardApi = {
|
||||
/** 仪表盘主数据 */
|
||||
data: () =>
|
||||
get('/dashboard').then(unwrap<any>()),
|
||||
/** 用工体检诊断(6 维度,与评分标准一致) */
|
||||
healthCheck: () =>
|
||||
get('/dashboard/health-check').then(unwrap<any>()),
|
||||
/** 体检诊断历史 */
|
||||
healthCheckHistory: () =>
|
||||
get('/dashboard/health-check/history').then(unwrap<any[]>()),
|
||||
/** 风险中心(与工作台同口径) */
|
||||
risks: () =>
|
||||
get('/dashboard/risks').then(unwrap<any[]>()),
|
||||
/** 月度日历 */
|
||||
calendar: (month: string) =>
|
||||
get(`/dashboard/calendar?month=${month}`).then(unwrap<any>()),
|
||||
/** 成本分析 */
|
||||
costAnalysis: (month: string) =>
|
||||
get(`/dashboard/cost-analysis?month=${month}`).then(unwrap<any>()),
|
||||
/** 人力信息总览 */
|
||||
workforceStats: () =>
|
||||
get('/dashboard/workforce-stats').then(unwrap<any>()),
|
||||
/** 下一步行动 */
|
||||
nextActions: () =>
|
||||
get('/dashboard/workspace/next-actions').then(unwrap<any>()),
|
||||
/** 入离职统计 */
|
||||
turnoverStats: (months = 12) =>
|
||||
get(`/dashboard/turnover-stats?months=${months}`).then(unwrap<any>()),
|
||||
/** 绩效统计 */
|
||||
performanceStats: (period: string) =>
|
||||
get(`/dashboard/performance-stats?period=${period}`).then(unwrap<any>()),
|
||||
/** 年度价值报告 */
|
||||
annualValue: (year: number) =>
|
||||
get(`/dashboard/annual-value?year=${year}`).then(unwrap<any>()),
|
||||
/** 年度价值报告历史 */
|
||||
annualValueHistory: () =>
|
||||
get('/dashboard/annual-value/history').then(unwrap<any[]>()),
|
||||
}
|
||||
|
||||
// ========== 考勤相关 ==========
|
||||
|
||||
export const attendanceApi = {
|
||||
list: (params: { month: string; department?: string; status?: string }) =>
|
||||
get('/attendance', { params }).then(unwrap<any>()),
|
||||
stats: (month: string) =>
|
||||
get(`/attendance/stats?month=${month}`).then(unwrap<any>()),
|
||||
shifts: () =>
|
||||
get('/attendance/shifts').then(unwrap<any[]>()),
|
||||
shiftAssignments: (date: string) =>
|
||||
get(`/attendance/shift-assignments?date=${date}`).then(unwrap<any>()),
|
||||
daily: (date: string) =>
|
||||
get(`/attendance/daily?date=${date}`).then(unwrap<any>()),
|
||||
monthlyReport: (month: string) =>
|
||||
get(`/attendance/monthly-report?month=${month}`).then(unwrap<any>()),
|
||||
leaves: () =>
|
||||
get('/attendance/leaves').then(unwrap<any[]>()),
|
||||
publishRecords: () =>
|
||||
get('/attendance/publish-records').then(unwrap<any[]>()),
|
||||
}
|
||||
Reference in New Issue
Block a user