diff --git a/docs/linuxcnc-axis-web-control-panel-source-logic.md b/docs/linuxcnc-axis-web-control-panel-source-logic.md index bc6976e..4e6c57d 100644 --- a/docs/linuxcnc-axis-web-control-panel-source-logic.md +++ b/docs/linuxcnc-axis-web-control-panel-source-logic.md @@ -825,6 +825,9 @@ machine/operation values remain on the main element as data attributes for browser diagnostics; no control command or gate changes with this layout. Home Joint, the numeric joint selector and Home All are rendered in the Manual tab's action area; the standalone Machine sequence heading is not rendered. +The XYZAC position summary and preview HUD display only X/Y/Z/A/C; J0-J4 +position readouts are omitted. Numeric homing target selection and canonical +joint data remain available to the existing control logic. ```text HOME(all/joint) diff --git a/docs/web-panel-png-guide/00-panel-overview-hd.png b/docs/web-panel-png-guide/00-panel-overview-hd.png new file mode 100644 index 0000000..11d7509 Binary files /dev/null and b/docs/web-panel-png-guide/00-panel-overview-hd.png differ diff --git a/docs/web-panel-png-guide/01-toolbar-and-workspace.html b/docs/web-panel-png-guide/01-toolbar-and-workspace.html new file mode 100644 index 0000000..543743c --- /dev/null +++ b/docs/web-panel-png-guide/01-toolbar-and-workspace.html @@ -0,0 +1,2 @@ +工具栏与文件操作
LinuxCNC AXIS Web/WASM · XYZAC TRT · 控件功能图解 01/04

工具栏与文件操作

截图状态:XYZAC TRT 已上电、已回零、程序空闲。灰色按钮须结合禁用原因判断,不代表点击后可以执行。

文件 / 帮助菜单入口

12
1

File 文件菜单

展开文件菜单。当前包含工具表编辑和退出入口,二者受浏览器运行边界限制。

menu-file
2

Help 帮助菜单

展开帮助菜单,可打开 About 信息窗口;不向机床发送运动命令。

menu-help

机器与程序工具栏 · 图标从左至右

34567891011121314151617181920212223
3

急停 / 解除急停 · F1

按当前状态切换急停。触发急停会中止当前执行和运动;解除后仍需单独上电。F1 在文本输入时也有效。

toolbar-estop
4

机床电源 · F2

在解除急停后上电;再次点击断电。断电中止运动和任务。上电不会自动回零,也不会自动执行程序。

toolbar-power
5

打开 G-code · o

从本机选择程序文件并通过 Worker/WASM 加载、解析预览。执行活动或加载未结束时不可替换程序;取消选择不提交。

toolbar-open
6

重新加载 XYZAC 案例

重新载入选定 INI、HAL 等配置及其 OPEN_FILE 程序。这是 Web 工作区入口;不会自动上电、回零或运行。

toolbar-load-case
7

重新加载当前程序 · Ctrl+r

将编辑区当前文本重新提交给解释器并生成静态预览。要求已有文件且允许加载;保留已有 Live Plot。

toolbar-reload
8

执行程序 · r

切换 AUTO 并从第 0 行开始执行当前文件。任务层检查上电、回零等条件;完成或 Stop 后可直接再次 Run。

toolbar-run
9

单步 · t

执行下一处程序/运动边界。首次单步启动后暂停;已有运动队列时按执行边界推进,不等于每次恰好执行一行文本。

toolbar-step
10

暂停 / 恢复

同一按钮按当前状态切换 Pause 与 Resume,保留程序和运动队列。暂停仍属于活动任务,不能据此进行 Jog 或 Home。

toolbar-pause-resume
11

停止程序 · Esc

中止当前任务及运动,保留所选程序。按钮按任务状态启用;Esc 也可停止手动运动。停止后重新 Run 从头开始。

toolbar-stop
12

跳过 / 程序段 · 未实现

原生功能用于跳过带斜杠的程序段。当前 WASM 未暴露完整状态,按钮保持禁用,不是本地开关。

toolbar-block-delete
13

可选停止 · 未实现

原生功能控制是否在 M1 处停止。当前 ABI 未提供完整命令和状态,按钮保持禁用。

toolbar-optional-pause
14

放大预览

增大当前预览的相机缩放;仅改变显示,不改变进给、机床坐标或程序内容。

toolbar-zoom-in
15

缩小预览

减小预览的相机缩放,用于查看更大范围;不改变实际运动。

toolbar-zoom-out
16

Z 顶视图

正交投影,屏幕右/上对应 X/Y。 点击后显示 Preview 页;不改变机床状态。

toolbar-view-z
17

Z2 旋转顶视图

顶视图在屏幕平面旋转,右/上对应 Y/-X。 点击后显示 Preview 页;不改变机床状态。

toolbar-view-z2
18

X 侧视图

正交投影,右/上对应 Y/Z。 点击后显示 Preview 页;不改变机床状态。

toolbar-view-x
19

Y 正视图

正交投影,右/上对应 X/Z。 点击后显示 Preview 页;不改变机床状态。

toolbar-view-y
20

Y2 反向正视图

原生工具栏附加方向,右/上对应 Z/X。 点击后显示 Preview 页;不改变机床状态。

toolbar-view-y2
21

P 透视图

三维透视观察刀路;可配合拖动、平移和缩放查看。 点击后显示 Preview 页;不改变机床状态。

toolbar-view-p
22

拖动 / 旋转模式

切换鼠标左键拖动时的平移/旋转行为。按钮按下不代表自动旋转,也不控制旋转轴运动。

toolbar-rotate
23

清除加工轨迹 · Ctrl+K

仅清除 Live Plot 历史,保留静态程序预览。运行中清除后继续积累新轨迹;不会停止、重载或重启程序。

toolbar-clear-live-plot

案例与示例程序

2425
24

仿真案例选择

当前目录限定为支持的 XYZAC TRT 案例。选择本身不执行加载;重新载入使用工具栏的案例加载按钮。

workspace-case-select
25

加载 3D_Chips.ngc

打开随项目提供的示例程序,走同一 WASM 加载和预览流程。保留 Live Plot,执行前需另按 Run。

workspace-load-3d-chips
83

文件选择对话框入口

隐藏的浏览器文件输入,由编号 05“打开 G-code”触发。选择 .ngc/.nc/.gcode 等文件后走同一加载事务;没有第二个可见按钮。

\ No newline at end of file diff --git a/docs/web-panel-png-guide/01-toolbar-and-workspace.png b/docs/web-panel-png-guide/01-toolbar-and-workspace.png new file mode 100644 index 0000000..be56207 Binary files /dev/null and b/docs/web-panel-png-guide/01-toolbar-and-workspace.png differ diff --git a/docs/web-panel-png-guide/02-manual-and-homing.html b/docs/web-panel-png-guide/02-manual-and-homing.html new file mode 100644 index 0000000..c4cf87a --- /dev/null +++ b/docs/web-panel-png-guide/02-manual-and-homing.html @@ -0,0 +1,2 @@ +手动操作与原生回零
LinuxCNC AXIS Web/WASM · XYZAC TRT · 控件功能图解 02/04

手动操作与原生回零

Home Joint 选择数字关节;Jog/Touch Off 选择世界轴。当前案例 Home 可能只重新建立坐标参考点,电机位置不变,这是原生 INI 回零语义。

Manual Control 手动页

29303132333435363738394041424344454647484950515253
29

Manual Control · F3

显示手动控制页,并在源门控允许时请求对应模式。AUTO 运行或暂停时,仅切换可见页签不会强制变为 MANUAL。

tab-manual
30

MDI · F5

显示单条指令输入页,并在允许时请求 MDI 模式。提交指令仍受任务层门控约束。

tab-mdi
31

Diagnostics 诊断

查看工作区资源、禁用原因、操作记录和错误信息。浏览此页本身不执行运动或恢复操作。

tab-diagnostics
32

回零关节选择

选择数字关节 0–4,仅决定 Home Joint 的目标。与下面 X/Y/Z/A/C 世界轴选择相互独立。

manual-home-joint-select
33

Home Joint 单关节回零

对选定数字关节运行原生 homemod。已回零时先确认;回零完成以 homing/homed 状态为准。不是 G53 返回机床零点。

manual-home-axis
34

HOME ALL / RE-HOME ALL

按 INI HOME_SEQUENCE 发起全部关节回零。当前案例搜索/锁存速度为 0,可能在当前位置建立参考点而不产生电机位移。

manual-home-all
35

选择 X 轴

选择世界坐标 X 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。线性轴按 mm/inch 显示单位处理。

manual-axis-x
36

选择 Y 轴

选择世界坐标 Y 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。线性轴按 mm/inch 显示单位处理。

manual-axis-y
37

选择 Z 轴

选择世界坐标 Z 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。线性轴按 mm/inch 显示单位处理。

manual-axis-z
38

选择 A 轴

选择世界坐标 A 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。旋转轴以度为单位。

manual-axis-a
39

选择 C 轴

选择世界坐标 C 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。旋转轴以度为单位。

manual-axis-c
40

Jog − 负向点动

沿所选轴负方向运动。Continuous 按住运动、释放/失焦停止;增量模式提交一次指定距离,松开不截断该增量。

manual-jog-negative
41

Jog + 正向点动

沿所选轴正方向运动,使用当前步长和 Jog Speed。手动页可见且任务允许时生效;运行、暂停或回零期间不可开始点动。

manual-jog-positive
42

点动步长

Continuous 为持续点动;0.1000/0.0100/0.0010/0.0001 为单次增量。线性值遵循 mm/inch,A/C 不做英寸换算。

manual-jog-increment
43

Touch Off 坐标系对刀

输入当前点应显示的坐标,再选择 P0 当前或 P1–P9 坐标系。通过 G10 L20 改偏置,不移动机床;取消对话框不执行。

manual-touch-off
44

Tool Touch Off · 未实现

原生为刀具偏置测定,涉及 G10 L10/L11 和 G43。当前 ABI 不完整,禁用;不能用普通 Touch Off 冒充。

manual-tool-touch-off
45

Override Limits · 未实现

原生用于限位触发后的脱离操作。当前面板没有对应完整状态/命令边界,禁用。

manual-override-limits
46

主轴逆时针

发送主轴反转方向命令,选中状态来自 WASM 主轴方向。需上电、任务空闲;不同于 A/C 旋转轴点动。

manual-spindle-ccw
47

Stop Spindle

停止主轴旋转。仅控制主轴,不等于停止正在执行的程序;程序停止使用工具栏 Stop。

manual-spindle-stop
48

主轴顺时针

发送主轴正转方向命令,运行方向和速度由规范快照回显;按钮不会设置本地伪运行状态。

manual-spindle-cw
49

降低主轴速度

主轴方向非零时启用。按下发送减速边沿,释放发送 SPINDLE_CONSTANT;不会减速穿过零后自动变成反转。

manual-spindle-decrease
50

提高主轴速度

主轴方向非零时启用。按下发送增速边沿,释放结束调速。主轴倍率与该指令速度分开处理。

manual-spindle-increase
51

Brake 主轴制动

请求接合或释放主轴制动,复选框由 WASM 制动状态回显。受手动操作门控约束。

manual-spindle-brake
52

Mist 雾化冷却

独立开关雾化冷却。手动页需上电且解释器空闲;与 Flood 相互独立,可同时开启。

manual-coolant-mist
53

Flood 浇注冷却

独立开关浇注冷却;状态来自 IO 快照,不因界面勾选而提前认定成功。

manual-coolant-flood
\ No newline at end of file diff --git a/docs/web-panel-png-guide/02-manual-and-homing.png b/docs/web-panel-png-guide/02-manual-and-homing.png new file mode 100644 index 0000000..b747c20 Binary files /dev/null and b/docs/web-panel-png-guide/02-manual-and-homing.png differ diff --git a/docs/web-panel-png-guide/03-views-and-overrides.html b/docs/web-panel-png-guide/03-views-and-overrides.html new file mode 100644 index 0000000..53699be --- /dev/null +++ b/docs/web-panel-png-guide/03-views-and-overrides.html @@ -0,0 +1,2 @@ +运动学、视图与倍率
LinuxCNC AXIS Web/WASM · XYZAC TRT · 控件功能图解 03/04

运动学、视图与倍率

Switchkins 改变运动学解释;相机与图层仅改变显示。Feed、Spindle、Jog 和 Max Velocity 各有独立含义,不能互相代替。

Switchkins 运动学模式

262728
26

Identity · M429

选择本案例 active_type=0 的恒等运动学。要求上电、已回零且无活动队列;M429 不会把模块 KINEMATICS_BOTH 类型改为 IDENTITY。

switchkins-0
27

TCP: XYZAC · M428

选择 active_type=1 的 XYZAC TRT 刀尖运动学,使用当前几何偏置进行变换。切换需任务空闲且运动队列为空。

switchkins-1
28

User K · M430

选择 active_type=2 的已链接用户运动学;当前为 identity 模板,不表示可在浏览器动态加载任意运动学模块。

switchkins-2

Preview / DRO 与画布平移

54555657585960
54

Preview 刀路页

查看静态程序刀路、加工轨迹和刀具位置。切换显示页不会加载文件、改变模式或发起运动。

tab-preview
55

DRO 数显页

切换至坐标数显与坐标/单位选择;其值来自 Worker 快照。不是另一个轴位置输入入口。

tab-dro
56

L 向左平移

向左平移相机观察中心。仅操作画布;“0”不会回零机床。

preview-panLeft
57

R 向右平移

向右平移相机观察中心。仅操作画布;“0”不会回零机床。

preview-panRight
58

U 向上平移

向上平移相机观察中心。仅操作画布;“0”不会回零机床。

preview-panUp
59

D 向下平移

向下平移相机观察中心。仅操作画布;“0”不会回零机床。

preview-panDown
60

0 重置视图

按当前预置视角和缩放重新取景。仅操作画布;“0”不会回零机床。

preview-reset

倍率滑块与预览图层

6162636465666768697071
61

Jog Speed 点动速度

调整之后点动使用的速度比例,当前范围 6%–100%。与程序进给倍率不同;滑块本身不发起运动。

override-jog-speed
62

Feed Override 进给倍率

按当前 INI 调整 0%–200% 程序进给倍率,可在自动运行时修改。不是修改 G-code 中的 F 值;快速倍率独立。

override-feed
63

Spindle Override 主轴倍率

调整主轴输出速度比例。设为 0% 不会丢失方向和原指令速度,恢复倍率后按原方向输出。

override-spindle
64

Max Velocity 最大速度

调整轨迹规划器最大速度比例,当前为 6%–100% 适配。它是速度上限,不能代替 Rapid Override。

override-max-velocity
65

Rapid Override · 未实现

原生为快速运动倍率。当前选定 WASM TP 没有完整 rapidrate 控制,滑块禁用,不借用 Max Velocity 模拟。

override-rapid
66

path · 静态刀路

显示/隐藏当前程序解析得到的静态路径。只改变显示,不改变程序、偏置或运动状态。

preview-layer-path
67

live · 加工轨迹

显示/隐藏已采样 Live Plot,隐藏不会删除轨迹。只改变显示,不改变程序、偏置或运动状态。

preview-layer-live
68

limits · 机床限位

显示/隐藏 WASM 提供的 XYZ 软限位框。只改变显示,不改变程序、偏置或运动状态。

preview-layer-limits
69

velocity · 运动速度

显示/隐藏预览中的当前规范速度文字。只改变显示,不改变程序、偏置或运动状态。

preview-layer-velocity
70

offsets · 坐标偏置

显示/隐藏当前已支持的 G5x 平移偏置指示。只改变显示,不改变程序、偏置或运动状态。

preview-layer-offsets
71

extents · 程序范围

显示/隐藏规范刀路样本的包围范围。只改变显示,不改变程序、偏置或运动状态。

preview-layer-extents

程序编辑与执行记录

72
72

G-code 编辑区

修改待提交程序文本。修改后必须通过 Reload 重新提交才影响解释器;编辑文字不等于已经加载或执行。

program-editor
\ No newline at end of file diff --git a/docs/web-panel-png-guide/03-views-and-overrides.png b/docs/web-panel-png-guide/03-views-and-overrides.png new file mode 100644 index 0000000..c49f829 Binary files /dev/null and b/docs/web-panel-png-guide/03-views-and-overrides.png differ diff --git a/docs/web-panel-png-guide/04-mdi-dro-and-menus.html b/docs/web-panel-png-guide/04-mdi-dro-and-menus.html new file mode 100644 index 0000000..ebe2ffc --- /dev/null +++ b/docs/web-panel-png-guide/04-mdi-dro-and-menus.html @@ -0,0 +1,2 @@ +MDI、数显与菜单窗口
LinuxCNC AXIS Web/WASM · XYZAC TRT · 控件功能图解 04/04

MDI、数显与菜单窗口

MDI 示例仅提交 G21(毫米单位),未执行加工运动。错误及禁用原因以当前状态栏与 Diagnostics 为准。

MDI 单条指令与历史

737475
73

MDI 指令输入

输入单条 G-code/M-code;Enter 与 Go 使用同一提交路径。提交会去除首尾空白,空输入不发送;执行受 manual_ok 与任务门控限制。

mdi-command
74

Go 执行 MDI

将输入指令提交给 WASM 解释器。可能产生真实仿真运动或 IO 动作;收到 ACK 不代表排队运动已经完成。

mdi-submit
75

MDI 历史条目

单击将该条指令填回输入框,双击重新提交执行。上下方向键浏览历史,相邻重复记录去重;历史并非执行成功证明。

mdi-history-select

DRO 数显设置

767778
76

Machine / Relative

切换机床坐标与相对工件坐标显示。当前相对投影支持已实现的 G5x 平移偏置,不用显示切换改写运动目标。

dro-coordinate
77

Actual / Commanded

切换实际与指令位置的显示语义。当前理想仿真两者可相同,不能据标签推断已模拟真实跟随误差。

dro-display
78

mm / inch

切换线性坐标显示单位,A/C 仍为角度。该设置也用于界面点动和对刀输入的线性单位换算,不改写原程序。

dro-units

File 菜单展开

7980
79

Edit tool data… · 未实现

桌面原生会启动工具表编辑器,浏览器没有对应宿主编辑流程,因此该菜单项禁用。

menu-file-edit-tool-data
80

Quit · 未实现

桌面原生用于结束 AXIS 进程。Web 不模拟结束机床进程,此项禁用;可由浏览器关闭页面。

menu-file-quit

Help 菜单展开

81
81

About AXIS

显示本地 About 窗口,查看应用名称与案例信息;不会改变 Worker、任务或 IO 状态。

menu-help-about

About 弹窗

82
82

About 窗口 OK

关闭 About 窗口并返回原界面。属于界面操作,不等于命令确认、复位或启动。

about-close
\ No newline at end of file diff --git a/docs/web-panel-png-guide/04-mdi-dro-and-menus.png b/docs/web-panel-png-guide/04-mdi-dro-and-menus.png new file mode 100644 index 0000000..55c9571 Binary files /dev/null and b/docs/web-panel-png-guide/04-mdi-dro-and-menus.png differ diff --git a/docs/web-panel-png-guide/README.md b/docs/web-panel-png-guide/README.md new file mode 100644 index 0000000..0eefc07 --- /dev/null +++ b/docs/web-panel-png-guide/README.md @@ -0,0 +1,42 @@ +# Web 控制台高清 PNG 功能图解 + +截图来源:`http://127.0.0.1:5175/`,2026-09-09。 +图解依据当前 XYZAC TRT Web 面板实现和 +[`linuxcnc-axis-web-control-panel-source-logic.md`](../linuxcnc-axis-web-control-panel-source-logic.md)。 + +## 图片 + +| 图片 | 内容 | 分辨率 | +| --- | --- | --- | +| [高清总览](00-panel-overview-hd.png) | 当前面板原始截图 | 3170 × 3196 | +| [01 工具栏与文件操作](01-toolbar-and-workspace.png) | 急停、电源、打开、加载、运行、暂停、停止、视角、菜单入口 | 3600 × 5308 | +| [02 手动操作与原生回零](02-manual-and-homing.png) | 回零关节选择、Home、Jog、对刀、主轴、冷却 | 3600 × 6000 | +| [03 运动学、视图与倍率](03-views-and-overrides.png) | Switchkins、预览控制、倍率、图层、编辑区 | 3600 × 8134 | +| [04 MDI、数显与菜单窗口](04-mdi-dro-and-menus.png) | MDI、历史、DRO、File/Help 菜单、About | 3600 × 7888 | + +红色编号对应每项的中文详细说明。覆盖 83 个控件 ID,含按钮、菜单、页签、 +复选框、选择框、滑块和输入框;隐藏的文件输入入口作为编号 83 单独说明。 +禁用且未实现的功能有明确标记。动态 Pause/Resume、Home All/Re-home All +使用同一编号解释其状态变化。 + +总览中的状态文字为只读监控:Task mode 是 MANUAL/MDI/AUTO;Task state +是机床上电/急停状态;Interpreter 为解释器状态;Motion mode 是 +FREE/COORD/TELEOP,不能与 Motion type 混用。Homing 表示当前回零活动, +Machine sequence 的 HOMED 表示各关节已完成参考点建立,二者并不相同。 + +当前案例采用原生无搜索回零配置,因此 Jog 后 Home 可以改变关节坐标与 +电机偏置而不移动电机;不能将其理解为 G53 返回预先固定的物理原点。 + +## 再生成 + +从仓库根目录运行,需启动面板服务并有可见桌面和 Playwright: + +```bash +DISPLAY=:1 PLAYWRIGHT_MODULE=/path/to/playwright/index.js \ +XYZAC_PANEL_URL=http://127.0.0.1:5175/ \ +node scripts/generate_panel_png_guide.mjs +``` + +脚本在独立浏览器会话中操作面板,完成上电/回零并输入无运动的 G21 以展示 +MDI 历史,然后抓取界面与控件位置。标注仅存在于导出的图片/HTML 中, +不修改控制台程序。`controls.json` 保存全部编号、控件 ID 和说明。 diff --git a/docs/web-panel-png-guide/controls.json b/docs/web-panel-png-guide/controls.json new file mode 100644 index 0000000..7d7f64b --- /dev/null +++ b/docs/web-panel-png-guide/controls.json @@ -0,0 +1,509 @@ +{ + "url": "http://127.0.0.1:5175/", + "controls": [ + { + "id": "menu-file", + "name": "File 文件菜单", + "detail": "展开文件菜单。当前包含工具表编辑和退出入口,二者受浏览器运行边界限制。", + "number": 1 + }, + { + "id": "menu-help", + "name": "Help 帮助菜单", + "detail": "展开帮助菜单,可打开 About 信息窗口;不向机床发送运动命令。", + "number": 2 + }, + { + "id": "toolbar-estop", + "name": "急停 / 解除急停 · F1", + "detail": "按当前状态切换急停。触发急停会中止当前执行和运动;解除后仍需单独上电。F1 在文本输入时也有效。", + "number": 3 + }, + { + "id": "toolbar-power", + "name": "机床电源 · F2", + "detail": "在解除急停后上电;再次点击断电。断电中止运动和任务。上电不会自动回零,也不会自动执行程序。", + "number": 4 + }, + { + "id": "toolbar-open", + "name": "打开 G-code · o", + "detail": "从本机选择程序文件并通过 Worker/WASM 加载、解析预览。执行活动或加载未结束时不可替换程序;取消选择不提交。", + "number": 5 + }, + { + "id": "toolbar-load-case", + "name": "重新加载 XYZAC 案例", + "detail": "重新载入选定 INI、HAL 等配置及其 OPEN_FILE 程序。这是 Web 工作区入口;不会自动上电、回零或运行。", + "number": 6 + }, + { + "id": "toolbar-reload", + "name": "重新加载当前程序 · Ctrl+r", + "detail": "将编辑区当前文本重新提交给解释器并生成静态预览。要求已有文件且允许加载;保留已有 Live Plot。", + "number": 7 + }, + { + "id": "toolbar-run", + "name": "执行程序 · r", + "detail": "切换 AUTO 并从第 0 行开始执行当前文件。任务层检查上电、回零等条件;完成或 Stop 后可直接再次 Run。", + "number": 8 + }, + { + "id": "toolbar-step", + "name": "单步 · t", + "detail": "执行下一处程序/运动边界。首次单步启动后暂停;已有运动队列时按执行边界推进,不等于每次恰好执行一行文本。", + "number": 9 + }, + { + "id": "toolbar-pause-resume", + "name": "暂停 / 恢复", + "detail": "同一按钮按当前状态切换 Pause 与 Resume,保留程序和运动队列。暂停仍属于活动任务,不能据此进行 Jog 或 Home。", + "number": 10 + }, + { + "id": "toolbar-stop", + "name": "停止程序 · Esc", + "detail": "中止当前任务及运动,保留所选程序。按钮按任务状态启用;Esc 也可停止手动运动。停止后重新 Run 从头开始。", + "number": 11 + }, + { + "id": "toolbar-block-delete", + "name": "跳过 / 程序段 · 未实现", + "detail": "原生功能用于跳过带斜杠的程序段。当前 WASM 未暴露完整状态,按钮保持禁用,不是本地开关。", + "number": 12 + }, + { + "id": "toolbar-optional-pause", + "name": "可选停止 · 未实现", + "detail": "原生功能控制是否在 M1 处停止。当前 ABI 未提供完整命令和状态,按钮保持禁用。", + "number": 13 + }, + { + "id": "toolbar-zoom-in", + "name": "放大预览", + "detail": "增大当前预览的相机缩放;仅改变显示,不改变进给、机床坐标或程序内容。", + "number": 14 + }, + { + "id": "toolbar-zoom-out", + "name": "缩小预览", + "detail": "减小预览的相机缩放,用于查看更大范围;不改变实际运动。", + "number": 15 + }, + { + "id": "toolbar-view-z", + "name": "Z 顶视图", + "detail": "正交投影,屏幕右/上对应 X/Y。 点击后显示 Preview 页;不改变机床状态。", + "number": 16 + }, + { + "id": "toolbar-view-z2", + "name": "Z2 旋转顶视图", + "detail": "顶视图在屏幕平面旋转,右/上对应 Y/-X。 点击后显示 Preview 页;不改变机床状态。", + "number": 17 + }, + { + "id": "toolbar-view-x", + "name": "X 侧视图", + "detail": "正交投影,右/上对应 Y/Z。 点击后显示 Preview 页;不改变机床状态。", + "number": 18 + }, + { + "id": "toolbar-view-y", + "name": "Y 正视图", + "detail": "正交投影,右/上对应 X/Z。 点击后显示 Preview 页;不改变机床状态。", + "number": 19 + }, + { + "id": "toolbar-view-y2", + "name": "Y2 反向正视图", + "detail": "原生工具栏附加方向,右/上对应 Z/X。 点击后显示 Preview 页;不改变机床状态。", + "number": 20 + }, + { + "id": "toolbar-view-p", + "name": "P 透视图", + "detail": "三维透视观察刀路;可配合拖动、平移和缩放查看。 点击后显示 Preview 页;不改变机床状态。", + "number": 21 + }, + { + "id": "toolbar-rotate", + "name": "拖动 / 旋转模式", + "detail": "切换鼠标左键拖动时的平移/旋转行为。按钮按下不代表自动旋转,也不控制旋转轴运动。", + "number": 22 + }, + { + "id": "toolbar-clear-live-plot", + "name": "清除加工轨迹 · Ctrl+K", + "detail": "仅清除 Live Plot 历史,保留静态程序预览。运行中清除后继续积累新轨迹;不会停止、重载或重启程序。", + "number": 23 + }, + { + "id": "workspace-case-select", + "name": "仿真案例选择", + "detail": "当前目录限定为支持的 XYZAC TRT 案例。选择本身不执行加载;重新载入使用工具栏的案例加载按钮。", + "number": 24 + }, + { + "id": "workspace-load-3d-chips", + "name": "加载 3D_Chips.ngc", + "detail": "打开随项目提供的示例程序,走同一 WASM 加载和预览流程。保留 Live Plot,执行前需另按 Run。", + "number": 25 + }, + { + "id": "switchkins-0", + "name": "Identity · M429", + "detail": "选择本案例 active_type=0 的恒等运动学。要求上电、已回零且无活动队列;M429 不会把模块 KINEMATICS_BOTH 类型改为 IDENTITY。", + "number": 26 + }, + { + "id": "switchkins-1", + "name": "TCP: XYZAC · M428", + "detail": "选择 active_type=1 的 XYZAC TRT 刀尖运动学,使用当前几何偏置进行变换。切换需任务空闲且运动队列为空。", + "number": 27 + }, + { + "id": "switchkins-2", + "name": "User K · M430", + "detail": "选择 active_type=2 的已链接用户运动学;当前为 identity 模板,不表示可在浏览器动态加载任意运动学模块。", + "number": 28 + }, + { + "id": "tab-manual", + "name": "Manual Control · F3", + "detail": "显示手动控制页,并在源门控允许时请求对应模式。AUTO 运行或暂停时,仅切换可见页签不会强制变为 MANUAL。", + "number": 29 + }, + { + "id": "tab-mdi", + "name": "MDI · F5", + "detail": "显示单条指令输入页,并在允许时请求 MDI 模式。提交指令仍受任务层门控约束。", + "number": 30 + }, + { + "id": "tab-diagnostics", + "name": "Diagnostics 诊断", + "detail": "查看工作区资源、禁用原因、操作记录和错误信息。浏览此页本身不执行运动或恢复操作。", + "number": 31 + }, + { + "id": "manual-home-joint-select", + "name": "回零关节选择", + "detail": "选择数字关节 0–4,仅决定 Home Joint 的目标。与下面 X/Y/Z/A/C 世界轴选择相互独立。", + "number": 32 + }, + { + "id": "manual-home-axis", + "name": "Home Joint 单关节回零", + "detail": "对选定数字关节运行原生 homemod。已回零时先确认;回零完成以 homing/homed 状态为准。不是 G53 返回机床零点。", + "number": 33 + }, + { + "id": "manual-home-all", + "name": "HOME ALL / RE-HOME ALL", + "detail": "按 INI HOME_SEQUENCE 发起全部关节回零。当前案例搜索/锁存速度为 0,可能在当前位置建立参考点而不产生电机位移。", + "number": 34 + }, + { + "id": "manual-axis-x", + "name": "选择 X 轴", + "detail": "选择世界坐标 X 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。线性轴按 mm/inch 显示单位处理。", + "number": 35 + }, + { + "id": "manual-axis-y", + "name": "选择 Y 轴", + "detail": "选择世界坐标 Y 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。线性轴按 mm/inch 显示单位处理。", + "number": 36 + }, + { + "id": "manual-axis-z", + "name": "选择 Z 轴", + "detail": "选择世界坐标 Z 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。线性轴按 mm/inch 显示单位处理。", + "number": 37 + }, + { + "id": "manual-axis-a", + "name": "选择 A 轴", + "detail": "选择世界坐标 A 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。旋转轴以度为单位。", + "number": 38 + }, + { + "id": "manual-axis-c", + "name": "选择 C 轴", + "detail": "选择世界坐标 C 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。旋转轴以度为单位。", + "number": 39 + }, + { + "id": "manual-jog-negative", + "name": "Jog − 负向点动", + "detail": "沿所选轴负方向运动。Continuous 按住运动、释放/失焦停止;增量模式提交一次指定距离,松开不截断该增量。", + "number": 40 + }, + { + "id": "manual-jog-positive", + "name": "Jog + 正向点动", + "detail": "沿所选轴正方向运动,使用当前步长和 Jog Speed。手动页可见且任务允许时生效;运行、暂停或回零期间不可开始点动。", + "number": 41 + }, + { + "id": "manual-jog-increment", + "name": "点动步长", + "detail": "Continuous 为持续点动;0.1000/0.0100/0.0010/0.0001 为单次增量。线性值遵循 mm/inch,A/C 不做英寸换算。", + "number": 42 + }, + { + "id": "manual-touch-off", + "name": "Touch Off 坐标系对刀", + "detail": "输入当前点应显示的坐标,再选择 P0 当前或 P1–P9 坐标系。通过 G10 L20 改偏置,不移动机床;取消对话框不执行。", + "number": 43 + }, + { + "id": "manual-tool-touch-off", + "name": "Tool Touch Off · 未实现", + "detail": "原生为刀具偏置测定,涉及 G10 L10/L11 和 G43。当前 ABI 不完整,禁用;不能用普通 Touch Off 冒充。", + "number": 44 + }, + { + "id": "manual-override-limits", + "name": "Override Limits · 未实现", + "detail": "原生用于限位触发后的脱离操作。当前面板没有对应完整状态/命令边界,禁用。", + "number": 45 + }, + { + "id": "manual-spindle-ccw", + "name": "主轴逆时针", + "detail": "发送主轴反转方向命令,选中状态来自 WASM 主轴方向。需上电、任务空闲;不同于 A/C 旋转轴点动。", + "number": 46 + }, + { + "id": "manual-spindle-stop", + "name": "Stop Spindle", + "detail": "停止主轴旋转。仅控制主轴,不等于停止正在执行的程序;程序停止使用工具栏 Stop。", + "number": 47 + }, + { + "id": "manual-spindle-cw", + "name": "主轴顺时针", + "detail": "发送主轴正转方向命令,运行方向和速度由规范快照回显;按钮不会设置本地伪运行状态。", + "number": 48 + }, + { + "id": "manual-spindle-decrease", + "name": "降低主轴速度", + "detail": "主轴方向非零时启用。按下发送减速边沿,释放发送 SPINDLE_CONSTANT;不会减速穿过零后自动变成反转。", + "number": 49 + }, + { + "id": "manual-spindle-increase", + "name": "提高主轴速度", + "detail": "主轴方向非零时启用。按下发送增速边沿,释放结束调速。主轴倍率与该指令速度分开处理。", + "number": 50 + }, + { + "id": "manual-spindle-brake", + "name": "Brake 主轴制动", + "detail": "请求接合或释放主轴制动,复选框由 WASM 制动状态回显。受手动操作门控约束。", + "number": 51 + }, + { + "id": "manual-coolant-mist", + "name": "Mist 雾化冷却", + "detail": "独立开关雾化冷却。手动页需上电且解释器空闲;与 Flood 相互独立,可同时开启。", + "number": 52 + }, + { + "id": "manual-coolant-flood", + "name": "Flood 浇注冷却", + "detail": "独立开关浇注冷却;状态来自 IO 快照,不因界面勾选而提前认定成功。", + "number": 53 + }, + { + "id": "tab-preview", + "name": "Preview 刀路页", + "detail": "查看静态程序刀路、加工轨迹和刀具位置。切换显示页不会加载文件、改变模式或发起运动。", + "number": 54 + }, + { + "id": "tab-dro", + "name": "DRO 数显页", + "detail": "切换至坐标数显与坐标/单位选择;其值来自 Worker 快照。不是另一个轴位置输入入口。", + "number": 55 + }, + { + "id": "preview-panLeft", + "name": "L 向左平移", + "detail": "向左平移相机观察中心。仅操作画布;“0”不会回零机床。", + "number": 56 + }, + { + "id": "preview-panRight", + "name": "R 向右平移", + "detail": "向右平移相机观察中心。仅操作画布;“0”不会回零机床。", + "number": 57 + }, + { + "id": "preview-panUp", + "name": "U 向上平移", + "detail": "向上平移相机观察中心。仅操作画布;“0”不会回零机床。", + "number": 58 + }, + { + "id": "preview-panDown", + "name": "D 向下平移", + "detail": "向下平移相机观察中心。仅操作画布;“0”不会回零机床。", + "number": 59 + }, + { + "id": "preview-reset", + "name": "0 重置视图", + "detail": "按当前预置视角和缩放重新取景。仅操作画布;“0”不会回零机床。", + "number": 60 + }, + { + "id": "override-jog-speed", + "name": "Jog Speed 点动速度", + "detail": "调整之后点动使用的速度比例,当前范围 6%–100%。与程序进给倍率不同;滑块本身不发起运动。", + "number": 61 + }, + { + "id": "override-feed", + "name": "Feed Override 进给倍率", + "detail": "按当前 INI 调整 0%–200% 程序进给倍率,可在自动运行时修改。不是修改 G-code 中的 F 值;快速倍率独立。", + "number": 62 + }, + { + "id": "override-spindle", + "name": "Spindle Override 主轴倍率", + "detail": "调整主轴输出速度比例。设为 0% 不会丢失方向和原指令速度,恢复倍率后按原方向输出。", + "number": 63 + }, + { + "id": "override-max-velocity", + "name": "Max Velocity 最大速度", + "detail": "调整轨迹规划器最大速度比例,当前为 6%–100% 适配。它是速度上限,不能代替 Rapid Override。", + "number": 64 + }, + { + "id": "override-rapid", + "name": "Rapid Override · 未实现", + "detail": "原生为快速运动倍率。当前选定 WASM TP 没有完整 rapidrate 控制,滑块禁用,不借用 Max Velocity 模拟。", + "number": 65 + }, + { + "id": "preview-layer-path", + "name": "path · 静态刀路", + "detail": "显示/隐藏当前程序解析得到的静态路径。只改变显示,不改变程序、偏置或运动状态。", + "number": 66 + }, + { + "id": "preview-layer-live", + "name": "live · 加工轨迹", + "detail": "显示/隐藏已采样 Live Plot,隐藏不会删除轨迹。只改变显示,不改变程序、偏置或运动状态。", + "number": 67 + }, + { + "id": "preview-layer-limits", + "name": "limits · 机床限位", + "detail": "显示/隐藏 WASM 提供的 XYZ 软限位框。只改变显示,不改变程序、偏置或运动状态。", + "number": 68 + }, + { + "id": "preview-layer-velocity", + "name": "velocity · 运动速度", + "detail": "显示/隐藏预览中的当前规范速度文字。只改变显示,不改变程序、偏置或运动状态。", + "number": 69 + }, + { + "id": "preview-layer-offsets", + "name": "offsets · 坐标偏置", + "detail": "显示/隐藏当前已支持的 G5x 平移偏置指示。只改变显示,不改变程序、偏置或运动状态。", + "number": 70 + }, + { + "id": "preview-layer-extents", + "name": "extents · 程序范围", + "detail": "显示/隐藏规范刀路样本的包围范围。只改变显示,不改变程序、偏置或运动状态。", + "number": 71 + }, + { + "id": "program-editor", + "name": "G-code 编辑区", + "detail": "修改待提交程序文本。修改后必须通过 Reload 重新提交才影响解释器;编辑文字不等于已经加载或执行。", + "number": 72 + }, + { + "id": "mdi-command", + "name": "MDI 指令输入", + "detail": "输入单条 G-code/M-code;Enter 与 Go 使用同一提交路径。提交会去除首尾空白,空输入不发送;执行受 manual_ok 与任务门控限制。", + "number": 73 + }, + { + "id": "mdi-submit", + "name": "Go 执行 MDI", + "detail": "将输入指令提交给 WASM 解释器。可能产生真实仿真运动或 IO 动作;收到 ACK 不代表排队运动已经完成。", + "number": 74 + }, + { + "id": "mdi-history-select", + "name": "MDI 历史条目", + "detail": "单击将该条指令填回输入框,双击重新提交执行。上下方向键浏览历史,相邻重复记录去重;历史并非执行成功证明。", + "number": 75 + }, + { + "id": "dro-coordinate", + "name": "Machine / Relative", + "detail": "切换机床坐标与相对工件坐标显示。当前相对投影支持已实现的 G5x 平移偏置,不用显示切换改写运动目标。", + "number": 76 + }, + { + "id": "dro-display", + "name": "Actual / Commanded", + "detail": "切换实际与指令位置的显示语义。当前理想仿真两者可相同,不能据标签推断已模拟真实跟随误差。", + "number": 77 + }, + { + "id": "dro-units", + "name": "mm / inch", + "detail": "切换线性坐标显示单位,A/C 仍为角度。该设置也用于界面点动和对刀输入的线性单位换算,不改写原程序。", + "number": 78 + }, + { + "id": "menu-file-edit-tool-data", + "name": "Edit tool data… · 未实现", + "detail": "桌面原生会启动工具表编辑器,浏览器没有对应宿主编辑流程,因此该菜单项禁用。", + "number": 79 + }, + { + "id": "menu-file-quit", + "name": "Quit · 未实现", + "detail": "桌面原生用于结束 AXIS 进程。Web 不模拟结束机床进程,此项禁用;可由浏览器关闭页面。", + "number": 80 + }, + { + "id": "menu-help-about", + "name": "About AXIS", + "detail": "显示本地 About 窗口,查看应用名称与案例信息;不会改变 Worker、任务或 IO 状态。", + "number": 81 + }, + { + "id": "about-close", + "name": "About 窗口 OK", + "detail": "关闭 About 窗口并返回原界面。属于界面操作,不等于命令确认、复位或启动。", + "number": 82 + }, + { + "id": "program-file-input", + "name": "文件选择对话框入口", + "detail": "隐藏的浏览器文件输入,由编号 05“打开 G-code”触发。选择 .ngc/.nc/.gcode 等文件后走同一加载事务;没有第二个可见按钮。", + "number": 83 + } + ], + "images": [ + "01-toolbar-and-workspace.png", + "02-manual-and-homing.png", + "03-views-and-overrides.png", + "04-mdi-dro-and-menus.png" + ] +} \ No newline at end of file diff --git a/scripts/generate_panel_png_guide.mjs b/scripts/generate_panel_png_guide.mjs new file mode 100644 index 0000000..5e601a9 --- /dev/null +++ b/scripts/generate_panel_png_guide.mjs @@ -0,0 +1,183 @@ +import assert from "node:assert/strict"; +import { mkdir, writeFile } from "node:fs/promises"; +import { resolve } from "node:path"; + +const modulePath = process.env.PLAYWRIGHT_MODULE ?? "/home/mes006/.npm/_npx/e41f203b7505f1fb/node_modules/playwright/index.js"; +const imported = await import(modulePath); +const { chromium } = imported.default ?? imported; +const url = process.env.XYZAC_PANEL_URL ?? "http://127.0.0.1:5175/"; +const out = resolve("docs/web-panel-png-guide"); +await mkdir(out, { recursive: true }); +const entries = []; +const add = (id, name, detail) => entries.push({ id, name, detail, number: entries.length + 1 }); +add("menu-file", "File 文件菜单", "展开文件菜单。当前包含工具表编辑和退出入口,二者受浏览器运行边界限制。"); +add("menu-help", "Help 帮助菜单", "展开帮助菜单,可打开 About 信息窗口;不向机床发送运动命令。"); +add("toolbar-estop", "急停 / 解除急停 · F1", "按当前状态切换急停。触发急停会中止当前执行和运动;解除后仍需单独上电。F1 在文本输入时也有效。"); +add("toolbar-power", "机床电源 · F2", "在解除急停后上电;再次点击断电。断电中止运动和任务。上电不会自动回零,也不会自动执行程序。"); +add("toolbar-open", "打开 G-code · o", "从本机选择程序文件并通过 Worker/WASM 加载、解析预览。执行活动或加载未结束时不可替换程序;取消选择不提交。"); +add("toolbar-load-case", "重新加载 XYZAC 案例", "重新载入选定 INI、HAL 等配置及其 OPEN_FILE 程序。这是 Web 工作区入口;不会自动上电、回零或运行。"); +add("toolbar-reload", "重新加载当前程序 · Ctrl+r", "将编辑区当前文本重新提交给解释器并生成静态预览。要求已有文件且允许加载;保留已有 Live Plot。"); +add("toolbar-run", "执行程序 · r", "切换 AUTO 并从第 0 行开始执行当前文件。任务层检查上电、回零等条件;完成或 Stop 后可直接再次 Run。"); +add("toolbar-step", "单步 · t", "执行下一处程序/运动边界。首次单步启动后暂停;已有运动队列时按执行边界推进,不等于每次恰好执行一行文本。"); +add("toolbar-pause-resume", "暂停 / 恢复", "同一按钮按当前状态切换 Pause 与 Resume,保留程序和运动队列。暂停仍属于活动任务,不能据此进行 Jog 或 Home。"); +add("toolbar-stop", "停止程序 · Esc", "中止当前任务及运动,保留所选程序。按钮按任务状态启用;Esc 也可停止手动运动。停止后重新 Run 从头开始。"); +add("toolbar-block-delete", "跳过 / 程序段 · 未实现", "原生功能用于跳过带斜杠的程序段。当前 WASM 未暴露完整状态,按钮保持禁用,不是本地开关。"); +add("toolbar-optional-pause", "可选停止 · 未实现", "原生功能控制是否在 M1 处停止。当前 ABI 未提供完整命令和状态,按钮保持禁用。"); +add("toolbar-zoom-in", "放大预览", "增大当前预览的相机缩放;仅改变显示,不改变进给、机床坐标或程序内容。"); +add("toolbar-zoom-out", "缩小预览", "减小预览的相机缩放,用于查看更大范围;不改变实际运动。"); +for (const [id, name, detail] of [ + ["z", "Z 顶视图", "正交投影,屏幕右/上对应 X/Y。"], ["z2", "Z2 旋转顶视图", "顶视图在屏幕平面旋转,右/上对应 Y/-X。"], + ["x", "X 侧视图", "正交投影,右/上对应 Y/Z。"], ["y", "Y 正视图", "正交投影,右/上对应 X/Z。"], + ["y2", "Y2 反向正视图", "原生工具栏附加方向,右/上对应 Z/X。"], ["p", "P 透视图", "三维透视观察刀路;可配合拖动、平移和缩放查看。"], +]) add(`toolbar-view-${id}`, name, `${detail} 点击后显示 Preview 页;不改变机床状态。`); +add("toolbar-rotate", "拖动 / 旋转模式", "切换鼠标左键拖动时的平移/旋转行为。按钮按下不代表自动旋转,也不控制旋转轴运动。"); +add("toolbar-clear-live-plot", "清除加工轨迹 · Ctrl+K", "仅清除 Live Plot 历史,保留静态程序预览。运行中清除后继续积累新轨迹;不会停止、重载或重启程序。"); +add("workspace-case-select", "仿真案例选择", "当前目录限定为支持的 XYZAC TRT 案例。选择本身不执行加载;重新载入使用工具栏的案例加载按钮。"); +add("workspace-load-3d-chips", "加载 3D_Chips.ngc", "打开随项目提供的示例程序,走同一 WASM 加载和预览流程。保留 Live Plot,执行前需另按 Run。"); +add("switchkins-0", "Identity · M429", "选择本案例 active_type=0 的恒等运动学。要求上电、已回零且无活动队列;M429 不会把模块 KINEMATICS_BOTH 类型改为 IDENTITY。"); +add("switchkins-1", "TCP: XYZAC · M428", "选择 active_type=1 的 XYZAC TRT 刀尖运动学,使用当前几何偏置进行变换。切换需任务空闲且运动队列为空。"); +add("switchkins-2", "User K · M430", "选择 active_type=2 的已链接用户运动学;当前为 identity 模板,不表示可在浏览器动态加载任意运动学模块。"); +add("tab-manual", "Manual Control · F3", "显示手动控制页,并在源门控允许时请求对应模式。AUTO 运行或暂停时,仅切换可见页签不会强制变为 MANUAL。"); +add("tab-mdi", "MDI · F5", "显示单条指令输入页,并在允许时请求 MDI 模式。提交指令仍受任务层门控约束。"); +add("tab-diagnostics", "Diagnostics 诊断", "查看工作区资源、禁用原因、操作记录和错误信息。浏览此页本身不执行运动或恢复操作。"); +add("manual-home-joint-select", "回零关节选择", "选择数字关节 0–4,仅决定 Home Joint 的目标。与下面 X/Y/Z/A/C 世界轴选择相互独立。"); +add("manual-home-axis", "Home Joint 单关节回零", "对选定数字关节运行原生 homemod。已回零时先确认;回零完成以 homing/homed 状态为准。不是 G53 返回机床零点。"); +add("manual-home-all", "HOME ALL / RE-HOME ALL", "按 INI HOME_SEQUENCE 发起全部关节回零。当前案例搜索/锁存速度为 0,可能在当前位置建立参考点而不产生电机位移。"); +for (const axis of ["x", "y", "z", "a", "c"]) add(`manual-axis-${axis}`, `选择 ${axis.toUpperCase()} 轴`, `选择世界坐标 ${axis.toUpperCase()} 作为 Jog、Touch Off 目标。选择本身不移动机床,也不修改回零关节选择。${["a", "c"].includes(axis) ? "旋转轴以度为单位。" : "线性轴按 mm/inch 显示单位处理。"}`); +add("manual-jog-negative", "Jog − 负向点动", "沿所选轴负方向运动。Continuous 按住运动、释放/失焦停止;增量模式提交一次指定距离,松开不截断该增量。"); +add("manual-jog-positive", "Jog + 正向点动", "沿所选轴正方向运动,使用当前步长和 Jog Speed。手动页可见且任务允许时生效;运行、暂停或回零期间不可开始点动。"); +add("manual-jog-increment", "点动步长", "Continuous 为持续点动;0.1000/0.0100/0.0010/0.0001 为单次增量。线性值遵循 mm/inch,A/C 不做英寸换算。"); +add("manual-touch-off", "Touch Off 坐标系对刀", "输入当前点应显示的坐标,再选择 P0 当前或 P1–P9 坐标系。通过 G10 L20 改偏置,不移动机床;取消对话框不执行。"); +add("manual-tool-touch-off", "Tool Touch Off · 未实现", "原生为刀具偏置测定,涉及 G10 L10/L11 和 G43。当前 ABI 不完整,禁用;不能用普通 Touch Off 冒充。"); +add("manual-override-limits", "Override Limits · 未实现", "原生用于限位触发后的脱离操作。当前面板没有对应完整状态/命令边界,禁用。"); +add("manual-spindle-ccw", "主轴逆时针", "发送主轴反转方向命令,选中状态来自 WASM 主轴方向。需上电、任务空闲;不同于 A/C 旋转轴点动。"); +add("manual-spindle-stop", "Stop Spindle", "停止主轴旋转。仅控制主轴,不等于停止正在执行的程序;程序停止使用工具栏 Stop。"); +add("manual-spindle-cw", "主轴顺时针", "发送主轴正转方向命令,运行方向和速度由规范快照回显;按钮不会设置本地伪运行状态。"); +add("manual-spindle-decrease", "降低主轴速度", "主轴方向非零时启用。按下发送减速边沿,释放发送 SPINDLE_CONSTANT;不会减速穿过零后自动变成反转。"); +add("manual-spindle-increase", "提高主轴速度", "主轴方向非零时启用。按下发送增速边沿,释放结束调速。主轴倍率与该指令速度分开处理。"); +add("manual-spindle-brake", "Brake 主轴制动", "请求接合或释放主轴制动,复选框由 WASM 制动状态回显。受手动操作门控约束。"); +add("manual-coolant-mist", "Mist 雾化冷却", "独立开关雾化冷却。手动页需上电且解释器空闲;与 Flood 相互独立,可同时开启。"); +add("manual-coolant-flood", "Flood 浇注冷却", "独立开关浇注冷却;状态来自 IO 快照,不因界面勾选而提前认定成功。"); +add("tab-preview", "Preview 刀路页", "查看静态程序刀路、加工轨迹和刀具位置。切换显示页不会加载文件、改变模式或发起运动。"); +add("tab-dro", "DRO 数显页", "切换至坐标数显与坐标/单位选择;其值来自 Worker 快照。不是另一个轴位置输入入口。"); +for (const [id, name, text] of [["panLeft", "L 向左平移", "向左平移相机观察中心"], ["panRight", "R 向右平移", "向右平移相机观察中心"], ["panUp", "U 向上平移", "向上平移相机观察中心"], ["panDown", "D 向下平移", "向下平移相机观察中心"], ["reset", "0 重置视图", "按当前预置视角和缩放重新取景"]]) add(`preview-${id}`, name, `${text}。仅操作画布;“0”不会回零机床。`); +add("override-jog-speed", "Jog Speed 点动速度", "调整之后点动使用的速度比例,当前范围 6%–100%。与程序进给倍率不同;滑块本身不发起运动。"); +add("override-feed", "Feed Override 进给倍率", "按当前 INI 调整 0%–200% 程序进给倍率,可在自动运行时修改。不是修改 G-code 中的 F 值;快速倍率独立。"); +add("override-spindle", "Spindle Override 主轴倍率", "调整主轴输出速度比例。设为 0% 不会丢失方向和原指令速度,恢复倍率后按原方向输出。"); +add("override-max-velocity", "Max Velocity 最大速度", "调整轨迹规划器最大速度比例,当前为 6%–100% 适配。它是速度上限,不能代替 Rapid Override。"); +add("override-rapid", "Rapid Override · 未实现", "原生为快速运动倍率。当前选定 WASM TP 没有完整 rapidrate 控制,滑块禁用,不借用 Max Velocity 模拟。"); +for (const [id, name, detail] of [["path", "静态刀路", "显示/隐藏当前程序解析得到的静态路径"], ["live", "加工轨迹", "显示/隐藏已采样 Live Plot,隐藏不会删除轨迹"], ["limits", "机床限位", "显示/隐藏 WASM 提供的 XYZ 软限位框"], ["velocity", "运动速度", "显示/隐藏预览中的当前规范速度文字"], ["offsets", "坐标偏置", "显示/隐藏当前已支持的 G5x 平移偏置指示"], ["extents", "程序范围", "显示/隐藏规范刀路样本的包围范围"]]) add(`preview-layer-${id}`, `${id} · ${name}`, `${detail}。只改变显示,不改变程序、偏置或运动状态。`); +add("program-editor", "G-code 编辑区", "修改待提交程序文本。修改后必须通过 Reload 重新提交才影响解释器;编辑文字不等于已经加载或执行。"); +add("mdi-command", "MDI 指令输入", "输入单条 G-code/M-code;Enter 与 Go 使用同一提交路径。提交会去除首尾空白,空输入不发送;执行受 manual_ok 与任务门控限制。"); +add("mdi-submit", "Go 执行 MDI", "将输入指令提交给 WASM 解释器。可能产生真实仿真运动或 IO 动作;收到 ACK 不代表排队运动已经完成。"); +add("mdi-history-select", "MDI 历史条目", "单击将该条指令填回输入框,双击重新提交执行。上下方向键浏览历史,相邻重复记录去重;历史并非执行成功证明。"); +add("dro-coordinate", "Machine / Relative", "切换机床坐标与相对工件坐标显示。当前相对投影支持已实现的 G5x 平移偏置,不用显示切换改写运动目标。"); +add("dro-display", "Actual / Commanded", "切换实际与指令位置的显示语义。当前理想仿真两者可相同,不能据标签推断已模拟真实跟随误差。"); +add("dro-units", "mm / inch", "切换线性坐标显示单位,A/C 仍为角度。该设置也用于界面点动和对刀输入的线性单位换算,不改写原程序。"); +add("menu-file-edit-tool-data", "Edit tool data… · 未实现", "桌面原生会启动工具表编辑器,浏览器没有对应宿主编辑流程,因此该菜单项禁用。"); +add("menu-file-quit", "Quit · 未实现", "桌面原生用于结束 AXIS 进程。Web 不模拟结束机床进程,此项禁用;可由浏览器关闭页面。"); +add("menu-help-about", "About AXIS", "显示本地 About 窗口,查看应用名称与案例信息;不会改变 Worker、任务或 IO 状态。"); +add("about-close", "About 窗口 OK", "关闭 About 窗口并返回原界面。属于界面操作,不等于命令确认、复位或启动。"); +add("program-file-input", "文件选择对话框入口", "隐藏的浏览器文件输入,由编号 05“打开 G-code”触发。选择 .ngc/.nc/.gcode 等文件后走同一加载事务;没有第二个可见按钮。"); +assert.equal(entries.length, 83); +const byId = new Map(entries.map((entry) => [entry.id, entry])); +const covered = new Set(); +const escape = (s) => String(s).replaceAll("&", "&").replaceAll("<", "<").replaceAll('"', """); +const browser = await chromium.launch({ headless: false, executablePath: "/usr/bin/google-chrome", slowMo: 90 }); +const page = await browser.newPage({ viewport: { width: 1600, height: 1100 }, deviceScaleFactor: 2 }); +const errors = []; +page.on("pageerror", (error) => errors.push(error.message)); +page.on("dialog", (dialog) => dialog.dismiss()); +async function capture(selector, title, ids) { + const locator = page.locator(selector); + await locator.scrollIntoViewIfNeeded(); + await page.waitForTimeout(180); + const bounds = await locator.boundingBox(); + const marks = []; + for (const id of ids) { + assert.ok(byId.has(id), `unknown id ${id}`); + const control = locator.locator(`[data-axis-control="${id}"]`); + if (!await control.count()) continue; + if (!await control.first().isVisible()) continue; + const box = await control.first().boundingBox(); + marks.push({ ...byId.get(id), x: box.x - bounds.x, y: box.y - bounds.y, w: box.width, h: box.height }); + covered.add(id); + } + const image = await locator.screenshot(); + return { title, image: image.toString("base64"), width: bounds.width, height: bounds.height, marks }; +} +const ids = (prefix) => entries.filter((e) => e.id.startsWith(prefix)).map((e) => e.id); +const docs = []; +try { + await page.goto(url); + await page.waitForFunction(() => document.querySelector("main")?.dataset.axisProgramLoading === "false"); + await page.locator('[data-axis-control="toolbar-power"]').click(); + await page.locator('[data-axis-control="manual-home-all"]').click(); + await page.waitForFunction(() => document.querySelector(".command-status")?.textContent === "HOME complete"); + await page.evaluate(() => scrollTo(0, 0)); + await page.screenshot({ path: `${out}/00-panel-overview-hd.png`, fullPage: true }); + docs.push({ file: "01-toolbar-and-workspace", title: "工具栏与文件操作", note: "截图状态:XYZAC TRT 已上电、已回零、程序空闲。灰色按钮须结合禁用原因判断,不代表点击后可以执行。", captures: [ + await capture(".axis-menubar", "文件 / 帮助菜单入口", ["menu-file", "menu-help"]), + await capture(".axis-toolbar", "机器与程序工具栏 · 图标从左至右", ids("toolbar-")), + await capture(".axis-case-strip", "案例与示例程序", ids("workspace-")), + ], extra: ["program-file-input"] }); + docs.push({ file: "02-manual-and-homing", title: "手动操作与原生回零", note: "Home Joint 选择数字关节;Jog/Touch Off 选择世界轴。当前案例 Home 可能只重新建立坐标参考点,电机位置不变,这是原生 INI 回零语义。", captures: [ + await capture(".left-notebook", "Manual Control 手动页", [...ids("tab-").filter((id) => ["tab-manual", "tab-mdi", "tab-diagnostics"].includes(id)), ...ids("manual-")]), + ] }); + docs.push({ file: "03-views-and-overrides", title: "运动学、视图与倍率", note: "Switchkins 改变运动学解释;相机与图层仅改变显示。Feed、Spindle、Jog 和 Max Velocity 各有独立含义,不能互相代替。", captures: [ + await capture(".xyzac-kinematics", "Switchkins 运动学模式", ids("switchkins-")), + await capture(".right-notebook", "Preview / DRO 与画布平移", ["tab-preview", "tab-dro", ...ids("preview-pan"), "preview-reset"]), + await capture(".axis-metrics", "倍率滑块与预览图层", [...ids("override-"), ...ids("preview-layer-")]), + await capture(".axis-program-pane", "程序编辑与执行记录", ["program-editor"]), + ] }); + await page.locator('[data-axis-control="tab-mdi"]').click(); + await page.locator('[data-axis-control="mdi-command"]').fill("G21"); + await page.locator('[data-axis-control="mdi-submit"]').click(); + await page.waitForFunction(() => document.querySelector(".command-status")?.textContent === "MDI_EXECUTE acknowledged"); + const mdi = await capture(".left-notebook", "MDI 单条指令与历史", ids("mdi-")); + await page.locator('[data-axis-control="tab-dro"]').click(); + const dro = await capture(".right-notebook", "DRO 数显设置", ids("dro-")); + await page.locator('[data-axis-control="menu-file"]').click(); + const fileMenu = await capture('.axis-menu-item:has([data-axis-control="menu-file"]) .axis-menu-popup', "File 菜单展开", ["menu-file-edit-tool-data", "menu-file-quit"]); + await page.locator('[data-axis-control="menu-file"]').click(); + await page.locator('[data-axis-control="menu-help"]').click(); + const helpMenu = await capture('.axis-menu-item:has([data-axis-control="menu-help"]) .axis-menu-popup', "Help 菜单展开", ["menu-help-about"]); + await page.locator('[data-axis-control="menu-help-about"]').click(); + const about = await capture('.axis-about-dialog', "About 弹窗", ["about-close"]); + docs.push({ file: "04-mdi-dro-and-menus", title: "MDI、数显与菜单窗口", note: "MDI 示例仅提交 G21(毫米单位),未执行加工运动。错误及禁用原因以当前状态栏与 Diagnostics 为准。", captures: [mdi, dro, fileMenu, helpMenu, about] }); + covered.add("program-file-input"); + assert.deepEqual(entries.filter((e) => !covered.has(e.id)).map((e) => e.id), [], "unannotated controls"); + assert.deepEqual(errors, []); + const reportPage = await browser.newPage({ viewport: { width: 1800, height: 1200 }, deviceScaleFactor: 2 }); + const paths = []; + for (const doc of docs) { + const blocks = doc.captures.map((cap) => { + const scale = Math.min(1.2, 1672 / cap.width); + const width = cap.width * scale; + const height = cap.height * scale; + // Put badges in lanes outside small controls, with a leader to each target. + const used = []; + const badges = cap.marks.map((mark) => { + let x = Math.max(14, Math.min(width - 14, (mark.x + mark.w / 2) * scale)); + let y = mark.y * scale + 60 - 16; + while (used.some((p) => Math.abs(p.x - x) < 34 && Math.abs(p.y - y) < 28)) y -= 30; + used.push({ x, y }); + const tx = (mark.x + mark.w / 2) * scale, ty = (mark.y + mark.h / 2) * scale + 60; + return `${mark.number}`; + }).join(""); + return `

${cap.title}

${badges}
${cap.marks.map((e) => `
${e.number}

${escape(e.name)}

${escape(e.detail)}

${e.id}
`).join("")}
`; + }).join(""); + const extra = (doc.extra ?? []).map((id) => { const e = byId.get(id); return `
${e.number}

${escape(e.name)}

${escape(e.detail)}

`; }).join(""); + const html = `${doc.title}
LinuxCNC AXIS Web/WASM · XYZAC TRT · 控件功能图解 ${doc.file.slice(0,2)}/04

${doc.title}

${doc.note}

${blocks}${extra}
红色编号指向实际控件;说明依据当前 Web 实现与源流程契约。灰色“未实现”项不代表已支持。截图来源:${url} · 2026-09-09 · PNG 2× 清晰度
`; + await writeFile(`${out}/${doc.file}.html`, html); + await reportPage.setContent(html); + await reportPage.evaluate(() => document.fonts.ready); + await reportPage.waitForTimeout(250); + assert.equal(await reportPage.evaluate(() => document.documentElement.scrollWidth <= innerWidth), true); + await reportPage.screenshot({ path: `${out}/${doc.file}.png`, fullPage: true }); + paths.push(`${doc.file}.png`); + } + await writeFile(`${out}/controls.json`, JSON.stringify({ url, controls: entries, images: paths }, null, 2)); + console.log(JSON.stringify({ status: "verified", controls: entries.length, annotated: covered.size, output: out, images: paths })); +} finally { await browser.close(); } diff --git a/web/react/src/XyzacToolPreview.tsx b/web/react/src/XyzacToolPreview.tsx index a25deee..17b6df5 100644 --- a/web/react/src/XyzacToolPreview.tsx +++ b/web/react/src/XyzacToolPreview.tsx @@ -404,7 +404,7 @@ export function XyzacToolPreview({ visual, view = "p", zoom = 1, rotateMode = fa element.dataset.xyzacLimitsVisible = String(limitGrid.visible); element.dataset.xyzacExtentsVisible = String(extents.visible); element.dataset.xyzacOffset = JSON.stringify(offset); - if (hudRef.current) hudRef.current.textContent = `TOOL PREVIEW\nX ${Number(renderedPose.x).toFixed(3)} Y ${Number(renderedPose.y).toFixed(3)} Z ${Number(renderedPose.z).toFixed(3)}\nA ${Number(renderedPose.a).toFixed(3)} C ${Number(renderedPose.c).toFixed(3)}\nJ0 ${Number(renderedJoints[0] ?? 0).toFixed(3)} J1 ${Number(renderedJoints[1] ?? 0).toFixed(3)} J2 ${Number(renderedJoints[2] ?? 0).toFixed(3)}\nJ3 ${Number(renderedJoints[3] ?? 0).toFixed(3)} J4 ${Number(renderedJoints[4] ?? 0).toFixed(3)}`; + if (hudRef.current) hudRef.current.textContent = `TOOL PREVIEW\nX ${Number(renderedPose.x).toFixed(3)} Y ${Number(renderedPose.y).toFixed(3)} Z ${Number(renderedPose.z).toFixed(3)}\nA ${Number(renderedPose.a).toFixed(3)} C ${Number(renderedPose.c).toFixed(3)}`; if (layer.showVelocity && hudRef.current) hudRef.current.textContent += `\nV ${Number(state.velocityMmMin ?? 0).toFixed(1)} mm/min`; controls.mouseButtons.LEFT = rotateRef.current ? THREE.MOUSE.ROTATE : THREE.MOUSE.PAN; controls.update(); renderer.render(scene, camera); frame = requestAnimationFrame(render); @@ -417,7 +417,7 @@ export function XyzacToolPreview({ visual, view = "p", zoom = 1, rotateMode = fa const helixCount = visual.toolpath.filter((segment) => (segment as { kind?: string }).kind === "helix").length; const sampleCount = visual.toolpath.reduce((count, segment) => count + (Array.isArray((segment as { samples?: unknown[] }).samples) ? (segment as { samples: unknown[] }).samples.length : 0), 0); const controllerButton = (action: string, label: string, glyph: string) => ["zoomIn", "zoomOut"].includes(action) ? null : ; - return
{controllerButton("zoomIn", "Zoom in", "+")}{controllerButton("zoomOut", "Zoom out", "-")}
{visual.authoritative ? `TOOL PREVIEW\nX ${Number(pose.x).toFixed(3)}  Y ${Number(pose.y).toFixed(3)}  Z ${Number(pose.z).toFixed(3)}\nA ${Number(pose.a).toFixed(3)}  C ${Number(pose.c).toFixed(3)}\nJ0 ${Number(visual.joints[0]).toFixed(3)}  J1 ${Number(visual.joints[1]).toFixed(3)}  J2 ${Number(visual.joints[2]).toFixed(3)}\nJ3 ${Number(visual.joints[3]).toFixed(3)}  J4 ${Number(visual.joints[4]).toFixed(3)}` : "TOOL PREVIEW\nWASM state pending"}
; + return
{controllerButton("zoomIn", "Zoom in", "+")}{controllerButton("zoomOut", "Zoom out", "-")}
{visual.authoritative ? `TOOL PREVIEW\nX ${Number(pose.x).toFixed(3)}  Y ${Number(pose.y).toFixed(3)}  Z ${Number(pose.z).toFixed(3)}\nA ${Number(pose.a).toFixed(3)}  C ${Number(pose.c).toFixed(3)}` : "TOOL PREVIEW\nWASM state pending"}
; } export function XyzacToolPreviewFromSnapshot({ snapshot, ...props }: Omit & { snapshot: XyzacVisualSource | null | undefined }) { diff --git a/web/react/src/XyzacTrtPanel.tsx b/web/react/src/XyzacTrtPanel.tsx index 0bb2009..fdc54a3 100644 --- a/web/react/src/XyzacTrtPanel.tsx +++ b/web/react/src/XyzacTrtPanel.tsx @@ -24,7 +24,7 @@ export function XyzacManualPanel({ view }: { view: XyzacPanelView }) { return
XYZAC authority{view.kinematics?.linear_units ?? "mm"} / {view.kinematics?.angular_units ?? "deg"}
- {axes.map((axis, index) =>
{axis.toUpperCase()}{pose ? Number(pose[axis] ?? Number.NaN).toFixed(axis === "a" || axis === "c" ? 3 : 4) : "-"}J{index} {view.joints.length === 5 ? Number(view.joints[index]).toFixed(4) : "-"}
)} + {axes.map((axis) =>
{axis.toUpperCase()}{pose ? Number(pose[axis] ?? Number.NaN).toFixed(axis === "a" || axis === "c" ? 3 : 4) : "-"}
)}
Tool {view.kinematics ? Number(view.kinematics.offsets.tool_offset).toFixed(3) : "-"}Y offset {view.kinematics ? Number(view.kinematics.offsets.y_offset).toFixed(3) : "-"}Z offset {view.kinematics ? Number(view.kinematics.offsets.z_offset).toFixed(3) : "-"}
;