简介
本技术文档围绕 DouPHP 小程序“在线聊天”能力,系统梳理从前端页面到后端接口、再到数据模型与服务层的完整实现。重点覆盖:
- WebSocket 连接管理(接入点与生命周期)
- 消息收发机制(发送、接收、状态同步)
- 会话列表管理与历史记录查看
- 聊天页架构设计(消息队列、断线重连、状态同步)
- 用户体验优化(发送动画、已读标记、输入框自适应等)
- 开发示例(即时通讯集成、多消息类型、群聊扩展)
- 常见问题与解决方案(网络异常、消息丢失恢复、性能优化)
项目结构
小程序端采用 pages 分层组织,聊天相关页面包括:
- 对话页:chat.wxml / chat.ts
- 应用中心(会话入口):list.wxml / list.ts
- 历史会话:history.wxml / history.ts
后端提供 API 控制器用于聊天业务,以及管理后台的会话与消息模型和服务层。
graph TB
subgraph "小程序端"
A["对话页<br/>chat.wxml / chat.ts"]
B["应用中心<br/>list.wxml / list.ts"]
C["历史会话<br/>history.wxml / history.ts"]
end
subgraph "API 服务"
D["聊天控制器<br/>api/controller/chat/ChatController.php"]
E["用户控制器<br/>api/controller/chat/UserController.php"]
end
subgraph "管理后台"
F["会话控制器<br/>admin/controller/chat/SessionController.php"]
G["会话模型<br/>admin/model/chat/ChatSession.php"]
H["消息模型<br/>admin/model/chat/ChatMessage.php"]
I["会话服务<br/>admin/service/chat/SessionService.php"]
end
B --> D
A --> D
C --> D
D --> E
F --> G
F --> H
F --> I
图表来源
- miniprogram/default/pages/chat/chat.wxml:1-52
- miniprogram/default/pages/chat/list.wxml:1-25
- miniprogram/default/pages/chat/history.wxml:1-25
- api/controller/chat/ChatController.php
- api/controller/chat/UserController.php
- admin/controller/chat/SessionController.php
- admin/model/chat/ChatSession.php
- admin/model/chat/ChatMessage.php
- admin/service/chat/SessionService.php
章节来源
- miniprogram/default/pages/chat/chat.wxml:1-52
- miniprogram/default/pages/chat/list.wxml:1-25
- miniprogram/default/pages/chat/history.wxml:1-25
核心组件
- 对话页(chat)
- 工具栏:模型选择、会话抽屉开关、新建会话
- 消息区:滚动渲染、打字态提示、系统消息样式
- 输入区:文本输入、发送按钮、停止生成按钮
- 应用中心(list)
- 展示可用聊天应用列表,支持进入具体应用
- 历史会话(history)
- 列出历史会话摘要(标题、应用名、消息数、Tokens、更新时间),支持跳转到应用中心
这些页面通过小程序事件绑定驱动交互,并在逻辑层(.ts)中调用 API 完成数据获取与状态更新。
章节来源
- miniprogram/default/pages/chat/chat.wxml:1-52
- miniprogram/default/pages/chat/list.wxml:1-25
- miniprogram/default/pages/chat/history.wxml:1-25
架构总览
整体采用“小程序前端 + API 后端 + 管理后台”的分层架构。小程序负责 UI 与交互,API 层处理聊天业务(会话、消息、鉴权等),管理后台提供会话与消息的持久化与统计能力。
sequenceDiagram
participant U as "用户"
participant P as "小程序对话页<br/>chat.ts"
participant A as "API 聊天控制器<br/>ChatController.php"
participant S as "会话服务<br/>SessionService.php"
participant M as "消息/会话模型<br/>ChatMessage/ChatSession"
U->>P : 点击发送
P->>A : 发送消息请求
A->>S : 创建/追加消息
S->>M : 写入数据库
M-->>S : 返回结果
S-->>A : 组装响应
A-->>P : 返回消息或流式片段
P->>P : 渲染消息/打字态
Note over P,A : 后续可接入WebSocket推送增量消息
图表来源
- miniprogram/default/pages/chat/chat.wxml:33-50
- api/controller/chat/ChatController.php
- admin/service/chat/SessionService.php
- admin/model/chat/ChatMessage.php
- admin/model/chat/ChatSession.php
详细组件分析
对话页(chat)
- 工具栏
- 模型选择器:切换不同 AI 模型
- 会话抽屉:显示当前应用的会话列表,支持切换
- 新建会话:创建新会话并清空本地消息
- 消息区
- 滚动容器:按 index 定位滚动位置
- 消息渲染:区分用户/AI/系统消息;支持 typing 态
- 输入区
- 输入框:支持回车发送
- 发送按钮:触发发送流程
- 停止生成:中断正在进行的生成过程
flowchart TD
Start(["进入对话页"]) --> LoadApp["加载应用信息"]
LoadApp --> InitSession{"是否存在当前会话?"}
InitSession --> |是| LoadHistory["拉取历史消息"]
InitSession --> |否| NewSession["创建新会话"]
LoadHistory --> Render["渲染消息列表"]
NewSession --> Render
Render --> Input["等待用户输入"]
Input --> Send{"点击发送?"}
Send --> |是| CallAPI["调用发送接口"]
CallAPI --> ShowTyping["显示打字态"]
ShowTyping --> Stream{"是否流式返回?"}
Stream --> |是| AppendMsg["追加片段并滚动到底部"]
Stream --> |否| FinalMsg["渲染最终消息"]
AppendMsg --> Done(["完成"])
FinalMsg --> Done
Send --> |否| Input
图表来源
- miniprogram/default/pages/chat/chat.wxml:33-50
章节来源
- miniprogram/default/pages/chat/chat.wxml:1-52
- miniprogram/default/pages/chat/chat.ts
应用中心(list)
- 展示应用列表,包含图标、名称、描述、付费标识
- 点击条目进入对应应用对话页
章节来源
- miniprogram/default/pages/chat/list.wxml:1-25
- miniprogram/default/pages/chat/list.ts
历史会话(history)
- 展示会话摘要:标题、应用名、消息数、Tokens、更新时间
- 空状态引导至应用中心
章节来源
- miniprogram/default/pages/chat/history.wxml:1-25
- miniprogram/default/pages/chat/history.ts
后端 API 与管理后台
- API 聊天控制器:统一处理聊天相关请求(如发送消息、获取会话列表、读取历史等)
- 用户控制器:处理与用户相关的聊天权限与配额校验
- 管理后台会话控制器:维护会话生命周期与聚合统计
- 会话/消息模型:定义数据结构与查询方法
- 会话服务:封装复杂业务逻辑(如消息落库、Token 统计、会话合并等)
classDiagram
class ChatController {
+发送消息()
+获取会话列表()
+读取历史()
}
class SessionService {
+创建会话()
+追加消息()
+统计用量()
}
class ChatSession {
+id
+session_sn
+title
+created_at
+updated_at
}
class ChatMessage {
+id
+session_id
+type
+content
+tokens
+status
}
ChatController --> SessionService : "调用"
SessionService --> ChatSession : "读写"
SessionService --> ChatMessage : "读写"
图表来源
- api/controller/chat/ChatController.php
- admin/service/chat/SessionService.php
- admin/model/chat/ChatSession.php
- admin/model/chat/ChatMessage.php
章节来源
- api/controller/chat/ChatController.php
- api/controller/chat/UserController.php
- admin/controller/chat/SessionController.php
- admin/service/chat/SessionService.php
- admin/model/chat/ChatSession.php
- admin/model/chat/ChatMessage.php
依赖关系分析
- 小程序页面依赖各自逻辑层(.ts)进行状态管理与 API 调用
- API 控制器依赖服务层与模型层完成业务编排与数据持久化
- 管理后台控制器服务于运营与统计需求,与模型/服务解耦
graph LR
P1["chat.ts"] --> API1["ChatController.php"]
P2["list.ts"] --> API1
P3["history.ts"] --> API1
API1 --> SVC["SessionService.php"]
SVC --> M1["ChatSession.php"]
SVC --> M2["ChatMessage.php"]
图表来源
- miniprogram/default/pages/chat/chat.ts
- miniprogram/default/pages/chat/list.ts
- miniprogram/default/pages/chat/history.ts
- api/controller/chat/ChatController.php
- admin/service/chat/SessionService.php
- admin/model/chat/ChatSession.php
- admin/model/chat/ChatMessage.php
章节来源
- miniprogram/default/pages/chat/chat.ts
- miniprogram/default/pages/chat/list.ts
- miniprogram/default/pages/chat/history.ts
- api/controller/chat/ChatController.php
- admin/service/chat/SessionService.php
性能考虑
- 消息渲染
- 使用滚动容器与按需渲染减少首屏压力
- 对长消息进行分页或虚拟列表优化
- 网络与并发
- 发送节流与去抖,避免重复提交
- 合理设置超时与重试策略
- 存储与缓存
- 本地缓存最近会话与消息片段,提升回看速度
- 对图片/文件进行压缩与懒加载
- 服务端
- 消息写入批量操作与索引优化
- 流式输出时控制分片大小,降低内存占用
故障排查指南
- 网络异常
- 检查 API 返回码与错误信息
- 实现断线重连与指数退避重试
- 消息丢失
- 基于 session_sn 与消息序号做幂等插入
- 客户端维护本地待发送队列,重连后补发
- 性能问题
- 监控首屏渲染时间与消息滚动卡顿
- 对大对象进行序列化裁剪与分页加载
- 鉴权与配额
- 校验用户身份与剩余配额,失败时给出明确提示
结论
DouPHP 小程序在线聊天功能以清晰的页面分层与前后端职责划分为基础,具备可扩展的消息体系与完善的会话管理能力。通过合理的渲染策略、网络容错与数据持久化方案,可在保证用户体验的同时支撑高并发场景。未来可进一步引入 WebSocket 实时推送、富媒体消息与群聊能力,以满足更丰富的业务需求。
附录
- 关键交互路径参考
- 发送消息:见对话页模板中的输入区与发送按钮绑定
- 会话切换:见工具栏的会话抽屉与切换逻辑
- 历史查看:见历史会话页面的列表渲染与跳转
章节来源
- miniprogram/default/pages/chat/chat.wxml:33-50
- miniprogram/default/pages/chat/history.wxml:5-20