/** * ICC 智电改造线路(消防探测器)数据字段映射(集中配置,便于按 ICC 平台实际返回结构调整)。 * * ICC 返回的原始字段名 → 本系统 electric_line 字段。接入真实 ICC 平台时 * 仅需调整本文件与 fetch 路径即可,业务层无需改动。纯映射逻辑,无 SQL 无 DOM。 */ export interface IccLineRawRecord { [field: string]: any; } /** 探测器分页列表接口路径({version} 由调用方按 ICC_VERSION 替换) */ export const ICC_LINE_ENDPOINT = "/evo-apigw/evo-fdbu/{version}/detector/subsystem/page"; /** 原始记录关键字段映射:本系统字段 → ICC 返回字段名 */ export const ICC_LINE_FIELDS = { lineCode: "detectorCode", // 探测器编码(唯一幂等键) lineName: "detectorName", // 探测器名称 imei: "imei", // 探测器 IMEI orgCode: "orgCode", // 所属组织编码(→ customer.icc_code 反查客户,不落库) parentCode: "parentCode", // 上级网关编码(→ electric_gateway.device_code 反查网关,不落库) typeCode: "typeCode", // 探测器类型编码 typeName: "typeName", // 探测器类型名称 fireSystemCode: "fireSystemCode", // 消防系统编码 fireSystemName: "fireSystemName", // 消防系统名称 partUnitLoopCode: "partUnitLoopCode", // 部件/单元/回路编码 channelNo: "channelNo", // 通道号 channelSn: "channelSn", // 通道序列号 produceDate: "produceDate", // 生产日期 detectorStatus: "detectorStatus" // 上报状态 01=在线 02=离线 } as const; /** 离线标记集合:命中即归一化为离线(0),其余(含空)均视为在线(1) */ export const OFFLINE_MARKERS = new Set(["02", "0", "false", "off", "离线"]); /** 字符串 trim;null / undefined / 空串统一归一为 undefined。 */ export function toOptionalString(value: unknown): string | undefined { if (value === undefined || value === null) return undefined; const s = String(value).trim(); return s === "" ? undefined : s; } /** 将 ICC 原始探测器记录映射为本系统 electric_line 落库字段(不含联表外键)。 */ export function mapIccLineRecord(raw: IccLineRawRecord): { lineCode: string; lineName?: string; imei?: string; orgCode?: string; parentCode?: string; typeCode?: string; typeName?: string; fireSystemCode?: string; fireSystemName?: string; partUnitLoopCode?: string; channelNo?: string; channelSn?: string; produceDate?: string; status: number; } { const f = ICC_LINE_FIELDS; const result: Record = { // 匹配键保持空串语义,由调用方判跳 lineCode: String(raw[f.lineCode] ?? "").trim() }; // 可选字符串字段 for (const key of ["lineName", "imei", "orgCode", "parentCode", "typeCode", "typeName", "fireSystemCode", "fireSystemName", "partUnitLoopCode", "channelNo", "channelSn", "produceDate"] as const) { result[key] = toOptionalString(raw[f[key]]); } // 上报状态归一化:离线标记集合 → 0,其余(含空)→ 1 const statusRaw = String(raw[f.detectorStatus] ?? "").trim(); result.status = OFFLINE_MARKERS.has(statusRaw) ? 0 : 1; return result as any; } /** * 解析探测器分页响应(兼容三种形态): * - payload 为数组 → 直接作为列表 * - payload.data.pageData 为数组 → 取 pageData * - payload.data.list 为数组 → 取 list * - 结构不匹配或解析异常 → 返回空列表 */ export function parseLinePage(payload: any): { list: IccLineRawRecord[]; nextPage?: number; totalCount?: number; } { try { if (Array.isArray(payload)) { return { list: payload }; } const page = payload?.data; if (page && Array.isArray(page.pageData)) { return { list: page.pageData, nextPage: Number(page.nextPage) > 0 ? Number(page.nextPage) : undefined, totalCount: Number(page.totalCount) > 0 ? Number(page.totalCount) : undefined }; } if (page && Array.isArray(page.list)) { return { list: page.list, nextPage: Number(page.nextPage) > 0 ? Number(page.nextPage) : undefined, totalCount: Number(page.totalCount) > 0 ? Number(page.totalCount) : undefined }; } return { list: [] }; } catch { return { list: [] }; } }