1. 控制数据(ReinLoop 里的 core/data_collecter)和辨识数据一样,上传服务器后,需要服务器向panel提供删除下载查看功能。 2. 控制台许可证撤销界面点了没有反应,需要实现撤销和下载功能。 修改reinloop和panel,并给出服务器端需要实现的接口及功能。 ## 服务端访问约定 不再调用微信云函数或云存储接口。ReinLoop 与 ControlPanel 统一访问云服务器: ```text https://ReinLoop.dominatedconvergence.com/api ``` - 所有业务接口均使用 `POST /api`,请求与响应均为 JSON。 - 通过请求体中的 `type` 字段区分业务功能。 - 管理端接口必须携带 `adminToken`,由服务端校验 `B_ADMIN_TOKEN`;ReinLoop 客户端上传控制数据时不携带管理令牌。 - 所有响应必须包含 `success: true|false`;失败时必须提供可展示的 `errMsg`。 - 设备标识 `deviceId` 固定为 `/`,服务端必须校验其格式,禁止路径遍历。 - 服务端需要设置 `PUBLIC_BASE_URL=https://ReinLoop.dominatedconvergence.com`,确保上传地址和下载地址均为可从客户端访问的 HTTPS URL。 ### 通用文件上传接口:`uploadDataFile` ReinLoop 的控制数据、辨识数据及配置文件均通过此两步协议上传: 1. 客户端调用业务接口申请一次性上传地址: ```json { "type": "uploadDataFile", "fileName": "episode_raw_data_20260730_120000_part1of2.pkl", "folder": "/data_record/data_50SLM_5L" } ``` 2. 服务端返回 `uploadMetadata.url` 后,客户端以 `multipart/form-data` 向该 URL 提交 `file` 字段。上传成功应返回 HTTP `204` 或 `200`。 服务端需要在上传完成时保存文件本体和 `fileRecords` 元数据(包括 `fileID`、`fileName`、`folder`、`uploadTime`、`size`)。控制数据目录必须以 `/data_record/` 为前缀。 ## 服务器端接口需求(控制数据) 控制数据由 `ReinLoop/core/data_collector.py` 上传到 `/data_record/`,包括控制 Episode 的 `.pkl` 分片和对应的 JSON manifest。 以下接口均为管理端接口,要求请求体携带有效的 `adminToken`;响应统一包含 `success: true|false`,失败时返回 `errMsg`。 ### `listControlFiles` 按设备分页查询控制数据文件,供 Panel 的“控制数据”列表使用。 请求: ```json { "type": "listControlFiles", "adminToken": "", "deviceId": "/", "page": 1, "pageSize": 100 } ``` 成功响应: ```json { "success": true, "files": [ { "fileID": "local://ReinLoop_GUI//data_record/...", "fileName": "episode_raw_data_20260730_120000_part1of2.pkl", "uploadTime": "2026-07-30T04:00:00.000Z", "size": 123456 } ], "total": 1, "page": 1, "pageSize": 100 } ``` 服务端只可返回指定 `deviceId` 的 `data_record` 目录及其子目录中的文件;按上传时间倒序排列, `pageSize` 建议限制在 $1\dots100$。 ### `getControlFileDownload` 按 `fileID` 获取控制数据原始文件的短期下载地址,供 Panel 查看 JSON manifest 或保存 `.pkl` / `.json` 文件。 请求: ```json { "type": "getControlFileDownload", "adminToken": "", "fileID": "local://ReinLoop_GUI//data_record/..." } ``` 成功响应: ```json { "success": true, "fileID": "local://ReinLoop_GUI//data_record/...", "fileName": "episode_raw_data_20260730_120000_manifest.json", "uploadTime": "2026-07-30T04:00:00.000Z", "size": 1024, "url": "https://server.example/files/...?..." } ``` `url` 必须是绑定该文件且会过期的签名 URL,不能根据任意路径直接下载。服务端须校验文件存在, 且该文件必须属于控制数据目录。 ### `deleteControlFile` 永久删除指定控制数据文件,供 Panel 的二次确认删除操作使用。 请求: ```json { "type": "deleteControlFile", "adminToken": "", "fileID": "local://ReinLoop_GUI//data_record/..." } ``` 成功响应: ```json { "success": true, "deletedCount": 1 } ``` 服务端须同时删除文件本体及 `fileRecords` 中的元数据;必须校验 `fileID` 属于控制数据目录, 禁止借此接口删除模型、辨识数据、配置或许可证相关文件。文件不存在时返回明确错误,不应将删除操作视为成功。 ## 许可证接口补充 ### `getLicense` Panel 的许可证“下载”复用既有 `getLicense` 接口。请求: ```json { "type": "getLicense", "adminToken": "", "licenseId": "" } ``` 成功响应中的 `license` 对象必须包含原始许可证文本字段 `license`;Panel 将该字段保存为 `.lic` 文件。 服务端不得将私钥或其他许可证的内容一并返回。 ### `revokeLicense` Panel 的许可证撤销使用既有 `revokeLicense` 接口: ```json { "type": "revokeLicense", "adminToken": "", "licenseId": "", "reason": "管理员撤销原因" } ``` 成功响应应返回 `success: true` 及更新后的许可证对象,其中 `status` 为 `revoked`。服务端必须保留 `revokedAt` 与 `revocationReason` 审计信息;许可证在线校验接口 `validateLicense` 随后应返回 `valid: false`、`status: "revoked"`,使 ReinLoop 客户端在下一次许可证巡检时生效。 ### Panel 对应功能 - “控制数据”页面:调用 `listControlFiles` 刷新列表;JSON manifest 可请求下载后直接预览,`.pkl` 仅提供下载;删除前需二次确认。 - “许可证”页面:调用 `getLicense` 下载 `.lic`;调用 `revokeLicense` 撤销,并在成功后刷新许可证列表。 - Panel 不得自行拼接服务器文件路径、下载 URL 或绕过上述 Admin 接口访问文件。