Archived
271 lines
18 KiB
HTML
271 lines
18 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Web Service SPA Source Tree | HiAPI-C# 2025 </title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="title" content="Web Service SPA Source Tree | HiAPI-C# 2025 ">
|
|
|
|
|
|
<link rel="icon" href="../../img/HiAPI.favicon.ico">
|
|
<link rel="stylesheet" href="../../public/docfx.min.css">
|
|
<link rel="stylesheet" href="../../public/main.css">
|
|
<meta name="docfx:navrel" content="../../toc.html">
|
|
<meta name="docfx:tocrel" content="toc.html">
|
|
|
|
<meta name="docfx:rel" content="../../">
|
|
|
|
|
|
|
|
<meta name="loc:inThisArticle" content="In this article">
|
|
<meta name="loc:searchResultsCount" content="{count} results for "{query}"">
|
|
<meta name="loc:searchNoResults" content="No results for "{query}"">
|
|
<meta name="loc:tocFilter" content="Filter by title">
|
|
<meta name="loc:nextArticle" content="Next">
|
|
<meta name="loc:prevArticle" content="Previous">
|
|
<meta name="loc:themeLight" content="Light">
|
|
<meta name="loc:themeDark" content="Dark">
|
|
<meta name="loc:themeAuto" content="Auto">
|
|
<meta name="loc:changeTheme" content="Change theme">
|
|
<meta name="loc:copy" content="Copy">
|
|
<meta name="loc:downloadPdf" content="Download PDF">
|
|
|
|
<script type="module" src="./../../public/docfx.min.js"></script>
|
|
|
|
<script>
|
|
const theme = localStorage.getItem('theme') || 'auto'
|
|
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
|
|
</script>
|
|
|
|
</head>
|
|
|
|
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
|
|
<header class="bg-body border-bottom">
|
|
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
|
|
<div class="container-xxl flex-nowrap">
|
|
<a class="navbar-brand" href="../../index.html">
|
|
<img id="logo" class="svg" src="../../img/HiAPI.logo.png" alt="">
|
|
|
|
</a>
|
|
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
|
|
<i class="bi bi-three-dots"></i>
|
|
</button>
|
|
<div class="collapse navbar-collapse" id="navpanel">
|
|
<div id="navbar">
|
|
<form class="search" role="search" id="search">
|
|
<i class="bi bi-search"></i>
|
|
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
</header>
|
|
|
|
<main class="container-xxl">
|
|
<div class="toc-offcanvas">
|
|
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
|
|
<div class="offcanvas-header">
|
|
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
|
|
</div>
|
|
<div class="offcanvas-body">
|
|
<nav class="toc" id="toc"></nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="content">
|
|
<div class="actionbar">
|
|
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
|
|
<i class="bi bi-list"></i>
|
|
</button>
|
|
|
|
<nav id="breadcrumb"></nav>
|
|
</div>
|
|
|
|
<article data-uid="Anatomy-BySource-WebserviceSpa">
|
|
<h1 id="web-service-spa-source-tree">Web Service SPA Source Tree</h1>
|
|
|
|
<p><code>HiNC-2025-webservice/wwwroot-src/src</code> is the flagship front end: a Quasar CLI single-page
|
|
application in Vue 3, TypeScript and Pinia, served by the same ASP.NET Core process that answers its
|
|
REST calls. Every page in Anatomy documents something in this tree or in the backend beside it.</p>
|
|
<p>Folders below follow the stock Quasar skeleton order, with the two places the skeleton breaks called
|
|
out where they occur.</p>
|
|
<h2 id="the-one-thing-to-know-first">The One Thing to Know First</h2>
|
|
<p><code>components/</code> is grouped <strong>both ways at the same level</strong>, and that is deliberate rather than untidy:</p>
|
|
<ul>
|
|
<li><strong>Page-scoped</strong> — <code>components/execution/</code> and half of <code>components/mech/</code> are chrome for exactly
|
|
one route.</li>
|
|
<li><strong>Domain-scoped</strong> — <code>components/geom/</code>, <code>components/topo/</code>, <code>components/toolhouse/</code>,
|
|
<code>components/spindle/</code>, <code>components/workpiece/</code> and <code>components/mission/</code> are pulled in from
|
|
wherever the domain surfaces, most often the Control Tree.</li>
|
|
<li><strong>Primitives</strong> — <code>components/widgets/</code> and <code>components/panels/</code> have no domain at all and are the
|
|
most-imported folders in the application.</li>
|
|
</ul>
|
|
<p>So a component's folder does not tell a reader who mounts it. <code>components/mission/</code> has no Mission
|
|
page — <code>/mission</code> redirects into the Execution page's tree — and <code>components/workpiece/</code> holds a
|
|
single dropdown while the real workpiece editors are Control-Tree panels.</p>
|
|
<p>The second break is history. The application has been re-architected repeatedly, and because
|
|
Control-Tree node ids ride in <code>?tree=</code> links they are a public surface: every regroup <strong>adds</strong> a
|
|
migration hop rather than rewriting the last one. The residue is visible in <code>wwwroot-src/src/router/routes.ts</code>, where a large share of the table is
|
|
redirects preserving URLs from earlier architectures — a route existing there does <strong>not</strong> mean a
|
|
page exists for it.</p>
|
|
<h2 id="root-and-boot">Root and Boot</h2>
|
|
<ul>
|
|
<li><code>wwwroot-src/src/App.vue</code> — not the shell. It is a bare router view plus the once-per-load wiring
|
|
that subscribes the project store to the execution-status hub. The real shell is
|
|
<code>wwwroot-src/src/layouts/MainLayout.vue</code>. Documented in
|
|
<a class="xref" href="../platform/session-state.html">Session State</a>.</li>
|
|
<li><code>wwwroot-src/src/boot/auth.ts</code>, <code>wwwroot-src/src/boot/i18n.ts</code>,
|
|
<code>wwwroot-src/src/boot/routine-toast.ts</code> — Quasar boot files, run once before mount and in a
|
|
declared order. The auth boot file patches the global fetch and inspects every 401, which is why
|
|
no API module carries its own 401 handling — but the redirect it can raise is conditional: it
|
|
fires only while the auth store reports the login gate enabled, and not when the router is
|
|
already on the login route, so on a build with the gate off a 401 redirects nowhere. The toast
|
|
boot file patches the shared notify helper so every toast is mirrored into the footer history
|
|
without touching a call site. Documented in
|
|
<a class="xref" href="../platform/login-and-auth.html">Login and Authentication</a> and
|
|
<a class="xref" href="../platform/i18n.html">Internationalization</a>.</li>
|
|
<li><code>wwwroot-src/src/layouts/MainLayout.vue</code> — the shell: menu bar, the routed page container, footer.
|
|
It also owns the mechanism every page depends on and no page implements: a project epoch, bumped
|
|
when the loaded project changes, is the keep-alive key, so a project change destroys and rebuilds
|
|
every cached page. Documented in <a class="xref" href="../shell/main-panel.html">Main Panel</a> and
|
|
<a class="xref" href="../platform/session-state.html">Session State</a>.</li>
|
|
</ul>
|
|
<h2 id="the-rest-edge">The REST Edge</h2>
|
|
<p><code>wwwroot-src/src/api/</code> is one thin typed module per backend controller family — functions, DTO types
|
|
and kind unions, no Vue code. This is the tightest correspondence between the two halves of the
|
|
application: each module wraps one named controller almost one-to-one.</p>
|
|
<ul>
|
|
<li><code>wwwroot-src/src/api/http.ts</code> — the shared response layer. Its own header names the modules that
|
|
deliberately bypass it, so “every API module goes through it” would be wrong.</li>
|
|
<li><code>wwwroot-src/src/api/index-service.ts</code> — <strong>not</strong> a barrel file. It wraps the backend's keyed object
|
|
store, which is where the <code>key</code> string threaded through the whole application comes from.
|
|
Documented in <a class="xref" href="../conventions/dictionary-service-pattern.html">Dictionary Service Pattern</a>.</li>
|
|
</ul>
|
|
<h2 id="components">Components</h2>
|
|
<ul>
|
|
<li><code>wwwroot-src/src/components/</code> — the shared top level: <code>wwwroot-src/src/components/AppMenuBar.vue</code>,
|
|
<code>wwwroot-src/src/components/AppFooter.vue</code>, <code>wwwroot-src/src/components/RenderingCanvas.vue</code>,
|
|
<code>wwwroot-src/src/components/FileExplorer.vue</code> and <code>wwwroot-src/src/components/StlPreviewPane.vue</code>.
|
|
The canvas does not render locally: it opens a SignalR connection and paints server-rendered
|
|
frames, which is why several pages each own a canvas bound to a different backend scene.
|
|
Documented in
|
|
<a class="xref" href="../conventions/rendering-canvas-web-service.html">Rendering Canvas on Web Service</a>,
|
|
<a href="../util/file-explorer.html">File Explorer</a> and
|
|
<a class="xref" href="../util/stl-preview-pane.html">STL Preview Pane</a>.</li>
|
|
<li><code>wwwroot-src/src/components/controlTree/</code> — the largest folder in the SPA by a factor of two, and
|
|
a <strong>registry-driven panel system</strong> rather than a folder of tree widgets.
|
|
<code>wwwroot-src/src/components/controlTree/itemTypes.ts</code> and its domain siblings map an item-type
|
|
string onto a panel component and a child-building function;
|
|
<code>wwwroot-src/src/components/controlTree/useControlTreeHost.ts</code> is the state machine that builds the
|
|
tree, gates a dirty selection switch, and syncs <code>?tree=</code>; the many
|
|
panel components are the editors the registry resolves. It serves <strong>three</strong> consumers, not one —
|
|
the Execution and General Setup pages each instantiate their own scoped host, while the Tool House
|
|
page reuses the identical panels and registry through a tab cascade and never touches the host.
|
|
Documented in <a class="xref" href="../platform/control-tree.html">Control Tree</a> — the folder's own page — with
|
|
<a class="xref" href="../execution/index.html">Execution Page</a>, <a class="xref" href="../general-setup/index.html">General Setup Page</a> and
|
|
<a class="xref" href="../tool-house/index.html">Tool House Page</a> for the three consumers, and
|
|
<a class="xref" href="../execution/program.html">Program Branch</a> for the NC-program item types and panels that live in
|
|
this folder. The nineteen <code>SoftNc*</code> panels and their registry are a wave of their own, documented
|
|
under <a class="xref" href="../general-setup/controller/index.html">Controller Branch</a>: which of them the tree mounts at all is decided
|
|
by <a class="xref" href="../general-setup/controller/brand-matrix.html">Brand Matrix</a>, and what they share is
|
|
<a class="xref" href="../general-setup/controller/editing-contract.html">Editing Contract</a>.</li>
|
|
<li><code>wwwroot-src/src/components/controlTree/toolhouse/</code> — the Tool House branch's panels. Easy to
|
|
confuse with <code>wwwroot-src/src/components/toolhouse/</code>: these are the panels the registry mounts,
|
|
that folder holds
|
|
the content fragments those panels embed, and the dependency runs one way only.</li>
|
|
<li><code>wwwroot-src/src/components/execution/</code> — the run cockpit's own panels, plus its <code>charts/</code>
|
|
sub-folder, the uPlot charting layer. Not purely page-local:
|
|
<code>wwwroot-src/src/components/execution/ExecutionToolBar.vue</code> is mounted by the Control Tree's
|
|
primary panel, and the spindle contours chart imports from the charts folder. Documented in
|
|
<a class="xref" href="../execution/index.html">Execution Page</a>, <a class="xref" href="../execution/strip-charts.html">Strip Charts</a> and
|
|
<a class="xref" href="../execution/cycle-line-charts.html">Cycle-Line Charts</a>.</li>
|
|
<li><code>wwwroot-src/src/components/geom/</code> and <code>wwwroot-src/src/components/topo/</code> — structural twins: one
|
|
editor per kind, the same <code>modelKey</code> prop and <code>changed</code> / <code>error</code> emits, and a single kind → editor
|
|
map — <code>wwwroot-src/src/components/geom/geometryEditors.ts</code> and
|
|
<code>wwwroot-src/src/components/topo/transformerEditors.ts</code> — that is the source of truth for both the
|
|
switchboard and the Control Tree. A new kind must be registered there,
|
|
not merely dropped in the folder. “topo” means coordinate <strong>transformers</strong>, not mesh topology.
|
|
Documented in <a class="xref" href="../geom/index.html">Geometry Panels</a> and
|
|
<a class="xref" href="../geom/transformer-panel.html">Transformer Select Panel</a>.</li>
|
|
<li><code>wwwroot-src/src/components/widgets/</code> — the reusable input library: numeric, vector and matrix
|
|
inputs, the file-path input and picker, the CodeMirror text editor, the display-options and
|
|
object-management menus. Documented in <a class="xref" href="../widget/index.html">Widgets</a>.</li>
|
|
<li><code>wwwroot-src/src/components/panels/</code> — pure layout machinery with no domain: the collapsible
|
|
expansion panel and the resizable stack whose registration contract produces the “rows collapse in
|
|
place” behaviour the tree pages describe. Documented in
|
|
<a class="xref" href="../platform/control-tree.html">Control Tree</a>, whose dock rows are both expansion rows, and
|
|
<a class="xref" href="../platform/session-state.html">Session State</a> for the keep-mounted flag that decides whether a
|
|
collapse unmounts its content.</li>
|
|
<li><code>wwwroot-src/src/components/mission/</code>, <code>.../toolhouse/</code>, <code>.../spindle/</code>, <code>.../preference/</code>,
|
|
<code>.../mech/</code> and <code>.../workpiece/</code> — the domain and page folders named above. The
|
|
<code>*Div.vue</code> suffix inside the Tool House folder is a convention carried over from the legacy Blazor
|
|
components: a Div is an embeddable content fragment with no panel chrome.</li>
|
|
</ul>
|
|
<h2 id="state-routing-and-text">State, Routing and Text</h2>
|
|
<ul>
|
|
<li><code>wwwroot-src/src/composables/</code> — three different concerns in one folder: hub access, shared domain
|
|
state, and UI mechanics. <code>wwwroot-src/src/composables/useSharedHub.ts</code> is the reference-counted connection manager
|
|
behind every hub composable, so a hub opens only while something consumes it.
|
|
<code>wwwroot-src/src/composables/useToolHouse.ts</code> and <code>wwwroot-src/src/composables/useSpindleCapability.ts</code> are module-level
|
|
singletons, not per-component instances. <code>wwwroot-src/src/composables/useViewPrefs.ts</code> stores layout state in the
|
|
browser only — it is neither in the project file nor in the server's user config. Documented in
|
|
<a class="xref" href="../platform/session-state.html">Session State</a>.</li>
|
|
<li><code>wwwroot-src/src/stores/</code> — four Pinia stores. <code>wwwroot-src/src/stores/index.ts</code> is <strong>not</strong> a barrel; it is the
|
|
Quasar factory. Most shared state lives in <code>composables/</code> instead. Documented in
|
|
<a class="xref" href="../platform/session-state.html">Session State</a>.</li>
|
|
<li><code>wwwroot-src/src/router/</code> — <code>wwwroot-src/src/router/routes.ts</code> is the table plus the legacy redirects, and
|
|
<code>wwwroot-src/src/router/treeRoutes.ts</code> is the load-bearing file its name understates: it holds the accumulated
|
|
chain of tree-id renames and the id → page resolver, plus the tab-name constants both the router
|
|
and the tab composable consume. A route's <code>meta.title</code> holds an i18n key, not a title.
|
|
Documented in <a class="xref" href="../platform/tree-ids-and-routes.html">Tree Ids and Routes</a>.</li>
|
|
<li><code>wwwroot-src/src/i18n/</code> — three locales shipped together, each a list of namespace files.
|
|
<strong>English is the schema</strong>, not merely a locale: the two Chinese bundles are typed against it, so a
|
|
key present in English and missing there is a build error. Keys are split by UI region rather than
|
|
by source file, so there is no one-to-one mapping between an i18n file and a components folder.
|
|
Documented in <a class="xref" href="../platform/i18n.html">Internationalization</a> and
|
|
<a class="xref" href="../conventions/translation-remarks.html">Translation Remarks</a>.</li>
|
|
<li><code>wwwroot-src/src/pages/</code> — one file per route, and page size is a poor guide to importance: the
|
|
General Setup page is small because it delegates almost everything to the Control Tree dock and the
|
|
equipment canvas, while the File Explorer page is a thin wrapper around a large shared component.</li>
|
|
<li><code>wwwroot-src/src/utils/</code>, <code>wwwroot-src/src/directives/</code>, <code>wwwroot-src/src/css/</code> — small and mostly
|
|
presentational. Two severity scales exist and must not be conflated:
|
|
<code>wwwroot-src/src/utils/messageSeverity.ts</code> maps the engine's diagnostic scale, while the footer's routine severity
|
|
is a separate, shorter toast scale.</li>
|
|
</ul>
|
|
<h2 id="see-also">See Also</h2>
|
|
<ul>
|
|
<li><a class="xref" href="index.html">Anatomy by Source Directory</a> — the other two source trees, and how this
|
|
layer is meant to be entered</li>
|
|
<li><a class="xref" href="webservice-backend.html">Web Service Backend Source Tree</a> — the process that
|
|
serves this application and answers its REST and hub traffic</li>
|
|
</ul>
|
|
|
|
</article>
|
|
|
|
<div class="contribution d-print-none">
|
|
</div>
|
|
|
|
<div class="next-article d-print-none border-top" id="nextArticle"></div>
|
|
|
|
</div>
|
|
|
|
<div class="affix">
|
|
<nav id="affix"></nav>
|
|
</div>
|
|
</main>
|
|
|
|
<div class="container-xxl search-results" id="search-results"></div>
|
|
|
|
<footer class="border-top text-secondary">
|
|
<div class="container-xxl">
|
|
<div class="flex-fill">
|
|
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</body>
|
|
</html>
|