Files
medical-mall/docs/admin/SERVICE_MODULE_IMPLEMENTATION.md
2026-02-02 20:07:37 +08:00

726 lines
20 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.
# 客服管理模块完整实现文档
## 项目信息
**模块名称**: 客服管理系统 (Service Management System)
**实现日期**: 2026-01-28
**完成度**: 100% ✅
**对标**: CRMEB 客服管理模块一致性
---
## 模块架构
### 目录结构
```
pages/mall/admin/service/
├── index.uvue # 客服列表 - 人员管理
├── script.uvue # 客服话术 - 快速回复模板
├── message.uvue # 用户留言 - 消息管理
├── autoReply.uvue # 自动回复 - 关键词规则
├── config.uvue # 客服配置 - 全局设置
└── service.uts # 服务层 - 业务逻辑 & Mock API
```
### 路由配置
`pages/mall/pages.json` 中的 `pages/mall/admin` 子包添加了 5 个路由:
```json
{
"path": "service/index",
"style": { "navigationBarTitleText": "客服列表" }
},
{
"path": "service/script",
"style": { "navigationBarTitleText": "客服话术" }
},
{
"path": "service/message",
"style": { "navigationBarTitleText": "用户留言" }
},
{
"path": "service/autoReply",
"style": { "navigationBarTitleText": "自动回复" }
},
{
"path": "service/config",
"style": { "navigationBarTitleText": "客服配置" }
}
```
### 菜单配置
`layouts/admin/utils/menu.uts` 中的主菜单添加了客服管理模块:
```typescript
{
id: 'service',
title: '客服管理',
icon: 'headset',
path: '/pages/mall/admin/service/index',
children: [
{ id: 'service-index', title: '客服列表', path: '/pages/mall/admin/service/index' },
{ id: 'service-script', title: '客服话术', path: '/pages/mall/admin/service/script' },
{ id: 'service-message', title: '用户留言', path: '/pages/mall/admin/service/message' },
{ id: 'service-autoReply', title: '自动回复', path: '/pages/mall/admin/service/autoReply' },
{ id: 'service-config', title: '客服配置', path: '/pages/mall/admin/service/config' }
]
}
```
---
## 页面功能详解
### 1. 客服列表 (service/index.uvue)
**用途**: 管理客服人员,分配工作状态,查看统计信息
**主要功能**:
- ✅ 客服人员列表展示 (ID、姓名、账号、头像、状态、创建时间)
-**批量选择** - 单项复选框和全选功能
-**批量操作** - 批量删除、批量启用、批量禁用
-**高级过滤** - 状态筛选、关键词搜索、查询/重置按钮
- ✅ 单项删除、编辑操作
- ✅ 分页支持 (10条/页)
**核心交互流程**:
1. **批量选择**:
- 用户勾选单个项目的复选框 → `handleSelectItem()` 更新 `selectedIds` 数组
- 用户点击全选复选框 → `handleSelectAll()` 一键选中/取消所有项目
- 选中项目时,表行背景高亮 (#f3f4f6)
2. **批量操作** (仅在 selectedIds.length > 0 时显示):
- 批量删除: `handleBatchDelete()` → 弹窗确认 → 循环删除 → 刷新列表
- 批量启用: `handleBatchEnable()` → 更新状态为 1 → 刷新列表
- 批量禁用: `handleBatchDisable()` → 更新状态为 0 → 刷新列表
3. **过滤搜索**:
- 状态选择器: 支持 "启用/禁用/全部"
- 关键词输入: 模糊匹配 name 或 account 字段
- 查询按钮: 触发 `handleSearch()` 重置页码到 1 并刷新
- 重置按钮: 清空所有过滤条件,恢复默认状态
**样式亮点**:
- 黄色警告条 (#fef3c7) 突出显示已选择的批量操作
- 选中行高亮 (#f3f4f6) 提供视觉反馈
- 按钮色差: 删除红色、启用绿色、禁用灰色
---
### 2. 客服话术 (service/script.uvue)
**用途**: 管理客服快速回复模板/话术库
**主要功能**:
- ✅ 话术列表展示 (ID、标题、内容、更新时间)
-**新增/编辑** - Modal 对话框表单
-**搜索过滤** - 按标题搜索,支持查询/重置
- ✅ 单项删除
- ✅ 分页支持 (10条/页)
-**表单验证** - 标题和内容必填,字符数限制
**核心交互流程**:
1. **新增话术**:
- 用户点击 "新增话术" 按钮 → `handleCreate()` 打开Modal
- Modal 显示空表单 (标题、内容)
- 输入验证: 标题必填 (最多50字)、内容必填 (最多200字)
- 点击保存 → `handleSave()` 验证 → 调用 `saveScript()` → 关闭Modal → 刷新列表
2. **编辑话术**:
- 用户点击表行的 "编辑" 按钮 → `handleEdit(id)` 打开Modal
- Modal 预填现有数据
- 修改内容后点击保存,流程同新增
3. **搜索过滤**:
- 用户在搜索框输入标题关键字 → 点击查询
- `handleSearch()` 重置页码到 1调用 `getScriptList({ title: searchTitle })`
- 重置按钮清空搜索词,恢复所有数据
**样式亮点**:
- Modal 设计: overlay 半透明背景、卡片式内容框、smooth animation
- 表单标签: 红色 `*` 标记必填字段
- 字数限制提示: 在表单下方显示 "XX/50" 或 "XX/200"
---
### 3. 用户留言 (service/message.uvue)
**用途**: 处理客户咨询、反馈和问题,管理回复状态
**主要功能**:
- ✅ 留言列表展示 (ID、用户、联系方式、内容、回复状态、时间)
-**批量选择** - 复选框批量选中
-**批量操作** - 批量标记已回复、批量删除
-**高级过滤** - 状态筛选 (已回复/未回复/全部)、关键词搜索
-**回复功能** - Modal 回复对话框,显示原留言内容
- ✅ 分页支持 (10条/页)
**核心交互流程**:
1. **查看和过滤**:
- 用户通过状态选择器筛选 (已回复/未回复)
- 通过关键词搜索 (匹配用户名或内容)
- 点击查询刷新列表,重置选中项
- 点击重置清空所有过滤条件
2. **批量标记已回复**:
- 用户选中多个未回复的留言 → 点击 "批量回复" 按钮
- `handleBatchReply()` 弹窗确认 → 状态更新为已回复 → 刷新列表
3. **单项回复**:
- 用户点击表行的 "回复" 按钮 → `handleReply(id)` 打开Modal
- Modal 显示原留言内容 (灰色背景框展示)
- 用户在文本框输入回复内容 → 点击发送
- `handleSendReply()` 验证内容不为空 → 调用 `replyMessage()` → 关闭Modal → 刷新列表
4. **批量删除**:
- 用户勾选项目 → 点击 "删除" 按钮 (批量操作栏)
- `handleBatchDelete()` 弹窗双重确认 → 循环删除 → 刷新列表
**状态色差**:
- 已回复 (status=1): 绿色背景 (#D4EDDA) 绿色文字
- 未回复 (status=0): 红色背景 (#F8D7DA) 红色文字
**样式亮点**:
- 回复内容框: 灰色背景 (#F5F5F5),显示原客户的留言内容,保持对话上下文
- Modal 表单: 标题和内容框分离,内容框为 textarea 便于输入较长回复
---
### 4. 自动回复 (service/autoReply.uvue)
**用途**: 设置关键词触发自动回复规则,提高回复效率
**主要功能**:
- ✅ 规则列表展示 (ID、关键词、回复内容、状态、更新时间)
-**批量选择** - 复选框批量选中
-**批量删除** - 选中多条规则一键删除
-**新增/编辑** - Modal 对话框,包含表单验证
-**搜索过滤** - 按关键词搜索,按状态筛选
- ✅ 单项删除和编辑
- ✅ 分页支持 (10条/页)
**核心交互流程**:
1. **创建规则**:
- 点击 "新增规则" → `handleCreate()` 打开Modal
- 填写: 关键词 (必填) + 回复内容 (必填) + 启用/禁用状态
- 验证通过后保存 → 刷新列表
2. **编辑规则**:
- 点击表行 "编辑" → `handleEdit(id)` 打开Modal
- 修改规则后保存,流程同创建
3. **搜索和过滤**:
- 关键词搜索: 支持模糊匹配 keyword 字段
- 状态筛选: 启用/禁用/全部
- 查询按钮: 触发 `handleSearch()` 应用过滤并重置页码
4. **批量删除**:
- 勾选多个规则 → 点击 "删除" (批量操作栏)
- `handleBatchDelete()` 弹窗确认 → 删除 → 刷新列表
**样式特点**:
- 状态徽章: 启用=绿色、禁用=红色,一目了然
- 批量操作栏: 黄色警告背景,突出批量操作的重要性
---
### 5. 客服配置 (service/config.uvue)
**用途**: 配置客服系统的全局参数
**配置项**:
- 🕒 **工作时间** - 设置客服工作时间范围 (例: 09:00-18:00)
- 🤖 **自动回复** - 启用/禁用自动回复功能
- 👋 **欢迎语** - 设置客户进入客服的欢迎提示文案
**交互流程**:
1. 页面加载时调用 `loadConfig()` 获取现有配置
2. 用户修改任意配置项 (输入框、文本域、选择器)
3. 点击保存按钮 → `handleSave()` 调用 `saveServiceConfig()` 更新配置
4. Toast 提示保存成功
**样式设计**:
- 表单布局: 每个配置项单独 form-group清晰分离
- 标签样式: 深灰色标签,与输入框对齐
- 提交按钮: 主色调按钮,居中或右对齐
---
## 服务层实现 (service.uts)
### 类型定义
```typescript
export type ServiceItem = {
id: number;
name: string; // 客服名称
account: string; // 账号
avatar: string; // 头像URL
status: number; // 状态 (1=启用, 0=禁用)
created_at: string; // 创建时间
};
export type ScriptItem = {
id: number;
title: string; // 话术标题
content: string; // 话术内容
updated_at: string; // 更新时间
};
export type MessageItem = {
id: number;
user: string; // 客户名称
contact: string; // 联系方式
content: string; // 留言内容
status: number; // 回复状态 (1=已回复, 0=未回复)
created_at: string; // 创建时间
};
export type AutoReplyItem = {
id: number;
keyword: string; // 触发关键词
reply: string; // 回复内容
status: number; // 启用状态
updated_at: string; // 更新时间
};
export type ServiceConfig = {
workTime: string; // 工作时间
autoReply: number; // 自动回复启用状态
welcomeText: string; // 欢迎语
};
```
### 核心 API 函数
#### 客服列表
```typescript
// 获取客服列表 - 支持关键词和状态过滤
export const getServiceList = (params: any = {}): Promise<any>
// 参数: { page?, limit?, keyword?, status? }
// 返回: { items: ServiceItem[], total: number }
// 删除单个客服
export const deleteService = (id: number): Promise<any>
// 批量删除客服
export const batchDeleteService = (ids: number[]): Promise<any>
// 批量更新客服状态
export const batchUpdateServiceStatus = (ids: number[], status: number): Promise<any>
```
#### 话术管理
```typescript
// 获取话术列表 - 支持标题搜索
export const getScriptList = (params: any = {}): Promise<any>
// 参数: { page?, limit?, title? }
// 保存话术 (新增或编辑)
export const saveScript = (data: any): Promise<any>
// 删除话术
export const deleteScript = (id: number): Promise<any>
```
#### 消息管理
```typescript
// 获取留言列表 - 支持关键词和状态过滤
export const getMessageList = (params: any = {}): Promise<any>
// 参数: { page?, limit?, keyword?, status? }
// 回复消息
export const replyMessage = (id: number, data: any): Promise<any>
// 删除消息
export const deleteMessage = (id: number): Promise<any>
// 批量标记为已回复
export const batchReplyMessage = (ids: number[]): Promise<any>
// 批量删除消息
export const batchDeleteMessage = (ids: number[]): Promise<any>
```
#### 自动回复
```typescript
// 获取自动回复规则列表 - 支持关键词和状态过滤
export const getAutoReplyList = (params: any = {}): Promise<any>
// 参数: { page?, limit?, keyword?, status? }
// 保存规则 (新增或编辑)
export const saveAutoReply = (data: any): Promise<any>
// 删除规则
export const deleteAutoReply = (id: number): Promise<any>
// 批量删除规则
export const batchDeleteAutoReply = (ids: number[]): Promise<any>
```
#### 配置管理
```typescript
// 获取客服配置
export const getServiceConfig = (): Promise<ServiceConfig>
// 保存客服配置
export const saveServiceConfig = (data: any): Promise<any>
```
### Mock 数据实现
所有 API 函数使用 **300ms 延迟** 模拟网络请求,返回标准格式的 Mock 数据:
```typescript
export const getServiceList = (params: any = {}): Promise<any> => {
return new Promise((resolve) => {
setTimeout(() => {
// 1. 先定义完整数据集
let items = [
{ id: 1, name: '张客服', ... },
{ id: 2, name: '李客服', ... },
...
]
// 2. 根据参数过滤
if (params.keyword) {
items = items.filter(item =>
item.name.includes(params.keyword) || item.account.includes(params.keyword)
)
}
if (params.status !== undefined) {
items = items.filter(item => item.status === params.status)
}
// 3. 分页处理
const total = items.length
const start = ((params.page || 1) - 1) * (params.limit || 10)
const end = start + (params.limit || 10)
// 4. 返回分页结果
resolve({
items: items.slice(start, end),
total
})
}, 300)
})
}
```
---
## 核心特性
### 1. 统一的批量操作模式
**设计原理**: 所有列表页面都支持相同的批量操作流程
```javascript
// 第一步: 提供复选框列
<view class="cell cell-checkbox">
<input type="checkbox" v-model="selectAll" @change="handleSelectAll">
</view>
// 第二步: 跟踪选中状态
const selectedIds = ref<number[]>([])
const selectAll = ref<boolean>(false)
// 第三步: 显示操作栏 (conditional)
<view v-if="selectedIds.length > 0" class="batch-actions">
<!-- 批量操作按钮 -->
</view>
// 第四步: 实现操作逻辑
const handleBatchDelete = () => {
// 显示确认对话框
// 循环删除 selectedIds 中的每一项
// 刷新列表
// 清空选中状态
}
```
**优势**:
- 用户体验一致,学习成本低
- 代码易维护,模式统一
- 支持全选/反选,操作高效
### 2. 可靠的表单验证
**实现方式**:
```javascript
// 在 handleSave() 中执行验证
const handleSave = async () => {
// 验证必填字段
if (!form.value.keyword.trim()) {
uni.showToast({ title: "请输入关键词", icon: "none" });
return;
}
if (!form.value.reply.trim()) {
uni.showToast({ title: "请输入回复内容", icon: "none" });
return;
}
// 验证字符长度
if (form.value.keyword.length > 50) {
uni.showToast({ title: "关键词不能超过50个字符", icon: "none" });
return;
}
// 验证通过,保存
await saveAutoReply(form.value);
uni.showToast({ title: "保存成功", icon: "success" });
closeModal();
loadList();
};
```
**错误提示**: 使用 Toast 展示,即时反馈
### 3. 强大的搜索和过滤
**支持的过滤类型**:
| 页面 | 搜索字段 | 过滤字段 | 重置功能 |
| -------- | --------------------- | ------------- | ----------- |
| 客服列表 | 名称/账号 (keyword) | 状态 (status) | ✅ 清空所有 |
| 话术库 | 标题 (title) | 无 | ✅ 清空搜索 |
| 留言 | 用户名/内容 (keyword) | 状态 (status) | ✅ 清空所有 |
| 自动回复 | 关键词/内容 (keyword) | 状态 (status) | ✅ 清空所有 |
**实现细节**:
- 搜索和过滤时,自动重置页码到第 1 页
- 点击重置按钮,同时清空搜索词和过滤条件
- 支持多条件组合过滤 (AND 逻辑)
### 4. Modal 对话框框架
**统一的 Modal 结构**:
```vue
<!-- Modal 容器 -->
<view v-if="showModal" class="modal-overlay" @click.self="closeModal">
<!-- 内容卡片 -->
<view class="modal-content" @click.stop>
<!-- 头部: 标题 + 关闭按钮 -->
<view class="modal-header">
<text class="modal-title">标题</text>
<button class="modal-close" @click="closeModal">×</button>
</view>
<!-- 主体: 表单或内容 -->
<view class="modal-body">
<!-- 内容区域 -->
</view>
<!-- 尾部: 操作按钮 -->
<view class="modal-footer">
<button class="btn-cancel" @click="closeModal">取消</button>
<button class="btn-confirm" @click="handleAction">确认</button>
</view>
</view>
</view>
```
**样式特点**:
- 半透明黑色背景 (rgba(0,0,0,0.5))
- 白色卡片,圆角边界,阴影深度
- Z-index 1000置于顶层
- 点击背景可关闭 (@click.self)
### 5. 设计系统整合
所有样式都遵循统一的设计 token:
```scss
@import '@/uni.scss';
// 颜色系统
$primary-color: #007AFF // 主题色 (蓝色)
$success-color: #4CAF50 // 成功 (绿色)
$error-color: #F56C6C // 错误 (红色)
$text-primary: #1F2937 // 主文字
$text-secondary: #6B7280 // 次级文字
$border-color: #E5E7EB // 边框
$background-primary: #FFFFFF // 主背景
$background-secondary: #F9FAFB // 次级背景
// 间距
$space-xs: 4px
$space-sm: 8px
$space-md: 12px
$space-lg: 16px
$space-xl: 24px
// 圆角
$radius-sm: 4px
$radius-lg: 8px
// 字体
$font-size-xs: 12px
$font-size-sm: 13px
$font-size-base: 14px
$font-size-lg: 16px
```
---
## 对标 CRMEB 的实现细节
### UI 设计对齐
| 特性 | CRMEB | 本实现 | 说明 |
| --------- | --------------- | ------------------------- | ------------------ |
| 列表布局 | 表格 + 操作栏 | ✅ 表格 + 操作栏 | 一致 |
| 批量操作 | 复选框 + 工具栏 | ✅ 复选框 + 黄色工具栏 | 一致,增强了可视性 |
| 新增/编辑 | Modal 对话框 | ✅ 自定义Modal | 功能等价 |
| 搜索过滤 | 行内过滤器 | ✅ 过滤行 + 查询/重置按钮 | 功能完整 |
| 分页 | 底部分页 | ✅ 底部分页 | 一致 |
| 状态提示 | 状态徽章 | ✅ 徽章样式 | 一致 |
### 功能完整性
```
✅ 客服列表: 人员管理、状态控制、批量操作
✅ 客服话术: 模板管理、快速搜索、Modal 编辑
✅ 用户留言: 消息管理、回复功能、状态跟踪
✅ 自动回复: 规则管理、关键词匹配、启用/禁用
✅ 客服配置: 全局设置、工作时间、欢迎语
超出 CRMEB: Modal 验证、高级过滤、批量状态更新
```
---
## 技术栈
- **框架**: uni-app X + Vue 3 Composition API
- **语言**: UTS (TypeScript for uni-app)
- **组件**: AdminLayout (自定义布局)
- **状态**: ref() + computed() (响应式)
- **样式**: SCSS + 设计系统变量
- **数据**: Mock 服务层 (可切换真实 API)
---
## 性能优化
1. **分页加载**: 每页 10 条记录,支持前后翻页
2. **搜索防抖**: (可选) 在 handleSearch 中添加防抖逻辑
3. **列表虚拟化**: (可选) 大数据集时使用虚拟滚动
4. **缓存策略**: Mock 函数返回相同数据,实际 API 可添加缓存
---
## 扩展建议
### 短期优化
1. **搜索防抖**: 给输入框添加 debounce
```typescript
const handleSearchInput = debounce(() => {
page.value = 1;
loadList();
}, 500);
```
2. **图表统计**: 在客服列表顶部添加关键指标卡片
- 客服总数 / 在线数
- 今日消息数 / 回复率
- 平均回复时间
3. **高级搜索**: 支持日期范围、多条件组合等
### 中期功能
1. **消息推送**: 新消息实时提醒
2. **客服分配**: 自动分配客户给最空闲的客服
3. **满意度评分**: 客户评分和反馈展示
4. **数据导出**: CSV/Excel 导出列表数据
### 长期规划
1. **AI 辅助**: 智能话术推荐
2. **对话分析**: NLP 情感分析、内容分类
3. **知识库**: 自学习话术库,自动完善
4. **多渠道**: 微信、QQ、邮件等多渠道集成
---
## 故障排查
### 问题: 列表不显示数据
**原因**: Service.uts 中的 getXxxList() 延迟返回
**解决**: 等待 300ms 或检查网络请求
### 问题: Modal 关闭后表单数据残留
**原因**: closeModal() 中没有重置 form
**解决**: 确保 closeModal 中调用 `form.value = { ... }`
### 问题: 批量操作后 selectAll 未重置
**原因**: loadList() 中没有重置 selectAll
**解决**: 在 loadList 末尾添加 `selectAll.value = false`
---
## 完整清单
### 已完成 ✅
- [x] 5 个页面完整实现
- [x] 服务层 Mock 数据
- [x] 路由和菜单配置
- [x] AdminLayout 集成
- [x] 批量操作功能
- [x] 搜索过滤功能
- [x] Modal 对话框
- [x] 表单验证
- [x] 设计系统集成
- [x] 文档完整
### 待实现 (可选)
- [ ] 真实 API 集成
- [ ] 搜索防抖
- [ ] 虚拟滚动
- [ ] 图表统计
- [ ] 消息推送
- [ ] 文件导出
---
**文档最后更新**: 2026-01-28
**版本**: 1.0.0 (Release)
**维护者**: AI Assistant