gis-view-webgl2 0.1.7 → 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 +9 -8
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +232 -228
- package/dist/index.js +1 -1
- package/docs/AI/345/257/271/350/257/235/346/261/207/346/200/273.md +49 -0
- package/docs/GisView.md +1 -1
- 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 +48 -0
- package/docs/demos/BasicDemo.vue +2 -2
- package/docs/demos/BatchAddDemo.vue +6 -6
- package/docs/demos/ConnectDemo.vue +164 -33
- package/docs/demos/CopyMergeDemo.vue +27 -14
- package/docs/demos/EventDemo.vue +17 -20
- package/docs/demos/LabelDemo.vue +5 -5
- package/docs/demos/api-index.js +31 -29
- package/docs/demos/gis-view-demo/GisViewDemoCardHeader.vue +1 -1
- package/docs/demos/gis-view-demo/GisViewDemoStage.vue +1 -1
- package/docs/demos/gis-view-demo/panels/DataPanels.vue +1 -1
- package/docs/demos/gis-view-demo/useGisViewDemo.js +31 -33
- package/docs/format/07-/344/272/213/344/273/266/350/275/275/350/215/267/344/270/216/347/244/272/344/276/213/346/225/260/346/215/256.md +8 -7
- package/docs/from0/05-/347/233/270/346/234/272/344/270/216/344/272/244/344/272/222.md +1 -1
- package/docs/from0/07-/351/200/232/351/201/223/345/210/206/347/273/204/344/270/216/345/244/232/345/233/236/347/272/277.md +26 -10
- 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/04-/344/272/213/344/273/266/344/270/216/345/233/236/350/260/203.md +21 -16
- package/docs/manual/06-/346/225/260/346/215/256/344/270/216/345/234/272/346/231/257/346/233/264/346/226/260.md +9 -10
- 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 +54 -31
- package/docs/manual/08-/351/200/211/344/270/255/344/270/216/346/213/220/347/202/271.md +3 -3
- package/docs/manual/09-/351/200/232/351/201/223/344/270/216/345/244/232/345/233/236/347/272/277.md +9 -6
- package/docs/manual/10-/351/200/232/351/201/223/347/274/226/350/276/221/344/270/216/346/226/260/345/242/236.md +226 -493
- package/docs/manual/12-/346/240/207/347/255/276/344/270/216/350/243/205/351/245/260.md +2 -2
- package/docs/manual/14-/350/247/206/345/233/276/344/270/216/347/255/233/351/200/211.md +12 -13
- package/docs/manual/16-/345/256/236/344/276/213/346/226/271/346/263/225/346/200/273/350/241/250.md +23 -21
- package/docs/manual/17-/345/217/202/346/225/260/351/200/237/346/237/245.md +19 -17
- package/docs/manual/18-/351/200/220/346/226/271/346/263/225/347/244/272/344/276/213.md +125 -78
- 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 +1 -1
- package/docs/manual/20-/346/200/247/350/203/275/344/270/216/345/244/247/346/225/260/346/215/256.md +2 -2
- 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 -4
- package/docs/steps/README.md +9 -7
- package/docs/steps/bench-scale.html +1 -1
- package/docs/steps/index.html +6 -6
- package/docs/steps/selftest-actions.html +26 -25
- package/docs/steps/selftest-data.html +1 -1
- package/docs/steps/selftest-demos.html +102 -6
- package/docs/steps/selftest-docs.html +3 -3
- package/docs/steps/selftest-features.html +283 -51
- package/docs/steps/selftest-full.html +3 -3
- package/docs/steps/selftest-labels.html +1 -1
- package/docs/steps/selftest-perf.html +31 -4
- package/docs/steps/selftest-select.html +20 -5
- package/docs/steps/step-05-pick.js +4 -8
- package/docs/steps/step-07-channels.js +3 -5
- package/docs/steps/step-08-labels.js +3 -3
- package/docs/steps/step-10-full.js +3 -3
- package/docs/steps/step-12-events.js +41 -24
- package/package.json +1 -1
|
@@ -2264,7 +2264,7 @@
|
|
|
2264
2264
|
check('拆分发 channelGroupChange(action: splitGroups 带新组表)', cgBus.length === 1 && cgSplit?.action?.type === 'splitGroups' && cgSplit.action.groupIds.length === 2 && cgSplit.channelId === 'ch-1' && cgSplit.groups.length === 2, JSON.stringify({ type: cgSplit?.action?.type, groupIds: cgSplit?.action?.groupIds }))
|
|
2265
2265
|
check('onChannelGroupChange 回调和事件总线收到同一份载荷', cgOption.length === 1 && cgOption[0] === cgBus[0])
|
|
2266
2266
|
|
|
2267
|
-
//
|
|
2267
|
+
// 选中一条回线再合并:选中项不再挂通道字段,实时归属要跟着真值走(回归守卫)
|
|
2268
2268
|
cgView.selectFeatures('c2')
|
|
2269
2269
|
await settle(60)
|
|
2270
2270
|
const cgTruth = () => {
|
|
@@ -2277,7 +2277,10 @@
|
|
|
2277
2277
|
cgView.mergeChannelGroups('ch-1', [cgAfterSplit[1].id], cgAfterSplit[0].id)
|
|
2278
2278
|
await settle(60)
|
|
2279
2279
|
const cgMerged = cgTruth()
|
|
2280
|
-
|
|
2280
|
+
const cgOwner = cgView.getLineChannel('c2')
|
|
2281
|
+
const cgOwnerGroups = cgView.getChannelGroups('ch-1')
|
|
2282
|
+
const cgOwnerGroupIndex = cgOwnerGroups.findIndex(group => String(group.id) === String(cgOwner?.groupId))
|
|
2283
|
+
check('合并回线之后 getLineChannel 的 groupId / groupIndex 一起刷新,选中项仍不挂通道字段', String(cgOwner?.groupId) === cgMerged?.id && cgOwnerGroupIndex === cgMerged?.index && cgMirror()?.groupId === undefined && cgMirror()?.groupIndex === undefined, `归属 ${cgOwner?.groupId}/${cgOwnerGroupIndex} / 真值 ${cgMerged?.id}/${cgMerged?.index} / 镜像 ${cgMirror()?.groupId}/${cgMirror()?.groupIndex}`)
|
|
2281
2284
|
const cgMerge = cgBus[cgBus.length - 1]
|
|
2282
2285
|
check('合并发 channelGroupChange(action: mergeGroups 带目标组与来源组)', cgMerge?.action?.type === 'mergeGroups' && String(cgMerge.action.groupId) === String(cgMerged?.id) && cgMerge.action.groupIds.length === 2, JSON.stringify({ type: cgMerge?.action?.type, groupId: cgMerge?.action?.groupId, groupIds: cgMerge?.action?.groupIds }))
|
|
2283
2286
|
|
|
@@ -2657,7 +2660,7 @@
|
|
|
2657
2660
|
chView.destroy()
|
|
2658
2661
|
chHost.remove()
|
|
2659
2662
|
|
|
2660
|
-
|
|
2663
|
+
/* 这一轮新增:屏幕 ↔ 真实坐标互转 / addChannel 第二段 lineData / beginAddChannel 交接模式 */
|
|
2661
2664
|
const hwHost = document.createElement('div')
|
|
2662
2665
|
hwHost.style.cssText = 'width:420px;height:280px'
|
|
2663
2666
|
document.body.appendChild(hwHost)
|
|
@@ -2701,18 +2704,18 @@
|
|
|
2701
2704
|
const hwClientViaScreen = hwView.screenToClient(hwScreen[0], hwScreen[1])
|
|
2702
2705
|
check('screenToClient(project(世界)) 与 worldToClient(同一世界) 同一结果:反向也等价', Math.abs(hwClientViaScreen[0] - hwClient[0]) < 1e-6 && Math.abs(hwClientViaScreen[1] - hwClient[1]) < 1e-6, JSON.stringify({ viaScreen: hwClientViaScreen, viaWorld: hwClient }))
|
|
2703
2706
|
// ② addChannel / addLine 第二段:连同线路一起新建
|
|
2704
|
-
const hwAdd = hwView.addChannel({ from: 'ha', to: 'hb', name: '第二段通道'
|
|
2707
|
+
const hwAdd = hwView.addChannel({ from: 'ha', to: 'hb', name: '第二段通道' }, [
|
|
2705
2708
|
{ id: 'hw-l1', color: '#112233', width: 4 },
|
|
2706
2709
|
{ id: 'hw-l2', color: '#445566' }
|
|
2707
2710
|
])
|
|
2708
2711
|
const hwLine = id => hwView.getOptions().lines.find(line => String(line.id) === id)
|
|
2709
2712
|
const hwChannelOf = channelId => hwView.getOptions().channels.find(channel => String(channel.id) === String(channelId))
|
|
2710
|
-
check('addChannel(
|
|
2711
|
-
const hwAddOne = hwView.addLine({ from: 'hc', to: 'hd'
|
|
2713
|
+
check('addChannel(spec, lineData):给几条建几条,逐条字段各自落地', hwAdd.ok === true && hwAdd.lineIds.length === 2 && hwAdd.circuits === 2 && (hwChannelOf(hwAdd.channelId)?.lineIds ?? []).length === 2 && hwLine('hw-l1')?.color === '#112233' && hwLine('hw-l1')?.width === 4 && hwLine('hw-l2')?.color === '#445566', JSON.stringify({ ids: hwAdd.lineIds, circuits: hwAdd.circuits, l1: hwLine('hw-l1') }))
|
|
2714
|
+
const hwAddOne = hwView.addLine({ from: 'hc', to: 'hd' }, { id: 'hw-solo', color: '#abcdef' })
|
|
2712
2715
|
check('第二段收单条(非数组)也认:addLine 按它建一条独立线路', hwAddOne.ok === true && hwAddOne.lineIds.length === 1 && hwAddOne.lineIds[0] === 'hw-solo' && hwAddOne.kind === 'line' && hwLine('hw-solo')?.color === '#abcdef', JSON.stringify({ ids: hwAddOne.lineIds, circuits: hwAddOne.circuits }))
|
|
2713
|
-
const hwBatch = hwView.addChannels([{ from: 'ha', to: 'hc',
|
|
2714
|
-
check('addChannels
|
|
2715
|
-
|
|
2716
|
+
const hwBatch = hwView.addChannels([{ from: 'ha', to: 'hc', lineData: [{ id: 'hw-b1' }, { id: 'hw-b2' }, { id: 'hw-b3' }] }])
|
|
2717
|
+
check('addChannels 的每一项写 lineData:三条一起建', hwBatch.ok === true && hwBatch.lineIds.length === 3 && ['hw-b1', 'hw-b2', 'hw-b3'].every(id => hwLine(id) !== undefined), JSON.stringify({ ids: hwBatch.lineIds }))
|
|
2718
|
+
// ③ beginAddChannel:lineData 对齐条数、handoff 交接
|
|
2716
2719
|
const hwClickPoint = id => {
|
|
2717
2720
|
const item = hwView.getData().points.find(point => point.id === id)
|
|
2718
2721
|
return hwView.project(item.x, item.y)
|
|
@@ -2748,9 +2751,13 @@
|
|
|
2748
2751
|
const hwHandAdd = hwReady ? hwView.addChannel({ from: hwReady.from.id, to: hwReady.to.id, name: '交接通道' }) : { ok: false }
|
|
2749
2752
|
check('交接之后自己走 addChannel:真实的通道与回线落地', hwHandAdd.ok === true && hwHandAdd.channelId !== null && hwView.getOptions().lines.length === hwLineBefore + 1, JSON.stringify({ ok: hwHandAdd.ok, channelId: hwHandAdd.channelId }))
|
|
2750
2753
|
hwDraftEvents.length = 0
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
+
hwView.beginAddChannel({ lineItems: [{ id: 'hw-old-d1' }, { id: 'hw-old-d2' }] })
|
|
2755
|
+
await settle(40)
|
|
2756
|
+
check('beginAddChannel 旧 lineItems 已移除:不进入草稿的 lineData、回数按缺省 1', hwView.getAddChannelDraft()?.lineData === null && hwView.getAddChannelDraft()?.circuits === 1, JSON.stringify({ circuits: hwView.getAddChannelDraft()?.circuits, lineData: hwView.getAddChannelDraft()?.lineData }))
|
|
2757
|
+
hwView.cancelAddChannel()
|
|
2758
|
+
hwView.beginAddChannel({ autoCommit: true, lineData: [{ id: 'hw-d1', color: '#0a0b0c' }, { id: 'hw-d2', color: '#0d0e0f' }] })
|
|
2759
|
+
await settle(40)
|
|
2760
|
+
check('beginAddChannel({ lineData }):草稿按第二段对齐条数(circuits = 2)', hwView.getAddChannelDraft()?.circuits === 2 && (hwView.getAddChannelDraft()?.lineData?.length ?? 0) === 2, JSON.stringify({ circuits: hwView.getAddChannelDraft()?.circuits }))
|
|
2754
2761
|
hwClick(hwClickPoint('hb'))
|
|
2755
2762
|
await settle(30)
|
|
2756
2763
|
hwClick(hwClickPoint('hd'))
|
|
@@ -2812,17 +2819,17 @@
|
|
|
2812
2819
|
check('位置对账:新加进来的节点以加入时坐标入账(刚加不算,之后再挪才算)', mvAfterAdd === 0 && mvMovedNew.length === 1 && mvMovedNew[0].id === 'me' && mvMovedNew[0].x === 620, JSON.stringify({ afterAdd: mvAfterAdd, afterMove: mvMovedNew.map(item => item.id) }))
|
|
2813
2820
|
check('位置对账:clearMovedPoints 返回实例本身(可以链式调)', mvView.clearMovedPoints('me') === mvView && mvView.clearMovedPoints().getMovedPoints().length === 0, '')
|
|
2814
2821
|
|
|
2815
|
-
const mvAdd1 = mvView.
|
|
2822
|
+
const mvAdd1 = mvView.addChannelGroupLines('mch')
|
|
2816
2823
|
const mvCh1 = mvChannel('mch')
|
|
2817
|
-
check('
|
|
2818
|
-
check('
|
|
2819
|
-
const mvAdd2 = mvView.
|
|
2824
|
+
check('addChannelGroupLines 已有通道:新分组,通道 lineIds 与 groups 一起追加', mvAdd1.ok === true && mvAdd1.resolution?.type === 'newGroup' && mvCh1.lineIds.length === 3 && mvCh1.groups.length === 2 && mvCh1.groups[1].lineIds.length === 1, JSON.stringify({ type: mvAdd1.resolution?.type, lineIds: mvCh1.lineIds, groups: mvCh1.groups.map(group => group.lineIds) }))
|
|
2825
|
+
check('addChannelGroupLines 已有通道:结果回带更新后的通道 lineIds(channelLineIds 与声明一致)', Array.isArray(mvAdd1.channelLineIds) && mvAdd1.channelLineIds.length === 3 && JSON.stringify(mvAdd1.channelLineIds) === JSON.stringify(mvCh1.lineIds), JSON.stringify(mvAdd1.channelLineIds))
|
|
2826
|
+
const mvAdd2 = mvView.joinChannelGroupLines('mch', 0)
|
|
2820
2827
|
const mvCh2 = mvChannel('mch')
|
|
2821
|
-
check('
|
|
2822
|
-
const mvAdd3 = mvView.
|
|
2823
|
-
check('
|
|
2824
|
-
const mvAdd4 = mvView.addChannel({ from: 'mb', to: 'mc',
|
|
2825
|
-
check('addChannel
|
|
2828
|
+
check('joinChannelGroupLines 按分组序号并进指定分组(通道 lineIds 继续追加)', mvAdd2.ok === true && mvAdd2.resolution?.type === 'joinGroup' && mvAdd2.groupId === mvCh2.groups[0].id && mvCh2.lineIds.length === 4 && mvCh2.groups[0].lineIds.length === 3, JSON.stringify({ type: mvAdd2.resolution?.type, groupId: mvAdd2.groupId, lineIds: mvCh2.lineIds, groups: mvCh2.groups.map(group => group.lineIds) }))
|
|
2829
|
+
const mvAdd3 = mvView.addChannelGroupLines('nope')
|
|
2830
|
+
check('分组方法指定了不存在的通道:失败并给出可读原因', mvAdd3.ok === false && typeof mvAdd3.reason === 'string' && mvAdd3.reason.includes('找不到通道'), JSON.stringify({ ok: mvAdd3.ok, reason: mvAdd3.reason }))
|
|
2831
|
+
const mvAdd4 = mvView.addChannel({ from: 'mb', to: 'mc', id: 'mch-x' })
|
|
2832
|
+
check('addChannel 两个节点之间还没有通道:id 是新建通道的 id', mvAdd4.ok === true && mvAdd4.channelId === 'mch-x' && Array.isArray(mvAdd4.channelLineIds) && mvAdd4.channelLineIds.length === 1 && mvChannel('mch-x').lineIds.length === 1, JSON.stringify({ ok: mvAdd4.ok, channelId: mvAdd4.channelId, channelLineIds: mvAdd4.channelLineIds }))
|
|
2826
2833
|
mvView.destroy()
|
|
2827
2834
|
mvHost.remove()
|
|
2828
2835
|
|
|
@@ -3096,8 +3103,8 @@
|
|
|
3096
3103
|
diag('右键回线中段', `世界 ${rcMidWorld.map(value => Number(value).toFixed(2)).join(',')} · 回线折点 ${Array.isArray(rcLine?.path) ? rcLine.path.length : 0}`)
|
|
3097
3104
|
await rcRightClick(rcView.project(rcMidWorld[0], rcMidWorld[1]))
|
|
3098
3105
|
const rcContext = rcHits[1]?.channelContext
|
|
3099
|
-
check('右键落在回线中段:同一份 onContextMenu 载荷里带 channelContext(组数 / 当前分组 / 可用交互)', rcHits.length === 2 && rcContext?.channelId === 'ch-rc' && rcHits[1]?.
|
|
3100
|
-
check('右键通道只发这一条(不再额外发 onChannelContextMenu
|
|
3106
|
+
check('右键落在回线中段:同一份 onContextMenu 载荷里带 channelContext(组数 / 当前分组 / 可用交互)', rcHits.length === 2 && rcContext?.channelId === 'ch-rc' && rcHits[1]?.item?.id === 'rc-1' && rcContext?.groupCount === 1 && (rcContext?.actions ?? []).length > 0, JSON.stringify({ count: rcHits.length, channel: rcContext?.channelId, line: rcHits[1]?.item?.id, groups: rcContext?.groupCount }))
|
|
3107
|
+
check('右键通道只发这一条(不再额外发 onChannelContextMenu),线路下标读 index、id 读 item.id', rcHits[1]?.type === 'line' && rcHits[1]?.channelId === 'ch-rc' && rcHits[1]?.item?.id === 'rc-1' && Number.isInteger(rcHits[1]?.index) && rcHits[1]?.lineId === undefined && rcHits[1]?.lineIndex === undefined && rcHits[1]?.action?.target === 'channel', JSON.stringify({ count: rcHits.length, type: rcHits[1]?.type, index: rcHits[1]?.index, item: rcHits[1]?.item?.id, target: rcHits[1]?.action?.target }))
|
|
3101
3108
|
rcView.destroy()
|
|
3102
3109
|
rcHost.remove()
|
|
3103
3110
|
|
|
@@ -3519,18 +3526,19 @@
|
|
|
3519
3526
|
await settle(60)
|
|
3520
3527
|
}
|
|
3521
3528
|
await rdClick(rdView.project(0, 0))
|
|
3522
|
-
|
|
3529
|
+
const rdClickInfo = rdView.getSelectionInfo()
|
|
3530
|
+
check('单击载荷:selected true / wasSelected false(点之前没选中),总读数走 getSelectionInfo()', rdClicks[0]?.selected === true && rdClicks[0]?.wasSelected === false && rdClicks[0]?.selection === undefined && rdClickInfo.count === 1 && rdClickInfo.points === 1, JSON.stringify({ selected: rdClicks[0]?.selected, was: rdClicks[0]?.wasSelected, count: rdClickInfo.count }))
|
|
3523
3531
|
await rdClick(rdView.project(0, 0))
|
|
3524
|
-
check('再点已经选中的节点:wasSelected 也是 true(点之前就在选中集里)', rdClicks[1]?.selected === true && rdClicks[1]?.wasSelected === true && rdClicks[1]?.selection
|
|
3532
|
+
check('再点已经选中的节点:wasSelected 也是 true(点之前就在选中集里)', rdClicks[1]?.selected === true && rdClicks[1]?.wasSelected === true && rdClicks[1]?.selection === undefined && rdView.getSelectionInfo().count === 1, JSON.stringify({ selected: rdClicks[1]?.selected, was: rdClicks[1]?.wasSelected }))
|
|
3525
3533
|
const rdSelects = []
|
|
3526
3534
|
rdView.on('selectChange', payload => rdSelects.push(payload))
|
|
3527
3535
|
await rdClick(rdView.project(0, 0), { ctrlKey: true })
|
|
3528
3536
|
check('Ctrl + 点已选中的节点:多选取反走 onSelectChange(count 0),不经过 onClick', rdSelects.length === 1 && rdSelects[0].count === 0 && rdSelects[0].items.length === 0 && rdClicks.length === 2 && rdView.getSelectionData().count === 0, JSON.stringify({ selects: rdSelects.length, clicks: rdClicks.length, count: rdSelects[0]?.count }))
|
|
3529
3537
|
rdView.selectFeatures(['rd-a', 'rd-b'])
|
|
3530
3538
|
await rdRightClick(rdView.project(320, 0))
|
|
3531
|
-
check('右键落在没选中的节点上:selected / wasSelected 都是 false
|
|
3539
|
+
check('右键落在没选中的节点上:selected / wasSelected 都是 false,总读数走 getSelectionInfo()', rdMenus[0]?.type === 'point' && rdMenus[0]?.item?.id === 'rd-c' && rdMenus[0]?.selected === false && rdMenus[0]?.wasSelected === false && rdMenus[0]?.selection === undefined && rdView.getSelectionInfo().count === 2, JSON.stringify({ id: rdMenus[0]?.item?.id, selected: rdMenus[0]?.selected, count: rdView.getSelectionInfo().count }))
|
|
3532
3540
|
await rdRightClick(rdView.project(0, 0))
|
|
3533
|
-
check('右键落在已选中的节点上:wasSelected true(据此决定要不要保住整份多选)', rdMenus[1]?.selected === true && rdMenus[1]?.wasSelected === true && rdMenus[1]?.selection
|
|
3541
|
+
check('右键落在已选中的节点上:wasSelected true(据此决定要不要保住整份多选)', rdMenus[1]?.selected === true && rdMenus[1]?.wasSelected === true && rdMenus[1]?.selection === undefined && rdView.getSelectionInfo().count === 2, JSON.stringify({ selected: rdMenus[1]?.selected, was: rdMenus[1]?.wasSelected }))
|
|
3534
3542
|
const rdPointInfo = rdView.getSelectionData()
|
|
3535
3543
|
check('getSelectionData 给读数(ids / count / 各类型条数)', rdPointInfo.count === 2 && rdPointInfo.pointCount === 2 && rdPointInfo.lineCount === 0 && rdPointInfo.channelCount === 0 && rdPointInfo.ids.join(',') === 'rd-a,rd-b', JSON.stringify(rdPointInfo))
|
|
3536
3544
|
rdView.selectFeatures(['rd-1', 'rd-2'])
|
|
@@ -3982,27 +3990,27 @@
|
|
|
3982
3990
|
const apiCorners = [[0, 0], [400, 40]].map(spot => apiView.project(spot[0], spot[1]))
|
|
3983
3991
|
const apiInside = apiCorners.every(spot => spot[0] >= 0 && spot[0] <= apiStats.cssWidth && spot[1] >= 0 && spot[1] <= apiStats.cssHeight)
|
|
3984
3992
|
check('focusOn(一批目标, { zoom: true }):整体包围盒居中,三个点都在视口里', Math.abs(apiBatch.center[0] - 200) < 1e-6 && Math.abs(apiBatch.center[1] - 20) < 1e-6 && apiBatch.scale > 0 && apiInside, JSON.stringify({ center: apiBatch.center, corners: apiCorners }))
|
|
3985
|
-
//
|
|
3986
|
-
apiView.focusOn(['api-a', 'api-b']
|
|
3993
|
+
// 只挪中心、比例一点不动是 focusOn 的缺省语义
|
|
3994
|
+
apiView.focusOn(['api-a', 'api-b'])
|
|
3987
3995
|
const apiCenter1 = apiView.getCamera()
|
|
3988
|
-
check('focusOn(
|
|
3989
|
-
apiView.focusOn([400, 0]
|
|
3996
|
+
check('focusOn(一批):中心挪到这一段的中点,比例一点不动', Math.abs(apiCenter1.center[0] - 100) < 1e-6 && Math.abs(apiCenter1.center[1] - 20) < 1e-6 && apiCenter1.scale === apiBatch.scale, JSON.stringify(apiCenter1.center))
|
|
3997
|
+
apiView.focusOn([400, 0])
|
|
3990
3998
|
const apiCenter2 = apiView.getCamera().center
|
|
3991
|
-
check('focusOn([x, y]
|
|
3992
|
-
apiView.focusOn('api-b'
|
|
3999
|
+
check('focusOn([x, y]) 与 { x, y } 写法都认', Math.abs(apiCenter2[0] - 400) < 1e-6 && Math.abs(apiCenter2[1]) < 1e-6, JSON.stringify(apiCenter2))
|
|
4000
|
+
apiView.focusOn('api-b')
|
|
3993
4001
|
const apiCenter3 = apiView.getCamera().center
|
|
3994
|
-
check('focusOn(id
|
|
4002
|
+
check('focusOn(id):中心挪到这个要素上', Math.abs(apiCenter3[0] - 200) < 1e-6 && Math.abs(apiCenter3[1] - 40) < 1e-6, JSON.stringify(apiCenter3))
|
|
3995
4003
|
const apiChannelScale = apiView.getCamera().scale
|
|
3996
4004
|
apiView.focusOn({ type: 'channel', channelId: 'api-ch' })
|
|
3997
4005
|
const apiChannelCamera = apiView.getCamera()
|
|
3998
4006
|
const apiCenter4 = apiChannelCamera.center
|
|
3999
4007
|
check('focusOn(通道写法) 缺省只居中,线路 / 通道不再自动放大', Math.abs(apiCenter4[0] - 100) < 5 && Math.abs(apiCenter4[1] - 20) < 5 && apiChannelCamera.scale === apiChannelScale, JSON.stringify({ center: apiCenter4, scale: [apiChannelScale, apiChannelCamera.scale] }))
|
|
4000
|
-
apiView.focusOn('没有这个 id'
|
|
4008
|
+
apiView.focusOn('没有这个 id')
|
|
4001
4009
|
const apiCenter5 = apiView.getCamera().center
|
|
4002
4010
|
check('focusOn:认不出来的目标什么都不做(视角停在原处)', apiCenter5[0] === apiCenter4[0] && apiCenter5[1] === apiCenter4[1], JSON.stringify(apiCenter5))
|
|
4003
|
-
apiView.focusOn({ minX: 0, minY: 0, maxX: 400, maxY: 40 }
|
|
4011
|
+
apiView.focusOn({ minX: 0, minY: 0, maxX: 400, maxY: 40 })
|
|
4004
4012
|
const apiCenter6 = apiView.getCamera().center
|
|
4005
|
-
check('focusOn(
|
|
4013
|
+
check('focusOn(一段范围):取中心', Math.abs(apiCenter6[0] - 200) < 1e-6 && Math.abs(apiCenter6[1] - 20) < 1e-6, JSON.stringify(apiCenter6))
|
|
4006
4014
|
// select: true:被聚焦的要素同时变成选中状态(与接口选中同一份 state);mode 决定怎么并进当前选中集
|
|
4007
4015
|
const apiBeforeFocusSelect = apiView.getSelectionData().ids.join(',')
|
|
4008
4016
|
apiView.focusOn(['api-a', 'api-b', 'api-c'], { select: true, zoom: true, padding: 20 })
|
|
@@ -4733,13 +4741,13 @@
|
|
|
4733
4741
|
check('addChannel 新签名:lineIds 自动按线路数组每项的 id 构建', JSON.stringify(nwCh1?.lineIds) === JSON.stringify(['nl1', 'nl2']) && JSON.stringify(nwAdd.lineIds) === JSON.stringify(['nl1', 'nl2']), JSON.stringify(nwCh1?.lineIds))
|
|
4734
4742
|
check('addChannel 新签名:线路数组逐条落地(自己的字段保留、from / to 固定两端)', nwLine('nl1')?.color === '#112233' && nwLine('nl1')?.from === 'na' && nwLine('nl1')?.to === 'nb' && nwAdd.circuits === 2, JSON.stringify({ l1: nwLine('nl1'), count: nwAdd.circuits }))
|
|
4735
4743
|
check('addChannel 新签名:第三段分组信息写进声明(id / lineIds / path)', nwCh1?.groups?.length === 1 && nwCh1.groups[0].id === 'ng1' && JSON.stringify(nwCh1.groups[0].lineIds) === JSON.stringify(['nl1', 'nl2']) && JSON.stringify(nwCh1.groups[0].path) === JSON.stringify([[0, 30]]), JSON.stringify(nwCh1?.groups))
|
|
4736
|
-
check('addChannel
|
|
4744
|
+
check('addChannel 缺省不改变选中集(select 是显式选项)', nwView.getSelectionData().ids.length === 0, JSON.stringify(nwView.getSelectionData().ids))
|
|
4737
4745
|
|
|
4738
|
-
// ②
|
|
4746
|
+
// ② 旧写法已移除;只写 { from, to } 是新签名,会新建一条回线
|
|
4739
4747
|
const nwLegacy = nwView.addChannel({ from: 'nc', to: 'nd', circuits: 2, name: '丙丁' })
|
|
4740
|
-
check('addChannel
|
|
4748
|
+
check('addChannel 旧 circuits 写法已移除:明确失败且不写数据', nwLegacy.ok === false && String(nwLegacy.reason).includes('circuits') && nwView.getOptions().lines.filter(item => item.from === 'nc' && item.to === 'nd').length === 0, JSON.stringify({ ok: nwLegacy.ok, reason: nwLegacy.reason }))
|
|
4741
4749
|
const nwBare = nwView.addChannel({ from: 'nc', to: 'nd' })
|
|
4742
|
-
check('只写 { from, to }
|
|
4750
|
+
check('只写 { from, to }:新建通道并自动建一条回线', nwBare.ok === true && nwBare.resolution?.type === 'newChannel' && nwBare.lineIds.length === 1, JSON.stringify({ ok: nwBare.ok, type: nwBare.resolution?.type, reason: nwBare.reason }))
|
|
4743
4751
|
|
|
4744
4752
|
// ③ 两个节点之间已有通道:新签名整条失败,plan 里带分组信息(拿来给用户看「已经有几组」)
|
|
4745
4753
|
const nwLinesBefore = nwView.getOptions().lines.length
|
|
@@ -4748,9 +4756,11 @@
|
|
|
4748
4756
|
check('失败结果里的 plan 带 hasChannel / hasGroup / groups / channel / group', nwBlocked.plan?.hasChannel === true && nwBlocked.plan?.hasGroup === true && nwBlocked.plan.groups.length === 1 && nwBlocked.plan.channel?.id === 'nc1' && nwBlocked.plan.group?.id === 'ng1', JSON.stringify({ hasChannel: nwBlocked.plan?.hasChannel, groups: nwBlocked.plan?.groups?.map(item => item.id) }))
|
|
4749
4757
|
|
|
4750
4758
|
// ④ 拆出来的两个方法:新加一组 / 并进某一组
|
|
4751
|
-
const
|
|
4759
|
+
const nwSelectBefore = nwSelectChanges.length
|
|
4760
|
+
const nwNewGroup = nwView.addChannelGroupLines('nc1', [{ id: 'nl3', color: '#334455' }], { id: 'ng2' }, { select: true })
|
|
4752
4761
|
const nwCh1b = nwChannel('nc1')
|
|
4753
4762
|
check('addChannelGroupLines:新回线进新分组(成员表一起长)', nwNewGroup.ok === true && nwNewGroup.groupId === 'ng2' && nwNewGroup.resolution?.type === 'newGroup' && JSON.stringify(nwCh1b.lineIds) === JSON.stringify(['nl1', 'nl2', 'nl3']) && nwCh1b.groups.length === 2, JSON.stringify({ ok: nwNewGroup.ok, groupId: nwNewGroup.groupId }))
|
|
4763
|
+
check('addChannelGroupLines({ select: true }):落地后只选中这次的新回线,并只发一次选中变化', nwSelectChanges.length === nwSelectBefore + 1 && JSON.stringify(nwView.getSelectionData().ids) === JSON.stringify(['nl3']), JSON.stringify({ changes: nwSelectChanges.length - nwSelectBefore, ids: nwView.getSelectionData().ids }))
|
|
4754
4764
|
const nwJoin = nwView.joinChannelGroupLines('nc1', 'ng1', [{ id: 'nl4' }])
|
|
4755
4765
|
check('joinChannelGroupLines:按分组 id 并进某一组', nwJoin.ok === true && nwJoin.groupId === 'ng1' && JSON.stringify(nwChannel('nc1').groups.find(item => item.id === 'ng1').lineIds) === JSON.stringify(['nl1', 'nl2', 'nl4']), JSON.stringify({ groups: nwChannel('nc1')?.groups?.map(item => [item.id, item.lineIds]) }))
|
|
4756
4766
|
const nwJoinIndex = nwView.joinChannelGroupLines('nc1', 1, 'nl5')
|
|
@@ -4759,8 +4769,10 @@
|
|
|
4759
4769
|
check('通道找不到时拆出来的方法给出 reason、不抛错', nwJoinMiss.ok === false && String(nwJoinMiss.reason).includes('找不到通道'), JSON.stringify({ ok: nwJoinMiss.ok, reason: nwJoinMiss.reason }))
|
|
4760
4770
|
|
|
4761
4771
|
// ⑤ addChannels 的每一项也认新签名(lineData + group 写在对象上)
|
|
4762
|
-
const
|
|
4772
|
+
const nwBatchSelectBefore = nwSelectChanges.length
|
|
4773
|
+
const nwMany = nwView.addChannels([{ from: 'na', to: 'nc', name: '甲丙', id: 'nc2', lineData: [{ id: 'nl6' }, { id: 'nl7' }], group: { id: 'ng3' } }], { select: true })
|
|
4763
4774
|
check('addChannels 的每一项认新签名(lineData + group)', nwMany.ok === true && nwMany.channelIds[0] === 'nc2' && JSON.stringify(nwChannel('nc2')?.lineIds) === JSON.stringify(['nl6', 'nl7']) && nwChannel('nc2')?.groups?.[0]?.id === 'ng3', JSON.stringify({ ok: nwMany.ok, ids: nwMany.channelIds }))
|
|
4775
|
+
check('addChannels({ select: true }):两条回线一次选中,不逐条发选中变化', nwSelectChanges.length === nwBatchSelectBefore + 1 && JSON.stringify(nwView.getSelectionData().ids) === JSON.stringify(['nl6', 'nl7']), JSON.stringify({ changes: nwSelectChanges.length - nwBatchSelectBefore, ids: nwView.getSelectionData().ids }))
|
|
4764
4776
|
|
|
4765
4777
|
// ⑥ updateChannel 的 group(单数:改一组的信息)/ groups(复数:整份换)
|
|
4766
4778
|
nwView.updateChannel('nc1', { group: { id: 'ng1', path: [[7, 8]] } })
|
|
@@ -4784,7 +4796,7 @@
|
|
|
4784
4796
|
send('pointerdown', { buttons: 1 })
|
|
4785
4797
|
send('pointerup', { buttons: 0 })
|
|
4786
4798
|
}
|
|
4787
|
-
const
|
|
4799
|
+
const nwSelectedBeforeDraft = nwView.getSelectionData().ids
|
|
4788
4800
|
nwEvents.length = 0
|
|
4789
4801
|
nwSelectChanges.length = 0
|
|
4790
4802
|
nwView.beginAddChannel({ select: false })
|
|
@@ -4794,7 +4806,7 @@
|
|
|
4794
4806
|
await settle(40)
|
|
4795
4807
|
nwClick(nwScreenOf('nb'))
|
|
4796
4808
|
await settle(60)
|
|
4797
|
-
check('select 关着:点两个节点不改变选中集(只画两个草稿点)', JSON.stringify(nwView.getSelectionData().ids) === JSON.stringify(
|
|
4809
|
+
check('select 关着:点两个节点不改变选中集(只画两个草稿点)', JSON.stringify(nwView.getSelectionData().ids) === JSON.stringify(nwSelectedBeforeDraft) && nwSelectChanges.length === 0, JSON.stringify(nwView.getSelectionData().ids))
|
|
4798
4810
|
const nwReadyPlain = nwEvents.find(payload => payload.phase === 'ready')
|
|
4799
4811
|
check('结束事件(ready)带两个节点与「没有分组」的读数', nwReadyPlain !== undefined && nwReadyPlain.from.id === 'nd' && nwReadyPlain.to.id === 'nb' && nwReadyPlain.finished === true && nwReadyPlain.hasChannel === false && nwReadyPlain.hasGroup === false && nwReadyPlain.groups.length === 0 && nwReadyPlain.group === null && nwReadyPlain.channel === null, JSON.stringify({ from: nwReadyPlain?.from?.id, to: nwReadyPlain?.to?.id, hasGroup: nwReadyPlain?.hasGroup }))
|
|
4800
4812
|
check('beginAddChannel 只负责示例路径:ready 之后草稿还在、一条数据都没落', nwView.getAddChannelDraft()?.phase === 'ready' && nwEvents.every(payload => payload.phase !== 'commit'), JSON.stringify({ draft: nwView.getAddChannelDraft()?.phase, phases: nwEvents.map(payload => payload.phase) }))
|
|
@@ -4817,6 +4829,7 @@
|
|
|
4817
4829
|
nwDraftMode = 'commit'
|
|
4818
4830
|
nwEvents.length = 0
|
|
4819
4831
|
const nwLinesBefore2 = nwView.getOptions().lines.length
|
|
4832
|
+
const nwSelectedBeforeInside = nwView.getSelectionData().ids
|
|
4820
4833
|
nwView.beginAddChannel()
|
|
4821
4834
|
await settle(40)
|
|
4822
4835
|
nwClick(nwScreenOf('nd'))
|
|
@@ -4824,7 +4837,7 @@
|
|
|
4824
4837
|
nwClick(nwScreenOf('nb'))
|
|
4825
4838
|
await settle(80)
|
|
4826
4839
|
check('事件里 endAddChannel + addChannel:真实通道与回线落地、假通道不留', nwInside?.ok === true && nwChannel('nc9') !== undefined && nwLine('nl9') !== undefined && nwLine('nl10') !== undefined && nwView.getOptions().lines.length === nwLinesBefore2 + 2, JSON.stringify({ ok: nwInside?.ok, lines: nwView.getOptions().lines.map(item => item.id) }))
|
|
4827
|
-
check('
|
|
4840
|
+
check('事件里落地之后草稿收掉、缺省不改选中集', nwView.getAddChannelDraft() === null && JSON.stringify(nwView.getSelectionData().ids) === JSON.stringify(nwSelectedBeforeInside), JSON.stringify({ before: nwSelectedBeforeInside, after: nwView.getSelectionData().ids }))
|
|
4828
4841
|
|
|
4829
4842
|
// ⑩ select: true 与结束事件里的分组读数;提前结束用 cancelAddChannel
|
|
4830
4843
|
nwDraftMode = null
|
|
@@ -4938,10 +4951,10 @@
|
|
|
4938
4951
|
check('addLine 不传 id:按 from-to-序号 自动编号(撞车由 uniqueLineId 往后排)',
|
|
4939
4952
|
bvAuto.ok === true && String(bvAuto.lineId) === 'bb-bc-0',
|
|
4940
4953
|
JSON.stringify({ ok: bvAuto.ok, lineId: bvAuto.lineId }))
|
|
4941
|
-
const
|
|
4942
|
-
check('
|
|
4943
|
-
|
|
4944
|
-
JSON.stringify({ ok:
|
|
4954
|
+
const bvChannel = bvView.addChannel({ from: 'ba', to: 'bb' }, ['bare-4', 'bare-5'])
|
|
4955
|
+
check('addChannel 第二段同样认裸 id:给了两条就建两条回线',
|
|
4956
|
+
bvChannel.ok === true && JSON.stringify(bvChannel.lineIds.map(String)) === JSON.stringify(['bare-4', 'bare-5']),
|
|
4957
|
+
JSON.stringify({ ok: bvChannel.ok, lineIds: bvChannel.lineIds }))
|
|
4945
4958
|
bvView.destroy()
|
|
4946
4959
|
bvHost.remove()
|
|
4947
4960
|
// 容器先 display:none(量不出视口)再显示:挂起的那次落位兑现的是「请求那一刻」的范围,中途新加的远处节点不算进来
|
|
@@ -4993,7 +5006,96 @@
|
|
|
4993
5006
|
JSON.stringify(dfView.getCamera()))
|
|
4994
5007
|
dfView.destroy()
|
|
4995
5008
|
dfHost.remove()
|
|
4996
|
-
|
|
5009
|
+
|
|
5010
|
+
/* 新增接口:选中由 options.select 显式打开;addLine 一步撤销;有通道声明时仍走追加式补线 */
|
|
5011
|
+
const awHost = document.createElement('div')
|
|
5012
|
+
awHost.style.cssText = 'width:520px;height:340px'
|
|
5013
|
+
document.body.appendChild(awHost)
|
|
5014
|
+
const awSelectChanges = []
|
|
5015
|
+
const awView = createGisView(awHost, {
|
|
5016
|
+
points: [
|
|
5017
|
+
{ id: 'aa', x: -180, y: -100 },
|
|
5018
|
+
{ id: 'ab', x: -90, y: -100 },
|
|
5019
|
+
{ id: 'ac', x: 0, y: -100 },
|
|
5020
|
+
{ id: 'ad', x: 90, y: -100 },
|
|
5021
|
+
{ id: 'ae', x: 0, y: 100 },
|
|
5022
|
+
{ id: 'af', x: 180, y: 100 }
|
|
5023
|
+
],
|
|
5024
|
+
lines: [],
|
|
5025
|
+
channels: [],
|
|
5026
|
+
features: { channelDraft: true },
|
|
5027
|
+
history: true,
|
|
5028
|
+
showGrid: false,
|
|
5029
|
+
onSelectChange: event => awSelectChanges.push(event)
|
|
5030
|
+
})
|
|
5031
|
+
await settle(60)
|
|
5032
|
+
const awIds = () => awView.getSelectionData().ids
|
|
5033
|
+
const awLine = id => awView.getOptions().lines.find(item => String(item.id) === String(id))
|
|
5034
|
+
const awInitialChanges = awSelectChanges.length
|
|
5035
|
+
const awPointPlain = awView.addPoint({ id: 'aw-p1', x: 40, y: 30 })
|
|
5036
|
+
check('addPoint 缺省不改变选中集', awPointPlain.ok === true && awIds().length === 0 && awSelectChanges.length === awInitialChanges, JSON.stringify({ ids: awIds(), changes: awSelectChanges.length - awInitialChanges }))
|
|
5037
|
+
const awPointsSelected = awView.addPoints([{ id: 'aw-p2', x: 50, y: 35 }, { id: 'aw-p3', x: 60, y: 40 }], { select: true })
|
|
5038
|
+
check('addPoints({ select: true }):一次选中这批新节点', awPointsSelected.ok === true && JSON.stringify(awIds()) === JSON.stringify(['aw-p2', 'aw-p3']), JSON.stringify(awIds()))
|
|
5039
|
+
awView.selectFeatures(null)
|
|
5040
|
+
const awLinesPlain = awView.addLines([{ id: 'aw-l1', from: 'aa', to: 'ab' }])
|
|
5041
|
+
check('addLines 缺省不改变选中集', awLinesPlain.ok === true && awIds().length === 0, JSON.stringify(awIds()))
|
|
5042
|
+
const awLinesSelected = awView.addLines([{ id: 'aw-l2', from: 'ac', to: 'ad' }, { id: 'aw-l3', from: 'ae', to: 'af' }], { select: true })
|
|
5043
|
+
check('addLines({ select: true }):一次选中这批新线路', awLinesSelected.ok === true && JSON.stringify(awIds()) === JSON.stringify(['aw-l2', 'aw-l3']), JSON.stringify(awIds()))
|
|
5044
|
+
awView.selectFeatures(null)
|
|
5045
|
+
const awLinePlain = awView.addLine({ from: 'aa', to: 'ac', id: 'aw-l4' })
|
|
5046
|
+
check('addLine 缺省不改变选中集', awLinePlain.ok === true && awIds().length === 0, JSON.stringify(awIds()))
|
|
5047
|
+
const awLineSelected = awView.addLine({ from: 'ae', to: 'af', id: 'aw-l5' }, undefined, { select: true })
|
|
5048
|
+
check('addLine({ select: true }):只选中新增回线', awLineSelected.ok === true && JSON.stringify(awIds()) === JSON.stringify(['aw-l5']), JSON.stringify(awIds()))
|
|
5049
|
+
awView.selectFeatures(null)
|
|
5050
|
+
const awChannelPlain = awView.addChannel({ from: 'aa', to: 'ab', id: 'aw-c1' }, ['aw-c1-1'])
|
|
5051
|
+
check('addChannel 缺省不改变选中集', awChannelPlain.ok === true && awIds().length === 0, JSON.stringify(awIds()))
|
|
5052
|
+
const awChannelSelected = awView.addChannel({ from: 'ab', to: 'ad', id: 'aw-c2' }, ['aw-c2-1', 'aw-c2-2'], undefined, { select: true })
|
|
5053
|
+
check('addChannel({ select: true }):只选中这次新建的全部回线', awChannelSelected.ok === true && JSON.stringify(awIds()) === JSON.stringify(['aw-c2-1', 'aw-c2-2']), JSON.stringify(awIds()))
|
|
5054
|
+
const awLineLegacy = awView.addLine({ from: 'ac', to: 'af', circuits: 2 })
|
|
5055
|
+
check('addLine 旧 circuits 入参已移除:明确失败且不写数据', awLineLegacy.ok === false && String(awLineLegacy.reason).includes('circuits') && awLine('ac-af-0') === undefined, JSON.stringify({ ok: awLineLegacy.ok, reason: awLineLegacy.reason }))
|
|
5056
|
+
const awCommitLegacy = awView.commitAddChannel({ lineItems: [{ id: 'aw-old-commit' }] })
|
|
5057
|
+
check('commitAddChannel 旧 lineItems 入参已移除:明确失败且不写数据', awCommitLegacy.ok === false && String(awCommitLegacy.reason).includes('lineItems') && awLine('aw-old-commit') === undefined, JSON.stringify({ ok: awCommitLegacy.ok, reason: awCommitLegacy.reason }))
|
|
5058
|
+
const awChannelGroupsBefore = JSON.stringify(awView.getOptions().channels)
|
|
5059
|
+
const awLineCountBeforeGroups = awView.getOptions().lines.length
|
|
5060
|
+
const awGroupLegacy = awView.addChannelGroups('aw-c2', [{ lineData: [{ id: 'aw-group-new' }], lineItems: [{ id: 'aw-group-old' }] }])
|
|
5061
|
+
check('addChannelGroups 旧 lineItems 入参已移除:整组拒绝、不改数据', awGroupLegacy.ok === false && String(awGroupLegacy.reason).includes('lineItems') && JSON.stringify(awView.getOptions().channels) === awChannelGroupsBefore && awView.getOptions().lines.length === awLineCountBeforeGroups, JSON.stringify({ ok: awGroupLegacy.ok, reason: awGroupLegacy.reason }))
|
|
5062
|
+
|
|
5063
|
+
awView.beginAddChannel({ kind: 'line' })
|
|
5064
|
+
await settle(20)
|
|
5065
|
+
const awDraftKind = awView.getAddChannelDraft()?.kind
|
|
5066
|
+
awView.continueAddChannel({ kind: 'line' })
|
|
5067
|
+
await settle(20)
|
|
5068
|
+
const awContinuedKind = awView.getAddChannelDraft()?.kind
|
|
5069
|
+
awView.cancelAddChannel()
|
|
5070
|
+
awView.beginAddLine({ kind: 'channel' })
|
|
5071
|
+
await settle(20)
|
|
5072
|
+
const awLineDraftKind = awView.getAddChannelDraft()?.kind
|
|
5073
|
+
awView.cancelAddChannel()
|
|
5074
|
+
check('beginAddChannel 固定通道语义:运行时 kind: line 不再切换入口', awDraftKind === 'channel', JSON.stringify({ kind: awDraftKind }))
|
|
5075
|
+
check('continueAddChannel 不切换入口语义:通道草稿传 kind: line 仍是通道', awContinuedKind === 'channel', JSON.stringify({ kind: awContinuedKind }))
|
|
5076
|
+
check('beginAddLine 固定线路语义:运行时 kind: channel 不再切换入口', awLineDraftKind === 'line', JSON.stringify({ kind: awLineDraftKind }))
|
|
5077
|
+
|
|
5078
|
+
const awChannelsBeforeLine = JSON.stringify(awView.getOptions().channels)
|
|
5079
|
+
awView.clearHistory()
|
|
5080
|
+
const awHistoryLine = awView.addLine({ from: 'aa', to: 'af', id: 'aw-history' })
|
|
5081
|
+
await settle(20)
|
|
5082
|
+
const awCenter = awView.project(0, 0)
|
|
5083
|
+
const awHistoryHit = awView.pick(awCenter[0], awCenter[1])
|
|
5084
|
+
const awHistoryState = awView.getHistoryState()
|
|
5085
|
+
const awUndo = awView.undo()
|
|
5086
|
+
await settle(20)
|
|
5087
|
+
const awUndoHit = awView.pick(awCenter[0], awCenter[1])
|
|
5088
|
+
const awChannelsAfterUndo = JSON.stringify(awView.getOptions().channels)
|
|
5089
|
+
check('addLine 有通道声明时仍可落地与拾取,通道成员 / 分组不变', awHistoryLine.ok === true && awHistoryHit?.item?.id === 'aw-history' && awChannelsBeforeLine === JSON.stringify(awView.getOptions().channels), JSON.stringify({ hit: awHistoryHit?.item?.id }))
|
|
5090
|
+
check('addLine 的撤销只记一步:一次 undo 就摘掉这条回线', awHistoryState.undoCount === 1 && awUndo?.type === 'addLine' && awLine('aw-history') === undefined && awUndoHit?.item?.id !== 'aw-history' && awChannelsAfterUndo === awChannelsBeforeLine, JSON.stringify({ before: awHistoryState.undoCount, undo: awUndo, hit: awUndoHit?.item?.id }))
|
|
5091
|
+
const awRedo = awView.redo()
|
|
5092
|
+
await settle(20)
|
|
5093
|
+
const awRemovedLine = awView.removeLine('aw-history')
|
|
5094
|
+
check('addLine 重做后再删除:只摘回线,通道声明保持不变', awRedo?.type === 'addLine' && awRemovedLine.ok === true && awLine('aw-history') === undefined && JSON.stringify(awView.getOptions().channels) === awChannelsBeforeLine, JSON.stringify({ redo: awRedo, removed: awRemovedLine.ok }))
|
|
5095
|
+
check('有通道时 addLine 仍返回独立线路读数(channelId / channelLineIds 为 null)', awHistoryLine.channelId === null && awHistoryLine.channelLineIds === null && awHistoryLine.kind === 'line', JSON.stringify({ channelId: awHistoryLine.channelId, channelLineIds: awHistoryLine.channelLineIds }))
|
|
5096
|
+
awView.destroy()
|
|
5097
|
+
awHost.remove()
|
|
5098
|
+
|
|
4997
5099
|
nwHost.remove()
|
|
4998
5100
|
/* 这一轮新增:组件方法审计(getPointStyle / updateCopyPoint / setCurrentChannelGroup(null) / options 透传 / getElementBounds / 拐点中间点口径 / minimap.setZoom / off / runChannelAction 认不出的动作) */
|
|
4999
5101
|
const auHost = document.createElement('div')
|
|
@@ -5475,6 +5577,104 @@
|
|
|
5475
5577
|
clearedLayers === 1 && draftView.getWebGLLayers().length === 0 && (draftView.getOptions().webglLayers ?? []).length === 0 && draftView.requestRender() === draftView,
|
|
5476
5578
|
JSON.stringify({ cleared: clearedLayers, layers: draftView.getWebGLLayers().length, options: draftView.getOptions().webglLayers?.length }))
|
|
5477
5579
|
|
|
5580
|
+
/* beginAddLine / beginAddChannel:单一通道阻断、已有通道新分组 / 指定分组、beginAddLine 挂回线 */
|
|
5581
|
+
const bdHost = document.createElement('div')
|
|
5582
|
+
bdHost.style.cssText = 'width:520px;height:320px'
|
|
5583
|
+
document.body.append(bdHost)
|
|
5584
|
+
const bdEvents = []
|
|
5585
|
+
const bdView = createGisView(bdHost, {
|
|
5586
|
+
points: [
|
|
5587
|
+
{ id: 'bda', x: 0, y: 0, name: 'A' },
|
|
5588
|
+
{ id: 'bdb', x: 80, y: 0, name: 'B' },
|
|
5589
|
+
{ id: 'bdc', x: 0, y: 70, name: 'C' }
|
|
5590
|
+
],
|
|
5591
|
+
lines: [],
|
|
5592
|
+
fitPadding: 60,
|
|
5593
|
+
showGrid: false,
|
|
5594
|
+
features: { channelDraft: true },
|
|
5595
|
+
onChannelDraft: payload => bdEvents.push(payload)
|
|
5596
|
+
})
|
|
5597
|
+
await settle(120)
|
|
5598
|
+
const bdSeed = bdView.addChannel({ id: 'bd-ch', name: '已有通道', from: 'bda', to: 'bdb' }, [
|
|
5599
|
+
{ id: 'bd-l1' },
|
|
5600
|
+
{ id: 'bd-l2' }
|
|
5601
|
+
], [
|
|
5602
|
+
{ id: 'bd-g1', lineIds: ['bd-l1'] },
|
|
5603
|
+
{ id: 'bd-g2', lineIds: ['bd-l2'] }
|
|
5604
|
+
])
|
|
5605
|
+
check('beginAddChannel 前置:已有通道带两个命名分组,供 singleChannel / newGroup / joinGroup 测试', bdSeed.ok === true && bdView.getChannelGroups('bd-ch').length === 2, JSON.stringify({ ok: bdSeed.ok, groups: bdView.getChannelGroups('bd-ch').map(group => group.id) }))
|
|
5606
|
+
const bdCanvas = bdView.canvas
|
|
5607
|
+
const bdClick = async (id) => {
|
|
5608
|
+
const point = bdView.getData().points.find(item => item.id === id)
|
|
5609
|
+
const screen = bdView.project(point.x, point.y)
|
|
5610
|
+
const rect = bdCanvas.getBoundingClientRect()
|
|
5611
|
+
for (const type of ['pointerdown', 'pointerup']) {
|
|
5612
|
+
bdCanvas.dispatchEvent(new PointerEvent(type, {
|
|
5613
|
+
bubbles: true,
|
|
5614
|
+
cancelable: true,
|
|
5615
|
+
composed: true,
|
|
5616
|
+
pointerId: 31,
|
|
5617
|
+
pointerType: 'mouse',
|
|
5618
|
+
isPrimary: true,
|
|
5619
|
+
button: 0,
|
|
5620
|
+
clientX: rect.left + screen[0],
|
|
5621
|
+
clientY: rect.top + screen[1]
|
|
5622
|
+
}))
|
|
5623
|
+
}
|
|
5624
|
+
await settle(50)
|
|
5625
|
+
}
|
|
5626
|
+
|
|
5627
|
+
bdView.beginAddLine({ from: 'bda', singleChannel: true })
|
|
5628
|
+
const bdLineStart = bdView.getAddChannelDraft()
|
|
5629
|
+
await bdClick('bdb')
|
|
5630
|
+
const bdLineReady = bdView.getAddChannelDraft()
|
|
5631
|
+
const bdLineBefore = bdView.getData().lines.length
|
|
5632
|
+
const bdLineResult = bdView.commitAddChannel()
|
|
5633
|
+
check('beginAddLine 不把 singleChannel 当成挂通道开关:两端已有通道仍出独立线路草稿', bdLineStart?.kind === 'line' && bdLineStart.singleChannel === false && bdLineStart.existingChannel === null && bdLineReady?.blocked === false, JSON.stringify({ kind: bdLineStart?.kind, single: bdLineStart?.singleChannel, existing: bdLineStart?.existingChannel, readyBlocked: bdLineReady?.blocked }))
|
|
5634
|
+
check('beginAddLine 提交后只加独立线路,不碰已有通道', bdLineResult.ok === true && bdLineResult.kind === 'line' && bdView.getData().lines.length === bdLineBefore + 1 && bdView.getChannelGroups('bd-ch').length === 2, JSON.stringify({ kind: bdLineResult.kind, channelId: bdLineResult.channelId, groups: bdView.getChannelGroups('bd-ch').length }))
|
|
5635
|
+
|
|
5636
|
+
bdEvents.length = 0
|
|
5637
|
+
const bdBlockLines = bdView.getData().lines.length
|
|
5638
|
+
bdView.beginAddChannel({ from: 'bda', singleChannel: true })
|
|
5639
|
+
await bdClick('bdb')
|
|
5640
|
+
const bdBlockDraft = bdView.getAddChannelDraft()
|
|
5641
|
+
const bdBlockResult = bdView.commitAddChannel()
|
|
5642
|
+
const bdBlockEvent = bdEvents.find(payload => payload.phase === 'blocked')
|
|
5643
|
+
check('singleChannel:两端已有通道时 ready 直接 blocked,并给出 singleChannel 原因', bdBlockDraft?.blocked === true && bdBlockDraft.existingChannel === 'block' && /singleChannel/.test(bdBlockDraft.reason ?? ''), JSON.stringify({ blocked: bdBlockDraft?.blocked, existing: bdBlockDraft?.existingChannel, reason: bdBlockDraft?.reason }))
|
|
5644
|
+
check('singleChannel:隐式提交发 blocked 事件且不改数据,事件仍报 channel / 当前电路数', bdBlockResult.ok === false && bdBlockEvent?.kind === 'channel' && bdBlockEvent?.singleChannel === true && bdView.getData().lines.length === bdBlockLines, JSON.stringify({ result: bdBlockResult.ok, event: bdBlockEvent?.phase, kind: bdBlockEvent?.kind, lines: bdView.getData().lines.length }))
|
|
5645
|
+
|
|
5646
|
+
bdEvents.length = 0
|
|
5647
|
+
bdView.beginAddChannel({ from: 'bda', singleChannel: true, existingChannel: 'newGroup' })
|
|
5648
|
+
await bdClick('bdb')
|
|
5649
|
+
const bdNewGroupDraft = bdView.getAddChannelDraft()
|
|
5650
|
+
const bdNewGroupResult = bdView.commitAddChannel()
|
|
5651
|
+
check('existingChannel: newGroup 覆盖 singleChannel:已有通道新加一组回线', bdNewGroupDraft?.blocked === false && bdNewGroupDraft.preferred === 'newGroup' && bdNewGroupResult.ok === true && bdNewGroupResult.channelId === 'bd-ch' && bdView.getChannelGroups('bd-ch').length === 3, JSON.stringify({ preferred: bdNewGroupDraft?.preferred, ok: bdNewGroupResult.ok, groupId: bdNewGroupResult.groupId, groups: bdView.getChannelGroups('bd-ch').length }))
|
|
5652
|
+
|
|
5653
|
+
bdEvents.length = 0
|
|
5654
|
+
bdView.beginAddChannel({ from: 'bda', existingChannel: 'joinGroup', groupId: 'bd-g1' })
|
|
5655
|
+
await bdClick('bdb')
|
|
5656
|
+
const bdJoinDraft = bdView.getAddChannelDraft()
|
|
5657
|
+
const bdJoinBefore = bdView.getChannelGroups('bd-ch').find(group => group.id === 'bd-g1')?.lineIndexes.length ?? 0
|
|
5658
|
+
const bdJoinResult = bdView.commitAddChannel()
|
|
5659
|
+
const bdJoinAfter = bdView.getChannelGroups('bd-ch').find(group => group.id === 'bd-g1')?.lineIndexes.length ?? 0
|
|
5660
|
+
check('existingChannel: joinGroup + groupId:新回线落进指定分组,读数带回 targetGroupId', bdJoinDraft?.targetGroupId === 'bd-g1' && bdJoinResult.ok === true && bdJoinResult.groupId === 'bd-g1' && bdJoinAfter === bdJoinBefore + 1, JSON.stringify({ draftTarget: bdJoinDraft?.targetGroupId, groupId: bdJoinResult.groupId, before: bdJoinBefore, after: bdJoinAfter }))
|
|
5661
|
+
|
|
5662
|
+
bdEvents.length = 0
|
|
5663
|
+
bdView.beginAddLine({ from: 'bda', existingChannel: 'joinGroup', groupId: 'bd-g2' })
|
|
5664
|
+
await bdClick('bdb')
|
|
5665
|
+
const bdAttachDraft = bdView.getAddChannelDraft()
|
|
5666
|
+
const bdAttachChannels = bdView.getOptions().channels.length
|
|
5667
|
+
const bdAttachResult = bdView.commitAddChannel()
|
|
5668
|
+
check('beginAddLine + existingChannel: joinGroup:线路入口也能把新回线挂进已有分组(不新建通道)', bdAttachDraft?.kind === 'line' && bdAttachDraft.existingChannel === 'joinGroup' && bdAttachDraft.targetGroupId === 'bd-g2' && bdAttachResult.ok === true && bdAttachResult.kind === 'channel' && bdAttachResult.groupId === 'bd-g2' && bdView.getOptions().channels.length === bdAttachChannels, JSON.stringify({ draftKind: bdAttachDraft?.kind, target: bdAttachDraft?.targetGroupId, resultKind: bdAttachResult.kind, groupId: bdAttachResult.groupId, channels: bdView.getOptions().channels.length }))
|
|
5669
|
+
|
|
5670
|
+
bdView.beginAddChannel({ from: 'bda', existingChannel: 'auto' })
|
|
5671
|
+
await bdClick('bdb')
|
|
5672
|
+
const bdAutoDraft = bdView.getAddChannelDraft()
|
|
5673
|
+
check('existingChannel: auto:有组余量时优先推荐新分组', bdAutoDraft?.blocked === false && bdAutoDraft.preferred === 'newGroup' && bdAutoDraft.existingChannel === 'auto', JSON.stringify({ preferred: bdAutoDraft?.preferred, existing: bdAutoDraft?.existingChannel }))
|
|
5674
|
+
bdView.cancelAddChannel()
|
|
5675
|
+
bdView.destroy()
|
|
5676
|
+
bdHost.remove()
|
|
5677
|
+
|
|
5478
5678
|
/* 隐藏 / 显示、节点拆分、通道变化对账:接口级自测 */
|
|
5479
5679
|
const splitHost = document.createElement('div')
|
|
5480
5680
|
splitHost.style.cssText = 'width:640px;height:380px'
|
|
@@ -5591,6 +5791,38 @@
|
|
|
5591
5791
|
lineOnlyView.removeLine('lo-ab')
|
|
5592
5792
|
const lineOnlyAfterDelete = lineOnlyView.getChangedLines().find(line => line.id === 'lo-ab')
|
|
5593
5793
|
check('getChangedLines:只有节点和线路时独立对账,删线路后同步清账', lineOnlyInitial && Boolean(lineOnlyChange) && lineOnlyChange.fields.includes('name') && !lineOnlyAfterDelete, JSON.stringify({ initial: lineOnlyInitial, change: lineOnlyChange?.reasons, after: lineOnlyAfterDelete ?? null }))
|
|
5794
|
+
const autoSplitHost = document.createElement('div')
|
|
5795
|
+
autoSplitHost.style.cssText = 'width:480px;height:280px'
|
|
5796
|
+
document.body.append(autoSplitHost)
|
|
5797
|
+
const autoSplitView = createGisView(autoSplitHost, {
|
|
5798
|
+
points: [
|
|
5799
|
+
{ id: 'as-hub', x: 0, y: 0 },
|
|
5800
|
+
{ id: 'as-a', x: 8, y: 0 },
|
|
5801
|
+
{ id: 'as-b', x: 0, y: 8 }
|
|
5802
|
+
],
|
|
5803
|
+
lines: [
|
|
5804
|
+
{ id: 'as-c1', from: 'as-hub', to: 'as-a' },
|
|
5805
|
+
{ id: 'as-c2', from: 'as-hub', to: 'as-a' },
|
|
5806
|
+
{ id: 'as-i1', from: 'as-hub', to: 'as-b' },
|
|
5807
|
+
{ id: 'as-i2', from: 'as-hub', to: 'as-b' },
|
|
5808
|
+
{ id: 'as-i3', from: 'as-hub', to: 'as-a' }
|
|
5809
|
+
],
|
|
5810
|
+
channels: [{ id: 'as-ch', from: 'as-hub', to: 'as-a', lineIds: ['as-c1', 'as-c2'] }],
|
|
5811
|
+
showGrid: false
|
|
5812
|
+
})
|
|
5813
|
+
const autoSplit = autoSplitView.splitPoint('as-hub', [
|
|
5814
|
+
{ x: -1, y: 0, name: '解除 A' },
|
|
5815
|
+
{ x: 1, y: 0, name: '解除 B' }
|
|
5816
|
+
], { autoLines: 'alternate' })
|
|
5817
|
+
const autoAssignSlot = id => autoSplit.lineAssignments.find(assignment => assignment.lineIds.includes(id))?.index
|
|
5818
|
+
const autoChannelSlotA = autoAssignSlot('as-c1')
|
|
5819
|
+
const autoChannelSlotB = autoAssignSlot('as-c2')
|
|
5820
|
+
const autoSplitChannel = autoSplitView.getOptions().channels.find(channel => channel.id === 'as-ch')
|
|
5821
|
+
const autoSplitNewPoint = autoSplit.pointIds[1]
|
|
5822
|
+
check('splitPoint({ autoLines: alternate }):按通道成组轮流分配,两条同通道回线不会拆到不同节点', autoSplit.ok === true && autoSplit.autoLines === 'alternate' && autoSplit.autoAssignedLines === 5 && autoChannelSlotA !== undefined && autoChannelSlotA === autoChannelSlotB, JSON.stringify({ autoLines: autoSplit.autoLines, assigned: autoSplit.autoAssignedLines, slots: [autoChannelSlotA, autoChannelSlotB], assignments: autoSplit.lineAssignments.map(item => `${item.index}:${item.lineIds.join('+')}`) }))
|
|
5823
|
+
check('splitPoint({ autoLines: alternate }):通道端点跟随整组成员,lineAssignments 报出每一份的线路条数', autoSplit.lineAssignments.length === 2 && autoSplit.lineAssignments.reduce((sum, item) => sum + item.lineCount, 0) === 5 && String(autoSplitChannel?.from) === String(autoSplit.pointIds[autoChannelSlotA]) && String(autoSplitChannel?.to) === 'as-a' && autoSplitNewPoint !== 'as-hub', JSON.stringify({ channelFrom: autoSplitChannel?.from, newPoint: autoSplitNewPoint, counts: autoSplit.lineAssignments.map(item => item.lineCount) }))
|
|
5824
|
+
autoSplitView.destroy()
|
|
5825
|
+
autoSplitHost.remove()
|
|
5594
5826
|
lineOnlyView.destroy()
|
|
5595
5827
|
lineOnlyHost.remove()
|
|
5596
5828
|
splitView.destroy()
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
onClick: payload => push('click', payload),
|
|
43
43
|
onDblClick: payload => push('dblclick', payload),
|
|
44
44
|
onSelect: payload => push('select', payload),
|
|
45
|
-
onPointerDown:
|
|
46
|
-
onPointerUp:
|
|
47
|
-
onContextMenu:
|
|
45
|
+
onPointerDown: payload => push('down', payload),
|
|
46
|
+
onPointerUp: payload => push('up', payload),
|
|
47
|
+
onContextMenu: payload => push('contextmenu', payload),
|
|
48
48
|
onChannelDraft: payload => push('draft', payload),
|
|
49
49
|
onChannelDraftClick: payload => push('draftclick', payload)
|
|
50
50
|
})
|
|
@@ -536,7 +536,7 @@
|
|
|
536
536
|
const labelMenuEvent = new MouseEvent('contextmenu', { bubbles: true, cancelable: true, button: 2, clientX: menuRect.left + 4, clientY: menuRect.top + 4 })
|
|
537
537
|
firstMenu.dispatchEvent(labelMenuEvent)
|
|
538
538
|
const menuPayload = menuPayloads[menuPayloads.length - 1]
|
|
539
|
-
check('右键标签发 labelContextMenu:哪一条 / 内容 / 挂在谁 / 指针位置都在,系统菜单被拦下', menuPayload?.labelId === 'default' && menuPayload?.label?.content === '右键站' && menuPayload?.parent?.id === 'm1' && Math.abs(menuPayload.clientX - (menuRect.left + 4)) < 0.01 && labelMenuEvent.defaultPrevented === true, JSON.stringify({ labelId: menuPayload?.labelId, content: menuPayload?.label?.content, parent: menuPayload?.parent?.id, x: menuPayload?.clientX, prevented: labelMenuEvent.defaultPrevented }))
|
|
539
|
+
check('右键标签发 labelContextMenu:哪一条 / 内容 / 挂在谁 / 指针位置都在,系统菜单被拦下', menuPayload?.labelId === 'default' && menuPayload?.label?.content === '右键站' && menuPayload?.parent?.id === 'm1' && Math.abs(menuPayload.originalEvent.clientX - (menuRect.left + 4)) < 0.01 && menuPayload.clientX === undefined && labelMenuEvent.defaultPrevented === true, JSON.stringify({ labelId: menuPayload?.labelId, content: menuPayload?.label?.content, parent: menuPayload?.parent?.id, x: menuPayload?.originalEvent?.clientX, prevented: labelMenuEvent.defaultPrevented }))
|
|
540
540
|
check('右键载荷里的 state 与偏移读数和点选同一套', menuPayload?.state === null && Array.isArray(menuPayload?.offset) && menuPayload.offset[0] === 0 && menuPayload.offset[1] === 0, JSON.stringify({ state: menuPayload?.state, offset: menuPayload?.offset }))
|
|
541
541
|
}
|
|
542
542
|
menuView.updateOptions({ preventContextMenu: false })
|