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:
1 parent
cf0a0d4d31
commit
160ad85051
13 files changed
+510
-200
No files matched your search
@@ -4,9 +4,9 @@ import { Repository } from "sequelize-typescript";
|
||||
import { Op } from "sequelize";
|
||||
import { Context } from "@midwayjs/koa";
|
||||
import ElectricLine from "../entity/electric_line.entity";
|
||||
import ElectricGateway from "../entity/electric_gateway.entity";
|
||||
import Customer from "../entity/customer.entity";
|
||||
import CustomerEquipment from "../entity/customer_equipment.entity";
|
||||
import CustomerBuilding from "../entity/customer_building.entity";
|
||||
import SysUserRole from "../entity/sysUserRole.entity";
|
||||
import SysRole from "../entity/sysRole.entity";
|
||||
|
||||
@@ -21,8 +21,8 @@ export class ElectricLineService {
|
||||
@InjectRepository(CustomerEquipment)
|
||||
equipmentModel!: Repository<CustomerEquipment>;
|
||||
|
||||
@InjectRepository(CustomerBuilding)
|
||||
buildingModel!: Repository<CustomerBuilding>;
|
||||
@InjectRepository(ElectricGateway)
|
||||
gatewayModel!: Repository<ElectricGateway>;
|
||||
|
||||
@InjectRepository(SysUserRole)
|
||||
userRoleModel!: Repository<SysUserRole>;
|
||||
@@ -44,12 +44,12 @@ export class ElectricLineService {
|
||||
if (query.keyword) {
|
||||
where[Op.or] = [
|
||||
{ lineName: { [Op.like]: `%${query.keyword}%` } },
|
||||
{ lineCode: { [Op.like]: `%${query.keyword}%` } }
|
||||
{ lineCode: { [Op.like]: `%${query.keyword}%` } },
|
||||
{ imei: { [Op.like]: `%${query.keyword}%` } }
|
||||
];
|
||||
}
|
||||
if (query.customerId !== undefined && query.customerId !== "") where.customerId = Number(query.customerId);
|
||||
if (query.equipId !== undefined && query.equipId !== "") where.equipId = Number(query.equipId);
|
||||
if (query.buildingId !== undefined && query.buildingId !== "") where.buildingId = Number(query.buildingId);
|
||||
if (query.status !== undefined && query.status !== "" && query.status !== null) where.status = Number(query.status);
|
||||
|
||||
// 非管理员按客户归属自动限定数据范围
|
||||
@@ -95,15 +95,15 @@ export class ElectricLineService {
|
||||
return { code: 200, message: "获取线路台账详情成功", data: decorated[0] };
|
||||
}
|
||||
|
||||
/** 补全客户/设备/建筑展示信息,避免 N+1。 */
|
||||
/** 补全客户/设备/网关展示信息,避免 N+1。 */
|
||||
private async decorate(rows: ElectricLine[]): Promise<any[]> {
|
||||
if (rows.length === 0) return rows as any;
|
||||
|
||||
const customerIds = [...new Set(rows.map((r) => r.customerId).filter(Boolean))];
|
||||
const equipIds = [...new Set(rows.map((r) => r.equipId).filter(Boolean))];
|
||||
const buildingIds = [...new Set(rows.map((r) => r.buildingId).filter(Boolean))];
|
||||
const gatewayIds = [...new Set(rows.map((r) => r.gatewayId).filter(Boolean))];
|
||||
|
||||
const [customers, equips, buildings] = await Promise.all([
|
||||
const [customers, equips, gateways] = await Promise.all([
|
||||
customerIds.length
|
||||
? this.customerModel.findAll({
|
||||
where: { id: { [Op.in]: customerIds } },
|
||||
@@ -116,28 +116,29 @@ export class ElectricLineService {
|
||||
attributes: ["id", "equipCode", "equipName"]
|
||||
})
|
||||
: Promise.resolve([]),
|
||||
buildingIds.length
|
||||
? this.buildingModel.findAll({
|
||||
where: { id: { [Op.in]: buildingIds } },
|
||||
attributes: ["id", "buildingName"]
|
||||
gatewayIds.length
|
||||
? this.gatewayModel.findAll({
|
||||
where: { id: { [Op.in]: gatewayIds } },
|
||||
attributes: ["id", "deviceCode", "deviceName"]
|
||||
})
|
||||
: Promise.resolve([])
|
||||
]);
|
||||
|
||||
const customerMap = new Map(customers.map((c) => [c.id, c]));
|
||||
const equipMap = new Map(equips.map((e) => [e.id, e]));
|
||||
const buildingMap = new Map(buildings.map((b) => [b.id, b]));
|
||||
const gatewayMap = new Map(gateways.map((g) => [g.id, g]));
|
||||
|
||||
return rows.map((row) => {
|
||||
const json: any = row.toJSON();
|
||||
const customer: any = customerMap.get(row.customerId);
|
||||
const equip: any = equipMap.get(row.equipId);
|
||||
const building: any = row.buildingId ? buildingMap.get(row.buildingId) : undefined;
|
||||
const equip: any = row.equipId ? equipMap.get(row.equipId) : undefined;
|
||||
const gateway: any = row.gatewayId ? gatewayMap.get(row.gatewayId) : undefined;
|
||||
json.customerNo = customer?.customerNo || "";
|
||||
json.customerName = customer?.customerName || "";
|
||||
json.equipCode = equip?.equipCode || "";
|
||||
json.equipName = equip?.equipName || "";
|
||||
json.buildingName = building?.buildingName || "";
|
||||
json.gatewayCode = gateway?.deviceCode || "";
|
||||
json.gatewayName = gateway?.deviceName || "";
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user