diff --git a/demo/topology_audit/04_ghc01_desktop.png b/demo/topology_audit/04_ghc01_desktop.png new file mode 100644 index 0000000..7741ce0 Binary files /dev/null and b/demo/topology_audit/04_ghc01_desktop.png differ diff --git a/demo/topology_audit/browser_back_mismatch.png b/demo/topology_audit/browser_back_mismatch.png new file mode 100644 index 0000000..b2700af Binary files /dev/null and b/demo/topology_audit/browser_back_mismatch.png differ diff --git a/demo/topology_audit/explicit_time_with_mission.png b/demo/topology_audit/explicit_time_with_mission.png new file mode 100644 index 0000000..60baae9 Binary files /dev/null and b/demo/topology_audit/explicit_time_with_mission.png differ diff --git a/demo/topology_audit/ghc05_slice_bottom.png b/demo/topology_audit/ghc05_slice_bottom.png new file mode 100644 index 0000000..0dd7a73 Binary files /dev/null and b/demo/topology_audit/ghc05_slice_bottom.png differ diff --git a/demo/topology_audit/ghc05_slice_mid.png b/demo/topology_audit/ghc05_slice_mid.png new file mode 100644 index 0000000..52f89f4 Binary files /dev/null and b/demo/topology_audit/ghc05_slice_mid.png differ diff --git a/demo/topology_audit/ghc05_slice_top.png b/demo/topology_audit/ghc05_slice_top.png new file mode 100644 index 0000000..b2700af Binary files /dev/null and b/demo/topology_audit/ghc05_slice_top.png differ diff --git a/demo/topology_audit/invalid_time_error.png b/demo/topology_audit/invalid_time_error.png new file mode 100644 index 0000000..dfa95db Binary files /dev/null and b/demo/topology_audit/invalid_time_error.png differ diff --git a/demo/topology_audit/missing_mission.png b/demo/topology_audit/missing_mission.png new file mode 100644 index 0000000..bd207a0 Binary files /dev/null and b/demo/topology_audit/missing_mission.png differ diff --git a/demo/topology_audit/mission_bl_01.png b/demo/topology_audit/mission_bl_01.png new file mode 100644 index 0000000..da5e455 Binary files /dev/null and b/demo/topology_audit/mission_bl_01.png differ diff --git a/demo/topology_audit/mission_bl_02.png b/demo/topology_audit/mission_bl_02.png new file mode 100644 index 0000000..2918673 Binary files /dev/null and b/demo/topology_audit/mission_bl_02.png differ diff --git a/demo/topology_audit/mission_bl_03.png b/demo/topology_audit/mission_bl_03.png new file mode 100644 index 0000000..a717c8e Binary files /dev/null and b/demo/topology_audit/mission_bl_03.png differ diff --git a/demo/topology_audit/mission_ghc_01.png b/demo/topology_audit/mission_ghc_01.png new file mode 100644 index 0000000..a3eef35 Binary files /dev/null and b/demo/topology_audit/mission_ghc_01.png differ diff --git a/demo/topology_audit/mission_ghc_02.png b/demo/topology_audit/mission_ghc_02.png new file mode 100644 index 0000000..5998c14 Binary files /dev/null and b/demo/topology_audit/mission_ghc_02.png differ diff --git a/demo/topology_audit/mission_ghc_03.png b/demo/topology_audit/mission_ghc_03.png new file mode 100644 index 0000000..23a4283 Binary files /dev/null and b/demo/topology_audit/mission_ghc_03.png differ diff --git a/demo/topology_audit/mission_ghc_04.png b/demo/topology_audit/mission_ghc_04.png new file mode 100644 index 0000000..e63d5ba Binary files /dev/null and b/demo/topology_audit/mission_ghc_04.png differ diff --git a/demo/topology_audit/mission_ghc_05.png b/demo/topology_audit/mission_ghc_05.png new file mode 100644 index 0000000..75d6455 Binary files /dev/null and b/demo/topology_audit/mission_ghc_05.png differ diff --git a/demo/topology_audit/mission_jc_01.png b/demo/topology_audit/mission_jc_01.png new file mode 100644 index 0000000..bc841b7 Binary files /dev/null and b/demo/topology_audit/mission_jc_01.png differ diff --git a/demo/topology_audit/mobile_390_top.png b/demo/topology_audit/mobile_390_top.png new file mode 100644 index 0000000..d675e04 Binary files /dev/null and b/demo/topology_audit/mobile_390_top.png differ diff --git a/demo/topology_audit/mobile_modal.png b/demo/topology_audit/mobile_modal.png new file mode 100644 index 0000000..731f7f6 Binary files /dev/null and b/demo/topology_audit/mobile_modal.png differ diff --git a/demo/topology_audit/modal_core_cabin.png b/demo/topology_audit/modal_core_cabin.png new file mode 100644 index 0000000..c8a7122 Binary files /dev/null and b/demo/topology_audit/modal_core_cabin.png differ diff --git a/demo/topology_audit/modal_power_west_group.png b/demo/topology_audit/modal_power_west_group.png new file mode 100644 index 0000000..c5aa9e4 Binary files /dev/null and b/demo/topology_audit/modal_power_west_group.png differ diff --git a/demo/topology_audit/modal_wugang_2.png b/demo/topology_audit/modal_wugang_2.png new file mode 100644 index 0000000..94db690 Binary files /dev/null and b/demo/topology_audit/modal_wugang_2.png differ diff --git a/demo/topology_audit/time_before_base.png b/demo/topology_audit/time_before_base.png new file mode 100644 index 0000000..f23b794 Binary files /dev/null and b/demo/topology_audit/time_before_base.png differ diff --git a/docs/guanghan_topology_adaptation_audit_2026-07-09.md b/docs/guanghan_topology_adaptation_audit_2026-07-09.md new file mode 100644 index 0000000..12488e7 --- /dev/null +++ b/docs/guanghan_topology_adaptation_audit_2026-07-09.md @@ -0,0 +1,422 @@ +# 广寒基地时态拓扑页面适配审计报告 + +日期:2026-07-09 + +测试目标: + +```text +http://localhost:8080/guanghan_topology_demo.html?mission=GHC-01 +``` + +审计范围: + +- 页面初始加载和默认快照; +- 全部 9 个任务选项; +- 明确时间查询、任务与时间并存、基地建立前时间点; +- 无效时间、不存在任务、API 异常呈现; +- 浏览器回退与 URL 状态一致性; +- GHC-05 全部 14 个可视节点的详情弹窗; +- 鼠标、键盘、关闭按钮、遮罩和 Escape 交互; +- 1440×1000 桌面视图与 390×844 窄屏视图; +- API 响应、数据库任务事件、布局数据; +- 既有自动化回归测试; +- 页面、API、种子数据和近期改动的根因检查。 + +本轮只检查、截图和出具报告,没有修改页面、API、数据库或测试代码。 + +## 1. 总结结论 + +当前版本不建议确认完成或发布。 + +它已经具备可工作的基本链路:页面能从 API 取得数据,9 个任务均可查询,GHC-05 最终拓扑的空间骨架基本正确,14 个可视节点均能打开详情弹窗,弹窗在桌面和窄屏下都可用。 + +但适配仍存在发布阻断问题: + +1. 页面并未真正由数据库拓扑和布局驱动,仍是固定 SVG 加少量显隐逻辑; +2. 历史任务会显示不存在的悬空连接线,散热器在基地不存在时仍出现; +3. 5 个任务的“最后一条任务记录时间”与 Timeline 不一致; +4. GHC-05 图中文字大面积越界,严重影响工程总图可读性; +5. 页面写死 `localhost:5000`,部署到真正 Wiki 后,其他访问者会请求自己电脑的 localhost; +6. 无效时间导致 API 返回 HTML 500,页面显示 JSON 解析错误; +7. 自动化回归测试 8 项中有 4 项失败; +8. 后端配置文件包含已提交的明文默认数据库凭据。 + +## 2. 测试结果概览 + +| 测试项 | 结果 | 说明 | +|---|---|---| +| API 健康检查 | 通过 | `/health` 返回 200 | +| 无参数默认快照 | 部分通过 | 页面能显示最新数据,但数据库“最新事件”本身不完整 | +| 9 个任务逐项查询 | 接口通过、呈现部分失败 | 全部返回数据并截图;早期任务拓扑线和散热器错误 | +| 明确时间优先 | 部分通过 | 时间生效,但任务上下文从 API 请求和副标题中丢失 | +| 基地建立前时间 | 部分通过 | 组件和连接为空,但 4 个散热器仍显示 | +| 无效时间 | 失败 | API 500 HTML;页面显示 `Unexpected token '<'` | +| 不存在任务 | 基本通过 | 404 能显示,但下拉框丢失请求值,错误文案为英文 | +| 浏览器回退 | 失败 | URL 回到 GHC-01,页面仍显示 GHC-05 | +| 14 个节点点击弹窗 | 通过 | 全部能打开和关闭 | +| Enter / Space 打开弹窗 | 通过 | 两种键盘操作均有效 | +| × / 遮罩 / Escape 关闭 | 通过 | 三种方式均有效 | +| 关闭后焦点恢复 | 失败 | 焦点落到 `BODY`,未返回触发节点 | +| 390×844 页面布局 | 部分通过 | 页面本身无横向溢出,地图可横向滚动;图中文字仍越界 | +| 390×844 弹窗 | 通过 | 弹窗完整落在视口内 | +| 既有自动化测试 | 失败 | 8 项中 4 项失败 | + +## 3. 全部任务测试 + +所有任务都通过页面下拉框和“查询”按钮实际执行,并分别截图。 + +| 任务 | API 快照时间(页面显示,UTC+8) | 组件数 | API 连接数 | 页面结果 | 截图 | +|---|---:|---:|---:|---|---| +| BL-01 | 2024-04-20 06:58 | 1 | 0 | 失败:仍显示一条供电/燃料线;4 个散热器始终存在 | [截图](../demo/topology_audit/mission_bl_01.png) | +| GHC-01 | 2024-06-16 15:23 | 2 | 0 | 失败:核心舱四条结构线悬空,冰轮线悬空 | [截图](../demo/topology_audit/mission_ghc_01.png) | +| JC-01 | 2024-06-17 16:19 | 2 | 0 | 失败:与 GHC-01 相同 | [截图](../demo/topology_audit/mission_jc_01.png) | +| BL-02 | 2024-06-23 13:23 | 3 | 0 | 失败:显示 6 条并不存在的固定线 | [截图](../demo/topology_audit/mission_bl_02.png) | +| GHC-02 | 2024-07-01 18:37 | 3 | 1 | 失败:页面固定线不能表达 API 中实际的冰轮连接 | [截图](../demo/topology_audit/mission_ghc_02.png) | +| GHC-03 | 2024-08-19 08:00 | 9 | 7 | 失败:显示核心舱未来安装口悬空线和不存在的电力东侧线 | [截图](../demo/topology_audit/mission_ghc_03.png) | +| BL-03 | 2024-09-24 03:20 | 10 | 7 | 失败:固定线仍多于该时刻实际拓扑 | [截图](../demo/topology_audit/mission_bl_03.png) | +| GHC-04 | 2024-11-08 08:00 | 12 | 14 | 部分通过:主要电力拓扑可见,但固定图不能忠实反映连接记录 | [截图](../demo/topology_audit/mission_ghc_04.png) | +| GHC-05 | 2025-01-02 08:00 | 17 | 19 | 空间骨架基本正确;文字越界、信息缺失和时间锚点错误 | [截图](../demo/topology_audit/mission_ghc_05.png) | + +说明:17 个数据库组件被合并成 14 个可视节点,电力模块东、西两组分别使用组合节点。这种组合可以保留,但组合关系目前硬编码在页面中。 + +## 4. 发布阻断问题 + +### P0-1 页面没有真正使用数据库拓扑和布局 + +表现: + +- API 返回 `layout`,页面没有读取 `currentData.layout`; +- SVG 节点、连接线和散热器全部写死在 HTML 中; +- 任务列表也由 `loadMissions()` 返回固定数组; +- 数据库新增模块、连接或未来十字结构后,页面不会自动出现; +- 数据库 17 个组件只能依赖页面中的 `GROUP_MEMBERS` 硬编码压成 14 个节点。 + +证据: + +- `data/wiki/guanghan_topology_demo.html:258` 写死 API 地址; +- `data/wiki/guanghan_topology_demo.html:282` 写死任务列表; +- `data/wiki/guanghan_topology_demo.html:301` 仅对固定节点执行显隐; +- 页面没有任何 `currentData.layout` 使用点; +- `topology_api/queries/snapshot_queries.py` 已返回布局,但前端丢弃。 + +根因: + +这次改动保留了原始静态 SVG,只将部分文字和显隐状态接到了 API。它不是“从数据库渲染拓扑”,而是“数据库数据覆盖固定模板”。 + +影响: + +- 无法满足未来扩建; +- 无法保证任意历史快照准确; +- 数据库和页面会持续形成两套事实来源。 + +### P0-2 正式 Wiki 部署后 API 地址不可用 + +页面写死: + +```js +const API_BASE = 'http://localhost:5000'; +``` + +在当前开发机上可以工作,但真正的 Wiki 访问者打开页面后,浏览器会请求访问者自己电脑的 `localhost:5000`,而不是服务器。 + +根因: + +缺少同源反向代理路径或部署时可注入的 API 基址。 + +影响: + +除开发机外,页面大概率完全无法加载。 + +### P0-3 后端源码包含明文默认数据库凭据 + +`topology_api/config.py` 在环境变量缺失时使用硬编码用户名和密码,并已进入 Git 历史。 + +报告中不重复凭据内容。 + +影响: + +- 凭据泄露; +- 环境变量遗漏时会静默连接真实数据库; +- 后续即使删除源码中的字符串,Git 历史仍保留旧值。 + +需要在修复阶段先轮换凭据,再移除默认密码并检查 Git 历史处置方案。 + +## 5. 高优先级功能问题 + +### P1-1 历史拓扑连接线不可信 + +页面没有根据 `currentData.connections` 画线,而是给固定线配置粗粒度的组件依赖: + +```js +const connTypes = { + 'core-structural': ['core_cabin'], + ... +}; +``` + +随后使用“任意一个依赖组件存在即可显示”: + +```js +needed.some(k => existing.has(k)) +``` + +因此: + +- GHC-01 只有核心舱和冰轮一号、API 连接数为 0,但页面显示核心舱四条悬空线和冰轮线; +- 基地建立前 0 组件时,4 个散热器仍显示; +- GHC-03 电力东部模块尚不存在,东侧结构线仍显示。 + +相关截图: + +- [GHC-01 桌面图](../demo/topology_audit/04_ghc01_desktop.png) +- [基地建立前](../demo/topology_audit/time_before_base.png) + +### P1-2 任务默认时间不符合已确认规则 + +已确认规则是:仅传任务编号时,采用该任务最后一条记录的时间。 + +数据库目前只录入少量拓扑变化事件,导致 5 个任务的最大事件时间早于 Timeline 中最后一条任务记录。 + +下表均以 Timeline 原始时间(UTC)比较: + +| 任务 | 数据库最后事件 | Timeline 最后记录 | 结果 | +|---|---:|---:|---| +| BL-01 | 2024-04-19 22:58 | 2024-05-17 23:01 | 错误 | +| GHC-01 | 2024-06-16 07:23 | 2024-06-16 07:23 | 正确 | +| JC-01 | 2024-06-17 08:19 | 2024-06-17 08:19 | 正确 | +| BL-02 | 2024-06-23 05:23 | 2024-06-23 05:23 | 正确 | +| GHC-02 | 2024-07-01 10:37 | 2024-07-15 03:16 | 错误 | +| GHC-03 | 2024-08-19 00:00 | 2024-08-30 12:45 | 错误 | +| BL-03 | 2024-09-23 19:20 | 2024-09-23 19:20 | 正确 | +| GHC-04 | 2024-11-08 00:00 | 2024-11-20 13:57 | 错误 | +| GHC-05 | 2025-01-02 00:00 | 2025-01-22 10:52 | 错误 | + +根因: + +种子数据将 `mission_events` 当成“拓扑变化事件”,但查询规则将其当成“完整任务时间线”。两种语义冲突。 + +### P1-3 GHC-05 图中文字严重越界 + +`updateNodeLabels()` 将数据库中的长摘要直接写入固定大小 SVG ``,没有截断、换行或 `foreignObject` 布局。 + +同时它把原本的安装位置说明替换成泛化类型,如“舱段模块”“设备模块”,使工程图信息反而减少。 + +核心舱和北部模块仍残留“加载中...”占位文本。 + +截图: + +- [上半区](../demo/topology_audit/ghc05_slice_top.png) +- [电力模块区](../demo/topology_audit/ghc05_slice_mid.png) +- [底部区](../demo/topology_audit/ghc05_slice_bottom.png) + +### P1-4 同时提供任务和时间时,页面丢失任务上下文 + +页面 URL 正确保留: + +```text +?mission=GHC-01&at=2025-01-02T08:00:00+08:00 +``` + +但 `fetchSnapshot()` 使用: + +```js +if (at) ... +else if (mission) ... +``` + +所以 API 请求只携带 `at`,没有携带 `mission`。最终副标题显示“(最新)”,而不是保留 GHC-01 上下文。 + +API 本身在同时收到两个参数时行为正确,缺陷位于页面请求组装。 + +截图:[任务与时间并存](../demo/topology_audit/explicit_time_with_mission.png) + +### P1-5 浏览器回退后 URL 与页面状态不一致 + +页面查询时调用 `history.pushState()`,但没有监听 `popstate`。 + +复现: + +1. 查询 GHC-01; +2. 查询 GHC-05; +3. 浏览器后退; +4. URL 已回到 `mission=GHC-01`; +5. 下拉框、副标题和拓扑仍是 GHC-05。 + +截图:[浏览器回退错位](../demo/topology_audit/browser_back_mismatch.png) + +### P1-6 无效时间产生 500 和技术性错误文案 + +输入 `not-a-time` 后: + +- API 将原字符串直接送入 PostgreSQL `timestamptz` 强制转换; +- PostgreSQL 抛错; +- Flask 返回 HTML 500; +- 页面对错误响应强制执行 `res.json()`; +- 用户看到 `Unexpected token '<'`; +- 旧副标题仍保留,形成新旧状态混杂。 + +截图:[无效时间错误](../demo/topology_audit/invalid_time_error.png) + +### P1-7 “任务节点”字段并不是任务信息 + +弹窗中的“任务节点”实际显示 `detailUrl`: + +```text +详见 Wiki: /home/Spacecraft/... +``` + +没有链接时显示“资料未记录”。 + +API 没有返回组件引入任务、最后状态任务或生效事件,因此页面无法正确展示任务节点。 + +### P1-8 模块尺寸和详情数据不完整 + +GHC-05 的 17 个组件中: + +- 只有居住舱一号、居住舱二号、温室舱和实验舱具有完整几何尺寸; +- 核心舱只有质量,没有长宽高; +- 其余 12 个组件的 `dimensions` 为空; +- 多个电力设备只有一句摘要,没有描述和规格; +- 电力东、西组合弹窗以第一个成员作为标题、位置和状态,其他成员只被拼进“关键参数”。 + +全部 14 个可视节点的弹窗操作都成功,但信息完整性未达到“模块状态、模块信息等均从数据库读取并完整呈现”的目标。 + +代表截图: + +- [核心舱弹窗](../demo/topology_audit/modal_core_cabin.png) +- [西部组合弹窗](../demo/topology_audit/modal_power_west_group.png) +- [吴刚二号弹窗](../demo/topology_audit/modal_wugang_2.png) + +### P1-9 冰轮连接端口数据与空间位置冲突 + +视觉图将冰轮一号、二号、三号分别放在电力模块西、南、东。 + +但数据库中的 6 条燃料/供电连接全部指向: + +```text +power_module_hub.west +``` + +这使弹窗连接数据与工程图位置矛盾。至少冰轮二号、三号应分别核对南、东端口语义。 + +## 6. 中优先级问题 + +### P2-1 任务下拉框不是数据库数据 + +`loadMissions()` 返回固定任务数组。数据库新增任务后页面不会出现,删除或更名也不会同步。 + +需要任务列表 API,或在快照 API 中返回可选任务。 + +### P2-2 自动化测试与适配代码不同步 + +执行: + +```text +python -m unittest tests.test_guanghan_topology_demo tests.test_guanghan_topology_e2e -v +``` + +结果: + +```text +Ran 8 tests +FAILED (failures=4) +``` + +失败项: + +1. 加压走道连接契约; +2. 每个可点击模块的尺寸字段契约; +3. 未来扩展锚点注释; +4. 渲染和弹窗 E2E。 + +部分失败是适配后没有同步测试,部分对应真实回归: + +- 原来要求保留的 `FUTURE_EXPANSION_ANCHOR:north/east/west` 注释已被删除; +- 新 E2E 没有启动或模拟拓扑 API; +- 测试仍检查旧 `data-connection` 契约。 + +此外,当前没有 API 查询、时间优先级、数据库约束和 9 个任务快照的自动化测试。 + +### P2-3 详情弹窗关闭后不恢复焦点 + +Enter 和 Space 可以打开弹窗,Escape 可以关闭;但关闭后焦点落在 `BODY`,没有返回原节点。 + +这会影响键盘连续浏览和无障碍体验。 + +窄屏证据: + +- [390×844 页面](../demo/topology_audit/mobile_390_top.png) +- [390×844 弹窗](../demo/topology_audit/mobile_modal.png) + +### P2-4 时间显示依赖访问者本地时区 + +页面使用 `toLocaleString('zh-CN')`,没有固定时区或显示 UTC 偏移。不同地区的访问者可能看到不同日期和时间。 + +### P2-5 页面显示内部枚举值 + +页面直接显示: + +```text +mission_latest_event +latest_recorded_state +explicit_time +``` + +这些是 API 内部值,不适合作为最终 Wiki 文案。 + +### P2-6 数据库内容进入 `innerHTML` 时未转义 + +尺寸、关键参数和连接关系通过模板字符串写入 `innerHTML`。当前种子数据可信,但未来如果后台编辑内容含 HTML,会形成存储型脚本注入风险。 + +## 7. 已确认通过的部分 + +以下部分不应在修复时无故推翻: + +- GHC-05 核心舱十字结构与电力模块十字结构的整体空间关系; +- 两条加压走道为绿色实线; +- 四组散热器的视觉样式和文字标注; +- 14 个可视节点均可点击; +- 弹窗 ×、遮罩和 Escape 关闭; +- 节点 Enter / Space 键打开弹窗; +- 窄屏弹窗尺寸和内部信息布局; +- API 的明确时间优先规则; +- API 的未知基地 404 和未知任务 404; +- 无参数查询采用数据库内已发生任务的最大事件时间这一查询逻辑。 + +最后一项的查询代码逻辑正确,但种子事件不完整,所以实际得到的“最新时间”仍错误。 + +## 8. 建议修复边界 + +如果本报告获确认,建议按以下顺序实施: + +1. 先处理凭据轮换与部署 API 地址; +2. 为页面/API/数据库补充失败测试,固定已确认语义; +3. 补齐任务末条事件或拆分“拓扑事件”和“任务时间锚点”; +4. 用 API 的组件、连接和布局数据真正生成图,不再维护固定拓扑事实; +5. 修复历史快照连接、散热器和组合节点; +6. 修复图中文字布局和残留占位符; +7. 修复时间校验、任务上下文、回退导航和错误状态; +8. 补齐任务列表、模块引入任务、尺寸与详情数据; +9. 完成 9 个任务、明确时间、异常输入、桌面和窄屏全量回归并重新截图。 + +修复过程中应保留目前已通过的 GHC-05 空间骨架、绿色加压走道、散热器样式和弹窗视觉风格。 + +## 9. 截图目录 + +全部测试截图位于: + +```text +demo/topology_audit/ +``` + +其中包括: + +- 9 个任务各 1 张完整页面截图; +- GHC-05 上、中、下三段人工视觉检查; +- 3 个代表性详情弹窗; +- 明确时间、无效时间、基地建立前、不存在任务和浏览器回退; +- 390×844 页面和弹窗。 + +其他异常截图: + +- [不存在的任务](../demo/topology_audit/missing_mission.png)