This commit is contained in:
2026-09-15 01:12:50 +08:00
parent 2db889ad89
commit 1a75503105
99 changed files with 4168 additions and 726 deletions
@@ -87,7 +87,7 @@
<article data-uid="Anatomy-Execution">
<h1 id="execution-page">Execution Page</h1>
<p>The Execution page is the run cockpit: the simulation plays here, and every panel on it reads the run. It is the app's landing route — <code>/</code> redirects to <code>/execution</code> — and its Control Tree, the <strong>Execution</strong> root with <strong>Mission</strong> and <strong>Program</strong> beneath it, rides the <code>?tree=</code> query, so <code>/execution?tree=execution/mission</code> deep-links the Mission editor.</p>
<p>The Execution page is the run cockpit: the simulation plays here, and every panel on it reads the run. It is the app's landing route — <code>/</code> redirects to <code>/execution</code> — and its Control Tree — two roots, <strong>Mission</strong> above <strong>Program</strong> — rides the <code>?tree=</code> query, so <code>/execution?tree=execution/mission</code> deep-links the Mission editor.</p>
<div class="NOTE">
<h5>Note</h5>
<p>The app says <strong>Execution</strong> throughout: the route <code>/execution</code>, the REST endpoints (<code>/api/Execution/*</code>), the status hub (<code>/executionStatusHub</code>) and the stored layout (<code>UserConfig.ExecutionDivConfig</code>). The HiAPI engine keeps its own library vocabulary — <a class="xref" href="../../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_PlayerCommand">PlayerCommand</a> <small>(API)</small> and <a class="xref" href="../../api/Hi.Common.PacePlayer.html">PacePlayer</a> <small>(API)</small> — which is a different codebase's naming, not an inconsistency here.</p>
@@ -101,16 +101,16 @@
<h2 id="layout">Layout</h2>
<p>Four columns, left to right. The two dock dividers are pixel-sized, so dragging one moves only that dock's edge while the flexible middle absorbs the change.</p>
<ul>
<li><strong>Left dock</strong> — the Control Tree over the primary editor panel for the selected tree node. The <a href="execution-tool-bar.html">Execution Tool Bar</a> — the transport buttons — sits atop that panel and is shown for the Execution root and every node under it.</li>
<li><strong>Left dock</strong> — the Control Tree over the primary editor panel for the selected tree node. The tree pane opens with a run header pinned above its rows: the <a href="execution-tool-bar.html">Execution Tool Bar</a> — the transport buttons — with the live status badge to its right. The editor panel below holds the editor alone.</li>
<li><strong>Main</strong> — the <a class="xref" href="../../technique/rendering/rendering-canvas.html">RenderingCanvas</a> over the <a class="xref" href="../shell/session-message-panel.html">Session Message Panel</a>, stacked as collapsible panels with a draggable divider between them. The canvas panel's header adopts the <a class="xref" href="../widget/renderingcanvas-tool-bar.html">RenderingCanvas Tool Bar</a> and the <a href="execution-extended-renderingcanvas-tool-bar.html">Execution Extended RenderingCanvas Tool Bar</a>.</li>
<li><strong>Strip Charts</strong> — the strip-chart group bar over the three <a href="strip-charts.html">Strip Charts</a>: Availability Chart, Surface Roughness Chart and Color Index Time Chart.</li>
<li><strong>Step Info</strong> — <em>Sentence Syntax</em> as its own region (an NC sentence need not map to any machining step, so it is not a member of the step-based panels), then the Step Info group bar, then <a href="selected-step-info-panel.html">Step Properties</a>, <em>CWE</em> (cutter–workpiece engagement) and the four <a href="cycle-line-charts.html">Cycle-Line Charts</a>.</li>
</ul>
<p>The four columns are toggled from the app menu bar; the panels inside them collapse in place from their own expansion headers. The canvas stays mounted while collapsed so its rendering connection survives, and its engine is paused rather than torn down. The page itself also stays mounted while the user is on another route: the shell wraps the router view in a <code>keep-alive</code> keyed on the project epoch, so navigating away pauses the canvas but keeps the page — and its connection — alive until the loaded project changes.</p>
<h2 id="control-tree">Control Tree</h2>
<p>The page hosts an <code>execution</code>-scoped Control Tree: an <strong>Execution</strong> root with the <strong>Mission</strong> branch above the <strong>Program</strong> branch. Selecting a node fills the primary editor pane below the tree, and the <a href="execution-tool-bar.html">Execution Tool Bar</a> is mounted on top of that pane whenever the selected id is <code>execution</code> or starts with <code>execution/</code> — so the transport stays reachable from every node of this tree.</p>
<p><strong>Execution root</strong> is the cockpit's home: a short orientation panel, because the controls it would otherwise hold live where they act — the transport on the primary pane's header, the panel switches on each panel's own expansion header, the column switches on the nav bar. The live run state rides the tree itself: the Execution tree item carries a status badge fed by <code>/executionStatusHub</code>.</p>
<p><strong>Mission</strong> (<code>execution/mission</code>) is the editable command list a run executes — the project's <a class="xref" href="../../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_PlayerCommand">PlayerCommand</a> <small>(API)</small>, always a list, with nested lists read as sub-trees. Its ItemType registry supplies the tree checkbox that decides whether a command runs. The branch root is the entry-list editor — Add Command over a drag-reorderable row list with up / down / duplicate / delete — each command entry gets a control bar over that kind's own editor, and each of the kind's remaining setting groups becomes a section child of the command node. Every command type has its own page under <a href="mission/index.html">Mission</a>.</p>
<p>The page hosts an <code>execution</code>-scoped Control Tree with two roots and no wrapper node over them: the <strong>Mission</strong> branch above the <strong>Program</strong> branch. Node ids keep the <code>execution/</code> prefix (<code>execution/mission</code>, <code>execution/program/…</code>) because that first segment is the page-scope key — <code>?tree=</code> routing and the remembered last selection hang off it — not a parent row; a bare <code>?tree=execution</code> resolves to <code>execution/mission</code>, and a URL with no <code>?tree=</code> lands on the remembered selection or, failing that, on Mission. Selecting a node fills the primary editor pane below the tree; that pane holds nothing but the selected node's editor.</p>
<p><strong>Run header.</strong> The tree pane opens, on this page only, with a row pinned above the tree scroller: the <a href="execution-tool-bar.html">Execution Tool Bar</a> — the page's sole transport, which therefore owns the F5–F8 shortcuts — and, to its right, the status badge fed by <code>/executionStatusHub</code>. It sits inside the pane rather than on the dock's expansion header because that header is shared with General Setup, which renders neither piece. The button strip is the only shrinkable child, so narrowing the tree column scrolls the buttons away while the badge stays in view; the dock keeps the tree row mounted while collapsed, so the transport and its shortcuts survive a collapsed row. The other controls the cockpit needs live where they act — the panel switches on each panel's own expansion header, the column switches on the app menu bar.</p>
<p><strong>Mission</strong> (<code>execution/mission</code>) is the editable command list a run executes — the project's <a class="xref" href="../../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_PlayerCommand">PlayerCommand</a> <small>(API)</small>, always a list, with nested lists read as sub-trees. Its ItemType registry supplies the tree checkbox that decides whether a command runs. Every row-level structural op lives on the tree rows, not in a panel: each command row carries a drag handle and — revealed on hover and on the selected row — move up / move down / duplicate / delete; every list row, the Mission root included, carries an always-visible <strong>+</strong> (Add Command) that opens the command catalog and inserts the pick right after that list's focused command (the last selected or last added), else at the list's tail. The one panel-side insert is the Program File editor's <a href="mission/NcFileCommand-panel.html#multi-pick-fan-out">multi-pick fan-out</a>: each extra pick becomes a new Program File command right after that command in its own list, and the panel reports the insert range to the host, which treats it as a structural op like any row op — the same busy gate, the same carry-over of index-based ids onto the new siblings, the same rebuild scoped to the owning list. Dropping a dragged row on another command row's edge reorders it within its list or relocates it into the target row's list; dropping on a List row's middle band or on the Mission root row appends it into that list. The host runs all five ops through one path — a busy gate that holds tree selection, the checkboxes and further drags read-only while an op is in flight; the open editor's dirty-switch gate, which can refuse the op: a Script Command with unsaved edits asks <strong>Save &amp; switch</strong> / <strong>Discard</strong> / <strong>Cancel</strong>, while an NC Code editor or a List title sends its pending save without asking, and either one answers no when the user cancels or the save does not land — a refused gate drops the op and toasts that the open editor keeps its unsaved edits, which is why a delete that was already confirmed can still leave its row in place; then the API call, a rebuild scoped to the list it rewrote (the nearest list above both, for a move across lists), then the selection. The selection moves only when it already rode on the acted-on row — that row, or a section or nested entry under it: it follows a moved command, lands on the clone of a duplicated one, and after a delete lands on the nearest surviving entry of that list or, once the list is empty, on the owning list row; a selection riding elsewhere stays on its own re-indexed row, and Add Command never moves it at all — only the Add focus moves, onto the new row, so a run of adds chains in order. The root's own panel is informational — what the tree cannot say: a no-project note while no project is loaded, otherwise the command count and, while it is zero, a prompt to click Add Command; the run-order hint closes it either way. A command node's panel is that kind's own editor (a List shows only its optional Title; its entries are its tree children), and each of the kind's remaining setting groups becomes a section child of the command node. Every command type has its own page under <a href="mission/index.html">Mission</a>.</p>
<p><strong>Program</strong> (<code>execution/program</code>) is the read-only inspection twin of Mission: one node per NC source file the session read, its passes and execution marks filled in from run data rather than typed in. Its nodes, its per-pass line and mark views, and the status changes that rebuild it are on <a href="program.html">Program Branch</a>.</p>
<p>Selection and URL are synced two ways through the <code>tree</code> query argument: the URL's <code>?tree=</code> is adopted once the tree is built, and every selection change replaces it. A <code>?tree=</code> id belonging to another page's tree redirects to that page (<code>routeForTreeId</code>), and <code>/mission</code> lands on <code>/execution?tree=execution/mission</code>.</p>
<h2 id="renderingcanvas-behavior">RenderingCanvas Behavior</h2>
@@ -129,18 +129,19 @@
<ul>
<li><code>wwwroot-src/src/pages/ExecutionPage.vue</code> — the routed page at <code>/execution</code>: the four columns, their pixel / ratio splitters, the panel-expansion stacks, and the <code>execution</code>-scoped Control Tree host it provides.</li>
<li><code>wwwroot-src/src/router/routes.ts</code> — the <code>/</code> → <code>execution</code> redirect, the <code>execution</code> route, and the <code>/mission</code> redirect to <code>/execution?tree=execution/mission</code>.</li>
<li><code>wwwroot-src/src/router/treeRoutes.ts</code> — <code>routeForTreeId</code>, which lands a <code>?tree=</code> id on the page that owns that branch.</li>
<li><code>wwwroot-src/src/components/controlTree/useControlTreeHost.ts</code> — the Control Tree state machine: <code>buildExecutionRoot()</code> builds the <code>execution</code> root holding <code>execution/mission</code> above <code>execution/program</code>, syncs <code>?tree=</code>, and re-reads the Program branch whenever the broadcast execution status changes.</li>
<li><code>wwwroot-src/src/components/controlTree/ControlTreeDock.vue</code> — the left dock: the Control Tree row over the primary editor row.</li>
<li><code>wwwroot-src/src/components/controlTree/ControlTreePanel.vue</code> — the tree pane; carries the live execution-status badge on the Execution tree item.</li>
<li><code>wwwroot-src/src/components/controlTree/PrimarySlavePanel.vue</code> — the primary editor pane for the selected node; mounts the Execution Tool Bar on top whenever the selection is <code>execution</code> or a descendant.</li>
<li><code>wwwroot-src/src/components/controlTree/ExecutionRootPanel.vue</code> — the editor panel of the Execution root node.</li>
<li><code>wwwroot-src/src/router/treeRoutes.ts</code> — <code>migrateLegacyTreeId</code>, which folds legacy ids onto the current ones (a bare <code>execution</code> becomes <code>execution/mission</code>), and <code>routeForTreeId</code>, which runs that migration first and then lands a <code>?tree=</code> id on the page that owns its first segment.</li>
<li><code>wwwroot-src/src/components/controlTree/useControlTreeHost.ts</code> — the Control Tree state machine: <code>buildExecutionRoots()</code> builds the two roots, <code>execution/mission</code> above <code>execution/program</code>; <code>landingSelection()</code> picks the remembered selection or the first root; the <code>?tree=</code> sync; the Program branch re-read on every broadcast execution-status change; and the five mission row ops — add, drag move, step, duplicate, delete — through one <code>missionRowOp</code> helper that owns the busy gate, the dirty-switch gate (a refusal drops the op and toasts it), the scoped rebuild and the post-op selection.</li>
<li><code>wwwroot-src/src/components/controlTree/useMissionTreeDrag.ts</code> — the HTML5 drag-and-drop bookkeeping between Mission rows: the edge / into drop modes and the row indicator classes; the move itself is the host's.</li>
<li><code>wwwroot-src/src/components/controlTree/ControlTreeDock.vue</code> — the left dock: the Control Tree row over the primary editor row, each kept mounted while collapsed; the tree row's expansion header is the same on both tree pages, so nothing run-specific rides it.</li>
<li><code>wwwroot-src/src/components/controlTree/ControlTreePanel.vue</code> — the tree pane; on the Execution page it pins the run header — the Execution Tool Bar and the live status badge — above the tree scroller, and renders the Mission rows' drag handle, the hover-revealed row ops and the Add Command <strong>+</strong> on every list row.</li>
<li><code>wwwroot-src/src/components/controlTree/AddCommandDialog.vue</code> — the search-first command catalog the <strong>+</strong> opens, fed by <code>GET /api/Mission/command-catalog</code>; one pick per opening.</li>
<li><code>wwwroot-src/src/components/controlTree/PrimarySlavePanel.vue</code> — the primary editor pane shared by both tree pages: it mounts the selected node's registry panel, or one of the three inline root panels it carries for General Setup's equipment roots (Machine Tool, Fixture, Workpiece — object management plus a summary), which no Execution node ever selects; here it shows the registry panel alone, and hands that panel's dirty-switch gate to the host.</li>
</ul>
<p>Mission branch:</p>
<ul>
<li><code>wwwroot-src/src/components/controlTree/missionItemTypes.ts</code> — the branch's ItemType registry and the per-command enable ticks.</li>
<li><code>wwwroot-src/src/components/controlTree/MissionRootPanel.vue</code> — the entry-list editor of a list command, serving the branch root and every nested list.</li>
<li><code>wwwroot-src/src/components/controlTree/MissionCommandSlavePanel.vue</code> — the per-command editor host.</li>
<li><code>wwwroot-src/src/components/controlTree/MissionRootPanel.vue</code> — the Mission root's informational panel: a no-project note while no project is loaded, otherwise the command count and a &ldquo;No commands yet&rdquo; prompt while it is zero, and the run-order hint in every state.</li>
<li><code>wwwroot-src/src/components/controlTree/MissionCommandSlavePanel.vue</code> — the per-command editor host; a List command shows only its optional Title.</li>
<li><code>wwwroot-src/src/components/controlTree/MissionSectionPanel.vue</code> — one setting section of a command.</li>
</ul>
<p>Program branch (see the dedicated anatomy page for details):</p>
@@ -150,7 +151,7 @@
<p>Panels and canvas:</p>
<ul>
<li><code>wwwroot-src/src/components/RenderingCanvas.vue</code> — the browser canvas and its <code>/renderingHub</code> connection.</li>
<li><code>wwwroot-src/src/components/execution/ExecutionToolBar.vue</code> — the transport controls.</li>
<li><code>wwwroot-src/src/components/execution/ExecutionToolBar.vue</code> — the transport controls; the page's one instance, mounted in the tree pane's run header, registers F5–F8.</li>
<li><code>wwwroot-src/src/components/execution/ExecutionExtendedToolBar.vue</code> — the view and rendering-flag controls adopted onto the canvas panel's header.</li>
<li><code>wwwroot-src/src/components/execution/SelectedStepInfoPanel.vue</code> — Step Properties.</li>
<li><code>wwwroot-src/src/components/execution/StepVolumePanel.vue</code> — the CWE panel.</li>
@@ -173,7 +174,7 @@
<p>Backends:</p>
<ul>
<li><code>Execution/ExecutionController.cs</code> — <code>POST /api/Execution/start | pause | resume | run-line | run-step | stop | reset</code>; <code>GET status</code>, <code>status/{connectionId}</code>, <code>project-status</code>, <code>selected-step-info</code> and <code>cl-strip-dots</code>; the canvas actions <code>initialize/{connectionId}</code> (binds the displayee and calls <code>SetViewToHomeView</code>) and <code>fit-view/{connectionId}</code>; and the <code>step-volume/{connectionId}</code> family behind the CWE panel.</li>
<li><code>Execution/ExecutionStatusHub.cs</code> + <code>Execution/ExecutionStatusService.cs</code> — <code>/executionStatusHub</code>, the run-state broadcast that drives the transport and the tree badge.</li>
<li><code>Execution/ExecutionStatusHub.cs</code> + <code>Execution/ExecutionStatusService.cs</code> — <code>/executionStatusHub</code>, the run-state broadcast that drives the transport and the run header's badge.</li>
<li><code>Execution/SessionSinkHub.cs</code> + <code>Execution/SessionSinkBroadcastService.cs</code> — one hub per message sink (<code>/shellMessageHub</code>, <code>/ncDiagnosticHub</code>, <code>/stepDiagnosticHub</code>, <code>/ncManipulationDiagnosticHub</code>), so a client subscribes to exactly the sink it wants.</li>
<li><code>Execution/SelectedStepInfoService.cs</code> — the selected-step payload. It has no hub of its own: the &ldquo;selection changed&rdquo; push rides <code>/clStripHub</code>.</li>
<li><code>Execution/ClStripController.cs</code> + <code>Execution/ClStripHub.cs</code> + <code>Execution/ClStripBroadcastService.cs</code> — CL-strip range state and the zoom / pan / select / enter broadcasts.</li>
@@ -197,10 +198,10 @@
</ol>
</div>
<h2 id="pages">Pages</h2>
<p>Ordered as the cockpit reads: the two tool bars across the top, the step column and the charts down
the side, the menus and dialogs they open, then the Control-Tree branch the page hosts.</p>
<p>Ordered as the cockpit reads: the two tool bars — the transport pinned in the Control Tree pane's run header, the extended controls on the canvas panel's header — then the step column and the charts down
the side, the menus and dialogs they open, then the two Control-Tree branches the page hosts.</p>
<ul>
<li><a href="execution-tool-bar.html">Execution Tool Bar</a> — The transport controls on the primary panel header, and the status they read</li>
<li><a href="execution-tool-bar.html">Execution Tool Bar</a> — The transport controls in the Control Tree pane's run header, and the status they read</li>
<li><a href="execution-extended-renderingcanvas-tool-bar.html">Execution Extended RenderingCanvas Tool Bar</a> — The run-specific canvas controls: the CL strip, fit view and the Scene menu</li>
<li><a href="selected-step-info-panel.html">Selected-Step Info Panel</a> — The Step Properties panel in the Step Info column</li>
<li><a href="strip-charts.html">Strip Charts</a> — The whole-program charts in the Strip Charts column</li>