Files
qhmes/yy-admin-master/doc/桌面端后端数据交互通用模板(以车辆管理为例).md

300 lines
8.8 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.
# 桌面端后端数据交互通用模板(以车辆管理为例)
## 1. 目的与适用范围
本文将“车辆管理”已落地的同步能力抽象为可复用模板,适用于后续任意业务模块(如供应商、订单、库存、质检等)快速实现:
- 桌面端 CRUD 与后端数据交互
- 正向同步(桌面端 -> 后端)
- 反向同步(后端 -> 桌面端)
- 断线续传(离线可操作,重连自动补偿)
- 本地缓存(保证离线可查、可改)
---
## 2. 总体架构模板
建议统一采用“**信号触发 + REST 拉取 + Outbox 补偿**”架构:
1. 后端业务变更后,广播 STOMP 信号(只发变更事件,不强依赖完整数据包)。
2. 桌面端接收信号后,不直接写本地业务表,而是触发“拉取接口”同步最新数据。
3. 桌面端本地操作时,在线优先调用后端;失败或离线则先写本地缓存 + 记录待同步操作Outbox
4. 网络恢复后自动回放 Outbox成功后清理队列并全量回拉一次做一致性对齐。
**核心原则**
- 在线追求实时,离线保证可用,重连追求最终一致。
- 任何“回传动作”必须幂等。
- 同步链路必须有完整日志(请求、结果、回放、失败原因)。
---
## 3. 后端接口模板(推荐样式)
以车辆管理为例,接口分两类:业务 CRUD 接口 + 同步辅助接口。
### 3.1 业务 CRUD给桌面端直接调用
建议统一路径风格(示例):
- `GET /{module}/{entity}/anon/list?pageNo=1&pageSize=10000&tenantId=1002`
- `GET /{module}/{entity}/anon/queryById?id=xxx&tenantId=1002`
- `POST /{module}/{entity}/anon/add?tenantId=1002`
- `POST /{module}/{entity}/anon/edit?tenantId=1002`
- `DELETE /{module}/{entity}/anon/delete?id=xxx&tenantId=1002`
- `POST /{module}/{entity}/anon/updateStatus?id=xxx&status=1&tenantId=1002`
返回建议统一:
```json
{
"success": true,
"code": 200,
"message": "操作成功",
"result": {}
}
```
分页 `result` 建议统一包含:
- `records`
- `total`
- `current`
- `size`
### 3.2 后端推送信号(反向同步触发)
后端每次成功增删改后,广播 STOMP
- Topic`/topic/sync/{entity-topic}`
- Payload 示例:
```json
{
"cmd": "MES_VEHICLE_CHANGED",
"action": "add|edit|delete|status",
"entityId": "xxx",
"timestamp": 1710000000000
}
```
说明:
- `cmd` 必须唯一且稳定,桌面端按它路由处理。
- `action` 用于日志和增量策略判断。
- `entityId` 可选但建议提供。
### 3.3 桌面端正向回传批量接口(可选增强)
若使用统一 Outbox 回传通道,建议后端提供:
- `POST /sys/sync/batch`
请求体示例:
```json
[
{
"messageId": "outbox-id-1",
"aggregateType": "VEHICLE",
"aggregateId": "vehicle-id",
"eventType": "CREATE|UPDATE|DELETE|TOGGLE_STATUS",
"payload": "{...}",
"occurredAt": "2026-01-01T10:00:00Z"
}
]
```
后端必须做 `messageId` 幂等去重。
---
## 4. 桌面端数据层模板
## 4.1 必备组件
每个模块建议固定四层:
1. `EntityService`(例:`VehicleService`
- CRUD 入口
- 本地缓存 + 离线队列
- 重连回放逻辑
2. `SyncCoordinator`(例:`VehicleSyncCoordinator`
- 监听 STOMP 信号
- 识别 `cmd` 并发布本地事件或触发同步
3. `OutboxProcessor`(全局复用)
- 持久化消息
- 在线实时发、离线补发
- 失败重试 + 指数退避
4. `NetworkMonitor`(全局复用)
- 网络状态检测
- 状态变化事件发布
## 4.2 本地缓存与待同步队列
推荐本地文件结构(示例):
- `%LocalAppData%/YY.Admin/sync-cache/{entity}-cache.json`
- `%LocalAppData%/YY.Admin/sync-cache/{entity}-pending-ops.json`
建议数据结构:
- `cache`: 最新本地快照(可直接查询)
- `pendingOps`: 离线期间操作日志,按时间顺序回放
`pendingOps` 字段建议:
- `id`
- `opType`Add/Edit/Delete/UpdateStatus
- `entityId`
- `payload`
- `createdAt`
---
## 5. 同步逻辑模板(标准流程)
### 5.1 查询流程Page/List
1. 在线:先拉远端数据 -> 刷新本地缓存。
2. 远端失败:回退本地缓存。
3.`pendingOps` 叠加到查询结果(保证 UI 看到“离线后的最新本地状态”)。
### 5.2 新增/编辑/删除/状态修改
1. 若在线,优先调用远端接口。
2. 远端成功:更新本地缓存。
3. 远端失败或离线:写入 `pendingOps`,并立即更新本地缓存(保证可用)。
**注意**:新增时若本地临时 ID`local-xxx`)不符合后端主键规则,回放前需清空 ID 让后端生成。
### 5.3 网络恢复(断线续传)
触发条件:`NetworkMonitor` 从离线 -> 在线。
流程:
1. 串行回放 `pendingOps`
2. 回放中任意失败立即停止,等待下次重试。
3. 回放完成后再做一次全量拉取,覆盖本地缓存。
4. 发布 UI 刷新事件(避免用户手动点查询)。
### 5.4 后端 -> 桌面反向同步
流程:
1. STOMP 收到 `cmd`
2. `SyncCoordinator` 解析命令。
3. 触发本地“拉取并刷新缓存”。
4. UI 订阅变更事件刷新列表。
---
## 6. 可复用方法模板
后续新模块可直接复用以下模式(名称替换即可):
- `FetchRemoteListAsync()`
- `RemoteAddAsync() / RemoteEditAsync() / RemoteDeleteAsync() / RemoteUpdateStatusAsync()`
- `ApplyFilters()`
- `ApplyPendingOpsSnapshotUnsafe()`
- `EnqueuePendingOperation()`
- `ReplayPendingOperationsAsync()`
- `ExecutePendingOperationAsync()`
- `LoadPendingOpsFromDisk() / SavePendingOpsToDiskUnsafe()`
- `LoadCacheFromDisk() / SaveCacheToDiskUnsafe()`
- `CloneEntity()`
建议抽一个通用基类(后续可做):
- `OfflineSyncEntityServiceBase<TEntity, TPendingOp>`
- 负责缓存、队列、回放、网络事件订阅
- 业务子类只实现远端接口和过滤逻辑
---
## 7. 日志模板(强制建议)
每个模块建议统一日志前缀,便于检索。
车辆管理示例前缀可复用为模块名替换:
- `[车辆同步]` 服务初始化
- `[车辆列表]` 查询链路
- `[车辆新增]` `[车辆修改]` `[车辆删除]` `[车辆状态]` 本地/远端操作
- `[车辆远端]` 实际 HTTP 请求与结果
- `[车辆入队]` 离线入队
- `[车辆回放]` 重连回放
- `[车辆重连]` 全量对齐
- `[车辆推送]` STOMP 信号处理
- `[车辆网络]` 网络状态变化
每条日志建议最少包含:
- 操作类型
- 业务主键
- 在线/离线状态
- 是否成功
- 失败原因(异常 message
- 队列长度(适用时)
---
## 8. 新模块落地清单(开发步骤)
按以下顺序复制模板最稳:
1. 后端先准备 `anon` CRUD 接口(或授权接口)+ 统一返回结构。
2. 后端在 CRUD 成功后广播 STOMP 变更信号。
3. 桌面端新增 `EntityService`(先把在线 CRUD 跑通)。
4. 增加本地缓存与 `pendingOps` 持久化。
5. 加入网络状态监听与重连回放。
6. 新增 `SyncCoordinator` 处理 STOMP -> 本地刷新。
7. 全链路日志补齐。
8. 按“联调测试矩阵”逐项验证。
---
## 9. 联调测试矩阵(建议)
每个模块至少跑完以下用例:
1. 在线新增 -> 后端可见。
2. 在线编辑 -> 后端可见。
3. 在线删除 -> 后端可见。
4. 在线状态切换 -> 后端可见。
5. 离线新增/编辑/删除 -> 本地立即可见。
6. 重连后自动回放 -> 后端最终一致。
7. 后端直接改数据 -> 桌面端自动刷新。
8. 异常网络抖动 -> 不崩溃,回放可恢复。
---
## 10. 车辆管理对应实现参考(当前项目)
桌面端:
- `YY.Admin.Services/Service/Vehicle/VehicleService.cs`
- `YY.Admin.Services/Service/Vehicle/VehicleSyncCoordinator.cs`
- `YY.Admin.Core/Core/Services/IVehicleService.cs`
后端:
- `jeecg-module-xslmes/.../MesXslVehicleController.java`(业务接口 + 变更推送)
- `jeecg-module-device-sync/.../SyncController.java`(如启用统一回传通道)
基础设施:
- `YY.Admin/Infrastructure/Sync/OutboxProcessor.cs`
- `YY.Admin/Infrastructure/Network/NetworkMonitor.cs`
- `YY.Admin/Infrastructure/Hubs/StompWebSocketService.cs`
---
## 11. 推荐统一规范(后续团队约定)
1. 所有新模块都按“在线优先 + 离线入队 + 重连回放 + 全量对齐”实现。
2. 所有模块都使用统一日志前缀和字段。
3. 后端变更推送统一 `cmd` 命名:`{SYSTEM}_{ENTITY}_CHANGED`
4. 回传消息统一带 `messageId` 幂等键。
5. 同步失败不阻塞主流程,但必须可观测(日志 + 队列长度)。
6. 任意新模块上线前必须跑完“联调测试矩阵”。
---
> 结论:
> 车辆管理已经提供了完整的可复制样板。后续新模块只需替换“实体、接口、过滤字段、命令字”,其余同步骨架可直接复用,从而快速实现稳定的桌面端/后端数据交互能力。