| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- // 批次 3 合成计划断言(验收清单第 1 项):四套变体归属、尺寸层级、锚点、内层几何、着色与降饱和。
- // 直接跑 node,无需浏览器。
- import { planMarker, MASTER_GEOMETRY, MARKER_WIDTH } from '../../../src/modules/cockpit/domain/markerPlan.js'
- let pass = 0
- let fail = 0
- function eq(actual, expected, label) {
- const a = JSON.stringify(actual)
- const e = JSON.stringify(expected)
- if (a === e) { pass++; console.log(` ✓ ${label}`) } else { fail++; console.log(` ✗ ${label}\n 期望 ${e}\n 实际 ${a}`) }
- }
- console.log('① 母版归属唯一')
- eq(planMarker({ kind: 'monitoring-point', status: 'ALARM' }).master, 'solid', '报警监测点 = 实心')
- eq(planMarker({ kind: 'monitoring-point', status: 'NORMAL' }).master, 'solid', '正常监测点 = 实心')
- eq(planMarker({ kind: 'monitoring-device', status: 'ALARM' }).master, 'solid', '关联设备 = 实心')
- eq(planMarker({ kind: 'monitoring-point', status: 'EMPTY' }).master, 'hollow', 'EMPTY 点位 = 镂空')
- eq(planMarker({ kind: 'monitoring-device', status: 'NORMAL', unassociated: true }).master, 'hollow', '未关联设备 = 镂空')
- console.log('② 内层图标规则')
- eq(planMarker({ kind: 'monitoring-point', status: 'EMPTY', industry: 'GAS' }).inner.enabled, false, 'EMPTY 点位不用内层(即使有行业)')
- eq(planMarker({ kind: 'monitoring-device', status: 'NORMAL', unassociated: true, industry: 'GAS' }).inner.enabled, true, '未关联设备用行业图标')
- eq(planMarker({ kind: 'monitoring-device', status: 'NORMAL', unassociated: true, industry: 'GAS' }).inner.icon, 'gas', '未关联设备内层 = gas')
- eq(planMarker({ kind: 'monitoring-device', status: 'NORMAL', industry: 'WATER_SUPPLY' }).inner.icon, 'water', '关联设备内层 = water')
- eq(planMarker({ kind: 'monitoring-device', status: 'NORMAL', industry: 'DRAINAGE' }).inner.icon, 'drainage', '关联设备内层 = drainage')
- eq(planMarker({ kind: 'monitoring-device', status: 'NORMAL', industry: 'MANHOLE' }).inner.icon, 'manhole', '关联设备内层 = manhole')
- eq(planMarker({ kind: 'monitoring-point', status: 'NORMAL', industry: 'UNKNOWN_X' }).inner.enabled, false, '未知行业不画内层')
- console.log('③ 尺寸层级:监测点恒大于设备(2026-10-12 走查反馈放大 50%:27/21)')
- for (const status of ['ALARM', 'WARNING', 'WORK_ORDER', 'NORMAL', 'OFFLINE']) {
- const p = planMarker({ kind: 'monitoring-point', status }).size.width
- const d = planMarker({ kind: 'monitoring-device', status }).size.width
- if (p > d) { pass++; console.log(` ✓ ${status}: 点 ${p} > 设备 ${d}`) } else { fail++; console.log(` ✗ ${status}: 点 ${p} <= 设备 ${d}`) }
- }
- eq(MARKER_WIDTH.point, 27, '监测点本体宽基准 = 27(18 × 1.5)')
- eq(MARKER_WIDTH.device, 21, '设备本体宽基准 = 21(14 × 1.5)')
- eq(planMarker({ kind: 'monitoring-point', status: 'NORMAL' }).size.height, Math.round(27 * MASTER_GEOMETRY.aspect * 100) / 100, '点高 = 宽 × 母版比例')
- console.log('③b billboard 绘制尺寸含描边余量(draw)')
- const dp = planMarker({ kind: 'monitoring-point', status: 'NORMAL' })
- if (dp.draw.width > dp.size.width && dp.draw.height > dp.size.height) { pass++; console.log(` ✓ draw ${dp.draw.width}x${dp.draw.height} > 本体 ${dp.size.width}x${dp.size.height}(描边余量已含)`) } else { fail++; console.log(` ✗ draw ${dp.draw.width}x${dp.draw.height} 未含余量`) }
- if (dp.draw.pad > 0) { pass++; console.log(` ✓ pad 屏显 = ${dp.draw.pad}`) } else { fail++; console.log(' ✗ pad 缺失') }
- console.log('④ 锚点 = 尖端;标签偏移在图标上方(修重叠)')
- eq(planMarker({ kind: 'monitoring-point', status: 'NORMAL' }).anchor, { x: 0.4987, y: 1.0 }, '锚点在 bbox 底部中心(尖端)')
- const lp = planMarker({ kind: 'monitoring-point', status: 'NORMAL' })
- if (lp.labelOffsetY < 0 && Math.abs(lp.labelOffsetY) > lp.size.height) { pass++; console.log(` ✓ 标签偏移 ${lp.labelOffsetY} 在图标上沿之外(高 ${lp.size.height})`) } else { fail++; console.log(` ✗ 标签偏移 ${lp.labelOffsetY} 未越过图标底 ${lp.size.height}`) }
- const ld = planMarker({ kind: 'monitoring-device', status: 'NORMAL' })
- if (ld.labelOffsetY < 0 && Math.abs(ld.labelOffsetY) > ld.size.height) { pass++; console.log(` ✓ 设备标签偏移 ${ld.labelOffsetY} 在图标上沿之外(高 ${ld.size.height})`) } else { fail++; console.log(` ✗ 设备标签偏移 ${ld.labelOffsetY} 未越过图标底 ${ld.size.height}`) }
- console.log('⑤ 内层几何:80% 直径 + 帽心对齐(走查反馈 60% 看不清 → 两连放到 80%)')
- eq(planMarker({ kind: 'monitoring-device', status: 'NORMAL', industry: 'GAS' }).inner.diameterRatio, 0.8, '内层直径 = 80%')
- eq(planMarker({ kind: 'monitoring-device', status: 'NORMAL', industry: 'GAS' }).inner.center, MASTER_GEOMETRY.capCenter, '内层圆心 = 帽心')
- console.log('⑥ 着色与降饱和')
- eq(planMarker({ kind: 'monitoring-point', status: 'ALARM' }).tint, 'lv1', '报警 tint = lv1(状态推导)')
- eq(planMarker({ kind: 'monitoring-point', status: 'WARNING' }).tint, 'lv2', '预警 tint = lv2')
- eq(planMarker({ kind: 'monitoring-point', status: 'WORK_ORDER' }).tint, 'lv3', '工单 tint = lv3')
- eq(planMarker({ kind: 'monitoring-point', status: 'NORMAL' }).tint, 'lv4', '正常 tint = lv4')
- eq(planMarker({ kind: 'monitoring-point', status: 'OFFLINE' }).tint, 'neutral', '离线 tint = neutral')
- eq(planMarker({ kind: 'monitoring-point', status: 'EMPTY' }).tint, 'neutral', 'EMPTY tint = neutral')
- eq(planMarker({ kind: 'monitoring-point', status: 'MAINTENANCE' }).tint, 'neutral', '未知状态 tint = neutral(不猜)')
- eq(planMarker({ kind: 'monitoring-point', status: 'NORMAL', tone: 'lv1' }).tint, 'lv1', '调用方可覆盖 tone')
- eq(planMarker({ kind: 'monitoring-device', status: 'NORMAL', unassociated: true }).desaturate, true, '未关联设备 = 降饱和')
- eq(planMarker({ kind: 'monitoring-device', status: 'ALARM' }).desaturate, false, '关联设备不降饱和')
- eq(planMarker({ kind: 'monitoring-point', status: 'EMPTY' }).desaturate, false, 'EMPTY 点位不降饱和')
- console.log(`\n合成计划断言:${pass} 过 / ${fail} 败`)
- if (fail) process.exitCode = 1
|