朵米客服系统源码部署实战:PHP+ThinkPHP私有化客服系统搭建
发布时间:2026/10/22 8:34:13 锦皓数字建站

简介朵米3.5客服系统源码2023正式版是一套基于ThinkPHP开发的全功能客户服务解决方案专为企业搭建在线咨询、工单管理和多渠道客服入口设计能够与MySQL、Nginx等常见运行环境快速集成。系统内置智能分流、实时对话、消息记录、数据报表等模块可有效提升客服团队响应效率与客户满意度。该源码包共2000个文件压缩后约43.85MB以JavaScript、HTML、CSS等前端资源为主配合PHP业务逻辑、SQL数据库脚本、Shell部署脚本及Markdown文档覆盖从前台交互到后台数据管理的完整链路目录组织清晰便于二次开发。目前已有384人学习适合有一定PHP和MySQL基础的中级开发者。压缩包内还附带详细的安装搭建配置文档明确CentOS 7.6NginxPHP7.1-7.3环境要求并对运行目录、伪静态规则、数据库导入等关键操作给出指引可帮助使用者快速完成部署上线并投入生产。1. 朵米客服系统源码一套能直接跑起来的 PHP 客服中台2023 正式版的朵米客服系统源码本质上是一套基于 ThinkPHP 的 PHP MySQL 客服工作台压缩包里带完整前端样式、后台管理端和安装文档。它解决的问题很直接网站或 App 里的在线聊天、邮件工单、电话回拨统一排队后台能按客服在线状态和技能组自动分配会话还有一套会话量、响应时长、满意度报表。适合手里有服务器、想自己部署一套私有化客服系统又不想被 SaaS 客服厂商按坐席数收费的团队或开发者。我拆过几套类似源码这套的目录结构和文档算比较规整的按流程走基本不会卡在安装环节。2. 部署选型与依赖为什么固定 CentOS 7.6 宝塔 PHP 7.2 MySQL 5.7先说结论这套源码对环境版本非常敏感官方给的环境范围是 CentOS 7.6-7.9、宝塔面板、Nginx 1.18-1.22、PHP 7.1-7.3、MySQL 5.6-5.7。很多人在新服务器上习惯性装 PHP 8.0、MySQL 8.0结果安装完白屏或接口报错这不是源码坏了而是版本边界没卡住。这一章把技术栈构成和版本选型的逻辑讲清楚后面部署才不会翻车。2.1 从源码静态资源看技术栈ThinkPHP 5.x AmazeUI 前端框架打开压缩包的 CSS 文件列表能直接推断出这套系统的前后端技术构成。style.css 是站点主题样式amazeui.css 和 amazeui.min.css 是阿玛祖伊AmazeUI框架这是一个移动优先的 HTML5 跨屏前端框架说明客服工作台和访客端都做了响应式适配materialdesignicons.min.css 是 Material Design 图标库对应按钮和状态图标的渲染。bootstrap.min.css 在这里更多是作为兼容层存在因为 layui.css 同时也在列表里而 layui 通常用来渲染后台管理表格和弹窗组件。这个组合说明一件事访客对话窗口和管理后台用的是两套 UI 体系接口层统一走 ThinkPHP 的路由。你在改样式的时候要分清改的是哪一块不要全局覆盖 bootstrap否则后台列表排版会被 AmazeUI 的栅格规则干扰。前端静态资源带哈希后缀比如 app.ccaa54a563bd7edef54a4a5dbd192ae7.css说明源码在打包时已经执行过版本号处理直接上传即可用不需要重新构建前端。2.2 为什么是 PHP 7.1-7.3 而不是 PHP 7.4 或 8.0这套源码基于 ThinkPHP 5 系列开发从目录结构和数据库配置文件能确认这一点。ThinkPHP 5.0/5.1 在 PHP 7.4 开始会出现两个典型问题一是某些废弃函数如 each在 PHP 8.0 直接移除框架底层调用时直接 fatal error二是 PHP 7.4 之后对数组类型和函数的隐式转换做了更严格的限制源码中基于旧写法写的类型判断会抛出 notice 级别以上的异常。所以宝塔面板上创建站点时PHP 版本不要贪新直接选 PHP 7.2 或 7.3。我在实际部署中偏好 7.2因为 7.3 对某些编译扩展比如 fileinfo在部分宝塔版本上需要手动开启而 7.2 是所有扩展开箱即用的。如果你只有 PHP 7.4 可用短期能跑通安装但跑一段时间会出现客服会话记录写入失败、后台报表导出乱码之类的间歇性故障排查成本远高于切换版本。2.3 服务器硬件底线2核2G 5M 到底能撑多大并发官方要求服务器 CPU 2 核心以上、内存 2G 以上、带宽 5M 以上。这套组合的实际容量上限要心里有数PHP-FPM 常驻进程和 MySQL 5.7 的 InnoDB 缓冲池是内存占用大头2G 内存下 MySQL 缓冲池默认配置大概吃掉 400M-500M剩余内存跑 20 个 PHP-FPM 子进程刚好够用换算成同时在线客服大约 20-50 人取决于每个客服同时接待的会话窗口数。带宽 5M 的限制反而比 CPU 更容易踩。客服工作台是长轮询 消息推送机制每个打开的会话窗口会周期性拉取新消息如果访客端上传图片或文件5M 上行带宽会在高峰期被打满。我一般建议在 Nginx 层面对 /uploads 路径做静态缓存并把访客端的图片压缩放到前端处理这样带宽瓶颈能缓解不少。如果你们的客服团队超过 30 人建议直接上 4 核 4G 配置内存翻倍后 MySQL 和 PHP 的余量都宽裕很多。3. 部署全流程从压缩包到客服工作台的完整四步部署流程本身不复杂官方文档写得很简明上传解压、设置运行目录、配置伪静态、改数据库配置并导入 SQL。但每一步都有边界细节——运行目录为什么必须指向 public、伪静态规则要选哪种、SQL 导入用什么字符集这些才是真正让新手卡住的地方。这一章按完整流程走一遍每一步都给出可复现的命令和配置。3.1 上传解压与站点运行目录为什么入口在 public把压缩包通过宝塔文件管理器上传到站点根目录后常见做法是用 unzip 命令解压因为压缩包在 Windows 下解压再上传会丢失 Linux 文件权限位某些缓存目录会因为没有写权限而报错。cd /www/wwwroot/你的站点目录 unzip 朵米3.5客服系统源码2023正式版.zip chmod -R 755 . chmod -R 777 runtime # runtime 目录需要写入权限解压后能看到源码目录结构是 ThinkPHP 经典布局application 目录存业务逻辑public 目录是 Web 入口config 目录存配置。宝塔设置站点时要把「运行目录」从根目录切换到 /public这一步的本质是让 Nginx 的 root 指向 public避免用户直接访问到 application 目录下的 PHP 业务文件。如果不设置运行目录访问站点首页会直接列出目录结构或者报「No input file specified」这是第一个最容易翻车的点。3.2 Nginx 伪静态配置ThinkPHP 的 pathinfo 路由规则客服系统的访问地址依赖 ThinkPHP 的路由解析典型链接形如 /index/index/index 这种多级路径。Nginx 默认配置不会把 URL 中的路径信息传给 PHP所以必须配置伪静态规则。宝塔面板里选择「ThinkPHP」模板即可但有些版本面板的模板不带 if 判断需要手动核对。location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s$1 last; } } location ~ \.php$ { fastcgi_pass unix:/tmp/php-cgi-72.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }这段配置的逻辑是当请求的文件在磁盘上不存在时把整个路径重写到 index.php 并作为参数 s 传入由 ThinkPHP 解析出对应的控制器和方法。第一段 location 是伪静态核心第二段是 PHP 请求转发后面的 fastcgi_pass 后面的 sock 路径要和你宝塔上实际安装的 PHP 版本对应PHP 7.2 对应 php-cgi-72.sock如果你用的是 7.3 就要改成 73。改完伪静态记得重载 Nginx很多 404 问题其实是改了配置没 reload。3.3 修改 config/database.php 并导入 shujuku.sql数据库配置是部署的关键一步。打开压缩包里的 /config/database.php 文件把数据库连接信息改成你实际创建的值。这里的路径是相对于站点根目录的也就是 public 目录的上一级。?php return [ type mysql, hostname 127.0.0.1, database dumi_db, username dumi_user, password 换成你的强密码, hostport 3306, charset utf8mb4, prefix dumi_, ];数据库名、用户名、密码要和你在宝塔里创建的一致重点是 charset 保持 utf8mb4不要改成 utf8否则访客消息里带 emoji 表情时会写入失败。改完保存后导入根目录下的 shujuku.sql 文件mysql -u dumi_user -p dumi_db /www/wwwroot/你的站点目录/shujuku.sql导入前建议在命令行先执行 SET NAMES utf8mb4避免终端默认字符集导致 SQL 里中文数据变乱码。导入完成后可以用 mysql 客户端确认表数量一般这套系统有 40-60 张表覆盖客服账号、会话记录、排队队列、报表统计等模块。如果导入时报错注意看是不是重复导入导致的「table already exists」这种情况直接 drop 掉再重新导入即可。3.4 安装验证管理后台与客服工作台的入口数据库导入完成、伪静态生效后访问站点域名应该能看到客服系统的访客对话入口页面这是一个带在线聊天按钮的页面。接着访问 /admin 或 /manage 进入管理后台登录页具体入口以安装文档为准不同版本可能不同用 SQL 文件里预置的管理员账号登录。验证的重点有三个第一页面能正常打开且 CSS 加载完整说明伪静态和静态资源路径都对第二登录后台后能看到客服列表、会话监控、报表菜单说明数据库连接正常第三点开「在线客服」工作台页面确认左侧会话列表能加载出模拟数据或空列表而不报 500 错误。如果后台能进但接口报错先看 runtime 日志里的具体异常通常指向 PHP 扩展缺失或 Redis 配置未生效。4. 功能落地智能分流、多渠道接入与数据报表的配置口径部署跑通只是开始客服系统的核心价值在于分流逻辑、渠道接入和报表分析。这套源码的智能分流、多渠道支持、数据报表三个模块都有对应的后台配置项配置口径直接决定客服团队的日常使用体验。这一章结合源码结构讲清功能逻辑并给出配置和验证方法。4.1 智能分流规则按客服在线状态与技能组分配会话智能分流的本质是访客发起会话时系统从在线客服列表中筛选出符合条件的客服再按负载情况分配会话。源码中这一逻辑通常在 application 模块下的 service 层或 controller 层。分流条件一般有三个维度客服是否在线、客服所属技能组是否匹配、客服当前持有的会话数是否小于上限。后台配置中心里一般会有「最大接待会话数」参数默认单个客服同时接待 5-10 个会话。如果队列里超过上限访客会进入排队等待。这里有一个常见误区很多团队以为智能分流是自动把会话均匀分给所有在线客服实际上源码实现的是「优先分配空闲客服空闲则按最大会话数顺序分配」并不是严格均分。验证分流是否生效可以开两个浏览器窗口模拟两个访客同时发起会话观察会话是否被分配给不同客服。如果想查看当前客服负载可以直接查数据库SELECT agent_id, COUNT(*) AS active_sessions FROM dumi_session WHERE status active GROUP BY agent_id ORDER BY active_sessions ASC;这条 SQL 统计每个客服正在处理的活跃会话数按升序排列后排在前面的是空闲客服系统分流时理论上会优先把新会话配给这些账号。如果你的团队发现某几个客服总是被分配大量会话重点检查这些账号是否被勾选了「技能组全选」或「最大会话数」设置得过高。4.2 多渠道接入在线聊天、邮件与电话的统一排队机制多渠道支持是朵米客服系统的卖点之一访客可以从网页在线聊天发消息也可以发邮件进来电话渠道则是通过回拨网关接入。这三类请求最终都会汇聚到同一套客服工作台队列里客服不需要切换系统就能处理所有渠道的会话。网页在线聊天接入方式最简单直接在站点页面的 body 标签底部插入一段 JavaScript 代码script // 访客端聊天组件初始化app_id 在后台渠道管理中生成 (function() { var chat document.createElement(script); chat.src /public/js/chat.js; chat.setAttribute(data-app-id, 你的应用ID); document.body.appendChild(chat); })(); /script邮件渠道需要在后台填写 SMTP 服务器、端口、账号和授权码源码会用这些配置通过 IMAP/POP3 协议拉取邮件内容并生成工单。电话渠道一般对接第三方呼叫中心网关提供 API 回调地址源码收到回调后把通话记录挂到会话队列里。这一块配置完测试时要特别注意电话渠道的回调地址必须是外网可访问的公网 URL本地环境回调不通是正常的不是代码问题。4.3 数据分析与报告会话量、响应时长和满意度指标数据报表模块在后台「统计报表」菜单下主要展示三个维度会话量趋势、客服响应时长、满意度评分。源码报表的数据来源是会话记录表每次会话关闭时会写入结束时间、响应时长平均值、访客评价分数。如果团队需要自定义报表可以直接对数据库做统计比如查最近 7 天每日会话量SELECT DATE(create_time) AS day, COUNT(*) AS total_sessions FROM dumi_session WHERE create_time DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY DATE(create_time) ORDER BY day ASC;这里 create_time 的时区是 PHP 配置的默认时区如果服务器是 UTC 时间而你在北京时间使用报表统计会偏移 8 小时。部署时记得在 php.ini 里把 date.timezone 设置为 Asia/Shanghai否则日报数据对不上业务时段。5. 朵米 3.5 部署避坑五个高频问题与定位方法这套源码我在多台服务器上部署过也帮别人排查过不少问题。下面五个坑基本覆盖了从安装到日常运行的各个阶段前三个是安装期的致命问题后两个是运行期的隐性故障。每条按「现象 → 原因 → 解决」梳理排查时直接对照就能少走弯路。5.1 安装后首页 404前端路由全部打不开现象访问站点域名显示 404 Not Found直接在浏览器输入 /index.php 才能打开页面所有链接点击后都报错。原因Nginx 伪静态未生效或配置不正确。大多数情况下是宝塔面板里选择了错误的伪静态模板或者改完配置没有重载 Nginx。解决确认站点运行目录指向 public伪静态模板选择 ThinkPHP然后手动检查配置文件里是否有if (!-e $request_filename)这一段。如果模板里只有 rewrite 规则没有 if 判断需要手动补上。改完执行nginx -t验证配置无错误后 reload再刷新页面。5.2 导入 shujuku.sql 时报错或导入后中文乱码现象mysql 命令导入 shujuku.sql 报 ERROR 1064 或 ERROR 1366又或者导入成功后登录后台看到的中文都是问号和乱码。原因SQL 文件里有 utf8mb4 编码的数据但导入客户端的默认字符集不是 utf8mb4导致多字节字符写入失败或存储异常。解决导入前执行SET NAMES utf8mb4;然后用source方式导入进入 mysql 客户端后执行 source 路径。如果已经导入了乱码数据先 drop 掉所有表重新导入不要尝试在现有表上做字符集转换因为字段的 collation 也已错乱转换很容易丢数据。5.3 PHP 版本不对导致登录后台白屏或提示控制器不存在现象安装界面能打开但进入后台登录页时白屏或者提示「控制器不存在」「方法不存在」。查看 runtime 日志发现大量 PHP 错误。原因站点使用了 PHP 7.4 或 PHP 8.0ThinkPHP 5 旧版框架对高版本 PHP 的兼容性问题集中爆发尤其是函数引用和数组操作方式不兼容。解决在宝塔站点设置里切换 PHP 版本为 7.2 或 7.3切换后强制刷新页面。同时删除 runtime 目录下的缓存文件rm -rf runtime/*因为旧的编译缓存里可能记录了错误的框架路径。这一条也是很多人在新服务器上最容易踩的坑看到 PHP 8.0 就想装新的反而导致整个框架跑不起来。5.4 后台修改了客服分配规则前端却不生效现象在后台把「最大接待会话数」从 10 改成 3保存后测试发现新会话还是被分配给已经有超过 3 个会话的客服。原因ThinkPHP 的配置缓存机制。后台修改的配置项被写入数据库或配置文件后框架层有 cache 存在 runtime 目录下未及时更新导致读取的还是旧值。解决删除 runtime/cache 和 runtime/temp 目录下的缓存文件或者在后台「系统设置」里如果有「更新缓存」按钮则优先点击。改配置后没有清理缓存是这类系统里最常见的「改了个寂寞」场景排查时先清缓存再测避免误判成代码逻辑问题。5.5 客服端总是收不到新会话消息现象访客端发消息后显示发送成功但客服工作台这边没有任何提示刷新页面才能看到新会话。原因消息推送是长轮询机制客服端每隔几秒请求一次新消息接口。如果 Nginx 超时时间设置过短或者服务器防火墙拦截了长连接前端拿不到消息推送。解决检查 Nginx 配置里 proxy_read_timeout 和 fastcgi_read_timeout 是否大于 30 秒如果长轮询间隔是 10 秒超时时间至少设置到 60 秒。同时确认客服工作台页面的控制台没有 WebSocket 连接报错有的版本用的是 WebSocket 实时推送这种情况要额外在安全组放行对应端口一般是 2050 或 2120具体要查源码配置。放行端口后重开客服工作台页面即可重新建立推送通道。6. 二次开发实战把「空闲优先」分流改成「最少会话优先」源码默认的分流逻辑是「优先分配空闲客服」但实际运营中团队会遇到一个典型问题某几个客服响应速度快、处理效率高会话总是被优先分配其他客服闲着手头却没活。我们项目里就遇到这个情况后来决定改成「最少会话优先」策略——新会话永远分配给当前活跃会话数最少的客服不考虑是否刚处理完上个会话。定位分流代码在 application 模块的 service 层通过后台设置的分配规则找到分配客服的核心方法。常见做法是在该方法里查出一批在线客服再按某个条件排序取第一个。默认实现通常是对在线状态和空闲状态做筛选负载值只作为过滤条件而不是排序条件。修改方案是在排序处加入 usort 函数按当前会话数升序排列// 修改前按在线状态顺序取第一个客服 $agent $onlineAgents[0]; // 修改后按活跃会话数升序排序后取第一个客服 usort($onlineAgents, function($a, $b) { return $a[active_sessions] $b[active_sessions]; }); $agent $onlineAgents[0];这段代码的逻辑很简单把候选客服数组按 active_sessions 字段升序排列然后取数组第一个元素。active_sessions 需要在上一步的查询中统计出来每个客服对象返回时带上这个字段。如果你的数据库查询是聚合查询直接在 SQL 里用 ORDER BY active_sessions ASC 更高效不需要额外在 PHP 里排序。修改完成后要验证效果清空 runtime 缓存用两个不同的访客窗口同时发起会话观察分配结果——如果两个会话分别分配给当前负载为 0 的两个客服说明改动生效。如果仍然分配给同一个客服检查排序后的数组是否被后续逻辑重新洗牌有的版本在取完第一候选后会做随机打散防止排队倾斜需要把 usort 调整到打散逻辑之后。从那以后我每次改分流逻辑都强制走一遍固定流程先查数据库统计会话负载再改代码最后清缓存验证分配结果三步缺一不可。这种系统级改动最怕的就是改了代码没有清缓存导致测试时看到的还是旧行为白白浪费时间排查。如果你也在调整这套客服系统的分流策略按这个流程走会省掉不少冤枉路。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。