Files
iot-device-management-service/docs/plans/2026-03-23-work-order-v2-design.md
16337 08167378be 文档:工单引擎对接+H5详情页实施计划v2
基于IoT平台完整5接口(create/confirm/submit/false-alarm/auto-complete),
采用方案A严格模式(IoT回调后再更新告警+卡片)。
2026-03-23 11:41:45 +08:00

198 lines
7.1 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.

# 工单引擎对接 + H5 工单详情页 实施计划v2
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 打通 告警→IoT工单→企微卡片→保安处理→H5提交→IoT结单→告警状态同步 的完整闭环。
**Architecture:** vsp-service 作为企微通知网关IoT 平台作为工单状态权威源。告警触发后 vsp-service 调 IoT 创建工单IoT 派单后回调 vsp-service 发企微卡片。保安通过卡片按钮做简单操作(确认/误报),通过 H5 详情页做复杂操作(描述+图片)。所有状态变更走 IoT → 回调 vsp-service 同步告警+卡片。
**Tech Stack:** Python/FastAPI, Vue 3/Ant Design Vue, 企微 JS-SDK/OAuth2, work_order_client (SHA256签名)
---
## IoT 平台开放接口vsp-service 调用)
| 接口 | 路径 | 必填参数 | 可选参数 |
|------|------|---------|---------|
| 创建工单 | `POST /open-api/.../create` | title, areaId | description, priority, alarmId, alarmType, cameraId, roiId, imageUrl, sourceType |
| 确认工单 | `POST /open-api/.../confirm` | orderId | |
| 工单提交 | `POST /open-api/.../submit` | orderId, result | resultImgUrls |
| 误报标记 | `POST /open-api/.../false-alarm` | orderId | |
| 自动完单 | `POST /open-api/.../auto-complete` | orderId | remark |
## vsp-service 提供给 IoT 的接口
| 接口 | 入参 | 用途 |
|------|------|------|
| `POST /api/wechat/notify/send-card` | alarmId, orderId, userIds[], title, areaName, cameraName, eventTime, level, snapshotUrl | IoT 派单后调用,发企微工单卡片 |
| `POST /api/wechat/notify/sync-status` | alarmId, orderId, status(confirmed/completed/false_alarm/auto_resolved), operator, remark | IoT 状态变更后调用,同步告警+卡片 |
## 完整流程
```
边缘告警 → vsp-service VLM复核 → 调IoT /create拿到orderId
→ IoT自动派单 → IoT调 vsp-service /send-card → 发企微卡片
卡片按钮:[确认处理] [误报忽略] | 点击卡片整体 → H5详情页
点[确认处理]
→ vsp-service 调 IoT /confirm
→ IoT 回调 /sync-status(status=confirmed)
→ 更新告警CONFIRMED + 卡片重绘"已接单,请点击卡片提交处理结果"
点[误报忽略]
→ vsp-service 调 IoT /false-alarm
→ IoT 回调 /sync-status(status=false_alarm)
→ 更新告警FALSE + 卡片终态"已忽略"
H5提交处理结果
→ 上传图片到COS → 调 vsp-service → vsp-service 调 IoT /submit
→ IoT 回调 /sync-status(status=completed)
→ 更新告警CLOSED + 卡片终态"已处理"
边缘端告警自动解除:
→ vsp-service 调 IoT /auto-complete
→ IoT 回调 /sync-status(status=auto_resolved)
→ 更新告警 + 卡片终态"系统自动结单"
```
---
### Task 1: work_order_client 补充 3 个新方法
**Files:**
- Modify: `iot-device-management-service/app/services/work_order_client.py`
在现有 `create_order``auto_complete_order` 基础上,新增:
- `confirm_order(orderId)``POST /confirm`
- `submit_order(orderId, result, resultImgUrls=[])``POST /submit`
- `false_alarm(orderId)``POST /false-alarm`
签名逻辑复用现有的 `_sign``_build_headers`
---
### Task 2: work_order_client 初始化启用
**Files:**
- Modify: `iot-device-management-service/app/main.py`
取消 `work_order_client` 初始化的注释,从 `.env` 读取配置。
---
### Task 3: notify_dispatch 启用工单创建
**Files:**
- Modify: `iot-device-management-service/app/services/notify_dispatch.py`
VLM 复核通过后:
1.`wo_client.create_order()` 创建工单
2. 存 orderId 到 `alarm_event_ext`ext_type=WORK_ORDER
3. 企微通知正常发送(后续改为由 IoT 回调触发)
---
### Task 4: 新增 IoT 回调接口send-card + sync-status
**Files:**
- Create: `iot-device-management-service/app/routers/wechat_notify_api.py`
- Modify: `iot-device-management-service/app/main.py`(注册路由)
```
POST /api/wechat/notify/send-card
→ 接收 IoT 派单通知 → 发企微工单卡片给指定 userIds
POST /api/wechat/notify/sync-status
→ 接收 IoT 状态变更 → 更新告警状态 + 更新企微卡片
→ status 映射:
confirmed → 告警CONFIRMED + 卡片重绘"已接单,请点击卡片提交处理结果"
completed → 告警CLOSED + 卡片终态"已处理"
false_alarm → 告警FALSE + 卡片终态"已忽略"
auto_resolved → 告警CLOSED + 卡片终态"系统自动结单"
```
---
### Task 5: 卡片按钮回调改造(调 IoT 而非直接更新)
**Files:**
- Modify: `iot-device-management-service/app/routers/wechat_callback.py`
方案A严格模式
- 点[确认处理] → 调 IoT /confirm → 等 IoT 回调 sync-status 再更新
- 点[误报忽略] → 调 IoT /false-alarm → 等 IoT 回调 sync-status 再更新
卡片按钮简化为一步(去掉 step2 的第二轮按钮)。
---
### Task 6: 卡片样式调整 + card_action.url
**Files:**
- Modify: `iot-device-management-service/app/services/wechat_service.py`
1. `_alarm_detail_url` 改为 H5 工单页:`/work-order?alarmId={alarm_id}`
2. 卡片按钮只保留 [确认处理] [误报忽略]
3. 确认后卡片重绘提示:"已接单,请点击卡片提交处理结果"
4. 去掉 `update_alarm_card_step2` 中的第二轮交互按钮
---
### Task 7: 后端 — H5 工单处理 API
**Files:**
- Create: `iot-device-management-service/app/routers/work_order_api.py`
- Modify: `iot-device-management-service/app/main.py`(注册路由)
```
GET /api/work-order/detail?alarmId={alarmId}
→ 返回告警信息 + orderId + 工单状态 + 截图URL
POST /api/work-order/submit
Body: {alarmId, result, resultImgUrls?}
→ 查 orderId → 调 IoT /submit → 等 IoT 回调同步状态
POST /api/work-order/upload-image
Body: multipart/form-data
→ 上传到 COS → 返回永久 URL
```
---
### Task 8: 前端 — H5 工单详情页
**Files:**
- Create: `iot-device-management-frontend/apps/web-antd/src/views/work-order/index.vue`
页面逻辑:
1. 从 URL 参数获取 alarmId
2.`/api/work-order/detail` 获取信息
3. 根据状态展示:
- 待处理/处理中:告警截图 + 处理表单(文字输入+拍照+提交)
- 已完成:告警截图 + 处理后照片 + 描述(只读)
- 误报:显示"已标记误报"
拍照使用 `<input type="file" accept="image/*" capture="environment">`
---
### Task 9: 前端 — 路由配置
**Files:**
- 添加 `/work-order` 路由,使用空布局(无侧边栏无顶栏)
- 不需要登录(通过企微 OAuth2 或 alarmId 鉴权)
---
## 验证清单
- [ ] 边缘告警 → VLM复核 → IoT工单创建成功
- [ ] IoT 回调 send-card → 企微卡片正确发送
- [ ] 点[确认处理] → 调IoT confirm → 回调更新告警+卡片
- [ ] 点[误报忽略] → 调IoT false-alarm → 回调更新告警+卡片终态
- [ ] H5 详情页展示告警信息和工单状态
- [ ] H5 提交描述+图片 → 调IoT submit → 回调更新告警+卡片终态
- [ ] 边缘端告警解除 → 调IoT auto-complete → 回调更新告警+卡片终态
- [ ] 所有配置通过 .env 控制,无硬编码密钥