gis-view-webgl2 0.1.11 → 0.1.13
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 +0 -24
- package/dist/gis-view.css +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +524 -33
- package/dist/index.js +1 -1
- package/docs/AI/345/257/271/350/257/235/346/261/207/346/200/273.md +156 -8
- package/docs/GisView.md +6 -6
- package/docs/ai/06-/344/274/232/350/257/235/347/264/242/345/274/225/344/270/216/345/244/215/346/237/245/346/226/271/346/263/225.md +157 -7
- package/docs/demos/BackgroundDemo.vue +600 -0
- package/docs/demos/ChannelDemo.vue +145 -3
- package/docs/demos/StyleDemo.vue +280 -69
- package/docs/demos/api-index.js +35 -19
- package/docs/demos/demos.js +26 -18
- package/docs/demos/gis-view-demo/demo.css +76 -0
- package/docs/demos/gis-view-demo/panels/StylePanels.vue +24 -8
- package/docs/demos/gis-view-demo/panels/ViewPanels.vue +33 -3
- package/docs/demos/gis-view-demo/useGisViewDemo.js +236 -22
- package/docs/format/02-/350/212/202/347/202/271/344/270/216/347/272/277/350/267/257.md +1 -1
- package/docs/format/03-/346/213/220/347/202/271/350/243/205/351/245/260/344/270/216/346/240/267/345/274/217.md +3 -3
- package/docs/from0/06-/344/273/216/346/225/260/346/215/256/345/210/260/345/256/236/344/276/213-/350/247/243/346/236/220/345/261/202.md +13 -11
- package/docs/from0/15-/351/231/204/345/275/225-/345/270/270/351/207/217/351/200/237/346/237/245/344/270/216/350/270/251/345/235/221/346/270/205/345/215/225.md +1 -1
- package/docs/index.html +2 -2
- package/docs/internals/10-/350/247/204/345/210/231/346/235/241/344/273/266/344/270/216/347/212/266/346/200/201/346/240/267/345/274/217.md +3 -3
- package/docs/internals/13-/351/271/260/347/234/274/345/233/276.md +1 -1
- package/docs/internals/14-/350/203/214/346/231/257/345/261/202.md +1 -0
- package/docs/internals/15-03-/351/200/220/350/275/256/350/256/260/345/275/225-/346/200/247/350/203/275/344/270/216/344/277/256/345/244/215-/344/270/213.md +199 -0
- package/docs/internals/17-/350/260/203/350/257/225/344/270/216/346/211/251/345/261/225/345/273/272/350/256/256.md +1 -1
- package/docs/internals/18-/346/200/247/350/203/275/345/256/236/346/265/213/344/270/216WebGPU/350/257/204/344/274/260.md +32 -0
- package/docs/manual/02-/345/235/220/346/240/207/344/270/216/346/225/260/346/215/256.md +1 -1
- package/docs/manual/03-/351/205/215/347/275/256/351/241/271.md +217 -26
- package/docs/manual/07-/346/214/207/351/222/210/344/270/216/350/246/201/347/264/240/347/274/226/350/276/221.md +2 -2
- package/docs/manual/08-/351/200/211/344/270/255/344/270/216/346/213/220/347/202/271.md +37 -4
- package/docs/manual/09-/351/200/232/351/201/223/344/270/216/345/244/232/345/233/236/347/272/277.md +58 -1
- package/docs/manual/11-/346/240/267/345/274/217/344/270/216/350/247/204/345/210/231.md +59 -8
- package/docs/manual/12-/346/240/207/347/255/276/344/270/216/350/243/205/351/245/260.md +1 -1
- package/docs/manual/13-/345/212/250/346/225/210/344/270/216/345/233/276/345/205/203.md +220 -2
- package/docs/manual/14-/350/247/206/345/233/276/344/270/216/347/255/233/351/200/211.md +77 -16
- package/docs/manual/15-/345/257/274/345/207/272/344/270/216/351/233/206/346/210/220.md +30 -17
- package/docs/manual/16-/345/256/236/344/276/213/346/226/271/346/263/225/346/200/273/350/241/250.md +11 -4
- package/docs/manual/17-/345/217/202/346/225/260/351/200/237/346/237/245.md +17 -8
- package/docs/manual/18-/351/200/220/346/226/271/346/263/225/347/244/272/344/276/213.md +128 -4
- package/docs/manual/19-/350/257/273/346/225/260/344/270/216/346/213/226/346/213/275/351/242/204/350/247/210.md +2 -2
- package/docs/manual/20-/346/200/247/350/203/275/344/270/216/345/244/247/346/225/260/346/215/256.md +13 -1
- package/docs/manual/21-/350/257/264/346/230/216/344/270/216/345/270/270/350/247/201/351/227/256/351/242/230.md +4 -1
- package/docs/steps/index.html +1 -1
- package/docs/steps/selftest-demo.html +2 -2
- package/docs/steps/selftest-demos.html +626 -11
- package/docs/steps/selftest-docs.html +8 -4
- package/docs/steps/selftest-features.html +1428 -2
- package/docs/steps/selftest-perf.html +296 -25
- package/docs/steps/selftest-scale.html +61 -3
- package/docs/steps/selftest-select.html +303 -1
- package/docs/steps/step-06-style.js +3 -2
- package/package.json +2 -2
|
@@ -43,12 +43,17 @@ const simplifyColor = ref('#ff6b35')
|
|
|
43
43
|
const simplifyWidth = ref(4)
|
|
44
44
|
const simplifyDash = ref('dashed')
|
|
45
45
|
const simplifyText = ref('通道简略:关(reopen 后甲 / 丙通道会各折叠成一条代表线)')
|
|
46
|
+
/** 隐藏回线 / 分组后,剩余回线是保留原槽位还是重新居中;切完立刻重排车道 */
|
|
47
|
+
const channelHiddenLineLayout = ref('preserve')
|
|
48
|
+
const groupVisibilityText = ref('分组显隐:先点「准备两分组」,再试单组 / 批量隐藏与恢复')
|
|
49
|
+
const channelLaneText = ref('车道布局:—')
|
|
46
50
|
/** 待确认的删除请求('remove' 事件的 pending 载荷):确认框照着它渲染 */
|
|
47
51
|
const removeRequest = ref(null)
|
|
48
52
|
const removeText = ref('删除:按 Delete 或点上面的按钮,先出载荷、确认之后才动数据')
|
|
49
53
|
const channelsText = ref('—')
|
|
50
54
|
const groupsText = ref('—')
|
|
51
55
|
const visibilityText = ref('隐藏 / 显示:—')
|
|
56
|
+
const channelLineVisibilityText = ref('通道内线路显隐:—')
|
|
52
57
|
const changedText = ref('最近变化:—')
|
|
53
58
|
const exportText = ref('')
|
|
54
59
|
const logLines = ref([])
|
|
@@ -317,6 +322,8 @@ const buildOptions = () => ({
|
|
|
317
322
|
// 分组拐点拖动:共用骨架 / 只移同组同序号拐点
|
|
318
323
|
channelWaypointDragMode: channelWaypointDragMode.value,
|
|
319
324
|
channelSimplify: simplifyOption(),
|
|
325
|
+
// 隐藏回线 / 分组后:保留原车道槽位,或让剩余可见回线重新居中
|
|
326
|
+
channelHiddenLineLayout: channelHiddenLineLayout.value,
|
|
320
327
|
// 删除配置:confirm 缺省(null)表示组件不弹界面、停在待确认 —— 这一页订阅 'remove' 事件自己画确认框
|
|
321
328
|
remove: { scope: 'lines' },
|
|
322
329
|
// 交互框里的「加拐点 / 删拐点」动的是分组骨架,要有这一项才不是灰的(Ctrl + 点击加点、双击删点也一起开了)
|
|
@@ -376,6 +383,113 @@ const applyChannelSimplify = () => {
|
|
|
376
383
|
pushLog(simplifyText.value)
|
|
377
384
|
}
|
|
378
385
|
|
|
386
|
+
/** 车道读数:隐藏组仍保留成员与偏移,读 getChannels() 就能看出 preserve / center 的差别 */
|
|
387
|
+
const syncGroupVisibilityReadout = () => {
|
|
388
|
+
const entry = view?.getChannels()?.[0]
|
|
389
|
+
const channelId = entry?.channelId ?? entry?.id
|
|
390
|
+
if (channelId === undefined || channelId === null) {
|
|
391
|
+
channelLaneText.value = '车道布局:—'
|
|
392
|
+
return
|
|
393
|
+
}
|
|
394
|
+
const states = (view?.getChannels() ?? []).filter(state => String(state.channelId) === String(channelId))
|
|
395
|
+
if (!states.length) {
|
|
396
|
+
channelLaneText.value = '车道布局:—'
|
|
397
|
+
return
|
|
398
|
+
}
|
|
399
|
+
const dataLines = view?.getData().lines ?? []
|
|
400
|
+
const spacing = states.find(state => Number(state.spacing) > 0)?.spacing ?? 0
|
|
401
|
+
const describeState = state => {
|
|
402
|
+
const lineIds = state.lineIndexes.map(index => dataLines[index]?.id ?? index).join(',')
|
|
403
|
+
const offsets = state.offsets.map(offset => Number(offset).toFixed(2)).join(',')
|
|
404
|
+
return `${state.id ?? state.channelId}${state.visible ? '' : '(隐)'}[${lineIds}] → [${offsets}]`
|
|
405
|
+
}
|
|
406
|
+
channelLaneText.value = `车道布局:${channelHiddenLineLayout.value} · spacing ${Number(spacing).toFixed(2)} · ${states.map(describeState).join(' · ')}`
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/** 准备两分组显隐演示:首通道只有一组时,把末回线拆成独立组;其余情况保持现状 */
|
|
410
|
+
const prepareGroupVisibilityDemo = () => {
|
|
411
|
+
const current = firstChannelGroups()
|
|
412
|
+
if (!view || !current) {
|
|
413
|
+
groupVisibilityText.value = '分组显隐:当前没有可编辑的通道'
|
|
414
|
+
return
|
|
415
|
+
}
|
|
416
|
+
let groups = current.groups
|
|
417
|
+
let added = false
|
|
418
|
+
if (groups.length < 2) {
|
|
419
|
+
const lineIds = groups[0]?.lineIds ?? []
|
|
420
|
+
if (lineIds.length < 2) {
|
|
421
|
+
groupVisibilityText.value = `${current.channelId}:至少要有两回线才能拆成两组`
|
|
422
|
+
return
|
|
423
|
+
}
|
|
424
|
+
const result = view.addChannelGroup(current.channelId, [lineIds[lineIds.length - 1]])
|
|
425
|
+
if (!result.ok) {
|
|
426
|
+
groupVisibilityText.value = '分组显隐准备失败:' + result.reason
|
|
427
|
+
pushLog('addChannelGroup 被拒绝:' + result.reason)
|
|
428
|
+
return
|
|
429
|
+
}
|
|
430
|
+
groups = view.getChannelGroups(current.channelId)
|
|
431
|
+
added = true
|
|
432
|
+
}
|
|
433
|
+
groupVisibilityText.value = `${current.channelId}:${groups.map(group => `「${group.id}」${group.lineIds.length} 回`).join(',')}${added ? ';已把末回线拆成独立组' : ''}。单组按钮操作末组,批量按钮一次收起或恢复全部组`
|
|
434
|
+
pushLog('分组显隐准备:' + groups.map(group => group.id + '(' + group.lineIds.length + ' 回)').join(' / '))
|
|
435
|
+
syncReadouts()
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* 分组显隐:all 为 true 走批量引用,否则只隐藏 / 恢复最后一个分组。
|
|
440
|
+
* 单组隐藏后保留其余分组的车道;批量隐藏全部组时成员一起退场,但分组与拐点声明仍在。
|
|
441
|
+
*/
|
|
442
|
+
const setVisibilityGroups = (visible, all) => {
|
|
443
|
+
const current = firstChannelGroups()
|
|
444
|
+
if (!view || !current || current.groups.length < 2) {
|
|
445
|
+
groupVisibilityText.value = '分组显隐:先点「准备两分组」,再试单组 / 批量隐藏与恢复'
|
|
446
|
+
return
|
|
447
|
+
}
|
|
448
|
+
const targets = all ? current.groups : [current.groups[current.groups.length - 1]]
|
|
449
|
+
const refs = targets.map(group => ({ channelId: current.channelId, groupId: group.id }))
|
|
450
|
+
const outcome = visible ? view.showFeatures('group', refs) : view.hideFeatures('group', refs)
|
|
451
|
+
const targetLabel = all ? '全部组(批量)' : `末组「${targets[0].id}」`
|
|
452
|
+
groupVisibilityText.value = outcome.ok
|
|
453
|
+
? `${visible ? '显示' : '隐藏'}${targetLabel}:${outcome.ids.map(String).join('、')}${outcome.skipped.length ? ` · 跳过 ${outcome.skipped.length}` : ''}`
|
|
454
|
+
: `${visible ? '显示' : '隐藏'}${targetLabel}失败:${outcome.reason}`
|
|
455
|
+
pushLog(visible ? 'showFeatures(group)' : 'hideFeatures(group)', groupVisibilityText.value)
|
|
456
|
+
syncReadouts()
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const setLastGroupVisible = visible => setVisibilityGroups(visible, false)
|
|
460
|
+
const setAllGroupsVisible = visible => setVisibilityGroups(visible, true)
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* 通道内单条回线显隐:引用直接给线路 id,通道 / 分组声明完全不动。
|
|
464
|
+
* 隐藏后成员仍留在 getChannelGroups() 里,只从画面与车道账本退场;preserve / center 仍按 options 决定其余回线的位置。
|
|
465
|
+
*/
|
|
466
|
+
const setFirstChannelLineVisible = (visible) => {
|
|
467
|
+
const current = firstChannelGroups()
|
|
468
|
+
if (!view || !current) {
|
|
469
|
+
channelLineVisibilityText.value = '通道内线路显隐:当前没有可编辑的通道'
|
|
470
|
+
return
|
|
471
|
+
}
|
|
472
|
+
const group = [...current.groups].reverse().find(item => item.lineIds?.length)
|
|
473
|
+
const lineId = group?.lineIds?.[group.lineIds.length - 1]
|
|
474
|
+
if (lineId === undefined) {
|
|
475
|
+
channelLineVisibilityText.value = `${current.channelId}:读不到可隐藏的成员回线`
|
|
476
|
+
return
|
|
477
|
+
}
|
|
478
|
+
const outcome = visible ? view.showFeatures('line', lineId) : view.hideFeatures('line', lineId)
|
|
479
|
+
channelLineVisibilityText.value = outcome.ok
|
|
480
|
+
? `${visible ? '显示' : '隐藏'}通道内回线:通道 ${String(current.channelId)} · 分组「${String(group.id)}」· 回线 ${String(lineId)}(线路下标 ${outcome.indexes.join('、')})`
|
|
481
|
+
: `${visible ? '显示' : '隐藏'}通道内回线失败:${outcome.reason}`
|
|
482
|
+
pushLog(visible ? 'showFeatures(line)' : 'hideFeatures(line)', channelLineVisibilityText.value)
|
|
483
|
+
syncReadouts()
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/** 隐藏回线车道:preserve 保留原槽位,center 让剩余可见回线重新居中;只改布局,不动分组 */
|
|
487
|
+
const applyChannelHiddenLineLayout = () => {
|
|
488
|
+
view?.updateOptions({ channelHiddenLineLayout: channelHiddenLineLayout.value })
|
|
489
|
+
syncGroupVisibilityReadout()
|
|
490
|
+
pushLog('隐藏回线车道:' + channelHiddenLineLayout.value)
|
|
491
|
+
}
|
|
492
|
+
|
|
379
493
|
/**
|
|
380
494
|
* 通道读数:几条通道、各自几回线、每组分了几组。
|
|
381
495
|
* getChannels() 给的是**分组**那一档(一条通道拆成几组就返回几条,按 channelId 归并);
|
|
@@ -401,6 +515,7 @@ const syncReadouts = () => {
|
|
|
401
515
|
syncMenu()
|
|
402
516
|
syncChangedChannels()
|
|
403
517
|
syncSimplifyReadout()
|
|
518
|
+
syncGroupVisibilityReadout()
|
|
404
519
|
}
|
|
405
520
|
|
|
406
521
|
/** 最近变化通道:分组 / 成员 / 拐点 / 端点 / 可见性 / 其余声明字段 */
|
|
@@ -1283,24 +1398,51 @@ onBeforeUnmount(() => {
|
|
|
1283
1398
|
</div>
|
|
1284
1399
|
|
|
1285
1400
|
<div class="dv-group">
|
|
1286
|
-
<h3
|
|
1401
|
+
<h3>显隐 / 车道布局与最近变化</h3>
|
|
1287
1402
|
<div class="dv-row">
|
|
1288
1403
|
<button type="button" class="dv-button" data-demo="point-hide" @click="setFirstFeatureVisible('point', false)">隐藏第一个节点</button>
|
|
1289
1404
|
<button type="button" class="dv-button dv-button--primary" data-demo="point-show" @click="setFirstFeatureVisible('point', true)">显示第一个节点</button>
|
|
1290
1405
|
<button type="button" class="dv-button" data-demo="line-hide" @click="setFirstFeatureVisible('line', false)">隐藏第一条线路</button>
|
|
1291
1406
|
<button type="button" class="dv-button dv-button--primary" data-demo="line-show" @click="setFirstFeatureVisible('line', true)">显示第一条线路</button>
|
|
1292
1407
|
</div>
|
|
1408
|
+
<div class="dv-row">
|
|
1409
|
+
<button type="button" class="dv-button" data-demo="channel-line-hide" @click="setFirstChannelLineVisible(false)">隐藏首通道末回线</button>
|
|
1410
|
+
<button type="button" class="dv-button dv-button--primary" data-demo="channel-line-show" @click="setFirstChannelLineVisible(true)">显示首通道末回线</button>
|
|
1411
|
+
</div>
|
|
1293
1412
|
<div class="dv-row">
|
|
1294
1413
|
<button type="button" class="dv-button" data-demo="channel-hide" @click="setFirstFeatureVisible('channel', false)">隐藏第一条通道</button>
|
|
1295
1414
|
<button type="button" class="dv-button dv-button--primary" data-demo="channel-show" @click="setFirstFeatureVisible('channel', true)">显示第一条通道</button>
|
|
1296
1415
|
<button type="button" class="dv-button" data-demo="channel-clear-changed" @click="clearChannelChanges">通道对账</button>
|
|
1297
1416
|
</div>
|
|
1417
|
+
<div class="dv-row">
|
|
1418
|
+
<button type="button" class="dv-button" data-demo="channel-group-prepare" @click="prepareGroupVisibilityDemo">准备两分组</button>
|
|
1419
|
+
<button type="button" class="dv-button" data-demo="channel-group-hide" @click="setLastGroupVisible(false)">隐藏末组</button>
|
|
1420
|
+
<button type="button" class="dv-button dv-button--primary" data-demo="channel-group-show" @click="setLastGroupVisible(true)">显示末组</button>
|
|
1421
|
+
</div>
|
|
1422
|
+
<div class="dv-row">
|
|
1423
|
+
<button type="button" class="dv-button" data-demo="channel-group-hide-all" @click="setAllGroupsVisible(false)">批量隐藏全部组</button>
|
|
1424
|
+
<button type="button" class="dv-button dv-button--primary" data-demo="channel-group-show-all" @click="setAllGroupsVisible(true)">批量显示全部组</button>
|
|
1425
|
+
<label>隐藏后车道
|
|
1426
|
+
<select v-model="channelHiddenLineLayout" data-demo="channel-hidden-line-layout" @change="applyChannelHiddenLineLayout">
|
|
1427
|
+
<option value="preserve">preserve(保留原槽位)</option>
|
|
1428
|
+
<option value="center">center(剩余回线居中)</option>
|
|
1429
|
+
</select>
|
|
1430
|
+
</label>
|
|
1431
|
+
</div>
|
|
1298
1432
|
<p class="dv-readout" data-demo="channel-visibility">{{ visibilityText }}</p>
|
|
1433
|
+
<p class="dv-readout" data-demo="channel-line-visibility">{{ channelLineVisibilityText }}</p>
|
|
1434
|
+
<p class="dv-readout" data-demo="channel-group-visibility">{{ groupVisibilityText }}</p>
|
|
1435
|
+
<p class="dv-readout" data-demo="channel-lane-layout">{{ channelLaneText }}</p>
|
|
1299
1436
|
<p class="dv-readout" data-demo="channel-changed">{{ changedText }}</p>
|
|
1300
1437
|
<p class="dv-hint">
|
|
1301
1438
|
节点 / 线路 / 通道都能用 hideFeatures / showFeatures 收起再恢复,只改 visible,数据本身不删;通道收起时成员回线、分组、拐点与编辑状态都保留;
|
|
1302
|
-
|
|
1303
|
-
|
|
1439
|
+
「隐藏首通道末回线」演示的是通道内部只收一条成员线路:引用直接传 line id,分组与其它回线不动,隐藏后的车道仍受 preserve / center 控制;
|
|
1440
|
+
分组也走同一条接口:「准备两分组」把首通道末回线拆成独立组,单组按钮操作最后一组,批量按钮把全部组引用一次交给接口。
|
|
1441
|
+
getChangedChannels 会把分组、成员、拐点、端点、可见性与其余字段的变化逐条列出来,clearChangedChannels 把当前声明记成新的对账基准。
|
|
1442
|
+
</p>
|
|
1443
|
+
<p class="dv-hint">
|
|
1444
|
+
隐藏回线车道:preserve(缺省)保留整条通道原来的槽位;center 把剩余可见回线压紧并重新居中。
|
|
1445
|
+
先隐藏末组,再切换两项,看下面读数里的 offset 变化 —— 分组、成员与拐点声明始终不变。
|
|
1304
1446
|
</p>
|
|
1305
1447
|
</div>
|
|
1306
1448
|
|
package/docs/demos/StyleDemo.vue
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* 样式与规则演示:同一份数据,换几套规则看画面怎么变,并现场改单个 / 多个要素。
|
|
4
4
|
*
|
|
5
|
-
* 规则就是「条件 + 样式」的数组(`pointRules` / `lineRules`),改完交给 updateOptions 立刻重排;
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* 规则就是「条件 + 样式」的数组(`pointRules` / `lineRules`),改完交给 updateOptions 立刻重排;
|
|
6
|
+
* 普通规则高于 pointStyle / lineStyle、低于要素自身字段(逐点样式),单条规则写 override: true 后压过要素字段;
|
|
7
|
+
* 悬停 / 选中 / 多选 / 框选 / 级联这些交互样式始终压在最上面,override 规则也盖不住它们写的颜色。
|
|
8
8
|
*/
|
|
9
9
|
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
|
10
10
|
import { createGisView } from '../../src/index.js'
|
|
@@ -18,47 +18,89 @@ let view = null
|
|
|
18
18
|
|
|
19
19
|
const preset = ref('voltage')
|
|
20
20
|
const pointSize = ref(7)
|
|
21
|
-
const lineWidth = ref(1.6)
|
|
22
|
-
const perPointStyle = ref(false)
|
|
21
|
+
const lineWidth = ref(1.6)
|
|
22
|
+
const perPointStyle = ref(false)
|
|
23
|
+
const ruleOverride = ref(false)
|
|
23
24
|
const highlightOn = ref(true)
|
|
25
|
+
const cascadeOn = ref(true)
|
|
26
|
+
const editPointId = ref(dataset.points[0]?.id ?? '')
|
|
27
|
+
const editLineId = ref(dataset.lines[0]?.id ?? '')
|
|
24
28
|
const applyMs = ref('—')
|
|
25
29
|
const ruleText = ref('—')
|
|
26
30
|
const selectText = ref('未选中:点一下节点或线路看高亮')
|
|
31
|
+
const cascadeText = ref('级联高亮未触发:点一下画布上的节点或线路')
|
|
32
|
+
const editText = ref('单 / 多要素补丁尚未执行')
|
|
33
|
+
const detailText = ref('点「查询详情」读取当前节点、线路与第一条通道')
|
|
34
|
+
|
|
35
|
+
const pointChoices = dataset.points.slice(0, 12)
|
|
36
|
+
const lineChoices = dataset.lines.slice(0, 12)
|
|
37
|
+
const pointBatchIds = dataset.points.slice(0, 3).map(point => point.id)
|
|
38
|
+
const lineBatchIds = dataset.lines.slice(0, 3).map(line => line.id)
|
|
39
|
+
|
|
40
|
+
const INTERACTION_STYLES = {
|
|
41
|
+
pointHoverStyle: { color: '#fb923c', strokeColor: '#7c2d12', strokeWidth: 2, sizeScale: 1.25 },
|
|
42
|
+
pointSelectStyle: { color: '#ffd166', strokeColor: '#5c3b00', strokeWidth: 2, sizeScale: 1.45 },
|
|
43
|
+
pointMultiSelectStyle: { color: '#f97316', strokeColor: '#7c2d12', strokeWidth: 2, sizeScale: 1.4 },
|
|
44
|
+
pointBoxSelectStyle: { color: '#22d3ee', strokeColor: '#155e75', strokeWidth: 2, sizeScale: 1.4 },
|
|
45
|
+
lineHoverStyle: { color: '#fb923c', width: 4, opacity: 1 },
|
|
46
|
+
lineSelectStyle: { color: '#ffd166', width: 5, opacity: 1 },
|
|
47
|
+
lineMultiSelectStyle: { color: '#f97316', width: 5.5, opacity: 1 },
|
|
48
|
+
waypointSelectStyle: { color: '#ffd166', strokeColor: '#5c3b00', strokeWidth: 2, sizeScale: 1.35 }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const CASCADE_STYLES = {
|
|
52
|
+
scope: 'both',
|
|
53
|
+
pointStyle: { color: '#22d3ee', strokeColor: '#155e75', strokeWidth: 2, sizeScale: 1.3 },
|
|
54
|
+
lineStyle: { color: '#22d3ee', width: 4.5, opacity: 1 }
|
|
55
|
+
}
|
|
27
56
|
|
|
28
57
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
58
|
+
* 交互样式按状态拆成几份:悬停 / 单选 / 多选 / 框选 / 级联各有一种颜色。
|
|
59
|
+
* 这些颜色是 `resolvePointWithBase` / `resolveLineStyleInto` 取值链的第一层,
|
|
60
|
+
* 即使规则写了 override: true 也压不过它们;关掉高亮时整层传 false,普通规则照旧生效。
|
|
32
61
|
*/
|
|
33
|
-
const
|
|
34
|
-
? {
|
|
35
|
-
:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return [{ name: '统一', when: { field: 'id', op: 'exists' }, style: { color: '#ffffff', strokeColor: '#4c8dff', strokeWidth: 1.5, size: pointSize.value } }]
|
|
48
|
-
}
|
|
49
|
-
return [
|
|
50
|
-
{ name: '1050 kV', when: { vn_kv: { gte: 1050 } }, style: { color: VOLTAGE_COLORS[1050], strokeColor: '#5c1338', strokeWidth: 2.2, size: pointSize.value + 3, zIndex: 4 } },
|
|
51
|
-
{ name: '525 kV', when: { vn_kv: { gte: 525, lt: 1050 } }, style: { color: VOLTAGE_COLORS[525], strokeColor: '#2f1b5c', strokeWidth: 2, size: pointSize.value + 1, zIndex: 3 } },
|
|
52
|
-
{ name: '230 kV', when: { vn_kv: { gte: 230, lt: 525 } }, style: { color: VOLTAGE_COLORS[230], strokeColor: '#123a5c', strokeWidth: 1.6, size: pointSize.value, zIndex: 2 } },
|
|
53
|
-
{ name: '其它', when: { vn_kv: { lt: 230 } }, style: { color: VOLTAGE_COLORS[15.7], strokeColor: '#12402f', strokeWidth: 1.4, size: pointSize.value - 1, zIndex: 1 } }
|
|
54
|
-
]
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const buildLineRules = () => (preset.value === 'load'
|
|
58
|
-
? [{ name: '线路重载', when: { max_loading_rate: { gte: 1 } }, style: { color: '#ff9f68', width: lineWidth.value + 1.4 } }]
|
|
59
|
-
: [])
|
|
62
|
+
const interactionStyles = () => highlightOn.value
|
|
63
|
+
? { ...INTERACTION_STYLES }
|
|
64
|
+
: {
|
|
65
|
+
pointHoverStyle: false,
|
|
66
|
+
pointSelectStyle: false,
|
|
67
|
+
pointMultiSelectStyle: false,
|
|
68
|
+
pointBoxSelectStyle: false,
|
|
69
|
+
lineHoverStyle: false,
|
|
70
|
+
lineSelectStyle: false,
|
|
71
|
+
lineMultiSelectStyle: false,
|
|
72
|
+
waypointSelectStyle: false
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const cascadeOptions = () => (cascadeOn.value ? { ...CASCADE_STYLES } : false)
|
|
60
76
|
|
|
61
|
-
/**
|
|
77
|
+
/** 三套预设:按电压上色 / 按负载上色 / 单色 */
|
|
78
|
+
const withRuleOverride = rules => (ruleOverride.value ? rules.map(rule => ({ ...rule, override: true })) : rules)
|
|
79
|
+
|
|
80
|
+
const buildPointRules = () => {
|
|
81
|
+
if (preset.value === 'load') {
|
|
82
|
+
return withRuleOverride([
|
|
83
|
+
{ name: '重载', when: { max_loading_rate: { gte: 1.1 } }, style: { color: '#ff7a45', strokeColor: '#7a2d10', strokeWidth: 2, size: pointSize.value + 3 } },
|
|
84
|
+
{ name: '正常', when: { max_loading_rate: { gte: 0.7, lt: 1.1 } }, style: { color: '#ffd166', strokeColor: '#6d5a1e', strokeWidth: 1.6, size: pointSize.value } },
|
|
85
|
+
{ name: '轻载', when: { max_loading_rate: { lt: 0.7 } }, style: { color: '#4fd1a5', strokeColor: '#1d5c46', strokeWidth: 1.6, size: pointSize.value - 1 } }
|
|
86
|
+
])
|
|
87
|
+
}
|
|
88
|
+
if (preset.value === 'mono') {
|
|
89
|
+
return withRuleOverride([{ name: '统一', when: { field: 'id', op: 'exists' }, style: { color: '#ffffff', strokeColor: '#4c8dff', strokeWidth: 1.5, size: pointSize.value } }])
|
|
90
|
+
}
|
|
91
|
+
return withRuleOverride([
|
|
92
|
+
{ name: '1050 kV', when: { vn_kv: { gte: 1050 } }, style: { color: VOLTAGE_COLORS[1050], strokeColor: '#5c1338', strokeWidth: 2.2, size: pointSize.value + 3, zIndex: 4 } },
|
|
93
|
+
{ name: '525 kV', when: { vn_kv: { gte: 525, lt: 1050 } }, style: { color: VOLTAGE_COLORS[525], strokeColor: '#2f1b5c', strokeWidth: 2, size: pointSize.value + 1, zIndex: 3 } },
|
|
94
|
+
{ name: '230 kV', when: { vn_kv: { gte: 230, lt: 525 } }, style: { color: VOLTAGE_COLORS[230], strokeColor: '#123a5c', strokeWidth: 1.6, size: pointSize.value, zIndex: 2 } },
|
|
95
|
+
{ name: '其它', when: { vn_kv: { lt: 230 } }, style: { color: VOLTAGE_COLORS[15.7], strokeColor: '#12402f', strokeWidth: 1.4, size: pointSize.value - 1, zIndex: 1 } }
|
|
96
|
+
])
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const buildLineRules = () => withRuleOverride(preset.value === 'load'
|
|
100
|
+
? [{ name: '线路重载', when: { max_loading_rate: { gte: 1 } }, style: { color: '#ff9f68', width: lineWidth.value + 1.4 } }]
|
|
101
|
+
: [])
|
|
102
|
+
|
|
103
|
+
/** 逐点样式:数据里自己写了 color / size 的节点默认压过普通规则;开启强制覆盖后由规则压回来(每 6 个一个金节点) */
|
|
62
104
|
const pointsWithOwnStyle = () => (perPointStyle.value
|
|
63
105
|
? dataset.points.map((point, index) => (index % 6 === 0 ? { ...point, color: '#ffd15c', size: 15, selectStyle: { color: '#ff7a45' } } : point))
|
|
64
106
|
: dataset.points)
|
|
@@ -69,11 +111,10 @@ const buildOptions = () => ({
|
|
|
69
111
|
channels: dataset.channels,
|
|
70
112
|
pointStyle: { size: pointSize.value, color: '#ffffff', strokeColor: '#4c8dff', strokeWidth: 1.5 },
|
|
71
113
|
lineStyle: { width: lineWidth.value, color: 'rgba(120, 168, 226, 0.5)' },
|
|
72
|
-
pointRules: buildPointRules(),
|
|
73
|
-
lineRules: buildLineRules(),
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
waypointSelectStyle: selectHighlight(),
|
|
114
|
+
pointRules: buildPointRules(),
|
|
115
|
+
lineRules: buildLineRules(),
|
|
116
|
+
...interactionStyles(),
|
|
117
|
+
cascadeHighlight: cascadeOptions(),
|
|
77
118
|
showGrid: true,
|
|
78
119
|
fitPadding: 60,
|
|
79
120
|
// 功能开关缺省全关:这一页要能平移缩放、能悬停选中看状态样式,显式打开查看类
|
|
@@ -81,10 +122,11 @@ const buildOptions = () => ({
|
|
|
81
122
|
label: { content: '{vn_kv} kV', position: 'top', gap: 7, maxCount: 30, style: { color: '#27405f', fontSize: '11px' } },
|
|
82
123
|
// 标签按优化档显示(限数 + 避让),见 docs/GisView.md 的「标签显示优化开关」
|
|
83
124
|
labelOptimize: true,
|
|
84
|
-
onReady: () => {
|
|
85
|
-
emit('notice', `${dataset.points.length} 个节点,规则预设「${preset.value}」`)
|
|
86
|
-
syncRules()
|
|
87
|
-
|
|
125
|
+
onReady: () => {
|
|
126
|
+
emit('notice', `${dataset.points.length} 个节点,规则预设「${preset.value}」`)
|
|
127
|
+
syncRules()
|
|
128
|
+
requestAnimationFrame(syncDetail)
|
|
129
|
+
},
|
|
88
130
|
/**
|
|
89
131
|
* 读数接 onSelectChange 而不是 onSelect:前者对「点选、框选、API selectFeatures()」都会发,
|
|
90
132
|
* 后者只代表画布上的那一次点击 —— 用接口选中时读数也不会停在「未选中」。
|
|
@@ -92,14 +134,19 @@ const buildOptions = () => ({
|
|
|
92
134
|
*/
|
|
93
135
|
onSelectChange: (info) => {
|
|
94
136
|
selectText.value = info?.count
|
|
95
|
-
? `选中 ${info.count} 个(点 ${info.points} / 线 ${info.lines} / 通道 ${info.channels}
|
|
96
|
-
: '
|
|
137
|
+
? `选中 ${info.count} 个(点 ${info.points} / 线 ${info.lines} / 通道 ${info.channels}):多选与框选会换成各自的状态色`
|
|
138
|
+
: '未选中:点一下节点或线路看高亮;Ctrl 点击多选、Shift 拖动框选'
|
|
139
|
+
},
|
|
140
|
+
onCascadeHighlight: (payload) => {
|
|
141
|
+
cascadeText.value = payload
|
|
142
|
+
? `级联:起点 ${payload.origin?.item?.id ?? payload.origin?.channelId ?? '—'},邻接点 ${payload.points.length} 个 / 线 ${payload.lines.length} 条`
|
|
143
|
+
: '级联高亮未触发:点一下画布上的节点或线路'
|
|
97
144
|
}
|
|
98
145
|
})
|
|
99
146
|
|
|
100
|
-
const syncRules = () => {
|
|
101
|
-
ruleText.value = `节点规则 ${buildPointRules().length} 条 · 线路规则 ${buildLineRules().length}
|
|
102
|
-
}
|
|
147
|
+
const syncRules = () => {
|
|
148
|
+
ruleText.value = `节点规则 ${buildPointRules().length} 条 · 线路规则 ${buildLineRules().length} 条${ruleOverride.value ? ' · 全部 override: true' : ''}`
|
|
149
|
+
}
|
|
103
150
|
|
|
104
151
|
/**
|
|
105
152
|
* 改规则 / 尺寸 / 高亮:只发样式类配置(不重发 points / lines),
|
|
@@ -112,9 +159,8 @@ const applyRules = () => {
|
|
|
112
159
|
lineRules: buildLineRules(),
|
|
113
160
|
pointStyle: { size: pointSize.value, color: '#ffffff', strokeColor: '#4c8dff', strokeWidth: 1.5 },
|
|
114
161
|
lineStyle: { width: lineWidth.value, color: 'rgba(120, 168, 226, 0.5)' },
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
waypointSelectStyle: selectHighlight()
|
|
162
|
+
...interactionStyles(),
|
|
163
|
+
cascadeHighlight: cascadeOptions()
|
|
118
164
|
})
|
|
119
165
|
syncRules()
|
|
120
166
|
applyMs.value = `${(performance.now() - started).toFixed(1)} ms`
|
|
@@ -125,6 +171,120 @@ const applyPerPointStyle = () => {
|
|
|
125
171
|
view?.updateOptions({ points: pointsWithOwnStyle() })
|
|
126
172
|
syncRules()
|
|
127
173
|
}
|
|
174
|
+
|
|
175
|
+
let pointEditStep = 0
|
|
176
|
+
let lineEditStep = 0
|
|
177
|
+
const POINT_EDIT_COLORS = ['#f97316', '#22c55e', '#e11d48', '#0ea5e9']
|
|
178
|
+
const LINE_EDIT_COLORS = ['#ec4899', '#14b8a6', '#eab308', '#8b5cf6']
|
|
179
|
+
|
|
180
|
+
/** 单个节点:按字段合并,颜色 / 尺寸 / 图标 / 描边都能现场改 */
|
|
181
|
+
const updateSinglePoint = () => {
|
|
182
|
+
const color = POINT_EDIT_COLORS[pointEditStep % POINT_EDIT_COLORS.length]
|
|
183
|
+
pointEditStep += 1
|
|
184
|
+
view?.updatePoint(editPointId.value, {
|
|
185
|
+
color,
|
|
186
|
+
size: 18,
|
|
187
|
+
strokeColor: '#17233d',
|
|
188
|
+
strokeWidth: 3,
|
|
189
|
+
symbol: { type: 'square', radius: 3 }
|
|
190
|
+
})
|
|
191
|
+
editText.value = `updatePoint(${editPointId.value}):color=${color},size=18,symbol=square`
|
|
192
|
+
syncDetail()
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** 一批节点:同一份补丁一次写完,patchPoints 返回 indexes / count / skipped */
|
|
196
|
+
const patchPointBatch = () => {
|
|
197
|
+
const result = view?.patchPoints(pointBatchIds, {
|
|
198
|
+
color: '#22c55e',
|
|
199
|
+
size: 15,
|
|
200
|
+
strokeColor: '#14532d',
|
|
201
|
+
strokeWidth: 2
|
|
202
|
+
})
|
|
203
|
+
editText.value = `patchPoints(${pointBatchIds.join(', ')}):${result?.count ?? 0} 个,颜色 #22c55e`
|
|
204
|
+
syncDetail()
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** 单条线路:颜色、线宽、透明度与线型都能逐条改 */
|
|
208
|
+
const updateSingleLine = () => {
|
|
209
|
+
const color = LINE_EDIT_COLORS[lineEditStep % LINE_EDIT_COLORS.length]
|
|
210
|
+
lineEditStep += 1
|
|
211
|
+
view?.updateLine(editLineId.value, { color, width: 4, opacity: 0.95, lineType: 'dashed' })
|
|
212
|
+
editText.value = `updateLine(${editLineId.value}):color=${color},width=4,lineType=dashed`
|
|
213
|
+
syncDetail()
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** 一批线路:entries 也支持 `{ id, ...字段 }` 逐条给不同补丁 */
|
|
217
|
+
const patchLineBatch = () => {
|
|
218
|
+
const result = view?.patchLines(lineBatchIds, {
|
|
219
|
+
color: '#14b8a6',
|
|
220
|
+
width: 2.8,
|
|
221
|
+
opacity: 0.9,
|
|
222
|
+
lineType: 'dotted'
|
|
223
|
+
})
|
|
224
|
+
editText.value = `patchLines(${lineBatchIds.join(', ')}):${result?.count ?? 0} 条,颜色 #14b8a6`
|
|
225
|
+
syncDetail()
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** 清掉单条 / 批量补丁,回到原始数据;规则、通道与相机保持不变 */
|
|
229
|
+
const resetElementStyles = () => {
|
|
230
|
+
view?.updateData({ points: pointsWithOwnStyle(), lines: dataset.lines, channels: dataset.channels })
|
|
231
|
+
view?.selectFeatures(null)
|
|
232
|
+
editText.value = '已恢复原始节点 / 线路数据(规则与交互样式仍在)'
|
|
233
|
+
syncDetail()
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const selectSinglePoint = () => view?.selectFeatures(editPointId.value)
|
|
237
|
+
const selectMultiplePoints = () => view?.selectFeatures(dataset.points.slice(0, 2).map(point => point.id))
|
|
238
|
+
const selectSingleLine = () => view?.selectFeatures({ type: 'line', id: editLineId.value })
|
|
239
|
+
const selectMultipleLines = () => view?.selectFeatures(dataset.lines.slice(0, 2).map(line => line.id))
|
|
240
|
+
|
|
241
|
+
/** 程序化框选相邻节点:与 Shift 拖动走同一个 selectInBox,直接命中项用 boxSelectStyle */
|
|
242
|
+
const selectPointsInBox = () => {
|
|
243
|
+
const screens = dataset.points.slice(0, 3).map(point => view?.project(point.x, point.y)).filter(Boolean)
|
|
244
|
+
if (!screens.length) {
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
const margin = 28
|
|
248
|
+
const xs = screens.map(screen => screen[0])
|
|
249
|
+
const ys = screens.map(screen => screen[1])
|
|
250
|
+
const minX = Math.min(...xs) - margin
|
|
251
|
+
const minY = Math.min(...ys) - margin
|
|
252
|
+
view?.selectInBox({
|
|
253
|
+
x: minX,
|
|
254
|
+
y: minY,
|
|
255
|
+
width: Math.max(Math.max(...xs) + margin - minX, 2),
|
|
256
|
+
height: Math.max(Math.max(...ys) + margin - minY, 2)
|
|
257
|
+
}, { selectionKinds: ['point'] })
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const clearSelection = () => view?.selectFeatures(null)
|
|
261
|
+
|
|
262
|
+
const screenText = screen => (Array.isArray(screen) ? `${screen[0].toFixed(1)}, ${screen[1].toFixed(1)}` : '—')
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* 详情查询分两层:getPoint / getLine / getChannel 查单个,listPoints / listLines / getChannels 查一批。
|
|
266
|
+
* 这里只用节点、线路与通道;分组详情不在这份演示里。
|
|
267
|
+
*/
|
|
268
|
+
const syncDetail = () => {
|
|
269
|
+
if (!view) {
|
|
270
|
+
return
|
|
271
|
+
}
|
|
272
|
+
const point = view.getPoint(editPointId.value)
|
|
273
|
+
const points = view.listPoints({ indexes: dataset.points.slice(0, 3).map((_point, index) => index), withScreen: true, visibleOnly: false, limit: 3 })
|
|
274
|
+
const line = view.getLine(editLineId.value)
|
|
275
|
+
const lines = view.listLines({ indexes: dataset.lines.slice(0, 3).map((_line, index) => index), withScreen: true, visibleOnly: false, limit: 3 })
|
|
276
|
+
const channelId = dataset.channels[0]?.id
|
|
277
|
+
const channel = channelId === undefined || channelId === null ? null : view.getChannel(channelId)
|
|
278
|
+
const channelCount = view.getChannels().length
|
|
279
|
+
detailText.value = [
|
|
280
|
+
`节点单查:${point ? `${point.item.id} · index ${point.index} · screen ${screenText(point.screen)} · radius ${point.radius.toFixed(1)}` : 'null'}`,
|
|
281
|
+
`节点批量:${points.length} 条 · ${points.map(entry => entry.item.id).join(', ')}`,
|
|
282
|
+
`线路单查:${line ? `${line.item.id} · ${line.path.length} 个折点 · width ${line.width.toFixed(1)}` : 'null'}`,
|
|
283
|
+
`线路批量:${lines.length} 条 · ${lines.map(entry => entry.item.id).join(', ')}`,
|
|
284
|
+
`通道单查:${channel ? `${channel.item.id} · ${channel.lineIndexes.length} 条回线 · ${channel.skeleton.length} 个骨架点` : 'null'}`,
|
|
285
|
+
`通道全量:getChannels() ${channelCount} 条`
|
|
286
|
+
].join(';')
|
|
287
|
+
}
|
|
128
288
|
|
|
129
289
|
onMounted(() => {
|
|
130
290
|
view = createGisView(container.value, buildOptions())
|
|
@@ -161,24 +321,75 @@ onBeforeUnmount(() => {
|
|
|
161
321
|
<div class="dv-row">
|
|
162
322
|
<label><input v-model="perPointStyle" type="checkbox" @change="applyPerPointStyle" /> 逐点样式(数据里自己写 color / size)</label>
|
|
163
323
|
</div>
|
|
164
|
-
<div class="dv-row">
|
|
165
|
-
<label><input v-model="highlightOn" type="checkbox" @change="applyRules" />
|
|
166
|
-
|
|
324
|
+
<div class="dv-row">
|
|
325
|
+
<label><input v-model="highlightOn" type="checkbox" @change="applyRules" /> 悬停 / 选中 / 多选 / 框选</label>
|
|
326
|
+
<label><input v-model="cascadeOn" data-demo="style-cascade" type="checkbox" @change="applyRules" /> 级联高亮</label>
|
|
327
|
+
</div>
|
|
328
|
+
<div class="dv-row">
|
|
329
|
+
<label><input v-model="ruleOverride" data-demo="style-rule-override" type="checkbox" @change="applyRules" /> 规则强制覆盖(override: true)</label>
|
|
330
|
+
</div>
|
|
167
331
|
<p class="dv-readout">{{ ruleText }}</p>
|
|
168
332
|
<p class="dv-readout">最近一次重排:{{ applyMs }}</p>
|
|
333
|
+
</div>
|
|
334
|
+
<div class="dv-group">
|
|
335
|
+
<h3>单个 / 多个要素样式</h3>
|
|
336
|
+
<div class="dv-row">
|
|
337
|
+
<label>节点
|
|
338
|
+
<select v-model="editPointId" data-demo="style-point-target">
|
|
339
|
+
<option v-for="point in pointChoices" :key="point.id" :value="point.id">{{ point.id }}</option>
|
|
340
|
+
</select>
|
|
341
|
+
</label>
|
|
342
|
+
<button type="button" class="dv-button dv-button--primary" data-demo="style-update-point" @click="updateSinglePoint">updatePoint</button>
|
|
343
|
+
</div>
|
|
344
|
+
<div class="dv-row">
|
|
345
|
+
<button type="button" class="dv-button" data-demo="style-patch-points" @click="patchPointBatch">patchPoints(前 3 个)</button>
|
|
346
|
+
</div>
|
|
347
|
+
<div class="dv-row">
|
|
348
|
+
<label>线路
|
|
349
|
+
<select v-model="editLineId" data-demo="style-line-target">
|
|
350
|
+
<option v-for="line in lineChoices" :key="line.id" :value="line.id">{{ line.id }}</option>
|
|
351
|
+
</select>
|
|
352
|
+
</label>
|
|
353
|
+
<button type="button" class="dv-button dv-button--primary" data-demo="style-update-line" @click="updateSingleLine">updateLine</button>
|
|
354
|
+
</div>
|
|
355
|
+
<div class="dv-row">
|
|
356
|
+
<button type="button" class="dv-button" data-demo="style-patch-lines" @click="patchLineBatch">patchLines(前 3 条)</button>
|
|
357
|
+
<button type="button" class="dv-button dv-button--danger" data-demo="style-reset" @click="resetElementStyles">恢复原始数据</button>
|
|
358
|
+
</div>
|
|
359
|
+
<p class="dv-readout" data-demo="style-edit-readout">{{ editText }}</p>
|
|
360
|
+
<p class="dv-hint">单条走 updatePoint / updateLine,批量走 patchPoints / patchLines;普通规则只补空位,override 规则会压过这里写进去的字段,但压不过下面这些交互状态。</p>
|
|
361
|
+
</div>
|
|
362
|
+
<div class="dv-group">
|
|
363
|
+
<h3>交互样式优先级</h3>
|
|
364
|
+
<div class="dv-row">
|
|
365
|
+
<button type="button" class="dv-button" data-demo="style-select-single" @click="selectSinglePoint">单选节点</button>
|
|
366
|
+
<button type="button" class="dv-button" data-demo="style-select-multi" @click="selectMultiplePoints">多选节点</button>
|
|
367
|
+
<button type="button" class="dv-button" data-demo="style-select-box" @click="selectPointsInBox">框选节点</button>
|
|
368
|
+
</div>
|
|
369
|
+
<div class="dv-row">
|
|
370
|
+
<button type="button" class="dv-button" data-demo="style-select-line" @click="selectSingleLine">单选线路</button>
|
|
371
|
+
<button type="button" class="dv-button" data-demo="style-select-lines" @click="selectMultipleLines">多选线路</button>
|
|
372
|
+
<button type="button" class="dv-button" data-demo="style-clear-selection" @click="clearSelection">清除选中</button>
|
|
373
|
+
</div>
|
|
169
374
|
<p class="dv-readout">{{ selectText }}</p>
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
375
|
+
<p class="dv-readout">{{ cascadeText }}</p>
|
|
376
|
+
<p class="dv-hint">
|
|
377
|
+
状态颜色始终是第一条取值链:黄 = 单选、橙 = 多选、青 = 框选、青色级联;即使勾上 override 规则也会被这些颜色盖住。
|
|
378
|
+
直接点击画布上的节点 / 线路可看悬停与级联,Ctrl 点击看多选,Shift 拖动看框选。
|
|
379
|
+
</p>
|
|
380
|
+
</div>
|
|
381
|
+
<div class="dv-group">
|
|
382
|
+
<h3>详情查询</h3>
|
|
383
|
+
<div class="dv-row">
|
|
384
|
+
<button type="button" class="dv-button dv-button--primary" data-demo="style-query" @click="syncDetail">查询详情</button>
|
|
385
|
+
</div>
|
|
386
|
+
<p class="dv-readout" data-demo="style-detail-readout">{{ detailText }}</p>
|
|
387
|
+
<p class="dv-hint">单条用 getPoint / getLine / getChannel;多条用 listPoints / listLines;全部通道用 getChannels。单条查不到返回 null,批量查询返回数组。</p>
|
|
388
|
+
</div>
|
|
389
|
+
<div class="dv-group">
|
|
390
|
+
<h3>试一下</h3>
|
|
391
|
+
<p class="dv-hint">先把预设切到「按电压上色」再切「按负载率」,同一份数据两种读法;同时勾「逐点样式」与「规则强制覆盖」,对比同一批金节点在两种优先级下的颜色 / 尺寸;再选一个节点或线路点 updatePoint / updateLine,最后直接点画布看交互色仍然最高。</p>
|
|
392
|
+
</div>
|
|
182
393
|
</aside>
|
|
183
394
|
</section>
|
|
184
395
|
</template>
|