map.primaryArea)What to build: 驾驶舱配置新增主场景区矩形 map.primaryArea.bounds。部署写好即生效;未配置或顺序非法时,依赖它的区域限位与自建雾整体关闭,并在状态浮标如实提示原因 —— 即决策票 01 的「部署期准备候选值 + 运行时未配置则关闭」。
Blocked by: None
Status: resolved Labels: ready-for-agent
cockpit-primary-area-guardrails/spec.md(决策票 03 的落地口径)。cockpit-primary-area-guardrails/issues/01-primary-area-config-contract.md(已 resolved)。map.primaryArea.bounds 取 [west, south, east, north](度)四元数组,与 map.overlays[].bounds 同口径。west < east、south < north;不自动翻转甲方给的 [W, N, E, S] 顺序。data-* 读数)上,人工与走查都能读到,不只是注释。config.example.json 同步该字段形状。已完成(2026-09-28)。 本票是配置与开关的落地:只回答「限位与自建雾能不能开、开在哪个矩形」, 不实现限位本身(票 37)也不实现雾(票 38)——那两张票消费本票的出口。
domain/primaryArea.js:形状 / 顺序判定的唯一一处(配置归一化也调它,不写第二份),
另给三态 ready|missing|invalid、浮标措辞、关闭原因词表。纯函数、不 import cesium(与 domain/basemap.js、mapLayers.js 同模式)。services/cockpitConfig.js:内置默认补 primaryArea: { bounds: null, configured: false }
—— 故意不预置任何地理常量(决策票 01 Q3=A:兜底归部署期算,不写死源码);
normalizeConfig 原样收下数组(不翻转)、把不可用原因记进 issues 并保留。
configured 用来区分「部署没写这个字段」(未配置)与「写了但是空的」(写错了)。services/mapService.js:启动时按配置算一次计划(放在「引擎已由配置关闭」那条早退之前),
浮标加一句 主场景区:…,宿主加 data-map-primary-area / data-map-primary-area-reason,
getLifecycleStats() 补三个字段,并给出票 37/38 的唯一入口 getPrimaryAreaPlan()(返回副本)。public/cockpit/config.json 写本部署显式值;config.example.json 同步字段形状与一条字段说明;
docs/cockpit-deployment.md 新增 2.9 主场景区(顺序是硬要求、三种浮标读数的对照表、矩形怎么定)。verify/t36-primary-area.mjs(逻辑闸门)+ verify/t36-primary-area-walkthrough.mjs(真机走查);
verify/t05-adapter.mjs 的静态守卫面按仓库惯例纳入新 domain 文件(218→230 项)。booting/failed/disabled 下浮标也照说这一句。t36-primary-area.mjs 通过,覆盖验收点名的四类输入(合法 / 顺序写反 / 缺字段 / 个数不对,
其中个数类含 3 个、5 个、空数组、混字符串、null、NaN、非数组、对象共 8 种)。
另含:甲方原样的 [W,N,E,S] 必须判非法且不给出矩形;三条关闭路径原因两两不同;
本部署显式值与甲方原值只差纬度两值对调(逐位差 < 1e-9 度,仅截位);模板示例值自身合法;
以及静态守卫(判定唯一、无内置地理常量、无翻转、只读出口齐)。mountMap,
读回宿主 dataset 与浮标文本 —— 未读到配置前不宣布结论;关引擎的部署浮标上照样读到
主场景区:配置无效(顺序应为 [西,南,东,北],不自动翻转) · 限位与雾气关闭。fetch / 反向 import service 均打红)。t28-fill-container.mjs 是 puppeteer 脚本,
因 DSH profile 的 @puppeteer/browsers 是空目录(0 个文件)而 ERR_MODULE_NOT_FOUND,
与本票无关(改动前后同样失败;本票走查因此改用 DSH 自带浏览器,见下)。运行方式与脚本原始设计不同,且证据更强:verify/t36-primary-area-walkthrough.mjs 的 puppeteer 路线在本机被
@puppeteer/browsers 包为空目录卡住(与本票无关,t28 等所有 puppeteer 脚本同样失败),
故改用 DSH 自带浏览器手工驱动同一条验收链(真实 Chrome、真实 yarn dev @ 127.0.0.1:8000、
真实页面 #/cockpit)。这比脚本的 evaluateOnNewDocument 注入多证明一件事:
配置是走真实运行时文件层(data-source=file)生效的,不是注入旁路。
| # | 用例 | 改 public/cockpit/config.json |
实测读数 | 结果 |
|---|---|---|---|---|
| A1 | 合法 | 本部署显式值 | data-map-primary-area=ready;浮标 主场景区:13.4×11.1 km;出口 bounds 四元齐 |
✅ |
| A2 | 未配置 | 删除 map.primaryArea |
missing;原因 未配置;浮标 未配置 · 限位与雾气关闭;出口 bounds=null |
✅ |
| A3 | 顺序写反 | 甲方原样 [W,N,E,S] |
invalid;原因 顺序应为 [西,南,东,北],不自动翻转;出口 bounds=null(没被默默翻转) |
✅ |
| A4 | 个数不对 | [110, 28, 111] |
invalid;原因 bounds 应为四个有限数字(与 A3 措辞不同,排查能对号) |
✅ |
| A5 | 关引擎 | cesium.enabled=false |
引擎 disabled、canvas=0,但 primaryArea=ready 且浮标照样读到 主场景区:13.4×11.1 km |
✅ |
data-map-primary-area(-reason)、__cockpitMap.getPrimaryAreaPlan()、浮标文本
—— 即「人工读得到」与「走查读得到」在同一时刻都被证实,不只是断言源码里存在。t36-a1-ready.png(生效,浮标在中央顶部一行内可读)、
t36-a3-invalid.png(关闭,浮标写明顺序原因 + 「限位与雾气关闭」)。
顺带证实了「主场景区排在最前」这个决定的必要性:A3 关闭路径那句明显更长,
排在后面时截图里尾部已被 … 省略;提到最前之后,最关键的那句完整可见。public/cockpit/config.json 已逐字节还原(2291 bytes、无 BOM、intro.enabled=true、本部署 bounds),
与运行前备份 Compare 相等。浮标原来只在引擎 ready 时才拼业务读数,于是把引擎关掉的部署(map.cesium.enabled=false)
在主场景区这件事上完全失声 —— 而这恰恰是最需要看到「限位与雾气关了」的那种部署。
已改为:配置到手后,无论引擎处于何种状态,这一句都跟着说;引擎就绪时仍按原顺序拼在业务读数最前。
(顺手把主场景区提到 basemapText 之前:这根浮标是 nowrap + ellipsis,关闭路径那句更长,排后面会被尾省略。)
36 就位,37(进区锁定与相机区域限位)解除阻塞(38 仍等 37:它的门控要 areaState)。
37 与 38 都从 mapService.getPrimaryAreaPlan() 取「开不开、开在哪儿」,不要再自己解析一遍配置
——判定只有 domain/primaryArea.js 一处,自己再判一次就会出现第二套口径。
40(全程质量收口)按 36→37→38→39→40 的顺序留到最后。