From 3c5f39ed73412021c92e106b99aae3f168569193 Mon Sep 17 00:00:00 2001 From: que01 Date: Wed, 26 Aug 2026 15:26:41 +0800 Subject: [PATCH] fix: refine workbench map layers --- .../check.jsonl | 1 + .../implement.jsonl | 1 + .../08-26-workbench-layer-scene-polish/prd.md | 18 +++++++ .../task.json | 26 +++++++++ workbench/client/src/App.tsx | 54 +++++++++++++++---- workbench/client/src/map/layers.ts | 13 +++-- 6 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 .trellis/tasks/08-26-workbench-layer-scene-polish/check.jsonl create mode 100644 .trellis/tasks/08-26-workbench-layer-scene-polish/implement.jsonl create mode 100644 .trellis/tasks/08-26-workbench-layer-scene-polish/prd.md create mode 100644 .trellis/tasks/08-26-workbench-layer-scene-polish/task.json diff --git a/.trellis/tasks/08-26-workbench-layer-scene-polish/check.jsonl b/.trellis/tasks/08-26-workbench-layer-scene-polish/check.jsonl new file mode 100644 index 0000000..9dd3234 --- /dev/null +++ b/.trellis/tasks/08-26-workbench-layer-scene-polish/check.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."} diff --git a/.trellis/tasks/08-26-workbench-layer-scene-polish/implement.jsonl b/.trellis/tasks/08-26-workbench-layer-scene-polish/implement.jsonl new file mode 100644 index 0000000..9dd3234 --- /dev/null +++ b/.trellis/tasks/08-26-workbench-layer-scene-polish/implement.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."} diff --git a/.trellis/tasks/08-26-workbench-layer-scene-polish/prd.md b/.trellis/tasks/08-26-workbench-layer-scene-polish/prd.md new file mode 100644 index 0000000..ba191e9 --- /dev/null +++ b/.trellis/tasks/08-26-workbench-layer-scene-polish/prd.md @@ -0,0 +1,18 @@ +# 优化工作台图层与场景标线 + +## Goal + +移除不再需要的高德规整路口参考图层,提供可读的编译概览,并恢复场景模式下双向道路中心线的可辨识渲染。 + +## Confirmed Facts + +- 科技园一路的三个双向路段在 `center_lines.geojson` 中都有完整的黄色虚线 feature;不是编译缺失。 +- React adapter 将原版中心线的属性驱动样式简化为固定样式,造成场景模式下辨识度不正确。 +- 高德参考层仅在 React 前端图层 registry、图层开关和状态装载中使用;不影响编译。 + +## Acceptance Criteria + +- 工作台不显示或加载高德规整路口参考图层。 +- 场景模式下保留中心线,并按线的颜色和虚/实线属性清晰渲染。 +- 编译概览以中文分组指标和诊断摘要展示,不显示 schema、note、null 或 `[object Object]`。 +- 格式化、类型检查和生产构建通过。 diff --git a/.trellis/tasks/08-26-workbench-layer-scene-polish/task.json b/.trellis/tasks/08-26-workbench-layer-scene-polish/task.json new file mode 100644 index 0000000..80be83d --- /dev/null +++ b/.trellis/tasks/08-26-workbench-layer-scene-polish/task.json @@ -0,0 +1,26 @@ +{ + "id": "workbench-layer-scene-polish", + "name": "workbench-layer-scene-polish", + "title": "优化工作台图层与场景标线", + "description": "移除高德规整路口参考,优化编译概览,并修复场景模式下科技园一路中心线缺失", + "status": "in_progress", + "dev_type": null, + "scope": null, + "package": null, + "priority": "P2", + "creator": "dingkang", + "assignee": "dingkang", + "createdAt": "2026-08-26", + "completedAt": null, + "branch": null, + "base_branch": "main", + "worktree_path": null, + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": null, + "relatedFiles": [], + "notes": "", + "meta": {} +} \ No newline at end of file diff --git a/workbench/client/src/App.tsx b/workbench/client/src/App.tsx index 8ae1e0d..1e7d036 100644 --- a/workbench/client/src/App.tsx +++ b/workbench/client/src/App.tsx @@ -17,7 +17,6 @@ const layerLabels: Array<[LayerName, string]> = [ ['edgeLines', '道路外缘线'], ['controls', '斑马线与停止线'], ['signals', '红绿灯设施'], - ['gaodeReference', '高德规整路口参考'], ['reference', 'osm2streets 参考面'], ]; const defaultLayers = Object.fromEntries( @@ -26,6 +25,50 @@ const defaultLayers = Object.fromEntries( const direction = (road: Road) => (road.direction === 'forward' ? '沿 OSM 方向' : '逆 OSM 方向'); const label = (road: Road) => road.tags.name || `${road.highway}(OSM ${road.osmWayIds.join(', ')})`; const laneIndex = (id: string) => Number(id.split(':').at(-1)); +const overviewMetrics = [ + ['nativeRoadCount', '方向道路'], + ['nativeRoadSurfaceFeatures', '道路面'], + ['nativeJunctionSurfaceFeatures', '路口面'], + ['nativeLaneCenterlineFeatures', '车道中心线'], + ['nativeCenterLineFeatures', '道路中心线'], + ['nativeConnectorFeatures', '连接路径'], + ['nativeCrosswalkFeatures', '斑马线'], + ['nativeVehicleStopLineFeatures', '停止线'], + ['unconnectedInteriorRoadEnds', '未连接端点'], +] as const; +function Overview({ comparison }: { comparison: Record }) { + const severity = comparison.diagnosticsBySeverity as Record | undefined; + return ( +
+
+ {overviewMetrics.map(([key, label]) => ( +
+ {label} + {Number(comparison[key] || 0).toLocaleString('zh-CN')} +
+ ))} +
+
+ osm2streets 参考面 + + {comparison.osm2streetsAvailable === true + ? `${Number(comparison.osm2streetsRoadSurfaceFeatures || 0)} 个` + : '未提供'} + +
+ {severity && ( +
+ 编译诊断 + {Object.entries(severity).map(([level, count]) => ( + + {level === 'error' ? '错误' : level === 'warning' ? '警告' : '提示'} {count} + + ))} +
+ )} +
+ ); +} function App() { const [state, setState] = useState(); const [selected, setSelected] = useState(null); @@ -137,14 +180,7 @@ function App() { ))}

当前编译概览

-
- {Object.entries(state.comparison).map(([key, value]) => ( - <> -
{key}
-
{String(value)}
- - ))} -
+

待检查问题

diff --git a/workbench/client/src/map/layers.ts b/workbench/client/src/map/layers.ts index 5deea3a..0b7669f 100644 --- a/workbench/client/src/map/layers.ts +++ b/workbench/client/src/map/layers.ts @@ -15,7 +15,6 @@ const geojson = new GeoJSON(); const source = () => new VectorSource(); export type LayerName = | 'reference' - | 'gaodeReference' | 'native' | 'sidewalks' | 'osm' @@ -34,7 +33,6 @@ export function createLayers(onRoad: () => Road | null, scene: () => boolean) { new Style({ fill: new Fill({ color: `${color}55` }), stroke: new Stroke({ color, width }) }); const layers: Record> = { reference: new VectorLayer({ source: source(), visible: false, style: simple('#8999a0') }), - gaodeReference: new VectorLayer({ source: source(), style: simple('#2563eb', 1.5) }), native: new VectorLayer({ source: source(), style: () => (scene() ? new Style({ fill: new Fill({ color: '#3f4b50' }) }) : simple('#296956')), @@ -72,7 +70,15 @@ export function createLayers(onRoad: () => Road | null, scene: () => boolean) { }), centerLines: new VectorLayer({ source: source(), - style: new Style({ fill: new Fill({ color: '#f5be2a' }), stroke: new Stroke({ color: '#d29d16', width: 1 }) }), + style: (feature) => { + const white = feature.get('color') === 'white'; + const color = white ? '#faf9ee' : '#f5be2a'; + const solid = feature.get('pattern') === 'solid'; + return new Style({ + fill: new Fill({ color }), + stroke: new Stroke({ color: solid ? color : white ? '#aeb0aa' : '#d29d16', width: solid ? 0.25 : 0.8 }), + }); + }, }), controls: new VectorLayer({ source: source(), @@ -126,7 +132,6 @@ export function updateLayers(layers: ReturnType, state: Wor target.addFeatures(features(value)); }; put('reference', state.layers.osm2streetsRoadSurface); - put('gaodeReference', state.junctionReference?.converted); put('native', state.layers.nativeRoadSurface); get('native').addFeatures(features(state.layers.nativeIntersectionSurface)); put('sidewalks', state.layers.nativeSidewalkSurface);