Files
wecom_it_smart_desk/docs/PRD-增量-人工按钮与术语统一.md
T

338 lines
13 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.
# PRD-增量-人工按钮与术语统一
> **文档版本**: v1.0
> **创建日期**: 2026-06-11
> **产品经理**: 许清楚 (Xu) · 宋献
> **状态**: 待评审
> **对应任务**: 人工按钮需求定义 + 术语/图标统一规范
---
## 摘要
本文档包含两个增量需求:
1. **"人工"按钮需求文档** — 定义H5用户端呼叫坐席按钮的完整产品规范
2. **术语/图标统一规范** — 全局统一"人工"与"摇人"概念,取消"举手"概念
---
## 一、"人工"按钮需求文档
### 1.1 需求背景
当前H5用户端存在以下问题:
- 按钮文案不统一:代码中为"呼叫",产品语言中应为"人工"
- 按钮图标使用了摇铃铛 🔔(手摇铃),与产品定义不符
- 按钮启用条件未明确定义
- 坐席端对应状态图标未同步
### 1.2 产品定义
**"人工"** = 用户(员工)主动呼叫IT坐席,请求人工服务。
| 属性 | 定义 |
|------|------|
| 触发者 | H5用户端员工 |
| 接收者 | IT坐席(主责坐席或系统分配坐席) |
| 图标 | 传菜铃(桌面拍铃)—— 前台/厨房放在桌面、拍一下发出"叮"声的圆形金属铃铛 |
| 区别于 | "摇人" = 坐席呼叫其他坐席(详见第二节) |
> **图标说明:传菜铃 vs 摇铃**
>
> - ✅ **传菜铃**(正确):圆形金属铃铛,放在桌面上,从上方拍打铃面发出"叮"声。代表"我已提出问题,请人工来看一下"。
> - ❌ **摇铃** 🔔(错误):有把手的手摇铃,摇动发出声响。当前代码中使用的是此图标,需替换。
> - 传菜铃的SVG/Unicode表示:无直接对应的Unicode字符,建议使用自定义SVG图标(圆形底座+金属铃面)
### 1.3 按钮设计
#### 1.3.1 H5用户端按钮
**位置**:H5聊天界面标题栏右侧(当前"呼叫"按钮位置)
**形态**
```
┌────────────────────────────────────┐
│ IT智能服务台 [🔔 人工] │ ← 启用状态(橙色)
│ [▓▓ 人工] │ ← 禁用状态(灰色)
└────────────────────────────────────┘
```
**文案**`人工`(按钮文字)
**图标规范**
- 启用状态:传菜铃SVG图标 + 橙色系配色 `#FF9800`
- 禁用状态:传菜铃SVG图标 + 灰色 `#9E9E9E`,按钮整体 `opacity: 0.5; cursor: not-allowed`
- 图标尺寸:16×16px(标题栏)、24×24px(弹窗内)
**传菜铃SVG参考**
```svg
<!-- 传菜铃(桌面拍铃)SVG示意 -->
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<!-- 铃身(圆形,从上方拍打) -->
<circle cx="12" cy="14" r="7" fill="#FFD54F" stroke="#FFA000" stroke-width="1.5"/>
<!-- 铃底金属边框 -->
<ellipse cx="12" cy="20" rx="5" ry="1.5" fill="#FFA000"/>
<!-- 拍铃动画指示(从上方向下拍) -->
<line x1="12" y1="4" x2="12" y2="7" stroke="#FF9800" stroke-width="2" stroke-linecap="round"/>
<circle cx="12" cy="3" r="2" fill="#FF9800"/>
</svg>
```
#### 1.3.2 启用条件
按钮在以下任一条件满足时**启用**(橙色,可点击):
| # | 条件 | 说明 |
|---|------|------|
| 1 | **问题已确定** | AI已识别问题类型(`problem_confirmed = true`),用户可能需要人工进一步处理 |
| 2 | **会话交互达3次** | 用户与AI的对话轮次 ≥ 3(不含:直接呼叫人工的消息、问候语如"你好""hi" |
**禁用状态**(灰色,不可点击):
- 以上条件均未满足时
- 显示 `title="请先描述您的问题,AI将为您匹配最佳坐席"`
**计数规则**
```
计入交互轮次:
✅ 用户发送有效问题消息
✅ AI回复消息
❌ 用户发送"你好"、"hi"等纯问候语(不计入)
❌ 用户直接点击呼叫(不计入,但触发呼叫流程)
❌ 系统消息(不计入)
```
#### 1.3.3 点击流程
```
用户点击"人工"按钮
CallAgentModal 弹窗
├── 显示传菜铃动画(替换当前的摇铃铛动画)
├── 话术:"叮!IT坐席马上来~"
└── 同时发送 shake/fetch 请求到后端
成功 → 显示"已通知坐席,请稍候"
失败 → 提示"当前坐席繁忙,请稍后再试"
```
#### 1.3.4 坐席端联动
坐席端(Agent工作台)对应位置的按钮/状态指示也使用**传菜铃**图标:
| 位置 | 当前状态 | 目标状态 |
|------|---------|---------|
| 会话列表 - 标签 | "举手"黄色标签 | "人工"橙色标签 + 传菜铃图标 |
| 会话列表 - 排序权重 | `hand_raise` 标记 | `human_requested` 标记 |
| 聊天区 - 系统消息 | "员工摇人请求人工" | "员工请求人工服务🔔" |
#### 1.3.5 坐席离线状态
当无坐席在线时:
- H5标题栏坐席状态显示:**灰色圆点 + "坐席离线"**
- "人工"按钮:保持可见但**禁用**(灰色),`title="当前无在线坐席,请稍后再试或继续与AI对话"`
- 不隐藏按钮(保持用户认知一致性)
---
## 二、术语/图标统一规范
### 2.1 核心概念定义
| 术语 | 定义 | 触发者 | 接收者 | 图标 | 使用范围 |
|------|------|--------|--------|------|----------|
| **人工** | 用户呼叫坐席,请求人工服务 | H5用户端员工 | IT坐席 | 传菜铃(桌面拍铃)SVG | 用户端H5 + 坐席端(状态指示) |
| **摇人** | 主责坐席呼叫其他坐席进入群聊协助 | IT坐席 | 其他IT坐席 | 👋 招手 | 仅坐席端 |
| ~~**举手**~~ | <span style="color:red">**已取消**</span> | — | — | — | 全局移除 |
### 2.2 "人工"详细规范
**含义**:用户(员工)需要人工坐席介入处理问题。
**触发方式**
1. 用户点击H5标题栏"🔔 人工"按钮
2. 用户输入关键词("转人工"、"人工"、"人工服务"等)—— 关键词触发仍有效
**后端标记字段**(重构方向):
```python
# backend/app/schemas/conversation.py
class ConversationTags(BaseModel):
# 移除: hand_raise: bool = False
# 新增:
human_requested: bool = Field(default=False, description="用户请求人工服务")
human_requested_at: datetime | None = Field(default=None, description="用户请求人工的时间")
```
**前端显示**
- H5端:标题栏按钮"🔔 人工"
- 坐席端会话列表:橙色"人工"标签 + 传菜铃图标
### 2.3 "摇人"详细规范
**含义**:主责坐席在处理会话时,邀请其他坐席进入当前会话协助。
**触发方式**
- 坐席点击聊天区"🤝 摇人"按钮 → 弹出 InviteDialog.vue
**与"人工"的区别**
| 维度 | 人工 | 摇人 |
|------|------|------|
| 触发者 | 用户(员工) | 主责坐席 |
| 接收者 | IT坐席 | 其他IT坐席 |
| 目的 | 请求人工服务 | 协作处理复杂问题 |
| 图标 | 传菜铃 SVG | 👋 招手 |
| 对应代码 | `human_requested` | `collaborating_agent_ids` |
**InviteDialog.vue 改动**
- 标题改为:`🤝 摇人 — 邀请坐席协作`(当前为"🤝 摇人 — 邀请坐席协作",已正确)
- 确保图标使用 👋 而非传菜铃
### 2.4 全局取消"举手"概念
**涉及范围**
| 类别 | 涉及文件/位置 | 改动说明 |
|------|-------------|---------|
| **代码变量名** | `hand_raise`, `hand_raise_keywords`, `detect_hand_raise()` | 标记为 `@deprecated`,下个迭代重构为 `human_requested`, `human_request_keywords`, `detect_human_request()` |
| **数据库字段** | `tags` JSON中的 `hand_raise: true` | 保持兼容,新增 `human_requested: true`,逐步迁移 |
| **API响应** | `ConversationResponse.tags.hand_raise` | 新增 `ConversationResponse.tags.human_requested`,旧字段保留一个迭代周期 |
| **前端状态** | `store.tags.hand_raise` | 改为 `store.tags.human_requested` |
| **UI文案** | "举手标签"、"举手标记" | 改为"人工标签"、"人工请求标记" |
| **文档** | PRD.md、ARCHITECTURE.md 等 | 全局替换"举手"为"人工(用户呼叫)" |
| **测试用例** | `test_scoring_service.py``test_h5_shake.py` | 变量名重构时同步更新 |
**兼容策略**(避免一次性破坏):
```
阶段1(本迭代):
- 新增 human_requested 字段
- 旧 hand_raise 字段保留,标记为 @deprecated
- UI全局切换为"人工"
- 后端同时写入 hand_raise 和 human_requested(兼容旧逻辑)
阶段2(下个迭代):
- 重构变量名:hand_raise → human_requested
- 移除 hand_raise 写入逻辑
- 数据库迁移:将 tags 中的 hand_raise 合并到 human_requested
```
### 2.5 图标汇总表
| 场景 | 图标 | 说明 |
|------|------|------|
| H5用户端 - "人工"按钮 | 传菜铃 SVG | 橙色,启用状态 |
| H5用户端 - "人工"按钮(禁用) | 传菜铃 SVG | 灰色,`opacity: 0.5` |
| 坐席端 - 会话列表"人工"标签 | 传菜铃 SVG + "人工"文字 | 橙色标签 |
| 坐席端 - "摇人"按钮 | 👋 | 招手emoji |
| 坐席端 - InviteDialog 标题 | 🤝 + 👋 | "摇人 — 邀请坐席协作" |
| 坐席离线状态 | ⚪ 灰色圆点 | CSS: `background-color: #9E9E9E` |
---
## 三、改动清单
### 3.1 前端改动
| 文件 | 改动类型 | 说明 |
|------|---------|------|
| `frontend-h5/src/components/chat/ChatPanel.vue` | 修改 | 按钮文案"呼叫"→"人工",图标🔔→传菜铃SVG,启用条件逻辑 |
| `frontend-h5/src/components/chat/CallAgentModal.vue` | 修改 | 弹窗标题"摇铃呼叫人工坐席"→"呼叫人工坐席",动画场景图标更新 |
| `frontend-h5/src/stores/conversation.ts` | 修改 | `canCallAgent` 逻辑(问题确定或交互≥3轮) |
| `frontend-agent/src/components/conversation/ConversationItem.vue` | 修改 | "举手"标签→"人工"标签+传菜铃图标 |
| `frontend-agent/src/stores/conversation.ts` | 修改 | 排序逻辑中 `hand_raise``human_requested` |
| `frontend-agent/src/components/conversation/InviteDialog.vue` | 修改 | 确认图标/文案为"摇人"=👋 |
### 3.2 后端改动
| 文件 | 改动类型 | 说明 |
|------|---------|------|
| `backend/app/schemas/conversation.py` | 修改 | 新增 `human_requested` 字段,标记 `hand_raise``@deprecated` |
| `backend/app/services/scoring_service.py` | 修改 | `detect_hand_raise()``detect_human_request()`,关键词配置 key 不变(兼容) |
| `backend/app/services/message_router.py` | 修改 | 标记检测:设置 `human_requested = True` |
| `backend/app/api/h5.py` | 修改 | shake 端点响应文案更新 |
| `backend/app/models/conversation.py` | 修改 | `tags` 字段兼容 `human_requested` |
### 3.3 文档改动
| 文件 | 改动类型 | 说明 |
|------|---------|------|
| `docs/PRD.md` | 修改 | 全局"举手"→"人工(用户呼叫)",更新术语表 |
| `docs/ARCHITECTURE.md` | 修改 | 更新排序规则描述,替换"举手"相关描述 |
| `docs/01-项目总览与部署手册.md` | 修改 | 替换"举手"标签说明 |
| `docs/团队沟通文档-架构消息知识库.md` | 修改 | 更新标记体系说明 |
---
## 四、验收标准
### 4.1 "人工"按钮
| # | 验收标准 | 验证方式 |
|---|---------|---------|
| 1 | H5标题栏显示"🔔 人工"按钮(传菜铃图标) | 视觉验收 |
| 2 | 问题未确定且交互<3轮时,按钮为灰色禁用状态 | 功能测试 |
| 3 | 问题确定或交互≥3轮时,按钮为橙色启用状态 | 功能测试 |
| 4 | 点击按钮弹出CallAgentModal,动画使用传菜铃场景 | 视觉+功能测试 |
| 5 | 坐席离线时,按钮禁用,title提示"当前无在线坐席" | 功能测试 |
| 6 | 坐席端会话列表显示"人工"标签+传菜铃图标 | 视觉验收 |
### 4.2 术语统一
| # | 验收标准 | 验证方式 |
|---|---------|---------|
| 1 | 所有UI、代码注释中无"举手"一词(待重构变量除外,需标记@deprecated | 全文搜索 |
| 2 | "人工"概念在用户端和坐席端统一 | 功能测试 |
| 3 | "摇人"概念仅在坐席端出现,图标为👋 | 视觉验收 |
| 4 | 后端同时写入 `hand_raise`(兼容)和 `human_requested`(新) | 单元测试 |
---
## 五、开发优先级
| 优先级 | 内容 | 预计工时 |
|--------|------|---------|
| P0 | H5"人工"按钮UI改动(文案+图标+启用条件) | 0.5天 |
| P0 | 坐席端"人工"标签显示 | 0.5天 |
| P1 | CallAgentModal动画更新(传菜铃) | 0.5天 |
| P1 | 后端新增 `human_requested` 字段 | 0.5天 |
| P2 | 文档全局更新(PRD/ARCHITECTURE等) | 0.5天 |
| P3 | 代码变量名重构(`hand_raise``human_requested` | 1天(下个迭代) |
---
## 附录 A:传菜铃图标注说明
由于Unicode中无直接对应的传菜铃字符,使用自定义SVG图标。
**推荐SVG(简洁版)**
```svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
<!-- 铃身 -->
<circle cx="12" cy="14" r="7" fill="#FFD54F" stroke="#FFA000" stroke-width="1.5"/>
<!-- 金属高光 -->
<ellipse cx="10" cy="12" rx="2.5" ry="1.5" fill="#FFF9C4" opacity="0.6"/>
<!-- 铃底 -->
<ellipse cx="12" cy="20" rx="5" ry="1.5" fill="#FFA000"/>
<!-- 拍击指示(小圆点代表"拍"的动作) -->
<circle cx="12" cy="5" r="1.8" fill="#FF9800"/>
<line x1="12" y1="5" x2="12" y2="8" stroke="#FF9800" stroke-width="1.5"/>
</svg>
```
**启用/禁用状态CSS**
```css
.bell-counter-icon { filter: none; }
.bell-counter-icon--disabled { filter: grayscale(100%); opacity: 0.5; }
```