Files
TurboHR/frontend/src/lib/api-services.ts
T
selfrelease 7e720d9bfc feat: 北京解聘合规增强 — 政策法规库+地区过滤+工会回执证据链
1. 政策法规库(RAG知识库):
   - 新增6条北京地区单方解除劳动合同工作指引种子数据
   - 涵盖通知工会程序、函件内容要求、回执要求、监督提示函、仲裁审查等
   - 企业用户通过AI问答可检索到北京地区工会通知规定

2. 地区差异化合规检查:
   - getChecklistForReason 增加 orgCity 参数
   - 工会通知检查项仅北京地区显示(FAULT/NONFAULT/LAYOFF)
   - 前端解聘方式说明中北京工会提示仅北京地区动态显示
   - 非北京地区不显示工会通知检查项,避免误导

3. 工会回执上传+证据链留存:
   - 后端新增3个接口:上传回执文件、保存回执信息、获取回执信息
   - 回执信息保存到草稿 checklistOverrides
   - 自动追加到证据链(appendEvidence),作为劳动仲裁举证材料
   - 前端合规检查步骤增加工会回执上传区域
   - 确认提交步骤展示回执文件链接
   - 新增 uploads 静态文件服务

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-15 16:01:02 +08:00

1117 lines
43 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 统一 API 服务层
* 所有页面应通过此模块调用 API,确保口径统一
*/
import api from './api'
import axios from 'axios'
/** 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
const patch = ((url: string, data?: any, config?: any) => api.patch(url, data, config)) as any
const del = ((url: string, config?: any) => api.delete(url, config)) as any
/** 统一响应解析:返回一个回调函数,用于 .then() 中取 data 字段 */
function unwrap<T>(): (res: any) => T {
return (res: any) => (res?.data ?? res) as T
}
// ========== 认证相关 ==========
export const authApi = {
/** 登录 */
login: (data: { phone: string; password: string }) =>
post('/auth/login', data).then(unwrap<any>()),
/** 注册 */
register: (data: Record<string, unknown>) =>
post('/auth/register', data).then(unwrap<any>()),
/** 平台登录 */
platformLogin: (data: Record<string, unknown>) =>
post('/auth/platform-login', data).then(unwrap<any>()),
/** 发送忘记密码验证码 */
forgotPasswordSendCode: (phone: string) =>
post('/auth/forgot-password/send-code', { phone }).then(unwrap<any>()),
/** 验证忘记密码 */
forgotPasswordVerify: (data: { phone: string; code: string; newPassword: string }) =>
post('/auth/forgot-password/verify', data),
}
// ========== 员工相关 ==========
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[]>()),
/** 员工分页列表 */
paged: (params: { page?: number; pageSize?: number; search?: string; department?: string }) =>
get('/employees', { params }).then(unwrap<any>()),
/** 员工详情 */
detail: (id: string) =>
get(`/employees/${id}`).then(unwrap<any>()),
/** 创建员工 */
create: (data: Record<string, unknown>) =>
post('/employees', data),
/** 身份证查重 */
checkIdCard: (idCard: string) =>
get('/employees/check-id-card', { params: { idCard } }).then(unwrap<{ exists: boolean; employee?: any }>()),
/** 手机号查重 */
checkPhone: (phone: string) =>
get('/employees/check-phone', { params: { phone } }).then(unwrap<{ exists: boolean; employee?: any }>()),
/** 更新员工 */
update: (id: string, data: Record<string, unknown>) =>
put(`/employees/${id}`, data),
/** 删除员工 */
remove: (id: string) =>
del(`/employees/${id}`),
/** 重新入职 */
rehire: (id: string, data: Record<string, unknown>) =>
post(`/employees/${id}/rehire`, data),
/** 添加合同 */
addContract: (data: Record<string, unknown>) =>
post('/employees/contracts', data),
/** 删除合同 */
removeContract: (contractId: string) =>
del(`/employees/contracts/${contractId}`),
/** 批量续签预检 */
previewRenew: (contractIds: string[]) =>
post('/employees/contracts/preview-renew', { contractIds }),
/** 批量续签 */
batchRenew: (data: { contractIds: string[]; years: number }) =>
post('/employees/contracts/batch-renew', data),
}
// ========== 花名册相关 ==========
export interface RosterParams {
page?: number
pageSize?: number
search?: string
status?: string
department?: string
contractStatus?: string
}
export interface RosterResponse {
data: Record<string, unknown>[]
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[]>()),
/** 培训记录列表(全员) */
trainingList: (params: { page?: number; pageSize?: number; keyword?: string; ackStatus?: string }) =>
get('/roster/training/list', { params }).then(unwrap<any>()),
/** 培训记录催办 */
trainingRemind: (recordId: string) =>
post(`/roster/training/remind/${recordId}`).then(unwrap<any>()),
/** 绩效记录列表(全员) */
performanceList: (params: { page?: number; pageSize?: number; keyword?: string }) =>
get('/roster/performance/list', { params }).then(unwrap<any>()),
/** 绩效模板列表 */
performanceTemplates: () =>
get('/roster/performance/templates').then(unwrap<any[]>()),
/** 创建绩效模板 */
createPerformanceTemplate: (data: any) =>
post('/roster/performance/templates', data).then(unwrap<any>()),
/** 更新绩效模板 */
updatePerformanceTemplate: (id: string, data: any) =>
put(`/roster/performance/templates/${id}`, data).then(unwrap<any>()),
/** 删除绩效模板 */
deletePerformanceTemplate: (id: string) =>
del(`/roster/performance/templates/${id}`).then(unwrap<any>()),
/** 违纪记录列表(全员) */
disciplinaryList: (params: { page?: number; pageSize?: number; keyword?: string }) =>
get('/roster/disciplinary/list', { params }).then(unwrap<any>()),
/** 违纪记录 */
disciplinary: (employeeId: string) =>
get(`/roster/${employeeId}/disciplinary`).then(unwrap<any[]>()),
/** 证据链 */
evidenceChain: (employeeId: string) =>
get(`/roster/${employeeId}/evidence-chain`).then(unwrap<any>()),
/** 员工档案 */
profile: (employeeId: string) =>
get(`/roster/${employeeId}/profile`).then(unwrap<any>()),
/** 调薪 */
salaryChange: (employeeId: string, data: Record<string, unknown>) =>
post(`/roster/${employeeId}/salary-change`, data),
/** 调岗 */
departmentChange: (employeeId: string, data: Record<string, unknown>) =>
post(`/roster/${employeeId}/department-change`, data),
/** 考勤记录 */
attendance: (employeeId: string, data: Record<string, unknown>) =>
post(`/roster/${employeeId}/attendance`, data),
/** 删除考勤记录 */
removeAttendance: (employeeId: string, id: string) =>
del(`/roster/${employeeId}/attendance/${id}`),
/** 培训记录 */
training: (employeeId: string, data: Record<string, unknown>) =>
post(`/roster/${employeeId}/training`, data),
/** 删除培训记录 */
removeTraining: (employeeId: string, id: string) =>
del(`/roster/${employeeId}/training/${id}`),
/** 绩效记录 */
performance: (employeeId: string, data: Record<string, unknown>) =>
post(`/roster/${employeeId}/performance`, data),
/** 删除绩效记录 */
removePerformance: (employeeId: string, id: string) =>
del(`/roster/${employeeId}/performance/${id}`),
/** 违纪记录-创建 */
createDisciplinary: (employeeId: string, data: Record<string, unknown>) =>
post(`/roster/${employeeId}/disciplinary`, data),
/** 删除违纪记录 */
removeDisciplinary: (employeeId: string, id: string) =>
del(`/roster/${employeeId}/disciplinary/${id}`),
}
// ========== 附件相关 ==========
export const attachmentApi = {
/** 添加附件 */
add: (data: Record<string, unknown>) =>
post('/attachments', data),
/** 获取附件列表 */
list: (employeeId: string) =>
get(`/attachments/${employeeId}`).then(unwrap<any[]>()),
/** 删除附件 */
remove: (id: string) =>
del(`/attachments/${id}`),
}
// ========== 仪表盘相关 ==========
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[]>()),
/** 体检诊断保存 */
healthCheckSave: () =>
post('/dashboard/health-check/save').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[]>()),
/** 年度价值报告保存 */
annualValueSave: (year: number) =>
post('/dashboard/annual-value/save', { year }).then(unwrap<any>()),
/** 待办标记已处理 */
resolveTodo: (id: string) =>
patch(`/dashboard/todos/${id}/resolve`),
/** 待办忽略 */
ignoreTodo: (id: string) =>
patch(`/dashboard/todos/${id}/ignore`),
/** 批量标记已处理 */
batchResolveTodos: (ids: string[]) =>
patch('/dashboard/todos/batch-resolve', { ids }),
/** 批量忽略 */
batchIgnoreTodos: (ids: string[]) =>
patch('/dashboard/todos/batch-ignore', { ids }),
}
// ========== 考勤相关 ==========
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[]>()),
/** 发布考勤 */
publish: (month: string) =>
post('/attendance/publish', { month }).then(unwrap<any>()),
/** 取消发布 */
cancelPublish: (id: string) =>
post(`/attendance/publish/${id}/cancel`).then(unwrap<any>()),
/** 批量确认 */
batchConfirm: (data: { month: string; all?: boolean; ids?: string[] }) =>
post('/attendance/batch-confirm', data).then(unwrap<any>()),
/** 单条确认 */
confirm: (data: { employeeId: string; month: string }) =>
post('/attendance/confirm', data).then(unwrap<any>()),
/** 创建/更新班次 */
saveShift: (data: Record<string, unknown>, editId?: string) =>
editId ? put(`/attendance/shifts/${editId}`, data) : post('/attendance/shifts', data),
/** 删除班次 */
removeShift: (id: string) =>
del(`/attendance/shifts/${id}`),
/** 批量排班 */
batchAssign: (items: Record<string, unknown>[]) =>
post('/attendance/shift-assignments/batch', { items }),
/** 删除排班 */
removeAssignment: (id: string) =>
del(`/attendance/shift-assignments/${id}`),
/** 创建请假记录 */
createLeave: (data: Record<string, unknown>) =>
post('/attendance/leaves', data),
/** 删除请假记录 */
removeLeave: (id: string) =>
del(`/attendance/leaves/${id}`),
/** 手动补卡/修正考勤 */
manualCorrect: (data: { employeeId: string; date: string; checkInTime?: string; checkOutTime?: string; status?: string; remark?: string }) =>
post('/attendance/manual-correct', data).then(unwrap<any>()),
}
// ========== 休假审批流 ==========
export const leaveApi = {
list: (params?: Record<string, unknown>) =>
get('/leaves', { params }).then(unwrap<any>()),
stats: (month?: string) =>
get('/leaves/stats', { params: { month } }).then(unwrap<any>()),
create: (data: Record<string, unknown>) =>
post('/leaves', data).then(unwrap<any>()),
approve: (id: string, action: string, remark?: string) =>
post(`/leaves/${id}/approve`, { action, remark }).then(unwrap<any>()),
cancel: (id: string) =>
post(`/leaves/${id}/cancel`).then(unwrap<any>()),
remove: (id: string) =>
del(`/leaves/${id}`),
}
// ========== AI 相关 ==========
export const aiApi = {
/** 对话历史列表 */
conversations: (type: string) =>
get(`/ai/conversations?type=${type}`).then(unwrap<any[]>()),
/** 对话详情 */
conversation: (id: string) =>
get(`/ai/conversations/${id}`).then(unwrap<any>()),
/** 创建对话 */
createConversation: (data: Record<string, unknown>) =>
post('/ai/conversations', data).then(unwrap<any>()),
/** 更新对话 */
updateConversation: (id: string, data: Record<string, unknown>) =>
put(`/ai/conversations/${id}`, data),
/** 删除对话 */
removeConversation: (id: string) =>
del(`/ai/conversations/${id}`),
/** AI 咨询 */
consult: (data: Record<string, unknown>) =>
post('/ai/consultation', data).then(unwrap<any>()),
/** AI 上下文问答 */
contextAsk: (data: Record<string, unknown>) =>
post('/ai/context-ask', data).then(unwrap<any>()),
/** 合同审查上传 */
reviewUpload: (formData: FormData) =>
post('/ai/review/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(unwrap<any>()),
/** 合同审查 */
review: (contractText: string) =>
post('/ai/review', { contractText }).then(unwrap<any>()),
/** 保存审查结果 */
reviewSave: (data: Record<string, unknown>) =>
post('/ai/review/save', data),
/** 案例匹配 */
matchCase: (scenario: string) =>
post('/ai/match-case', { scenario }).then(unwrap<any>()),
/** 案例转待办 */
caseToTodo: (data: Record<string, unknown>) =>
post('/ai/case-to-todo', data),
/** RAG 知识库列表 */
ragList: () =>
get('/ai/rag/list').then(unwrap<any[]>()),
/** RAG 添加知识 */
ragAdd: (data: Record<string, unknown>) =>
post('/ai/rag/add', data),
/** RAG 删除知识 */
ragRemove: (id: string) =>
del(`/ai/rag/${id}`),
/** RAG 帮助搜索 */
ragHelpSearch: (query: string, topK = 8) =>
post('/ai/rag/help-search', { query, topK }).then(unwrap<any>()),
/** RAG 知识库种子数据 */
ragSeed: () =>
post('/ai/rag/seed'),
}
// ========== 薪酬相关 ==========
export const payrollApi = {
/** 薪酬模版列表 */
template: () =>
get('/payroll2/template').then(unwrap<any[]>()),
/** 创建模版项 */
createTemplateItem: (data: Record<string, unknown>) =>
post('/payroll2/template', data),
/** 更新模版项 */
updateTemplateItem: (id: string, data: Record<string, unknown>) =>
put(`/payroll2/template/${id}`, data),
/** 删除模版项 */
removeTemplateItem: (id: string) =>
del(`/payroll2/template/${id}`),
/** 检查本月是否已发薪 */
batchCheck: (month: string) =>
get('/payroll2/batches/check', { params: { month } }).then(unwrap<any>()),
/** 批次列表 */
batches: (params?: Record<string, unknown>) =>
get('/payroll2/batches', { params }).then(unwrap<any[]>()),
/** 归档批次列表 */
archivedBatches: () =>
get('/payroll2/batches/archived/list').then(unwrap<any[]>()),
/** 批次详情 */
batchDetail: (id: string) =>
get(`/payroll2/batches/${id}`).then(unwrap<any>()),
/** 创建批次 */
createBatch: (data: Record<string, unknown>) =>
post('/payroll2/batches', data),
/** 重命名批次 */
renameBatch: (batchId: string, name: string) =>
put(`/payroll2/batches/${batchId}/name`, { name }),
/** 删除批次 */
removeBatch: (batchId: string) =>
del(`/payroll2/batches/${batchId}`),
/** 归档批次 */
archiveBatch: (batchId: string) =>
post(`/payroll2/batches/${batchId}/archive`),
/** 取消归档 */
unarchiveBatch: (batchId: string) =>
post(`/payroll2/batches/${batchId}/unarchive`),
/** 发布工资条 */
publishPayslip: (batchId: string) =>
post(`/payroll2/batches/${batchId}/publish`),
/** 定时发送工资条 */
schedulePayslip: (batchId: string, scheduledAt: string) =>
post(`/payroll2/batches/${batchId}/schedule`, { scheduledAt }),
/** 批次增加人员 */
addBatchEmployees: (batchId: string, employeeIds: string[]) =>
post(`/payroll2/batches/${batchId}/employees`, { employeeIds }),
/** 批次移除人员 */
removeBatchEmployee: (batchId: string, employeeId: string) =>
del(`/payroll2/batches/${batchId}/employees/${employeeId}`),
/** 更新批次条目 */
updateBatchEntry: (batchId: string, employeeId: string, data: Record<string, unknown>) =>
put(`/payroll2/batches/${batchId}/entries/${employeeId}`, data),
/** 获取条目个税计算明细 */
taxDetail: (batchId: string, employeeId: string) =>
get(`/payroll2/batches/${batchId}/entries/${employeeId}/tax-detail`).then(unwrap<any>()),
/** 算薪前 AI 校验 */
preCheck: (batchId: string) =>
get(`/payroll2/batches/${batchId}/pre-check`).then(unwrap<any>()),
/** 生成工资条 */
generatePayslips: (month: string) =>
post('/payroll2/payslips/generate', { month }).then(unwrap<any>()),
/** 加班费记录列表 */
overtimeRecords: (params: { month?: string; employeeId?: string }) =>
get('/payroll/overtime', { params }).then(unwrap<any[]>()),
/** 保存加班费记录 */
saveOvertime: (data: Record<string, unknown>) =>
post('/payroll/overtime', data).then(unwrap<any>()),
/** 更新加班费记录 */
updateOvertime: (id: string, data: Record<string, unknown>) =>
put(`/payroll/overtime/${id}`, data).then(unwrap<any>()),
/** 批量导入加班工时 */
batchImportOvertime: (data: Record<string, unknown>[]) =>
post('/payroll/overtime/batch', data),
/** 从考勤记录同步加班工时 */
syncOvertimeFromAttendance: (month: string) =>
post('/payroll/overtime/sync-from-attendance', { month }).then(unwrap<any>()),
/** 导入加班费到批次 */
importOvertimeToBatch: (batchId: string) =>
post(`/payroll/overtime/import-to-batch/${batchId}`).then(unwrap<any>()),
/** 加班费配置 */
overtimeConfig: () =>
get('/payroll/overtime/config').then(unwrap<any>()),
/** 保存加班费配置 */
saveOvertimeConfig: (data: Record<string, unknown>) =>
post('/payroll/overtime/config', data),
/** 工资条列表 */
payslips: (params: { month?: string; employeeId?: string }) =>
get('/payroll/payslip', { params }).then(unwrap<any[]>()),
/** 创建/更新工资条 */
savePayslip: (data: Record<string, unknown>) =>
post('/payroll/payslip', data).then(unwrap<any>()),
/** 删除工资条 */
removePayslip: (id: string) =>
del(`/payroll/payslip/${id}`),
/** 个税试算 */
taxPreview: (data: Record<string, unknown>) =>
post('/payroll/tax-preview', data).then(unwrap<any>()),
/** 薪资汇总表 */
batchSummary: (id: string) =>
get(`/payroll/batch/${id}/summary`).then(unwrap<any>()),
/** 薪资明细表(旧接口) */
batchDetailExport: (id: string) =>
get(`/payroll/batch/${id}/detail`).then(unwrap<any>()),
}
// ========== 薪资仪表盘 ==========
export const salaryDashboardApi = {
data: (year: number) =>
get('/salary/dashboard', { params: { year } }).then(unwrap<any>()),
}
// ========== 社保公积金相关 ==========
export const socialInsuranceApi = {
/** 城市列表 */
cities: () =>
get('/social/config/cities').then(unwrap<string[]>()),
/** 社保配置 */
config: (city: string) =>
get('/social/config', { params: { city } }).then(unwrap<any>()),
/** 公积金配置 */
housingConfig: (city: string) =>
get('/social/housing-config', { params: { city } }).then(unwrap<any>()),
/** 社保配置版本列表 */
configVersions: (city: string) =>
get('/social/config/versions', { params: { city } }).then(unwrap<any[]>()),
/** 公积金配置版本列表 */
housingConfigVersions: (city?: string) =>
get('/social/housing-config/versions', { params: city ? { city } : {} }).then(unwrap<any[]>()),
/** 创建社保配置版本 */
createConfigVersion: (data: Record<string, unknown>) =>
post('/social/config/versions', data),
/** 创建公积金配置版本 */
createHousingConfigVersion: (data: Record<string, unknown>) =>
post('/social/housing-config/versions', data),
/** 社保计算 */
calculate: (base: number, city: string) =>
post('/social/calculate', { base, city }).then(unwrap<any>()),
/** 公积金计算 */
housingCalculate: (base: number, city: string) =>
post('/social/housing-calculate', { base, city }).then(unwrap<any>()),
/** AI 建议 */
aiSuggest: (data: { city: string; effectiveFrom: string; type: 'social' | 'housing' }) =>
post('/social/ai-suggest', data).then(unwrap<any>()),
/** 调整预览 */
adjustPreview: (configId: string) =>
get(`/social/config/${configId}/adjust-preview`).then(unwrap<any>()),
/** 公积金调整预览 */
housingAdjustPreview: (configId: string) =>
get(`/social/housing-config/${configId}/adjust-preview`).then(unwrap<any>()),
/** 应用调整 */
applyAdjust: (configId: string, data: Record<string, unknown>) =>
post(`/social/config/${configId}/adjust-apply`, data),
/** 应用公积金调整 */
applyHousingAdjust: (configId: string, data: Record<string, unknown>) =>
post(`/social/housing-config/${configId}/adjust-apply`, data),
/** 重置调整 */
resetAdjust: (configId: string, city: string) =>
post(`/social/config/${configId}/reset-adjustment`, { city }),
/** 重置公积金调整 */
resetHousingAdjust: (configId: string, city: string) =>
post(`/social/housing-config/${configId}/reset-adjustment`, { city }),
/** 月度办理列表 */
monthlyProcessList: () =>
get('/social/monthly-process/list').then(unwrap<any[]>()),
/** 月度办理状态 */
monthlyProcessStatus: (month: string) =>
get('/social/monthly-process/status', { params: { month } }).then(unwrap<any>()),
/** 完成月度办理 */
completeMonthlyProcess: (data: Record<string, unknown>) =>
post('/social/monthly-process/complete', data),
/** 专项附加扣除批量 */
specialDeductionBatch: (month: string) =>
get('/social/special-deduction/batch', { params: { month } }).then(unwrap<any[]>()),
/** 保存专项附加扣除 */
saveSpecialDeduction: (data: Record<string, unknown>) =>
post('/social/special-deduction', data),
/** 活跃申报员工 */
activeDeclaration: (month: string) =>
get('/social/active-declaration', { params: { month } }).then(unwrap<any>()),
/** 社保/公积金记录更正 */
correctRecord: (type: 'social' | 'housing', id: string, data: Record<string, unknown>) =>
put(`/social/records/${type}/${id}/correct`, data).then(unwrap<any>()),
/** 社保月度变动 */
monthlyChanges: (month: string) =>
get('/social/monthly-changes', { params: { month } }).then(unwrap<any>()),
/** 公积金月度变动 */
housingMonthlyChanges: (month: string) =>
get('/social/housing/monthly-changes', { params: { month } }).then(unwrap<any>()),
/** 公积金活跃申报 */
housingActiveDeclaration: (month: string) =>
get('/social/housing/active-declaration', { params: { month } }).then(unwrap<any>()),
/** 员工参保信息列表 */
employeeEnrollment: (keyword?: string) =>
get('/social/employee-enrollment', { params: keyword ? { keyword } : {} }).then(unwrap<any[]>()),
}
// ========== 商业保险 ==========
export const commercialInsuranceApi = {
/** 方案列表 */
plans: () =>
get('/commercial-insurance/plans').then(unwrap<any[]>()),
/** 方案详情(含参保人员) */
enrollments: (planId: string) =>
get(`/commercial-insurance/plans/${planId}/enrollments`).then(unwrap<any[]>()),
/** 创建/更新方案 */
savePlan: (data: Record<string, unknown>, editId?: string) =>
editId ? put(`/commercial-insurance/plans/${editId}`, data) : post('/commercial-insurance/plans', data),
/** 删除方案 */
removePlan: (id: string) =>
del(`/commercial-insurance/plans/${id}`),
/** 批量参保 */
enroll: (planId: string, data: { employeeIds: string[]; premium?: number; effectiveFrom?: string }) =>
post(`/commercial-insurance/plans/${planId}/enroll`, data),
/** 退保 */
terminateEnrollment: (enrollmentId: string, effectiveTo?: string) =>
post(`/commercial-insurance/enrollments/${enrollmentId}/terminate`, { effectiveTo }),
/** 员工商险汇总 */
employeeSummary: () =>
get('/commercial-insurance/employee-summary').then(unwrap<any[]>()),
}
// ========== 员工福利 ==========
export const benefitApi = {
plans: () =>
get('/benefits/plans').then(unwrap<any[]>()),
savePlan: (data: Record<string, unknown>, editId?: string) =>
editId ? put(`/benefits/plans/${editId}`, data) : post('/benefits/plans', data),
removePlan: (id: string) =>
del(`/benefits/plans/${id}`),
enrollments: (planId: string) =>
get(`/benefits/plans/${planId}/enrollments`).then(unwrap<any[]>()),
enroll: (planId: string, data: { employeeIds: string[]; effectiveFrom?: string }) =>
post(`/benefits/plans/${planId}/enroll`, data),
terminateEnrollment: (enrollmentId: string, effectiveTo?: string) =>
post(`/benefits/enrollments/${enrollmentId}/terminate`, { effectiveTo }),
employeeSummary: () =>
get('/benefits/employee-summary').then(unwrap<any[]>()),
}
// ========== 电子签署(易签宝) ==========
export const esignApi = {
list: (params?: { status?: string; scene?: string }) =>
get('/esign', { params: params || {} }).then(unwrap<any[]>()),
create: (data: { contractId?: string; employeeId: string; documentTitle: string; documentContent?: string; remark?: string; scene?: string }) =>
post('/esign/create', data),
status: (id: string) =>
get(`/esign/${id}/status`).then(unwrap<any>()),
cancel: (id: string) =>
post(`/esign/${id}/cancel`),
}
// ========== 离职相关 ==========
export const terminationApi = {
/** 创建离职 */
create: (data: Record<string, unknown>) =>
post('/termination', data),
/** 创建草稿 */
createDraft: (data: Record<string, unknown>) =>
post('/termination/draft', data),
/** 更新草稿 */
updateDraft: (draftId: string, data: Record<string, unknown>) =>
put(`/termination/draft/${draftId}`, data),
/** 草稿列表 */
drafts: (params: Record<string, unknown>) =>
get('/termination/drafts', { params }).then(unwrap<any>()),
/** 草稿详情 */
detail: (draftId: string) =>
get(`/termination/detail/${draftId}`).then(unwrap<any>()),
/** 提交审批 */
submit: (draftId: string) =>
post(`/termination/draft/${draftId}/submit`),
/** 审批通过 */
approve: (draftId: string, comment: string) =>
post(`/termination/draft/${draftId}/approve`, { comment }),
/** 审批驳回 */
reject: (draftId: string, comment: string) =>
post(`/termination/draft/${draftId}/reject`, { comment }),
/** 执行解聘 */
execute: (draftId: string) =>
post(`/termination/draft/${draftId}/execute`),
/** 撤销 */
cancel: (draftId: string) =>
post(`/termination/draft/${draftId}/cancel`),
/** 删除草稿(仅 DRAFT 和 CANCELLED 状态) */
deleteDraft: (draftId: string) =>
del(`/termination/draft/${draftId}`),
/** 撤回离职记录 */
revoke: (recordId: string) =>
del(`/termination/${recordId}/revoke`),
/** 离职清单 */
checklist: (reason: string, employeeId: string) =>
get(`/termination/checklist/${reason}`, { params: { employeeId } }).then(unwrap<any>()),
/** 风险评估 */
assess: (employeeId: string, reason: string) =>
get(`/termination/assess/${employeeId}`, { params: { reason } }).then(unwrap<any>()),
/** 批量预览 */
batchPreview: (items: Record<string, unknown>[]) =>
post('/termination/batch/preview', { items }),
/** 上传工会回执文件 */
uploadUnionReceipt: (draftId: string, file: File) => {
const formData = new FormData()
formData.append('file', file)
return post(`/termination/draft/${draftId}/union-receipt/upload`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(unwrap<any>())
},
/** 保存工会回执信息 */
saveUnionReceipt: (draftId: string, data: Record<string, unknown>) =>
post(`/termination/draft/${draftId}/union-receipt`, data).then(unwrap<any>()),
/** 获取工会回执信息 */
getUnionReceipt: (draftId: string) =>
get(`/termination/draft/${draftId}/union-receipt`).then(unwrap<any>()),
}
// ========== 制度相关 ==========
export const policiesApi = {
/** 制度列表 */
list: (params: { page?: number; pageSize?: number; status?: string }) =>
get('/policies', { params }).then(unwrap<any>()),
/** 制度详情 */
detail: (id: string) =>
get(`/policies/${id}`).then(unwrap<any>()),
/** 创建制度 */
create: (data: Record<string, unknown>) =>
post('/policies', data),
/** 更新制度 */
update: (id: string, data: Record<string, unknown>) =>
put(`/policies/${id}`, data),
/** 推进民主程序 */
advanceStep: (id: string, step: number, note?: string) =>
post(`/policies/${id}/advance-step`, { step, note }),
/** 删除制度 */
remove: (id: string) =>
del(`/policies/${id}`),
/** 阅读签收统计 */
readStats: (id: string) =>
get(`/policies/${id}/read-stats`).then(unwrap<any>()),
/** 催办未签收员工 */
remind: (id: string, employeeIds?: string[]) =>
post(`/policies/${id}/remind`, { employeeIds }).then(unwrap<any>()),
}
// ========== 证据链相关 ==========
export const evidenceApi = {
/** 证据链列表 */
list: (params: { page?: number; pageSize?: number; category?: string }) =>
get('/evidence', { params }).then(unwrap<any>()),
/** 全量验证 */
verifyAll: () =>
get('/evidence/verify-all').then(unwrap<any>()),
/** 按员工获取证据链记录 */
byEmployee: (employeeId: string) =>
get(`/evidence/employee/${employeeId}`).then(unwrap<any[]>()),
/** 验证单条证据链 */
verify: (id: string) =>
get(`/evidence/verify/${id}`).then(unwrap<any>()),
}
// ========== 审计日志 ==========
export const auditApi = {
/** 审计日志列表 */
list: (params: { page?: number; pageSize?: number; entity?: string; dateFrom?: string; dateTo?: string }) =>
get('/audit', { params }).then(unwrap<any>()),
/** 审计统计 */
stats: () =>
get('/audit/stats').then(unwrap<any>()),
}
// ========== 日历相关 ==========
export const calendarApi = {
/** 自定义事件列表 */
events: (month: string) =>
get(`/calendar?month=${month}`).then(unwrap<any[]>()),
/** 创建事件 */
createEvent: (data: Record<string, unknown>) =>
post('/calendar', data),
/** 删除事件 */
removeEvent: (id: string) =>
del(`/calendar/${id}`),
}
// ========== 公司文件 ==========
export const companyFilesApi = {
/** 文件列表 */
list: (params?: { fileType?: string }) =>
get('/company-files', { params }).then(unwrap<any[]>()),
/** 添加文件 */
add: (data: Record<string, unknown>) =>
post('/company-files', data),
/** 删除文件 */
remove: (id: string) =>
del(`/company-files/${id}`),
}
// ========== 通知相关 ==========
export const notificationsApi = {
/** 通知日志 */
logs: (params?: { page?: number; pageSize?: number }) =>
get('/notifications/logs', { params }).then(unwrap<any>()),
/** 通知设置 */
settings: () =>
get('/notifications/settings').then(unwrap<any>()),
/** 更新通知设置 */
updateSettings: (data: Record<string, unknown>) =>
put('/notifications/settings', data),
/** 检查合同到期 */
checkContracts: () =>
post('/notifications/check-contracts'),
/** 测试通知发送 */
test: (channel: 'wechat' | 'email') =>
post('/notifications/test', { channel }),
}
// ========== 系统设置 ==========
export const settingsApi = {
/** 组织设置 */
org: () =>
get('/settings/org').then(unwrap<any>()),
/** 更新组织设置 */
updateOrg: (data: Record<string, unknown>) =>
put('/settings/org', data),
/** 用户列表 */
users: () =>
get('/settings/users').then(unwrap<any>()),
/** 添加用户 */
addUser: (data: Record<string, unknown>) =>
post('/settings/users', data),
/** 更新用户 */
updateUser: (id: string, data: Record<string, unknown>) =>
put(`/settings/users/${id}`, data),
/** 切换用户禁用状态 */
toggleDisable: (id: string) =>
patch(`/settings/users/${id}/toggle-disable`),
/** 用量统计 */
usage: () =>
get('/settings/usage').then(unwrap<any>()),
/** 更新套餐 */
updatePlan: (plan: string) =>
put('/settings/plan', { plan }),
/** 退休政策 */
retirementPolicy: () =>
get('/settings/retirement-policy').then(unwrap<any>()),
/** 确认退休政策生效 */
confirmRetirementPolicy: (id: string) =>
post(`/settings/retirement-policy/${id}/confirm`),
/** 医疗期政策列表 */
medicalPeriodPolicies: () =>
get('/settings/medical-period/policies').then(unwrap<any[]>()),
/** 保存医疗期政策 */
saveMedicalPeriodPolicy: (data: Record<string, unknown>) =>
post('/settings/medical-period/policies', data),
/** 删除医疗期政策 */
deleteMedicalPeriodPolicy: (id: string) =>
del(`/settings/medical-period/policies/${id}`),
}
// ========== 模板相关 ==========
export const templatesApi = {
/** 系统模板列表 */
list: (category?: string) =>
get('/templates', { params: category ? { category } : {} }).then(unwrap<any[]>()),
/** 系统模板详情 */
detail: (id: string) =>
get(`/templates/${id}`).then(unwrap<any>()),
/** 渲染模板 */
render: (id: string, variables: Record<string, unknown>) =>
post(`/templates/${id}/render`, { variables }).then(unwrap<any>()),
/** 企业模板列表 */
enterpriseList: (params: { page?: number; pageSize?: number; category?: string }) =>
get('/enterprise-templates', { params }).then(unwrap<any>()),
/** 企业模板详情 */
enterpriseDetail: (id: string) =>
get(`/enterprise-templates/${id}`).then(unwrap<any>()),
/** 创建/更新企业模板 */
saveEnterprise: (data: Record<string, unknown>, editId?: string) =>
editId ? put(`/enterprise-templates/${editId}`, data) : post('/enterprise-templates', data),
/** 删除企业模板 */
removeEnterprise: (id: string) =>
del(`/enterprise-templates/${id}`),
/** 渲染企业模板 */
renderEnterprise: (id: string, variables: Record<string, unknown>) =>
post(`/enterprise-templates/${id}/render`, { variables }).then(unwrap<any>()),
}
// ========== 工作流程 ==========
export const workProcessApi = {
/** 列表 */
list: (params: { page?: number; pageSize?: number; type?: string; status?: string }) =>
get('/work-processes', { params }).then(unwrap<any>()),
/** 详情 */
detail: (id: string) =>
get(`/work-processes/${id}`).then(unwrap<any>()),
/** 创建 */
create: (data: Record<string, unknown>) =>
post('/work-processes', data).then(unwrap<any>()),
/** 提交 */
submit: (id: string) =>
post(`/work-processes/${id}/submit`).then(unwrap<any>()),
/** 取消 */
cancel: (id: string) =>
post(`/work-processes/${id}/cancel`).then(unwrap<any>()),
/** 删除 */
remove: (id: string) =>
del(`/work-processes/${id}`),
/** 预览 */
preview: (id: string) =>
get(`/work-processes/${id}/preview`).then(unwrap<any>()),
}
// ========== 特殊状态台账 ==========
export const specialStatusApi = {
/** 列表 */
list: (params: { page?: number; pageSize?: number; search?: string; type?: string; status?: string }) =>
get('/special-statuses', { params }).then(unwrap<any>()),
/** 统计概览 */
stats: () =>
get('/special-statuses/stats/overview').then(unwrap<any>()),
/** 创建 */
create: (data: Record<string, unknown>) =>
post('/special-statuses', data),
/** 更新 */
update: (id: string, data: Record<string, unknown>) =>
put(`/special-statuses/${id}`, data),
/** 删除 */
remove: (id: string) =>
del(`/special-statuses/${id}`),
}
// ========== 搜索 ==========
export const searchApi = {
/** 全局搜索 */
search: (q: string) =>
get('/search', { params: { q } }).then(unwrap<any>()),
}
// ========== 问卷 ==========
export const surveyApi = {
/** 提交问卷 */
submit: (items: Record<string, unknown>[]) =>
post('/survey/submit', { items }),
}
// ========== 平台管理 ==========
export const platformApi = {
/** 平台仪表盘 */
dashboard: () =>
get('/platform/dashboard').then(unwrap<any>()),
/** 组织列表 */
orgs: (params: { page?: number; pageSize?: number; search?: string; plan?: string }) =>
get('/platform/orgs', { params }).then(unwrap<any>()),
/** 组织详情 */
orgDetail: (id: string) =>
get(`/platform/orgs/${id}`).then(unwrap<any>()),
/** 创建组织 */
createOrg: (data: Record<string, unknown>) =>
post('/platform/orgs', data),
/** 更新组织 */
updateOrg: (id: string, data: Record<string, unknown>) =>
put(`/platform/orgs/${id}`, data),
/** 更新组织管理员 */
updateOrgAdmin: (id: string, data: Record<string, unknown>) =>
put(`/platform/orgs/${id}/admin`, data),
/** 删除组织 */
removeOrg: (id: string) =>
del(`/platform/orgs/${id}`),
/** 用户列表 */
users: (params: { page?: number; pageSize?: number; search?: string; orgId?: string }) =>
get('/platform/users', { params }).then(unwrap<any>()),
/** 切换用户状态 */
toggleUser: (id: string) =>
put(`/platform/users/${id}/toggle`),
}
// ========== 员工端 Portal ==========
/** 员工端 API 实例(携带 portalToken */
const portalAxios = axios.create({ baseURL: '/api/v1/portal' })
portalAxios.interceptors.request.use((config: any) => {
const token = localStorage.getItem('portalToken')
if (token) config.headers.Authorization = `Bearer ${token}`
return config
})
const portalGet = ((url: string, config?: any) => portalAxios.get(url, config)) as any
const portalPost = ((url: string, data?: any, config?: any) => portalAxios.post(url, data, config)) as any
export const portalApi = {
/** 登录 */
login: (phone: string, password: string) =>
portalPost('/login', { phone, password }).then(unwrap<any>()),
/** 发送验证码 */
sendCode: (phone: string) =>
portalPost('/send-code', { phone }).then(unwrap<any>()),
/** 验证码登录 */
verifyCode: (phone: string, code: string) =>
portalPost('/verify-code', { phone, code }).then(unwrap<any>()),
/** 自动登录 */
autoLogin: (token: string) =>
portalGet('/auto-login', { params: { token } }).then(unwrap<any>()),
/** 生成自动登录令牌(管理端) */
generateAutoLoginToken: (employeeId: string) =>
post('/portal/auto-login-token', { employeeId }).then(unwrap<any>()),
/** 首页概览 */
homeOverview: () =>
portalGet('/home/overview').then(unwrap<any>()),
/** 工资条 */
payslip: (month: string) =>
portalGet('/payslip', { params: { month } }).then(unwrap<any>()),
/** 工资条历史 */
payslipHistory: () =>
portalGet('/payslip/history').then(unwrap<any[]>()),
/** 确认工资条 */
confirmPayslip: (id: string) =>
portalPost(`/payslip/${id}/confirm`),
/** 考勤 */
attendance: (month: string) =>
portalGet('/attendance', { params: { month } }).then(unwrap<any>()),
/** 合同 */
contract: () =>
portalGet('/contract').then(unwrap<any>()),
/** 合同信息 */
contractInfo: (token: string) =>
portalGet(`/contract-confirm/${token}`).then(unwrap<any>()),
/** 重发合同确认 */
resendContractConfirm: (contractId: string) =>
portalPost('/contract-confirm/resend', { contractId }).then(unwrap<any>()),
/** 合同确认-发送验证码 */
contractConfirmSendCode: (token: string) =>
portalPost('/contract-confirm/send-code', { token }).then(unwrap<any>()),
/** 合同确认 */
contractConfirm: (token: string, verifyCode: string) =>
portalPost('/contract-confirm', { token, agreed: true, verifyCode }),
/** 入职链接信息 */
onboardingInfo: (token: string) =>
portalGet(`/onboarding/${token}`).then(unwrap<any>()),
/** 入职提交 */
onboardingSubmit: (data: Record<string, unknown>) =>
portalPost('/onboarding', data),
/** 入职上传文件 */
onboardingUpload: (token: string, formData: FormData) =>
portalPost(`/onboarding/${token}/upload`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(unwrap<any>()),
/** 入职进度 */
onboardingProgress: () =>
portalGet('/onboarding/progress').then(unwrap<any>()),
/** 制度列表 */
policies: () =>
portalGet('/policies').then(unwrap<any[]>()),
/** 制度详情 */
policyDetail: (id: string) =>
portalGet(`/policies/${id}`).then(unwrap<any>()),
/** 制度阅读确认 */
policyRead: (id: string) =>
portalPost(`/policies/${id}/read`),
/** 离职状态 */
resignationStatus: () =>
portalGet('/resignation/status').then(unwrap<any[]>()),
/** 提交离职申请 */
resignationSubmit: (data: Record<string, unknown>) =>
portalPost('/resignation/submit', data).then(unwrap<any>()),
/** 撤回离职申请 */
resignationWithdraw: (id: string) =>
portalPost(`/resignation/${id}/withdraw`).then(unwrap<any>()),
/** 下载离职证明 */
downloadCertificate: (id: string) =>
portalGet(`/resignation/${id}/certificate`, { responseType: 'blob' }) as any,
/** 我的休假申请列表 */
myLeaves: () =>
portalGet('/leaves').then(unwrap<any[]>()),
/** 提交休假申请 */
submitLeave: (data: Record<string, unknown>) =>
portalPost('/leaves', data).then(unwrap<any>()),
/** 撤回休假申请 */
cancelLeave: (id: string) =>
portalPost(`/leaves/${id}/cancel`).then(unwrap<any>()),
/** 我的电子签署列表 */
myEsignList: () =>
portalGet('/esign').then(unwrap<any[]>()),
/** 电子签署详情 */
esignDetail: (id: string) =>
portalGet(`/esign/${id}`).then(unwrap<any>()),
/** 签署操作 */
signEsign: (id: string) =>
portalPost(`/esign/${id}/sign`).then(unwrap<any>()),
/** 我的培训记录 */
myTraining: () =>
portalGet('/training').then(unwrap<any[]>()),
/** 培训签收 */
signTraining: (id: string) =>
portalPost(`/training/${id}/sign`).then(unwrap<any>()),
/** 培训拒绝签收 */
refuseTraining: (id: string) =>
portalPost(`/training/${id}/refuse`).then(unwrap<any>()),
/** 我的绩效记录 */
myPerformance: () =>
portalGet('/performance').then(unwrap<any[]>()),
/** 绩效签字 */
signPerformance: (id: string) =>
portalPost(`/performance/${id}/sign`).then(unwrap<any>()),
/** 我的违纪记录 */
myDisciplinary: () =>
portalGet('/disciplinary').then(unwrap<any[]>()),
/** 违纪签字 */
signDisciplinary: (id: string) =>
portalPost(`/disciplinary/${id}/sign`).then(unwrap<any>()),
}