fix: avoid map refresh on road selection
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. 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."}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. 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."}
|
||||||
16
.trellis/tasks/08-26-workbench-selection-save-fix/prd.md
Normal file
16
.trellis/tasks/08-26-workbench-selection-save-fix/prd.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# 修复工作台选择与保存回归
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
道路选择只更新选择高亮,不重置地图数据或视图;保存修改后可靠保留并重新编译 overrides。
|
||||||
|
|
||||||
|
## Confirmed Cause
|
||||||
|
|
||||||
|
`MapCanvas` 使用 `[state, selected]` 更新全量 source 和 fit view,选择道路会触发全图重载。Road override 的前后端 schema 一致,因此保存回归需在 UI 操作后验证其状态同步和编译调用。
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- 选择道路不会清空 source、重新 fit 地图或改变视图。
|
||||||
|
- 仅选择高亮 layer 更新;选择相关 OSM 线条样式仍刷新。
|
||||||
|
- 暂存、保存、重新编译的 overrides 正确发送并以服务端响应更新状态。
|
||||||
|
- 格式化、类型检查和构建通过。
|
||||||
26
.trellis/tasks/08-26-workbench-selection-save-fix/task.json
Normal file
26
.trellis/tasks/08-26-workbench-selection-save-fix/task.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"id": "workbench-selection-save-fix",
|
||||||
|
"name": "workbench-selection-save-fix",
|
||||||
|
"title": "修复工作台选择与保存回归",
|
||||||
|
"description": "修复道路选择触发全图层重建,并排查修复 React 工作台保存 overrides 回归",
|
||||||
|
"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": {}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import View from 'ol/View';
|
|||||||
import Select from 'ol/interaction/Select';
|
import Select from 'ol/interaction/Select';
|
||||||
import { click } from 'ol/events/condition';
|
import { click } from 'ol/events/condition';
|
||||||
import type { Road, WorkbenchState } from '../types/state';
|
import type { Road, WorkbenchState } from '../types/state';
|
||||||
import { createLayers, updateLayers, type LayerName } from '../map/layers';
|
import { createLayers, updateLayers, updateSelectedRoad, type LayerName } from '../map/layers';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
state: WorkbenchState;
|
state: WorkbenchState;
|
||||||
@@ -72,7 +72,13 @@ export function MapCanvas({ state, selected, visible, scene, onSelectRoad, onFea
|
|||||||
updateLayers(layers, state, selected);
|
updateLayers(layers, state, selected);
|
||||||
const extent = layers.osm.getSource()!.getExtent();
|
const extent = layers.osm.getSource()!.getExtent();
|
||||||
if (extent && Number.isFinite(extent[0])) map.getView().fit(extent, { padding: [48, 48, 48, 48], maxZoom: 19 });
|
if (extent && Number.isFinite(extent[0])) map.getView().fit(extent, { padding: [48, 48, 48, 48], maxZoom: 19 });
|
||||||
}, [state, selected]);
|
}, [state]);
|
||||||
|
useEffect(() => {
|
||||||
|
const layers = layersRef.current;
|
||||||
|
if (!layers) return;
|
||||||
|
updateSelectedRoad(layers, selected);
|
||||||
|
layers.osm.changed();
|
||||||
|
}, [selected]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const layers = layersRef.current;
|
const layers = layersRef.current;
|
||||||
if (!layers) return;
|
if (!layers) return;
|
||||||
|
|||||||
@@ -157,9 +157,14 @@ export function updateLayers(layers: ReturnType<typeof createLayers>, state: Wor
|
|||||||
.filter((item) => item.geometry)
|
.filter((item) => item.geometry)
|
||||||
.map(({ geometry, ...properties }) => ({ type: 'Feature', properties, geometry: geometry! })),
|
.map(({ geometry, ...properties }) => ({ type: 'Feature', properties, geometry: geometry! })),
|
||||||
});
|
});
|
||||||
put('selectedRoad', { type: 'FeatureCollection', features: [] });
|
updateSelectedRoad(layers, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSelectedRoad(layers: ReturnType<typeof createLayers>, selected: Road | null) {
|
||||||
|
const source = layers.selectedRoad.getSource()!;
|
||||||
|
source.clear();
|
||||||
if (selected)
|
if (selected)
|
||||||
get('selectedRoad').addFeature(
|
source.addFeature(
|
||||||
new Feature({ geometry: new LineString(selected.centerline).transform('EPSG:4326', 'EPSG:3857') }),
|
new Feature({ geometry: new LineString(selected.centerline).transform('EPSG:4326', 'EPSG:3857') }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user