108 lines
3.9 KiB
Markdown
108 lines
3.9 KiB
Markdown
# 前端信号批量导出/导入 XML 功能
|
||
|
||
## 概述
|
||
|
||
在 5 个信号管理页面(out/in/yk/ao/param)的工具栏中新增"导出"和"导入"按钮,实现信号的批量导出到 XML 文件和从 XML 文件批量导入。
|
||
|
||
## 功能描述
|
||
|
||
- **导出**:将当前页面已添加的信号列表生成为 XML 文件,通过浏览器下载
|
||
- **导入**:读取本地 XML 文件,解析后按 seq 序号顺序逐个执行 add 操作
|
||
|
||
## 涉及文件
|
||
|
||
| 文件 | 修改类型 | 说明 |
|
||
|------|---------|------|
|
||
| `test/web_root/js/pages.js` | 修改 | 主要逻辑变更 |
|
||
| `src/system/libweb_server/src/packed_fs.c` | 重新生成 | `pack_web.sh` 打包输出 |
|
||
|
||
## 代码变更
|
||
|
||
### 1. 新增函数 `escapeXml(str)`
|
||
|
||
对 XML 特殊字符进行转义(`& < > " '`),用于拼接 XML 字符串时防止格式损坏。
|
||
|
||
### 2. 新增函数 `exportToXml(signalType, data)`
|
||
|
||
- 参数:`signalType` — 信号类型字符串,`data` — 信号数组
|
||
- 逻辑:
|
||
1. 空数据检查 → 弹窗提示
|
||
2. 拼接 XML 字符串(`<?xml ...?>` + `<signals type="...">` + 逐个 signal 节点)
|
||
3. 输出字段:`saddr`、`desc`、`data_type`、`val`(全部 escapeXml 转义)
|
||
4. 创建 Blob → URL.createObjectURL → `<a download>` 触发下载
|
||
5. 文件名格式:`signals_{type}_{timestamp}.xml`
|
||
6. 清理:removeChild + revokeObjectURL
|
||
|
||
### 3. 新增函数 `importFromXml(signalType)`
|
||
|
||
- 参数:`signalType` — 当前页面信号类型
|
||
- 逻辑:
|
||
1. 创建隐藏 `<input type="file" accept=".xml">` 并触发点击
|
||
2. 文件选中后用 FileReader 读取文本
|
||
3. DOMParser 解析 XML
|
||
4. 校验:根元素必为 `<signals>`,`type` 属性必须与 `signalType` 一致
|
||
5. 提取所有 `<signal>` 节点的 `<saddr>`,按 `seq` 属性升序排序
|
||
6. confirm 确认后,逐个发送 WsClient.send add 命令
|
||
7. 完成后 alert 提示结果
|
||
|
||
### 4. 修改函数 `makeToolbar(signalType, showSet)`
|
||
|
||
在工具栏末尾添加两个按钮:
|
||
- `<span style="flex:1"></span>` — 弹性撑开
|
||
- `<button class="btn btn-info" id="tb-export">📤 导出</button>`
|
||
- `<button class="btn btn-warn" id="tb-import">📥 导入</button>`
|
||
|
||
### 5. 修改函数 `bindToolbar(signalType, getDataFn)`
|
||
|
||
- 参数变更:第二个参数从 data 数组改为 getter 函数 `getDataFn`
|
||
- 导出按钮:`onclick` 调用 `getDataFn()` 获取最新数据,传给 `exportToXml`
|
||
- 导入按钮:`onclick` 直接调用 `importFromXml(signalType)`
|
||
|
||
### 6. 修改各页面调用
|
||
|
||
5 个页面均传递 getter 函数解决数据引用过时问题:
|
||
```javascript
|
||
bindToolbar('out', function() { return data; });
|
||
```
|
||
|
||
## XML 格式
|
||
|
||
```xml
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<signals type="out">
|
||
<signal seq="1">
|
||
<saddr>iec.run_cnt</saddr>
|
||
<desc>运行计数</desc>
|
||
<data_type>INT32</data_type>
|
||
<val>0</val>
|
||
</signal>
|
||
</signals>
|
||
```
|
||
|
||
- 根元素 `type` 标记信号类型,导入时校验是否匹配当前页面
|
||
- `desc`、`data_type`、`val` 为参考字段,导入时忽略(仅使用 `saddr`)
|
||
|
||
## 构建注意事项
|
||
|
||
Web 服务使用 `packed_fs.c`(通过 `release/pack_web.sh` 将 `test/web_root/` 打包为 C 字节数组)。修改前端文件后需要:
|
||
|
||
```bash
|
||
cd release && bash pack_web.sh # 重新打包
|
||
rm -f x86/lib/libweb_server.a # 删除旧库
|
||
make -C src/system/libweb_server # 重新编译 web_server 库
|
||
make # 重新链接 RTU
|
||
cp x86/exe/RTU ../test/ # 复制到运行目录
|
||
```
|
||
|
||
## 验证结果
|
||
|
||
| 验证项 | 结果 |
|
||
|--------|------|
|
||
| 5 个页面均有导出/导入按钮 | ✅ |
|
||
| 导出按钮响应点击(空数据提示) | ✅ |
|
||
| 导出按钮触发文件下载(有数据时) | ✅(代码审查确认) |
|
||
| 导入按钮弹出文件选择对话框 | ✅ |
|
||
| XML 解析逻辑正确 | ✅(代码审查确认) |
|
||
| 发送 add 命令逻辑正确 | ✅(代码审查确认) |
|
||
| 编译通过 | ✅ |
|