# ReinLoop ControlPanel 功能总览 ## 1. 产品定位 ControlPanel 是 ReinLoop 的 B 端管理工作台,用于管理公司与产线、签发许可证、管理模型、发布参数配置,并接收和审核 ReinLoop 上传的辨识数据。 桌面端基于 Electron,业务请求统一发送到 ReinLoop Server。渲染页面不直接访问文件系统、私钥或管理凭据,敏感操作通过 Electron 主进程完成。 ## 2. 连接与鉴权 应用启动后首先显示连接页面,只包含: - Server API URL - Admin Token - “连接并校验”按钮 点击连接后,主进程调用需要管理权限的 `listOrganizations` 接口,同时验证: - Server 地址是否可访问 - API 路径是否正确 - Admin Token 是否有效 只有校验成功才显示后续业务工作台。连接失败时业务区域保持隐藏,并显示 Server 返回的错误信息。 连接信息仅保存在当前应用进程中: - Token 不写入浏览器存储。 - Token 不写入本地配置文件。 - Token 只由 Electron 主进程附加到 Server 请求。 - 本次应用会话不提供更改连接入口;需要切换 Server 或 Token 时重新启动应用。 支持通过环境变量提供默认值: ```text REINLOOP_API_URL B_ADMIN_TOKEN REINLOOP_DEVICE_ID POLL_INTERVAL_MS DOWNLOAD_DIR ``` ## 3. 公司与产线选择 连接成功后,工作台顶部显示公司和产线两个选择菜单。 设备业务标识由 Server 生成,格式固定为: ```text / ``` 例如: ```text sample-co/line-1 ``` 配置、模型、辨识数据、审核反馈和容积请求都使用同一个 `deviceId`,避免不同公司或产线的数据混用。 ### 在线状态 公司菜单显示在线产线汇总,例如: ```text 示例公司 (sample-co) · 在线 2/3 ``` 产线菜单显示具体状态: ```text ● 在线 · 一号产线 (line-1) ○ 离线 · 二号产线 (line-2) ◇ 状态未知 · 三号产线 (line-3) ``` Panel 每 10 秒调用一次 `listOrganizations` 静默刷新状态。 Server 已实现设备心跳: - ReinLoop 调用 `deviceHeartbeat` 更新产线的 `lastSeenAt`。 - Server 以最近 30 秒是否收到心跳计算 `online`。 - `listOrganizations` 返回每条产线的 `online` 和 `lastSeenAt`。 - 旧数据缺少状态字段时,Panel 显示“状态未知”,不会误报在线或离线。 ## 4. 组织管理 “组织管理”页面支持: - 添加公司 - 为指定公司添加产线 - 刷新公司与产线列表 公司编码和产线编码只允许: - 小写英文字母 - 数字 - 下划线 - 连字符 编码长度为 2 到 64 位,并且必须以字母或数字开头。 公司编码由 Server 保证全局唯一;产线编码在同一公司内唯一。 相关 Server 接口: ```text listOrganizations createCompany createProductionLine ``` ## 5. 许可证签发与管理 “许可证”页面根据当前选择的公司和产线签发许可证。 签发字段包括: - 公司 - 产线 - 组合设备 ID - 签发时间 - 到期时间 - 功能范围 - 唯一许可证 ID 许可证载荷示例: ```json { "license_id": "UUID", "customer": "示例公司", "company_id": "company_UUID", "production_line_id": "line_UUID", "device_id": "sample-co/line-1", "issued": "2026-07-25 12:00", "expiry": "2027-07-25 12:00", "features": "*" } ``` ### 签名格式 Panel 使用 RSA-PSS SHA-256 签名,与 ReinLoop 的 Python 验签逻辑兼容。 许可证文件格式: ```text base64(JSON)|base64(signature) ``` 签发核心会拒绝: - 空公司或产线标识 - 非法组合设备 ID - 无效日期格式 - 到期时间不晚于签发时间 - 空功能字段 ### 私钥安全 - 每次签发由操作者选择外部 PEM 私钥。 - 私钥只在 Electron 主进程内读取。 - 私钥不会进入渲染页面。 - 私钥不会上传 Server。 - 私钥路径和内容不会由 Panel 持久化。 - 私钥不会打进安装包。 ### 本地与 Server 一致性 签发流程为: 1. 选择私钥。 2. 选择本地许可证保存位置。 3. 生成并写入本地许可证。 4. 将签发结果登记到 Server。 5. Server 登记失败时删除本次本地文件,避免出现半完成状态。 许可证管理支持: - 刷新许可证列表 - 查看许可证详情 - 下载已签发许可证 - 撤销有效许可证 - 填写撤销原因 - 区分有效和已撤销状态 相关 Server 接口: ```text createLicense listLicenses getLicense revokeLicense ``` 下载已签发许可证复用 `getLicense` 返回的许可证原文;Panel 在本地选择保存位置后写入 `.lic` 文件。 ## 5.1 控制数据暂存 “控制数据”页面按当前产线显示 ReinLoop 在控制结束后上传到 `/data_record/` 的 Episode 分片和清单文件。页面支持: - 刷新控制数据列表 - 查看 JSON 清单内容;`.pkl` 分片显示文件元数据和本地缓存位置 - 下载任意控制原始文件 - 删除指定控制数据文件 控制 Episode 分片采用 Python pickle 格式,Panel 不在渲染进程反序列化该二进制数据; 需要详细分析时,应下载后使用 ReinLoop/Python 读取。JSON manifest 可直接在页面中查看。 Panel 需要 Server 提供以下 Admin 接口: ```text listControlFiles deviceId, page, pageSize -> files, total, page, pageSize getControlFileDownload fileID -> fileID, fileName, uploadTime, size, url deleteControlFile fileID -> deletedCount ``` 每条 `files` 记录至少包含 `fileID`、`fileName`、`uploadTime` 和 `size`。下载接口必须返回 可下载原始文件的短期签名 URL;删除接口必须同时删除文件本体和元数据,并仅允许删除该设备的 控制数据目录中的文件。 ## 6. 模型管理 “模型管理”页面按当前产线操作: ```text /model_config ``` 支持: - 刷新模型列表 - 查看文件名、上传时间和大小 - 从本地选择并上传模型 - 同名模型覆盖前要求确认并输入完整文件名 - 下载模型到本地 `downloads` 目录 - 按 `fileID` 精确删除模型;删除前要求两次确认并输入完整文件名 上传使用 Server 的两步协议: 1. 调用 `uploadDataFile` 获取上传地址与凭证。 2. 使用 multipart 表单上传文件内容。 相关 Server 接口: ```text listModels uploadDataFile downloadModel deleteFile ``` ## 7. 参数配置发布 “配置发布”页面支持两类参数: - 容积测量配置 - 系统辨识配置 用户可以: - 直接编辑 JSON - 从本地导入 JSON - 从 Server 读取当前配置 - 发布新配置 ### 容积测量参数 严格包含 8 个字段: ```json { "q_in_val": 91, "dt": 0.1, "p_max": 200, "fit_low": 50, "fit_high": 200, "T_delta": 30, "xa_full": 1000, "num_runs": 6 } ``` Panel 在发布前检查: - 配置必须是 JSON 对象 - 字段不能缺失 - 不能包含多余字段 - 数值必须有限 - `num_runs` 必须是整数 容积配置只会响应 ReinLoop 当前有效的一次性请求;没有待处理请求时 Server 拒绝提交。 ### 系统辨识参数 严格包含 9 个字段: ```json { "q_in_val": 91, "dt": 0.1, "n_order": 8, "t_c": 2.5, "levels": [10, 20, 30, 40, 50, 60, 70, 80], "dead_area": 0, "xa_full": 1000, "V_val": 1, "repeat": 2 } ``` Panel 将其序列化为 `parameter,value` 两列 CSV,并发布到当前产线: ```text /identification_config/identification_config.csv ``` ## 8. 辨识数据接收与绘图 Panel 按当前产线轮询 Server 收件箱,不扫描 Server 文件目录。 默认轮询间隔为 1 秒,可通过 `POLL_INTERVAL_MS` 修改,最小允许值为 500 毫秒。 支持两类数据: ### 辨识 CSV 收到 CSV 后: 1. 下载到本地。 2. 生成阀门开度与压力组合时序图。 3. 在工作台中显示图片。 4. 等待人工提交“通过”或“未通过”。 ### 行程稳定压力 JSON 收到 JSON 后: 1. 下载到本地。 2. 将行程与稳定压力绘制为固定 0-1000 行程范围的数值折线图,并显示各点坐标。 3. 在工作台中显示图片。 4. 绘图成功后确认已处理;文件保留在 Server 暂存区,可继续查看和下载。 绘图结果支持在系统文件管理器中定位,也支持在应用内放大、缩小、适应窗口和原始比例查看。 ## 9. 辨识数据暂存 “辨识数据”页面按当前产线列出 Server 暂存的 CSV 和行程 JSON,支持: - 查看并生成对应图像预览 - 将原始 CSV 或 JSON 保存到用户选择的位置 - 管理员二次确认后删除暂存数据 - 查看待处理和已处理状态 文件下载请求携带 Admin Token;Server 可使用该令牌校验下载访问,或返回短期授权下载 URL。 ## 10. 辨识人工审核 绘图页面提供: - “通过”按钮 - “未通过”按钮 ### 通过 提交数字 `1`: ```json { "type": "setIdentificationFeedback", "deviceId": "sample-co/line-1", "runId": "辨识 CSV 文件名", "result": 1 } ``` ReinLoop 获取结果后结束当前辨识流程。 ### 未通过 提交数字 `0` 前,Panel 强制要求: 1. 选择一份新的系统辨识参数 JSON。 2. 成功发布新的辨识 CSV 配置。 3. 再提交未通过结果。 ReinLoop 获取数字 `0` 后重新下载配置并执行下一轮辨识。 ### 消息可靠性 CSV 不会在绘图后立即从 Server 删除。 只有以下操作都成功后才确认消息: 1. 人工审核结论提交成功。 2. Server 接受 `0/1` 反馈。 3. Panel 调用 `ackPanelFile` 成功。 如果应用在审核前退出,CSV 仍保留在 Server,重新启动并选择同一产线后可以再次获取。 Panel 同一时间只处理一个待审核 CSV,避免多个审核结果串线。 ## 10. Electron 安全边界 BrowserWindow 使用: ```text contextIsolation: true nodeIntegration: false sandbox: true ``` 渲染页面只能通过 preload 暴露的有限 IPC 调用主进程。 以下能力仅存在于主进程: - Server Token 请求 - 私钥读取和许可证签名 - 本地文件选择与保存 - 模型上传与下载 - 绘图文件读取 - 在文件管理器中定位文件 页面配置了 Content Security Policy,只允许加载应用自身脚本、样式和 data URL 图片。 ## 11. 命令行兼容工具 除 Electron GUI 外,仍保留原有命令行能力: ```text b-admin.js poll-panel-inbox.js ``` 支持: - 发布容积配置 - 发布系统辨识配置 - 读取配置 - 轮询待处理数据 - 命令行人工审核 Electron GUI 是主要管理入口,命令行工具用于调试和兼容既有流程。 ## 12. 运行与打包 安装依赖: ```bash cd ControlPanel npm install ``` 启动 Electron: ```bash npm run gui ``` 运行语法检查: ```bash npm run check ``` 运行测试: ```bash npm test ``` 构建 Windows 安装版和便携版: ```bash npm run pack:win ``` 输出目录: ```text Build/ ``` 构建内容包含: - Electron 主进程和 preload - 页面文件 - Server 客户端 - 配置管理模块 - 许可证签发模块 - CSV/JSON 绘图模块 - `canvas` 原生依赖 `canvas` 会从 ASAR 中解包,以便 Windows 原生模块正常加载。 ## 13. 当前验证状态 已验证: - 所有 Panel JavaScript 文件通过 `node --check`。 - 许可证 RSA-PSS 签名可由对应公钥验证。 - 非法身份、设备 ID 和时间范围会被拒绝。 - 许可证签发单元测试通过。 - 连接门禁首屏只显示 Server URL、Token 和校验按钮。 - 未通过连接校验时业务区域保持隐藏。 - 页面文件没有编辑器诊断错误。 当前 Linux 工作区中的完整绘图测试受原生 `canvas` 环境限制:已有 `canvas.node` 不是当前 Linux 可加载格式,源码重建又缺少系统 `pangocairo` 开发库。该限制不影响 JavaScript 语法和许可证测试,但 Windows 发布前仍需在目标构建环境执行完整绘图和打包验证。 ## 14. 主要 Server 接口依赖 连接与组织: ```text listOrganizations createCompany createProductionLine ``` 许可证: ```text createLicense listLicenses getLicense revokeLicense ``` 模型与文件: ```text uploadDataFile listModels downloadModel deleteFile ``` 配置: ```text getPendingVolumeConfigRequest submitVolumeConfigFile publishIdentificationConfig getIdentificationConfig getFunctionConfig ``` 辨识与收件箱: ```text getPendingPanelFile ackPanelFile setIdentificationFeedback ``` 设备在线状态由 ReinLoop 调用: ```text deviceHeartbeat ```