# javaTest 完整地图与路径差异审计增量设计 ## 1. 背景与目标 现有审计台虽然按真实坐标绘制路径,但画布边界只由选中任务涉及的站点决定,未显示完整地图 拓扑。使用者只能看到一条孤立折线,无法判断路线位于实际地图的哪个通道,也难以识别历史 `path_info` 与调度中心 `plannedPath` 的共同段和分叉段。 本增量设计替代原设计第 4.5 节中“只返回路径附近节点”的限制,并细化第 7 节的路径语义: - 默认显示当前楼层的完整可通行地图; - 保留 1-8 楼切换,路径经过的楼层明确标记; - 提供“完整地图”和“聚焦路径”两种视口; - 对历史路径与新规划路径执行边级差异比较; - 浏览器仍只展示 Java 返回的地图和结果,不实现路径规划算法。 ## 2. 方案选择 ### 2.1 采用:单画布完整楼层地图 + 差异叠加 当前楼层的全部站点和真实邻接边作为浅灰底图,新规划路径、历史路径和实际轨迹叠加在同一 坐标系中。该方案最适合核对“新旧路线在哪个路口分开、在哪个路口重新汇合”,且无需在两张 图之间依赖记忆比较。 ### 2.2 不采用:历史/规划双画布并排 并排视图能分别看清两条路线,但每张图的可用宽度减半,移动端阅读困难;使用者仍需人工在 两张图之间寻找同一个站点,不利于边级审计。 ### 2.3 不采用:历史/规划交替切换 单选切换视觉最干净,但切换后上一条路线消失,无法直接定位分叉和汇合位置,不满足本次 “看出区别”的核心要求。 ## 3. 地图数据契约 `GET /api/bootstrap` 保留完整站点列表,并新增权威无向边列表 `edges`: ```json { "sites": [{ "siteId": "010701", "floor": 1, "x": 15, "y": 1 }], "edges": [{ "fromSite": "010701", "toSite": "020701", "floor": 1 }] } ``` 边来源只能是 `HistoricalSimulationInput.getGridMap()`。后端遍历全部站点的 `GridMap.getNeighbors(siteId)`,将端点按站点编号排序后去重,确保同一条无向边只返回一次。 页面不得根据坐标猜测相邻关系。 每个任务继续返回原始 `historicalPath` 和调度结果 `plannedPath`,并增加 `pathComparison`: - `sharedEdges`:历史路径和新路径共同使用的真实边; - `plannedOnlyEdges`:只有新规划使用的边; - `historicalOnlyEdges`:只有历史路径使用的边; - `invalidHistoricalSegments`:历史 `path_info` 中节点不存在或不相邻的段; - `sharedEdgeCount/plannedOnlyEdgeCount/historicalOnlyEdgeCount`:检查器使用的计数。 边比较使用无向规范键,避免同一物理边因端点顺序不同被误判。`pathChanged` 原有的完整节点序列 比较继续保留,用于兼容报告和既有测试;边差异用于可视化解释,不参与调度或规划。 ## 4. 地图交互 ### 4.1 默认视图 运行任务后默认选择任务起点所在楼层,并显示该楼层全部可通行站点和邻接边。楼层选择器列出 1-8 楼;经过路径的楼层带有路径提示,当前车辆所在楼层带有车辆提示。 完整地图使用稳定坐标边界,不因选择任务、推进 tick 或切换历史路径而重新缩放。这样同一站点 在同一楼层始终位于同一屏幕位置,便于重复核查。 ### 4.2 视口工具 路径画布提供: - `完整地图`:适配当前楼层完整地图,为默认模式; - `聚焦路径`:适配当前任务在该楼层涉及的路径范围; - 放大、缩小、复位按钮; - 鼠标滚轮缩放和拖动画布; - 悬停站点显示站点编号、楼层和真实坐标。 切换 tick 只更新动态路径和车辆位置,不重置用户已经选择的缩放与平移状态。切换楼层或任务时 重新执行当前视口模式的适配。 ## 5. 视觉语义 绘制层级从底到顶固定为:完整地图、历史/规划对比、实际轨迹、节点状态、车辆。 - 完整地图边:浅灰 1px;完整地图节点:低对比度小圆点; - 仅历史边:橙色点线; - 仅新规划边:绿色实线; - 共同边:绿色实线底层叠加较窄的橙色点线,使两份证据同时可见; - 已实际通过边:蓝色高亮,位于比较路径上方; - HOLD:琥珀色节点或边; - A、B 和当前车辆:保留稳定的不同标记。 完整地图不常驻显示所有站点文字,避免 1,175 个站点形成文字遮挡。仅 A、B、车辆、HOLD、 分叉点和鼠标悬停站点显示标签;完整站点编号仍可通过悬停和任务路径文本读取。 图例增加“共同路段、仅历史、仅新规划”,任务检查器增加边差异计数和无效历史段提示。 历史参考开关关闭时只隐藏历史专属和共同边上的橙色证据,不隐藏新规划路径。 ## 6. 性能与错误处理 完整地图按当前楼层绘制,而不是同时叠加 8 层。页面首次加载后缓存每层背景 SVG 分组;推进 时间线时只重建路径、节点状态和车辆等动态层。约千级站点和邻接边不会在每个 tick 重复创建。 如果历史路径含未知站点或非邻接段,页面不把它伪造成地图连线:无效段显示在检查器中,已知且 有效的历史段继续绘制。若某楼层没有任务路径,仍显示完整底图并提示该层无选中任务路径。 ## 7. 测试策略 ### 7.1 Java 测试 - bootstrap 边数与从 `GridMap.getNeighbors()` 导出的权威边集合完全一致; - 所有边端点存在、端点顺序规范、没有正反向重复; - 相同边、仅历史边、仅规划边的集合差计算正确; - 空路径、单节点路径、反向边和未知历史节点不会产生伪造边; - 原有 240/0/0、资源安全、归档和 WMS 幂等结果不变。 ### 7.2 浏览器测试 - 未选择任务时也能显示当前楼层完整地图; - 完整地图边数量明显大于选中任务路径边数量; - “完整地图/聚焦路径”、楼层、缩放、拖拽和复位有效; - 历史与规划不同的任务同时出现共同、仅历史和仅规划样式; - 关闭历史参考后,新规划和完整底图仍存在; - tick 推进不改变完整地图坐标和用户视口; - 1440x900 和 390x844 无重叠、无横向页面溢出、控制台无错误。 ## 8. 验收标准 - 使用者能明确看出路径位于当前楼层完整地图的哪个通道; - 可以一键在全图上下文和路径细节之间切换; - 历史路径和新规划路径的共同段、分叉段、汇合段无需手工阅读节点列表即可识别; - 页面路径边全部来自后端权威地图拓扑,不由坐标推测; - 历史无效段被明确报告且不绘制成真实地图边; - 现有调度、交通裁决、PLC、车辆移动、归档和 WMS 结果不被改写; - 自动测试与真实浏览器验收通过。