Files
road-compiler/.trellis/tasks/archive/2026-08/08-26-direct-edit-map-editor/implement.md

3.8 KiB
Raw Blame History

实施计划

对应父任务 implement.md 的第 1、6 步。每步一个提交,门禁不过就停。

前置:direct-edit-solver-api 第 2 步handle manifest已可用。完整验收需其预览与保存端点就绪。

1. ol-ext 限时探针

  • 目标:只回答一个问题——能否复用通用 handle 的命中、pointer 生命周期与视觉反馈。
  • 范围:隔离探针目录,不修改生产基线图层,不进依赖清单直到通过。
  • 验证:手动跑探针页,确认 OL Map 未重建、proxy 拖拽稳定、基线 source 未被写入、事件能转成 draft 值。
  • 门禁:三条同时成立才把 ol-ext 固定为依赖。超过一个工作日或任一条不成立,立刻停止排障。
  • 回滚点:删除探针目录,改用原生 OL Snap + 小型 PointerInteraction adapter。数据合约不变本步失败只换输入层。

2. EditSession 纯逻辑

  • 目标:先把可单测的部分做完,与地图解耦。
  • 范围:命令栈与 undo/redopreviewSeq 仲裁handle 事件到约束值的投影;指针位移到米的换算。不含任何 OpenLayers 引用。
  • 验证:npm run test:client:unit —— 命令栈压入/撤销/重做序列正确;乱序响应(后发先到)被丢弃且不覆盖较新预览;投影在四种 kind 上给出预期约束值;同一像素位移在低纬与高纬得到一致的米值(纬度缩放正确)。
  • 门禁:四类纯逻辑全部有测试;EditSession 不 import ol
  • 回滚点纯新增模块无调用方revert 无影响。

3. 手柄渲染与开关

  • 目标:选中道路后能看到正确的手柄,且禁入区可见可解释。
  • 范围:directEdit 开关默认关闭selection → manifest 读取;editHandles source 渲染reserve 内手柄置灰并带原因提示。只读不可拖。
  • 验证:npm run test:clientnpm run build;手测——选中道路出现手柄,拖拽前后 Map 为同一实例reserve 内手柄置灰并提示进入 JunctionTools;关闭开关后无手柄、无 manifest 请求。
  • 门禁:Map 未被重建;基线 source 未被写入。
  • 回滚点:开关关闭即止损。

4. 拖拽、ghost 与预览

  • 目标:四类能力真正可拖,预览权威且不闪烁。
  • 范围:外缘偏移、步行带宽度、车道分隔位置、区间范围控制;editGhost 即时反馈80ms 防抖与 pointerup 最终请求;AbortController 取消在途请求;editPreview 替换;无效草稿诊断与保留最后有效预览。
  • 验证:npm run test:client:unitnpm run test:clientnpm run build;手测——拖动外缘时道路面/步行带/车道线/标线/connector 一致更新且只有受影响 source 被替换;车道分隔可独立调整;区间范围手柄改变影响区间且两端平滑;连续快速拖拽松手后无回跳;违反不变量时停在最后有效预览并显示诊断。
  • 门禁:只有受影响 source 被替换,无全图层重建;无回跳。
  • 回滚点:按能力分批提交,可单独回退某一类手柄。

5. 应用、保存与撤销

  • 目标:闭合编辑生命周期。
  • 范围:应用/保存/取消undo/redo 接到命令栈;保存走 expectedDocumentVersion409 冲突提示。
  • 验证:npm run test:client:unit(保存冲突分支)、npm run test:clientnpm run build;手测——未保存编辑可撤销/重做;保存后重新编译几何不变且状态 exact;两标签页同时保存后者收到 409 提示且前者结果保留。
  • 门禁撤销不重写已保存历史409 有明确用户提示而非静默失败。
  • 回滚点revert 后回到第 4 步的预览-only 状态。

步骤依赖

1 与 2 可并行3 依赖 1 的结论与 24 依赖 35 依赖 4。第 1 步失败不阻塞 2-5只改变第 3、4 步的命中与拖拽实现方式。