feat(integration): 新增数据接入监控页
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- 字段:车牌 / VIN / 品牌+型号 / GB32960 状态+最后接收 / JT808 状态+最后接收 / 接入时间 - 状态:在线 / 断流 / 未对接,三色 pill + 脉冲点 - 重点标记:双协议均未对接的车辆 → 行红底 + 警示图标 + 顶部 banner - 工具栏:搜索(车牌/VIN/品牌/型号)+ 5 维筛选 + 4 维排序 + CSV 导出 - KPI:总车辆 / GB 在线 / GB 断流 / JT 在线 / JT 断流 / 完全未对接 - 数据:fleet.js 增 brand/model/gbStatus/gbLastSeen/jtStatus/jtLastSeen/onboardAt - 路由 #/integration · sidebar 增 plug 图标项
This commit is contained in:
@@ -133,6 +133,60 @@ const _enrich = (v, i) => {
|
||||
const h2 = v.status === "danger" ? 0.8 : (v.soc / 100 * 5.6 + 0.2).toFixed(1);
|
||||
const motorTemp = v.status === "danger" ? 102 : 58 + Math.floor(r()*15);
|
||||
|
||||
// ── Brand & model — 真实国内氢能车型样本 ──
|
||||
const MODELS = [
|
||||
{ brand: "上汽大通", model: "MIFA-H 氢燃料 MPV" },
|
||||
{ brand: "上汽大通", model: "EUNIQ 7 氢电版" },
|
||||
{ brand: "现代", model: "NEXO" },
|
||||
{ brand: "丰田", model: "MIRAI 第二代" },
|
||||
{ brand: "格罗夫", model: "格罗夫氢能 SUV" },
|
||||
{ brand: "海马汽车", model: "7X-H" },
|
||||
{ brand: "红旗", model: "H5 FCV" },
|
||||
{ brand: "长安深蓝", model: "SL03 氢燃料版" },
|
||||
{ brand: "飞驰科技", model: "FCB80 氢燃料客车" },
|
||||
{ brand: "宇通客车", model: "ZK6105FCEVG3" },
|
||||
];
|
||||
const m = MODELS[Math.floor(r() * MODELS.length)];
|
||||
|
||||
// ── Integration / 对接情况 ──
|
||||
// src: T = TBOX(GB/T 32960), J = JT808/1078, B = both
|
||||
// 状态:online (recent) / offline (had data, now stale) / not_connected (从未对接)
|
||||
// 5% 完全未对接(重点标记) · 12% TBOX 断流 · 8% JT 断流
|
||||
const integFlag = r();
|
||||
let gbStatus, jtStatus;
|
||||
if (i >= 12 && integFlag < 0.05) {
|
||||
// 5% 全部未对接(重点标记)
|
||||
gbStatus = "not_connected";
|
||||
jtStatus = "not_connected";
|
||||
} else {
|
||||
if (v.src === "T" || v.src === "B") {
|
||||
gbStatus = (r() < 0.12) ? "offline" : "online";
|
||||
} else {
|
||||
gbStatus = (r() < 0.30) ? "offline" : "not_connected";
|
||||
}
|
||||
if (v.src === "J" || v.src === "B") {
|
||||
jtStatus = (r() < 0.08) ? "offline" : "online";
|
||||
} else {
|
||||
jtStatus = (r() < 0.20) ? "offline" : "not_connected";
|
||||
}
|
||||
}
|
||||
|
||||
// 时间戳生成
|
||||
const now = Date.now();
|
||||
const minute = 60 * 1000, hour = 60 * minute, day = 24 * hour;
|
||||
const tsFor = (st, baseSeed) => {
|
||||
if (st === "not_connected") return null;
|
||||
if (st === "online") return now - Math.floor(baseSeed * 5 * minute) - 2000; // 2s ~ 5min
|
||||
// offline
|
||||
return now - Math.floor(baseSeed * 7 * day) - 30 * minute; // 30min ~ 7d ago
|
||||
};
|
||||
const gbLastSeen = tsFor(gbStatus, r());
|
||||
const jtLastSeen = tsFor(jtStatus, r());
|
||||
|
||||
// 接入时间(首次对接日期,6 个月内随机)
|
||||
const onboardDays = Math.floor(r() * 180) + 7;
|
||||
const onboardAt = now - onboardDays * day;
|
||||
|
||||
return {
|
||||
...v,
|
||||
plate: v.id,
|
||||
@@ -148,6 +202,12 @@ const _enrich = (v, i) => {
|
||||
// Hydrogen-specific
|
||||
h2Pressure: parseFloat(h2),
|
||||
range: Math.round(v.soc * 6.2),
|
||||
// Brand / model
|
||||
brand: m.brand, model: m.model,
|
||||
// Integration / 对接情况
|
||||
gbStatus, gbLastSeen,
|
||||
jtStatus, jtLastSeen,
|
||||
onboardAt,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -175,6 +235,17 @@ const COUNTS = {
|
||||
acc[d.id] = VEHICLES.filter(v => v.dept === d.id).length;
|
||||
return acc;
|
||||
}, {}),
|
||||
// Integration / 数据接入
|
||||
gbOnline: VEHICLES.filter(v => v.gbStatus === "online").length,
|
||||
gbOffline: VEHICLES.filter(v => v.gbStatus === "offline").length,
|
||||
gbNotConn: VEHICLES.filter(v => v.gbStatus === "not_connected").length,
|
||||
jtOnline: VEHICLES.filter(v => v.jtStatus === "online").length,
|
||||
jtOffline: VEHICLES.filter(v => v.jtStatus === "offline").length,
|
||||
jtNotConn: VEHICLES.filter(v => v.jtStatus === "not_connected").length,
|
||||
// 完全未对接(重点标记)
|
||||
bothNone: VEHICLES.filter(v => v.gbStatus === "not_connected" && v.jtStatus === "not_connected").length,
|
||||
// 任一在线
|
||||
anyOnline: VEHICLES.filter(v => v.gbStatus === "online" || v.jtStatus === "online").length,
|
||||
};
|
||||
|
||||
// ── User roles for permission demo ────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user