import assert from 'node:assert/strict' import { test } from 'node:test' import { planMarker } from '../src/modules/cockpit/domain/markerPlan.js' import { mountMarkerOverlay, syncMarkerOverlay, unmountMarkerOverlay } from '../src/modules/cockpit/services/markerOverlay.js' import { markerTestDocument } from './helpers/marker-dom.mjs' const tones = { lv1: '#ff3b52', lv2: '#ffb020', lv3: '#01abea', lv4: '#27d17a', neutral: '#5680b0' } const facility = (status, id = '1') => ({ key: `facility-point|WATER_PLANT|${id}`, kind: 'facility-point', code: 'WP001', name: '水厂', type: 'WATER_PLANT', entityId: id, detailCategory: 'WATER_PLANT', clickable: true, status, longitude: 110.38, latitude: 28.43, }) const planOf = (row) => planMarker({ kind: row.kind, status: row.status, facilityType: row.type, industry: row.industry, tone: row.tone }) function mount(t) { const previous = globalThis.document const document = markerTestDocument() globalThis.document = document assert.equal(mountMarkerOverlay(document.host), true) t.after(() => { unmountMarkerOverlay() if (previous === undefined) delete globalThis.document else globalThis.document = previous }) return { document, sync: (rows, effectOf, extra = {}) => syncMarkerOverlay({ facilities: rows, facilityPlanOf: planOf, planOf, tones, facilityEffectOf: effectOf, projectToWindow: () => ({ x: 100, y: 200 }), ...extra, }), node: (row) => document.host.nodes().find((node) => node.dataset.markerOverlayKey === row.key), } } test('正常设施不能被错误或过期的门控键挂上报警环', (t) => { const scene = mount(t) const row = { ...facility('0'), tone: 'lv1' } scene.sync([row], () => 'pulse') assert.equal(scene.node(row).dataset.markerRing, 'no') assert.equal(scene.node(row).dataset.markerEffect, undefined) }) test('同一设施在超限降级与恢复时更新已有环的大小和透明度', (t) => { const scene = mount(t) const row = facility('2') scene.sync([row], () => 'pulse') assert.equal(scene.node(row).dataset.markerEffectConverged, 'no') scene.sync([row], () => 'pulse', { converge: { peak: 0.6, alpha: 0.5 } }) const degraded = scene.node(row) assert.equal(degraded.dataset.markerEffectConverged, 'yes') assert.equal(degraded.dataset.markerEffectAlpha, '0.5') const ringHost = degraded.children.find((node) => node.className.includes('marker-overlay-fx--')) assert.equal(ringHost.style.opacity, '0.5') assert.equal(ringHost.style.transform, 'scale(0.6)') scene.sync([row], () => 'pulse', { converge: null }) assert.equal(scene.node(row).dataset.markerEffectConverged, 'no') assert.equal(scene.node(row).dataset.markerEffectAlpha, '1') }) test('设施报警、预警、维修与同态设备的实际环节点和动画配置一致', (t) => { const scene = mount(t) for (const [status, deviceStatus, effect, layers, period, color, glow] of [ ['1', 'WORK_ORDER', 'spin', 1, '18000ms', '#01abea', 0], ['2', 'ALARM', 'pulse', 4, '1800ms', '#ff3b52', 1], ['WARNING', 'WARNING', 'blink', 3, '1400ms', '#ffb020', 0], ]) { const row = facility(status) scene.sync([row], () => effect, { devices: [{ code: 'd1', status: deviceStatus, industry: 'WATER_SUPPLY', x: 100, y: 200 }], deviceEffectOf: () => effect, }) const node = scene.node(row) const device = scene.document.host.nodes().find((item) => item.dataset.markerOverlayKey === 'device|d1') assert.equal(node.dataset.markerTone, color) for (const key of ['markerEffect', 'markerEffectLayers', 'markerEffectAlpha', 'markerEffectConverged', 'markerDrawWidth']) { assert.equal(node.dataset[key], device.dataset[key]) } const rings = node.children[0].children.filter((item) => item.className === 'marker-overlay-fx-ring') assert.equal(rings.length, layers) assert.equal(rings[0].style.animationDuration, period) assert.equal(rings[0].style.animationName, effect === 'spin' ? 'markerFxSpin' : `markerFxRing--${effect}--0`) assert.equal(node.children[0].children.filter((item) => item.className === 'marker-overlay-fx-glow').length, glow) } }) test('特效开关与设施状态切换不遗留旧环,编码重复的设施按主键独立更新', (t) => { const scene = mount(t) const left = facility('1', 'A') const right = facility('2', 'B') const effects = (row) => row.key === left.key ? 'spin' : 'pulse' scene.sync([left, right], effects) assert.equal(scene.node(left).dataset.markerEffect, 'spin') assert.equal(scene.node(right).dataset.markerEffect, 'pulse') scene.sync([left, right], () => '') assert.equal(scene.node(left).dataset.markerRing, 'no') assert.equal(scene.node(right).dataset.markerEffect, undefined) scene.sync([left, right], effects) assert.equal(scene.node(left).dataset.markerEffect, 'spin') scene.sync([{ ...left, status: '0' }, right], effects) assert.equal(scene.node(left).dataset.markerRing, 'no') assert.equal(scene.node(right).dataset.markerRing, 'yes') scene.sync([], effects) assert.equal(scene.node(left).style.display, 'none') assert.equal(scene.node(right).style.display, 'none') }) test('跨图层降级与恢复同时更新设备和监测点已有节点', (t) => { const scene = mount(t) const extra = { devices: [{ code: 'd2', status: 'ALARM', x: 100, y: 200 }], deviceEffectOf: () => 'pulse', markers: [{ kind: 'monitoring-point', code: 'MP1', status: 'ALARM', tone: 'lv1', longitude: 110.38, latitude: 28.43 }], effectOf: () => 'pulse', } scene.sync([], () => '', extra) scene.sync([], () => '', { ...extra, converge: { peak: 0.6, alpha: 0.5 } }) for (const key of ['device|d2', 'monitoring-point|MP1']) { const node = scene.document.host.nodes().find((item) => item.dataset.markerOverlayKey === key) assert.equal(node.dataset.markerEffectConverged, 'yes') assert.equal(node.dataset.markerEffectAlpha, '0.5') } scene.sync([], () => '', extra) for (const key of ['device|d2', 'monitoring-point|MP1']) { const node = scene.document.host.nodes().find((item) => item.dataset.markerOverlayKey === key) assert.equal(node.dataset.markerEffectConverged, 'no') assert.equal(node.dataset.markerEffectAlpha, '1') } })