feat(line): 智电改造线路台账接入 ICC 消防探测器真实同步

- 重建 electric_line 表结构(迁移20261024_icc_line_rebuild.sql并同步db_init/db_seed):删building_id/floor_no/location/icc_device_code占位字段,equip_id改可空,新增imei/gateway_id/type_code/type_name/fire_system_code/fire_system_name/part_unit_loop_code/channel_no/channel_sn/produce_date,gateway_id外键→electric_gateway
- 同步服务IccLineSyncService复用OAuth2真实鉴权分页拉取探测器(POST /detector/subsystem/page,pageSize=50短页停止),按line_code(detectorCode)幂等upsert写icc_sync_log;customer_id由orgCode→customer.icc_code解析、gateway_id由parentCode→electric_gateway.device_code匹配、equip_id同步不填充
- 列表接口返回gateway/type/imei等新字段,keyword检索含imei;前端台账页更新为新列(IMEI/所属网关/探测器类型/回路通道/消防系统/生产日期),保留手动同步按钮与筛选
- 更新系统设计文档electric_line表定义与spec(add-icc-line-sync)
This commit is contained in:
wk authored and trae-solo-agent committed 2026-10-24 13:50:32 +08:00
1 parent cf0a0d4d31
commit 160ad85051
13 files changed
+510 -200

No files matched your search

+71
View File
@@ -0,0 +1,71 @@
# 智电线路真实 ICC 同步 Spec(add-icc-line-sync)
## Why
现有 electric_line(智电改造线路台账)为占位实现:表结构是手工设计的占位字段(building/floor/location 等),同步链路 `icc_line_sync.service.ts` 走假的 `ICC_TOKEN` 配置、无真实鉴权。本次依据 ICC 平台接口文档第三节「消防探测器分页查询」(`POST /evo-apigw/evo-fdbu/{version}/detector/subsystem/page`)将线路台账升级为**真实数据同步**:重建表结构(按 DetectorVO 落库字段 + 与 customer/customer_equipment/electric_gateway 三张表的关联),后端替换为真实 OAuth2 拉取(复用 icc_customer_auth),前端台账页补充新字段展示并保留手动同步按钮。
## What Changes
- **表结构变更(BREAKING)**:`electric_line` 按 DetectorVO 重建字段集:
- 删除:`building_id`、`floor_no`、`location`、`icc_device_code`(占位字段无真实数据源)
- `equip_id` 由 `NOT NULL` 改为**可空**(→ customer_equipment,同步不填充,留待手动关联)
- 新增:`imei`、`gateway_id`(→ electric_gateway)、`type_code`、`type_name`、`fire_system_code`、`fire_system_name`、`part_unit_loop_code`、`channel_no`、`channel_sn`、`produce_date`
- 保留:`line_code`(= detectorCode,唯一幂等键)、`line_name`(= detectorName)、`customer_id`(NOT NULL)、`status`(= detectorStatus:01→1 在线 / 02→0 离线)、`synced_at`、`created_at`
- 不落库(仅作关联匹配键):`orgCode`→customer.icc_code 反查 customer_id;`parentCode`→electric_gateway.device_code 反查 gateway_id
- **后端同步真实化**:重写 `icc_line_mapper.ts`(DetectorVO 映射 + 分页解析)与 `icc_line_sync.service.ts`(复用 `getIccAccessToken`/`iccFetch`,POST 分页 pageSize=50 短页停止、全量拉取、按 line_code 幂等 upsert、写 icc_sync_log sync_type=electric_line、失败仅记日志不抛)
- **关联规则**:customer_id 由 orgCode 匹配;gateway_id 由 parentCode 匹配 device_code;equip_id 同步不填充
- **前端台账页更新**:`views/device/line/index.vue` 移除楼层/建筑/位置列,新增探测器类型、IMEI、回路/通道、消防系统、生产日期、网关等列;保留「同步线路」手动按钮与筛选
- **设计文档同步**:更新 `系统设计/表结构新增及变更.md` 补充 electric_line 新结构
- 定时任务 `icc_line_sync`(jobKey 不变,cron */10)、菜单 61、RBAC `/api/electric-lines → device:list`、前端路由 `/device/line` 均沿用既有,无需新增
## Impact
- Affected specs:add-icc-line-ledger(本 spec 升级其占位实现)、add-icc-gateway-sync(复用其真实同步模式与关联表)
- Affected code:
- 后端:`server/src/entity/electric_line.entity.ts`、`server/src/task/icc_line_mapper.ts`、`server/src/service/icc_line_sync.service.ts`、`server/src/service/electric_line.service.ts`(decorate 去掉 building、新增 gateway/类型展示)、`server/src/controller/electric_line.controller.ts`(不动)
- 迁移:`database/migrations/20261011_icc_line_ledger.sql`(重建 electric_line 结构)或新增增量迁移;`database/db_seed.sql` 同步
- 前端:`client/src/views/device/line/index.vue`、`client/src/api/device.ts`(ElectricLine 类型)
- 设计文档:`系统设计/表结构新增及变更.md`
## ADDED Requirements
### Requirement: electric_line 表结构按 DetectorVO 重建
系统 SHALL 将 `electric_line` 重建为与 DetectorVO 对应的字段集,且:
- `line_code` 存 detectorCode(唯一,幂等键)
- `customer_id` NOT NULL,由 orgCode→customer.icc_code 反查
- `gateway_id` 可空,由 parentCode→electric_gateway.device_code 反查
- `equip_id` 可空,同步不填充
#### Scenario: 迁移执行成功
- **WHEN** 执行迁移到生产库
- **THEN** electric_line 包含新字段集,旧字段(building_id/floor_no/location/icc_device_code)被移除,equip_id 可空,索引重建;db_seed.sql 与生产库一致
### Requirement: 真实 ICC 探测器拉取同步
系统 SHALL 复用 `getIccAccessToken`/`iccFetch` 真实鉴权,POST `{baseUrl}/evo-apigw/evo-fdbu/{version}/detector/subsystem/page` 分页全量拉取(pageNum 递增、pageSize=50、短页停止、MAX_PAGES 保护),按 line_code 幂等 upsert,写 icc_sync_log(sync_type=electric_line)。
#### Scenario: 同步成功
- **WHEN** 手动点击「同步线路」或定时任务触发
- **THEN** 返回 {pulled, inserted, updated, skipped, synced};新探测器落库、重复 detectorCode 更新;customer_id 解析失败的行跳过;写成功日志
#### Scenario: 同步失败
- **WHEN** ICC 拉取异常(超时/HTTP 错误/鉴权失败)
- **THEN** 仅写 icc_sync_log 失败日志,不抛业务错误,接口返回 code 200 与当前计数
### Requirement: 前端台账页按新字段展示
系统 SHALL 更新 `views/device/line/index.vue`:删除建筑/楼层/位置列,新增探测器类型、IMEI、回路/通道、消防系统、生产日期、所属网关列;保留筛选(客户/状态/关键词)与「同步线路」手动按钮。
#### Scenario: 页面渲染
- **WHEN** 登录 admin 打开 /device/line
- **THEN** 表格展示新字段列,无 v-html,同步按钮触发 POST /api/electric-lines/sync
## MODIFIED Requirements
### Requirement: 线路台账列表接口(原有)
`GET /api/electric-lines` 保留分页/筛选/RBAC(非 ADMIN 限定 customer_id),decorate 从 building 改为 gateway/类型/IMEI 展示字段,删除 customer_building 关联。
#### Scenario: 列表返回
- **WHEN** 带权限请求 GET /api/electric-lines
- **THEN** 返回行包含 lineCode/lineName/imei/customer/gateway/type/loop/channel/fireSystem/produceDate/status/syncedAt
## REMOVED Requirements
### Requirement: 占位 ICC 同步实现(原 icc_line_sync.service / icc_line_mapper 假配置映射)
**Reason**:无真实鉴权与接口,与 ICC 文档字段不对应。
**Migration**:删除 `ICC_TOKEN` 占位用法,改为复用 icc_customer_auth 真实鉴权;映射按 DetectorVO 重写。