Files
road-compiler/.trellis/tasks/archive/2026-08/08-28-edit-interaction-polish/prd.md

4.1 KiB
Raw Blame History

直接编辑交互收尾ghost 定位与 manifest 裁剪

父任务:.trellis/tasks/08-26-direct-manipulation-road-editor。 前置:08-26-direct-edit-map-editor(已归档)交付了手柄、拖拽、预览与保存。

背景

perf: stop recomputing control bounds in overlap testsd893e40把预览从 ~1535ms 降到 ~142ms 之后,两件事的前提变了:

1. ghost 的原始职责被大半抵消。 它当初是为了在 1.5 秒等待里提供即时反馈。 现在权威几何在约 220ms 内落地80ms 防抖 + 142ms 求解),用户观察到的是 「好像是实时修改」——那正是服务端几何,不是 ghost。

research/joint-solver.md:48 要求 ghost 包含「半透明预估轮廓」,该轮廓未实现。 本任务不补它,因为它与父任务 design.md 的另一条规则冲突:

浏览器不实现第二套道路几何算法

准确的预估轮廓就是在浏览器里重算路面。粗糙的轮廓(把边缘线整体外移 N 米) 在过渡段、路口交界、钳位处都是错的——会撒谎的预览比没有预览更糟

2. manifest 裁剪的时机到了。 现在 41 条路的片区产出 221 个手柄,每次预览全量下发, 客户端再过滤成 6 个。后续每加一类元素(停止线、斑马线、红绿灯、箭头)都会成倍放大, 应在手柄种类增长之前把过滤挪到服务端。

目标

把 ghost 重新定位为「意图与约束的读数」,并让 manifest 只返回选中对象的手柄, 使这套子系统在加入新元素类型前处于稳定、可扩展的状态。

回答什么问题
ghost 要求的是什么?到极限了吗?求解还在路上吗?
preview 会得到什么?

范围

A. ghost 精简

去掉回到起点的虚线辅助线。几何已经实时在动,那条线的原始用途(漫长等待中标示起点) 已经消失,现在是视觉噪音。保留 ghost 独有、preview 表达不了的三件事:

  • 圆点手柄本身
  • 数值增量标签(+2.35 米)——看几何看不出改了多少
  • 钳位配色——几何单纯停住有歧义:是到极限了还是卡了?

B. degraded 状态

design.md

超预算仍返回结果但标 degraded: true,客户端保留 ghost 与待定状态,不做几何闪烁。

EditSession.degraded 已实现并有单测,但没有任何消费者。求解超预算时 ghost 必须 保持可见并显示待定,而不是清除后让几何跳变。

C. manifest 按选中裁剪

GET /api/edit-statePOST /api/edit-preview 接受可选的选中标识segment id 只返回该对象的手柄。未提供时保持现有全量行为,供其他调用方与既有测试使用。

客户端随之停止本地过滤——handlesForSegment() 的过滤职责移到服务端, 但该函数保留并继续单测:它仍是「哪些手柄属于主地图」这条规则的唯一定义 road kinds、排除 junction kinds、保留置灰手柄服务端与它必须一致。

不做

  • 不实现半透明预估轮廓(理由见背景)
  • 不做局部编译d893e40 之后没有必要,且是全项目最高风险项)
  • 不做 Web Worker 预览(用户 2026-08-28 明确搁置)
  • 不实现区间生效,方块手柄继续隐藏
  • 不新增元素类型

验收标准

  • 拖拽时 ghost 显示圆点 + 数值增量,不再有回到起点的虚线
  • 拖到钳位边界时 ghost 变色,与「仍在跟手」明显可分
  • degraded: true 的响应不清除 ghost且有可见的待定提示几何不闪烁
  • /api/edit-state/api/edit-preview 接受选中标识并只返回该 segment 的手柄
  • 不带选中标识时返回全量手柄,既有测试不受影响
  • 服务端裁剪结果与客户端 handlesForSegment() 对同一输入一致(测试断言)
  • 裁剪前后手柄数与响应体积实测记录在案
  • npm run format:checknpm run testnpm run test:clientnpm run test:client:unitnpm run build 全绿

顺序依赖

无前置。后继:手柄目标泛化与新元素类型,两者都受益于本任务的裁剪。