topo-engine 0.1.6 → 0.1.8
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.
- package/README.md +38 -6
- package/dist/index.d.ts +16 -2
- package/dist/style.css +71 -42
- package/dist/topo-engine.cjs +11538 -10574
- package/dist/topo-engine.cjs.map +1 -1
- package/dist/topo-engine.js +11539 -10575
- package/dist/topo-engine.js.map +1 -1
- package/dist/topo-engine.umd.cjs +11538 -10574
- package/dist/topo-engine.umd.cjs.map +1 -1
- package/docs/API.md +1358 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -6,18 +6,19 @@
|
|
|
6
6
|
|
|
7
7
|
## 功能特性
|
|
8
8
|
|
|
9
|
-
- 🧩 **Vue 3 组件** — `TopoGraph
|
|
9
|
+
- 🧩 **Vue 3 组件** — `TopoGraph`(画布;可选左上工具条默认隐藏,`:toolbar` 开启)、`SidePanel`(设备详情与上下游)、`DistanceTop10`(父子连线距离 Top10 面板)
|
|
10
10
|
- 🎨 **深色 / 浅色双主题** — 黑底 SCADA 或白底两种画布风格,图元 / 导线 / 文字随之配套适配,可随时切换(`theme` prop 或工具栏按钮)。默认浅色主题
|
|
11
11
|
- 📐 **自研正交布局** — 主干沿最长路径横向铺开 + 分支带垂直直走,整图**横平竖直、0 交叉、0 重叠**,边缘路由为直线 / L 形折线
|
|
12
12
|
- 🔍 **拓扑查询 API** — 节点 / 边 / 邻居 / 子树 / 主干链 / 路径 / 坐标 查询
|
|
13
13
|
- 🎨 **样式控制** — 节点、边样式覆盖与批量重置
|
|
14
|
+
- 🎨 **节点 / 电表染色** — 按 **psrId(设备编码)** 染普通节点、按 **assetNo(资产编号)** 染计量箱内电表户(状态色、告警色场景)
|
|
14
15
|
- ✨ **动画与高亮** — 节点脉动、边流动、路径高亮、其余变暗、异常标注
|
|
15
16
|
- 📝 **文字标注** — 附加文字、用户名 full / short / hidden 切换
|
|
16
17
|
- 🃏 **卡片盒** — 节点信息卡片(字段 + 按钮),适配"运行曲线/工单跳转"类场景
|
|
17
18
|
- 🔗 **连接线 / 拓扑线** — 任意两节点动态连接线、路径拓扑高亮线
|
|
18
19
|
- 🎧 **事件系统** — 点击 / 悬停 / 画布空白 / 视口变化事件总线
|
|
19
20
|
- 💾 **导出** — 整图 PNG 下载、DataURL、图数据 JSON
|
|
20
|
-
- 📦 **零配置渲染** —
|
|
21
|
+
- 📦 **零配置渲染** — 组件内置主题与解析渲染,`data` 或 `dataUrl` 二选一即可出图
|
|
21
22
|
|
|
22
23
|
## 安装
|
|
23
24
|
|
|
@@ -33,6 +34,9 @@ npm install topo-engine
|
|
|
33
34
|
import 'topo-engine/style.css';
|
|
34
35
|
```
|
|
35
36
|
|
|
37
|
+
> 📖 **完整 API 参考手册**随包发布:安装后可打开 `node_modules/topo-engine/docs/API.md`,
|
|
38
|
+
> 或在线查看仓库中的 [docs/API.md](docs/API.md)(事件、卡片、连接线、布局参数、TS 类型等一应俱全)。
|
|
39
|
+
|
|
36
40
|
## 快速开始
|
|
37
41
|
|
|
38
42
|
### 1. 最小示例 —— 只画一张图
|
|
@@ -186,20 +190,24 @@ const g6Data = buildGraphData(model, layout); // → G6 可直接消费的 { n
|
|
|
186
190
|
| ---- | ---- | ---- | ---- |
|
|
187
191
|
| `dataUrl` | `String` | `''` | 拓扑 JSON 的 URL(内部 `fetch` 加载)。变化后自动重新加载 |
|
|
188
192
|
| `data` | `Object` | `null` | 直接传入 JSON 对象;优先级高于 `dataUrl`;深度 watch,变化自动重绘 |
|
|
193
|
+
| `customerData` | `Array` | `null` | 客户数据(`[{ psrId, consumerList }]`),注入计量箱并按户渲染 / 可点 |
|
|
189
194
|
| `theme` | `'dark' \| 'light'` | `'light'` | 画布主题:`dark`(黑底 SCADA)/ `light`(白底,图元配套加深,默认)。支持 `v-model:theme`,也可点内置工具栏 ☀️/🌙 按钮切换 |
|
|
195
|
+
| `toolbar` | `Boolean` | `false` | 是否显示左上工具条(标题 / 统计 / 主题 / 适应画布 / 导出 PNG),默认隐藏 |
|
|
190
196
|
|
|
191
197
|
### Emits
|
|
192
198
|
|
|
193
199
|
| 事件 | 载荷 | 触发时机 |
|
|
194
200
|
| ---- | ---- | ---- |
|
|
195
201
|
| `loaded` | `{ title, stats }`,`stats = { total, depth, leaves, byCat }` | 每次数据渲染完成 |
|
|
196
|
-
| `node-select` | `{ node, upstream, downstream }`(均为解析后模型节点) |
|
|
202
|
+
| `node-select` | `{ node, upstream, downstream }`(均为解析后模型节点) | 点击节点(含金框选中与详情联动);空白清除时 `node=null` |
|
|
203
|
+
| `customer-select` | `{ node, customer, index, count, upstream, downstream }` | 点中计量箱内某个用户(展示客户档案) |
|
|
197
204
|
| `top-distances` | `Array<{ parent: {id,name,catLabel}, child: {id,name,catLabel}, distance }>`(≤10) | 渲染完成时,父-子连线折线长度 Top10(过滤站内边与主干鱼骨边) |
|
|
198
205
|
|
|
199
206
|
### 内置交互与 UI
|
|
200
207
|
|
|
201
208
|
- 滚轮缩放、拖拽平移、悬停高亮(上下游与连线),点击选中(金色虚框,再次点空白取消)。
|
|
202
|
-
-
|
|
209
|
+
- **计量箱用户点击**:单户箱整箱即该户;多户箱点电表格 / 户名 = 该户客户档案(悬停青圈、选中金圈),点箱体空白 = 选中整箱(事件 `consumer:click` / `customer-select`)。
|
|
210
|
+
- 左上角工具条**默认隐藏**:传 `:toolbar="true"` 后显示标题 / `节点 n · 边 m · 深度 d · 叶子 l` 统计 / 「适应画布」/「导出 PNG」按钮。
|
|
203
211
|
- 加载中 / 出错(如 dataUrl 404)有内置遮罩提示。
|
|
204
212
|
- 卸载时自动 `destroy()` 图实例与事件监听,无内存泄漏。
|
|
205
213
|
|
|
@@ -211,6 +219,8 @@ const g6Data = buildGraphData(model, layout); // → G6 可直接消费的 { n
|
|
|
211
219
|
| ---- | ---- |
|
|
212
220
|
| `loadRaw(jsonText)` | 用一段 JSON 文本(如本地文件上传内容)重新成图 |
|
|
213
221
|
| `selectNode(id)` | 选中某节点并联动 `node-select` 事件 |
|
|
222
|
+
| `selectCustomer(nodeId, index)` | 编程式选中计量箱内第 `index` 户(联动 `customer-select`) |
|
|
223
|
+
| `getSelectedCustomer()` | 当前选中的户:`{ nodeId, index, customer, node } \| null` |
|
|
214
224
|
| `resetView()` | 适应画布 |
|
|
215
225
|
| `exportPng()` | 导出整图 PNG(按画布标题命名下载) |
|
|
216
226
|
| `getLayoutData()` | 获取当前正交布局数据(坐标 / 折线 / stats) |
|
|
@@ -220,7 +230,7 @@ const g6Data = buildGraphData(model, layout); // → G6 可直接消费的 { n
|
|
|
220
230
|
|
|
221
231
|
引擎内置两套主题,**浅色为默认**(白底,图元配套深色,适合打印或嵌入浅色页面);深色为**黑底 SCADA 风格**。
|
|
222
232
|
|
|
223
|
-
- `TopoGraph`:`:theme` 取值 `'
|
|
233
|
+
- `TopoGraph`:`:theme` 取值 `'light'`(默认)或 `'dark'`,推荐 `v-model:theme` 双向绑定;开启 `:toolbar="true"` 后工具条内置 ☀️ / 🌙 切换按钮(点击 emit `update:theme`)。
|
|
224
234
|
- `SidePanel` / `DistanceTop10`:同样接收 `theme` prop,与画布保持一致观感。
|
|
225
235
|
- 切换主题会**按当前数据自动重建画布**:G6 画布背景、图元、边、标注文字全部随主题更新,布局不变。
|
|
226
236
|
|
|
@@ -273,6 +283,24 @@ const dataUrl = ref('/data/topology.json');
|
|
|
273
283
|
`setNodeStyle(id, style)`、`batchSetNodeStyle(ids, style)`、`resetNodeStyle(id)`、`resetAllNodeStyles()`
|
|
274
284
|
`setEdgeStyle(src, tgt, style)`、`batchSetEdgeStyle([[src,tgt],…], style)`、`resetEdgeStyle(src, tgt)`
|
|
275
285
|
|
|
286
|
+
### 节点 / 箱内电表户染色(psrId / 资产编号)
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
// 普通节点:按 psrId(设备编码)整图单色换装(主体/引线/描边换成该色,白字细节保留)
|
|
290
|
+
topo.setNodeColor('8ff4786d548a7073a2517297e801518ff456732f4d', '#FF0000');
|
|
291
|
+
// 箱内电表户:按资产编号(assetNo,兼容 consNo/consId)染该户电表图标 + 户名
|
|
292
|
+
topo.setNodeColor('4230010007008084768', '#FF6600');
|
|
293
|
+
// 批量(数组 / 对象数组 / ref→color 对象均可)
|
|
294
|
+
topo.batchSetNodeColor({ '8ff4…': '#FF0000', '4230…': '#FF6600' });
|
|
295
|
+
// 清除 / 查询
|
|
296
|
+
topo.resetNodeColor('4230010007008084768');
|
|
297
|
+
topo.resetAllNodeColors();
|
|
298
|
+
topo.getNodeColor('4230010007008084768'); // → { kind, id, color } | null
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
> 引用规则与 `addConnection` 一致:节点 id / **psrId** 命中普通节点;**assetNo** 命中计量箱内某户电表。
|
|
302
|
+
> 染色记录随主题切换 / 数据重渲染自动保留并重放(无需重新设置)。详见 [docs/API.md](docs/API.md)。
|
|
303
|
+
|
|
276
304
|
### 高亮 / 变暗
|
|
277
305
|
|
|
278
306
|
```javascript
|
|
@@ -336,6 +364,7 @@ topo.removeAllTopoLines();
|
|
|
336
364
|
| `canvas:click` | `{ event }` | 画布空白处点击 |
|
|
337
365
|
| `viewport:change` | `{ zoom, center }` | 视口缩放 / 平移变化 |
|
|
338
366
|
| `card:button` | `{ nodeId, buttonIndex }` | 卡片按钮点击 |
|
|
367
|
+
| `consumer:click` | `{ nodeId, index, customer, node }` | 点中计量箱内用户(多户箱点格子;单户箱整箱即该户) |
|
|
339
368
|
|
|
340
369
|
```javascript
|
|
341
370
|
const handler = ({ nodeId }) => console.log('点击了', nodeId);
|
|
@@ -361,10 +390,13 @@ topo.off('node:click', handler); // 不传 handler 则移除该事件全部监
|
|
|
361
390
|
| 模式 | 条件 | 渲染效果 |
|
|
362
391
|
| ---- | ---- | ---- |
|
|
363
392
|
| 无客户数据 | 未传入 customerData 或无匹配 | 原始 JX 黑底白字方框 |
|
|
364
|
-
| 单用户 | customerList 有 1 个用户 | 电能表图标(圆圈 + 竖线)+
|
|
393
|
+
| 单用户 | customerList 有 1 个用户 | 电能表图标(圆圈 + 竖线)+ 用户名;**整箱即该户,点击即客户档案** |
|
|
365
394
|
| 多用户(显示名称) | customerList 2~20 个用户 | 方框内电能表网格,每个格子含图标 + 用户名(每行最多 5 个) |
|
|
366
395
|
| 多用户(仅图标) | customerList >20 个用户 | 方框内电能表网格,仅显示图标(格子更紧凑) |
|
|
367
396
|
|
|
397
|
+
> 交互:多用户箱内**点击某个电表格 / 户名 = 选中该户**(金圈高亮 + `customer-select` / `consumer:click`),
|
|
398
|
+
> 点箱体空白 / 外框 = 选中整箱;悬停该户有青圈提示。用户端点(连接线)用客户档案 `assetNo` 引用即可。
|
|
399
|
+
|
|
368
400
|
客户数据格式(与拓扑 JSON 配套的 customer JSON):
|
|
369
401
|
|
|
370
402
|
```json
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* 拓扑引擎类型声明文件
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
// 让本类型声明在消费方 tsconfig 未开启 ES2015+ lib 时也能编译:
|
|
6
|
+
// 声明里用到了 Map/Promise(TS2583: Cannot find name 'Map'),此处自动引入对应 lib 定义。
|
|
7
|
+
/// <reference lib="es2015.collection" />
|
|
8
|
+
/// <reference lib="es2015.promise" />
|
|
9
|
+
|
|
5
10
|
// 核心 API
|
|
6
11
|
export class TopoApi {
|
|
7
12
|
constructor(graph: any, model: any, layout: any, nodeByIdMap: Map<string, any>);
|
|
@@ -38,6 +43,13 @@ export class TopoApi {
|
|
|
38
43
|
batchSetNodeStyle(nodeIds: string[], style: object): void;
|
|
39
44
|
resetNodeStyle(nodeId: string): void;
|
|
40
45
|
resetAllNodeStyles(): void;
|
|
46
|
+
|
|
47
|
+
// 节点 / 箱内电表户染色(ref:节点 id 或 psrId;电表户用客户 assetNo/consNo/consId)
|
|
48
|
+
setNodeColor(ref: string, color: string | null): boolean;
|
|
49
|
+
batchSetNodeColor(entries: any, color?: string): { total: number, ok: number, failed: Array<{ ref: string, reason: string }> };
|
|
50
|
+
resetNodeColor(ref: string): boolean;
|
|
51
|
+
resetAllNodeColors(): void;
|
|
52
|
+
getNodeColor(ref: string): { kind: 'node' | 'customer', id: string, index?: number, color: string | null } | null;
|
|
41
53
|
|
|
42
54
|
// 边样式
|
|
43
55
|
setEdgeStyle(srcId: string, tgtId: string, style: object): void;
|
|
@@ -69,8 +81,9 @@ export class TopoApi {
|
|
|
69
81
|
hideCard(nodeId: string): void;
|
|
70
82
|
hideAllCards(): void;
|
|
71
83
|
|
|
72
|
-
//
|
|
73
|
-
|
|
84
|
+
// 连接线与拓扑线(端点支持节点 id 或箱内用户的客户档案编号 consNo/consId)
|
|
85
|
+
resolveUserRef(ref: string): string | null;
|
|
86
|
+
addConnection(fromId: string, toId: string, opts?: object): string | false;
|
|
74
87
|
removeConnection(fromId: string, toId: string): void;
|
|
75
88
|
removeAllConnections(): void;
|
|
76
89
|
addTopoLine(nodeIds: string[], opts?: object): string;
|
|
@@ -112,6 +125,7 @@ export function getSymbolSpec(cat: string): { w: number, h: number };
|
|
|
112
125
|
export function buildCustomerMap(customerData: Array<any>): Map<string, Array<any>>;
|
|
113
126
|
export function injectCustomers(model: any, customerMap: Map<string, Array<any>>): void;
|
|
114
127
|
export function getMeterBoxSize(node: any): { w: number, h: number } | null;
|
|
128
|
+
export function getCustomerLocalPositions(node: any): Array<{ x: number, y: number }>;
|
|
115
129
|
|
|
116
130
|
// 常量
|
|
117
131
|
export const SYMBOL_SPEC: Record<string, { w: number, h: number }>;
|
package/dist/style.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
/* —— 主题变量:dark 为默认值,light 由 [data-theme='light'] 覆盖 —— */
|
|
3
|
-
.topo-wrap[data-v-
|
|
3
|
+
.topo-wrap[data-v-c2cd8b2c] {
|
|
4
4
|
--tp-bg: #050505;
|
|
5
5
|
--tp-toolbar-bg: rgba(20, 20, 20, 0.88);
|
|
6
6
|
--tp-toolbar-border: #333;
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
overflow: hidden;
|
|
20
20
|
background: var(--tp-bg);
|
|
21
21
|
}
|
|
22
|
-
.topo-wrap[data-theme='light'][data-v-
|
|
22
|
+
.topo-wrap[data-theme='light'][data-v-c2cd8b2c] {
|
|
23
23
|
--tp-bg: #ffffff;
|
|
24
24
|
--tp-toolbar-bg: rgba(255, 255, 255, 0.92);
|
|
25
25
|
--tp-toolbar-border: #d9d9d9;
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
--tp-text: #555;
|
|
34
34
|
--tp-error: #d32f2f;
|
|
35
35
|
}
|
|
36
|
-
.topo-container[data-v-
|
|
36
|
+
.topo-container[data-v-c2cd8b2c] {
|
|
37
37
|
width: 100%;
|
|
38
38
|
height: 100%;
|
|
39
39
|
}
|
|
40
|
-
.topo-toolbar[data-v-
|
|
40
|
+
.topo-toolbar[data-v-c2cd8b2c] {
|
|
41
41
|
position: absolute;
|
|
42
42
|
top: 10px;
|
|
43
43
|
left: 12px;
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
color: var(--tp-text);
|
|
53
53
|
z-index: 10;
|
|
54
54
|
}
|
|
55
|
-
.topo-title[data-v-
|
|
55
|
+
.topo-title[data-v-c2cd8b2c] {
|
|
56
56
|
color: var(--tp-title);
|
|
57
57
|
font-weight: 600;
|
|
58
58
|
}
|
|
59
|
-
.topo-meta[data-v-
|
|
59
|
+
.topo-meta[data-v-c2cd8b2c] {
|
|
60
60
|
color: var(--tp-meta);
|
|
61
61
|
}
|
|
62
|
-
.btn[data-v-
|
|
62
|
+
.btn[data-v-c2cd8b2c] {
|
|
63
63
|
margin-left: 4px;
|
|
64
64
|
padding: 3px 10px;
|
|
65
65
|
border: 1px solid var(--tp-btn-border);
|
|
@@ -69,12 +69,12 @@
|
|
|
69
69
|
cursor: pointer;
|
|
70
70
|
font-size: 12px;
|
|
71
71
|
}
|
|
72
|
-
.btn[data-v-
|
|
72
|
+
.btn[data-v-c2cd8b2c]:hover {
|
|
73
73
|
border-color: var(--tp-accent);
|
|
74
74
|
color: var(--tp-accent);
|
|
75
75
|
}
|
|
76
|
-
.topo-loading[data-v-
|
|
77
|
-
.topo-error[data-v-
|
|
76
|
+
.topo-loading[data-v-c2cd8b2c],
|
|
77
|
+
.topo-error[data-v-c2cd8b2c] {
|
|
78
78
|
position: absolute;
|
|
79
79
|
inset: 0;
|
|
80
80
|
display: flex;
|
|
@@ -85,12 +85,12 @@
|
|
|
85
85
|
z-index: 5;
|
|
86
86
|
background: var(--tp-overlay-bg);
|
|
87
87
|
}
|
|
88
|
-
.topo-error[data-v-
|
|
88
|
+
.topo-error[data-v-c2cd8b2c] {
|
|
89
89
|
color: var(--tp-error);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/* —— 主题变量:dark 默认,light 由 [data-theme='light'] 覆盖 —— */
|
|
93
|
-
.panel[data-v-
|
|
93
|
+
.panel[data-v-f5a2adf8] {
|
|
94
94
|
--sp-bg: rgba(16, 16, 18, 0.96);
|
|
95
95
|
--sp-border: #2c2c30;
|
|
96
96
|
--sp-text: #ddd;
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
flex-direction: column;
|
|
117
117
|
color: var(--sp-text);
|
|
118
118
|
}
|
|
119
|
-
.panel[data-theme='light'][data-v-
|
|
119
|
+
.panel[data-theme='light'][data-v-f5a2adf8] {
|
|
120
120
|
--sp-bg: rgba(255, 255, 255, 0.97);
|
|
121
121
|
--sp-border: #e4e4ea;
|
|
122
122
|
--sp-text: #333;
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
--sp-hint: #8a8a8a;
|
|
136
136
|
--sp-label: #666;
|
|
137
137
|
}
|
|
138
|
-
.panel-head[data-v-
|
|
138
|
+
.panel-head[data-v-f5a2adf8] {
|
|
139
139
|
display: flex;
|
|
140
140
|
align-items: center;
|
|
141
141
|
justify-content: space-between;
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
color: var(--sp-title);
|
|
146
146
|
border-bottom: 1px solid var(--sp-border);
|
|
147
147
|
}
|
|
148
|
-
.panel-close[data-v-
|
|
148
|
+
.panel-close[data-v-f5a2adf8] {
|
|
149
149
|
border: none;
|
|
150
150
|
background: none;
|
|
151
151
|
color: var(--sp-close);
|
|
@@ -153,57 +153,86 @@
|
|
|
153
153
|
cursor: pointer;
|
|
154
154
|
line-height: 1;
|
|
155
155
|
}
|
|
156
|
-
.panel-close[data-v-
|
|
156
|
+
.panel-close[data-v-f5a2adf8]:hover {
|
|
157
157
|
color: var(--sp-close-hover);
|
|
158
158
|
}
|
|
159
|
-
.panel-body[data-v-
|
|
159
|
+
.panel-body[data-v-f5a2adf8] {
|
|
160
160
|
padding: 14px;
|
|
161
161
|
overflow-y: auto;
|
|
162
162
|
flex: 1;
|
|
163
163
|
}
|
|
164
|
-
.kv[data-v-
|
|
164
|
+
.kv[data-v-f5a2adf8] {
|
|
165
165
|
display: flex;
|
|
166
166
|
gap: 10px;
|
|
167
167
|
margin-bottom: 10px;
|
|
168
168
|
font-size: 13px;
|
|
169
169
|
word-break: break-all;
|
|
170
170
|
}
|
|
171
|
-
.kv .k[data-v-
|
|
171
|
+
.kv .k[data-v-f5a2adf8] {
|
|
172
172
|
color: var(--sp-sub);
|
|
173
173
|
flex: none;
|
|
174
|
-
width:
|
|
174
|
+
width: 74px;
|
|
175
175
|
}
|
|
176
|
-
.kv .v[data-v-
|
|
176
|
+
.kv .v[data-v-f5a2adf8] {
|
|
177
177
|
color: var(--sp-text);
|
|
178
178
|
}
|
|
179
|
-
.mono[data-v-
|
|
179
|
+
.mono[data-v-f5a2adf8] {
|
|
180
180
|
font-family: Consolas, monospace;
|
|
181
181
|
font-size: 12px;
|
|
182
182
|
color: var(--sp-mono);
|
|
183
183
|
}
|
|
184
|
-
.ok[data-v-
|
|
184
|
+
.ok[data-v-f5a2adf8] {
|
|
185
185
|
color: var(--sp-ok);
|
|
186
186
|
}
|
|
187
|
-
.warn[data-v-
|
|
187
|
+
.warn[data-v-f5a2adf8] {
|
|
188
188
|
color: var(--sp-warn);
|
|
189
|
+
}
|
|
190
|
+
/* 客户档案:所属计量箱信息卡 + 返回按钮 */
|
|
191
|
+
.cust-box[data-v-f5a2adf8] {
|
|
192
|
+
display: flex;
|
|
193
|
+
flex-direction: column;
|
|
194
|
+
gap: 8px;
|
|
195
|
+
padding: 8px 10px;
|
|
196
|
+
margin-bottom: 12px;
|
|
197
|
+
background: var(--sp-item);
|
|
198
|
+
border: 1px solid var(--sp-item-border);
|
|
199
|
+
border-radius: 5px;
|
|
200
|
+
}
|
|
201
|
+
.cust-box .kv[data-v-f5a2adf8] {
|
|
202
|
+
margin-bottom: 0;
|
|
203
|
+
}
|
|
204
|
+
.panel-back[data-v-f5a2adf8] {
|
|
205
|
+
align-self: flex-start;
|
|
206
|
+
border: 1px solid var(--sp-item-border);
|
|
207
|
+
border-radius: 4px;
|
|
208
|
+
background: var(--sp-item);
|
|
209
|
+
color: var(--sp-accent);
|
|
210
|
+
font-size: 12px;
|
|
211
|
+
padding: 3px 10px;
|
|
212
|
+
cursor: pointer;
|
|
213
|
+
}
|
|
214
|
+
.panel-back[data-v-f5a2adf8]:hover {
|
|
215
|
+
border-color: var(--sp-hover-border);
|
|
216
|
+
background: var(--sp-hover-bg);
|
|
217
|
+
color: var(--sp-title);
|
|
189
218
|
}
|
|
190
|
-
.neighbor-section[data-v-
|
|
219
|
+
.neighbor-section[data-v-f5a2adf8] {
|
|
191
220
|
margin-top: 16px;
|
|
192
221
|
border-top: 1px solid var(--sp-border);
|
|
193
222
|
padding-top: 12px;
|
|
194
223
|
}
|
|
195
|
-
.neighbor-title[data-v-
|
|
224
|
+
.neighbor-title[data-v-f5a2adf8] {
|
|
196
225
|
font-size: 13px;
|
|
197
226
|
font-weight: 600;
|
|
198
227
|
color: var(--sp-title);
|
|
199
228
|
margin-bottom: 6px;
|
|
200
229
|
}
|
|
201
|
-
.neighbor-list[data-v-
|
|
230
|
+
.neighbor-list[data-v-f5a2adf8] {
|
|
202
231
|
display: flex;
|
|
203
232
|
flex-direction: column;
|
|
204
233
|
gap: 4px;
|
|
205
234
|
}
|
|
206
|
-
.neighbor-item[data-v-
|
|
235
|
+
.neighbor-item[data-v-f5a2adf8] {
|
|
207
236
|
display: flex;
|
|
208
237
|
flex-direction: column;
|
|
209
238
|
gap: 3px;
|
|
@@ -214,34 +243,34 @@
|
|
|
214
243
|
cursor: pointer;
|
|
215
244
|
font-size: 12px;
|
|
216
245
|
}
|
|
217
|
-
.neighbor-item[data-v-
|
|
246
|
+
.neighbor-item[data-v-f5a2adf8]:hover {
|
|
218
247
|
border-color: var(--sp-hover-border);
|
|
219
248
|
background: var(--sp-hover-bg);
|
|
220
249
|
}
|
|
221
|
-
.n-main[data-v-
|
|
250
|
+
.n-main[data-v-f5a2adf8] {
|
|
222
251
|
display: flex;
|
|
223
252
|
align-items: center;
|
|
224
253
|
gap: 8px;
|
|
225
254
|
min-width: 0;
|
|
226
255
|
}
|
|
227
|
-
.n-type[data-v-
|
|
256
|
+
.n-type[data-v-f5a2adf8] {
|
|
228
257
|
flex: none;
|
|
229
258
|
color: var(--sp-accent);
|
|
230
259
|
font-size: 11px;
|
|
231
260
|
}
|
|
232
|
-
.n-name[data-v-
|
|
261
|
+
.n-name[data-v-f5a2adf8] {
|
|
233
262
|
color: var(--sp-text);
|
|
234
263
|
overflow: hidden;
|
|
235
264
|
text-overflow: ellipsis;
|
|
236
265
|
white-space: nowrap;
|
|
237
266
|
}
|
|
238
|
-
.n-psr[data-v-
|
|
267
|
+
.n-psr[data-v-f5a2adf8] {
|
|
239
268
|
display: flex;
|
|
240
269
|
align-items: center;
|
|
241
270
|
gap: 6px;
|
|
242
271
|
min-width: 0;
|
|
243
272
|
}
|
|
244
|
-
.n-psr-id[data-v-
|
|
273
|
+
.n-psr-id[data-v-f5a2adf8] {
|
|
245
274
|
font-family: Consolas, monospace;
|
|
246
275
|
font-size: 11px;
|
|
247
276
|
color: var(--sp-mono);
|
|
@@ -252,7 +281,7 @@
|
|
|
252
281
|
user-select: text;
|
|
253
282
|
-webkit-user-select: text;
|
|
254
283
|
}
|
|
255
|
-
.copy-btn[data-v-
|
|
284
|
+
.copy-btn[data-v-f5a2adf8] {
|
|
256
285
|
flex: none;
|
|
257
286
|
border: 1px solid var(--sp-item-border);
|
|
258
287
|
border-radius: 3px;
|
|
@@ -263,40 +292,40 @@
|
|
|
263
292
|
padding: 2px 5px;
|
|
264
293
|
cursor: pointer;
|
|
265
294
|
}
|
|
266
|
-
.copy-btn[data-v-
|
|
295
|
+
.copy-btn[data-v-f5a2adf8]:hover {
|
|
267
296
|
border-color: var(--sp-hover-border);
|
|
268
297
|
color: var(--sp-title);
|
|
269
298
|
background: var(--sp-hover-bg);
|
|
270
299
|
}
|
|
271
|
-
.neighbor-empty[data-v-
|
|
300
|
+
.neighbor-empty[data-v-f5a2adf8] {
|
|
272
301
|
font-size: 12px;
|
|
273
302
|
color: var(--sp-hint);
|
|
274
303
|
padding: 4px 0;
|
|
275
304
|
}
|
|
276
|
-
.stat-grid[data-v-
|
|
305
|
+
.stat-grid[data-v-f5a2adf8] {
|
|
277
306
|
display: grid;
|
|
278
307
|
grid-template-columns: 1fr 1fr;
|
|
279
308
|
gap: 10px;
|
|
280
309
|
margin-bottom: 16px;
|
|
281
310
|
}
|
|
282
|
-
.stat[data-v-
|
|
311
|
+
.stat[data-v-f5a2adf8] {
|
|
283
312
|
background: var(--sp-item);
|
|
284
313
|
border: 1px solid var(--sp-item-border);
|
|
285
314
|
border-radius: 6px;
|
|
286
315
|
padding: 10px;
|
|
287
316
|
text-align: center;
|
|
288
317
|
}
|
|
289
|
-
.stat-num[data-v-
|
|
318
|
+
.stat-num[data-v-f5a2adf8] {
|
|
290
319
|
font-size: 20px;
|
|
291
320
|
font-weight: 700;
|
|
292
321
|
color: var(--sp-accent);
|
|
293
322
|
}
|
|
294
|
-
.stat-label[data-v-
|
|
323
|
+
.stat-label[data-v-f5a2adf8] {
|
|
295
324
|
font-size: 12px;
|
|
296
325
|
color: var(--sp-label);
|
|
297
326
|
margin-top: 2px;
|
|
298
327
|
}
|
|
299
|
-
.hint[data-v-
|
|
328
|
+
.hint[data-v-f5a2adf8] {
|
|
300
329
|
font-size: 12px;
|
|
301
330
|
color: var(--sp-hint);
|
|
302
331
|
line-height: 1.7;
|