/** * 报考范围接口(《03-接口设计》§7.7 / §7.8)。 * * ## 它不是"从文件导入的计划" * * PRD V2.0 实测校正:**机构不下发计划清单**,而真实名单里「报考职业 / 报考工种 / 报考等级」 * 三列老师已经填好了(28/28)。所以这个范围就是**名册里这三列的去重组合**, * 不是一份独立的文件。界面上要按这个事实说话:不是"上传计划",而是"核对从名单里 * 归出来的范围"。 * * ## 确认按钮为什么会被禁用 * * `PUT` 要求 `rosterIds` 的并集**恰好覆盖名册全员**(差一个人就 40024 并点名)—— * 少一个人,导出包就缺人,而打开导出包时不会有人数出 27 个。 * 所以界面上"排除某人"是把他所在的分组标成 `EXCLUDED`,而不是把他从名单里删掉。 */ import http from '@/utils/http' /** 一个分组 = 职业 × 工种 × 等级 的一个组合。 */ export interface PlanScopeGroup { occupation: string | null worktype: string | null jobLevel: string | null certType: number | null count: number rosterIds: number[] /** `CONFIRMED` 已确认 / `NEED_REVIEW` 需人工确认 / `EXCLUDED` 已排除 */ status: string issue: string | null } export interface PlanScopeIssue { /** 契约没给语义词,只当排序与展示用 */ level: number code: string title: string detail: string /** ⚠️ 必须给:只说"存在不一致",管理员没法去核对 */ rosterIds: number[] } export interface PlanScopeHealth { passed: boolean issues: PlanScopeIssue[] } export interface PlanScopeVO { source: string updatedAt: string | null rosterCount: number confirmed: boolean groups: PlanScopeGroup[] healthCheck: PlanScopeHealth } export interface PlanScopeSaveReq { groups: Array<{ occupation: string | null worktype: string | null jobLevel: string | null certType?: number | null rosterIds: number[] status: string }> ignoredIssueCodes?: string[] remark?: string } export function getPlanScope(taskId: number) { return http.get(`/tasks/${taskId}/plan-scope`) } export function savePlanScope(taskId: number, data: PlanScopeSaveReq) { return http.put(`/tasks/${taskId}/plan-scope`, data) } /** 问题码 → 一句短说明(详情服务端已经写了,这里只做标签) */ export const SCOPE_ISSUE_NAMES: Record = { SCOPE_UNFILLED: '漏填报考项', SCOPE_LEVEL_MIXED: '同职业多等级', SCOPE_TYPEO_MISMATCH: '认定类型与工种/等级不匹配', SCOPE_OUT_OF_TASK: '任务范围外的职业', SCOPE_FREE_TEXT: '与字典拼写不符' } /** 分组状态 */ export const SCOPE_STATUS: Record = { CONFIRMED: { text: '已确认', color: 'green' }, NEED_REVIEW: { text: '需确认', color: 'orange' }, EXCLUDED: { text: '已排除', color: 'gray' } }