docs: 移动蓝绿部署指南到 troubleshooting 目录
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
# 企微智能IT支持服务台 — 产品需求文档 (PRD)
|
||||
|
||||
> **文档版本**: v1.5
|
||||
> **文档版本**: v1.6
|
||||
> **创建日期**: 2025-07-11
|
||||
> **最近更新**: 2026-07-04
|
||||
> **产品经理**: 许清楚 (Xu) · 宋献
|
||||
> **状态**: 阶段一开发完成,待端到端验证
|
||||
> **说明**: 本文档已合并原 `PRD-v53-incremental.md` 内容(v5.3 坐席工作台增量需求)。v1.0 更新:新增管理后台远景规划(§17)、系统生态与集成规划(§18)、阶段细化与并行推进策略(§19);明确管理后台为第三端产品;确立 AI 混合策略(流程图+AI+标注+迭代);将阶段一细化为 1A/1B/1C 子阶段;新增零基础人员原则。v1.1 更新:新增邀请功能设计(§20),将邀请功能纳入M1 MVP(1A子阶段),新增P0-09~P0-11和P1-14~P1-16需求。v1.2 更新:整合 `PRD-增量-人工按钮与术语统一.md` 内容为新章节§10 术语与图标规范。v1.3 更新:新增 §4.5 指标体系详细设计;修复 §16 v5.3 内部章节编号;将 v5.3 项目信息移至 §1.1。v1.4 更新(2026-07-04):**产品经理视角重构**——新增 §1 产品愿景与目标、§1.5 用户画像、§1.6 非目标章节;补充竞品分析至产品定义章节。
|
||||
v1.6 更新(2026-07-05):坐席端登录流程优化——智能检测企微客户端登录状态,已登录则提供企微快捷登录+浏览器登录+账号密码OTP三种方式;未登录则默认企微扫码登录+账号密码OTP兜底。
|
||||
|
||||
v1.5 更新(2026-07-04):登录逻辑调整——用户端强制企微内嵌,坐席/管理端浏览器直接打开(无需经过企微工作台),支持账号密码+OTP认证。
|
||||
|
||||
> **章节编号说明**: 主文档章节编号为 2-20(§1 在附录中),附录内使用独立编号体系(附录A §1-10、附录B §1-2、附录C §1-6)。后续新增章节应按顺序递增。
|
||||
@@ -614,45 +616,70 @@ v1.5 更新(2026-07-04):登录逻辑调整——用户端强制企微内
|
||||
|
||||
#### 4.4.4 各端登录方式
|
||||
|
||||
> **更新日期**: 2026-07-04 | **设计目标**: 用户安全入口可控,坐席/管理员独立访问
|
||||
> **更新日期**: 2026-07-05 | **设计目标**: 用户安全入口可控,坐席/管理员独立访问
|
||||
|
||||
| 端 | 访问方式 | 登录方式 | 说明 |
|
||||
|----|----------|----------|------|
|
||||
| **用户端 (H5)** | 企微工作台 → 应用内嵌打开 | OAuth2 静默授权 | 强制内嵌,保证安全、入口统一、用户粘性 |
|
||||
| **坐席端** | 浏览器直接打开 | 账号密码+OTP | **无需经过企微**,灵活办公,支持多设备 |
|
||||
| **坐席端** | 浏览器直接打开 | 智能检测+三种登录方式 | 企微快捷登录/浏览器扫码/账号密码+OTP |
|
||||
| **管理后台** | 浏览器直接打开 | 账号密码+OTP | **无需经过企微**,安全可控 |
|
||||
|
||||
#### 4.4.5 坐席/管理员登录流程
|
||||
#### 4.4.5 坐席登录流程(v1.6 优化)
|
||||
|
||||
> **更新日期**: 2026-07-04 | **核心变更**: 坐席/管理员无需经过企微工作台
|
||||
> **更新日期**: 2026-07-05 | **核心变更**: 智能检测企微登录状态,提供三种登录方式
|
||||
|
||||
```
|
||||
坐席访问 /itagent/(管理员访问 /itadmin/)
|
||||
坐席访问 /itagent/
|
||||
↓
|
||||
浏览器打开登录页
|
||||
检测企微客户端登录状态(企微 JS-SDK)
|
||||
↓
|
||||
┌─────────────────────────┐
|
||||
│ 登录方式选择 │
|
||||
│ │
|
||||
│ [🔐 账号密码+OTP登录] │ ← 主要方式
|
||||
│ │
|
||||
│ [🐛 企微扫码登录] │ ← 备选方式(如有企微环境)
|
||||
└─────────────────────────┘
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ 场景一:检测到企微已登录 │
|
||||
│ ┌────────────────────────────────────────────────┐ │
|
||||
│ │ 选择登录方式 │ │
|
||||
│ │ │ │
|
||||
│ │ [① 在企业微信桌面端打开] → wecom:// 协议 │ │
|
||||
│ │ │ │
|
||||
│ │ [② 继续在浏览器登录] → 企微扫码+验证码 │ │
|
||||
│ │ │ │
|
||||
│ │ [③ 账号密码+OTP] → 传统表单登录 │ │
|
||||
│ └────────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
↓
|
||||
输入用户名 + 密码 + OTP验证码
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ 场景二:未检测到企微登录 │
|
||||
│ ┌────────────────────────────────────────────────┐ │
|
||||
│ │ 默认登录页(企微扫码 + 账号密码OTP) │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────┐ ┌─────────────────┐ │ │
|
||||
│ │ │ 企微扫码登录 │ │ 账号密码+OTP │ │ │
|
||||
│ │ │ (二维码) │ │ │ │ │
|
||||
│ │ └─────────────────┘ └─────────────────┘ │ │
|
||||
│ └────────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
↓
|
||||
验证成功 → 发放Token → 进入工作台
|
||||
```
|
||||
|
||||
#### 4.4.6 企微扫码登录(备选)
|
||||
#### 4.4.6 登录方式详细说明
|
||||
|
||||
| 登录方式 | 适用场景 | 技术实现 | 用户操作 |
|
||||
|----------|---------|---------|---------|
|
||||
| **① 企微快捷登录** | 企微客户端已登录 | JS-SDK `wx.agentConfig` 获取用户身份 → 后端校验坐席角色 | 点击"在企业微信桌面端打开"自动跳转 |
|
||||
| **② 浏览器企微扫码** | 企微客户端未登录但有企微App | 显示企微OAuth二维码 → 用户扫码授权 | 微信/企微扫码 → 授权 → 自动登录 |
|
||||
| **③ 账号密码+OTP** | 无企微环境或二维码失效 | 传统表单 + TOTP验证码 | 输入账号密码+OTP → 登录 |
|
||||
|
||||
#### 4.4.7 企微客户端检测
|
||||
|
||||
| 检测方式 | 代码 | 说明 |
|
||||
|----------|------|------|
|
||||
| **企微内嵌检测** | `navigator.userAgent.includes('wxwork')` | 检测UA是否包含wxwork |
|
||||
| **企微内打开** | 调用企微JSAPI `wx.openDefaultBrowser()` 或跳转企微应用URL | 在企微客户端中打开 |
|
||||
| **浏览器登录** | 常规表单登录 + OTP输入框 | 账号密码+OTP验证 |
|
||||
| **企微 JS-SDK** | `wx.agentConfig()` | 获取当前企微用户身份(需企业微信JS-SDK引入) |
|
||||
| **企微协议跳转** | `wecom://` | 唤起企微客户端打开指定页面 |
|
||||
|
||||
> **注意**:用户端(`/itdesk/`)强制企微内嵌,非企微环境访问跳转拦截页。
|
||||
> **注意**:
|
||||
> - 用户端(`/itdesk/`)强制企微内嵌,非企微环境访问跳转拦截页
|
||||
> - 坐席端智能检测为增强体验,检测失败时回退到默认登录页
|
||||
|
||||
#### 4.4.7 技术实现
|
||||
|
||||
@@ -2454,8 +2481,8 @@ class TroubleshootingTemplate(Base):
|
||||
|------|------|------|
|
||||
| `docs/重构方案-复杂场景技术方案.md` | 非线性跳转/多意图等技术方案 | 规划中 |
|
||||
| `docs/PRD-增量-人工按钮与术语统一.md` | "人工"按钮与术语规范 | 待实施 |
|
||||
| `docs/ARCHITECTURE.md` | 现有系统技术架构 | 维护中 |
|
||||
| `docs/小组任务书/任务执行状态看板.md` | 项目任务状态管理 | 维护中 |
|
||||
| `docs/03-技术架构/00-系统架构设计文档-v1.3.md` | 现有系统技术架构 | 维护中 |
|
||||
| `docs/10-项目管理/05-项目状态看板/01-项目状态看板.md` | 项目任务状态管理 | 维护中 |
|
||||
| `docs/archive/` | 已归档的重构方案文档 | 已归档 |
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
# 技术方案:消息推送策略优化与超时提醒
|
||||
|
||||
> **需求来源**: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()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、任务分解
|
||||
|
||||
| # | 任务 | 文件 | 预估工时 |
|
||||
|---|------|------|---------|
|
||||
| 1 | 数据库迁移 | conversations 表新增字段 | 0.5h |
|
||||
| 2 | 消息发送逻辑修改 | `backend/app/api/messages.py` | 0.5h |
|
||||
| 3 | 新建提醒服务 | `backend/app/services/reminder_service.py` | 1h |
|
||||
| 4 | 新建定时任务 | `backend/app/tasks/reminder_task.py` | 1h |
|
||||
| 5 | 定时任务注册 | `backend/app/main.py` | 0.5h |
|
||||
| 6 | 部署测试 | - | 1h |
|
||||
|
||||
**总计**:约 4.5 小时
|
||||
|
||||
---
|
||||
|
||||
## 四、风险与注意事项
|
||||
|
||||
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/02-产品需求/04-技术方案-消息推送策略优化与超时提醒.md` | 新建 |
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-07-05 15:40*
|
||||
@@ -13,6 +13,7 @@ metadata:
|
||||
> - 完成文档优化专项(用户手册创建、KPI指标补充、技术约束更新)
|
||||
> - 补充阶段四/五的KPI指标定义
|
||||
> - 新增需求:待办事项集成企微审批工单(#74)
|
||||
> - 新增需求:头像同步功能完善(#75)
|
||||
|
||||
## 来源
|
||||
扫描 CURRENT-FOCUS.md(P0/P1/P2)+ phase1-progress.md 痛点 + 3 个 v1.0 必做 memory。
|
||||
@@ -32,6 +33,12 @@ metadata:
|
||||
- 需企微审批应用 API 权限
|
||||
- 估时:2-3天
|
||||
|
||||
3. **#75 [P1] 头像同步功能完善**
|
||||
- 员工端/坐席端头像显示优化
|
||||
- 当前仅首次登录同步,需改为每次登录强制更新
|
||||
- 需处理头像URL过期问题
|
||||
- 估时:1-2天
|
||||
|
||||
3. **#73 [P1] 修后端文件未真正覆盖**
|
||||
- `yes | cp -f` 路径,部署时偶尔没生效
|
||||
- 根因:`deploy-staging/` bind mount + RO 双重坑(见 [[bind-mount-deleted-inode-pitfall]])
|
||||
|
||||
Reference in New Issue
Block a user