ota管理界面
This commit is contained in:
166
.trae/documents/ota-management-interface.md
Normal file
166
.trae/documents/ota-management-interface.md
Normal file
@@ -0,0 +1,166 @@
|
||||
# OTA 管理界面 — 实施方案
|
||||
|
||||
## Context
|
||||
|
||||
系统设置模块目前缺少固件/版本管理入口。运维人员需要在一个统一界面里:
|
||||
- 查看所有机器的当前固件版本
|
||||
- 上传新的固件包(.bin/.zip)
|
||||
- 对单台或批量选中机器下发升级
|
||||
- 每台机器记住上一次的版本号,支持按机器批量回退
|
||||
|
||||
后端 OTA 接口尚未实现。本方案先以 Mock 数据把页面与交互跑通,API 函数集中在 `src/api/ota.ts`,后续后端接口就绪时只需把 mock 实现替换为真实 `request` 调用即可,页面无需改动。
|
||||
|
||||
## 关键参考文件
|
||||
|
||||
- [routes.tsx](file:///d:/code/机器人智慧服务系统/src/router/routes.tsx) — 路由 + 懒加载注册位置(L35-L42 导入区,L160-L177 systemSetting.children)
|
||||
- [SystemSetting.tsx](file:///d:/code/机器人智慧服务系统/src/pages/SystemSetting.tsx) — 系统设置页 Outlet 容器
|
||||
- [AllDeviceManagement.tsx](file:///d:/code/机器人智慧服务系统/src/components/SystemSetting/AllDeviceManagement.tsx) — 表格 + 搜索 + 操作列模板
|
||||
- [DeviceManagement.tsx](file:///d:/code/机器人智慧服务系统/src/components/SystemSetting/DeviceManagement.tsx) — Tabs 子页面模板
|
||||
- [device.ts](file:///d:/code/机器人智慧服务系统/src/api/device.ts) — API 封装范例(`request`、`getAllDevice`、`importBindDevices` 上传 FormData 范例)
|
||||
- [request.ts](file:///d:/code/机器人智慧服务系统/src/api/request.ts) — axios 实例 + token/FormData 拦截器
|
||||
- [Layout.tsx](file:///d:/code/机器人智慧服务系统/src/components/Layout.tsx) — 侧边栏菜单构建(`buildMenuTree`、`renderMenuItems`),动态菜单来自 `getMenuList`
|
||||
- [DeviceOverviewPage.tsx#L811-L814](file:///d:/code/机器人智慧服务系统/src/components/devices/DeviceOverviewPage.tsx) — 设备已有 `firmwareVersion` 字段
|
||||
- [zh/index.ts](file:///d:/code/机器人智慧服务系统/src/locales/zh/index.ts) — 中文 i18n(`systemSetting` 节 L2433、`router` 节 L3562)
|
||||
- [en/index.ts](file:///d:/code/机器人智慧服务系统/src/locales/en/index.ts) — 英文 i18n
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 新建 Mock API 层 `src/api/ota.ts`
|
||||
|
||||
定义以下函数,内部用 `setTimeout` 模拟网络延迟,数据保存在模块级内存变量中(页面刷新即重置)。
|
||||
|
||||
```ts
|
||||
// 数据结构
|
||||
interface MachineVersion {
|
||||
id: number; // 机器ID
|
||||
code: string; // 编号
|
||||
name: string; // 名称
|
||||
type: string; // 类型 ROBOT/DRONE/CAMERA/...
|
||||
online: 'ONLINE' | 'OFFLINE';
|
||||
currentVersion: string; // 当前固件版本
|
||||
previousVersion: string | null; // 上一版本(首次升级前为 null)
|
||||
lastUpgradeTime: string | null;
|
||||
status: 'IDLE' | 'UPGRADING' | 'FAILED' | 'SUCCESS';
|
||||
}
|
||||
interface FirmwarePackage {
|
||||
id: number;
|
||||
version: string; // 版本号,如 v1.2.3
|
||||
fileName: string;
|
||||
fileSize: number; // bytes
|
||||
description?: string;
|
||||
uploadTime: string;
|
||||
}
|
||||
```
|
||||
|
||||
导出函数:
|
||||
- `getMachineVersionList()` → 返回 8~10 条 Mock 机器数据
|
||||
- `getFirmwarePackageList()` → 返回已上传的固件包列表(初始内置 2 条历史版本)
|
||||
- `uploadFirmwarePackage({ file, version, description })` → 把新固件加入列表并返回
|
||||
- `upgradeMachines({ machineIds, targetVersion })` → 更新对应机器:`previousVersion = currentVersion`,`currentVersion = targetVersion`,`status` 流转,`lastUpgradeTime = now`
|
||||
- `rollbackMachines({ machineIds })` → 对每台机器:若 `previousVersion` 存在则交换 current/previous;否则报错
|
||||
|
||||
### 2. 新建页面 `src/components/SystemSetting/OTAManagement.tsx`
|
||||
|
||||
单页三段式布局(参考 [AllDeviceManagement.tsx](file:///d:/code/机器人智慧服务系统/src/components/SystemSetting/AllDeviceManagement.tsx) 的表格范式):
|
||||
|
||||
**A. 顶部 — 固件包上传卡(Card)**
|
||||
- `Upload` 组件(antd)`accept=".bin,.zip"` `beforeUpload` 返回 `false` 阻止自动上传
|
||||
- `Input` 版本号(必填,校验 `v\d+\.\d+\.\d+` 格式)
|
||||
- `Input.TextArea` 描述
|
||||
- 「上传」按钮 → 调用 `uploadFirmwarePackage`,成功后刷新固件列表
|
||||
|
||||
**B. 中部 — 已上传固件包列表(Table)**
|
||||
- 列:版本号 / 文件名 / 文件大小(格式化为 KB/MB)/ 描述 / 上传时间 / 操作(删除)
|
||||
- `rowKey="id"`,分页 pageSize=10
|
||||
|
||||
**C. 底部 — 机器版本表(Table + rowSelection)**
|
||||
- 列:机器编号 / 名称 / 类型 / 在线状态 / 当前版本 / 上一版本 / 最近升级时间 / 升级状态 / 操作(单台升级 / 单台回退)
|
||||
- `rowSelection={{ type: 'checkbox' }}` 支持多选
|
||||
- 表格上方工具栏:「批量升级」「批量回退」「刷新」按钮
|
||||
- 「批量升级」弹出 `Modal.select` 让用户选择目标固件版本(从固件包列表)
|
||||
- 「批量回退」对每台选中机器调用 `rollbackMachines`,对 `previousVersion` 为空的机器用 `message.warning` 跳过
|
||||
- 操作期间 `loading` 状态,操作完成后 `message.success` 并刷新表格
|
||||
|
||||
整页使用 `useTranslation` + `App.useApp().modal/message` 保持与 [AllDeviceManagement.tsx](file:///d:/code/机器人智慧服务系统/src/components/SystemSetting/AllDeviceManagement.tsx) 一致的交互风格。
|
||||
|
||||
### 3. 注册路由 `src/router/routes.tsx`
|
||||
|
||||
- L35-L42 区添加:`const OTAManagementPage = lazy(() => import('../components/SystemSetting/OTAManagement'));`
|
||||
- `systemSetting.children` 数组追加:`{ path: 'ota', element: withSuspense(OTAManagementPage) },`
|
||||
|
||||
### 4. 侧边栏入口 — `src/components/Layout.tsx` 加静态 fallback
|
||||
|
||||
`getMenu()` 拉到后端菜单后,遍历 `menuList` 找 `path === '/systemSetting'` 的节点,在其 `children` 末尾追加一项(若不存在):
|
||||
|
||||
```ts
|
||||
{
|
||||
key: '/systemSetting/ota',
|
||||
label: t('router.otaManagement'),
|
||||
icon: null, // 子项无图标,与现有子菜单保持一致
|
||||
}
|
||||
```
|
||||
|
||||
这样后端菜单数据未配置 OTA 时,前端也能立即在侧边栏看到入口;后端配置好之后该项会被原生菜单项覆盖或共存(key 相同不会重复渲染)。可通过 `t('router.otaManagement')` 做开关:前端 fallback 项的 label 与后端配置时使用同一个 i18n key。
|
||||
|
||||
### 5. i18n 文案
|
||||
|
||||
**`src/locales/zh/index.ts`**
|
||||
|
||||
`router` 节新增:
|
||||
```ts
|
||||
otaManagement: 'OTA 管理',
|
||||
```
|
||||
|
||||
`systemSetting` 节新增:
|
||||
```ts
|
||||
ota: {
|
||||
title: 'OTA 固件管理',
|
||||
uploadCard: '上传固件包',
|
||||
versionPlaceholder: '例如 v1.2.3',
|
||||
description: '描述',
|
||||
uploadBtn: '上传',
|
||||
firmwareList: '已上传固件包',
|
||||
machineVersionList: '机器版本列表',
|
||||
currentVersion: '当前版本',
|
||||
previousVersion: '上一版本',
|
||||
lastUpgradeTime: '最近升级时间',
|
||||
upgradeStatus: '升级状态',
|
||||
batchUpgrade: '批量升级',
|
||||
batchRollback: '批量回退',
|
||||
selectTargetVersion: '选择目标固件版本',
|
||||
confirmUpgrade: '确认对选中的 {count} 台机器升级到 {version}?',
|
||||
confirmRollback: '确认对选中的 {count} 台机器回退到上一版本?',
|
||||
noPreviousVersion: '机器 {name} 没有上一版本,无法回退',
|
||||
uploadSuccess: '固件包上传成功',
|
||||
upgradeSuccess: '升级指令已下发',
|
||||
rollbackSuccess: '回退指令已下发',
|
||||
deleteConfirm: '确认删除固件包 {version}?',
|
||||
statusIdle: '空闲',
|
||||
statusUpgrading: '升级中',
|
||||
statusFailed: '失败',
|
||||
statusSuccess: '成功',
|
||||
},
|
||||
```
|
||||
|
||||
**`src/locales/en/index.ts`** 同步补全英文翻译。
|
||||
|
||||
## 验证步骤
|
||||
|
||||
1. `npm run dev` 启动开发服务器
|
||||
2. 登录后从侧边栏「系统设置 → OTA 管理」进入,或直接访问 `/systemSetting/ota`
|
||||
3. 验证流程:
|
||||
- 顶部上传一个 `.zip` 测试文件 + 填版本号 `v1.0.0` → 中部固件列表出现新条目
|
||||
- 底部机器表勾选 2-3 台机器 → 点「批量升级」→ 弹窗选 `v1.0.0` → 确认 → 选中机器 `currentVersion` 变为 `v1.0.0`、`previousVersion` 记录原版本、`lastUpgradeTime` 刷新
|
||||
- 再次勾选同样机器 → 点「批量回退」→ 确认 → `currentVersion` 与 `previousVersion` 互换
|
||||
- 单台机器「操作」列的「升级」/「回退」按钮单独验证
|
||||
- 取消勾选时「批量升级/回退」按钮置灰
|
||||
- 切换语言到 English,所有文案正常
|
||||
4. 浏览器 Network 面板无需真实请求(Mock 在前端完成);控制台无报错
|
||||
5. `npm run build` 通过,无 TS 报错
|
||||
|
||||
## 范围边界
|
||||
|
||||
- 仅做前端 + Mock 数据,不修改后端代码
|
||||
- 不改 `getMenuList` 接口契约,仅前端 Layout 加 fallback
|
||||
- 不引入新依赖,全部使用项目已有的 antd 组件
|
||||
- Mock 数据保存在模块内存,刷新即重置;后续接后端时仅替换 `src/api/ota.ts` 内部实现
|
||||
Reference in New Issue
Block a user