From be3d2ac3afa68dad53e96577d9303e9977c030b3 Mon Sep 17 00:00:00 2001 From: Yoilun Date: Mon, 27 Apr 2026 12:55:46 +0800 Subject: [PATCH] fix: preserve calibration draft on refresh --- web/src/main.js | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/web/src/main.js b/web/src/main.js index e0ebf11..bc47fa3 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -2,6 +2,7 @@ import "./styles.css"; const zoneIds = ["r1c1", "r1c2", "r1c3", "r1c4", "r2c1", "r2c2", "r2c3", "r2c4"]; const allRegions = [...zoneIds, "trash"]; +const draftStorageKey = "cold-display-guard.calibrationDraft.v1"; const palette = { r1c1: "#d92d20", r1c2: "#b54708", @@ -133,6 +134,7 @@ const ctx = els.canvas.getContext("2d"); function boot() { wireEvents(); + loadDraftPolygons(); renderRegionList(); refreshAll(); } @@ -164,7 +166,9 @@ async function refreshAll() { state.summary = summary; state.events = events.items || []; fillForm(); - loadPolygonsFromConfig(false); + if (!hasAnyPolygon()) { + loadPolygonsFromConfig(false); + } render(); setStatus("已连接后端 19080"); } catch (error) { @@ -185,6 +189,7 @@ async function saveConfig() { }; state.config = await apiJson("/api/manage/config", {method: "PUT", body: payload}); const calibrationSaved = await persistCalibration({requireAny: false}); + saveDraftPolygons(); fillForm(); renderConfigPreview(); setStatus(calibrationSaved ? "配置和标定已保存" : "配置已保存;当前没有可保存的标定点"); @@ -228,6 +233,7 @@ async function saveCalibration() { try { const saved = await persistCalibration({requireAny: true}); if (saved) { + saveDraftPolygons(); render(); setStatus("标定已保存到项目配置"); } @@ -289,6 +295,7 @@ function loadPolygonsFromConfig(updateStatus = true) { if (Array.isArray(state.config.trash?.roi)) { state.polygons.trash = state.config.trash.roi.map(([x, y]) => ({x, y})); } + saveDraftPolygons(); render(); if (updateStatus) { setStatus("已载入当前配置区域"); @@ -335,6 +342,7 @@ function addPoint(event) { const x = clamp(rawX / imageRect.width); const y = clamp(rawY / imageRect.height); state.polygons[state.activeRegion].push({x: round(x), y: round(y)}); + saveDraftPolygons(); render(); } @@ -362,14 +370,44 @@ function getCanvasImageRect() { function undoPoint() { state.polygons[state.activeRegion].pop(); + saveDraftPolygons(); render(); } function clearRegion() { state.polygons[state.activeRegion] = []; + saveDraftPolygons(); render(); } +function hasAnyPolygon() { + return allRegions.some((id) => state.polygons[id].length > 0); +} + +function saveDraftPolygons() { + localStorage.setItem(draftStorageKey, JSON.stringify(state.polygons)); +} + +function loadDraftPolygons() { + const raw = localStorage.getItem(draftStorageKey); + if (!raw) { + return; + } + try { + const draft = JSON.parse(raw); + for (const id of allRegions) { + if (!Array.isArray(draft[id])) { + continue; + } + state.polygons[id] = draft[id] + .filter((point) => Number.isFinite(point.x) && Number.isFinite(point.y)) + .map((point) => ({x: clamp(point.x), y: clamp(point.y)})); + } + } catch { + localStorage.removeItem(draftStorageKey); + } +} + function drawCanvas() { ctx.clearRect(0, 0, els.canvas.width, els.canvas.height); if (state.image) {