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

+29 -11
View File
@@ -16,7 +16,7 @@
<span class="main-title">智电改造线路台账</span>
<span class="sub-title">ELECTRIC LINE LEDGER</span>
</div>
<p class="desc">由 ICC 平台同步的智电改造线路台账,按客户、设备、建筑查看线路及在线状态。</p>
<p class="desc">由 ICC 平台同步的智电改造线路台账,按客户、网关查看线路、探测器及在线状态。</p>
</div>
</div>
</div>
@@ -47,7 +47,7 @@
<label class="filter-label">关键词检索</label>
<a-input
v-model:value="searchForm.keyword"
placeholder="线路名称 / 线路编码"
placeholder="线路名称 / 编码 / IMEI"
allow-clear
@pressEnter="handleSearch"
>
@@ -103,16 +103,32 @@
<span class="line-name">{{ record.lineName || '-' }}</span>
</template>
<template v-else-if="column.key === 'imei'">
<span class="mono">{{ record.imei || '-' }}</span>
</template>
<template v-else-if="column.key === 'customerId'">
{{ record.customerName ? `${record.customerName}(${record.customerNo})` : '-' }}
</template>
<template v-else-if="column.key === 'equipId'">
{{ record.equipName ? `${record.equipName}(${record.equipCode})` : '-' }}
<template v-else-if="column.key === 'gatewayId'">
{{ record.gatewayName ? `${record.gatewayName}(${record.gatewayCode})` : (record.gatewayCode || '-') }}
</template>
<template v-else-if="column.key === 'buildingId'">
{{ record.buildingName || '-' }}
<template v-else-if="column.key === 'typeName'">
{{ record.typeName || '-' }}
</template>
<template v-else-if="column.key === 'loopChannel'">
{{ [record.partUnitLoopCode, record.channelNo].filter(Boolean).join('/') || '-' }}
</template>
<template v-else-if="column.key === 'fireSystemName'">
{{ record.fireSystemName || '-' }}
</template>
<template v-else-if="column.key === 'produceDate'">
{{ record.produceDate || '-' }}
</template>
<template v-else-if="column.key === 'status'">
@@ -172,11 +188,13 @@ const customerOptions = ref<{ label: string; value: number }[]>([]);
const columns = [
{ title: '线路编码', dataIndex: 'lineCode', key: 'lineCode', ellipsis: true, width: 160 },
{ title: '线路名称', dataIndex: 'lineName', key: 'lineName', ellipsis: true },
{ title: 'IMEI', dataIndex: 'imei', key: 'imei', ellipsis: true, width: 180 },
{ title: '所属客户', dataIndex: 'customerId', key: 'customerId', ellipsis: true, width: 180 },
{ title: '所属设备', dataIndex: 'equipId', key: 'equipId', ellipsis: true, width: 180 },
{ title: '所属建筑', dataIndex: 'buildingId', key: 'buildingId', ellipsis: true, width: 140 },
{ title: '所在楼层', dataIndex: 'floorNo', key: 'floorNo', ellipsis: true, width: 100 },
{ title: '所在位置', dataIndex: 'location', key: 'location', ellipsis: true },
{ title: '所属网关', dataIndex: 'gatewayId', key: 'gatewayId', ellipsis: true, width: 180 },
{ title: '探测器类型', dataIndex: 'typeName', key: 'typeName', ellipsis: true, width: 120 },
{ title: '回路/通道', dataIndex: 'loopChannel', key: 'loopChannel', ellipsis: true, width: 160 },
{ title: '消防系统', dataIndex: 'fireSystemName', key: 'fireSystemName', ellipsis: true, width: 140 },
{ title: '生产日期', dataIndex: 'produceDate', key: 'produceDate', ellipsis: true, width: 120 },
{ title: '状态', dataIndex: 'status', key: 'status', align: 'center' as const, width: 80 },
{ title: '同步时间', dataIndex: 'syncedAt', key: 'syncedAt', ellipsis: true, width: 170 },
];
@@ -499,4 +517,4 @@ function formatTime(val?: string) {
background: #136bfb;
border-color: #136bfb;
}
</style>
</style>