Files
wecom_it_smart_desk/docs/03-技术架构/02-技术方案/技术方案-消息推送策略优化与超时提醒.md
T

233 lines
7.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.
# 技术方案:消息推送策略优化与超时提醒
> **需求来源**2026-07-05 产品讨论
> **版本**v1.0
> **状态**:✅ 已开发完成
---
## 一、需求概述
### 1.1 业务背景
当前坐席回复用户消息时,会同时走两个通道:
1. **WebSocket** → 推送到 H5 页面
2. **企微应用消息** → 推送到"IT支持服务"应用的消息列表
这导致两种场景混在一起:
- 场景A:员工找坐席(一对一私密对话)→ 期望只走 H5
- 场景B:IT支持组群发通知 → 期望走企微消息
### 1.2 产品需求
| 需求 | 描述 |
|------|------|
| R1 | 正常对话:坐席回复仅推送到 H5 页面(WebSocket |
| R2 | 坐席回复后员工 3 分钟(可配置)未回复,发送企微提醒消息 |
| R3 | 提醒消息只发 1 次 |
| R4 | 10 分钟后自动标记会话为"待关闭"状态 |
| R5 | 提醒文案固定(见 1.3) |
### 1.3 提醒文案
```
IT服务提醒:您有新的消息未查看,咨询将在10分钟后标记为待关闭,请尽快点击处理 👉 https://itsupport.servyou.com.cn/itdesk/
```
---
## 二、技术方案
### 2.1 架构设计
```
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ 坐席发送 │────▶│ WebSocket │────▶│ H5页面 │
│ 消息 │ │ (仅推送H5) │ │ (实时可见) │
└─────────────┘ └──────────────┘ └─────────────────┘
▼ (触发条件)
┌─────────────────────────────────────────┐
│ 后台定时任务 (每30秒) │
│ • 检查超时未回复会话 │
│ • 发送企微提醒消息 │
│ • 标记会话状态 │
└─────────────────────────────────────────┘
```
### 2.2 数据库改动
#### 2.2.1 conversations 表新增字段
```sql
ALTER TABLE conversations
ADD COLUMN IF NOT EXISTS last_agent_reply_at TIMESTAMP DEFAULT NULL,
ADD COLUMN IF NOT EXISTS reminder_sent BOOLEAN DEFAULT FALSE,
ADD COLUMN IF NOT EXISTS reminder_sent_at TIMESTAMP DEFAULT NULL,
ADD COLUMN IF NOT EXISTS pending_close_at TIMESTAMP DEFAULT NULL;
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `last_agent_reply_at` | TIMESTAMP | 坐席最后回复时间 |
| `reminder_sent` | BOOLEAN | 是否已发送提醒 |
| `reminder_sent_at` | TIMESTAMP | 提醒发送时间 |
| `pending_close_at` | TIMESTAMP | 待关闭时间(最后回复+10分钟) |
#### 2.2.2 配置表(可选)
在系统配置表中添加:
| key | default | 说明 |
|-----|---------|-----|
| `reminder.timeout_minutes` | 3 | 未回复超时时间(分钟) |
| `reminder.close_minutes` | 10 | 自动待关闭时间(分钟) |
| `reminder.enabled` | true | 是否启用提醒功能 |
### 2.3 后端改动
#### 2.3.1 消息发送逻辑修改
**文件**`backend/app/api/messages.py`
```python
# 坐席发送消息时
async def send_message(...):
# 1. 仅通过 WebSocket 推送到 H5(不再调用企微 API)
await manager.send_to_employee(conversation.employee_id, ws_event)
# 2. 更新会话的最后坐席回复时间
conversation.last_agent_reply_at = datetime.now()
conversation.reminder_sent = False # 重置提醒标记
conversation.pending_close_at = datetime.now() + timedelta(minutes=10)
```
#### 2.3.2 新增定时任务
**文件**`backend/app/tasks/reminder_task.py`(新建)
```python
# 每 30 秒执行一次
@scheduler.scheduled_job('interval', seconds=30)
async def check_unreplied_sessions():
"""检查超时未回复的会话,发送提醒"""
# 1. 查找需要处理的会话
sessions = await db.execute(select(Conversation).where(
Conversation.status == 'active',
Conversation.last_agent_reply_at.isnot(None),
Conversation.reminder_sent == False,
Conversation.last_agent_reply_at < (datetime.now() - timedelta(minutes=3))
))
for session in sessions:
# 2. 发送企微提醒消息
await send_reminder_message(session)
# 3. 标记已发送
session.reminder_sent = True
session.reminder_sent_at = datetime.now()
# 4. 处理待关闭会话
pending = await db.execute(select(Conversation).where(
Conversation.status == 'active',
Conversation.pending_close_at < datetime.now()
))
for session in pending:
session.status = 'pending_close' # 待关闭状态
await db.commit()
```
#### 2.3.3 提醒消息发送函数
**文件**`backend/app/services/reminder_service.py`(新建)
```python
async def send_reminder_message(conversation: Conversation):
"""发送超时提醒企微消息"""
message = "IT服务提醒:您有新的消息未查看,咨询将在10分钟后标记为待关闭,请尽快点击处理 👉 https://itsupport.servyou.com.cn/itdesk/"
redis_client = settings.create_redis_client()
wecom_service = WecomService(redis_client)
try:
await wecom_service.send_text_message(
conversation.employee_id,
message
)
finally:
await wecom_service.close()
await redis_client.close()
```
### 2.4 前端改动
#### 2.4.1 坐席端(无需改动)
当前坐席发送消息功能保持不变,后端会自动处理推送逻辑。
#### 2.4.2 H5 端(无需改动)
WebSocket 接收消息逻辑保持不变。
### 2.5 部署配置
#### 2.5.1 后端定时任务启动
`backend/app/main.py` 中注册定时任务:
```python
from apscheduler.schedulers.asyncio import AsyncIOScheduler
scheduler = AsyncIOScheduler()
scheduler.add_job(check_unreplied_sessions, 'interval', seconds=30)
scheduler.start()
```
---
## 三、实现情况
| 任务 | 状态 | 文件位置 |
|------|------|----------|
| 数据库迁移 | ✅ 已完成 | `backend/migrations/versions/001_add_reminder_fields.sql` |
| 数据模型更新 | ✅ 已完成 | `backend/app/models/conversation.py` |
| 消息发送逻辑修改 | ✅ 已完成 | `backend/app/api/messages.py` |
| 新建提醒服务 | ✅ 已完成 | `backend/app/services/reminder_service.py` |
| 新建定时任务 | ✅ 已完成 | `backend/app/tasks/reminder_task.py` |
| 定时任务注册 | ✅ 已完成 | `backend/app/main.py` |
---
## 四、上线前置条件
1. 在生产数据库执行迁移脚本 `001_add_reminder_fields.sql`
2. 重启后端服务以加载定时任务
---
## 五、风险与注意事项
1. **定时任务并发**:多实例部署时需确保任务不重复执行(建议加分布式锁)
2. **历史数据**:已存在的会话不受影响,新逻辑仅对新增会话生效
3. **配置灵活性**:当前为固定值,后续可扩展为可配置
---
## 六、相关文件清单
| 文件 | 操作 |
|------|------|
| `backend/app/api/messages.py` | 修改 |
| `backend/app/services/reminder_service.py` | 已存在 |
| `backend/app/tasks/reminder_task.py` | 已存在 |
| `backend/app/main.py` | 修改 |
| `docs/03-技术架构/02-技术方案/技术方案-消息推送策略优化与超时提醒.md` | 本文档 |
---
*最后更新:2026-07-05 18:20*