# HANDOFF — 设备模拟模块

> **生成时间**: 2026-08-06
> **当前分支**: `platform-auto-test`
> **最近提交**: `b3b54f03` feat(smart-locate, device-sim): 验证类步骤自动识别 + 设备列表增强

---

## 📊 会话进度记录

### 2026-08-06 会话 B：中控设备多类型主题上报 — 代码实现

**会话目标**：按执行计划实现中控设备 7 种主题类型上报的 4 个阶段

**已完成内容**：

#### ✅ 阶段一：后端主题模板 + 模拟器消息体

1. **`topic_templates.py`** — 中控主题模板从 2 种扩展为 7 种
   - 新增 `template_subscribe` + `template_publish` 双模板结构（替代旧的 `template` + `direction`）
   - 每种模板带 `device_type` 标识，用于按类型筛选
   - 新增 `resolve_topics_by_device_type()` 函数，根据 `topic_params.device_type` 筛选对应主题
   - `resolve_all_topics()` 兼容新旧两种模板结构

2. **`central_simulator.py`** — 新增 7 种消息体构建方法
   - `_build_room_online_payload()` — 会议室在线（action: online）
   - `_build_device_online_payload()` — 设备在线（action: _updatestatus）
   - `_build_audio_payload()` — 音频系统（action: _updateaudio）
   - `_build_video_payload()` — 视频系统（action: _updatevideo）
   - `_build_control_payload()` — 控制系统（action: _updatecontrol）
   - `_build_network_payload()` — 网络系统（action: _updatenetwork）
   - `_build_power_payload()` — 电源系统（action: _updatepower）
   - `build_status_payload()` 根据 `topic_params.device_type` 动态选择方法

3. **`base_simulator.py`** — `_resolve_topics()` 支持按 `device_type` 筛选中控主题
   - 中控设备且 `topic_params` 含 `device_type` 时调用 `resolve_topics_by_device_type()`
   - 其他设备类型保持原有逻辑

#### ✅ 阶段二：后端 Excel 导入 + API 适配

1. **`device_sim_service.py`** — Excel 导入支持主题类型
   - 列映射新增 "主题类型" → `central_device_type`（兼容旧版 "设备类型"）
   - 中控设备自动存入 `topic_params.device_number`（= device_id）
   - 中控设备自动存入 `topic_params.device_type`（默认 `device_online`）
   - 新增 `switch_device_type()` 方法：更新 topic_params + 运行中自动重启

2. **`device_sim.py`** — Excel 模板 + 切换 API
   - 中控模板新增"会议室编号"和"主题类型"两列
   - 新增 `PATCH /api/device-sim/devices/{device_id}/type` API
   - API 参数 `device_type_name` 支持 7 种类型标识

3. **`device_sim.py` (schemas)** — `TopicTemplateResponse` 新增 `device_type` 字段

#### ✅ 阶段三：前端设备类型显示 + 切换 UI

1. **`device.ts`** — 新增 `CENTRAL_DEVICE_TYPES` 映射 + `TopicTemplate.deviceType` 字段
2. **`deviceSim.ts`** — 新增 `switchDeviceType()` API 调用
3. **`DeviceList.vue`** — 
   - 中控设备列表新增"主题类型"列（带 el-tag 标签）
   - 操作列新增"切换类型"下拉框（7 种选项，当前类型禁用+勾选）
   - 切换确认弹窗提示运行中设备将自动重启
   - 导入弹窗中控提示更新（会议室编号 + 主题类型说明）
   - **表格各列增加 tooltip 说明**：
     - 设备名称：设备的显示名称，可自定义
     - 设备 ID：设备的唯一标识符，用于 MQTT 消息关联
     - 主题类型：中控设备上报的 MQTT 主题类型，支持 7 种切换
     - 状态：设备的运行状态：运行中/已停止/异常
     - 上报次数：设备累计发送 MQTT 消息的次数
     - 最后上报：设备最后一次发送 MQTT 消息的时间

#### ✅ 阶段四：联调测试 + 部署验证

- Python 语法检查通过
- 前端 `npm run build` 构建成功
- 已部署到 192.168.5.60（SFTP 上传 + docker restart）

#### ✅ 文案优化

- 用户可见的"设备类型"统一改为"主题类型"
- Excel 表头、前端 UI、API 错误提示均已更新
- 后端列映射兼容旧版"设备类型"列名

**中控 7 种主题类型**：

| 类型 | action | 发布主题 | client_udid 来源 |
|------|--------|---------|------------------|
| 会议室在线 | `online` | `/maintain/room/online/{会议室编号}/` | -（udid 字段） |
| 设备在线 | `_updatestatus` | `/maintain/room/master/client/` | 会议室编号 |
| 音频系统 | `_updateaudio` | `/maintain/room/master/client/` | 设备编号 |
| 视频系统 | `_updatevideo` | `/maintain/room/master/client/` | 设备编号 |
| 控制系统 | `_updatecontrol` | `/maintain/room/master/client/` | 设备编号 |
| 网络系统 | `_updatenetwork` | `/maintain/room/master/client/` | 设备编号 |
| 电源系统 | `_updatepower` | `/maintain/room/master/client/` | 设备编号 |

**本次会话修改文件清单**：

| 文件 | 变更类型 | 说明 |
|------|----------|------|
| `backend/app/simulators/topic_templates.py` | 修改 | 中控模板扩展为 7 种 + 新增 resolve_topics_by_device_type() |
| `backend/app/simulators/central_simulator.py` | 修改 | 新增 7 种消息体构建方法 + 动态选择逻辑 |
| `backend/app/simulators/base_simulator.py` | 修改 | _resolve_topics() 支持按 device_type 筛选 |
| `backend/app/routers/device_sim.py` | 修改 | Excel 模板新增主题类型列 + PATCH 切换类型 API |
| `backend/app/services/device_sim_service.py` | 修改 | Excel 导入支持主题类型 + switch_device_type() |
| `backend/app/schemas/device_sim.py` | 修改 | TopicTemplateResponse 新增 device_type 字段 |
| `frontend/src/types/device.ts` | 修改 | 新增 CENTRAL_DEVICE_TYPES 映射 |
| `frontend/src/api/deviceSim.ts` | 修改 | 新增 switchDeviceType() API |
| `frontend/src/components/device/DeviceList.vue` | 修改 | 主题类型列 + 切换下拉框 + tooltip + 导入提示 |

---

### 2026-08-06 会话 A：中控设备多类型主题上报 — PRD + 计划

**会话目标**：输出 PRD 需求文档和执行计划文档

**已完成内容**：
1. ✅ PRD 需求文档 — `Docs/PRD/需求文档/设备模拟/_PRD_需求优化_中控设备多类型主题上报.md`
2. ✅ 执行计划文档 — `Docs/PRD/需求文档/设备模拟/_执行计划_中控设备多类型主题上报.md`
3. ✅ 初步代码实现（已部署到 192.168.5.60 但需按新计划重构）

---

### 2026-08-05 会话：Excel 批量导入 + 设备列表增强

## 一、本次会话完成的工作

### 1. ✅ Excel 批量导入设备功能

**需求**: 通过 Excel 文件批量导入模拟设备，快速创建多台设备。

**实现**:
- **后端新增端点**:
  - `GET /api/device-sim/devices/import/template` — 下载导入模板
  - `POST /api/device-sim/devices/import` — 批量导入设备
- **Excel 表头格式**:
  - 环境配置名称（必填）— 后台按名称查找环境配置 ID
  - 设备名称（必填）
  - 设备ID（必填）— 同一环境下唯一
  - 授权码/app_token（可选，仅门口屏）— 填入 topic_params
  - 自动重连（可选）— 支持是/否、true/false
  - 启用定时上报（可选）
  - 上报间隔(秒)（可选）
- **前端**:
  - 新增"批量导入"按钮和导入弹窗
  - 支持拖拽上传 .xlsx 文件
  - 模板下载链接
  - 导入结果表格显示每行成功/失败及错误原因

**修改文件**:
- `backend/requirements.txt` — 添加 `openpyxl==3.1.2`
- `backend/app/schemas/device_sim.py` — 新增 `DeviceImportRowResult`、`DeviceImportResponse`
- `backend/app/services/device_sim_service.py` — 新增 `import_simulators_from_excel()` 方法
- `backend/app/routers/device_sim.py` — 新增导入和模板下载端点
- `frontend/src/types/device.ts` — 新增导入相关类型
- `frontend/src/api/deviceSim.ts` — 新增 `importDevices()`、`downloadImportTemplate()`
- `frontend/src/components/device/DeviceList.vue` — 新增导入按钮、弹窗、逻辑

### 2. ✅ 移除实时消息流组件

**需求**: 暂时移除实时消息流面板，简化界面。

**实现**:
- 四个设备模拟页面（门口屏/无纸化/中控/集控客户端）移除右侧消息流面板
- 只保留设备列表，全宽显示
- `MessageStream.vue` 组件保留但不再使用

**修改文件**:
- `frontend/src/views/device-sim/DoorSim.vue`
- `frontend/src/views/device-sim/PaperlessSim.vue`
- `frontend/src/views/device-sim/CentralSim.vue`
- `frontend/src/views/device-sim/ClientSim.vue`

### 3. ✅ 分页器增强

**需求**: 分页器支持选择每页条数。

**实现**:
- 新增每页条数选择：10/20/50/100 条/页
- 布局调整：总数 + 每页条数 + 分页 + 跳转
- 使用 `v-model:page-size` 替代固定的 `limit`

**修改文件**:
- `frontend/src/components/device/DeviceList.vue`

### 4. ✅ 全部启动/全部停止按钮

**需求**: 快捷操作当前页所有设备。

**实现**:
- 未勾选设备时显示"全部启动"、"全部停止"按钮
- 勾选设备后切换为"批量启动"、"批量停止"、"批量删除"
- 操作当前页显示的所有设备

**修改文件**:
- `frontend/src/components/device/DeviceList.vue`

### 5. ✅ 模板下载中文文件名修复

**问题**: 下载模板时，中文文件名导致 HTTP 头编码错误。

**修复**: 使用 `urllib.parse.quote()` 对文件名进行 URL 编码。

**修改文件**:
- `backend/app/routers/device_sim.py`

### 6. ✅ 部署到 192.168.5.60

**方式**: 使用 paramiko SSH + SFTP 上传前端 dist 和后端代码，容器内安装 openpyxl 依赖后重启。

---

## 二、已知问题

### P0 — 消息流页面显示"暂无消息"（已移除消息流 UI，问题暂缓）

**说明**: 实时消息流组件已移除，此问题暂不处理。后续如需恢复消息流功能，再排查消息队列入队问题。

---

## 三、后续待办

| 优先级 | 任务 | 说明 |
|--------|------|------|
| P1 | 中控 7 种主题类型联调测试 | 下载中控模板 → 填写 7 种类型 → 导入验证 → 运行中切换类型 → 消息体格式验证 |
| P1 | 中控/集控客户端主题确认 | 确认真实上报/订阅主题与实际系统一致 |
| P2 | 环境配置统计功能 | 统计各环境下的设备数量 |
| P2 | 旧版中控设备兼容性测试 | 已创建的中控设备（无 device_type）默认为"设备在线"，需验证 |
| P2 | 执行计划文档状态更新 | 更新 `_执行计划_中控设备多类型主题上报.md` 中 4 个阶段的执行记录 |

---

## 四、相关文档索引

| 文档 | 路径 |
|------|------|
| 设备模拟 PRD | `Docs/PRD/需求文档/设备模拟/_PRD_需求文档_设备模拟模块.md` |
| 中控多类型 PRD | `Docs/PRD/需求文档/设备模拟/_PRD_需求优化_中控设备多类型主题上报.md` |
| 中控多类型执行计划 | `Docs/PRD/需求文档/设备模拟/_执行计划_中控设备多类型主题上报.md` |

---

## 五、部署信息

| 项目 | 值 |
|------|-----|
| 服务器 IP | `192.168.5.60` |
| SSH 用户/密码 | `ubains / Ubains@123` |
| 部署目录 | `/data/third_party/plat-auto-test/` |
| Docker 容器名 | `plat-auto-test-app` |
| MySQL 容器名 | `plat-auto-test-mysql` |
| 前端地址 | http://192.168.5.60 |

**部署方式**: 
- 后端：SFTP 上传 `backend/app/` 下修改的文件到服务器 `/data/third_party/plat-auto-test/backend/app/`
- 前端：本地 `npm run build` 后，SFTP 上传 `frontend/dist/` 到服务器 `/data/third_party/plat-auto-test/frontend/dist/`
- 重启容器：`docker restart plat-auto-test-app`

---

## 六、Excel 导入模板格式

### 门口屏模板

| 列 | 表头 | 必填 | 说明 |
|----|------|------|------|
| A | 环境配置名称 | 是 | 需与已创建的环境配置名称完全一致 |
| B | 设备名称 | 是 | |
| C | 设备编号 | 是 | 同一环境下唯一 |
| D | 授权码(app_token) | 否 | 仅门口屏需要，填入 topic_params |
| E | 自动重连 | 否 | 默认 true，支持 是/否、true/false |
| F | 启用定时上报 | 否 | 默认 true |
| G | 上报间隔(秒) | 否 | 默认 30，整数 >= 1 |

### 中控模板

| 列 | 表头 | 必填 | 说明 |
|----|------|------|------|
| A | 环境配置名称 | 是 | 需与已创建的环境配置名称完全一致 |
| B | 设备名称 | 是 | |
| C | 设备编号 | 是 | 同一环境下唯一，同时作为消息体 client_udid |
| D | 会议室编号 | 是 | 用于 MQTT 主题订阅和消息上报 |
| E | 主题类型 | 是 | 会议室在线/设备在线/音频系统/视频系统/控制系统/网络系统/电源系统 |
| F | 自动重连 | 否 | 默认 true |
| G | 启用定时上报 | 否 | 默认 true |
| H | 上报间隔(秒) | 否 | 默认 30 |

---

## 七、API 新增端点

| 方法 | 路径 | 说明 |
|------|------|------|
| `PATCH` | `/api/device-sim/devices/{device_id}/type` | 切换中控设备主题类型，参数 `device_type_name` |

---

*本文档记录设备模拟模块开发状态，供下次会话快速恢复上下文。*
