diff --git a/pic/600x500.png b/pic/600x500.png
new file mode 100644
index 0000000..1083ab9
Binary files /dev/null and b/pic/600x500.png differ
diff --git a/pic/ai-button-disabled.png b/pic/ai-button-disabled.png
new file mode 100644
index 0000000..e4dbf62
Binary files /dev/null and b/pic/ai-button-disabled.png differ
diff --git a/pic/ai-button.png b/pic/ai-button.png
new file mode 100644
index 0000000..76eb13c
Binary files /dev/null and b/pic/ai-button.png differ
diff --git a/pic/common-bg.png b/pic/common-bg.png
index 5db5436..2f247d4 100644
Binary files a/pic/common-bg.png and b/pic/common-bg.png differ
diff --git a/pic/x1Y2.png b/pic/x1Y2.png
index 0efcb3a..a0d5196 100644
Binary files a/pic/x1Y2.png and b/pic/x1Y2.png differ
diff --git a/pic/制丸线HMI界面UniTouch布局202500915.xd b/pic/制丸线HMI界面UniTouch布局202500915.xd
index 5b389a7..f8e1375 100644
Binary files a/pic/制丸线HMI界面UniTouch布局202500915.xd and b/pic/制丸线HMI界面UniTouch布局202500915.xd differ
diff --git a/pic/组 1833.png b/pic/组 1833.png
index 6e8a4c1..dbec485 100644
Binary files a/pic/组 1833.png and b/pic/组 1833.png differ
diff --git a/pic/组 1985.png b/pic/组 1985.png
new file mode 100644
index 0000000..0d07127
Binary files /dev/null and b/pic/组 1985.png differ
diff --git a/pic/组 1986.png b/pic/组 1986.png
new file mode 100644
index 0000000..ec38e23
Binary files /dev/null and b/pic/组 1986.png differ
diff --git a/unitouch.cmtp b/unitouch.cmtp
index b8dbab4..0aad559 100644
Binary files a/unitouch.cmtp and b/unitouch.cmtp differ
diff --git a/界面开发记录.md b/界面开发记录.md
index 9cde589..f025c34 100644
--- a/界面开发记录.md
+++ b/界面开发记录.md
@@ -13,13 +13,11 @@
| 文件 | 说明 |
| --- | --- |
| `unitouch.cmtp`(+ bak1~3) | EB Pro 工程文件 |
-| `unitouch.cxob` | 编译输出(gzip→tar:`config`/`mt8000/project`/`runtime`/`fonts`) |
| `unitouch.debug` | 调试数据 |
| `lwaddr.xls` / `lwaddr.csv` | 系统地址大全(1429 条,查系统寄存器用) |
| `制丸线HMI界面UniTouch布局202500915.xd` | XD 设计源(18 画板) |
-| `msg-login.txt` | 登录提示宏源码(记事本复制用) |
-`config`:`MachineIds=[216702]` / `Resolution=1920x1080` / `SocType=arm64`。
+> `unitouch.cxob` 是编译输出,已加入 `.gitignore`,不再入库。
XD 画板:`A_start`、`B_PID`、`C_运行1~3`、`D_点动1/2`、`E_配方1~3`、`F_设备参数2`、`G_清洗主机1`、`H_报警1`、`I_数据1~3`、`J_关于`。
@@ -28,25 +26,67 @@ XD 画板:`A_start`、`B_PID`、`C_运行1~3`、`D_点动1/2`、`E_配方1~3`
| 窗口 | 名称 | 用途 |
| --- | --- | --- |
| 4 | — | 白色底窗口(层叠底层) |
-| 10 | `start-login` | 启动登录页 |
-| 11 | — | 无权限提示弹窗(600×300,位 `LB-110`) |
-| 12 | — | 修改时间弹窗(位 `LB-120`) |
-| 13 | `about` | 关于(1200×800 弹窗,位 `LB-123`) |
-| 14 | `用户管理` | 用户管理弹窗(位 `LB-122`) |
-| 15 | — | 删除确认弹窗(位 `LB-121`) |
-| 20 | `点检` | 启动点检页(1920×1080 全屏) |
-| 100 | `common window joyea` | 公共窗口(顶部栏/导航/常驻元件) |
+| 5~9 | — | EB Pro 系统窗口(Device Response / HMI Connection / Password Restriction / Storage / Backup),不改内容 |
+| 10 | 登陆和入口画面 | 登录 + 入口;窗口开启执行 `logout` |
+| 11 | 弹出 | 无权限提示弹窗(600×300,位 `LB-110`) |
+| 12 | 修改时间 | 修改时间弹窗(位 `LB-120`) |
+| 13 | 系统IP和关于 | 关于 + 设置(1200×800 弹窗,位 `LB-123`) |
+| 14 | 用户管理 | 用户管理弹窗(位 `LB-122`,开启宏 `usr-init`) |
+| 15 | 用户删除确认 | 删除确认弹窗(位 `LB-121`) |
+| 16 | 空页面弹窗 | 无内容提示弹窗(600×300,位 `LB-124`) |
+| 17 | 超管登陆 | 管理员登录弹窗(600×360,位 `LB-125`) |
+| 20 | 点检check | 点检画面(可退出,暂无功能) |
+| 100 | `common-window-joyea` | 公共窗口(顶部栏/导航/常驻元件) |
| 101~128 | `X1Y1` ~ `X4Y7` | 主画面,共 28 个 |
## 4. 命名与导航
- 画面名:`X{段}Y{功能}_{工艺段}_{功能}`
-- **X(工艺段)**:`X1 配料/上料`、`X2 制丸1`、`X3 制丸2`、`X4 清洗`
+- **X(工艺段)**:`X1 配料/上料`、`X2 上料清洗`、`X3 制丸`、`X4 制丸清洗`
- **Y(功能)**:`Y1 初始状态`、`Y2 运行`、`Y3 配方`、`Y4 设备参数`、`Y5 I/O监控`、`Y6 报警`、`Y7 数据趋势`
- **窗口号**:`WIN = 101 + (X-1)*7 + (Y-1)`(101~128)
- **导航机制**:按钮宏把 X/Y 与目标窗口号写入 `LW-0/1/2`,由 **PLC 控制元件「切换基本窗口」**(触发地址 `LW-2`,回写 `LW-3`)执行切窗。
- 顶部「运行/点动」为全局状态,暂不参与 X/Y 导航。
+### 4.1 权限分配总表(按用户组)
+
+> 权限分三级:**● 拥有权限**(可操作)、**○ 仅可见**(看得到,点了弹 11 号无权限窗)、**× 不可见**(直接隐藏,看不到)。
+> 类别:A=工程师、B=管理员、C=上料、D=制丸;内定 `admin` 权限全开,所以整行都是 ●(对 × 的元件它也一样可见可操作)。
+> 未登录时类别位为 0,所有受限项按无权限处理。
+
+| 功能 / 页面 | 工程师 A | 管理员 B | 上料 C | 制丸 D | admin |
+| --- | :-: | :-: | :-: | :-: | :-: |
+| 登录 / 注销(10 号登录页) | ● | ● | ● | ● | ● |
+| 顶部当前账户 + 长按 1s 注销 | ● | ● | ● | ● | ● |
+| 点检页(20 号,入口 + 下一步) | ● | ● | ● | ● | ● |
+| 导航 X1 配料/上料 | ● | ● | ● | ○ | ● |
+| 导航 X2 上料清洗 | ● | ● | ● | ○ | ● |
+| 导航 X3 制丸 | ● | ● | ○ | ● | ● |
+| 导航 X4 制丸清洗 | ● | ● | ○ | ● | ● |
+| 导航 Y1 初始状态 | ● | ● | ● | ● | ● |
+| 导航 Y2 运行 | ● | ● | ● | ● | ● |
+| 导航 Y3 配方 | ● | ● | ● | ● | ● |
+| 导航 Y4 设备参数 | ● | ● | ○ | ○ | ● |
+| 导航 Y5 I/O 监控 | ● | ● | ○ | ○ | ● |
+| 导航 Y6 报警(含列表/确认) | ● | ● | ● | ● | ● |
+| 导航 Y7 数据趋势 | ● | ● | ● | ● | ● |
+| 用户管理(14 号窗:新增/删除/改权限/改密码) | × | ● | × | × | ● |
+| 修改时间(12 号窗) | × | ● | × | × | ● |
+| 关于(13 号窗) | ● | × | × | × | ● |
+| X1Y1 节点状态人工修正(数值输入) | ● | × | × | × | ● |
+| 无权限提示(11 号窗)/ 无内容提示(16 号窗) | 系统自动 | 系统自动 | 系统自动 | 系统自动 | 系统自动 |
+
+**三级怎么在 EB Pro 里设置**
+
+| 级别 | 元件设置方法 |
+| --- | --- |
+| ● 拥有权限 | 元件不勾安全,照旧由宏按 `LW-9222` 放行(现状) |
+| ○ 仅可见 | 元件不勾安全,宏校验不通过 → 弹 11 号无权限窗,元件保持可见(现状) |
+| × 不可见 | 元件「安全」页:勾「启用」→ 操作类别只勾有权组 → 勾「无权限时隐藏」 |
+
+> × 一共 4 处、6 个元件:用户管理按钮、时钟上的透明按钮(修改时间)、关于按钮、X1Y1 的节点修正数值输入框(两组各 3 个)。
+> 若希望「仅可见」点了不弹提示,把对应宏里 `LB-110` 那一行删掉即可(变成纯无反应)。
+
## 5. 地址规划
### 5.1 导航 / 公共
@@ -57,6 +97,7 @@ XD 画板:`A_start`、`B_PID`、`C_运行1~3`、`D_点动1/2`、`E_配方1~3`
| `LW-1` | Y(1~7) |
| `LW-2` | 目标窗口号(PLC 控制元件触发地址) |
| `LW-3` | 当前窗口号(PLC 控制元件回写) |
+| `LW-70`~`73` | **页面存在位图**:bit0=Y1 … bit6=Y7,1=该页有内容;X1/X2/X3/X4 段分别对应 `LW-70/71/72/73` |
| `LW-9222` | 当前登录用户类别位(bit0=A 工程师 / bit1=B 管理员 / bit2=C 上料 / bit3=D 制丸;0=未登录) |
### 5.2 弹窗 / 状态位
@@ -68,6 +109,8 @@ XD 画板:`A_start`、`B_PID`、`C_运行1~3`、`D_点动1/2`、`E_配方1~3`
| `LB-121` | 删除确认弹窗(→ 15 号窗) |
| `LB-122` | 用户管理弹窗(→ 14 号窗) |
| `LB-123` | 关于弹窗(→ 13 号窗) |
+| `LB-124` | 无内容提示弹窗(→ 16 号窗) |
+| `LB-125` | 管理员登录弹窗(→ 17 号窗) |
| `LB-131` | 三个 PLC 联机汇总(触发条件 AND → 位状态指示灯) |
### 5.3 控制地址(高级安全模式)
@@ -115,9 +158,7 @@ XD 画板:`A_start`、`B_PID`、`C_运行1~3`、`D_点动1/2`、`E_配方1~3`
| 地址 | 用途 |
| --- | --- |
-| `LW-260` | 登录提示字符串(字符框 16 words) |
| `LW-261` | 登录提示**字符串表编号**(0 空 / 1 成功 / 2 不存在 / 3 密码错 / 4 无法执行 / 5 名称不合法 / 6 密码无效 / 7 登录失败) |
-| `LW-20` | 点检位(`LW_Bit-2000`~`2008` 设备状态 9 项;`LW_Bit-2009`/`2010` 物料状态 2 项;全勾=`2047`) |
| `LW-9017`~`9022` | RTC:秒/分/时/日/月/年(写入即设置时间) |
| `LW-40`~`45` | 改时间暂存:秒/分/时/日/月/年 |
@@ -145,168 +186,960 @@ XD 画板:`A_start`、`B_PID`、`C_运行1~3`、`D_点动1/2`、`E_配方1~3`
> 网络写回控制位:`LB-12041` 刷新、`LB-12094`/`LB-12095` 更新(写 IP/掩码/网关后置 ON)、`LB-12822` 桥接模式。
+### 5.8 通用程序:3 台 PLC / 多屏通用配置
+
+> 一套工程,上料屏 / 制丸A屏 / 制丸B屏通用;换屏、换 PLC 只在 **13 号窗**改配置,现场不需要 EasyBuilder。
+
+**工程里的设备划分(两个以太网设备槽)**
+
+| 设备 | 绑定内容 | 上料屏 | 制丸A屏 | 制丸B屏 |
+| --- | --- | --- | --- | --- |
+| `设备4`:上料 PLC | X1/X2 画面、C 组数据 | 上料 PLC 的 IP | 上料 PLC 的 IP | 上料 PLC 的 IP |
+| `设备5`:制丸 PLC | X3/X4 画面、D 组数据 | A 或 B(D 登录后切) | A 的 IP | B 的 IP |
+
+- 制丸A屏、制丸B屏各自只连「自己的 PLC + 上料 PLC」,**互相看不见**;
+- 上料屏 D 登录:用「A/B 切换」按钮在 `设备5` 的 IP 间切(同一时间看一条线);**默认 A,只有人工切换才到 B,重启回 A**;按钮暂放 13 号窗(能开 13 号窗的是工程师 A / admin),后续再移到制丸页给 D 用;
+- 换屏 / 换 PLC:备件装同程序 → 13 号窗填 IP/角色 → 点「应用」即可。
+
+**13 号窗字段(全部存 `RW`,掉电保持)**
+
+| 字段 | 地址 | 写入的系统寄存器 |
+| --- | --- | --- |
+| HMI IP / 掩码 / 网关 | `RW-20`~`31` | `LW-9129`~`9132` / `LW-10750`~`10753` / `LW-9125`~`9128` + `LB-12094`(备屏/换屏用;HMI 固定 IP 必填) |
+| 上料 PLC IP | `RW-40`~`43` | `LW-9600`~`9603`(设备4) + `LB-10070` |
+| 制丸A PLC IP | `RW-44`~`47` | 选 A 时 → `LW-9605`~`9608`(设备5) + `LB-10071` |
+| 制丸B PLC IP | `RW-48`~`51` | 选 B 时 → `LW-9605`~`9608`(设备5) + `LB-10071` |
+| 本机角色 | `RW-60`:1=上料屏 / 2=制丸A屏 / 3=制丸B屏 | 角色 2/3 自动锁线别;**角色=0 不连制丸设备(防误连)** |
+| 制丸线选择 | `RW-61`:1=A 线 / 2=B 线 | 上料屏手动选;制丸屏由角色决定 |
+
+> 设备槽号按你工程实际(以太网设备从 4 号起):设备5 → `LW-9605`/`LB-10071`,设备6 → `LW-9610`/`LB-10072`。设备号查看:EB Pro 设备列表,或显示 `LW-9300`~`9306`(0=该槽无设备)。
+
+**切换互锁(防旧数据/防误操作)**
+
+| 用途 | 地址 | 说明 |
+| --- | --- | --- |
+| 设备4 通讯状态 | `LB-10100` | 上料 PLC:ON=已连接;写 ON 可重连一次 |
+| 设备5 通讯状态 | `LB-10400` | 制丸 PLC:ON=已连接;写 ON 可重连一次 |
+| 错误码 | `LW-9403` / `LW-9404` | 设备4 / 设备5 |
+| 禁止系统弹窗 | `LB-11963` / `LB-11964` | 置 ON:不弹设备4/5 的 “Device No Response” |
+
+- 制丸页放「通讯正常」指示灯 = `LB-10400`;A/B 切换后(或刚上电)**等它变 ON 再操作**,避免按到旧画面数据;
+- 切换按钮(`line-ab-switch`)只负责切 IP 和重连,不等待;互锁交给指示灯/操作条件。
+- **A/B 切换按钮只在上料屏(`RW-60`=1)生效**:制丸A/B 屏线别由角色锁死,宏内已挡,admin 登录也切不动。
+
+### 5.9 拓扑图
+
+> 三台 PLC、三台 HMI 都接在 PN 交换机(同一网段);图中画的是**逻辑连接**(每台 HMI 只连它需要的那两台 PLC)。
+
+```mermaid
+graph LR
+ P1["S7-1500
上料/配料 PLC"]
+ PA["S7-1500
制丸A PLC"]
+ PB["S7-1500
制丸B PLC"]
+ H1["HMI 上料屏
role=1"]
+ H2["HMI 制丸A屏
role=2"]
+ H3["HMI 制丸B屏
role=3"]
+ H1 -- "设备4" --> P1
+ H1 -. "设备5(A/B 可切)" .-> PA
+ H1 -.-> PB
+ H2 -- "设备4" --> P1
+ H2 -- "设备5" --> PA
+ H3 -- "设备4" --> P1
+ H3 -- "设备5" --> PB
+```
+
+**说明**
+
+- 一套工程烧 3 台屏;装机时在 13 号窗设:本机角色 `RW-60`、线别 `RW-61`、上料 IP `RW-40~43`、制丸A IP `RW-44~47`、制丸B IP `RW-48~51` → 点「应用」;
+- 用户组:C(上料)→ X1/X2(绑 `设备4`);D(制丸)→ X3/X4(绑 `设备5`);`admin` 全开;
+- 制丸A屏只连「A 的 PLC + 上料 PLC」;制丸B屏只连「B 的 PLC + 上料 PLC」;**A/B 互不可见**;
+- 上料屏 D 登录后可用「A/B 切换」按钮切换 `设备5` 指向(仅 role=1 生效);按钮暂放 13 号窗,后续再移到制丸页。
+
## 6. 宏清单
-> 命名:导航/权限类 = `btn-*`、登录 = `main-init`/`btn-login-index`/`logout`、用户管理 = `usr-*`、点检 = `insp-*`、时间 = `open-time`/`set-time`/`close-time`/`-`、提示 = `msg-login`、弹窗 = `close-msg`。
+> 命名:导航 = `btn-*`、登录 = `main-init`/`btn-login-index`/`logout`、管理员登录 = `admin-open`/`admin-login`/`admin-close`、用户管理 = `user-open` + `usr-*`(你的工程删除类为 `usr-delete*`)、关于窗 = `about-open`/`about-close`、时间 = `open-time`/`set-time`/`close-time`、弹窗 = `close-msg`/`close-nopage`。
+> **登录提示已内联**:`LW-101` 结果码 → `LW-261` 的映射直接写在 `btn-login-index`/`admin-login` 内,零延迟、不轮询、不依赖宏编号。`net-apply` 用宏属性「当 HMI 启动时即执行一次」。
> 权限判定统一用 `LW-9222` 的类别位(`GETBIT` 取值 + `if`,不用 `and`/`&`)。
**`main-init`**(开机执行一次)
```
-macro_command main()
- short x = 1, y = 1, win = 0
- SetData(x, "Local HMI", LW, 0, 1)
- SetData(y, "Local HMI", LW, 1, 1)
- SetData(win, "Local HMI", LW, 2, 1)
-end macro_command
+macro_command main() // 宏入口:HMI 启动时执行一次
+ short x = 1 // X 初值 = 1
+ short y = 1 // Y 初值 = 1
+ short win = 0 // 目标窗口号初值 = 0(不切窗)
+ short r1 = 127 // X1 段存在位图:bit0=Y1…bit6=Y7,1=有内容(按实际改)
+ short r2 = 127 // X2 段存在位图(按实际改)
+ short r3 = 127 // X3 段存在位图(按实际改)
+ short r4 = 127 // X4 段存在位图(按实际改)
+ short one = 1 // 常量 1(默认制丸线别)
+ SetData(x, "Local HMI", LW, 0, 1) // X → LW-0
+ SetData(y, "Local HMI", LW, 1, 1) // Y → LW-1
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 0 → LW-2(不触发切窗)
+ SetData(r1, "Local HMI", LW, 70, 1) // X1 位图 → LW-70
+ SetData(r2, "Local HMI", LW, 71, 1) // X2 位图 → LW-71
+ SetData(r3, "Local HMI", LW, 72, 1) // X3 位图 → LW-72
+ SetData(r4, "Local HMI", LW, 73, 1) // X4 位图 → LW-73
+ SetData(one, "Local HMI", RW, 61, 1) // 开机默认制丸线别 = A(只有人工切换才变 B)
+end macro_command // 宏结束
```
-**`btn-x1`**(X1,权限 A/B/C) x2/x3 换 `x = 2`/`3` 且取位改为 A/B/D;`btn-x4` 换 `x = 4` 且取 A/B/C/D
+**导航宏说明**:先查权限(`LW-9222` 类别位)→ 再查当前 Y 页面是否存在(`LW-70`~`73` 位图)→ 有内容才切窗,无内容弹 16 号窗。
+
+**`btn-x1`**(X1 配料/上料 · 权限 A/B/C)
```
-macro_command main()
- short cls = 0, x = 1, y = 0, win = 0, ok = 0
- short pop = 1
- short bA = 0, bB = 0, bC = 0
- GetData(cls, "Local HMI", LW, 9222, 1)
- GETBIT(cls, bA, 0)
- GETBIT(cls, bB, 1)
- GETBIT(cls, bC, 2)
- if bA == 1 then
- ok = 1
- end if
- if bB == 1 then
- ok = 1
- end if
- if bC == 1 then
- ok = 1
- end if
- if ok == 1 then
- SetData(x, "Local HMI", LW, 0, 1)
- GetData(y, "Local HMI", LW, 1, 1)
- win = 101 + (x - 1) * 7 + (y - 1)
- SetData(win, "Local HMI", LW, 2, 1)
- else
- SetData(pop, "Local HMI", LB, 110, 1)
- end if
-end macro_command
+macro_command main() // 宏入口:按下 X1 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 1 // 本按钮固定切到 X=1
+ short y = 0 // 运行时读回的当前 Y(1~7)
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // X1 段页面存在位图(LW-70)
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bC = 0 // 类别 C 位(上料)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bC == 1 then // 含类别 C?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 继续查页面
+ GetData(y, "Local HMI", LW, 1, 1) // 读当前 Y → y
+ GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段存在位图 → vpm
+ if y == 1 then // 当前 Y=1?
+ GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv
+ end if // 结束判断
+ if y == 2 then // 当前 Y=2?
+ GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv
+ end if // 结束判断
+ if y == 3 then // 当前 Y=3?
+ GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv
+ end if // 结束判断
+ if y == 4 then // 当前 Y=4?
+ GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv
+ end if // 结束判断
+ if y == 5 then // 当前 Y=5?
+ GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv
+ end if // 结束判断
+ if y == 6 then // 当前 Y=6?
+ GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv
+ end if // 结束判断
+ if y == 7 then // 当前 Y=7?
+ GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv
+ end if // 结束判断
+ if bv == 1 then // 该页面有内容?
+ SetData(x, "Local HMI", LW, 0, 1) // X=1 → LW-0
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
```
-**`btn-y1`**(Y1~Y3 全开放:取 A/B/C/D) Y4~Y7 仅 A/B:只取 `bA`/`bB`
+**`btn-x2`**(X2 上料清洗 · 权限 A/B/C)
```
-macro_command main()
- short cls = 0, x = 0, y = 1, win = 0, ok = 0
- short pop = 1
- short bA = 0, bB = 0, bC = 0, bD = 0
- GetData(cls, "Local HMI", LW, 9222, 1)
- GETBIT(cls, bA, 0)
- GETBIT(cls, bB, 1)
- GETBIT(cls, bC, 2)
- GETBIT(cls, bD, 3)
- if bA == 1 then
- ok = 1
- end if
- if bB == 1 then
- ok = 1
- end if
- if bC == 1 then
- ok = 1
- end if
- if bD == 1 then
- ok = 1
- end if
- if ok == 1 then
- SetData(y, "Local HMI", LW, 1, 1)
- GetData(x, "Local HMI", LW, 0, 1)
- win = 101 + (x - 1) * 7 + (y - 1)
- SetData(win, "Local HMI", LW, 2, 1)
- else
- SetData(pop, "Local HMI", LB, 110, 1)
- end if
-end macro_command
+macro_command main() // 宏入口:按下 X2 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 2 // 本按钮固定切到 X=2
+ short y = 0 // 运行时读回的当前 Y(1~7)
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // X2 段页面存在位图(LW-71)
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bC = 0 // 类别 C 位(上料)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bC == 1 then // 含类别 C?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 继续查页面
+ GetData(y, "Local HMI", LW, 1, 1) // 读当前 Y → y
+ GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段存在位图 → vpm
+ if y == 1 then // 当前 Y=1?
+ GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv
+ end if // 结束判断
+ if y == 2 then // 当前 Y=2?
+ GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv
+ end if // 结束判断
+ if y == 3 then // 当前 Y=3?
+ GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv
+ end if // 结束判断
+ if y == 4 then // 当前 Y=4?
+ GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv
+ end if // 结束判断
+ if y == 5 then // 当前 Y=5?
+ GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv
+ end if // 结束判断
+ if y == 6 then // 当前 Y=6?
+ GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv
+ end if // 结束判断
+ if y == 7 then // 当前 Y=7?
+ GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv
+ end if // 结束判断
+ if bv == 1 then // 该页面有内容?
+ SetData(x, "Local HMI", LW, 0, 1) // X=2 → LW-0
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
```
-**`btn-login-index`**(登录:索引登入 → 按组定位;`31` 为 `msg-login` 的宏编号)
+**`btn-x3`**(X3 制丸 · 权限 A/B/D)
```
-macro_command main()
- short cmd = 2, res = 0, cls = 0, x = 1, y = 1, win = 0
- short bA = 0, bB = 0, bC = 0, bD = 0
- SetData(cmd, "Local HMI", LW, 100, 1)
- DELAY(2000)
- GetData(res, "Local HMI", LW, 101, 1)
- ASYNC_TRIG_MACRO(31)
- if res == 1 then
- GetData(cls, "Local HMI", LW, 9222, 1)
- GETBIT(cls, bA, 0)
- GETBIT(cls, bB, 1)
- GETBIT(cls, bC, 2)
- GETBIT(cls, bD, 3)
- if bD == 1 then
- x = 2
- end if
- if bA == 1 then
- x = 1
- end if
- if bB == 1 then
- x = 1
- end if
- if bC == 1 then
- x = 1
- end if
- win = 101 + (x - 1) * 7 + (y - 1)
- SetData(x, "Local HMI", LW, 0, 1)
- SetData(y, "Local HMI", LW, 1, 1)
- SetData(win, "Local HMI", LW, 2, 1)
- end if
-end macro_command
+macro_command main() // 宏入口:按下 X3 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 3 // 本按钮固定切到 X=3
+ short y = 0 // 运行时读回的当前 Y(1~7)
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // X3 段页面存在位图(LW-72)
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bD = 0 // 类别 D 位(制丸)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bD == 1 then // 含类别 D?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 继续查页面
+ GetData(y, "Local HMI", LW, 1, 1) // 读当前 Y → y
+ GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段存在位图 → vpm
+ if y == 1 then // 当前 Y=1?
+ GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv
+ end if // 结束判断
+ if y == 2 then // 当前 Y=2?
+ GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv
+ end if // 结束判断
+ if y == 3 then // 当前 Y=3?
+ GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv
+ end if // 结束判断
+ if y == 4 then // 当前 Y=4?
+ GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv
+ end if // 结束判断
+ if y == 5 then // 当前 Y=5?
+ GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv
+ end if // 结束判断
+ if y == 6 then // 当前 Y=6?
+ GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv
+ end if // 结束判断
+ if y == 7 then // 当前 Y=7?
+ GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv
+ end if // 结束判断
+ if bv == 1 then // 该页面有内容?
+ SetData(x, "Local HMI", LW, 0, 1) // X=3 → LW-0
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`btn-x4`**(X4 制丸清洗 · 权限 A/B/D)
+```
+macro_command main() // 宏入口:按下 X4 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 4 // 本按钮固定切到 X=4
+ short y = 0 // 运行时读回的当前 Y(1~7)
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // X4 段页面存在位图(LW-73)
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bD = 0 // 类别 D 位(制丸)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bD == 1 then // 含类别 D?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 继续查页面
+ GetData(y, "Local HMI", LW, 1, 1) // 读当前 Y → y
+ GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段存在位图 → vpm
+ if y == 1 then // 当前 Y=1?
+ GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv
+ end if // 结束判断
+ if y == 2 then // 当前 Y=2?
+ GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv
+ end if // 结束判断
+ if y == 3 then // 当前 Y=3?
+ GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv
+ end if // 结束判断
+ if y == 4 then // 当前 Y=4?
+ GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv
+ end if // 结束判断
+ if y == 5 then // 当前 Y=5?
+ GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv
+ end if // 结束判断
+ if y == 6 then // 当前 Y=6?
+ GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv
+ end if // 结束判断
+ if y == 7 then // 当前 Y=7?
+ GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv
+ end if // 结束判断
+ if bv == 1 then // 该页面有内容?
+ SetData(x, "Local HMI", LW, 0, 1) // X=4 → LW-0
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`btn-y1`**(Y1 初始状态 · 权限 A/B/C/D)
+```
+macro_command main() // 宏入口:按下 Y1 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 0 // 运行时读回的当前 X(1~4)
+ short y = 1 // 本按钮固定切到 Y=1
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // 当前 X 段页面存在位图
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bC = 0 // 类别 C 位(上料)
+ short bD = 0 // 类别 D 位(制丸)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料)
+ GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bC == 1 then // 含类别 C?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bD == 1 then // 含类别 D?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 查当前 X 段位图
+ GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x
+ if x == 1 then // 当前在 X1 段?
+ GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70
+ end if // 结束判断
+ if x == 2 then // 当前在 X2 段?
+ GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71
+ end if // 结束判断
+ if x == 3 then // 当前在 X3 段?
+ GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72
+ end if // 结束判断
+ if x == 4 then // 当前在 X4 段?
+ GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73
+ end if // 结束判断
+ GETBIT(vpm, bv, 0) // 取位 0(Y1)→ bv
+ if bv == 1 then // 该页面有内容?
+ SetData(y, "Local HMI", LW, 1, 1) // Y=1 → LW-1
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`btn-y2`**(Y2 运行 · 权限 A/B/C/D)
+```
+macro_command main() // 宏入口:按下 Y2 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 0 // 运行时读回的当前 X(1~4)
+ short y = 2 // 本按钮固定切到 Y=2
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // 当前 X 段页面存在位图
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bC = 0 // 类别 C 位(上料)
+ short bD = 0 // 类别 D 位(制丸)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料)
+ GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bC == 1 then // 含类别 C?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bD == 1 then // 含类别 D?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 查当前 X 段位图
+ GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x
+ if x == 1 then // 当前在 X1 段?
+ GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70
+ end if // 结束判断
+ if x == 2 then // 当前在 X2 段?
+ GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71
+ end if // 结束判断
+ if x == 3 then // 当前在 X3 段?
+ GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72
+ end if // 结束判断
+ if x == 4 then // 当前在 X4 段?
+ GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73
+ end if // 结束判断
+ GETBIT(vpm, bv, 1) // 取位 1(Y2)→ bv
+ if bv == 1 then // 该页面有内容?
+ SetData(y, "Local HMI", LW, 1, 1) // Y=2 → LW-1
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`btn-y3`**(Y3 配方 · 权限 A/B/C/D)
+```
+macro_command main() // 宏入口:按下 Y3 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 0 // 运行时读回的当前 X(1~4)
+ short y = 3 // 本按钮固定切到 Y=3
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // 当前 X 段页面存在位图
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bC = 0 // 类别 C 位(上料)
+ short bD = 0 // 类别 D 位(制丸)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料)
+ GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bC == 1 then // 含类别 C?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bD == 1 then // 含类别 D?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 查当前 X 段位图
+ GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x
+ if x == 1 then // 当前在 X1 段?
+ GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70
+ end if // 结束判断
+ if x == 2 then // 当前在 X2 段?
+ GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71
+ end if // 结束判断
+ if x == 3 then // 当前在 X3 段?
+ GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72
+ end if // 结束判断
+ if x == 4 then // 当前在 X4 段?
+ GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73
+ end if // 结束判断
+ GETBIT(vpm, bv, 2) // 取位 2(Y3)→ bv
+ if bv == 1 then // 该页面有内容?
+ SetData(y, "Local HMI", LW, 1, 1) // Y=3 → LW-1
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`btn-y4`**(Y4 设备参数 · 权限仅 A/B)
+```
+macro_command main() // 宏入口:按下 Y4 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 0 // 运行时读回的当前 X(1~4)
+ short y = 4 // 本按钮固定切到 Y=4
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // 当前 X 段页面存在位图
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 查当前 X 段位图
+ GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x
+ if x == 1 then // 当前在 X1 段?
+ GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70
+ end if // 结束判断
+ if x == 2 then // 当前在 X2 段?
+ GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71
+ end if // 结束判断
+ if x == 3 then // 当前在 X3 段?
+ GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72
+ end if // 结束判断
+ if x == 4 then // 当前在 X4 段?
+ GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73
+ end if // 结束判断
+ GETBIT(vpm, bv, 3) // 取位 3(Y4)→ bv
+ if bv == 1 then // 该页面有内容?
+ SetData(y, "Local HMI", LW, 1, 1) // Y=4 → LW-1
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`btn-y5`**(Y5 I/O 监控 · 权限仅 A/B)
+```
+macro_command main() // 宏入口:按下 Y5 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 0 // 运行时读回的当前 X(1~4)
+ short y = 5 // 本按钮固定切到 Y=5
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // 当前 X 段页面存在位图
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 查当前 X 段位图
+ GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x
+ if x == 1 then // 当前在 X1 段?
+ GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70
+ end if // 结束判断
+ if x == 2 then // 当前在 X2 段?
+ GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71
+ end if // 结束判断
+ if x == 3 then // 当前在 X3 段?
+ GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72
+ end if // 结束判断
+ if x == 4 then // 当前在 X4 段?
+ GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73
+ end if // 结束判断
+ GETBIT(vpm, bv, 4) // 取位 4(Y5)→ bv
+ if bv == 1 then // 该页面有内容?
+ SetData(y, "Local HMI", LW, 1, 1) // Y=5 → LW-1
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`btn-y6`**(Y6 报警 · 权限 A/B/C/D)
+```
+macro_command main() // 宏入口:按下 Y6 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 0 // 运行时读回的当前 X(1~4)
+ short y = 6 // 本按钮固定切到 Y=6
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // 当前 X 段页面存在位图
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bC = 0 // 类别 C 位(上料)
+ short bD = 0 // 类别 D 位(制丸)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料)
+ GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bC == 1 then // 含类别 C?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bD == 1 then // 含类别 D?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 查当前 X 段位图
+ GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x
+ if x == 1 then // 当前在 X1 段?
+ GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70
+ end if // 结束判断
+ if x == 2 then // 当前在 X2 段?
+ GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71
+ end if // 结束判断
+ if x == 3 then // 当前在 X3 段?
+ GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72
+ end if // 结束判断
+ if x == 4 then // 当前在 X4 段?
+ GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73
+ end if // 结束判断
+ GETBIT(vpm, bv, 5) // 取位 5(Y6)→ bv
+ if bv == 1 then // 该页面有内容?
+ SetData(y, "Local HMI", LW, 1, 1) // Y=6 → LW-1
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`btn-y7`**(Y7 数据趋势 · 权限 A/B/C/D)
+```
+macro_command main() // 宏入口:按下 Y7 按钮时执行
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 0 // 运行时读回的当前 X(1~4)
+ short y = 7 // 本按钮固定切到 Y=7
+ short win = 0 // 计算出的目标窗口号
+ short ok = 0 // 权限通过标志:1=放行
+ short bv = 0 // 页面存在标志:1=有内容
+ short vpm = 0 // 当前 X 段页面存在位图
+ short pop = 1 // 弹窗置位常量 1
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bC = 0 // 类别 C 位(上料)
+ short bD = 0 // 类别 D 位(制丸)
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料)
+ GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸)
+ if bA == 1 then // 含类别 A?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bC == 1 then // 含类别 C?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if bD == 1 then // 含类别 D?
+ ok = 1 // 权限通过
+ end if // 结束判断
+ if ok == 1 then // 权限通过 → 查当前 X 段位图
+ GetData(x, "Local HMI", LW, 0, 1) // 读当前 X → x
+ if x == 1 then // 当前在 X1 段?
+ GetData(vpm, "Local HMI", LW, 70, 1) // 读 X1 段位图 LW-70
+ end if // 结束判断
+ if x == 2 then // 当前在 X2 段?
+ GetData(vpm, "Local HMI", LW, 71, 1) // 读 X2 段位图 LW-71
+ end if // 结束判断
+ if x == 3 then // 当前在 X3 段?
+ GetData(vpm, "Local HMI", LW, 72, 1) // 读 X3 段位图 LW-72
+ end if // 结束判断
+ if x == 4 then // 当前在 X4 段?
+ GetData(vpm, "Local HMI", LW, 73, 1) // 读 X4 段位图 LW-73
+ end if // 结束判断
+ GETBIT(vpm, bv, 6) // 取位 6(Y7)→ bv
+ if bv == 1 then // 该页面有内容?
+ SetData(y, "Local HMI", LW, 1, 1) // Y=7 → LW-1
+ win = 101 + (x - 1) * 7 + (y - 1) // 算窗口号:101+(X-1)*7+(Y-1)
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ else // 该页面无内容
+ SetData(pop, "Local HMI", LB, 124, 1) // 置 LB-124 → 弹 16 号窗
+ end if // 结束判断
+ else // 权限不通过
+ SetData(pop, "Local HMI", LB, 110, 1) // 置 LB-110 → 弹 11 号无权限窗
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`btn-login-index`**(登录:索引登入 → 按组定位;结果提示已内联,无宏编号依赖)
+```
+macro_command main() // 宏入口:点登录按钮时执行
+ short cmd = 2 // 命令=2:使用索引登入(读 LW-102 选中的账号)
+ short res = 0 // 存放命令结果(读 LW-101)
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 1 // 登录后入口 X 初值 = 1
+ short y = 1 // 登录后入口 Y = 1
+ short win = 0 // 计算出的目标窗口号
+ short idx = 7 // 提示编号(默认 7=登录失败)
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bC = 0 // 类别 C 位(上料)
+ short bD = 0 // 类别 D 位(制丸)
+ short z = 0 // 常量 0(清命令/清旧结果用)
+ SetData(z, "Local HMI", LW, 101, 1) // 先清旧结果 → 防止读到上一次的码
+ SetData(z, "Local HMI", LW, 261, 1) // 清底部提示 → 不显示上一次的信息
+ SetData(z, "Local HMI", LW, 100, 1) // 命令先清 0(保证 0→2 有跳变)
+ SetData(cmd, "Local HMI", LW, 100, 1) // 发命令 2 → LW-100(索引登入)
+ DELAY(300) // 等 0.3 秒
+ GetData(res, "Local HMI", LW, 101, 1) // 读命令结果 → res(1=成功)
+ if res == 0 then // 结果仍为 0?
+ DELAY(300) // 再等 0.3 秒
+ GetData(res, "Local HMI", LW, 101, 1) // 再读一次
+ end if // 结束判断
+ if res == 1 then // 结果=1?
+ idx = 1 // 提示编号 1:登录成功
+ end if // 结束判断
+ if res == 8 then // 结果=8?
+ idx = 2 // 提示编号 2:账号不存在
+ end if // 结束判断
+ if res == 16 then // 结果=16?
+ idx = 3 // 提示编号 3:密码错误
+ end if // 结束判断
+ if res == 32 then // 结果=32?
+ idx = 4 // 提示编号 4:命令无法执行
+ end if // 结束判断
+ if res == 64 then // 结果=64?
+ idx = 5 // 提示编号 5:名称不合法
+ end if // 结束判断
+ if res == 128 then // 结果=128?
+ idx = 6 // 提示编号 6:密码含无效字符
+ end if // 结束判断
+ if res == 0 then // 结果=0?
+ idx = 0 // 提示编号 0:不显示
+ end if // 结束判断
+ SetData(idx, "Local HMI", LW, 261, 1) // 提示编号 → LW-261(立即显示)
+ if res == 1 then // 登录成功?
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA(A 工程师)
+ GETBIT(cls, bB, 1) // 取 bit1 → bB(B 管理员)
+ GETBIT(cls, bC, 2) // 取 bit2 → bC(C 上料)
+ GETBIT(cls, bD, 3) // 取 bit3 → bD(D 制丸)
+ if bD == 1 then // 含类别 D(制丸)?
+ x = 3 // 只有制丸组 → 入口 X3
+ end if // 结束判断
+ if bA == 1 then // 含类别 A?
+ x = 1 // 入口 X1
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ x = 1 // 入口 X1
+ end if // 结束判断
+ if bC == 1 then // 含类别 C?
+ x = 1 // 入口 X1
+ end if // 结束判断
+ win = 101 + (x - 1) * 7 + (y - 1) // 算目标窗口号:101+(X-1)*7+(Y-1)
+ SetData(x, "Local HMI", LW, 0, 1) // X → LW-0
+ SetData(y, "Local HMI", LW, 1, 1) // Y → LW-1
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ end if // 结束判断
+end macro_command // 宏结束
```
**`logout`**(注销并回登录页;10 号窗「打开窗口时执行」也用它)
```
-macro_command main()
- short cmd = 3, win = 10, z = 0
- SetData(cmd, "Local HMI", LW, 100, 1)
- SetData(z, "Local HMI", LW, 0, 1)
- SetData(z, "Local HMI", LW, 1, 1)
- SetData(win, "Local HMI", LW, 2, 1)
-end macro_command
+macro_command main() // 宏入口:点注销按钮 / 进 10 号窗时执行
+ short cmd = 3 // 命令=3:注销当前账号
+ short win = 10 // 目标窗口号 = 10(登录页)
+ short z = 0 // 常量 0
+ short z8[8] = {0,0,0,0,0,0,0,0} // 8 个 0(清用户名/密码框用)
+ SetData(cmd, "Local HMI", LW, 100, 1) // 发命令 3 → LW-100(注销)
+ SetData(z, "Local HMI", LW, 0, 1) // X 清 0
+ SetData(z, "Local HMI", LW, 1, 1) // Y 清 0
+ SetData(z8[0], "Local HMI", LW, 104, 8) // 清用户名框 LW-104~111(下次默认下拉登入)
+ SetData(z8[0], "Local HMI", LW, 112, 8) // 清密码框 LW-112~119
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 10 → LW-2(切回登录页)
+end macro_command // 宏结束
```
-**`msg-login`**(把 `LW-101` 结果码转成字符串表编号 → `LW-261`)
+**`admin-open`**(登录页 logo 上透明按钮,长按 3 秒)
```
-macro_command main()
- short res = 0, idx = 0
- GetData(res, "Local HMI", LW, 101, 1)
- idx = 7
- if res == 1 then
- idx = 1
- end if
- if res == 8 then
- idx = 2
- end if
- if res == 16 then
- idx = 3
- end if
- if res == 32 then
- idx = 4
- end if
- if res == 64 then
- idx = 5
- end if
- if res == 128 then
- idx = 6
- end if
- if res == 0 then
- idx = 0
- end if
- SetData(idx, "Local HMI", LW, 261, 1)
-end macro_command
+macro_command main() // 宏入口:长按登录页隐藏按钮时执行
+ short on = 1 // 置位常量 1
+ short z8[8] = {0,0,0,0,0,0,0,0} // 8 个 0(先清输入框)
+ SetData(z8[0], "Local HMI", LW, 104, 8) // 清用户名框 LW-104~111
+ SetData(z8[0], "Local HMI", LW, 112, 8) // 清密码框 LW-112~119
+ SetData(on, "Local HMI", LB, 125, 1) // 置 LB-125 → 弹 17 号管理员登录窗
+end macro_command // 宏结束
+```
+
+**`admin-login`**(17 号窗「登录」:固定名称登入)
+```
+macro_command main() // 宏入口:点 17 号窗「登录」时执行
+ short cmd = 1 // 命令=1:使用名称登入(读 LW-104 + LW-112)
+ short res = 0 // 命令结果(读 LW-101)
+ short cls = 0 // 当前用户类别位(读 LW-9222)
+ short x = 1 // 入口 X 初值 = 1
+ short y = 1 // 入口 Y = 1
+ short win = 0 // 计算出的目标窗口号
+ short idx = 7 // 提示编号(默认 7=登录失败)
+ short bA = 0 // 类别 A 位(工程师)
+ short bB = 0 // 类别 B 位(管理员)
+ short bC = 0 // 类别 C 位(上料)
+ short bD = 0 // 类别 D 位(制丸)
+ short z = 0 // 常量 0
+ SetData(z, "Local HMI", LW, 101, 1) // 先清旧结果 → 防止读到上一次的码
+ SetData(z, "Local HMI", LW, 261, 1) // 清旧提示
+ SetData(z, "Local HMI", LW, 100, 1) // 命令先清 0
+ SetData(cmd, "Local HMI", LW, 100, 1) // 发命令 1 → LW-100(名称登入)
+ DELAY(300) // 等 0.3 秒
+ GetData(res, "Local HMI", LW, 101, 1) // 读命令结果 → res(1=成功)
+ if res == 0 then // 结果仍为 0?
+ DELAY(300) // 再等 0.3 秒
+ GetData(res, "Local HMI", LW, 101, 1) // 再读一次
+ end if // 结束判断
+ if res == 1 then // 结果=1?
+ idx = 1 // 提示编号 1:登录成功
+ end if // 结束判断
+ if res == 8 then // 结果=8?
+ idx = 2 // 提示编号 2:账号不存在
+ end if // 结束判断
+ if res == 16 then // 结果=16?
+ idx = 3 // 提示编号 3:密码错误
+ end if // 结束判断
+ if res == 32 then // 结果=32?
+ idx = 4 // 提示编号 4:命令无法执行
+ end if // 结束判断
+ if res == 64 then // 结果=64?
+ idx = 5 // 提示编号 5:名称不合法
+ end if // 结束判断
+ if res == 128 then // 结果=128?
+ idx = 6 // 提示编号 6:密码含无效字符
+ end if // 结束判断
+ if res == 0 then // 结果=0?
+ idx = 0 // 提示编号 0:不显示
+ end if // 结束判断
+ SetData(idx, "Local HMI", LW, 261, 1) // 提示编号 → LW-261(立即显示)
+ if res == 1 then // 登录成功?
+ SetData(z, "Local HMI", LB, 125, 1) // 清 LB-125 → 关 17 号弹窗
+ GetData(cls, "Local HMI", LW, 9222, 1) // 读当前用户类别位 → cls
+ GETBIT(cls, bA, 0) // 取 bit0 → bA
+ GETBIT(cls, bB, 1) // 取 bit1 → bB
+ GETBIT(cls, bC, 2) // 取 bit2 → bC
+ GETBIT(cls, bD, 3) // 取 bit3 → bD
+ if bD == 1 then // 含类别 D?
+ x = 3 // 只有制丸组 → X3
+ end if // 结束判断
+ if bA == 1 then // 含类别 A?
+ x = 1 // 入口 X1
+ end if // 结束判断
+ if bB == 1 then // 含类别 B?
+ x = 1 // 入口 X1
+ end if // 结束判断
+ if bC == 1 then // 含类别 C?
+ x = 1 // 入口 X1
+ end if // 结束判断
+ win = 101 + (x - 1) * 7 + (y - 1) // 算目标窗口号
+ SetData(x, "Local HMI", LW, 0, 1) // X → LW-0
+ SetData(y, "Local HMI", LW, 1, 1) // Y → LW-1
+ SetData(win, "Local HMI", LW, 2, 1) // 窗口号 → LW-2(触发切窗)
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`admin-close`**(17 号窗「取消」)
+```
+macro_command main() // 宏入口:点 17 号窗「取消」时执行
+ short z = 0 // 常量 0
+ short z8[8] = {0,0,0,0,0,0,0,0} // 8 个 0
+ SetData(z, "Local HMI", LB, 125, 1) // 清 LB-125 → 关 17 号窗
+ SetData(z8[0], "Local HMI", LW, 104, 8) // 清用户名框
+ SetData(z8[0], "Local HMI", LW, 112, 8) // 清密码框
+end macro_command // 宏结束
```
**`close-msg`**(关闭无权限提示窗)
```
-macro_command main()
- short z = 0
- SetData(z, "Local HMI", LB, 110, 1)
-end macro_command
+macro_command main() // 宏入口:点 11 号窗「确定」时执行
+ short z = 0 // 常量 0
+ SetData(z, "Local HMI", LB, 110, 1) // 清 LB-110 → 关闭 11 号无权限窗
+end macro_command // 宏结束
+```
+
+**`close-nopage`**(关闭 16 号「无内容」提示窗)
+```
+macro_command main() // 宏入口:点 16 号窗「确定」时执行
+ short z = 0 // 常量 0
+ SetData(z, "Local HMI", LB, 124, 1) // 清 LB-124 → 关闭 16 号无内容窗
+end macro_command // 宏结束
```
**用户管理 `usr-*`**
@@ -314,66 +1147,25 @@ end macro_command
| 宏 | 命令 | 说明 |
| --- | --- | --- |
| `usr-init` | — | 14 号窗「打开窗口时执行」:清 `LW-104`/`LW-112`/`LW-103`/`LW-101`,清 `LB-121` |
-| `usr-open` | — | 顶部按钮:仅 B/admin → 置 `LB-122` |
+| `user-open` | — | 顶部按钮:仅 B/admin → 置 `LB-122` |
| `usr-back` | — | 清 `LB-122` |
| `usr-add` | `5` | 新增(`LW-104`+`LW-112`+`LW-103`) |
-| `usr-del` | — | 置 `LB-121` 弹确认 |
-| `usr-del-ok` | `8` | 按索引删除 |
-| `usr-del-cancel` | — | 清 `LB-121` |
+| `usr-delete` | — | 置 `LB-121` 弹确认 |
+| `usr-delete-ok` | `8` | 按索引删除 |
+| `usr-delete-cancel` | — | 清 `LB-121` |
| `usr-getlevel` | `14` | 按索引读权限 → `LW-103` |
| `usr-setlevel` | `10` | 按索引设权限 |
| `usr-setpwd` | `12` | 按索引设密码 |
```
-macro_command main()
- short cmd = 14
- SetData(cmd, "Local HMI", LW, 100, 1)
-end macro_command
+macro_command main() // 宏入口:用户管理按钮(以 cmd=14 读取权限为例)
+ short cmd = 14 // 命令值:改成 5/8/10/12 等即为对应功能
+ SetData(cmd, "Local HMI", LW, 100, 1) // 发命令 → LW-100
+end macro_command // 宏结束
```
-> 其余 `usr-*` 同上模板:`cmd` = 5 / 8 / 10 / 12;`usr-open`/`usr-back`/`usr-del`/`usr-del-cancel`/`usr-init` 见 6.21.5。
+> 其余 `usr-*` 同上模板:`cmd` = 5 / 8 / 10 / 12;`user-open` 置 / `usr-back` 清 `LB-122`,`usr-delete` / `usr-delete-cancel` 置 / 清 `LB-121`,`usr-init` 清输入。
-**点检 `insp-*`**
-
-`insp-init`(20 号窗「打开窗口时执行」)
-```
-macro_command main()
- short z = 0
- SetData(z, "Local HMI", LW, 20, 1)
-end macro_command
-```
-`insp-next`(可选:11 项全勾才进主画面)
-```
-macro_command main()
- short v = 0, cls = 0, x = 1, y = 1, win = 0
- short bA = 0, bB = 0, bC = 0, bD = 0, np = 1
- GetData(v, "Local HMI", LW, 20, 1)
- if v == 2047 then
- GetData(cls, "Local HMI", LW, 9222, 1)
- GETBIT(cls, bA, 0)
- GETBIT(cls, bB, 1)
- GETBIT(cls, bC, 2)
- GETBIT(cls, bD, 3)
- if bD == 1 then
- x = 2
- end if
- if bA == 1 then
- x = 1
- end if
- if bB == 1 then
- x = 1
- end if
- if bC == 1 then
- x = 1
- end if
- win = 101 + (x - 1) * 7 + (y - 1)
- SetData(x, "Local HMI", LW, 0, 1)
- SetData(y, "Local HMI", LW, 1, 1)
- SetData(win, "Local HMI", LW, 2, 1)
- else
- SetData(np, "Local HMI", LB, 110, 1)
- end if
-end macro_command
-```
+**关于窗 `about-*`**:`about-open` 置 `LB-123`(弹 13 号窗);`about-close` 清 `LB-123`。
**修改时间**
@@ -384,20 +1176,134 @@ end macro_command
| `close-time` | 12 号窗「取消」 | 清 `LB-120` |
```
-macro_command main() // set-time
- short v[6] = {0,0,0,0,0,0}
- short z = 0
- GetData(v[0], "Local HMI", LW, 40, 6)
- SetData(v[0], "Local HMI", LW, 9017, 6)
- SetData(z, "Local HMI", LB, 120, 1)
-end macro_command
+macro_command main() // 宏入口:改时间弹窗点「设定」时执行
+ short v[6] = {0,0,0,0,0,0} // 暂存数组:秒/分/时/日/月/年
+ short z = 0 // 常量 0
+ GetData(v[0], "Local HMI", LW, 40, 6) // 从 LW-40~45 读入 6 个值 → v
+ SetData(v[0], "Local HMI", LW, 9017, 6) // v 写入 RTC 寄存器 LW-9017~9022(设置时间)
+ SetData(z, "Local HMI", LB, 120, 1) // 清 LB-120 → 关闭 12 号弹窗
+end macro_command // 宏结束
+```
+
+**网络设置 `net-*`**
+
+**`net-read`**(13 号窗「打开窗口时执行」:系统值 → 暂存 RW)
+```
+macro_command main() // 宏入口:进 13 号窗时执行
+ short v[4] = {0,0,0,0} // 4 字暂存数组
+ short line = 1 // 制丸线别(1=A / 2=B)
+ GetData(line, "Local HMI", RW, 61, 1) // 读 RW-61 线别
+ GetData(v[0], "Local HMI", LW, 9129, 4) // 读 HMI IP
+ SetData(v[0], "Local HMI", RW, 20, 4) // → RW-20~23
+ GetData(v[0], "Local HMI", LW, 10750, 4) // 读 HMI 掩码
+ SetData(v[0], "Local HMI", RW, 24, 4) // → RW-24~27
+ GetData(v[0], "Local HMI", LW, 9125, 4) // 读 HMI 网关
+ SetData(v[0], "Local HMI", RW, 28, 4) // → RW-28~31
+ GetData(v[0], "Local HMI", LW, 9600, 4) // 读上料 PLC(设备4)IP
+ SetData(v[0], "Local HMI", RW, 40, 4) // → RW-40~43
+ GetData(v[0], "Local HMI", LW, 9605, 4) // 读制丸 PLC(设备5)IP
+ if line == 1 then // 当前选 A 线?
+ SetData(v[0], "Local HMI", RW, 44, 4) // → RW-44~47(制丸A)
+ else // 当前选 B 线
+ SetData(v[0], "Local HMI", RW, 48, 4) // → RW-48~51(制丸B)
+ end if // 结束判断
+end macro_command // 宏结束
+```
+
+**`net-apply`**(13 号窗「应用」按钮;另勾选宏属性「当 HMI 启动时即执行一次」,开机自动套用)
+```
+macro_command main() // 宏入口:点「应用」/ 开机自动套用
+ short v[4] = {0,0,0,0} // 4 字暂存数组
+ short hmi0 = 0 // HMI IP 第一段(判断是否配置过)
+ short role = 0 // 本机角色(1上料/2制丸A/3制丸B)
+ short line = 1 // 制丸线别(1=A/2=B)
+ short okp = 0 // 是否连接制丸设备:1=连
+ short on = 1 // 置位常量
+ short z = 0 // 常量 0
+ GetData(hmi0, "Local HMI", RW, 20, 1) // 读 RW-20(HMI IP 第一段)
+ GetData(role, "Local HMI", RW, 60, 1) // 读 RW-60(本机角色)
+ GetData(line, "Local HMI", RW, 61, 1) // 读 RW-61(线别)
+ if line == 0 then // 线别未设置/无效?
+ line = 1 // 默认 A 线
+ end if // 结束判断
+ if role == 1 then // 上料屏?
+ okp = 1 // 连制丸设备(线别按 RW-61)
+ end if // 结束判断
+ if role == 2 then // 制丸A屏?
+ line = 1 // 强制 A 线
+ okp = 1 // 连制丸设备
+ end if // 结束判断
+ if role == 3 then // 制丸B屏?
+ line = 2 // 强制 B 线
+ okp = 1 // 连制丸设备
+ end if // 结束判断
+ SetData(line, "Local HMI", RW, 61, 1) // 回写线别(界面显示一致)
+ if hmi0 == 0 then // HMI IP 没填 → 跳过 HMI 部分
+ hmi0 = 0 // (保持原 HMI 网络)
+ else // 已填 → 应用 HMI 网络
+ GetData(v[0], "Local HMI", RW, 20, 4) // RW → HMI IP
+ SetData(v[0], "Local HMI", LW, 9129, 4) // 写 LW-9129~9132
+ GetData(v[0], "Local HMI", RW, 24, 4) // RW → HMI 掩码
+ SetData(v[0], "Local HMI", LW, 10750, 4) // 写 LW-10750~10753
+ GetData(v[0], "Local HMI", RW, 28, 4) // RW → HMI 网关
+ SetData(v[0], "Local HMI", LW, 9125, 4) // 写 LW-9125~9128
+ SetData(on, "Local HMI", LB, 12094, 1) // 置 LB-12094 → HMI 网络生效
+ end if // 结束判断
+ GetData(v[0], "Local HMI", RW, 40, 4) // RW → 上料 PLC IP
+ SetData(v[0], "Local HMI", LW, 9600, 4) // 写上料 PLC(设备4)
+ SetData(on, "Local HMI", LB, 10070, 1) // 重连设备4
+ if okp == 1 then // 需要连制丸设备?
+ if line == 1 then // 选 A 线
+ GetData(v[0], "Local HMI", RW, 44, 4) // RW → 制丸A IP
+ else // 选 B 线
+ GetData(v[0], "Local HMI", RW, 48, 4) // RW → 制丸B IP
+ end if // 结束判断
+ SetData(v[0], "Local HMI", LW, 9605, 4) // 写制丸 PLC(设备5)
+ SetData(on, "Local HMI", LB, 10071, 1) // 重连设备5
+ end if // 结束判断(角色=0:不连制丸设备,防误连)
+ DELAY(1000) // 等 1 秒
+ SetData(z, "Local HMI", LB, 12094, 1) // 清 LB-12094
+ SetData(z, "Local HMI", LB, 10070, 1) // 清 LB-10070
+ SetData(z, "Local HMI", LB, 10071, 1) // 清 LB-10071
+end macro_command // 宏结束
+```
+
+**`line-ab-switch`**(13 号窗「A/B 切换」按钮;仅本机角色=1 生效)
+```
+macro_command main() // 宏入口:点 A/B 线切换按钮
+ short v[4] = {0,0,0,0} // 4 字暂存数组
+ short role = 0 // 本机角色(读 RW-60)
+ short line = 1 // 当前线别
+ short on = 1 // 置位常量
+ short z = 0 // 常量 0
+ GetData(role, "Local HMI", RW, 60, 1) // 读本机角色
+ if role == 1 then // 只有上料屏允许切换
+ GetData(line, "Local HMI", RW, 61, 1) // 读当前线别
+ if line == 1 then // 当前 A → 切 B
+ line = 2 // 目标 B
+ else // 当前 B → 切 A
+ line = 1 // 目标 A
+ end if // 结束判断
+ SetData(line, "Local HMI", RW, 61, 1) // 写回 RW-61
+ if line == 1 then // 目标 A 线
+ GetData(v[0], "Local HMI", RW, 44, 4) // 取制丸A IP
+ else // 目标 B 线
+ GetData(v[0], "Local HMI", RW, 48, 4) // 取制丸B IP
+ end if // 结束判断
+ SetData(v[0], "Local HMI", LW, 9605, 4) // 写设备5 IP
+ SetData(on, "Local HMI", LB, 10071, 1) // 重连设备5
+ DELAY(1000) // 等 1 秒
+ SetData(z, "Local HMI", LB, 10071, 1) // 清重连位
+ end if // 非上料屏:无动作(线别锁定)
+end macro_command // 宏结束
```
## 7. 各页面要点
### 7.1 登录页(10 号窗)
- 项目选单(来源=用户账号)→ 写 `LW-102`;密码字符输入(勾系统键盘)→ `LW-112`。
-- 底部字符框读 `LW-260`(或文字元件用字符串表,编号 `LW-261`)。
+- admin 登录(隐藏入口):登录页 logo 上盖**透明功能键**(安全页「最少按键时间」= 3 秒)→ `admin-open`;10 号窗放「直接窗口」`LB-125`→17,弹窗里填 `admin` + 密码 → `admin-login`(名称登入),取消 → `admin-close`。
+- 底部提示用文字元件 + 字符串表,编号 `LW-261`(由登录宏直接写入)。
- 「登录」按钮 → `btn-login-index`。
- 窗口属性 → 「打开窗口时执行」= `logout`(每次回来强制重新登录)。
- 顶部账户显示读 `PLW-10754`,上面盖透明功能键 → 长按 1s(安全页最少按键时间=1)→ `logout`。
@@ -405,31 +1311,36 @@ end macro_command
### 7.2 公共窗口(100 号窗)
- 顶部:品牌、页签、`?`/首页/用户/报警图标;右上角「日期/时间」元件。
- PLC 联机:触发条件(3 台联机位 AND)→ `LB-131` → 位状态指示灯。
-- 直接窗口 ×5:`LB-110`→11、`LB-120`→12、`LB-121`→15、`LB-122`→14、`LB-123`→13。
-- 入口按钮:点检(功能键→切换基本窗口=20);关于(仅 A,安全页操作类别=类别 A);用户管理(`usr-open`)。
+- 直接窗口 ×6:`LB-110`→11、`LB-120`→12、`LB-121`→15、`LB-122`→14、`LB-123`→13、`LB-124`→16。
+- 入口按钮:点检(功能键→切换基本窗口=20);关于(仅 A,安全页操作类别=类别 A);用户管理(`user-open`)。
- X/Y 导航按钮:`btn-x1~x4`、`btn-y1~y7`。
### 7.3 用户管理(14 号窗,1200×800 弹窗)
-见 6.21.10:列表(`LW-102`)+ 用户名/密码 + 4 个权限开关(`LW_Bit-10300~10303`)+ 读取权限/修改权限/修改密码/删除/新增/关闭 + 结果 `LW-101`。
+见第 6 节 `usr-*`:列表(`LW-102`)+ 用户名/密码 + 4 个权限开关(`LW_Bit-10300~10303`)+ 读取权限/修改权限/修改密码/删除/新增/关闭 + 结果 `LW-101`。
只读管理员(B/admin)可用;改权限前先「读取权限」。
-### 7.4 点检(20 号窗,1920×1080)
-- 布局按 XD `B_PID`:左「设备状态」9 项、右「物料状态」2 项(`LW_Bit-2000~2010`),右侧两个提示框,右下插画 `pic/pid-illustration.png`。
-- 「关闭」= 功能键 → 返回上一个窗口;「下一步」= `insp-next`。
-- 点检暂不强制。
+### 7.4 点检(20 号窗)
+- 只做了画面(可退出),**暂无功能、暂不设计**;不放宏。
+- 「关闭」等功能键直接切窗口(未用宏)。
-### 7.5 关于(13 号窗,1200×800 弹窗)
-- 字段与地址见 5.7;`LB-123` 弹窗。
-- 入口仅工程师(A)。
+### 7.5 关于 / 设置(13 号窗,1200×800 弹窗)
+- 上方:关于信息,字段与地址见 5.7;`LB-123` 弹窗;入口仅工程师(A)。
+- 下方「设置」区(全部存 `RW`,掉电保持):
+ - 本机角色 → `RW-60`(1 上料屏 / 2 制丸A屏 / 3 制丸B屏);
+ - 制丸线选择 → `RW-61`(1 A 线 / 2 B 线,上料屏用);
+ - HMI IP / 掩码 / 网关 → `RW-20`~`31`(备屏/换屏用;HMI 固定 IP 必填);
+ - 上料 PLC IP → `RW-40`~`43`;制丸A PLC IP → `RW-44`~`47`;制丸B PLC IP → `RW-48`~`51`;
+ - 「应用」→ `net-apply`;窗口开启时执行 `net-read`(进窗自动带出当前值,不需要单独做「读取当前」按钮)。
+- 上料屏在 13 号窗设置区放「A/B 切换」按钮 → `line-ab-switch`(只切 `设备5` 的 IP 并重连;**仅本机角色=1 生效**,A/B 屏误点无效);旁边放当前线别显示(读 `RW-61`)。
+- **现场无需 EB**:换屏/换 PLC 只填这一页,点「应用」即可。
### 7.6 修改时间(12 号窗)
- 6 个数值输入(`LW-40`~`45` 秒/分/时/日/月/年)+ 设定/取消。
- 入口:100 号窗时钟上透明功能键(仅 B)→ `open-time`。
-### 7.7 主画面(101~128)
-- 每个画面 = 某工艺段 × 某功能组合,底图按 XD/`pic` 素材放置,控件按各功能需求(待逐个设计)。
+### 7.7 主画面(101~128)设计
-### 7.7 主画面设计
+每个画面 = 某工艺段 × 某功能组合,底图按 XD/`pic` 素材放置;其余页面待逐个补。
#### 7.7.1 X1Y1(配料/上料 · 初始状态)完整操作表
@@ -510,10 +1421,10 @@ end macro_command
**⑦ 收尾**
23. 各元件「安全」页按需限制操作类别(只显示/只工程师可改)。
24. 保存编译;等 PLC 地址到位后,把占位地址逐个替换即可,元件与布局不动。
-**底部 X 页签**:由 100 号公共窗口的 4 个功能键实现(配料/制丸1/制丸2/清洗 → 切换基本窗口)。
+**底部 X 页签**:由 100 号公共窗口的 4 个功能键实现(配料/上料、上料清洗、制丸、制丸清洗 → 切换基本窗口)。
#### 7.7.2 Y6 报警表页面(106 / 113 / 120 / 127)
-> Y6 = 报警功能;各工艺段各有一个报警表页:`106`(配料/上料)、`113`(制丸1)、`120`(制丸2)、`127`(清洗)。
+> Y6 = 报警功能;各工艺段各有一个报警表页:`106`(配料/上料)、`113`(上料清洗)、`120`(制丸)、`127`(制丸清洗)。
| 控件 | 元件 | 关键设置 |
| --- | --- | --- |
@@ -529,7 +1440,7 @@ end macro_command
2. 在 Y6 页放 **报警显示** 元件(多行列表);X1Y1 等页放 **报警条** 元件(一行滚动)。
3. 报警显示的属性里设 **确认地址**,并为每条报警配**确认值** → 操作员确认后写回该地址给 PLC。
4. 需要"清除"按钮就放 `位状态设置` 写 `LB-9021`(重置)/`LB-9023`(删除文件)。
-5. 4 个 Y6 页可共用同一套事件登录,也可按**类别**过滤(配料/制丸/清洗各自的报警)。
+5. 4 个 Y6 页可共用同一套事件登录,也可按**类别**过滤(配料/上料、上料清洗、制丸、制丸清洗各自的报警)。
### 7.8 弹窗规范(统一用直接窗口)
@@ -544,6 +1455,8 @@ end macro_command
| 关于 | `LB-123` | 13 |
| 用户管理 | `LB-122` | 14 |
| 删除确认 | `LB-121` | 15 |
+| 无内容提示 | `LB-124` | 16 |
+| 管理员登录 | `LB-125` | 17 |
## 8. 素材清单(`pic/`)
| 素材 | 说明 |
@@ -555,7 +1468,65 @@ end macro_command
| `pid-illustration.png` / `btn-back.png` / `btn-next.png` / `pid-logo.png` | 点检页素材(取自 XD `B_PID`) |
| `lwaddr.csv` | 系统地址大全 |
-## 9. 变更记录(里程碑)
+## 9. 多线共屏:完整方法与流程
+
+### 9.1 分工与连接
+
+| 屏幕 | 角色 `RW-60` | 连哪两台 PLC | 能看到 |
+| --- | --- | --- | --- |
+| 上料屏 | 1 | 上料(设备4)+ 制丸 A 或 B(设备5,可切) | 上料段 + 当前选的制丸线 |
+| 制丸A屏 | 2 | 上料(设备4)+ 制丸A(设备5) | 上料段 + A 线 |
+| 制丸B屏 | 3 | 上料(设备4)+ 制丸B(设备5) | 上料段 + B 线 |
+
+- 用户组:C → X1/X2(绑设备4);D → X3/X4(绑设备5);`admin` 全开;
+- 制丸A/B 互不可见:各屏只连自己那条线 + 上料;唯一例外是上料屏(D 登录可切 A/B)。
+
+### 9.2 EB Pro 一次性改造
+
+1. **设备列表**:确认以太网 PLC 占设备4/设备5;X1/X2 与 C 组数据绑设备4,X3/X4 与 D 组数据绑设备5。
+2. **13 号窗设置区**(`RW` 全部掉电保持):
+ - 本机角色 `RW-60`(1 上料 / 2 制丸A / 3 制丸B)、线别 `RW-61`(1=A / 2=B);
+ - HMI IP/掩码/网关 `RW-20~31`(备屏/换屏用;HMI 固定 IP 必填);
+ - 上料 IP `RW-40~43`、制丸A IP `RW-44~47`、制丸B IP `RW-48~51`;
+ - 「应用」= `net-apply`(勾「当 HMI 启动时即执行一次」);进窗自动执行 `net-read`。
+3. **宏**:第 6 节清单(`main-init` 写 `LW-70~73` 位图、`btn-x/y`、登录内联版、`logout`、`user-open`/`usr-*`、`about-*`、时间三支、`close-msg`/`close-nopage`、`admin-*`、`net-read`/`net-apply`/`line-ab-switch`)。
+4. **弹窗**:11/12/13/14/15/16/17 的直接窗口都放 100 号公共窗,属性「重叠」= 独立窗口。
+5. **切换按钮暂放 13 号窗设置区**:「A/B 切换」功能键 → `line-ab-switch`(仅 role=1 生效)+ 当前线别显示(读 `RW-61`);后续再移到制丸页给 D 用(通讯灯 `LB-10400` 一并加)。
+
+### 9.3 装机流程(每台屏,刷同一工程)
+
+| 步骤 | 上料屏 | 制丸A屏 | 制丸B屏 |
+| --- | --- | --- | --- |
+| 1 | 设 HMI 网络 IP(屏系统设置或 13 号窗) | 同 | 同 |
+| 2 | 13 号窗角色 = 1 | = 2 | = 3 |
+| 3 | 填 上料 IP + 制丸A IP + 制丸B IP | 填 上料 IP + 制丸A IP | 填 上料 IP + 制丸B IP |
+| 4 | 线别选 A(或 B) | 自动锁 A | 自动锁 B |
+| 5 | 点「应用」 | 同 | 同 |
+| 6 | 查 `LB-10100`(上料)、`LB-10400`(制丸)都 ON | 同 | 同 |
+
+### 9.4 现场运行
+
+- 上料屏切制丸线:暂在 13 号窗点「A/B 切换」→ 等 `LB-10400` ON 再操作(默认 A、重启回 A);能开 13 号窗的是工程师 A / admin,后续移到制丸页后 D 组可用;
+- 制丸A/B 屏天然只看本线;admin 在制丸屏也切不动(`line-ab-switch` 角色校验);
+- C 组只看上料段;工程师 A 看「关于/设置」;管理员 B 用「用户管理/改时间」。
+
+### 9.5 换件流程
+
+| 场景 | 操作 |
+| --- | --- |
+| HMI 屏坏 | 备件刷同工程 → 13 号窗设角色/线别/各组 IP → 应用 |
+| PLC 坏、IP 变 | 在对应屏 13 号窗改该线 IP(上料屏改 A 或 B 组)→ 应用 |
+| 整线换 PLC(IP 不变) | 不用动 |
+| 屏挪到另一条线(A↔B 换屏) | 13 号窗把角色 `RW-60` 改 2↔3,核对本线 IP;**HMI 是固定 IP:一并把 HMI IP 改成新位置规划的 IP**(系统设置或 13 号窗 `RW-20~31`)→ 应用 |
+
+### 9.6 注意
+
+- PLC 在线改 IP 只支持本机以太网设备 4 及以后(1~3 是 COM);
+- 切换 A/B 后要等 `LB-10400`=ON 再操作(防旧数据);
+- A/B 屏不要给对方的线留 IP/加设备槽;要"上料屏同时看 A+B"才加设备6(另案);
+- 系统弹窗可用 `LB-11963`/`LB-11964` 禁掉。
+
+## 10. 变更记录(里程碑)
| 日期 | 内容 |
| --- | --- |
@@ -565,3 +1536,32 @@ end macro_command
| 09-23 | 完成登录页、权限控制(`LW-9222`)、按钮宏与无权限弹窗 |
| 09-24 | 完成用户管理(索引命令)、点检页、关于页、修改时间、PLC 联机状态、登录提示框 |
| 09-24 | 文档精简;准备开始 28 个主画面的设计 |
+| 09-25 | 按钮宏全部改为逐行注释版(`btn-x1~x4`/`btn-y1~y7`,其余宏同步补注释);新增「该页面无内容」提示:`LB-124`→16 号窗 + `close-nopage`;`LW-70`~`73` 页面存在位图由 `main-init` 初始化 |
+| 09-25 | X 段更名:X2 上料清洗、X3 制丸、X4 制丸清洗(X1 配料/上料不变);权限调整:X2=A/B/C、X4=A/B/D(X1=A/B/C、X3=A/B/D,Y1~Y7 不变) |
+| 09-25 | 登录提示加速:`btn-login-index` 的 `DELAY(2000)` 改为「清旧结果 + 0.3s 读 + 0.3s 补读一次」,并在点登录时先清 `LW-261` 旧提示 |
+| 09-25 | Y6/Y7 开放给 C、D 用户组:权限改为 A/B/C/D(Y4/Y5 仍仅 A/B,Y1~Y3 不变) |
+| 09-25 | 新增「权限分配总表」(4.1):按用户组列出全部已开发功能的权限 |
+| 09-25 | 权限表改为三级:● 拥有权限 / ○ 仅可见 / × 不可见,并补充 EB Pro 对应设置方法(操作类别、无权限时隐藏) |
+| 09-25 | 修正登录/点检入口:制丸 D 登录后落到 X3Y1(段名调整后遗漏,原为 X2Y1) |
+| 09-25 | 文档整理:删除未使用内容(`insp-next`、`LW-260`、cxob 资产条目);合并重复的 7.7 标题;修正 7.3/7.4 失效引用 |
+| 09-25 | 登录页加用户名输入框 `LW-104`:填名称(admin)按名称登入,留空按下拉索引登入;`logout` 回登录页时清空用户名/密码框 |
+| 09-25 | admin 登录改为隐藏入口:登录页 logo 长按 3 秒 → 弹 17 号窗名称登入(`LB-125` + `admin-open`/`admin-login`/`admin-close`);撤销可见用户名框,`btn-login-index` 恢复纯索引登入 |
+| 09-25 | 新增 5.8 通用程序 IP 在线设置:HMI IP/掩码/网关(`LW-9129` 等 + `LB-12094`)、PLC IP(设备 4+:`LW-9600` 等 + `LB-1007x`)及现场设置页做法 |
+| 09-25 | 网络设置落在 13 号窗(关于页):`RW-20~35` 暂存,新增 `net-read`/`net-apply` 宏,7.5/5.8 同步 |
+| 09-25 | 窗口名按实际工程同步(10 登陆和入口、11 弹出、13 系统IP和关于、15 用户删除确认、16 空页面弹窗、17 超管登陆、20 点检check) |
+| 09-25 | 宏清单与工程实际对齐:`user-open`、`usr-delete*`、`about-*`;新增宏编号警告(`msg-login`=ID 031 被 `btn-login-index` 写死) |
+| 09-25 | 去掉高危数字宏号:`msg-login` 改由触发位 `LB-126` 驱动(执行条件 ON、结束自清);`btn-login-index`/`admin-login` 只置 `LB-126`;`net-apply` 用「HMI 启动时执行一次」 |
+| 09-25 | 点检页只保留画面(可退出、暂不设计功能):删除 `insp-init` 宏及相关描述 |
+| 09-25 | 确认保留 `logout`、废弃 `log-out`;`net-read`/`net-apply` 同步新 RW 规划(RW-40~51、RW-60 角色、RW-61 线别)并新增 `line-ab-switch` |
+| 09-25 | 5.8 补充切换互锁:设备通讯状态 `LB-10100`/`LB-10400`、错误码 `LW-9403`/`9404`、禁止系统弹窗 `LB-11963`/`11964` |
+| 09-25 | 登录提示改为内联(零延迟):映射写进 `btn-login-index`/`admin-login`,删除 `msg-login` 与 `LB-126` |
+| 09-25 | 多线共屏防串线:`line-ab-switch` 增加角色校验,仅上料屏(`RW-60`=1)可切 A/B;制丸A/B 屏线别由角色锁定 |
+| 09-25 | 新增 5.9 拓扑图(3 PLC × 3 HMI × 2 设备槽的逻辑连接) |
+| 09-25 | 新增第 9 章「多线共屏完整方法与流程」:分工/一次性改造/装机/运行/换件/注意;变更记录顺延为第 10 章 |
+| 09-25 | 上料屏制丸线默认 A:`main-init` 开机写 `RW-61`=1,`net-apply` 线别=0 按 A;只有人工切换才到 B |
+| 09-25 | 去掉多余的「读取当前」按钮:13 号窗打开时已自动执行 `net-read` |
+| 09-25 | A/B 切换按钮暂放 13 号窗设置区(仅 role=1 生效);后续再移到制丸页给 D 用 |
+| 09-25 | 制丸屏装机只改角色:A屏 role=2(锁A)、B屏 role=3(锁B);角色=0 时 `net-apply` 不连制丸设备,防装错位置误连 |
+| 09-25 | 9.5 换件流程补充「A↔B 换屏」:13 号窗改角色 2↔3 + 核对本线 IP |
+| 09-25 | 明确 HMI 固定 IP:换屏必须一起改 HMI IP;13 号窗 HMI IP/掩码/网关(RW-20~31)建议做上 |
+| 09-25 | 明确现场不碰 EB:IP 全部在 13 号窗完成;补充 PLC 设备号查看方法(设备列表或显示 `LW-9300~9306`) |
\ No newline at end of file