topo-engine 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1214,6 +1214,53 @@ const SYMBOL_SPEC = {
1214
1214
  function getSymbolSpec(cat) {
1215
1215
  return SYMBOL_SPEC[cat] || SYMBOL_SPEC.other;
1216
1216
  }
1217
+ function buildCustomerMap(customerData) {
1218
+ const map = /* @__PURE__ */ new Map();
1219
+ if (!Array.isArray(customerData)) return map;
1220
+ for (const entry of customerData) {
1221
+ if (entry && entry.psrId && Array.isArray(entry.consumerList)) {
1222
+ map.set(String(entry.psrId), entry.consumerList);
1223
+ }
1224
+ }
1225
+ return map;
1226
+ }
1227
+ const METER_CELL_W = 26;
1228
+ const METER_CELL_H = 38;
1229
+ const METER_GAP = 4;
1230
+ const METER_PAD = 6;
1231
+ const MAX_COLS = 5;
1232
+ const SHOW_NAME_LIMIT = 20;
1233
+ function injectCustomers(model, customerMap) {
1234
+ for (const node of model.nodes) {
1235
+ if (node.cat !== "meterBox") continue;
1236
+ const customers = customerMap.get(node.psrId);
1237
+ if (!customers || customers.length === 0) continue;
1238
+ node._customers = customers;
1239
+ if (customers.length === 1) {
1240
+ node._meterBoxMode = "single";
1241
+ node._meterBoxW = 30;
1242
+ node._meterBoxH = 38;
1243
+ } else {
1244
+ const showName = customers.length <= SHOW_NAME_LIMIT;
1245
+ const cols = Math.min(customers.length, MAX_COLS);
1246
+ const rows = Math.ceil(customers.length / cols);
1247
+ const cellW = METER_CELL_W;
1248
+ const cellH = showName ? METER_CELL_H : METER_CELL_W;
1249
+ node._meterBoxMode = "grid";
1250
+ node._meterBoxCols = cols;
1251
+ node._meterBoxRows = rows;
1252
+ node._meterBoxShowName = showName;
1253
+ node._meterBoxW = METER_PAD * 2 + cols * cellW + (cols - 1) * METER_GAP;
1254
+ node._meterBoxH = METER_PAD * 2 + rows * cellH + (rows - 1) * METER_GAP;
1255
+ }
1256
+ }
1257
+ }
1258
+ function getMeterBoxSize(node) {
1259
+ if (node._meterBoxW != null && node._meterBoxH != null) {
1260
+ return { w: node._meterBoxW, h: node._meterBoxH };
1261
+ }
1262
+ return null;
1263
+ }
1217
1264
  function stationPlans(model) {
1218
1265
  const nodesById = new Map(model.nodes.map((n) => [n.id, n]));
1219
1266
  const plans = [];
@@ -1265,6 +1312,10 @@ function stationInner(plan, model, band = 50, nodeMap) {
1265
1312
  const nmap = nodeMap || new Map(model.nodes.map((n) => [n.id, n]));
1266
1313
  const specOf = (id2) => {
1267
1314
  const n = nmap.get(id2);
1315
+ if (n && n.cat === "meterBox") {
1316
+ const dim = getMeterBoxSize(n);
1317
+ if (dim) return dim;
1318
+ }
1268
1319
  const s2 = getSymbolSpec(n ? n.cat : "other");
1269
1320
  return { w: s2.w, h: s2.h };
1270
1321
  };
@@ -1922,6 +1973,10 @@ function computeOrthogonalLayout(model, opts = {}) {
1922
1973
  const sz = (id2) => {
1923
1974
  const n = extNodeMap.get(id2);
1924
1975
  if (n && n._size) return n._size;
1976
+ if (n && n.cat === "meterBox") {
1977
+ const dim = getMeterBoxSize(n);
1978
+ if (dim) return dim;
1979
+ }
1925
1980
  const spec = getSymbolSpec(n ? n.cat : "other");
1926
1981
  return { w: spec.w, h: spec.h };
1927
1982
  };
@@ -2520,22 +2575,30 @@ function buildGraphData(model, layout) {
2520
2575
  const nodes = model.nodes.map((n) => {
2521
2576
  const spec = getSymbolSpec(n.cat);
2522
2577
  const busW = layout.stationBusWidth && layout.stationBusWidth.get(n.id);
2523
- const w = busW || spec.w;
2578
+ const meterBoxDim = n.cat === "meterBox" ? getMeterBoxSize(n) : null;
2579
+ const w = busW || (meterBoxDim ? meterBoxDim.w : spec.w);
2580
+ const h = meterBoxDim ? meterBoxDim.h : spec.h;
2524
2581
  const p = layout.pos.get(n.id) || { x: 0, y: 0 };
2525
2582
  return {
2526
2583
  id: n.id,
2527
- data: { ...n, width: w, height: spec.h },
2584
+ data: { ...n, width: w, height: h },
2528
2585
  style: {
2529
2586
  x: p.x,
2530
2587
  y: p.y,
2531
- size: [w, spec.h],
2588
+ size: [w, h],
2532
2589
  // 自定义字段(进 attributes,供 svg-symbol 节点绘制使用)
2533
2590
  cat: n.cat,
2534
- labelText: n.cat === "bus" || n.cat === "cableTerminal" ? "" : n.shortName || "",
2591
+ labelText: n.cat === "bus" || n.cat === "cableTerminal" || n.cat === "consumer" ? "" : n.shortName || "",
2535
2592
  rotate: layout.stationRotate && layout.stationRotate.get(n.id) || 0,
2536
2593
  highlight: 0,
2537
2594
  cursor: "pointer",
2538
- _nodeId: n.id
2595
+ _nodeId: n.id,
2596
+ // 计量箱客户数据
2597
+ _meterBoxMode: n._meterBoxMode || null,
2598
+ _meterBoxCols: n._meterBoxCols || 0,
2599
+ _meterBoxRows: n._meterBoxRows || 0,
2600
+ _meterBoxShowName: n._meterBoxShowName || false,
2601
+ _customers: n._customers || null
2539
2602
  }
2540
2603
  };
2541
2604
  });
@@ -27787,8 +27850,45 @@ function drawStationTerminal(attributes, group) {
27787
27850
  group.appendChild(new Polygon({ style: { points: [[0, -5], [0, 5], [9, 0]], fill: "none", stroke: C2.red, lineWidth: 1.4 } }));
27788
27851
  }
27789
27852
  function drawMeterBox(attributes, group) {
27790
- group.appendChild(new Rect({ style: { x: -9.5, y: -9.5, width: 19, height: 19, fill: C2.meterFill, stroke: C2.meterText, lineWidth: 0.9 } }));
27791
- text(attributes, group, "JX", 0, 0.5, 7.5, C2.meterText);
27853
+ const [w, h] = attributes.size;
27854
+ if (attributes._meterBoxMode === "single") {
27855
+ group.appendChild(new Circle({ style: { cx: 0, cy: -3, r: 11, fill: "none", stroke: C2.white, lineWidth: 1.6 } }));
27856
+ group.appendChild(new Line({ style: { x1: 0, y1: -14, x2: 0, y2: -7, stroke: C2.white, lineWidth: 1.6 } }));
27857
+ const name = attributes._customers && attributes._customers[0] ? attributes._customers[0].realConsName || attributes._customers[0].consName || "" : "";
27858
+ if (name) {
27859
+ group.appendChild(new Text({ style: { text: name, x: 0, y: 12, fontSize: 8, fill: C2.white, fontFamily: FONT, textAlign: "center", textBaseline: "middle" } }));
27860
+ }
27861
+ } else if (attributes._meterBoxMode === "grid" && attributes._customers) {
27862
+ group.appendChild(new Rect({ style: { x: -w / 2, y: -h / 2, width: w, height: h, fill: C2.meterFill, stroke: C2.meterText, lineWidth: 0.9, radius: 2 } }));
27863
+ const cols = attributes._meterBoxCols || 5;
27864
+ const customers = attributes._customers;
27865
+ const showName = attributes._meterBoxShowName;
27866
+ const cellW = METER_CELL_W;
27867
+ const cellH = showName ? METER_CELL_H : METER_CELL_W;
27868
+ const gridW = cols * cellW + (cols - 1) * METER_GAP;
27869
+ const rows = attributes._meterBoxRows || Math.ceil(customers.length / cols);
27870
+ const gridH = rows * cellH + (rows - 1) * METER_GAP;
27871
+ const startX = -gridW / 2;
27872
+ const startY = -gridH / 2;
27873
+ const meterR = 9;
27874
+ for (let i = 0; i < customers.length; i++) {
27875
+ const row2 = Math.floor(i / cols);
27876
+ const col = i % cols;
27877
+ const cx = startX + col * (cellW + METER_GAP) + cellW / 2;
27878
+ const cy = startY + row2 * (cellH + METER_GAP) + cellW / 2;
27879
+ group.appendChild(new Circle({ style: { cx, cy, r: meterR, fill: "none", stroke: C2.meterText, lineWidth: 0.8 } }));
27880
+ group.appendChild(new Line({ style: { x1: cx, y1: cy - meterR, x2: cx, y2: cy - meterR + 4, stroke: C2.meterText, lineWidth: 0.8 } }));
27881
+ if (showName) {
27882
+ const name = customers[i].realConsName || customers[i].consName || "";
27883
+ if (name) {
27884
+ group.appendChild(new Text({ style: { text: name, x: cx, y: cy + meterR + 6, fontSize: 7, fill: C2.meterText, fontFamily: FONT, textAlign: "center", textBaseline: "middle" } }));
27885
+ }
27886
+ }
27887
+ }
27888
+ } else {
27889
+ group.appendChild(new Rect({ style: { x: -9.5, y: -9.5, width: 19, height: 19, fill: C2.meterFill, stroke: C2.meterText, lineWidth: 0.9 } }));
27890
+ text(attributes, group, "JX", 0, 0.5, 7.5, C2.meterText);
27891
+ }
27792
27892
  }
27793
27893
  function drawConsumer(attributes, group) {
27794
27894
  group.appendChild(new Circle({ style: { cx: 0, cy: 0, r: 12.5, fill: "none", stroke: C2.white, lineWidth: 1.8 } }));
@@ -27914,8 +28014,10 @@ const _sfc_main$2 = {
27914
28014
  props: {
27915
28015
  dataUrl: { type: String, default: "" },
27916
28016
  data: { type: Object, default: null },
28017
+ /** 客户数据(计量箱关联的用户列表),直接传入 JSON 数组 */
28018
+ customerData: { type: Array, default: null },
27917
28019
  /** 主题:'dark'(默认,黑底 SCADA 风)| 'light'(白底);支持 v-model:theme 双向绑定 */
27918
- theme: { type: String, default: "dark" }
28020
+ theme: { type: String, default: "light" }
27919
28021
  },
27920
28022
  emits: ["node-select", "loaded", "top-distances", "update:theme"],
27921
28023
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -28031,6 +28133,10 @@ const _sfc_main$2 = {
28031
28133
  lastRaw.value = raw;
28032
28134
  const theme = applyTheme();
28033
28135
  model = parseTopo(raw);
28136
+ if (props.customerData && props.customerData.length) {
28137
+ const customerMap = buildCustomerMap(props.customerData);
28138
+ injectCustomers(model, customerMap);
28139
+ }
28034
28140
  nodeByIdMap = new Map(model.nodes.map((n) => [n.id, n]));
28035
28141
  title.value = String(model.title || "").replace(/\.+$/, "");
28036
28142
  stats.value = model.stats;
@@ -28162,6 +28268,13 @@ const _sfc_main$2 = {
28162
28268
  if (lastRaw.value) render(lastRaw.value);
28163
28269
  }
28164
28270
  );
28271
+ watch(
28272
+ () => props.customerData,
28273
+ () => {
28274
+ if (lastRaw.value) render(lastRaw.value);
28275
+ },
28276
+ { deep: true }
28277
+ );
28165
28278
  onBeforeUnmount(() => {
28166
28279
  if (api) {
28167
28280
  api.destroy();
@@ -28221,7 +28334,7 @@ const _sfc_main$2 = {
28221
28334
  };
28222
28335
  }
28223
28336
  };
28224
- const TopoGraph = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-562b2247"]]);
28337
+ const TopoGraph = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-c213df91"]]);
28225
28338
  const _hoisted_1$1 = ["data-theme"];
28226
28339
  const _hoisted_2$1 = { class: "panel-head" };
28227
28340
  const _hoisted_3$1 = {
@@ -28531,7 +28644,7 @@ const _sfc_main = {
28531
28644
  }
28532
28645
  };
28533
28646
  const DistanceTop10 = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-438b6017"]]);
28534
- const VERSION = "0.1.4";
28647
+ const VERSION = "0.1.5";
28535
28648
  const DESCRIPTION = "配电台区单线图拓扑成图引擎";
28536
28649
  export {
28537
28650
  DESCRIPTION,
@@ -28543,11 +28656,14 @@ export {
28543
28656
  TopoGraph,
28544
28657
  VERSION,
28545
28658
  assertOrthogonal,
28659
+ buildCustomerMap,
28546
28660
  buildGraphData,
28547
28661
  calculateTopDistances,
28548
28662
  computeOrthogonalLayout,
28549
28663
  edgeStyle,
28664
+ getMeterBoxSize,
28550
28665
  getSymbolSpec,
28666
+ injectCustomers,
28551
28667
  parseTopo
28552
28668
  };
28553
28669
  //# sourceMappingURL=topo-engine.js.map