| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- import assert from 'node:assert/strict'
- import { normalizeEntityDetail } from '../src/modules/cockpit/domain/entityDetail.js'
- const fieldOf = (detail, label) => detail.sections.flatMap((s) => s.fields).find((f) => f.label === label)
- const summaryOf = (detail, label) => detail.summary.find((s) => s.label === label)
- const NUMERIC = /^\d+(\.\d+)?$/ // 纯数字=没带单位
- /** 数值型读数必须带单位:值形如 "10 万m³/d",不能是裸数字。 */
- function assertUnit(label, value, expectedUnit) {
- assert.ok(value && value.includes(expectedUnit), label + ' 应有单位 ' + expectedUnit + ',实际: ' + value)
- assert.ok(!NUMERIC.test(value), label + ' 不得是裸数字: ' + value)
- }
- // —— 管网:长度/管径带单位,摘要与明细一致 ——
- const pipe = normalizeEntityDetail({ kind: 'facility', id: 'n1', category: 'PIPE_NETWORK' }, {
- category: 'PIPE_NETWORK', id: 'n1', name: '污水干管', status: '0',
- attributes: { networkType: '1', networkLevel: '0', lengthMeters: 1200, diameterMillimeters: 300, material: 'HDPE' },
- })
- assertUnit('长度(明细)', fieldOf(pipe, '长度').value, '米')
- assertUnit('管径(明细)', fieldOf(pipe, '管径').value, '毫米')
- assertUnit('长度(摘要)', summaryOf(pipe, '长度').value, '米')
- assertUnit('管径(摘要)', summaryOf(pipe, '管径').value, '毫米')
- assert.equal(fieldOf(pipe, '材质').value, 'HDPE')
- // —— 水厂 ——
- const plant = normalizeEntityDetail({ kind: 'facility', id: '1', category: 'WATER_PLANT' }, {
- category: 'WATER_PLANT', id: '1', name: '一水厂', status: '0',
- attributes: { designCapacity: 10, currentCapacity: 8.5, treatmentProcess: '过滤' },
- })
- assertUnit('设计能力(明细)', fieldOf(plant, '设计能力').value, '万m³/d')
- assertUnit('当前能力(明细)', fieldOf(plant, '当前能力').value, '万m³/d')
- assertUnit('当前能力(摘要)', summaryOf(plant, '当前能力').value, '万m³/d')
- // —— 泵站:设计流量是 m³/h ——
- const station = normalizeEntityDetail({ kind: 'facility', id: '2', category: 'PUMP_STATION' }, {
- category: 'PUMP_STATION', id: '2', name: '一号泵站', status: '0',
- attributes: { pumpCount: 3, designFlow: 1200, designHead: 25, powerCapacity: 90 },
- })
- assertUnit('水泵数量', fieldOf(station, '水泵数量').value, '台')
- assertUnit('设计流量(泵站)', fieldOf(station, '设计流量').value, 'm³/h')
- assertUnit('设计扬程', fieldOf(station, '设计扬程').value, 'm')
- assertUnit('装机功率', fieldOf(station, '装机功率').value, 'kW')
- assertUnit('设计流量(摘要)', summaryOf(station, '设计流量').value, 'm³/h')
- // —— 排水工程设施:设计流量是 m³/s(与泵站同名字段不同量纲) ——
- const engineering = normalizeEntityDetail({ kind: 'facility', id: 'f1', category: 'ENGINEERING_FACILITY' }, {
- category: 'ENGINEERING_FACILITY', id: 'f1', name: '东门闸', status: '0',
- attributes: { facilityType: '0', designFlow: 3.5, designHead: 4, storageCapacity: 1000 },
- })
- assertUnit('设计流量(工程设施)', fieldOf(engineering, '设计流量').value, 'm³/s')
- assertUnit('设计扬程(工程设施)', fieldOf(engineering, '设计扬程').value, 'm')
- assertUnit('调蓄容积', fieldOf(engineering, '调蓄容积').value, 'm³')
- // —— 应急资源 ——
- const resource = normalizeEntityDetail({ kind: 'emergency', id: 'e1', category: 'EMERGENCY_RESOURCE' }, {
- category: 'EMERGENCY_RESOURCE', id: 'e1', name: '应急水泵', attributes: { assetValue: 12000, useLifeYears: 8 },
- })
- assertUnit('资产价值', fieldOf(resource, '资产价值').value, '元')
- assertUnit('预计使用年限', fieldOf(resource, '预计使用年限').value, '年')
- // —— 防护目标 ——
- const target = normalizeEntityDetail({ kind: 'emergency', id: 'r1', category: 'PROTECTION_TARGET' }, {
- category: 'PROTECTION_TARGET', id: 'r1', name: '学校', attributes: { riskScore: 88 },
- })
- assertUnit('风险分值', fieldOf(target, '风险分值').value, '分')
- assertUnit('风险分值(摘要)', summaryOf(target, '风险分值').value, '分')
- // —— 预警/报警读数:实际值、阈值、超出幅度都带单位 ——
- const warning = normalizeEntityDetail({ kind: 'event', id: 'W1', family: 'WARNING' }, {
- warningNo: 'W1', warningName: '电导率预警', status: 'PENDING', warningLevel: 2,
- value: 454, unit: 'μS/cm', thresholdMinValue: 100, thresholdMaxValue: 5000, deviationRatio: 12.5,
- })
- assertUnit('实际值', fieldOf(warning, '实际值').value, 'μS/cm')
- assertUnit('阈值', fieldOf(warning, '阈值').value, 'μS/cm')
- assertUnit('超出幅度', fieldOf(warning, '超出幅度').value, '%')
- // —— 命名规范:标签一律中文且不带括注 ——
- for (const detail of [pipe, plant, station, engineering, resource, target, warning]) {
- for (const section of detail.sections) {
- for (const item of section.fields) {
- assert.ok(/[\u4e00-\u9fff]/.test(item.label), '字段名必须中文: ' + item.label)
- assert.ok(!item.label.includes('('), '字段名不得带括注: ' + item.label)
- }
- }
- }
- console.log('t65-metric-units: 40/40')
|