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

397 lines
14 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 Proposal: 在线客服模块集成
## 变更标识
- **变更ID**: customer-service-module
- **创建日期**: 2026-01-28
- **状态**: SPEC_COMPLETE
---
## 1. 上下文 (Context)
### 1.1 用户需求
在OG Live Gaming Platform的admin后台集成在线客服模块将PC端和移动端(Game/Portal)的客服功能从外链跳转改为内置实时聊天,所有用户消息统一转发到后台由客服人员回复。
### 1.2 现有实现
- **当前方案**: 外链跳转第三方客服平台
- PC端: `PC/src/components/updateService/update-service.vue` - 通过 `webconfig.customerLink` 跳转
- Portal端: `Portal/pages/user/customservice.vue` - 支持 Telegram/Line 外部链接
- **问题**: 无法统一管理用户咨询,缺乏历史记录追溯
### 1.3 技术环境
| 组件 | 技术栈 | 版本 |
|------|--------|------|
| 后端主服务 | ThinkPHP | 5.x |
| WebSocket服务 | ThinkPHP + Swoole | 6.x |
| PC前端 | Vue.js + Element UI | 2.x |
| Game前端 | Vue.js + Vant | 3.x |
| Portal前端 | uni-app + uView | - |
| 数据库 | MySQL | 5.7 |
| 缓存 | Redis | 5.x |
---
## 2. 约束集合 (Constraint Sets)
### 2.1 硬约束 (Hard Constraints) - 不可违反
| ID | 约束 | 来源 | 影响 |
|----|------|------|------|
| HC-01 | 必须使用现有Socket服务(ThinkPHP 6.x + Swoole)作为WebSocket通信基础 | 架构一致性 | 不能引入新的WebSocket服务 |
| HC-02 | 数据库表必须使用 `cg_` 前缀 | `application/database.php:23` | 表名规范 |
| HC-03 | Admin后台控制器必须继承 `Common` 基类 | `application/admin/controller/Common.php` | 权限控制 |
| HC-04 | 前端API请求必须通过现有封装的HTTP客户端 | 各端API封装 | 接口一致性 |
| HC-05 | 用户认证必须复用现有Session/Token机制 | 安全性 | 不能引入新认证体系 |
### 2.2 软约束 (Soft Constraints) - 建议遵循
| ID | 约束 | 来源 | 建议 |
|----|------|------|------|
| SC-01 | Admin后台UI应使用Layui框架 | 现有后台风格 | 保持视觉一致性 |
| SC-02 | WebSocket事件应遵循现有listener模式 | `Socket/app/listener/` | 代码组织一致 |
| SC-03 | 前端组件命名应遵循各端现有规范 | 代码风格 | PascalCase组件名 |
| SC-04 | 日志记录应使用现有 `insertAdminLog()` 函数 | `application/helper.php` | 审计追踪 |
### 2.3 依赖约束 (Dependencies)
| ID | 依赖项 | 类型 | 说明 |
|----|--------|------|------|
| DC-01 | cg_user 表 | 数据 | 用户信息关联 |
| DC-02 | cg_admin 表 | 数据 | 客服人员账号 |
| DC-03 | Redis | 基础设施 | 在线状态、会话分配 |
| DC-04 | Socket服务 | 服务 | 实时消息推送 |
---
## 3. 需求规格 (Requirements)
### 3.1 功能需求
#### REQ-01: 后台客服工作台
**场景**: 客服人员登录admin后台进入客服模块
**验收标准**:
- [ ] 显示待接入会话列表(按等待时间排序)
- [ ] 显示当前处理中的会话列表
- [ ] 支持同时处理多个会话(标签页切换)
- [ ] 实时显示新消息通知(声音+视觉提示)
- [ ] 显示用户基本信息(用户名、余额、来源端)
#### REQ-02: 会话自动分配
**场景**: 用户发起客服咨询
**验收标准**:
- [ ] 系统自动将用户分配给当前会话数最少的在线客服
- [ ] 客服离线时,消息进入待分配队列
- [ ] 支持会话转接给其他在线客服
- [ ] 记录会话分配历史
#### REQ-03: 实时消息通信
**场景**: 用户与客服进行对话
**验收标准**:
- [ ] 支持文字消息发送/接收
- [ ] 支持图片消息发送/接收(上传+预览)
- [ ] 消息实时推送(延迟<500ms
- [ ] 显示消息发送状态发送中/已送达/已读
- [ ] 支持消息时间戳显示
#### REQ-04: 离线消息
**场景**: 用户发送消息时客服全部离线或客服回复时用户已离线
**验收标准**:
- [ ] 离线消息持久化存储
- [ ] 用户/客服上线后自动推送未读消息
- [ ] 显示未读消息数量角标
#### REQ-05: 快捷回复
**场景**: 客服需要快速回复常见问题
**验收标准**:
- [ ] 支持预设快捷回复语管理增删改
- [ ] 支持快捷回复分类
- [ ] 一键插入快捷回复内容
#### REQ-06: 聊天记录查询
**场景**: 客服或管理员需要查看历史对话
**验收标准**:
- [ ] 支持按用户名搜索
- [ ] 支持按时间范围筛选
- [ ] 支持按客服人员筛选
- [ ] 支持导出聊天记录
#### REQ-07: 用户信息展示
**场景**: 客服处理会话时需要了解用户背景
**验收标准**:
- [ ] 显示用户账号昵称
- [ ] 显示用户余额
- [ ] 显示用户来源PC/Game/Portal
- [ ] 显示用户上级代理信息
- [ ] 显示用户最近下注记录可选
#### REQ-08: 会话评价
**场景**: 用户结束咨询后对服务进行评价
**验收标准**:
- [ ] 会话结束后弹出评价窗口
- [ ] 支持1-5星评分
- [ ] 支持文字评价可选
- [ ] 后台可查看评价统计
#### REQ-09: 前端客服入口改造
**场景**: 用户在PC/Game/Portal端点击客服按钮
**验收标准**:
- [ ] PC端: 替换外链跳转为内嵌聊天窗口
- [ ] Game端: 添加客服聊天组件
- [ ] Portal端: 替换外链页面为聊天页面
- [ ] 三端UI风格与各自设计语言一致
---
## 4. 数据库设计
### 4.1 新增表结构
```sql
-- 客服会话表
CREATE TABLE `cg_chat_session` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL COMMENT '用户ID',
`admin_id` int(10) unsigned DEFAULT NULL COMMENT '客服ID',
`source` tinyint(1) NOT NULL DEFAULT '1' COMMENT '来源: 1=PC 2=Game 3=Portal',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态: 0=待分配 1=进行中 2=已结束',
`rating` tinyint(1) DEFAULT NULL COMMENT '评分: 1-5',
`rating_content` varchar(500) DEFAULT NULL COMMENT '评价内容',
`create_time` int(10) unsigned NOT NULL,
`update_time` int(10) unsigned NOT NULL,
`end_time` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `admin_id` (`admin_id`),
KEY `status` (`status`),
KEY `create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客服会话表';
-- 聊天消息表
CREATE TABLE `cg_chat_message` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`session_id` int(10) unsigned NOT NULL COMMENT '会话ID',
`sender_type` tinyint(1) NOT NULL COMMENT '发送者类型: 1=用户 2=客服',
`sender_id` int(10) unsigned NOT NULL COMMENT '发送者ID',
`msg_type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '消息类型: 1=文字 2=图片',
`content` text NOT NULL COMMENT '消息内容',
`is_read` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已读',
`create_time` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `session_id` (`session_id`),
KEY `sender_type` (`sender_type`),
KEY `is_read` (`is_read`),
KEY `create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='聊天消息表';
-- 快捷回复表
CREATE TABLE `cg_chat_quick_reply` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`category` varchar(50) DEFAULT NULL COMMENT '分类',
`title` varchar(100) NOT NULL COMMENT '标题',
`content` text NOT NULL COMMENT '内容',
`sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态',
`create_time` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `category` (`category`),
KEY `status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='快捷回复表';
-- 客服在线状态表 (Redis辅助)
CREATE TABLE `cg_chat_admin_status` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`admin_id` int(10) unsigned NOT NULL COMMENT '客服ID',
`is_online` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否在线',
`current_sessions` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '当前会话数',
`max_sessions` int(10) unsigned NOT NULL DEFAULT '10' COMMENT '最大会话数',
`last_active_time` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `admin_id` (`admin_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客服状态表';
```
---
## 5. 技术方案
### 5.1 架构图
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ PC端 │ │ Game端 │ │ Portal端 │
│ (Vue 2.x) │ │ (Vue 3.x) │ │ (uni-app) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└────────────────┼────────────────┘
│ WebSocket
┌─────────────────┐
│ Socket服务 │
│ (TP6 + Swoole) │
│ │
│ 新增listener: │
│ - ChatConnect │
│ - ChatMessage │
│ - ChatSession │
└────────┬────────┘
┌─────────────┼─────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ MySQL │ │ Redis │ │ 文件存储 │
│ 消息持久化│ │ 在线状态 │ │ 图片上传 │
└──────────┘ └──────────┘ └──────────┘
┌─────────────────┐
│ Admin后台 │
│ (TP5 + Layui) │
│ │
│ 新增模块: │
│ - Chat控制器 │
│ - 客服工作台 │
│ - 快捷回复管理 │
│ - 聊天记录查询 │
└─────────────────┘
```
### 5.2 WebSocket事件设计
| 事件名 | 方向 | 说明 |
|--------|------|------|
| `chat.connect` | ClientServer | 用户/客服建立聊天连接 |
| `chat.message` | 双向 | 发送/接收消息 |
| `chat.typing` | 双向 | 正在输入状态 |
| `chat.read` | ClientServer | 消息已读回执 |
| `chat.session.new` | ServerAdmin | 新会话通知 |
| `chat.session.assign` | ServerAdmin | 会话分配通知 |
| `chat.session.transfer` | AdminServer | 会话转接 |
| `chat.session.end` | 双向 | 会话结束 |
| `chat.admin.online` | AdminServer | 客服上线 |
| `chat.admin.offline` | AdminServer | 客服下线 |
### 5.3 文件变更清单
#### Pro模块 (Admin后台)
```
application/admin/controller/
├── Chat.php # 新增 - 客服工作台控制器
├── ChatRecord.php # 新增 - 聊天记录控制器
└── ChatQuickReply.php # 新增 - 快捷回复管理控制器
application/admin/view/
├── chat/
│ ├── index.html # 新增 - 客服工作台页面
│ └── record.html # 新增 - 聊天记录页面
└── chat_quick_reply/
├── index.html # 新增 - 快捷回复列表
└── add.html # 新增 - 添加快捷回复
application/admin/view/index/index.html # 修改 - 添加客服菜单入口
```
#### Socket模块
```
app/listener/chat/
├── ChatConnect.php # 新增 - 聊天连接处理
├── ChatMessage.php # 新增 - 消息处理
└── ChatSession.php # 新增 - 会话管理
app/services/chat/
├── ChatService.php # 新增 - 聊天核心服务
├── SessionService.php # 新增 - 会话分配服务
└── MessageService.php # 新增 - 消息存储服务
app/models/chat/
├── ChatSession.php # 新增 - 会话模型
├── ChatMessage.php # 新增 - 消息模型
└── ChatQuickReply.php # 新增 - 快捷回复模型
```
#### PC端
```
src/components/chat/
├── ChatWindow.vue # 新增 - 聊天窗口组件
├── ChatMessage.vue # 新增 - 消息气泡组件
└── ChatInput.vue # 新增 - 输入框组件
src/components/updateService/
└── update-service.vue # 修改 - 改为打开聊天窗口
```
#### Game端
```
src/components/chat/
├── ChatWindow.vue # 新增 - 聊天窗口组件
├── ChatMessage.vue # 新增 - 消息气泡组件
└── ChatInput.vue # 新增 - 输入框组件
src/components/
└── HallNav.vue # 修改 - 添加客服入口
```
#### Portal端
```
pages/user/
└── customservice.vue # 修改 - 改为聊天页面
components/chat/
├── ChatWindow.vue # 新增 - 聊天窗口组件
└── ChatMessage.vue # 新增 - 消息组件
```
---
## 6. 风险评估
| 风险 | 等级 | 缓解措施 |
|------|------|----------|
| WebSocket连接数过多导致服务压力 | | 实现连接池心跳检测自动断开空闲连接 |
| 消息丢失 | | 消息持久化优先ACK确认机制 |
| 图片上传占用存储 | | 图片压缩定期清理可配置存储路径 |
| 客服全部离线时用户体验 | | 显示离线提示支持留言 |
---
## 7. 成功判据 (Success Criteria)
- [ ] 用户可在PC/Game/Portal三端发起客服咨询
- [ ] 客服可在Admin后台实时接收和回复消息
- [ ] 消息延迟 < 500ms
- [ ] 支持文字和图片消息
- [ ] 离线消息可正常存储和推送
- [ ] 会话自动分配正常工作
- [ ] 聊天记录可查询和导出
- [ ] 快捷回复功能正常
- [ ] 会话评价功能正常
---
## 8. 实施阶段建议
### Phase 1: 基础架构
- 数据库表创建
- Socket服务聊天事件监听器
- 基础消息收发功能
### Phase 2: Admin后台
- 客服工作台UI
- 会话管理
- 快捷回复管理
### Phase 3: 前端改造
- PC端聊天组件
- Game端聊天组件
- Portal端聊天页面
### Phase 4: 增强功能
- 离线消息
- 会话评价
- 聊天记录查询导出
---
*文档版本: 1.0*
*最后更新: 2026-01-28*