t37-area-limits.log 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. node:internal/modules/run_main:107
  2. triggerUncaughtException(
  3. ^
  4. AssertionError [ERR_ASSERTION]: 外壳要有区状态读数
  5. at file:///E:/City-Lifeline-Cockpit-TvT/.scratch/cockpit-shell-panel-layout/verify/t37-area-limits.mjs:466:8
  6. at ModuleJob.run (node:internal/modules/esm/module_job:561:25)
  7. at async node:internal/modules/esm/loader:647:26
  8. at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5) {
  9. generatedMessage: false,
  10. code: 'ERR_ASSERTION',
  11. actual: '<!--\r\n' +
  12. ' 驾驶舱外壳:唯一 /cockpit 路由的全部内容。\r\n' +
  13. '\r\n' +
  14. ' 骨架与视觉参考《驾驶舱原型图-美化版》(切角面板 / 青色辉光 / 深空蓝底 / 全息地图壳),\r\n' +
  15. ' 但不锁 16:9:页面铺满视口,**中央一张图作为整个主体的背景铺满**,左右两栏浮在图上。\r\n' +
  16. '\r\n' +
  17. ' 语义按 ADR 0003 / 0007:四个一级模式、模式内 4 个二级面板同屏展示、无子视图切换。\r\n' +
  18. ' 一级模式只通过 uiStore.mode 切换,不新增路由、不重建外壳与地图节点。\r\n' +
  19. ' 范围与行业是全局筛选(filterStore),切换一级模式不得重置它们(验收第 ⑦ 条)。\r\n' +
  20. '-->\r\n' +
  21. '<template>\r\n' +
  22. ' <div class="cockpit-shell">\r\n' +
  23. ' <div class="cockpit-shell__atmosphere" aria-hidden="true"></div>\r\n' +
  24. '\r\n' +
  25. ' <header class="cockpit-shell__topbar">\r\n' +
  26. ' <div class="cockpit-shell__topbar-bg" aria-hidden="true"></div>\r\n' +
  27. ' <span class="cockpit-shell__wing is-left" aria-hidden="true"></span>\r\n' +
  28. ' <span class="cockpit-shell__wing is-right" aria-hidden="true"></span>\r\n' +
  29. '\r\n' +
  30. ' <div class="cockpit-shell__brand">\r\n' +
  31. ' <span class="cockpit-shell__mark" aria-hidden="true">\r\n' +
  32. ' <CockpitIcon name="brand" size="100%" />\r\n' +
  33. ' </span>\r\n' +
  34. ' <span class="cockpit-shell__brand-text">\r\n' +
  35. ' <strong>城市生命线驾驶舱系统</strong>\r\n' +
  36. ' <em>沅陵县 · 只读展示</em>\r\n' +
  37. ' </span>\r\n' +
  38. ' </div>\r\n' +
  39. '\r\n' +
  40. ' <nav class="cockpit-shell__modes" aria-label="一级模式">\r\n' +
  41. ' <button\r\n' +
  42. ' v-for="item in MODES"\r\n' +
  43. ' :key="item"\r\n' +
  44. ' type="button"\r\n' +
  45. ' class="cockpit-shell__mode"\r\n' +
  46. ` :class="{ 'is-active': item === mode }"\r\n` +
  47. ' :aria-pressed="item === mode"\r\n' +
  48. ' @click="uiStore.setMode(item)"\r\n' +
  49. ' >\r\n' +
  50. ' {{ modeLabel(item) }}\r\n' +
  51. ' </button>\r\n' +
  52. ' </nav>\r\n' +
  53. '\r\n' +
  54. ' <div class="cockpit-shell__top-meta">\r\n' +
  55. ' <!--\r\n' +
  56. ' 票 30:快速归位(回到目标城市预设视角)。\r\n' +
  57. ' 票 37:区内/区外文案不同 —— 区内是「归位」(已进区,只是回该视角);\r\n' +
  58. ' 区外是「归位/进入」(点它就进区并锁定,ADR 0009 R2-5)。\r\n' +
  59. ' -->\r\n' +
  60. ' <button\r\n' +
  61. ' type="button"\r\n' +
  62. ' class="cockpit-shell__chip cockpit-shell__home"\r\n' +
  63. ` :class="{ 'is-active': atHomeView }"\r\n` +
  64. ` :data-home-at="atHomeView ? 'yes' : 'no'"\r\n` +
  65. ` :data-area-locked="areaLocked ? 'yes' : 'no'"\r\n` +
  66. ' :title="homeTitle"\r\n' +
  67. ' :aria-label="areaBar.homeLabel"\r\n' +
  68. ' @click="returnHome()"\r\n' +
  69. ' >\r\n' +
  70. ' {{ areaBar.homeLabel }}\r\n' +
  71. ' </button>\r\n' +
  72. ' <!-- 票 37:只有区内才有「返回全球」(区外它没有意义,不占位置)。 -->\r\n' +
  73. ' <button\r\n' +
  74. ' v-if="areaBar.returnGlobal"\r\n' +
  75. ' type="button"\r\n' +
  76. ' class="cockpit-shell__chip cockpit-shell__return-global"\r\n' +
  77. ' data-return-global\r\n' +
  78. ' :title="`解除主场景区限位,回到自由全球视角(区内最远 ${Math.round(areaLimits.max)} m)`"\r\n' +
  79. ' @click="returnToGlobal()"\r\n' +
  80. ' >\r\n' +
  81. ' 返回全球\r\n' +
  82. ' </button>\r\n' +
  83. ' <!-- 票 04:配置三态 + 数据源,顶栏可演示;data-* 供走查断言。\r\n' +
  84. ' 票 32:这是开发期的诊断读数,生产形态不占顶栏(状态退到底部小字)。 -->\r\n' +
  85. ' <span\r\n' +
  86. ' v-if="configLoaded && uiDebug"\r\n' +
  87. ' class="cockpit-shell__config"\r\n' +
  88. ' :data-config-state="configView.state"\r\n' +
  89. ' :data-data-source="configView.dataSource"\r\n' +
  90. ' :data-source="configState.source"\r\n' +
  91. ' >\r\n' +
  92. ' <StatusTag :tone="configView.tone" :label="configView.label" />\r\n' +
  93. ' </span>\r\n' +
  94. ' <span class="cockpit-shell__chip">只读视图</span>\r\n' +
  95. ' <span class="cockpit-shell__clock">{{ clockText }}</span>\r\n' +
  96. ' <p v-if="uiDebug" class="cockpit-shell__meta">当前模式 {{ mode }}</p>\r\n' +
  97. ' </div>\r\n' +
  98. ' </header>\r\n' +
  99. '\r\n' +
  100. ' <!-- 全局筛选:作用于整个驾驶舱,切换一级模式不重置 -->\r\n' +
  101. ' <div class="cockpit-shell__scope">\r\n' +
  102. ' <div class="cockpit-shell__scope-left">\r\n' +
  103. ' <span class="cockpit-shell__scope-label">当前范围</span>\r\n' +
  104. ' <div class="cockpit-shell__chips">\r\n' +
  105. ' <button\r\n' +
  106. ' v-for="item in SCOPES"\r\n' +
  107. ' :key="item.key"\r\n' +
  108. ' type="button"\r\n' +
  109. ' class="cockpit-shell__chip cockpit-shell__scope-btn"\r\n' +
  110. ` :class="{ 'is-active': item.key === scope }"\r\n` +
  111. ' :aria-pressed="item.key === scope"\r\n' +
  112. ' :data-scope="item.key"\r\n' +
  113. ' @click="filterStore.setScope(item.key)"\r\n' +
  114. ' >\r\n' +
  115. ' {{ item.label }}\r\n' +
  116. ' </button>\r\n' +
  117. ' </div>\r\n' +
  118. '\r\n' +
  119. ' <span class="cockpit-shell__divider" aria-hidden="true"></span>\r\n' +
  120. '\r\n' +
  121. ' <span class="cockpit-shell__scope-label">行业</span>\r\n' +
  122. ' <div class="cockpit-shell__chips">\r\n' +
  123. ' <button\r\n' +
  124. ' v-for="item in INDUSTRIES"\r\n' +
  125. ' :key="item.key"\r\n' +
  126. ' type="button"\r\n' +
  127. ' class="cockpit-shell__chip cockpit-shell__industry-btn"\r\n' +
  128. ` :class="{ 'is-active': item.key === industry }"\r\n` +
  129. ' :aria-pressed="item.key === industry"\r\n' +
  130. ' :data-industry="item.key"\r\n' +
  131. ' @click="filterStore.setIndustry(item.key)"\r\n' +
  132. ' >\r\n' +
  133. ' {{ item.label }}\r\n' +
  134. ' </button>\r\n' +
  135. ' </div>\r\n' +
  136. '\r\n' +
  137. ' <span class="cockpit-shell__divider" aria-hidden="true"></span>\r\n' +
  138. '\r\n' +
  139. ' <!--\r\n' +
  140. ' 票 21:地面/管线视图(决策地图票 05 定的「全局视图条件」)。\r\n' +
  141. ' 它是全局条件,与范围/行业同级 —— 切换一级模式不重置它。\r\n' +
  142. ' -->\r\n' +
  143. ' <span class="cockpit-shell__scope-label">视图</span>\r\n' +
  144. ' <div class="cockpit-shell__chips">\r\n' +
  145. ' <button\r\n' +
  146. ' v-for="item in VIEW_MODE_OPTIONS"\r\n' +
  147. ' :key="item.key"\r\n' +
  148. ' type="button"\r\n' +
  149. ' class="cockpit-shell__chip cockpit-shell__view-btn"\r\n' +
  150. ` :class="{ 'is-active': item.key === viewMode }"\r\n` +
  151. ' :aria-pressed="item.key === viewMode"\r\n' +
  152. ' :data-view-mode="item.key"\r\n' +
  153. ' :title="item.hint"\r\n' +
  154. ' @click="switchViewMode(item.key)"\r\n' +
  155. ' >\r\n' +
  156. ' {{ item.label }}\r\n' +
  157. ' </button>\r\n' +
  158. ' </div>\r\n' +
  159. ' </div>\r\n' +
  160. '\r\n' +
  161. ' <div class="cockpit-shell__scope-right">\r\n' +
  162. ' <div\r\n' +
  163. ' class="cockpit-shell__status-summary"\r\n' +
  164. ` :class="{ 'is-open': statusPanelExpanded }"\r\n` +
  165. ` :data-status-expanded="statusPanelExpanded ? 'true' : 'false'"\r\n` +
  166. ' >\r\n' +
  167. ' <button\r\n' +
  168. ' type="button"\r\n' +
  169. ' class="cockpit-shell__status-toggle"\r\n' +
  170. ' data-status-toggle\r\n' +
  171. ' :aria-expanded="statusPanelExpanded"\r\n' +
  172. ' aria-controls="cockpit-status-details"\r\n' +
  173. ' @click="statusPanelExpanded = !statusPanelExpanded"\r\n' +
  174. ' >\r\n' +
  175. ' <i class="cockpit-shell__status-dot" :class="statusSummaryTone" aria-hidden="true"></i>\r\n' +
  176. ' <span data-status-summary>{{ statusSummaryText }}</span>\r\n' +
  177. ` <span class="cockpit-shell__status-chevron" aria-hidden="true">{{ statusPanelExpanded ? '⌃' : '⌄' }}</span>\r\n` +
  178. ' </button>\r\n' +
  179. ' <div\r\n' +
  180. ' id="cockpit-status-details"\r\n' +
  181. ' v-show="statusPanelExpanded"\r\n' +
  182. ' class="cockpit-shell__status-details"\r\n' +
  183. ' data-status-details\r\n' +
  184. ' >\r\n' +
  185. ' <!--\r\n' +
  186. ' 票 14(决策 02 的 Q24/Q25):地图摘要进入系统/筛选变化后**自动分批加载到完成**。\r\n' +
  187. ' 它作为状态详情的一行保留 `data-map-summary-*` 断言面;手动刷新按钮移到状态摘要\r\n' +
  188. ' 右侧独立位置,避免和范围/行业/视图选择争抢横向空间。\r\n' +
  189. ' -->\r\n' +
  190. ' <div\r\n' +
  191. ' class="cockpit-shell__map-summary"\r\n' +
  192. ' :data-map-summary-phase="mapSummaryView.phase"\r\n' +
  193. ' role="status"\r\n' +
  194. ' aria-label="地图摘要"\r\n' +
  195. ' >\r\n' +
  196. ' <i class="cockpit-shell__map-summary-dot" aria-hidden="true"></i>\r\n' +
  197. ' <span class="cockpit-shell__map-summary-text" data-map-summary-label :title="mapSummaryView.detail">\r\n' +
  198. ' {{ mapSummaryView.label }}\r\n' +
  199. ' </span>\r\n' +
  200. ' </div>\r\n' +
  201. '\r\n' +
  202. ' <!--\r\n' +
  203. ' 票 05:共享数据分区的状态板。验收第 6 条要的「只把受影响分区标为数据不可用、\r\n' +
  204. ' 保留已成功分区与地图骨架」在这里可见;每个分区带 data-section-* 供走查断言。\r\n' +
  205. ' 票 14(规格 09):real 与 mock **同构启动**——同一套分区语义对两种数据源都成立,\r\n' +
  206. ' real 的失败路径(不可达 / 未配地址)同样只标对应分区。\r\n' +
  207. ' -->\r\n' +
  208. ' <span class="cockpit-shell__scope-label">数据分区</span>\r\n' +
  209. ' <div class="cockpit-shell__sections" data-section-board>\r\n' +
  210. ' <SectionStateTag\r\n' +
  211. ' v-for="item in sharedSections"\r\n' +
  212. ' :key="item.name"\r\n' +
  213. ' :name="item.name"\r\n' +
  214. ' :section="item.section"\r\n' +
  215. ' :label="item.label"\r\n' +
  216. ' />\r\n' +
  217. ' </div>\r\n' +
  218. '\r\n' +
  219. ' <!--\r\n' +
  220. ' 票 17:定位反馈。点面板里的可定位对象时,只有三种结果值得说话 ——\r\n' +
  221. ' 点位不在已加载范围内、后端判定不可上图、地图还没就绪。\r\n' +
  222. ' 成功不给文字(地图自己会动、详情卡会开,再弹一句是噪音)。\r\n' +
  223. ' -->\r\n' +
  224. ' <span\r\n' +
  225. ' v-if="locateFeedback"\r\n' +
  226. ' class="cockpit-shell__chip cockpit-shell__locate"\r\n' +
  227. ' :data-locate-result="locateFeedback.result"\r\n' +
  228. ' role="status"\r\n' +
  229. ' >\r\n' +
  230. ' {{ locateFeedback.reasonText }}\r\n' +
  231. ' </span>\r\n' +
  232. '\r\n' +
  233. ' <span v-if="detailOpen && !introVisible && !fixedLocationReason && !anchorLayout.visible"\r\n' +
  234. ' '... 73408 more characters,
  235. expected: /data-area-state/,
  236. operator: 'match',
  237. diff: 'simple'
  238. }
  239. Node.js v24.20.0