接入 INI 面板浏览器状态 report getter

This commit is contained in:
2026-06-14 22:10:57 +08:00
parent 5b45491e55
commit 404cb1344c
4 changed files with 147 additions and 13 deletions

View File

@@ -624,3 +624,73 @@ host_wasm_opfs_browser_smokes=ok
- 复制、下载、对外 API - 复制、下载、对外 API
当前阶段先继续补 workflow 和 report后面再把它整理成一版面向“控制网页界面”的 roadmap。 当前阶段先继续补 workflow 和 report后面再把它整理成一版面向“控制网页界面”的 roadmap。
五、2026-06-14 继续执行记录INI panel browser state report getter
本轮按“导出层”第一步推进,把 `MachineSessionStateReport` 接入真实浏览器 INI panel
流程,提供明确的上层 UI/API 读取入口,避免继续让消费者直接抓 DOM 或读取临时
`window.linuxCncIniPanelMachineSessionState`。
完成内容:
- `wasm-port/runtime/ui/ini-panel/app.js` 新增并暴露
`window.getMachineSessionStateReport()`
- getter 每次调用 `createMachineSessionStateReport(window.linuxCncIniPanelMachineSessionState)`
返回当前稳定 report
- `wasm-port/tests/browser/ini_panel_smoke.html` 在真实 save、restore-load、run
流程后读取 report并验证
- snapshot label
- G-code OPFS path
- loaded INI/parameter WASM path
- selected program source/path
- run status
- canonical-event 和 motion snapshot count
- last action 与 error
- `wasm-port/docs/ui-panel-state-summary.md` 明确上层 UI/API 应读取
`createMachineSessionStateReport(...)` 或 `window.getMachineSessionStateReport()`
不应抓 DOM 或直接依赖临时 window state
- 未新增下载/复制按钮,先稳定 API 入口;
- 未改变 INI panel OPFS bridge、snapshot-store、machine-file-store、LinuxCNC
interpreter、G-code 文本、canonical-event 语义、tool、parameter、planner 或
LinuxCNC-owned runtime semantics。
验证已通过:
```bash
git diff --check
wasm-port/tools/verify_vendor_sync.sh
wasm-port/tools/verify_no_standalone_cnc_semantics.sh
wasm-port/tests/ui/node/verify_ui_node_smokes.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_interp_wasm.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh
wasm-port/tests/host/verify_host_smokes.sh
```
关键输出:
```text
vendor sync up to date
standalone CNC semantics guard complete
ini_panel_run_summary_node_smoke=ok
ini_panel_run_workflow_node_smoke=ok
ini_panel_session_summary_node_smoke=ok
ini_panel_session_workflow_node_smoke=ok
ini_panel_machine_file_summary_node_smoke=ok
ini_panel_state_summary_node_smoke=ok
ui_node_smokes=ok
browser_ini_opfs_smoke=ok
interp_wasm_node_smoke=ok
sim_configs_wasm_node_inventory_executed=28
sim_configs_wasm_node_inventory_passed=28
sim_configs_wasm_node_inventory_skipped=131
sim_configs_wasm_node_inventory_unexpected_fail=0
host_wasm_opfs_browser_smokes=ok
```
下一步建议:
继续沿“导出层/控制网页界面”roadmap 推进。下一批可以在不新增复杂 UI 按钮的前提下,
补一个更靠近上层消费者的 report export helper 或 SDK-facing wrapper例如把 report
序列化成稳定 JSON 文本/Blob 输入;仍只组合已有 host/runtime boundary facts不解析
G-code、不推导 CNC 语义、不读取 DOM。

View File

@@ -11,6 +11,10 @@ objects produced by the run/session/machine-file helpers and the visible badge
state so browser tests or future UI consumers can compare panel state without state so browser tests or future UI consumers can compare panel state without
reading ad hoc DOM text. reading ad hoc DOM text.
Upper-level UI/API consumers should read `createMachineSessionStateReport(...)`
or `window.getMachineSessionStateReport()` rather than scraping DOM nodes or
depending on `window.linuxCncIniPanelMachineSessionState` directly.
## `createIniPanelStateSummary(input)` ## `createIniPanelStateSummary(input)`
`input` may contain: `input` may contain:

View File

@@ -47,6 +47,7 @@ import {
} from "./session-workflow.js"; } from "./session-workflow.js";
import { import {
createMachineSessionStateSnapshot, createMachineSessionStateSnapshot,
createMachineSessionStateReport,
} from "./panel-state-summary.js"; } from "./panel-state-summary.js";
const SAMPLE_PATH = const SAMPLE_PATH =
@@ -151,6 +152,10 @@ let canonicalEventText = "";
let runPlaybackTimer = null; let runPlaybackTimer = null;
let panelMachineSessionState = createMachineSessionStateSnapshot(); let panelMachineSessionState = createMachineSessionStateSnapshot();
function getMachineSessionStateReport() {
return createMachineSessionStateReport(window.linuxCncIniPanelMachineSessionState);
}
function updatePanelMachineSessionState(patch = {}) { function updatePanelMachineSessionState(patch = {}) {
panelMachineSessionState = createMachineSessionStateSnapshot({ panelMachineSessionState = createMachineSessionStateSnapshot({
...panelMachineSessionState, ...panelMachineSessionState,
@@ -164,6 +169,9 @@ function updatePanelMachineSessionState(patch = {}) {
return panelMachineSessionState; return panelMachineSessionState;
} }
window.getMachineSessionStateReport = getMachineSessionStateReport;
window.linuxCncIniPanelMachineSessionState = panelMachineSessionState;
function setBadge(node, text, className = "badge") { function setBadge(node, text, className = "badge") {
node.className = className; node.className = className;
node.textContent = text; node.textContent = text;

View File

@@ -493,6 +493,22 @@ TOOL_TABLE = browser-tool.tbl
) { ) {
throw new Error(`UI saved snapshot log missing metadata summary: ${savedSnapshotLog}`); throw new Error(`UI saved snapshot log missing metadata summary: ${savedSnapshotLog}`);
} }
const savedMachineSessionStateReport = uiDocument.defaultView.getMachineSessionStateReport();
assertEqual(
savedMachineSessionStateReport.session.snapshotLabel,
"ui-machine-session/ui-machine-session.json",
"UI saved machine session state report snapshot label",
);
assertEqual(
savedMachineSessionStateReport.session.gcode,
"linuxcnc/gcode/ui-session.ngc",
"UI saved machine session state report G-code path",
);
assertEqual(
savedMachineSessionStateReport.status.lastAction,
"save-session-snapshot",
"UI saved machine session state report last action",
);
const savedUiSnapshot = await loadMachineSessionSnapshot( const savedUiSnapshot = await loadMachineSessionSnapshot(
"ui-machine-session", "ui-machine-session",
"xyzab-tdr", "xyzab-tdr",
@@ -572,6 +588,27 @@ TOOL_TABLE = browser-tool.tbl
) { ) {
throw new Error(`UI restore/load session log missing OPFS default file mapping: ${uiLog}`); throw new Error(`UI restore/load session log missing OPFS default file mapping: ${uiLog}`);
} }
const restoredLoadedMachineSessionStateReport = uiDocument.defaultView.getMachineSessionStateReport();
assertEqual(
restoredLoadedMachineSessionStateReport.session.snapshotLabel,
"ui-machine-session/ui-machine-session.json",
"UI restored loaded machine session state report snapshot label",
);
assertEqual(
restoredLoadedMachineSessionStateReport.loaded.iniWasmPath,
"/work/session-machine.ini",
"UI restored loaded machine session state report loaded INI WASM path",
);
assertEqual(
restoredLoadedMachineSessionStateReport.loaded.parameterWasmPath,
"/work/session-linuxcnc.var",
"UI restored loaded machine session state report loaded parameter WASM path",
);
assertEqual(
restoredLoadedMachineSessionStateReport.status.lastAction,
"restore-load-session",
"UI restored loaded machine session state report last action",
);
uiDocument.getElementById("run-gcode").click(); uiDocument.getElementById("run-gcode").click();
await waitFor( await waitFor(
() => uiDocument.getElementById("log")?.textContent.includes("Ran G-code"), () => uiDocument.getElementById("log")?.textContent.includes("Ran G-code"),
@@ -660,36 +697,51 @@ TOOL_TABLE = browser-tool.tbl
2, 2,
"UI snapshot run summary motion snapshot count", "UI snapshot run summary motion snapshot count",
); );
const machineSessionState = uiDocument.defaultView.linuxCncIniPanelMachineSessionState; const machineSessionStateReport = uiDocument.defaultView.getMachineSessionStateReport();
assertEqual( assertEqual(
machineSessionState.lastAction, machineSessionStateReport.status.lastAction,
"run-gcode", "run-gcode",
"UI machine session state last action", "UI machine session state report last action",
); );
assertEqual( assertEqual(
machineSessionState.selectedProgram.opfsPath, machineSessionStateReport.program.opfsPath,
"linuxcnc/gcode/ui-session.ngc", "linuxcnc/gcode/ui-session.ngc",
"UI machine session state selected program OPFS path", "UI machine session state report selected program OPFS path",
); );
assertEqual( assertEqual(
machineSessionState.sessionLoad.iniWasmPath, machineSessionStateReport.loaded.iniWasmPath,
"/work/session-machine.ini", "/work/session-machine.ini",
"UI machine session state loaded INI WASM path", "UI machine session state report loaded INI WASM path",
); );
assertEqual( assertEqual(
machineSessionState.run.programSource, machineSessionStateReport.program.source,
"snapshot", "snapshot",
"UI machine session state run source", "UI machine session state report run source",
); );
assertEqual( assertEqual(
machineSessionState.fields.runWorkflow, machineSessionStateReport.session.workflow,
"save-session-snapshot", "save-session-snapshot",
"UI machine session state run workflow field", "UI machine session state report workflow",
); );
assertEqual( assertEqual(
machineSessionState.error, machineSessionStateReport.status.error,
null, null,
"UI machine session state error", "UI machine session state report error",
);
assertEqual(
machineSessionStateReport.run.status,
"ok",
"UI machine session state report run status",
);
assertEqual(
machineSessionStateReport.run.canonicalEventCount,
2,
"UI machine session state report canonical event count",
);
assertEqual(
machineSessionStateReport.run.motionSnapshotCount,
2,
"UI machine session state report motion snapshot count",
); );
if ( if (
!runLog.includes("canon_event=STRAIGHT_TRAVERSE") || !runLog.includes("canon_event=STRAIGHT_TRAVERSE") ||