完善云端RUN执行反馈

This commit is contained in:
2026-06-23 03:59:47 -04:00
parent bb71613051
commit 37604fa5b3
33 changed files with 3724 additions and 534 deletions

View File

@@ -59,6 +59,7 @@ function render(regions, state, dispatch) {
}
function renderTitlebar(element, state) {
const currentLine = currentGcodeExecutionLine(state);
element.innerHTML = `
<div class="brand-dot" aria-hidden="true">NS</div>
<div class="title-stack">
@@ -73,6 +74,10 @@ function renderTitlebar(element, state) {
`).join("")}
</select>
</label>
<div class="current-line-indicator" data-current-gcode-line="${currentLine}" data-current-gcode-source="${escapeHtml(currentGcodeLineSource(state))}">
<span>G-code line</span>
<strong>${currentLine}</strong>
</div>
<div class="run-state" data-run-state="${state.runState}">${state.runState}</div>
`;
element.querySelector('[data-action="select-profile"]').addEventListener("change", (event) => {
@@ -192,11 +197,20 @@ function droRow(axis, value, dtg) {
}
function renderGcode(element, state, dispatch) {
const currentLine = currentGcodeExecutionLine(state);
const rows = state.programLines
.map((line, index) => {
const lineNumber = state.programStartLine + index;
const execution = state.programLineExecution?.[lineNumber] || null;
const active = lineNumber === state.activeLine ? " active" : "";
return `<li class="gcode-row${active}" data-program-line="${lineNumber}"><span>${lineNumber}</span><code>${escapeHtml(line)}</code></li>`;
const status = execution?.status || (lineNumber < state.activeLine ? "done" : "pending");
return `
<li class="gcode-row${active}" data-program-line="${lineNumber}" data-line-status="${escapeHtml(status)}">
<span>${lineNumber}</span>
<code>${escapeHtml(line)}</code>
<small data-line-execution="${lineNumber}">${formatLineExecution(execution, active)}</small>
</li>
`;
})
.join("");
const programEndLine = state.programStartLine + Math.max(state.programLines.length - 1, 0);
@@ -210,7 +224,7 @@ function renderGcode(element, state, dispatch) {
<div class="gcode-header">
<strong>${escapeHtml(state.activeProgram)}</strong>
<span data-program-source="${state.programSource}">${state.programSource}</span>
<span data-active-program-line="${state.activeLine}">Current line ${state.activeLine}</span>
<span data-active-program-line="${currentLine}" data-current-gcode-line="${currentLine}">Executing line ${currentLine}</span>
</div>
<div class="linuxcnc-source-row" data-linuxcnc-gcode-source="row">
<label>
@@ -272,6 +286,19 @@ function renderGcode(element, state, dispatch) {
});
}
function currentGcodeExecutionLine(state) {
const feedbackLine = Number(state.programRuntimeFeedback?.line);
if (Number.isFinite(feedbackLine) && feedbackLine > 0) {
return feedbackLine;
}
const activeLine = Number(state.activeLine);
return Number.isFinite(activeLine) && activeLine > 0 ? activeLine : state.programStartLine;
}
function currentGcodeLineSource(state) {
return state.programRuntimeFeedback?.sourceMode || state.programExecutionSourceMode || "ui-state";
}
function renderLinuxCncGcodeSourceOptions(state) {
const sources = state.machineFileStaging.gcodeSources || [];
if (sources.length === 0) {
@@ -444,6 +471,21 @@ function formatProgramRuntimeDtg(state) {
return `DTG ${formatNumber(dtg.x, 3)} / ${formatNumber(dtg.y, 3)} / ${formatNumber(dtg.z, 3)} distance ${formatNumber(feedback.distanceToGo, 3)}`;
}
function formatLineExecution(execution, active) {
if (!execution) return active ? "running" : "pending";
const axes = execution.axisPose || {};
return [
execution.status || (active ? "running" : "done"),
`F ${formatNumber(execution.feed, 1)}`,
`X ${formatNumber(axes.x, 3)}`,
`Y ${formatNumber(axes.y, 3)}`,
`Z ${formatNumber(axes.z, 3)}`,
`A ${formatNumber(axes.a, 3)}`,
`C ${formatNumber(axes.c, 3)}`,
`cycle ${execution.taskCycle || 0}/${execution.servoCycle || 0}`,
].join(" | ");
}
function formatDuration(seconds) {
const safeSeconds = Math.max(Number(seconds) || 0, 0);
const minutes = Math.floor(safeSeconds / 60);
@@ -604,6 +646,7 @@ function renderBottomControls(element, state, dispatch) {
const controls = [
["Open", "OPEN", null],
["Reload", "RELOAD", () => dispatch({ type: "RELOAD_PROGRAM" })],
["Run Ready", "RUN_READY", () => dispatch({ type: "RUN_READY" })],
["Run", "RUN", () => dispatch({ type: "RUN" })],
["Stop", "STOP", () => dispatch({ type: "STOP" })],
["Pause", "PAUSE", () => dispatch({ type: "PAUSE" })],
@@ -659,6 +702,7 @@ function renderBottomControls(element, state, dispatch) {
function bottomControlGate(state, action) {
const actionMap = {
RUN: { type: "RUN" },
RUN_READY: { type: "UI_CONTROL" },
STEP: { type: "STEP" },
PAUSE: { type: "PAUSE" },
RESUME: { type: "RESUME" },