gisMapCanvas.test.mjs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import test from 'node:test'
  2. import assert from 'node:assert/strict'
  3. import { readFile } from 'node:fs/promises'
  4. import { getMapClusterIcon, getMonitoringPointColor, getMonitoringPointIcon, getMonitoringPointLabel, getMonitoringPointStatus, getMonitoringPointTagType } from '../src/utils/gisMapColors.js'
  5. import { getFacilityStatusIcon, getFacilityStatusMeta } from '../src/utils/gisMapColors.js'
  6. test('shared gis map canvas converts WGS84 coordinates before BMapGL rendering', async () => {
  7. const source = await readFile('src/components/GisMapCanvas.vue', 'utf8')
  8. assert.match(source, /import \{ convertCoord \} from '@\/utils\/coordTransform'/u)
  9. assert.match(source, /const \[lng, lat\] = convertCoord\(point\.lng, point\.lat\)/u)
  10. assert.match(source, /new BMapGL\.Point\(lng, lat\)/u)
  11. assert.match(source, /mapInstance\.setViewport\(bmapPoints/u)
  12. assert.doesNotMatch(source, /new BMapGL\.Point\(point\.lng, point\.lat\)/u)
  13. })
  14. test('shared gis map canvas renders pipelines without endpoint markers', async () => {
  15. const source = await readFile('src/components/GisMapCanvas.vue', 'utf8')
  16. const addLine = source.match(/function addLine\(BMapGL, line\) \{[\s\S]*?\n\}/u)?.[0] || ''
  17. assert.match(addLine, /new BMapGL\.Polyline\(bmapPoints/u)
  18. assert.match(addLine, /emit\('line-click', line\)/u)
  19. assert.doesNotMatch(addLine, /new BMapGL\.Marker/u)
  20. assert.doesNotMatch(addLine, /new BMapGL\.Label/u)
  21. assert.doesNotMatch(addLine, /起点/u)
  22. assert.doesNotMatch(addLine, /终点/u)
  23. })
  24. test('shared gis map canvas renders contextual clusters with colorful mixed icons', async () => {
  25. const source = await readFile('src/components/GisMapCanvas.vue', 'utf8')
  26. const addClusterMarker = source.match(/function addClusterMarker\(BMapGL, cluster\) \{[\s\S]*?\n\}/u)?.[0] || ''
  27. assert.match(source, /import \{ mergeMapPoints \} from '@\/utils\/gisMapClustering'/u)
  28. assert.match(source, /clusterRadius: \{ type: Number, default: 48 \}/u)
  29. assert.match(source, /clusterLabel: \{ type: String, default: '点位集合' \}/u)
  30. assert.match(source, /mergeMapPoints\(renderPoints, projectMapPoint, props\.clusterRadius\)/u)
  31. assert.match(source, /getMapClusterIcon\(cluster\.points\)/u)
  32. assert.match(source, /escapeHtml\(props\.clusterLabel\)/u)
  33. assert.match(source, /focusCluster\(cluster\)/u)
  34. assert.match(source, /emit\('cluster-click', cluster\)/u)
  35. assert.match(source, /function isClusterUnexpandable\(cluster\)/u)
  36. assert.match(addClusterMarker, /if \(isClusterUnexpandable\(cluster\)\) emit\('cluster-click', cluster\)/u)
  37. assert.doesNotMatch(addClusterMarker, /props\.showMarkerName/u)
  38. assert.match(source, /mapInstance\.addEventListener\('moveend', renderScene\)/u)
  39. assert.match(source, /mapInstance\.addEventListener\('zoomend', renderScene\)/u)
  40. })
  41. test('shared gis map canvas renders every point as an official icon with a label above it', async () => {
  42. const source = await readFile('src/components/GisMapCanvas.vue', 'utf8')
  43. assert.match(source, /function escapeHtml\(value\)/u)
  44. assert.match(source, /let bmapLoadTimer = null/u)
  45. assert.match(source, /let disposed = false/u)
  46. assert.match(source, /if \(disposed\) \{[\s\S]*?clearInterval\(bmapLoadTimer\)/u)
  47. assert.match(source, /if \(disposed \|\| !mapContainer\.value\) return/u)
  48. assert.match(source, /onBeforeUnmount\(\(\) => \{[\s\S]*?disposed = true/u)
  49. assert.match(source, /clearInterval\(bmapLoadTimer\)/u)
  50. assert.match(source, /markerSize: \{ type: Number, default: 28 \}/u)
  51. assert.match(source, /const iconUrl = point\.iconUrl \|\| getMonitoringPointIcon\(point\)/u)
  52. assert.match(source, /new BMapGL\.Icon\(iconUrl, new BMapGL\.Size\(size, size\), \{/u)
  53. assert.match(source, /anchor: new BMapGL\.Size\(size \/ 2, size\)/u)
  54. assert.match(source, /const marker = new BMapGL\.Marker\(position, \{/u)
  55. assert.match(source, /new BMapGL\.Label\(`<div class="gis-marker-label-text">/u)
  56. assert.match(source, /offset: new BMapGL\.Size\(-28, -props\.markerSize - 18\)/u)
  57. assert.match(source, /width: 56px/u)
  58. assert.match(source, /overflow-wrap: anywhere/u)
  59. assert.doesNotMatch(source, /white-space: nowrap/u)
  60. assert.doesNotMatch(source, /<img class="marker-icon"/u)
  61. assert.doesNotMatch(source, /class="marker-wrap"/u)
  62. assert.ok(source.includes("emit('point-click', point)"))
  63. })
  64. test('facility point colors follow the facility status semantics shared with monitoring devices', () => {
  65. // 供水设施一张图与首页统一:绿-正常、红-报警/异常、蓝-工单/检修、黄-预警/欠费
  66. assert.deepEqual(getFacilityStatusMeta('source', 0), { key: 'normal', text: '正常' })
  67. assert.deepEqual(getFacilityStatusMeta('source', 1), { key: 'alarm', text: '异常' })
  68. assert.deepEqual(getFacilityStatusMeta('plant', 1), { key: 'alarm', text: '停产' })
  69. assert.deepEqual(getFacilityStatusMeta('pumpStation', 1), { key: 'alarm', text: '故障停运' })
  70. assert.deepEqual(getFacilityStatusMeta('pumpStation', 2), { key: 'workOrder', text: '检修中' })
  71. assert.deepEqual(getFacilityStatusMeta('user', 1), { key: 'warning', text: '欠费' })
  72. assert.deepEqual(getFacilityStatusMeta('user', 2), { key: 'alarm', text: '停用' })
  73. // 未维护状态的设施按正常处理,不臆造异常
  74. assert.deepEqual(getFacilityStatusMeta('source', null), { key: 'normal', text: '正常' })
  75. assert.deepEqual(getFacilityStatusMeta('plant', undefined), { key: 'normal', text: '正常' })
  76. assert.deepEqual(getFacilityStatusMeta('source', 9), { key: 'normal', text: '正常' })
  77. assert.deepEqual(getFacilityStatusMeta('unknown', 1), { key: 'normal', text: '正常' })
  78. })
  79. test('facility gis page colors points by facility status instead of facility type', async () => {
  80. const source = await readFile('src/views/subSystem/waterSupply/facility/gis.vue', 'utf8')
  81. assert.match(source, /getFacilityStatusMeta/u)
  82. assert.match(source, /getFacilityStatusIcon/u)
  83. assert.doesNotMatch(source, /iconUrl: getFacilityPointIcon\(point\.type\)/u)
  84. assert.match(source, /设施状态图例/u)
  85. })
  86. test('pipelines keep no point icon while facilities map status to the shared palette', () => {
  87. // 管网保持现状:只构造管线,不添加图标
  88. assert.equal(getFacilityStatusIcon('pipe', 0), null)
  89. assert.match(getFacilityStatusIcon('source', 0), /T_MarkPoint_Green\.png/u)
  90. assert.match(getFacilityStatusIcon('source', 1), /T_MarkPoint_Red\.png/u)
  91. assert.match(getFacilityStatusIcon('pumpStation', 2), /T_MarkPoint_Blue\.png/u)
  92. assert.match(getFacilityStatusIcon('user', 1), /T_MarkPoint_Yellow\.png/u)
  93. })
  94. test('cluster icons reuse the single member icon or fall back to the colorful marker', () => {
  95. assert.match(getMapClusterIcon([{ alarmStatus: 1 }, { alarmStatus: 1 }]), /T_MarkPoint_Red\.png/u)
  96. assert.match(getMapClusterIcon([{ onlineStatus: 0 }, { onlineStatus: 0 }]), /T_MarkPoint_Grey\.png/u)
  97. assert.match(getMapClusterIcon([{ alarmStatus: 1 }, { onlineStatus: 0 }]), /T_MarkPoint_Colorful\.png/u)
  98. })
  99. test('monitoring point colors follow the documented status semantics', () => {
  100. assert.equal(getMonitoringPointStatus({ relatedOrderNo: 'WO-1' }), 'workOrder')
  101. assert.equal(getMonitoringPointStatus({ relatedWorkOrderNo: 'WO-2' }), 'workOrder')
  102. assert.equal(getMonitoringPointStatus({ orderNo: 'WO-3', orderStatus: 5 }), 'normal')
  103. assert.equal(getMonitoringPointStatus({ orderNo: 'WO-4', orderStatus: 7, deviceAlarmStatus: 1 }), 'alarm')
  104. assert.equal(getMonitoringPointStatus({ alarmStatus: 1 }), 'alarm')
  105. assert.equal(getMonitoringPointStatus({ currentStatus: 3 }), 'warning')
  106. assert.equal(getMonitoringPointStatus({ onlineStatus: 0 }), 'offline')
  107. assert.equal(getMonitoringPointStatus({}), 'normal')
  108. assert.equal(getMonitoringPointColor({ relatedOrderNo: 'WO-1' }), '#3498db')
  109. assert.equal(getMonitoringPointColor({ alarmStatus: 1 }), '#e74c3c')
  110. assert.equal(getMonitoringPointColor({ currentStatus: 3 }), '#f1c40f')
  111. assert.equal(getMonitoringPointColor({ onlineStatus: 0 }), '#95a5a6')
  112. assert.equal(getMonitoringPointColor({}), '#2ecc71')
  113. assert.match(getMonitoringPointIcon({ relatedOrderNo: 'WO-1' }), /T_MarkPoint_Blue\.png/u)
  114. assert.match(getMonitoringPointIcon({ alarmStatus: 1 }), /T_MarkPoint_Red\.png/u)
  115. assert.match(getMonitoringPointIcon({ currentStatus: 3 }), /T_MarkPoint_Yellow\.png/u)
  116. assert.match(getMonitoringPointIcon({ onlineStatus: 0 }), /T_MarkPoint_Grey\.png/u)
  117. assert.match(getMonitoringPointIcon({}), /T_MarkPoint_Green\.png/u)
  118. assert.equal(getMonitoringPointLabel({ currentStatus: 3 }), '预警')
  119. assert.equal(getMonitoringPointLabel({ relatedWorkOrderNo: 'WO-2' }), '关联工单')
  120. assert.equal(getMonitoringPointTagType({ relatedWorkOrderNo: 'WO-2' }), 'primary')
  121. assert.equal(getMonitoringPointTagType({ onlineStatus: 0 }), 'info')
  122. })
  123. test('an explicit status key wins over inferred monitoring point fields', () => {
  124. const offlineAlarmRecord = { statusKey: 'offline', alarmStatus: 1, onlineStatus: 0 }
  125. assert.equal(getMonitoringPointStatus(offlineAlarmRecord), 'offline')
  126. assert.equal(getMonitoringPointColor(offlineAlarmRecord), '#95a5a6')
  127. assert.match(getMonitoringPointIcon(offlineAlarmRecord), /T_MarkPoint_Grey\.png/u)
  128. const handledAlarm = { statusKey: 'normal', alarmStatus: 1 }
  129. assert.equal(getMonitoringPointStatus(handledAlarm), 'normal')
  130. assert.match(getMonitoringPointIcon(handledAlarm), /T_MarkPoint_Green\.png/u)
  131. assert.equal(getMonitoringPointStatus({ statusKey: '未知状态', alarmStatus: 1 }), 'alarm')
  132. })
  133. test('water supply GIS pages share the common canvas component', async () => {
  134. const deviceSource = await readFile('src/views/subSystem/waterSupply/components/WaterDeviceGisMap.vue', 'utf8')
  135. const facilitySource = await readFile('src/views/subSystem/waterSupply/facility/gis.vue', 'utf8')
  136. assert.match(deviceSource, /<GisMapCanvas/u)
  137. assert.match(deviceSource, /cluster-label="设备集合"/u)
  138. assert.match(deviceSource, /value="workOrder">关联工单/u)
  139. assert.match(deviceSource, /legend-dot warning/u)
  140. assert.match(deviceSource, /getMonitoringPointTagType/u)
  141. assert.match(deviceSource, /:points="mapPoints"/u)
  142. assert.match(deviceSource, /@point-click="openDetail\(\$event\.equipmentId\)"/u)
  143. assert.match(facilitySource, /<GisMapCanvas/u)
  144. assert.match(facilitySource, /:points="mapPoints"/u)
  145. assert.match(facilitySource, /:lines="mapLines"/u)
  146. assert.match(facilitySource, /getFacilityStatusIcon\(point\.type, point\.status\)/u)
  147. assert.match(facilitySource, /cluster-label="设施集合"/u)
  148. assert.match(facilitySource, /@point-click="locateFeature"/u)
  149. const alarmSource = await readFile('src/views/subSystem/waterSupply/alarm/alarmGIS.vue', 'utf8')
  150. assert.match(alarmSource, /<GisMapCanvas/u)
  151. assert.match(alarmSource, /@cluster-click="cluster = \$event.points \|\| \[\]"/u)
  152. assert.match(alarmSource, /levelStyle\(device.alarmLevel\)/u)
  153. assert.doesNotMatch(alarmSource, /color: point\.relatedOrderNo \?/u)
  154. assert.match(alarmSource, /:points="points"/u)
  155. assert.match(alarmSource, /@point-click="choose"/u)
  156. })