20 KiB
HashMall 前台客服系统产品需求文档
文档状态:已确认插件化方案,进入开发
文档版本:v0.2
编制日期:2026-07-16
插件目录:frontend-web/uni_modules/hashmall-customer-service/
目标终端:H5、微信小程序,结构上兼容后续 App 接入
1. 文档目的
本文档定义 HashMall 商城前台客服系统的产品范围、用户流程、交互要求、接口依赖、跨端兼容、安全前置条件和验收标准。
客服前台以 uni_modules 插件形式直接内嵌现有 frontend-web 商城工程,复用宿主登录态、请求封装、页面生命周期和构建流程;不创建、部署或运行独立客服前端服务。
2. 项目背景
HashMall 已经完成客服系统的主要后端能力和管理后台客服工作台,商城前台目前仍使用第三方 H5 客服页面或电话号码弹窗,没有接入自有客服会话。
现有前台客服入口包括:
- “我的”页服务工具中的“联系客服”。
- 商品详情页的客服入口。
- 订单列表或订单详情中的售后咨询入口。
- 现有
pages/rwa_package/kefu/kefu.vue.vue通过iframe加载第三方客服 H5。
微信小程序不能沿用当前 iframe 方案;即使改用小程序 web-view,也会受业务域名、登录态透传、返回导航和页面体验限制。因此新客服前台应采用 uni-app 原生页面与组件实现,不依赖 iframe。
3. 现状梳理
3.1 已完成的后端能力
当前 backend/JST-ERP 分支已经包含:
- 客服会话、客服消息、商品浏览历史数据表和 DAO。
- 用户发送消息、查询历史消息、查询浏览记录、查询订单、记录商品浏览等接口。
- 后台会话列表、会话详情、置顶、删除、消息发送和已读接口。
/ws/kefu与/api/ws/kefuWebSocket 端点。- 新消息、会话变化、已读状态变化的实时推送。
- 文本、图片、商品卡片和订单卡片四种消息类型。
3.2 已完成的管理后台能力
当前管理后台已经包含:
- 会话列表、置顶、删除、未读数量。
- 客服与会员聊天区。
- 文本、表情和图片消息。
- 会员资料、最近浏览和交易订单侧栏。
- WebSocket 实时刷新与断线重连。
- 图片上传后发送可访问 URL。
3.3 前台现状与缺口
当前商城前台:
- 没有自有客服聊天页。
- “我的”页客服入口主要弹出电话联系方式。
- 部分入口跳转到第三方 H5 客服页面。
- 没有复用自有客服消息接口。
- 没有接入自有客服 WebSocket。
- 没有发送商品卡片、订单卡片的完整流程。
- 没有客服消息发送状态、失败重试、断线恢复和历史消息分页体验。
- 商品详情页尚未统一接入客服浏览记录上报。
4. 产品目标
4.1 核心目标
- 用户能够从商城关键场景进入自有客服聊天页。
- 用户与后台客服能够实时收发消息并查看历史记录。
- H5 与微信小程序保持一致的核心功能和主要视觉体验。
- 用户可以携带商品或订单上下文发起咨询,减少描述成本。
- 网络异常、切后台、WebSocket 断开时不丢消息,并能自动恢复。
- 用户只能访问本人的会话和消息,不能通过修改参数读取他人数据。
4.2 成功指标
首期上线后建议关注:
- 客服入口点击至聊天页成功率不低于 99.5%。
- 文本消息发送成功率不低于 99.9%。
- 在线情况下新消息端到端可见时间 P95 不超过 2 秒。
- WebSocket 断线后 10 秒内自动恢复率不低于 99%。
- 由商品或订单场景进入时,上下文卡片发送率可被埋点统计。
- 因身份错误导致的跨用户数据访问事件为 0。
5. 用户与使用场景
5.1 用户角色
- 已登录会员:使用全部客服能力。
- 未登录访客:可看客服说明;发起聊天时必须先登录。
- 后台客服:使用现有管理后台接收和回复消息,不属于本项目前台开发范围。
首期不支持匿名访客会话,避免设备身份、会话合并和隐私归属问题。
5.2 主要场景
- 通用咨询:用户从“我的 → 联系客服”进入聊天页。
- 商品咨询:用户从商品详情进入,页面展示待咨询商品,可一键发送商品卡片。
- 订单咨询:用户从订单详情或售后场景进入,可一键发送订单卡片。
- 历史追问:用户再次进入客服页,继续原有会话并查看历史消息。
- 客服回复:页面打开时实时收到;页面关闭后,后续可扩展消息角标或订阅消息提醒。
6. 产品范围
6.1 P0:首期必须完成
- 登录校验与当前用户识别。
- 单一客服会话的创建或恢复。
- 历史消息加载和向上翻页。
- 文本消息发送与接收。
- 图片选择、压缩、上传、发送与预览。
- WebSocket 连接、心跳、断线重连。
- WebSocket 不可用时 3 至 5 秒轮询兜底。
- 发送中、发送成功、发送失败状态。
- 失败消息手动重试,防止重复发送。
- 商品上下文卡片发送。
- 订单上下文卡片发送。
- H5 与微信小程序兼容。
- 空状态、加载状态、错误状态和网络状态提示。
- 基础埋点和错误日志。
6.2 P1:建议紧随首期
- 表情面板。
- 从聊天页主动选择最近浏览商品。
- 从聊天页主动选择历史订单。
- 用户侧未读数量与已读回执。
- “客服正在输入”状态。
- 客服在线状态和服务时间提示。
- 小程序订阅消息或站内消息提醒。
6.3 本期不做
- 语音、视频和实时音视频通话。
- 多客服技能组、智能分配和排队系统。
- 机器人客服和知识库问答。
- 消息撤回、引用回复、群聊。
- 客服评价、投诉工单和 SLA 统计。
- 独立访客身份体系。
7. 信息架构
独立前台客服项目建议规划以下产品模块:
客服聊天页
├─ 顶部导航与连接状态
├─ 服务时间/系统公告
├─ 历史消息区
│ ├─ 文本消息
│ ├─ 图片消息
│ ├─ 商品卡片
│ ├─ 订单卡片
│ └─ 时间分隔与状态提示
├─ 场景上下文提示条
├─ 消息输入区
│ ├─ 文本输入
│ ├─ 图片选择
│ ├─ 表情入口(P1)
│ └─ 更多功能
├─ 商品选择面板(P1)
├─ 订单选择面板(P1)
└─ 图片预览
建议正式接入商城后的页面路由为:
/pages/customer-service/chat
建议作为分包页面注册,避免客服资源增加商城主包体积。
8. 核心用户流程
8.1 进入客服页
- 用户点击客服入口。
- 系统检查商城登录态。
- 未登录时跳转登录页,并记录客服目标页及场景参数。
- 登录成功后返回客服页。
- 页面从可信登录态获取当前用户,不从 URL 接收用户 ID。
- 加载最近一页历史消息和会话信息。
- 建立 WebSocket 并发送心跳。
- 若入口携带商品或订单上下文,在输入区上方展示待发送卡片,不自动发送。
8.2 发送文本消息
- 用户输入内容,空白内容不能发送。
- 前端生成本地消息 ID,立即在消息区展示“发送中”。
- 调用发送接口。
- 成功后用服务端消息 ID 替换本地状态。
- 失败后显示失败标识,点击可重试。
- 重试必须复用幂等键,避免网络超时导致重复消息。
8.3 发送图片消息
- 用户从相册选择图片或在 H5 选择本地文件。
- 校验格式、大小与数量。
- 客户端在支持的终端压缩长边和质量。
- 先上传到现有文件服务,获得 HTTPS 图片 URL。
- 再发送
contentType=2的客服消息。 - 上传或发送失败时允许重试。
- 首期每次最多选择 1 张,单张原图建议不超过 10 MB,压缩后建议不超过 2 MB。
禁止把大图片 Base64 长期写入 kefu_message.content。
8.4 发送商品卡片
- 从商品详情进入时携带
goodsId,不得在 URL 携带完整商品价格等可篡改展示数据。 - 客服页通过商品接口获取最新商品信息。
- 用户点击“发送商品”后发送
contentType=10。 - 卡片至少展示商品主图、名称、规格或价格、商品状态。
- 点击卡片返回商品详情;商品下架时显示“商品已失效”。
8.5 发送订单卡片
- 从订单场景进入时携带
orderId。 - 客服页通过有权限校验的订单接口获取当前用户的订单摘要。
- 用户确认后发送
contentType=11。 - 卡片至少展示商品主图、商品名称、订单号、金额和订单状态。
- 用户只能发送归属于自己的订单。
8.6 实时消息与恢复
- WebSocket 收到
kefu_message_type后按消息 ID 去重并插入列表。 - 收到
kefu_conversation_change后更新会话摘要。 - 收到
kefu_message_read_status_change后更新已读状态。 - 每 25 至 30 秒发送一次
ping,收到pong视为连接存活。 - 断线按 2、4、8、15、30 秒退避重连,最大间隔 30 秒。
- 应用切到前台时立即检查连接,并拉取断线期间的新消息。
- WebSocket 连续失败后启用 3 至 5 秒轮询;恢复连接后停止轮询。
9. 页面与交互要求
9.1 顶部区域
- 标题默认“在线客服”。
- 可展示“在线”“连接中”“网络异常”等连接状态。
- 服务时间由配置返回,不在前端硬编码。
- 微信小程序使用原生导航栏或自定义导航栏时必须适配安全区。
9.2 消息列表
- 客服消息居左,会员消息居右。
- 连续消息按时间间隔展示时间分隔,建议超过 5 分钟显示一次。
- 首次进入滚动到最新消息。
- 用户主动向上滚动时,新消息到达不得强制抢夺滚动位置,应显示“有新消息”按钮。
- 向上触顶加载更早消息,并保持加载前后的视觉位置。
- 文本必须换行并防止超长字符串撑破布局。
- 图片支持缩略图、加载占位、失败占位和全屏预览。
- 商品、订单卡片需要结构化解析失败兜底,不能因单条脏数据导致整页报错。
9.3 输入区
- 支持多行输入,最多显示 4 行后内部滚动。
- 文本长度上限首期建议 1000 字,与后端最终限制保持一致。
- 发送按钮仅在有有效内容时可用。
- 微信小程序需适配键盘顶起、底部安全区和
cursor-spacing。 - H5 需兼容 iOS Safari 软键盘造成的可视区域变化。
- 页面销毁时停止计时器、轮询和 Socket,防止重复连接。
9.4 状态反馈
- 首屏加载:骨架或明确加载状态。
- 无历史消息:欢迎语及常见咨询提示。
- 发送中:消息旁显示加载状态。
- 发送失败:红色失败标识与重试入口。
- 网络离线:顶部非阻塞提示,不清空输入内容。
- 登录失效:保存未发送草稿,重新登录后恢复。
10. 跨端兼容要求
| 能力 | H5 | 微信小程序 | 产品要求 |
|---|---|---|---|
| 页面实现 | uni-app 原生页面 | uni-app 原生页面 | 不使用 iframe 承载核心聊天 |
| 网络请求 | uni.request |
uni.request |
API 域名必须配置 HTTPS |
| WebSocket | uni.connectSocket |
uni.connectSocket |
不直接依赖浏览器 WebSocket 全局对象 |
| 图片选择 | H5 文件选择 | uni.chooseMedia/兼容接口 |
统一封装并限制大小 |
| 图片上传 | uni.uploadFile |
uni.uploadFile |
上传域名加入小程序合法域名 |
| 图片预览 | uni.previewImage |
uni.previewImage |
行为保持一致 |
| 键盘适配 | iOS/Android 浏览器 | 微信键盘与安全区 | 真机验收 |
| 返回行为 | 浏览器/uni 路由 | 小程序页面栈 | 从登录返回时恢复上下文 |
| 域名要求 | HTTPS/WSS | request/socket/upload 合法域名 | 发布前配置完成 |
微信小程序发布前必须在平台后台配置:
request合法域名。socket合法域名。uploadFile合法域名。downloadFile合法域名(如图片预览需要)。
测试环境建议使用 https://api.o.tbmall.xin 和对应 wss 地址;正式环境使用正式 API 域名。域名必须由环境配置注入,不允许散落硬编码。
11. 当前接口依赖
11.1 用户消息接口
| 功能 | 方法 | 当前路径 |
|---|---|---|
| 发送消息 | POST | /kefu/user/send |
| 查询会话和消息 | GET | /kefu/user/messages |
| 最近浏览 | GET | /kefu/user/browse-history |
| 交易订单 | GET | /kefu/user/orders |
| 记录商品浏览 | POST | /kefu/user/browse-record |
后端同时提供部分兼容路径,但新前台只使用一套规范路径,避免后续维护重复接口。
11.2 WebSocket
- 端点:
/ws/kefu或代理路径/api/ws/kefu。 - 当前会员连接参数:
userType=member、userId、mchId、conversationId。 - 心跳输入:字符串
ping。 - 心跳响应:
{"type":"pong"}。
当前事件类型:
| 事件 | 说明 |
|---|---|
kefu_connected |
连接建立成功 |
kefu_message_type |
新客服消息 |
kefu_conversation_change |
会话信息变化 |
kefu_message_read_status_change |
消息已读状态变化 |
11.3 消息类型
contentType |
类型 | content 建议格式 |
|---|---|---|
| 1 | 文本 | UTF-8 字符串 |
| 2 | 图片 | HTTPS 图片 URL |
| 10 | 商品卡片 | 版本化 JSON |
| 11 | 订单卡片 | 版本化 JSON |
商品和订单卡片建议增加 schemaVersion,并定义稳定字段,避免前后台各自猜测 JSON 结构。
12. 上线前后端必须补强项
以下问题不影响原型演示,但属于正式开发和上线的前置条件。
12.1 身份与数据权限(阻断上线)
当前用户接口允许客户端直接传 userId,且接口描述为免后台登录;WebSocket 也直接信任查询参数中的 userId。这会产生读取他人消息、订单或浏览记录的风险。
上线前必须:
- 用户接口强制校验商城
HSM-AUTH登录态。 - 后端从认证上下文取得会员 ID,忽略客户端提交的
userId。 - 会话、订单、浏览记录均按认证用户和商户双重校验。
- WebSocket 握手必须校验短期 token 或商城登录 token,并由服务端解析用户身份。
- 禁止仅通过
userType=member&userId=...建立会员连接。 - 限制允许来源,正式环境不应保持
AllowedOriginPatterns("*")。
12.2 历史消息分页(阻断完整体验)
当前消息按 ID 正序分页,直接请求第一页可能得到最早的 80 条而不是最新消息。需要提供以下任一方案:
- 游标分页:
beforeMessageId+limit,默认返回最新一页。 - 倒序查询最新消息,返回前端后再按时间正序展示。
接口还应支持断线补偿参数 afterMessageId,只拉取最后已知消息之后的数据。
12.3 幂等与消息状态
发送接口建议新增:
clientMessageId:客户端生成且在用户维度唯一。- 服务端唯一索引或幂等检查。
- 统一
createdAt服务端时间。 - 明确发送失败错误码。
12.4 用户侧已读
当前 readStatus 主要表达后台是否已读会员消息,不能完整表达会员是否已读客服回复。若 P1 要展示用户未读角标,需要新增用户侧未读数或双向已读字段及接口。
12.5 内容安全与限制
- 后端校验允许的
contentType。 - 文本长度限制并过滤危险 HTML,前端不得使用未净化的
v-html。 - 图片 URL 只允许可信 CDN/OSS 域名。
- 商品、订单卡片必须由服务端校验归属和关键展示信息。
- 按用户和 IP 做发送频率限制。
- 对恶意内容、重复刷屏和超大请求保留审计日志。
13. 前台项目技术边界
插件实现遵循:
- 技术栈与商城统一采用 uni-app,避免维护两套终端代码。
- 客服核心逻辑封装在
hashmall-customer-service组件中,由商城客服页直接承载。 - 请求层复用商城
HSM-AUTH与统一错误处理。 - Socket 层使用
uni.connectSocket封装单例连接。 - 不在组件内硬编码 API、WSS、用户 ID、商户 ID 或客服号码。
- H5 与小程序平台差异通过条件编译或适配器隔离。
- 公共请求、认证和上传能力直接复用宿主工程;平台差异由插件内部适配。
插件代码目录结构:
frontend-web/uni_modules/hashmall-customer-service/
├─ components/
│ ├─ hashmall-customer-service/
│ ├─ kefu-message-item/
│ └─ kefu-context-card/
├─ js_sdk/
│ ├─ api.js
│ └─ kefu-socket.js
├─ static/
├─ docs/
├─ package.json
└─ readme.md
14. 埋点与可观测性
建议埋点:
customer_service_entry_click:入口与场景来源。customer_service_page_view:页面打开成功。customer_service_ws_connected:连接耗时与重连次数。customer_service_message_send:消息类型、结果、耗时,不记录正文。customer_service_card_send:商品或订单卡片发送。customer_service_history_load:分页结果与耗时。customer_service_error:接口、Socket、解析、上传错误码。
日志和埋点不得记录 token、完整消息正文、订单隐私信息和图片内容。
15. 验收标准
15.1 功能验收
- 已登录用户能从“我的”、商品、订单三个场景进入客服页。
- 未登录用户被引导登录,登录后能返回原咨询场景。
- 首次进入能创建或恢复会话,并展示最新历史消息。
- 文本消息双向实时送达。
- 图片可选择、上传、发送、接收和预览。
- 商品和订单卡片可发送、正确展示并跳回相应详情。
- 发送失败可重试,网络超时不会生成重复消息。
- 向上滚动能连续加载更早消息且无重复、无跳动。
- WebSocket 断开后自动重连,断线消息能够补齐。
- WebSocket 不可用时轮询兜底可继续收取消息。
- 页面重复进入退出不会产生多个 Socket 或重复轮询。
15.2 安全验收
- 修改 URL、请求体或 Socket 参数不能访问其他会员数据。
- 失效 token 无法查询和发送消息。
- 用户不能发送不属于自己的订单卡片。
- 用户不能伪造商品关键字段欺骗后台客服。
- 非法消息类型、超长文本、非可信图片 URL 被后端拒绝。
15.3 兼容验收
- 微信开发者工具基础功能通过。
- 至少一台 iOS 微信真机和一台 Android 微信真机通过。
- iOS Safari 与 Android Chrome H5 通过。
- 键盘弹起、图片选择、后台切换、弱网和断网恢复通过。
- 小程序合法域名配置完整,正式包无“域名不合法”错误。
16. 实施阶段建议
阶段 A:接口收口与安全改造
- 用户接口改为从 token 获取用户身份。
- WebSocket 增加认证。
- 消息分页改为最新页/游标模式。
- 增加发送幂等字段。
- 固化商品、订单卡片协议。
阶段 B:独立前台客服 MVP
- 完成登录适配、聊天页、文本、图片、历史消息。
- 完成 WebSocket、心跳、重连、轮询兜底。
- 在 H5 和微信小程序独立联调。
阶段 C:商城场景接入
- 替换“我的”页电话弹窗和第三方客服 H5。
- 接入商品详情与订单详情上下文。
- 商品详情统一上报浏览记录。
- 完成小程序分包与合法域名配置。
阶段 D:灰度与上线
- 测试环境全链路验收。
- 小范围用户灰度。
- 观察连接率、发送成功率和错误率。
- 达标后全量替换旧客服入口。
17. 待产品与研发确认
- 首期是否只支持平台客服,还是区分平台客服、云仓客服和商家客服。
- 客服服务时间、非工作时间欢迎语及联系电话由谁配置。
- 商品和订单卡片是否纳入 P0。
- 是否需要用户侧消息未读角标和小程序订阅消息。
- 图片上传沿用哪个现有接口及 OSS/CDN 域名。
- 客服聊天记录保留期限和用户侧是否允许删除。
- 旧第三方客服系统是一次性替换,还是保留灰度开关。
- 独立项目最终以分包、源码模块还是私有组件包的方式并入商城。
18. 结论
现有后端与管理后台已经具备客服前台 MVP 所需的大部分业务基础,前台开发的主要工作集中在跨端聊天体验、可靠消息状态、Socket 生命周期和商城场景接入。
正式编码前应优先完成用户身份校验、WebSocket 鉴权和历史消息分页三项后端收口。否则即使前台页面能够运行,也不满足正式上线的数据安全和完整体验要求。