Files
railwaysystem/docs/development/demo-electronic-board-cleanup.md
T

111 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RailwaySystem Electronic Board Demo-Safe Cleanup (V2 闭环版) 实施报告
## 1. 任务背景与集成基线
本任务目标为 **RailwaySystem Electronic Board Demo-Safe Cleanup**:
1. **基线对齐**:切换至正式受控集成分支 `integration/delivery-cicd-20260914` (commit `c763cb691c4a48a0a01339de83731a99ed9311e6`),在新分支 `fix/demo-electronic-board-cleanup-v2` 下开发。
2. **结构对齐**:与已在数据库执行的 Database V2 (`public.train_electronic_board`) 真实物理结构完全对齐;
3. **界面清洁**:前端管理页面彻底消除裸露的数据库表名、列名、主键 ID 及枚举裸数值;
4. **生命周期写保护**:
- `boardStatus` / `lastHeartbeat` 均为设备运行只读字段;
- 前端表单中彻底删除 `boardStatus` 与 `lastHeartbeat`,避免管理员人工篡改;
- 后端新增时显式初始化 `boardStatus = 0`(离线);
- 后端编辑时写保护:强制置空防篡改,保留数据库原值;
5. **boardId 闭环**:前端不传 `boardId`,后端 Service 自动生成唯一 UUID,实现 INSERT 与 GET 闭环;
6. **逻辑删除**:DELETE 操作统一使用 `UPDATE ... SET del_flag = '2'` 软删除,所有查询(包含教室聚合)强制排除 `del_flag = '2'`;
7. **教室聚合无回归**:完全保持 CG-05 裁决的轻量 `ClassroomBoardSummaryVO` 契约,既有聚合行为 100% 正常;
8. **不伪造能力**:不伪造不存在的设备心跳上报、不伪造协议/MQTT、不添加假“在线心跳模拟”按钮。
---
## 2. 真实数据库 V2 结构验证 (Kingbase 元数据)
通过直连 Kingbase 只读查询 `information_schema.columns`、`information_schema.table_constraints`、`information_schema.key_column_usage`,确认当前 `public.train_electronic_board` 的实际元数据如下:
### 2.1 真实列清单与约束
| 列名 | 数据类型 | 允许空 | 默认值 | 约束类型 | 说明 |
|:---|:---|:---|:---|:---|:---|
| `board_id` | character varying(64) | NO | 无 | PRIMARY KEY (`pk_train_electronic_board`) | 班牌设备主键 UUID |
| `board_sn` | character varying(64) | NO | 无 | UNIQUE (`uq_train_electronic_board_sn`) | 设备硬件唯一序列号 |
| `board_name` | character varying(100) | NO | 无 | - | 设备名称 (V2 迁移脚本新增) |
| `bind_classroom_id`| character varying(64) | YES | NULL | FOREIGN KEY (`fk_electronic_board_classroom`) | 关联教室主键,外键关联 `train_classroom_info.class_room_id` |
| `board_ip` | character varying(45) | YES | NULL | - | 设备当前 IP 地址 |
| `api_endpoint` | character varying(255) | YES | NULL | - | 设备通信/推流端点 URL |
| `support_checkin_type` | character varying(50) | YES | 'CARD,FACE' | - | 支持签到方式 (CARD, FACE, QR) |
| `board_status` | smallint | YES | 1 | - | 状态 (0 离线, 1 在线) |
| `last_heartbeat` | timestamp without time zone | YES | NULL | - | 最近心跳时间 |
| `remark` | character varying(500) | YES | NULL | - | 备注信息 |
| `create_by` | character varying(64) | YES | '' | - | 创建人账号 |
| `create_time` | timestamp without time zone | YES | clock_timestamp() | - | 创建时间 |
| `update_by` | character varying(64) | YES | '' | - | 修改人账号 |
| `update_time` | timestamp without time zone | YES | clock_timestamp() | - | 修改时间 |
| `del_flag` | character(1) | YES | '0' | - | 逻辑删除标志 ('0' 存在, '2' 删除) |
### 2.2 确认已物理删除的旧字段
- ❌ `bind_plan_id`
- ❌ `board_content`
- ❌ `board_playmode`
- ❌ `create_user`
---
## 3. 后端最小兼容整改明细
### 3.1 实体模型对齐 (`TrainElectronicBoard.java`)
- 剔除 `bindPlanId`、`boardContent`、`boardPlaymode`、`createUser`。
- 补充 `boardName`、`apiEndpoint`、`delFlag`。
- 标注 `@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")`。
### 3.2 映射器对齐与逻辑删除 (`TrainElectronicBoardMapper.xml`)
- 彻底剔除不存在的旧列,加入 `board_name` 与 `api_endpoint`。
- 查询 `selectTrainElectronicBoardList` 与 `selectTrainElectronicBoardByBoardId` 均强制带上 `where del_flag = '0'`。
- 逻辑删除:
```sql
<update id="deleteTrainElectronicBoardByBoardId" parameterType="String">
update train_electronic_board
set del_flag = '2',
update_time = clock_timestamp()
where board_id = #{boardId}
</update>
```
### 3.3 业务服务层写保护与主键闭环 (`TrainElectronicBoardServiceImpl.java`)
- **boardId 生成位置**:在 `insertTrainElectronicBoard` 中:
```java
if (StringUtils.isEmpty(trainElectronicBoard.getBoardId())) {
trainElectronicBoard.setBoardId(IdUtils.fastSimpleUUID());
}
trainElectronicBoard.setBoardStatus(0); // 显式初始化为离线
```
- **boardStatus / lastHeartbeat 写保护位置**:在 `updateTrainElectronicBoard` 中:
```java
trainElectronicBoard.setBoardStatus(null);
trainElectronicBoard.setLastHeartbeat(null);
```
### 3.4 控制器与接口兼容 (`TrainElectronicBoardController.java`)
- 路由基路径:`@RequestMapping("/train/board")`。
- 权限保持系统正式权限:`@ss.hasPermi('system:board:...')`。
---
## 4. 前端表单与列表重构 (`build_ui/src/views/train/board/index.vue`)
- **表单彻底删除 boardStatus / lastHeartbeat**:仅录入设备名称*、硬件序列号*、安装教室、设备IP、通信端点、签到支持方式复选组、备注。
- **列表优雅展示**:安装教室根据 ID 映射显示 `roomName`;状态 Tag 化(绿标签“在线”/灰标签“离线”);心跳空显示“—”。
---
## 5. KingbaseES 9 步最小 Smoke Test 实测结果
在直连真实 KingbaseES 测试(`BoardSmokeTest.java`)中执行全部 9 项测试,结果全绿:
1. **新增 Board(不传 boardId)**:Service 生成 UUID 并成功执行 INSERT。
2. **查询 Board**:验证存在,初始 `board_status` 为 0(离线),`last_heartbeat` 为 NULL。
3. **修改业务字段**:名称与 IP 成功更新。
4. **确认写保护**:修改无法人为篡改 `boardStatus` 与 `lastHeartbeat`,DB 原值完好。
5. **删除 Board**:执行软删除 UPDATE。
6. **DB 物理验证**:底层行记录仍存在,`del_flag` 成功标记为 `'2'`。
7. **业务 list 验证**:业务 list 查询自动排除,已不再返回该设备。
8. **新增绑定教室 Board**:成功插入绑定测试教室的班牌。
9. **Classroom 聚合验证**:通过 `ClassroomBoardSummaryVO` 聚合查询成功回显该班牌,既有聚合行为 100% 无回归!