从Excel到自研CRM:客户管理系统设计与落地全过程复盘

发布时间:2026/9/20 5:33:15
从Excel到自研CRM:客户管理系统设计与落地全过程复盘 上周销售总监老周把我堵在工位上开口第一句就是“咱们那个客户表能不能别再让销售自己用Excel存了前天有人跟客户聊了俩小时今天换个人接手客户说了什么都没人知道。”他说的这个事其实我已经忍了很久。多个部门手里各有一份客户名单销售自己记跟进记录合同在商务那里签回款到账财务才反馈整个链条完全靠人在群里喊。就是在这种背景下我们决定从零做一套自己的客户管理系统名字就叫 DeskcommCRM把客户、线索、合同、回款、跟进记录全部收拢到一个系统里让销售、售前、财务、管理层看到的是同一个事实。这篇文章不打算写成产品发布会也不讲那种夸大到天上的“数字化转型”就是实打实聊聊这个系统从需求梳理、数据设计、权限划分到上线复盘的全过程。如果你也在考虑自研CRM或者正被现有系统难用得想换掉这篇值得你花十分钟看完。1. 从Excel到处飞的现状到 DeskcommCRM 立项1.1 项目最初要解决的三件事立项之前我们花了大概一周时间把公司现有的客户流转方式完整捋了一遍。真实情况比想象中还乱销售A手上有几十个客户的Excel表销售B觉得自己记在手机备忘录里更方便商务签完合同后把扫描件往共享网盘一丢财务回款后手工在财务软件里做一笔账。到了月底管理层想要看这个季度销售额是怎么构成的就得让几个部门分别汇报再找助理拼一张表。我当时的判断是问题绝对不是“缺一个数据库”而是缺一套能让所有人按同一套规则协作的工作流。所以 DeskcommCRM 要解决的第一件事是客户信息的唯一性。一个客户从线索到成交再到回款状态必须能在系统里连续跟踪。第二件事是跟进过程的可回溯性。就算销售离职、客户交接后来的人打开系统就能看到之前跟对方聊过什么、承诺过什么、价格谈到哪一步。第三件事是回款与合同的联动。合同签了不等于钱到了系统必须按月把应收、已收、逾期拆开让财务不用再追着销售问“那张合同到底开了多少票”。这三件事看着简单实际做起来牵涉的岗位和流程非常广。销售关心的是操作快不快别让我录一堆没用的字段管理层关心的是数据准不准别让报表成了摆设财务关心的是和现有开票流程怎么对接。这些诉求长期是互相拉扯的如果一开始不把优先级定清楚后面每做一个功能都会有人提意见。1.2 为什么没买现成CRM其实在决定自研之前我们正经评估过几家市面上的CRM产品。价格从每人每年几百到几千的都有功能从销售漏斗到营销自动化都很全。但最后都没选原因有三。第一数据打通成本高。我们内部已经有一个ERP系统管库存和采购财务软件管开票和到账小型CRM很难直接跟这两套系统做好双向同步。如果买回来还是靠人工导出再导入那就等于换了个Excel。第二定制审批流太慢。客户价格折扣超过某个比例要走审批不同级别销售的权限差异很大这些规则在外部系统里要么不支持要么需要提工单等排期。对于只有几十人的团队等厂商响应的时间太不可控。第三长期订阅费用并不低。按50人算一年下来几万块是起步价后面加模块还得另外算。与其每年付费还不如花几个月的开发成本做一套完全贴合自己的。当然自研绝不是因为市面上产品不好而是我们的业务流程足够垂直个性化需求足够多。如果你的团队只有五个人买现成的肯定更划算。但当我们已经有专职运维、有开发人手而且后续想把CRM跟企业微信、呼叫中心、电子签都接到一起自研就成了一条更能积累资产的路径。1.3 自研边界怎么划立项之后最容易犯的错就是把边界划得太大。当时也有同事说干脆把ERP、OA、客服工单全做进去反正都是后台系统。我坚决反对。CRM的核心价值在“客户关系”不是“全公司系统”。凡是跟客户、线索、合同、回款没有直接关系的诉求这次一律不做。最后我们定下的边界是模块本期范围明确不做客户管理客户档案、联系人、归属、公海池客户评级算法线索管理线索录入、分配、跟进记录外部线索自动爬取合同管理合同台账、审批、归档合同文件电子签回款管理回款计划、实收登记、逾期预警对接银行流水自动匹配报表看板销售漏斗、回款概览、个人业绩自定义BI可视化这个边界让我们在开发时少吵了很多架。遇到需求先问一句“是不是这期范围”不是就直接放进需求池大大缩短了需求评审的周期。2. 核心数据模型的设计客户、线索、合同到底怎么串起来2.1 线索池与客户表的转换关系几乎所有CRM都会区分“线索”和“客户”但很多系统的区分方式特别别扭。有的系统里线索被当成一种客户状态结果查询客户列表时还要把线索过滤掉有的系统线索转客户要复制一份数据客户ID变了历史跟进记录全丢了。DeskcommCRM 在设计上没有复制而是用一张leads表和一张customers表中间通过customer_id字段建立关联。线索刚进来时只有名字、电话、来源渠道、备注。销售跟进后如果判断对方有真实需求就点按钮“转为客户”。这里的本质不是新建一条客户记录而是把线索表的同一行数据状态改成已转化然后再在客户表创建一条对应记录并把主客户ID写回线索表。这样线索的历史跟进记录、原始来源、首次创建时间都还能查到同时客户表可以独立维护更完整的公司信息、行业分类、所在地区。这个设计解决了实际中特别常见的“老板问这个客户从哪个渠道来的”这种问题。没有线索表承接的话客户表里就只有一条冷冰冰的信息根本说不清是广告推广来的还是老销售转介绍来的。有了关联即便一条线索被退回公海重新分配原来的转化路径也还在。2.2 合同回款拆分逻辑合同和回款是CRM数据模型里最容易翻车的地方。一开始我们差点按“一个合同一年回款一次”的简单逻辑来设计后来说了一下实际业务发现完全不行。有的合同总金额五十万约定分三期回款每期数字不一样有的合同金额不大但客户要求每季度对账年年续签还有的合同附带设备款和服务费税率不一样开票科目也不一样。所以我们的表结构做了三层contracts合同主表只管合同编号、客户、总金额、签订日期、生效日期contract_installments回款计划表按每期拆字段有期数、应收金额、计划回款日期、实际回款日期、回款状态receipts实收回款表记录每一笔实际打款关联到具体的回款计划期数。这样做的好处非常直观。月底财务想看下个月有哪些钱应该到账不需要去翻合同原件直接查回款计划表里状态为待回款且计划日期在下个月的记录。销售跟进欠款客户也能看到对方到底逾期了多久是第一期没给还是第一期给了第二期没给沟通时心里有底。数据表拆干净之后后续做统计报表就只是简单的GROUP BY问题不需要在业务代码里做复杂的内存运算。2.3 字段设计的减法原则在设计字段时我们内部有个强约束业务字段必须由使用方解释“这个字段填了之后谁看、看了做什么决定”解释不出来就不做。很多CRM做得难用就是因为字段太多销售每天光填表就要花半小时。DeskcommCRM 客户表最终只保留了以下核心字段:客户名称、客户编号客户状态潜在/跟进中/已成交/暂停合作客户等级A/B/C所属行业、客户规模人/年营收区间归属销售、归属部门最后跟进时间、下次计划跟进时间线索来源字段少了以后录入成本大幅下降。销售在外面用手机也能很快补完一次跟进记录本次沟通内容、下一步计划、下次跟进时间。这三个字段是我觉得整个系统里最值钱的设计因为它把“销售动作”变成了“可管理的数据”。3. 权限模型与一线销售的日常体验3.1 基于角色的权限边界权限设计是CRM里最敏感的部分。客户数据直接关系到销售的个人业绩如果一个销售能随便看别人客户的报价和跟进记录后期的抢单纠纷会非常严重。我们采用了“角色 数据范围”的双层模型。角色主要分五类普通销售、销售主管、商务、财务、管理员。数据范围分三个层级本人可见、本部门可见、全公司可见。普通销售只允许看到自己名下和公海池里的客户销售主管可以看到本部门所有客户但不能越级看到其他部门商务能看到全公司合同和回款数据但跟进的客户详情有限制财务只看到回款计划和实收记录不关心跟进内容管理员拥有全部权限但操作日志全程留痕。这个模型有一个容易被忽视的点公海池的客户算“公开可见”但销售一旦领取就会变成个人客户其他销售立刻不可见。如果设计成“客户状态为公海时公开展示领取后隐藏其他字段”在并发时很容易出现两个销售同时点领取、系统不提示就都以为成功的情况。我们的做法是在领取接口里用了数据库行锁加载客户记录时加FOR UPDATE确保同一时刻只有一个销售能领取成功。3.2 客户转移与公海回收规则客户不是永远属于一个销售的。现实中有人离职、有人调岗、有人连续二十天不跟进一个高意向客户这些都需要一套自动流转规则。DeskcommCRM 里的转移分两种手动转移和自动回收。手动转移由销售主管发起填写接手人原销售会收到通知表示这个客户已经不再跟了。自动回收由系统定时任务扫描如果客户归属一个在职销售但超过20天没有新增跟进记录客户状态也不是已成交那么系统自动把客户移入公海池同时清掉原归属人。这里有一个值得注意的细节回收前不是直接清掉归属而是先给原销售发提醒第15天提醒一次第18天再提醒一次第20天才真正回收。直接把客户夺走销售大概率会投诉而且确实可能有客户在跟进中但销售忘了在系统里记录的情况。给了缓冲期之后销售要么补记录要么主动说明原因申请保护这样喷子就少了。3.3 移动端和企微提醒的接入大部分销售不会老老实实坐在电脑前录数据他们白天在外面跑客户晚上回来才补记录。所以DeskcommCRM从第一天起就做了移动端适配不过没有做原生App而是把Web端做成了响应式页面同时接入了企业微信。企业微信接入解决两个问题一是登录员工不用单独记一套账号密码扫码直接用企业微信身份进来二是提醒客户到了生日、跟进任务到时间、合同即将到期都会通过企业微信应用消息推给相关销售。很多同事说以前是领导催着记跟进现在是系统到点提醒感觉像有个助理在后面拿着小鞭子。这里要特别注意企业微信的消息推送有频率限制不是想发多少就能发多少的。同一个用户一分钟内最多接收几条我们最开始没做收敛一次批量任务直接发了几十条提醒给一个销售结果被限制了好几个小时。后来在推送服务里加了限流队列每人每五分钟最多收到三条多余的消息合并成一条摘要体验一下子好多了。4. 自动化引擎跟进任务、到期提醒、回款预警是怎么跑起来的4.1 定时任务不是越小越频繁越好CRM 里有一堆定时任务自动回收公海、发送跟进提醒、检测合同逾期、生成日报汇总。很多人的第一反应是把任务频率设到每分钟跑一次觉得这样最实时。但实际跑起来会发现问题每分钟扫描全表数据库压力大不说消息还容易被重复发送。我们的做法是把任务按时效分成三档秒级任务只处理用户主动触发的异步操作比如导入Excel后解析文件、批量分配客户分钟级任务处理公海回收和逾期检测默认每10分钟跑一次小时级任务处理统计报表和推送汇总每天凌晨两点跑一次全量数据快照。这样既保证了关键动作足够及时又不会让MySQL整天忙于低效的全表扫描。具体到公海回收这个任务SQL不能写得太大而全。我们会只捞取“上次跟进时间小于20天前且状态不等于已成交”的客户主键带上索引用游标分批处理每批100条。处理时还要再判断客户是否在保护期内、是否正被某个审批占用避免误回收。4.2 提醒消息的去重与触达优先级平时再好的功能如果消息满天飞也会被用户当成骚扰。DeskcommCRM 的提醒设计从一开始就遵循一个原则能合并的不单独发能少发的不多发。去重的核心是一个notifications表每条提醒对应一个唯一键例如follow_up_20240617_customer_123_sales_45。如果同一销售、同一客户、同一类型、同一自然日已经有记录就不会重复生成新记录。这样即使用户下午又改了一次下次跟进时间也不会给同一客户发两条提醒。触达优先级我们分成了三级高优先级是回款逾期这直接影响公司现金流必须通过企业微信消息加应用内红点双重触达中优先级是合同即将到期、跟进超时未记录低优先级是每周销售简报、客户生日问候。高优先级的消息由定时任务触发中低优先级的消息统一在每天早上九点半聚合发送。这个时间段是销售刚开始工作的时候打开率明显比下午高。4.3 事件驱动的埋点统计报表要准光靠查业务表是不够的。比如我们想统计“销售从线索到成交平均花了多少天”如果只看最后的客户表根本看不出中间等待了多久。所以 DeskcommCRM 内部加了一套轻量级事件表lead_events记录每个线索的关键时间点创建、分配、首次跟进、转为客户、创建合同、签署回传、首次回款。每次这些动作发生业务代码就顺手写一条事件带时间戳和当前操作人。后续统计“平均转化周期”“平均成交周期”的时候直接按客户维度取最早事件和最晚事件的差值非常方便。这个设计不用引入大数据的消息队列也不复杂但价值很大。后来我们甚至基于这套事件流做了个最简单的“销售漏斗”:线索数、有效跟进数、转客户数、签约数。漏斗每一层都能看出人员效率差距哪个环节掉链子一目了然。5. 技术选型与部署中的几个关键决策5.1 后端框架与数据库选型DeskcommCRM 后端选了 Go框架用的是 GinORM 用的 GORM。选 Go 的原因很直接团队里有人熟部署简单资源占用低而且它处理并发任务的能力强。我们并没有刻意追求高并发因为CRM这类系统在线用户也就一两百QPS 很低但它需要稳定、好运维。Go 编译出来就是一个二进制文件丢到服务器上就能跑比 Node.js 那一堆依赖要省心得多。数据库用了 MySQL 8.0。选它没什么悬念关系型数据模型非常适合CRM业务。表数量整体不多核心业务表一开始就控制在二十张以内。设置字符集时特意用了 utf8mb4因为客户的备注里经常有表情符号。之前吃过这个亏用 utf8mb3 存不进去报错报了半小时我才反应过来。所有的业务表都保留了created_at、updated_at和deleted_at。deleted_at是软删除用来实现回收站功能。这个字段在查询时需要特别注意GORM 默认会在查询条件里自动加上deleted_at IS NULL但如果你写了原生 SQL一定要记得手动过滤否则看到被别人删掉的数据就很奇怪。5.2 缓存、文件存储与搜索Redis 在系统里承担了三件事记录登录会话状态、缓存客户列表的常用查询结果、做限流计数。CRM 的实时性要求没有电商高缓存策略可以很粗暴。客户详情页每次打开时先查Redis没有就拿MySQL数据并回填缓存设置5分钟过期。这样在高频访问时段数据库压力能降一半以上。文件存储这块最初用本地磁盘挂载后来因为要支持多人同时上传合同附件就迁移到了 MinIO。用 MinIO 主要是兼容 S3 协议以后要是换到对象存储厂商代码不用大改。合同文件上传时我们做了两个处理一是限制单个文件不超过 20MB避免超大PDF拖慢接口二是上传成功后生成一个唯一文件ID不把文件路径直接暴露给前端防止有人拼接路径越权下载。搜索用了 MySQL 的全文索引还是 Elasticsearch我们选了后者但只在客户名和备注搜索时使用。倒不是说MySQL不行而是Elasticsearch部署起来也不复杂而且后续可能要对接全文搜索的知识库或工单系统留个口子更灵活。索引同步用最简单的方式业务代码里改动客户信息后异步提交一次索引更新。刚开始偶尔会有索引和数据库不一致的情况后来加了个每小时校准的定时任务问题就很少了。5.3 部署、备份和监控部署方案非常朴素两台云服务器一台跑应用和消息队列一台跑MySQL和Redis。反向代理用Nginx应用直接监听容器的8080端口。虽然用了Docker但没有上Kubernetes因为对几十个人的团队来说Kubernetes的维护成本已经超过了它带来的好处。在服务器上直接docker-compose up -d最省事出了问题也能快速重启。备份是我特别想强调的一点。CRM 里的客户数据是公司核心资产丢不起。MySQL 每天凌晨全量备份一次备份文件传到对象存储保留最近30天。另外开启binlog这样万一全量备份之间的数据出问题还可以做时间点恢复。我建议大家全部加上数据库主从复制就算没有读写分离的诉求多一台只读从库也能在高风险操作前手动备份快照。监控用的是 Prometheus Grafana主要看三个指标应用接口的P95延迟、MySQL慢查询数量、服务器磁盘空间使用率。CRM虽然不复杂但也没有必要等到用户投诉报错了才知道系统挂了。部署完这套监控后有一次磁盘差点写满提前三天收到告警避免了事故。6. 上线后的真实数据、问题复盘与下一步方向6.1 首月启用率与大家最常用功能DeskcommCRM 正式上线第一个月我们没有做强制任务只是把原有的Excel模板停掉规定客户信息一律以系统为准。两周后看后台数据60多个销售里已经有53个人产生了有效操作启用率接近九成。最常用的功能不是“客户管理”而是“跟进记录”和“公海池”。跟进记录使用率高的原因很实在以前销售交接客户时全靠互相问现在系统里直接能看见上一手的想法和承诺省了很多沟通成本。公海池使用率高的原因也很简单销售可以通过这个池子自己捡客户不用每次找主管审批。系统里能看到哪些客户被收回、为什么被收回过程透明大家心里都服。从事件数据统计出来的销售漏斗看线索转客户率大约35%客户转合同率约22%合同到首次回款平均周期是18天。这些数据在以前Excel时代根本统计不出来唯一能做的是财务年底拿一张总表蒙着头看。现在管理层终于可以说清楚“我们的转化卡在了哪一环”。6.2 被吐槽最多的三个点上线后不是没有怨言吐槽最集中的有三个。第一个是数据迁移不干净。从旧Excel导进系统的时候有些客户名是简称、有些备注里有特殊符号导致导入后列表看着很乱。这个锅我们认当时图快只做了简单的清洗就直接导库结果销售刚开始用的时候需要自己花时间整理。正确做法应该是先给销售一个“数据确认清单”让数据负责人做第一轮清洗再交给销售修正。第二个是移动端体验一般。响应式页面在手机上能用但表格和按钮都不如原生App顺手。尤其在弱网环境下上传图片和保存记录经常转圈。后来我们做了离线缓存草稿销售在没网的地方填完内容联网后自动补提交这个功能救了不少人。第三个是权限太严了。我们最初按“本部门可见”设计结果销售想参考兄弟部门的报价方案时被挡住了导致他们觉得系统阻碍协作。这个问题的本质是权限和协作之间的平衡。后来我们增加了一种“共享只读链接”销售可以主动把某个客户分享给部门内同事查看但分享行为会被记录避免数据被批量导出。6.3 下一步想做的功能跑顺了核心流程之后我个人的判断是接下来不要再堆功能而是把数据利用起来。第一优先级是做一个“客户健康度”模型把最近跟进间隔、合同回款逾期情况、沟通频次作为输入给每个客户打一个分数。得分低的客户系统提醒销售重点关注得分高的客户可以尝试让他做续费或转介绍不用再靠感觉。第二优先级是把电子签接入合同流程。现在合同签回还是先扫描上传再人工录入状态中间多一步。如果能在线完成电子签合同状态、到期时间都能自动更新回款计划也能自动创建能省掉不少人工。第三优先级是做一个可配置的报表中心。现在的报表虽然能看但所有维度都是写死的产品、区域、行业这些字段全换就要改代码。后面我打算把常用维度做成配置项让运营和财务能自己拖拽组合遇到临时统计就不用来回找开发了。这次做 DeskcommCRM 给我最大的感受是系统好不好用不在于功能多不多而在于它是不是贴着业务流长出来的。很多企业在选型时只看厂商功能清单结果买回来一堆用不上的模块我们从自己最痛的三件事出发一点一点磨到上线却是每一步都踩在真实需求上。如果你也在规划自研CRM别急着写代码先花时间把客户流转这条链路的细节画出来数据模型能少建一张表就少建一张表字段能少填一个就少填一个。能让人坚持用下去的系统才是好系统。