# 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*