Files
smart_grid_iot/系统设计/表结构新增及变更.md
T
wk dff366a823 feat(survey): 勘察业务重构为设备树明细模式并新增勘察完成流转
- 设备树明细模式:customer_equipment 新增 parent_id 自引用与树形查询(getTree/tree 接口),勘察明细按设备节点挂接(survey_detail 新增 equip_id,saveDetails 全量替换),新增迁移 20261024_survey_equipment_tree.sql 并同步 db_init;客户拜访页发起勘察改为两步向导路由(CustomerVisitSurveyCreate),form.vue 重构为两步向导
- 勘察明细页(detail.vue):三栏布局(设备树/拓扑图/属性与勘察登记);设备拓扑图修复显示不完整(tree roam 拖拽缩放+全展开+弹窗增高);新增/编辑设备表单「所在位置」改为「所属建筑」下拉并增加「所在楼层」;选择建筑后按建筑地上/地下层数动态生成楼层下拉(负N层在前,切换建筑清空楼层)
- 设备管理台账页:设备新增弹窗同步「所属建筑/所在楼层」动态下拉
- 台账页:进度跟踪主按钮改为跳转勘察明细页(DispatchSurveyDetail)而非编辑页;「审核测绘成果」按钮与复核弹窗标题改名「技术复核」
- 勘察完成流转:新增 PUT /api/survey-orders/:id/complete(现场勘察中→待技术复核,可见性校验+审计日志),勘察明细页新增「勘察完成」按钮(先保存明细再流转状态,成功后跳回台账页)
- 验证:server tsc 与 client vue-tsc 编译通过;浏览器端到端验证通过(技术复核按钮/弹窗标题、勘察完成按钮仅勘察中显示、进度跟踪跳转数字id)
2026-10-25 02:33:54 +08:00

163 lines
14 KiB
Markdown
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.
智电改造网关表:electric\_gatway(ICC同步)
| 字段 | 类型 | 键 | 说明 |
| :--------- | :---------- | :----- | :--------------- |
| id | BIGSERIAL | PK | 自增主键 |
| iccImei | VARCHAR(64) | UNIQUE | 设备唯一标识码,设备的imei号 |
| deviceCode | VARCHAR(64) | UNIQUE | 设备编码 |
| deviceName | VARCHAR(64) | <br /> | 设备名称 |
| <br /> | <br /> | <br /> | <br /> |
| <br /> | <br /> | <br /> | <br /> |
| <br /> | <br /> | <br /> | <br /> |
| <br /> | <br /> | <br /> | <br /> |
| <br /> | <br /> | <br /> | <br /> |
| <br /> | <br /> | <br /> | <br /> |
| <br /> | <br /> | <br /> | <br /> |
| <br /> | <br /> | <br /> | <br /> |
智电改造线路表:electric_line(ICC探测器同步)
| 字段 | 类型 | 键 | 说明 |
| :------------------ | :----------- | :----- | :------------------------------------------------------- |
| id | BIGSERIAL | PK | 自增主键 |
| line_code | VARCHAR(64) | UNIQUE | 探测器编码(ICC detectorCode,唯一幂等键) |
| equip_id | BIGINT | FK | 客户设备 ID(→ customer_equipment,可空,同步不填充) |
| gateway_id | BIGINT | FK | 网关设备 ID(→ electric_gateway,由 parentCode↔device_code 匹配) |
| customer_id | BIGINT | FK | 客户 ID(orgCode→customer.icc_code 解析,逻辑隔离键) |
| line_name | VARCHAR(128) | | 探测器名称(ICC detectorName) |
| imei | VARCHAR(64) | | 设备唯一标识码(ICC imei) |
| type_code | VARCHAR(32) | | 探测器类型编码 |
| type_name | VARCHAR(64) | | 探测器类型名称 |
| fire_system_code | VARCHAR(64) | | 消防系统编码 |
| fire_system_name | VARCHAR(128) | | 消防系统名称 |
| part_unit_loop_code | VARCHAR(64) | | 探测器回路号 |
| channel_no | VARCHAR(64) | | 探测器通道号 |
| channel_sn | VARCHAR(64) | | 通道唯一标识码 |
| produce_date | VARCHAR(16) | | 生产日期(yyyy-MM-dd) |
| status | SMALLINT | | 探测器状态:1在线 0离线(detectorStatus 01→1 / 02→0) |
| synced_at | TIMESTAMPTZ | | ICC 同步时间 |
| created_at | TIMESTAMPTZ | | 创建时间 |
electricity_data 表结构重建(ICC 模拟量同步)
原 `electricity_data`(线路用电信息表)仅有一版占位定义(单列 `electricity`),与 ICC 平台「消防最新模拟量信息分页查询」接口(`POST /evo-apigw/evo-fdbu/{version}/analog/subsystem/page`,实际返回 `AnalogInfoVO{deviceCode, uniqueCode, analogType, analogValue, analogUnit, analogName}`,无 reportTime)不对应,本次按接口返回数据重建表结构,并实现真实同步服务与定时任务。
| 字段 | 类型 | 键 | 说明 |
| :---------- | :------------ | :----------------- | :---------------------------------------------- |
| id | BIGSERIAL | PK(复合) | 自增主键(与 collect_time 组成复合主键) |
| line_id | BIGINT NOT NULL | FK | 线路 ID(→ electric_line.id) |
| line_code | VARCHAR(64) NOT NULL | UNIQUE(复合) | 线路编码(= ICC deviceCode,冗余 + 幂等键) |
| imei | VARCHAR(64) | | 设备唯一标识码(= ICC uniqueCode) |
| line_name | VARCHAR(128) | | 线路名称(冗余展示) |
| customer_id | BIGINT NOT NULL | | 客户 ID(逻辑隔离键 → customer.id) |
| analog_type | VARCHAR(64) | | 模拟量类型(= ICC analogType) |
| analog_name | VARCHAR(128) | | 模拟量名称(= ICC analogName,如"剩余电流") |
| analog_unit | VARCHAR(32) | | 模拟量单位(= ICC analogUnit,如"mA") |
| analog_value | NUMERIC(14,4) | | 模拟量值(= ICC analogValue) |
| collect_time | TIMESTAMPTZ NOT NULL | PK(复合)/分区键 | 采集时间 = 同步拉取时间(ICC 最新模拟量接口实际不返回 reportTime,经确认以同步时间作为分区键与采集时间) |
键与分区:
- 主键:`(id, collect_time)`(复合主键,兼容按月分区)
- 唯一键:`UNIQUE(line_code, analog_type, collect_time)`,作幂等键(同键重复上报覆盖更新)
- 分区:按 `collect_time` 按月 RANGE 分区,初始分区 `2026_10`~`2027_03`(`electricity_data_2026_10`~`electricity_data_2027_03`,共 6 个),后续按月自动/手动创建
- 索引:`idx_ed_customer(customer_id)`、`idx_ed_line(line_id)`、`idx_ed_time(collect_time)`、`idx_ed_customer_time(customer_id, collect_time)`(父表创建,自动继承到各分区)
关联关系:
- `line_id` → `electric_line.id`(再由 electric_line 关联 customer 与 customer_equipment)
- `customer_id` → `customer.id`(逻辑隔离键)
- **明确注明:按需求确认,`equip_id` 字段已删除,本表不再直接关联 customer_equipment。**
变更说明:
- 删除旧占位列 `electricity`(重建为通用模拟量行:analog_type / analog_value)与 `equip_id`
- 原 `icc_device_code` 更名 `imei`(映射 uniqueCode)
- 迁移文件:`database/migrations/20261024_icc_analog_data.sql`(建表/分区/索引/注释 + sys_job 种子,2026-10-24 已执行到生产库),`database/db_init.sql` 同步更新
同步服务说明:
- 默认每 5 分钟执行一次;复用 ICC OAuth2 鉴权(`getIccAccessToken`/`iccFetch`)
- 先读取已同步 `electric_line` 的 line_code(= detectorCode),按 deviceCodes 分批(每批 ≤50 个)POST 模拟量接口(pageSize=500,短页停止全量拉取)
- 字段映射:imei=uniqueCode、analog_type=analogType、analog_name=analogName、analog_unit=analogUnit、analog_value=analogValue;collect_time = 同步拉取时间(ICC 最新模拟量接口实际不返回 reportTime,经确认以同步时间作为分区键与采集时间);预取 deviceCode→(line_id, customer_id) 映射避免 N+1
- 按 `(line_code, analog_type, collect_time)` 幂等 upsert(同一次同步内重复则覆盖更新);写 `icc_sync_log`(sync_type=electricity_data);拉取失败仅记日志不抛业务错
定时任务:
- jobKey=`icc_analog_sync`,cron `*/5 * * * *`(默认每 5 分钟,sys_job 种子幂等,注册进 job_registry/JobRuntime)
- 手动同步接口:`POST /api/electricity-data/sync`(JWT+RBAC `device:list`,返回 pulled/inserted/updated/skipped/synced)
- 不做前端页面/菜单
2026-10-24 ICC 报警事件订阅
`device_alarm`(设备报警信息表)与 `alarm_dispatch`(报警派单信息表)原为旧设计(含 equip_id/building_id/floor_no/location/history_count/fault_type/alarm_date 等与 ICC 事件结构不符的字段),本次按 ICC 平台事件订阅推送的通用事件格式重建。两表均为空表,已 DROP 重建。迁移文件:`database/migrations/20261024_icc_event_alarm.sql`(2026-10-24 已执行到生产库),`database/db_init.sql` 同步更新。
device_alarm 表(设备报警信息表,ICC 事件订阅)
| 字段 | 类型 | 键 | 说明 |
| :---------- | :------------ | :----- | :-------------------------------------------------- |
| id | BIGSERIAL | PK | 自增主键 |
| alarm_code | VARCHAR(128) | UNIQUE | ICC 报警编码(幂等键) |
| uuid | VARCHAR(128) | | ICC 事件 uuid |
| line_id | BIGINT | IDX | 智电线路 ID(→ electric_line,nodeCode/deviceCode 匹配 line_code) |
| line_code | VARCHAR(64) | | 线路编码(electric_line.line_code) |
| line_name | VARCHAR(128) | | 线路名称 |
| customer_id | BIGINT | IDX | 客户 ID(由 line_id 联出) |
| node_code | VARCHAR(64) | | 探测器节点编码(info.nodeCode) |
| device_code | VARCHAR(64) | | 设备编码(info.deviceCode) |
| device_name | VARCHAR(128) | | 设备名称(info.deviceName) |
| org_code | VARCHAR(64) | | 组织编码(info.orgCode) |
| org_name | VARCHAR(128) | | 组织名称(info.orgName) |
| alarm_type | INT | | 报警类型(info.alarmType) |
| alarm_grade | SMALLINT | IDX | 报警等级 1/2/3(1 最严重) |
| alarm_stat | SMALLINT | | 报警状态(info.alarmStat) |
| is_event | BOOLEAN | | 是否事件(info.isEvent) |
| alarm_time | TIMESTAMPTZ | IDX | 报警发生时间(info.alarmDate 秒级时间戳) |
| alarm_value | NUMERIC(14,4) | | 报警数值(部分事件带值,可空) |
| synced_at | TIMESTAMPTZ | | 入库时间 |
alarm_dispatch 表(报警派单信息表)
| 字段 | 类型 | 键 | 说明 |
| :----------- | :------------ | :----- | :-------------------------------------- |
| id | BIGSERIAL | PK | 自增主键 |
| dispatch_no | VARCHAR(64) | UNIQUE | 报警派单号(如 AD20261024001,生成规则由后端实现) |
| alarm_id | BIGINT | IDX | 报警 ID(→ device_alarm) |
| line_id | BIGINT | | 线路 ID |
| line_code | VARCHAR(64) | | 线路编码 |
| line_name | VARCHAR(128) | | 线路名称 |
| customer_id | BIGINT | FK | 客户 ID(→ customer) |
| alarm_time | TIMESTAMPTZ | | 报警时间(快照) |
| alarm_grade | SMALLINT | | 报警等级(快照) |
| fault_desc | TEXT | | 故障事项(报警类型描述) |
| dispatcher | VARCHAR(64) | | 派发人(当前登录用户 realName) |
| worker_id | BIGINT | IDX | 共享电工 ID(→ worker) |
| status | SMALLINT | IDX | 状态:0已派发 1已处理 |
| created_at | TIMESTAMPTZ | | 创建时间 |
| completed_at | TIMESTAMPTZ | | 完成时间 |
订阅机制:
- 回调接口:`POST /api/icc-event/callback`,接收 ICC 平台事件订阅推送的报警事件,按 `alarm_code` 幂等入库 device_alarm(重复事件覆盖更新)
- 保活任务:每 30 分钟执行一次(向 ICC 平台上报回调地址,保活事件订阅)
- 字段映射:info.nodeCode→node_code、info.deviceCode→device_code、info.deviceName→device_name、info.orgCode→org_code、info.orgName→org_name、info.alarmType→alarm_type、info.alarmGrade→alarm_grade、info.alarmStat→alarm_stat、info.isEvent→is_event、info.alarmDate(秒级时间戳)→alarm_time;line_id/line_code/customer_id 由 nodeCode/deviceCode 匹配 electric_line.line_code 联出
- 报警派单:从 device_alarm 派单写入 alarm_dispatch,dispatch_no 生成规则由后端实现(如 AD20261024001)
勘察派单重构(20261024):客户设备表树形化 + 勘察明细关联设备
背景:现场勘察流程中,客户设备(customer_equipment)需表达配电层级(配电间→配电箱/井/柜,支持多级嵌套);勘察明细(survey_detail)需按设备树维护并拓扑展示。
| 表 | 字段变更 | 类型/键 | 说明 |
| :-- | :------ | :----- | :--- |
| customer_equipment | 新增 parent_id | BIGINT,FK(自引用) | 父设备 ID,空为根设备,支持多级嵌套 |
| customer_equipment | equip_type 取值扩展 | VARCHAR(32) | 设备类型:配电间/配电井/配电箱/配电柜 |
| survey_detail | 新增 equip_id | BIGINT,FK(→ customer_equipment) | 勘察明细挂接到设备节点,photos/remark 仍挂在明细上 |
说明:
- 新增接口:`GET /api/customer-equipments/tree?customerId=xx` 返回按 parent_id 组装的嵌套设备树(数据权限与列表一致)
- 创建/更新设备支持 `parentId`,校验父设备存在、同属客户、非自身/子节点(防循环)
- 勘察明细保存(`PUT /api/survey-orders/:id/details`)新增 `equipId` 必填校验(设备属于工单客户),全量替换
- survey_detail 原 building/floor/room 字段保留为可空,兼容历史数据;新流程以设备树为主