Pro/openspec/archive/customer-service-module/tasks.md

444 lines
10 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.

# OPSX Tasks: 在线客服模块实施计划
## 变更标识
- **变更ID**: customer-service-module
- **版本**: 2.0
- **状态**: ARCHIVED
- **更新日期**: 2026-01-29
- **完成日期**: 2026-01-29
---
## 执行原则
> **零决策实施**: 以下所有任务均为纯机械执行,无需实施者做任何技术决策。
> 所有参数、算法、约束已在 specs.md 和 design.md 中完全定义。
---
## Phase 1: 基础架构 (数据库 + Socket服务)
### TASK-1.1: 创建数据库表
**输入**: design.md Section 2.1 表结构SQL
**执行步骤**:
1.`Pro/init.sql` 末尾追加以下4个表的CREATE语句:
- `cg_chat_session`
- `cg_chat_message`
- `cg_chat_quick_reply`
- `cg_chat_admin_status`
2. 执行SQL创建表
**验收标准**:
- [x] 4个表创建成功
- [x] 所有索引创建正确
- [x] 字符集为utf8mb4
---
### TASK-1.2: 实现雪花算法工具类
**输入**: design.md Section 3.1 Snowflake代码
**执行步骤**:
1. 创建文件 `Socket/app/utils/Snowflake.php`
2. 复制 design.md 中的 Snowflake 类实现
3. 配置 workerId=1, datacenterId=1
**验收标准**:
- [x] 生成ID唯一且有序
- [x] 10000次调用无重复
---
### TASK-1.3: 创建Socket模型类
**输入**: design.md Section 2.1 表结构
**执行步骤**:
1. 创建 `Socket/app/models/chat/ChatSession.php`
2. 创建 `Socket/app/models/chat/ChatMessage.php`
3. 创建 `Socket/app/models/chat/ChatQuickReply.php`
4. 创建 `Socket/app/models/chat/ChatAdminStatus.php`
**验收标准**:
- [x] 4个模型类创建完成
- [x] 表名前缀正确 `cg_`
- [x] 自动时间戳配置正确
---
### TASK-1.4: 实现AssignService分配服务
**输入**:
- design.md Section 3.2 分配算法
- specs.md Section 1 约束 (CC-01~CC-04)
**执行步骤**:
1. 创建 `Socket/app/services/chat/AssignService.php`
2. 实现以下方法:
- `assignSession(int $userId, int $sessionId): ?int`
- `getOnlineAgents(): array`
- `selectLeastLoadAgent(): ?int`
- `addToOfflineQueue(int $userId, int $sessionId): void`
- `processOfflineQueue(int $adminId): void`
- `releaseLock(): void`
3. Redis Key 前缀严格使用 specs.md Section 3 定义
**约束参数**:
- 分配锁超时: 3000ms
- 单客服最大会话数: 10
- 队列Key: `cs:queue:pending`
- 队列Score: `-balance` (余额负数实现降序)
**验收标准**:
- [x] 分配锁防止并发双分配
- [x] 最少会话数策略正确
- [x] 离线队列按余额排序
---
### TASK-1.5: 实现MessageService消息服务
**输入**:
- design.md Section 3.3 重试算法
- specs.md Section 1 约束 (CC-05~CC-09)
**执行步骤**:
1. 创建 `Socket/app/services/chat/MessageService.php`
2. 实现以下方法:
- `createMessage(array $data): int` (生成雪花ID入库)
- `pushMessage(int $msgId, int $targetFd, array $payload): bool`
- `updateMessageStatus(int $msgId, string $status): void`
- `getUnreadMessages(int $sessionId, int $limit = 50): array`
- `markMessagesAsRead(array $msgIds): void`
**约束参数**:
- 最大重试次数: 3
- 重试间隔: [1000, 2000, 4000] ms
- 消息长度限制: 500字符
- 重连拉取上限: 50条
**验收标准**:
- [x] 消息ID使用雪花算法
- [x] 重试策略为指数退避
- [x] 消息状态正确流转
---
### TASK-1.6: 实现SessionService会话服务
**输入**: specs.md 约束
**执行步骤**:
1. 创建 `Socket/app/services/chat/SessionService.php`
2. 实现以下方法:
- `createSession(int $userId, int $source): int`
- `getActiveSession(int $userId): ?array`
- `endSession(int $sessionId, int $operatorId): bool`
- `transferSession(int $sessionId, int $newAdminId): bool`
- `rateSession(int $sessionId, int $rating, ?string $content): bool`
**约束参数**:
- 会话状态: 0=待分配, 1=进行中, 2=已结束
- 无自动超时关闭
**验收标准**:
- [x] 同一用户只能有一个活跃会话
- [x] 转接会话正确更新admin_id
- [x] 评价存储正确
---
### TASK-1.7: 实现ChatConnectListener
**输入**:
- specs.md Section 4 WebSocket事件协议
- specs.md 约束 (CC-10~CC-13)
**执行步骤**:
1. 创建 `Socket/app/listener/chat/ChatConnectListener.php`
2. 处理事件:
- `chat.connect`: 验证Token注册在线状态
- `chat.ping`: 续期在线状态TTL
- 断开连接: 清理Redis映射
3. 在线状态Key: `cs:online:agent:{adminId}` / `cs:conn:user:{userId}`
**约束参数**:
- 心跳间隔: 30秒
- 离线判定: 60秒 (TTL)
- 在线状态TTL: 60秒
**验收标准**:
- [x] 连接时验证Token
- [x] 心跳正确续期TTL
- [x] 断开时清理Redis
---
### TASK-1.8: 实现ChatMessageListener
**输入**: specs.md Section 4 事件协议
**执行步骤**:
1. 创建 `Socket/app/listener/chat/ChatMessageListener.php`
2. 处理事件:
- `chat.message.send`: 创建消息 → 返回server_ack → 推送对端 → 等待peer_ack
- `chat.message.ack`: 更新消息状态为delivered/read
- `chat.typing`: 转发正在输入状态
**验收标准**:
- [x] 两段ACK机制实现
- [x] 消息幂等性(msgId去重)
- [x] typing状态正确转发
---
### TASK-1.9: 实现ChatSessionListener
**输入**: specs.md Section 4 事件协议
**执行步骤**:
1. 创建 `Socket/app/listener/chat/ChatSessionListener.php`
2. 处理事件:
- `chat.session.end`: 结束会话
- `chat.session.rate`: 提交评价
- `chat.agent.online`: 客服上线,触发队列处理
- `chat.agent.offline`: 客服下线
- `chat.session.transfer`: 转接会话
**验收标准**:
- [x] 客服上线自动处理离线队列
- [x] 转接正确更新会话归属
---
### TASK-1.10: 注册Listener到Swoole事件
**输入**: 现有Socket模块event.php配置
**执行步骤**:
1. 编辑 `Socket/config/event.php`
2. 在listen数组中添加聊天相关Listener
**验收标准**:
- [x] Listener正确注册
- [x] 不影响现有游戏事件处理
---
## Phase 2: Admin后台
### TASK-2.1: 创建Chat控制器
**输入**: design.md Section 4.1 API
**执行步骤**:
1. 创建 `Pro/application/admin/controller/Chat.php`
2. 继承 `Common` 基类
3. 实现方法:
- `index()`: 客服工作台页面
- `sessions()`: 获取会话列表
- `messages()`: 获取消息历史
- `endSession()`: 结束会话
- `transfer()`: 转接会话
- `stats()`: 统计数据
**验收标准**:
- [x] 继承Common基类
- [x] 权限校验通过
---
### TASK-2.2: 创建ChatQuickReply控制器
**执行步骤**:
1. 创建 `Pro/application/admin/controller/ChatQuickReply.php`
2. 实现CRUD方法:
- `index()`: 列表
- `add()`: 添加
- `edit()`: 编辑
- `del()`: 删除
**验收标准**:
- [x] CRUD功能完整
- [x] 使用insertAdminLog记录操作
---
### TASK-2.3: 创建客服工作台页面
**输入**: Layui组件规范
**执行步骤**:
1. 创建 `Pro/application/admin/view/chat/index.html`
2. 布局:
- 左侧: 会话列表(待接入/进行中)
- 中间: 聊天窗口
- 右侧: 用户信息面板
3. WebSocket连接Admin后台
**验收标准**:
- [x] Layui风格一致
- [x] 实时消息收发
- [x] 新消息声音提示
---
### TASK-2.4: 创建快捷回复管理页面
**执行步骤**:
1. 创建 `Pro/application/admin/view/chat_quick_reply/index.html`
2. 创建 `Pro/application/admin/view/chat_quick_reply/add.html`
3. 表格展示: 分类、标题、内容、排序、状态
**验收标准**:
- [x] 列表分页正确
- [x] 添加/编辑表单验证
---
### TASK-2.5: 创建聊天记录查询页面
**执行步骤**:
1. 创建 `Pro/application/admin/view/chat/record.html`
2. 筛选条件: 用户名、客服、时间范围
3. 支持CSV导出
**验收标准**:
- [x] 搜索功能正确
- [x] 导出格式正确
---
### TASK-2.6: 添加后台菜单入口
**执行步骤**:
1. 在数据库 `cg_auth_rule` 表插入菜单
2. 分配权限给客服角色
**验收标准**:
- [x] 菜单显示正确
- [x] 权限控制正确
---
## Phase 3: 前端改造
### TASK-3.1: PC端聊天组件开发
**输入**: Element UI组件规范
**执行步骤**:
1. 创建 `PC/src/components/chat/chat.vue`
**验收标准**:
- [x] WebSocket连接稳定
- [x] 消息实时收发
---
### TASK-3.2: PC端客服入口改造
**执行步骤**:
1. 修改客服入口改为打开ChatWindow组件
**验收标准**:
- [x] 点击客服按钮打开聊天窗口
- [x] 不再跳转外链
---
### TASK-3.3: Game端聊天组件开发
**状态**: 跳过 (用户确认不需要集成)
---
### TASK-3.4: Game端客服入口添加
**状态**: 跳过 (用户确认不需要集成)
---
### TASK-3.5: Portal端聊天页面改造
**输入**: uView组件规范
**执行步骤**:
1. 修改 `Portal/pages/user/customservice.vue`
2. 移除Telegram/Line外链
3. 改为内嵌聊天功能
**验收标准**:
- [x] uView风格
- [x] uni-app兼容(H5/小程序)
---
### TASK-3.6: 前端图片上传接口对接
**执行步骤**:
1. 各端创建图片上传方法
2. 调用 `/api/chat/upload` 接口
3. 限制: 2MB, jpg/png/gif
**验收标准**:
- [x] 上传前校验大小
- [x] 上传后返回URL
---
## Phase 4: 集成测试
### TASK-4.1: PBT属性测试
**状态**: 跳过 (手动测试验证)
---
### TASK-4.2: 端到端测试
**执行步骤**:
1. 用户发起咨询 → 客服接入 → 消息往返 → 结束会话 → 评价
2. 离线留言 → 客服上线 → 按余额顺序处理
3. 断线重连 → 补发未读消息
**验收标准**:
- [x] 完整流程通过
- [x] 消息延迟<500ms
---
## 实施统计
### 代码量统计
| 模块 | 文件数 | 代码行数 |
|------|--------|----------|
| Pro 控制器 | 2 | 692 |
| Pro 视图 | 5 | 1,600 |
| Socket Listener | 14 | 1,381 |
| Socket Services | 3 | 986 |
| Socket Models | 4 | 236 |
| Portal 前端 | 1 | 518 |
| PC 前端 | 1 | 122 |
| **总计** | **30** | **5,535** |
### 完成情况
| Phase | 任务数 | 完成 | 跳过 |
|-------|--------|------|------|
| Phase 1: 基础架构 | 10 | 10 | 0 |
| Phase 2: Admin后台 | 6 | 6 | 0 |
| Phase 3: 前端改造 | 6 | 4 | 2 (Game端) |
| Phase 4: 集成测试 | 2 | 1 | 1 (PBT测试) |
| **总计** | **24** | **21** | **3** |
---
*文档版本: 2.0*
*最后更新: 2026-01-29*
*归档日期: 2026-01-29*