4.1 KiB
直接编辑交互收尾:ghost 定位与 manifest 裁剪
父任务:.trellis/tasks/08-26-direct-manipulation-road-editor。
前置:08-26-direct-edit-map-editor(已归档)交付了手柄、拖拽、预览与保存。
背景
perf: stop recomputing control bounds in overlap tests(d893e40)把预览从
~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-state 与 POST /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:check、npm run test、npm run test:client、npm run test:client:unit、npm run build全绿
顺序依赖
无前置。后继:手柄目标泛化与新元素类型,两者都受益于本任务的裁剪。