
1. 项目起源为什么我要折腾一个叫 DeskcommCRM 的东西先说结论DeskcommCRM 是我自己从零搭的一套轻量级客户管理系统核心就三个词——客户资料集中管、跟进记录不断档、团队协作不靠吼。如果你也是那种客户一多就混乱、跟进全靠微信聊天记录、每周靠翻手机回忆上次跟这个客户说到哪了的销售或小团队管理者这个系统就是冲着解决这些问题去的。先说下我自己的背景。我既不是大厂架构师也不是专业运维就是一家十来个人的小公司的业务负责人带着三个销售和两个客服。几年下来客户的联系方式、报价记录、合同进度、售后问题全散落在 Excel 表格、企业微信聊天记录和纸质笔记本里。最痛苦的是业务员离职客户关系直接断层有同事休个假回来根本不知道某个客户之前聊到什么阶段月底想统计一下销售转化率得靠人工去翻聊天记录翻到怀疑人生。市面上不是没有现成的 CRM 工具我当时也试用过不少。但问题也很现实免费的 SaaS 版功能阉割严重客户量稍微上来一点就要付费付费版一年上千甚至几千对一个小团队来说是一笔实打实的支出而最让我犹豫的是数据完全放在别人服务器上客户资料这种核心资产万一平台政策调整或者账号出问题想导出都麻烦。就是在这样的背景下我决定自己动手做一个——这就是 DeskcommCRM 的由来。这篇文章我会把整条路走一遍从需求梳理、方案选型到技术实现、部署上线再到实际使用中的各种坑和解决方案全部展开讲。内容对完全没有技术基础的读者也友好术语我会用大白话解释如果你本身就是搞技术的可以直接跳到第 3 章看架构设计和代码实现那里有你最关心的东西。2. 需求梳理先搞清楚要什么再做系统2.1 核心需求拆解我和团队真正缺的是什么动手之前我花了大概两周时间把团队所有人的日常动作观察了一遍也逐一问了一圈你希望有个什么东西来帮你管客户。汇总下来需求其实非常集中就是下面这四件事客户资料统一管理不光是姓名、电话、公司还包括来源渠道、所属行业、客户状态潜在、跟进中、已成交、已流失以及最重要的是——跟进历史。跟进记录和提醒谁在什么时间跟进了哪个客户聊了什么下一步计划是什么下次跟进时间是什么时候。到点了系统要主动提醒不能让销售凭记忆。团队协作和数据权限客户不是一个人的是公司的。但不同角色能看什么、能改什么要有区分。比如普通销售只能看自己的客户主管能看全组老板能看全部。数据统计和可视看板成交了多少、每个销售的跟进量、客户转化率、本月新增客户数。光有数据不够还得有直观的展示不然月底写总结还是靠拍脑袋。这些需求看起来简单但实际操作中你会发现一个隐藏前提系统必须永久在线。所谓永久在线不是指你电脑开机它就能用而是指不管你在公司、在家、还是出差在外打开浏览器输入网址就能访问数据实时同步不用装客户端也不用担心关机了别人用不了。这就决定了它是一个 Web 应用而不是本地软件。2.2 免费 CRM 与自建系统怎么选算清楚这笔账在决定自建之前我认真比较过三条路直接用免费 CRM、买商业 CRM、自己搭一个。我拿了一张表把优劣势列出来对比方案前期成本长期成本数据控制权功能灵活性维护负担免费 SaaS CRM零功能受限升级付费完全在平台方只能用它给的功能零商业付费 CRM几千元/年按坐席逐年付费数据在服务商手中支持定制但往往要加钱零自建系统一台服务器域名服务器租金约几十元/月完全自主可随时备份导出想加什么功能随时加需要自己维护看到这里你可能发现了自建的最大代价不是钱而是维护负担。你得自己搞定服务器、数据库、安全更新、数据备份。但对我来说这笔账是划算的服务器一年租金几百块比一个商业 CRM 坐席一年的钱还少而数据在自己手里备份、导出、迁移都是我说了算功能上我还能按团队的脾气随时改。还有一个很容易被忽略的点商业 SaaS 产品为了覆盖更多客户功能越做越重页面层级非常多每天录入客户信息要点五六次鼠标。而自建系统可以做到极简几个核心字段一遍页就录完了这对每天要录大量客户资料的销售来说体验差别是巨大的。DeskcommCRM 的第一个原则就是输入路径最短。3. 技术选型和整体架构设计3.1 技术栈的选择逻辑不追新只求稳说实话作为一个小型业务系统技术选型最大的忌讳就是为了用新技术而用新技术。团队要的是稳定、能改、有现成生态而不是炫技。DeskcommCRM 最终选择了非常成熟的一套组合后端语言PHP8.x原因是部署最简单、资料最多、虚拟主机都能跑后期换任何服务器都无缝迁移。数据库MySQL5.7 以上客户数据是典型的关系型数据用 MySQL 的生态最成熟备份、优化工具一堆现成的。前端原生 HTML JavaScript 少量 CSS 框架不引入前端工程化那套复杂构建流程。系统核心是表单和表格原生能力完全够用还省去了 node_modules 的烦恼。部署方式云服务器 Nginx PHP-FPM域名走 HTTPS 加密访问。这套组合不新潮但有一个非常实际的好处任何能装 Nginx 和 PHP 的服务器都能跑将来把整个系统迁移到另一家云服务商打包搬过去就行完全不受某家云厂商的绑定。3.2 数据库设计客户、跟进、用户的三角关系DeskcommCRM 的核心数据表非常克制就三张主表加两张辅助表customers客户表id、name、phone、company、source来源渠道、industry行业、status状态、owner_id负责员工、created_at 等字段。follow_ups跟进记录表id、customer_id、user_id、content跟进内容、next_time下次跟进时间、created_at。这张表是系统的灵魂每一条跟进记录都按时间线挂在对应客户下面。users用户表id、username、password_hash、real_name、role角色admin / manager / sales。reminders提醒表id、user_id、customer_id、remind_time、is_done。用于实现到点提醒跟进功能。operation_logs操作日志表记录谁在什么时候新增、修改了哪个客户的什么字段。排查问题全靠它。为什么要单独拆一张 follow_ups 表而不是直接把跟进内容塞在客户表里因为一个客户会有几十条跟进记录如果都放在客户表里客户表会膨胀得厉害而且查询某条跟进记录时要把整个客户信息一起捞出来性能会很差。拆成两张表之后客户信息查一次跟进记录按customer_id索引查询每次打开客户详情页只要一条 SQL 就能把所有历史记录按时间倒序取出来。这是最基础的关系型数据库设计思路成本低效果好。3.3 永久在线的实现部署方案与注意事项永久在线不是玄学它由三个层面决定部署层面系统跑在云服务器上而不是某台电脑上。云服务商有电力和网络保障只要不欠费它就一直在线。配置不用高我用的 2 核 2G 内存的机器带十来个人日常使用绰绰有余。域名和 HTTPS 层面绑一个自己的域名配置 SSL 证书让团队访问的是https://crm.yourdomain.com这样的地址而不是裸 IP。好处是稳定、安全、好记浏览器也不会提示不安全。数据备份层面永久在线不等于数据不丢。我设置了每天凌晨自动备份数据库备份文件保留最近 7 天定期下载到本地。数据备份这事儿我后面会专门讲这是整个系统里最容易出问题也最容易忽略的地方。4. 核心功能实现与操作实录4.1 客户管理模块让录入成为一件快事客户管理是 CRM 的底座如果这一步用着别扭整个系统就会被弃用。我在设计录入界面时只有一个标准一个客户从打开页面到保存成功最快只需要三步——打开新增客户、填表、点保存。表单字段控制在必填 3 项姓名、电话、来源其余全部选填。实操中发现一个很关键的细节电话号码唯一性校验必须做。以前用 Excel 的时候同一个客户被录两条甚至三条跟进时各记各的月底盘点才发现重复。系统里我专门对phone字段加了唯一索引重复录入时直接弹出提示同时允许合并客户操作把两个重复客户的跟进记录合并到一条。每天高频使用的客户搜索功能也花了不少心思。销售来找客户时往往只记得一个电话号码前几位或者一个公司简称。我把搜索框做成了全文模糊匹配输入任意关键词只要客户的姓名、电话、公司、备注里任一字段包含这个关键词就能搜出来。这就意味着哪怕只记得张工或者尾号 1234也能一秒定位到目标客户。体验上是质的提升。4.2 跟进记录与提醒把凭记忆变成按流程跟进记录是整个 DeskcommCRM 最核心的功能也是和 Excel 差别最大的地方。过去在 Excel 里写跟进要么新建一列要么在备注里追加时间一长格式一团糟根本谈不上时间线的概念。现在每次跟进操作流程是这样的在客户详情页点击新增跟进填写跟进内容比如客户对 A 方案感兴趣要求下周出详细报价选择跟进方式电话 / 微信 / 上门拜访 / 邮件如果还有下一步动作设置一个下次跟进时间。系统会自动记录这条跟进的创建人和创建时间并按时间倒序排列在客户详情页里。这样打开任何一个客户他的完整来龙去脉一目了然第一次电话是什么时候、中间因为报价搁置了多久、最后是怎么谈成的全在时间线上。销售休假回来五分钟就能接上之前的进度。下次跟进时间这个字段被单独抽出来每天早上 9 点系统会自动把当天需要跟进的客户推送到每个销售的今日待办里。这就是团队协作的核心不需要任何人在群里喊别忘了跟进谁系统本身就是那个永远不睡觉的提醒器。4.3 团队管理怎么把员工加进系统这也是一个使用频率极高的操作。系统上线之后老板或者管理员要做的第一件事就是把员工加进来。具体流程我写一下照着做即可用管理员账号登录系统进入系统设置 → 用户管理点击新增用户填写员工姓名、设置初始登录密码选择角色销售sales只能看见和操作自己名下的客户主管manager可以看见全组客户管理员admin拥有全部权限保存后把分配的登录账号和初始密码发给员工员工用浏览器打开系统网址即可登录员工首次登录后在个人设置里修改自己的密码并完善手机号便于找回密码。权限模型我做得比较朴素但有层级客户表里有一个owner_id字段它决定了客户归属普通销售查询时自动带WHERE owner_id 当前用户id主管和管理员不执行这个过滤。曾经有同事问如果客户转给另一个销售怎么办实操中的做法是在客户详情页提供转移负责人按钮转移后自己的待办里就不再出现这个客户新负责人接手所有跟进记录完整保留客户不需要重新说一遍需求。这一点对项目型团队尤其重要换人交接的时候客户体验不会断。4.4 数据看板让月底汇报不再靠翻聊天记录数据统计是我后期加的一个模块但使用频率意外地高。看板分两层个人层每个销售登录后能看到自己本月的新增客户数、跟进次数、已成交数、成交率。销售可以随时自检是不是这个月跟进量下降导致成交没跟上。管理层主管和老板看到的是一张汇总视图包含全公司各销售维度的表现对比、线索渠道分布、客户状态分布潜在 / 跟进中 / 已成交 / 流失。看板的数据实现并不复杂就是定时跑几条 SQL 聚合查询。比如本月各销售新增客户数就是SELECT owner_name, COUNT(*) FROM customers WHERE MONTH(created_at) 当月 GROUP BY owner_id。这类统计对数据库压力很小数据量在几万级别时毫秒级返回不需要引入大数据那套东西。5. 部署上线从零把系统跑起来的完整流程5.1 服务器与域名准备如果你没有技术基础最省心的方式是买一台云服务器。以腾讯云、阿里云这些主流的云厂商为例新用户轻量应用服务器一年经常有优惠2 核 2G 内存 40G 硬盘的配置跑一个小型 CRM 绰绰有余。操作系统选择 Ubuntu 22.04 或者 CentOS 7 都行我习惯用 Ubuntu。域名注册之后做一个 A 记录解析把crm.yourdomain.com指向服务器的公网 IP。这里有一个规律解析生效之后用浏览器访问这个域名能 ping 通服务器就算成功了一大半。5.2 服务器环境安装与系统部署我把关键的命令写到这里给大家一个可以直接照抄的版本# 更新软件源 sudo apt update sudo apt upgrade -y # 安装 Nginx、PHP 及常用扩展、MySQL sudo apt install -y nginx php-fpm php-mysql php-mbstring php-curl mysql-server # 启动服务并设置开机自启 sudo systemctl enable nginx sudo systemctl enable mysql sudo systemctl start nginx sudo systemctl start mysql # 数据库创建进入 MySQL 后执行 CREATE DATABASE deskcomm_crm DEFAULT CHARACTER SET utf8mb4; CREATE USER crm_userlocalhost IDENTIFIED BY 这里写一个强密码; GRANT ALL PRIVILEGES ON deskcomm_crm.* TO crm_userlocalhost; FLUSH PRIVILEGES;把 DeskcommCRM 的程序文件上传到/var/www/deskcommcrm目录然后配置 Nginx 站点。配置文件的要点是让所有请求都走 PHP 解析核心部分长这样server { listen 80; server_name crm.yourdomain.com; root /var/www/deskcommcrm/public; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.1-fpm.sock; } }最后记得用 Certbot 申请免费的 SSL 证书实现 HTTPS 访问sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d crm.yourdomain.com证书自动续期配置好就不用管了。整个过程熟练的话半小时内能搞定。系统首次访问会自动进入安装向导填好数据库连接信息和管理员账号密码就能开始使用。5.3 每日自动备份忘了什么都不能忘了这个这是我最想强调的一节。系统跑起来之后最可怕的事情不是功能设计得不好而是硬盘坏了或者手误删了数据库。没有备份所有客户数据、跟进记录、团队劳动成果瞬间归零而且无法挽回。我的做法是一个简单的 shell 脚本挂在系统 crontab 里每天凌晨 3 点执行#!/bin/bash BACKUP_DIR/data/backup/deskcommcrm DATE$(date %Y%m%d_%H%M%S) mysqldump -u crm_user -p密码 deskcomm_crm $BACKUP_DIR/db_$DATE.sql find $BACKUP_DIR -type f -name *.sql -mtime 7 -delete这个脚本做了什么每天把数据库完整导出一份到一个以日期命名的 SQL 文件里同时自动删除 7 天前的备份防止磁盘被占满。我还额外做了一步每周手动把备份文件下载到本地网盘实现异地备份。正所谓鸡蛋不能放在同一个篮子里数据也一样。6. 常见问题与排查经验实录系统上线半年我遇到的坑不少但真正有代表性的问题集中在下面几个我整理成了一张速查表现象可能原因解决办法登录后空白页PHP 缺少某个扩展如 mbstring查看 Nginx 错误日志按提示安装缺失扩展上传的客户资料有乱码数据库字符集不是 utf8mb4建库时明确指定 DEFAULT CHARACTER SET utf8mb4某个销售看不到客户列表该客户的 owner_id 不是当前用户用管理员账号在客户详情页执行转移负责人早上收不到待办提醒服务器未配置定时任务crontab 里加入待办推送脚本每天 9:00 执行数据库越来越慢数据表缺索引给 customers.phone、follow_ups.customer_id 加索引手机浏览器访问排版混乱未设置响应式或未引入移动端样式引入简单的响应式 CSS或为常用页面做移动端适配这里挑两个最典型的问题展开讲一下。第一个是登录后空白页。这个问题的排查路径非常标准先看 Nginx 的错误日志/var/log/nginx/error.log再查 PHP-FPM 的日志/var/log/php8.1-fpm.log。我的情况是 PHP 的mbstring扩展没装字符串处理函数全部失效程序直接挂了。安装扩展后重启 PHP 服务就恢复正常。遇到这种问题先不要慌按日志排查是最快的。第二个是早上收不到待办提醒。当时我以为代码有问题查了一上午最后发现是服务器时区是 UTC和北京时间差了 8 个小时。脚本每天早上 9 点执行但实际上在服务器本地时间只是凌晨 1 点。解决方法是把服务器时区设成Asia/Shanghaisudo timedatectl set-timezone Asia/Shanghai这类问题很有代表性很多诡异的问题根源都是环境配置而不是业务代码本身。所以在新服务器上部署时我第一件事就是统一时区和字符集这两项基础配置。7. 给后来者的一些建议最后说几句掏心窝的话。DeskcommCRM 从立项到上线用了不到两周但从能用到好用我断断续续调整了快两个月。这两周的开发和两个月的打磨让我对整个事情有了几层很深的体会。第一工具只是工具落地才是关键。再好的系统如果团队不愿意用就是个摆设。我做的第一版界面很简陋但销售们还是愿意用为什么因为录入和查询真的比 Excel 快快就是最大的动力。后来我所有的功能迭代都优先考虑能不能让使用路径更短而不是功能够不够多。第二数据比功能值钱。我见过有人花了大量时间纠结 CRM 的某个统计图好不好看却从没做过一次数据备份。系统跑着跑着最值钱的就是里面积累的客户关系和跟进历史这些是花钱买不来的。所以永远记得备份。第三不用一步到位。DeskcommCRM 从第一天能跑起来到现在也只是把客户管理、跟进提醒、团队权限、数据看板这四件事做扎实了。很多业务上的新需求比如对接企业微信、做自动报表推送都是后面逐步加进去的。如果你也想自建一套系统我的建议是从最小的可用版本开始先把客户不丢、跟进不断这件事跑通再慢慢生长。我踩过最深的坑不是技术问题而是在最开始花了很多时间纠结要不要找一个完美的现成方案。事实证明没有完美的方案适合自己团队体量的就是最好的方案。DeskcommCRM 这套思路和代码你也可以完全复刻甚至在这个基础上改得比我的更好。只要它真的能帮你把客户管好、把跟进做好这件事就值得做。