ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从Excel到自建轻量私有CRM:客户管理实践全记录

从Excel到自建轻量私有CRM:客户管理实践全记录 提到客户管理系统很多人第一时间想到的是Salesforce、销售易这类重型平台功能全、配置复杂、实施周期长。我今天要聊的DeskcommCRM则是一个完全相反的东西——它是我从零搭起来、带着一个小销售团队用了一年多的轻量私有CRM核心只有一句话把销售桌面上的客户资料、通信记录和跟进待办收拢到一个地方。如果你正被“客户信息散落在Excel、手机、聊天记录和一堆便利贴里”这件事折磨或者团队规模不大但又不想被SaaS月费绑架那这篇文章里从设计表结构到踩坑排查的全过程应该能给你不少参考。文章会比较实操向涉及数据库字段、消息规则、软电话对接、权限模型这些具体环节也会写清楚我为什么在每一步做那样的取舍。1. DeskcommCRM到底是什么为什么我坚持桌面端为主的客户管理1.1 从名字拆解产品定位Desk Comm CRM先说名字。DeskcommCRM这个词拆开就是Desk、Comm、CRM三段。Desk表示“桌面”不只是说它跑在电脑上而是强调“坐席工作台”这个使用场景——销售每天上班打开电脑就能看到今天该联系谁、哪些客户到了跟进日期、谁的通话还没补结论。Comm是Communication的缩写对应通信能力电话录音、通话弹屏、邮件记录、即时沟通摘要这些在传统CRM里往往是独立模块但在DeskcommCRM里是贯穿所有业务的主线。CRM则是客户关系管理的底座客户档案、商机阶段、成交数据都沉淀在上面。这个定位一开始就不是“给老板看报表的管人系统”而是“帮销售少记点事的工作台”。传统CRM最大的问题在于系统默认销售愿意主动录入数据。但实际上绝大部分销售最讨厌打字填表电话打完还要去系统里新建跟进记录时间一长就敷衍了事。DeskcommCRM的思路是反过来把通信行为变成自动记录让销售只补一句结论就行。这样客户动态不是靠人敲出来的而是从每一次真实沟通里长出来的。另一种取舍是移动端优先。很多产品喜欢搞一个App让销售随时掏出手机录客户。但在实际操作中销售的核心动作——打电话、回邮件、写报价、填合同——基本都在电脑前完成。手机端更适合在拜访现场临时查资料而不是成为主要录入端。所以DeskcommCRM桌面端是完整能力移动端只做了查看待办、接收提醒、审批和简单备注。这个选择让开发量大幅下降也让数据质量稳定了很多因为主录入通道只有一个用户不需要在不同屏之间来回倒腾。1.2 从Excel到CRM我遇到的三类痛点当时想自建这套系统不是因为公司买不起现成的CRM而是团队此前用Excel管客户暴露出来的问题已经明显影响业务了。第一个痛点是数据断裂。客户资料分散在销售个人电脑的Excel里、企业通讯录里、邮件签名里、手机通讯录里。老板问“上海区域这个季度到底接触了多少客户”没人能给准确数字。部分销售自己记录得详细但格式五花八门有人把客户等级写在备注栏有人把下次跟进时间写在一个黄色单元格里还有人在文件名里加日期表示“最新版”。这些习惯一旦换人接手基本等于资料作废。第二个痛点是交接断层。销售离职时公司能拿到的只有一份Excel。可这份Excel里往往只有客户名称、联系人和电话没有历史沟通记录、没有报价背景、没有关键决策人的偏好。新接手的人面对陌生客户只能硬着头皮重新电话开场很多客户就是这样被“丢”掉的。更麻烦的是有些老销售会把客户信息存在私人聊天记录里人一走信息也跟着走了。第三个痛点是跟进无闭环。Excel里就算写了“下次跟进时间”也没有人能保证那天真的会跟进。销售靠脑子和便利贴记待办忙起来必然漏。没有系统层面的提醒和统计主管也很难知道一个销售手头到底有多少客户到了该联系的日子。DeskcommCRM要解决的就是这三件事数据有固定结构、沟通有历史沉淀、跟进有系统提醒。2. 核心业务模型设计客户档案、跟进记录与商机流转2.1 客户表字段设计先定好唯一标识任何CRM最先要定的都是数据模型不是界面。DeskcommCRM第一版把模型控制在“客户、联系人、跟进记录、商机”四个核心实体没有一开始就上复杂的订单和库存体系。客户表我做了这样的设计CREATE TABLE customers ( id BIGSERIAL PRIMARY KEY, customer_no VARCHAR(32) NOT NULL UNIQUE, company_name VARCHAR(200) NOT NULL DEFAULT , contact_name VARCHAR(100) NOT NULL DEFAULT , mobile VARCHAR(30), work_phone VARCHAR(30), email VARCHAR(200), region VARCHAR(50), source VARCHAR(50), owner_id BIGINT, status VARCHAR(30) NOT NULL DEFAULT leads, level SMALLINT NOT NULL DEFAULT 0, last_contact_at TIMESTAMPTZ, next_follow_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), version INTEGER NOT NULL DEFAULT 1, deleted_at TIMESTAMPTZ, remark TEXT );这里面有几个设计是踩过坑之后才补上的。第一个是customer_no这是客户在系统里的唯一业务编号不用自增id的原因是后续要打印、导入导出、跨系统对接用一个带规则的编号比“12345”这种纯数字更直观。第二个是mobile和work_phone分开很多To B公司一个联系人既有手机又有固话混在一个字段里会导致搜索和电话匹配困难。第三个是version字段这是乐观锁用来解决多人同时编辑一个客户时互相覆盖的问题后面我会单独讲。还有一个容易忽略的点是deleted_at软删除。一开始我认为物理删除最省事后来才发现销售误删客户、主管想找回历史记录都是高频需求。改为软删除后列表页默认过滤掉deleted_at非空的数据但管理员后台还能看到被删记录也能一键恢复。历史数据不能丢这在CRM里是一条铁律因为客户关系本身就是企业资产删了就真的没了。关于手机号是否要设为唯一索引我建议是不要。因为同一个号码可能属于一个客户下的多个联系人也可能客户注销后重新分配给新的企业联系人。如果强制唯一导入历史数据时就会大量报错。正确的做法是建立普通索引在“搜索客户”时用电话号码快速匹配而不是把电话号码当作主键。2.2 跟进任务机制如何让销售不再漏跟踪客户档案建完之后另一个关键就是跟进记录。这段是DeskcommCRM使用频率最高的模块因为每一次和客户的实质接触都会落在这里。跟进记录表我采用了偏事件流的结构CREATE TABLE follow_up_logs ( id BIGSERIAL PRIMARY KEY, customer_id BIGINT NOT NULL, owner_id BIGINT NOT NULL, contact_type VARCHAR(20) NOT NULL, contact_time TIMESTAMPTZ NOT NULL DEFAULT now(), summary TEXT NOT NULL DEFAULT , status VARCHAR(20), call_duration INTEGER, recording_url TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() );contact_type我取了call、email、onsite、im、other这五类分别对应电话、邮件、拜访、即时聊天、其他。这个枚举不要轻易扩展类型越少报表统计越干净。比如“微信语音”本质上也是call“微信文字”可以归为im销售不需要纠结分类系统才能得到一致的统计口径。跟进任务的核心不在表结构而在规则。DeskcommCRM里有一个自动待办引擎规则是这样的每次电话结束或邮件发出后系统自动为这条客户记录生成一条“待补充跟进结论”的待办如果后续补了summary待办自动消除。客户等级为A的48小时内必须再次联系B级7天内C级30天内系统每到临界点就会在桌面端弹提醒。实际上待办提醒能不能起作用要看提醒的打扰程度。刚开始我们设置成每5分钟弹一次结果销售烦到直接静音整个应用。后来改成每天早上9点推送“今日应联系清单”下午4点推送“今日未完成跟进提醒”只推两次反而大家都在用。销售不是不愿意跟进而是需要有人在合适的节点帮他把待办摆到眼前。2.3 商机阶段与“公海回收”规则客户从线索到成交中间会经过多个状态。DeskcommCRM预设了一条状态流leads新建线索- contacted已联系- qualified意向明确- proposal方案/报价中- won成交- lost流失。很多人觉得这个状态流太死板销售想怎么点就怎么点。我坚持要做状态机约束因为如果销售可以随意从leads跳到won那主管看到的转化率就是假的。实际实现时DeskcommCRM在后台定义了每个状态的可达切换比如从leads只能到contacted或lost不能直接到won。只有主管角色可以强制纠偏普通销售没有越级变更权限。公海机制是这个模块里最实用的设计。所谓公海就是一个所有销售都能看到但不能随意认领的客户池。规则是这样的客户在某个销售名下超过30天没有产生任何跟进记录系统自动释放到公海公海里被销售认领后7天内必须至少有1次有效跟进否则自动退回公海。这个规则彻底解决了“占着客户不干活”的问题也让沉睡客户能重新被激活。有人会问公海会不会导致销售互相争抢客户实际上不会因为认领公海客户时系统会记录认领时间同一批客户短时间内只能被同一个人认领有限次数而且是先到先得。从运营效果上看公海机制让团队多产出了不少“捡回来的客户”很多客户并非没有需求只是原负责销售没有及时跟进被释放后换个销售重新接触反而有了新机会。3. 实现路线与关键技术选型本地优先的私有部署3.1 为什么我没直接采购SaaS而是自建在很多情况下买一个成熟的CRM是最快、最省心的方案。但当时我选择自建DeskcommCRM有几个非常具体的理由。第一是数据敏感度。客户电话、报价记录、合同金额这些数据公司管理层明确希望留在自有服务器上不想放在公有云SaaS平台。很多行业客户也会问“你们的数据存在哪”如果销售自己都没法回答这个问题会直接影响信任度。私有部署意味着数据资产完全可管控备份、迁移、销毁都有明确路径。第二是定制成本。市面上的CRM功能很多但真要落地到“通话弹屏”“按团队规则自动释放公海”“桌面端提醒”这些场景多数产品要么不支持要么在高阶版本里。真等采购流程走完业务需求可能都变了。自建虽然要投入开发人力但胜在逻辑可控想调整规则随时改代码。第三是长期费用。按坐席收费的SaaS几十人的团队一年下来也是笔不小的支出。私有部署的软件侧成本主要集中在初期开发硬件一台服务器就够了。当然自建也意味着要自己面对备份、升级、故障恢复这些运维问题没有免费的午餐。如果团队里完全没有专职技术人员我其实不建议走自建这条路。DeskcommCRM这套方案更适用于公司内部已有一定研发能力、希望把客户数据掌握在自己手里的团队。自主研发不是目的数据可控和流程适配才是。3.2 技术栈、目录规划与核心依赖DeskcommCRM的技术栈并不花哨桌面端用Electron Vue 3后端用Python FastAPI数据库用PostgreSQL缓存和任务队列用Redis部署用Docker Compose。这套组合在当时很成熟社区排障资料多团队也熟悉没必要为了追求新框架去冒风险。选Electron而不是纯Web最主要的原因是桌面提醒和来电弹屏。浏览器网页在最小化时定时器会被后台挂起通知能力也受限Electron则可以常驻系统托盘来电时通过主进程拉起置顶窗口这个体验比浏览器标签页稳定得多。代价是安装包体积大、内存占用高但公司内网电脑配置普遍不差可以接受。项目目录结构大致是这样的deskcomm-crm/ ├── client/ # Electron Vue3 桌面端 │ ├── src/ │ └── build/ ├── server/ # FastAPI 服务端 │ ├── app/ │ ├── models/ │ └── api/ ├── worker/ # 定时任务与提醒队列 ├── migrations/ # 数据库迁移SQL ├── scripts/ # 数据导入、号码清洗 ├── deploy/ │ ├── docker-compose.yml │ └── nginx.conf └── docs/为什么要把server和worker分开因为跟进提醒、公海释放、数据归档这类定时任务不能塞在API进程里跑。FastAPI主进程如果被一个长时间运行的报表查询拖住会导致接口响应慢。worker独立进程消费Redis任务队列既不影响API性能也方便单独扩容。这个拆分大概只有几十行代码的额外成本却让系统稳定性和可维护性高了一个档次。PostgreSQL是这套系统里我最不担心出问题的部分。它的JSONB字段在保存灵活配置时很好用比如客户等级、来源这类枚举值调整不需要频繁改表。事务能力和并发控制也可靠CRM里大量涉及“认领客户”“修改归属”这类操作一旦并发出错就是客户归属纠纷数据库层面必须顶住。3.3 通信集成的实现思路软电话弹屏与话单沉淀DeskcommCRM跟传统CRM拉开差距的关键模块就是通信集成。我们的方案是自建PBX基于Asterisk通过AMI接口与CRM对接。这套架构简要说的话销售在系统里绑定自己的分机号客户来电时PBX产生一个呼叫事件携带主叫号码CRM服务端收到事件后用号码去客户表里匹配匹配成功就把这个客户的资料和全部历史记录推送到桌面端弹窗。弹屏只是表面功能更重要的价值是通话结束后自动生成一条话单。通话时长、通话时间、录音文件URL一并写入follow_up_logs销售只需要在弹窗里补一句“客户对XX方案有兴趣下周三再联系”。如果没有自动话单销售很可能打完电话就忘了记录手工补录的积极性会随着电话数量增加急剧下降。关于怎么发起外呼我建议用回拨模式而不是在浏览器里做WebRTC软电话。回拨的操作是销售在CRM里点击呼叫按钮后端调用Asterisk的Originate动作Asterisk先呼叫这个销售的分机销售接起来后Asterisk再呼叫客户号码。两边接通后系统开始录音。这个模式的优点是音频质量稳定、不依赖电脑麦克风也避开了浏览器音频设备授权、回声消除、断线重连这些乱七八糟的问题。号码归一化是通信模块最容易踩的坑。同一个客户可能在Excel里存成“138 0013 8000”在话机里显示为“8613800138000”在微信里记录成“13800138000”。如果不做归一化来电弹屏就很难稳定匹配。我写了一个清洗函数统一去掉空格、横杠、括号区号统一补全手机号统一转成E.164格式。这个函数虽然不起眼但它是弹屏准确率的重要保障。4. 上线后的典型问题与排查经验4.1 多人编辑冲突版本号与编辑锁上线第一周我就遇到了一个非常现实的并发问题同一个客户两个销售同时打开编辑后保存的那个把先保存的覆盖了。尤其是在共享客户和公海交接阶段一个客户可能有销售A和主管B都在操作一个改备注一个改等级最后谁后点保存另一个人的改动就丢了。第一版我天真地以为“last write wins”就够了直到用户投诉“我明明写了三行备注保存后变成空的了”。后来在更新语句里加了版本号校验每次update时where条件带上version成功后将version加一。如果update影响行数为0说明版本已被别人改动客户端就会收到“客户资料已被其他同事更新请刷新后重试”的提示。还有一种更高强度的方案是编辑锁用户打开编辑页时占用一把锁其他人只能以只读方式查看。但这对体验影响很大因为销售经常编辑到一半去接电话锁会卡住别人很久。DeskcommCRM最终采用“乐观锁 保存时冲突提示”的方案不阻止编辑但保证不会无声无息地覆盖数据。这也是很多成熟CRM采用的策略轻量且有效。4.2 来电不弹屏号码归一化与CTI事件排查通信模块上线后排障频率最高的就是“来电为什么不弹屏”。运维日志看多了之后我总结了排查顺序先看PBX侧是否产生了呼叫事件再看CRM是否收到AMI事件再看号码匹配是否成功最后看桌面端弹窗代码有没有被系统拦截。有几次的问题是分机没有透传主叫号码AMI事件里呼出号是空的CRM自然无法匹配。这个要去Asterisk的呼叫配置里确认CallerID的设置。还有一次更隐蔽客户手机号码在系统里存的是“13800138000”但话机上显示的是“8613800138000”虽然看起来是同一个号码程序按字符串匹配永远匹配不上。这就是为什么号码归一化必须放在事件接收的第一道工序而不是等到匹配那一步再处理。桌面端弹窗被拦截也是常见问题。Electron程序在Windows上如果没设置合适的系统通知权限弹窗可能被静默拦截。特别是在部分企业安全软件环境下置顶窗口会被要求额外授权。这个坑不是代码层面能完全解决的需要在部署文档里明确写上“给DeskcommCRM设置允许置顶和通知权限”这类注意事项。4.3 权限边界共享客户与私客的划分权限设计在前期不够严谨后面补起来代价很高。DeskcommCRM第一版只有一个“管理员/普通销售”的区别结果主管想查看下属客户却没有权限入口普通销售想编辑公共客户又总是操作受限。后来改成三套数据权限维度客户归属、客户状态、操作类型。客户归属分成三种私客只归自己管、共享客户至少两个销售同时可见比如同一个连锁集团的不同门店、公海客户所有人可见但需要认领。客户状态分为线索和正式客户线索状态下其他销售还能看到一些基础信息变成正式客户后默认只对负责人和主管开放。操作类型则细分为查看、编辑、删除、转移、导出每个角色单独配置。这个模型用起来之后最明显的改变是责任边界清楚了。共享客户不是所有销售都能随意改只有绑定的share_permission里列出的角色才能编辑。主管拥有团队内所有客户的全部操作权限但普通销售即使看到了公海客户也不能删除任何记录。这套权限模型虽然初始配置麻烦但避免了后续大量人为纠纷。4.4 常见问题速查表这里整理一份排障速查表都是我实际遇到过的。每一个问题背后对应着一个容易忽略的原理弄清楚原理之后再遇到类似问题就有迹可循。现象常见原因解决办法来电不弹屏分机未透传主叫号码或号码格式不一致检查PBX的CallerID配置事件接收后先做号码归一化保存后数据被覆盖缺少乐观锁或版本号校验update条件带上version冲突时提示刷新待办不提醒Electron后台定时任务被系统挂起提醒改成服务端WebSocket推送客户端只负责展示录音文件无法播放文件名中文或音频格式不支持统一使用英文文件名转成mp3/wav格式报表数据对不上物理删除了历史客户统计时没有过滤改用软删除所有报表默认过滤deleted_at公海客户迟迟不释放定时任务进程挂掉没有重试机制worker进程加守护任务失败自动重试这张表特别适合上线初期贴在运维文档里。CRM系统本身逻辑不算复杂但涉及到电话、桌面端、定时任务多个环节链路一长就容易“这里漏一点、那里漏一点”。事后排查时如果一头扎进代码里翻效率很低按链路一层层剥离会快得多。5. 从落地到提效DeskcommCRM在团队里的实际变化5.1 销售习惯被改变的真实细节工具上线并不等于被使用真正改变团队习惯花了一个多月。初期最大的阻力来自销售“又要额外维护一个系统这不是增加工作量吗”我后来调整了策略不强制要求销售填写一大堆客户画像而是先把“自动生成通话记录”这个能力做扎实让销售打完电话发现自己不用录太多东西系统的价值就开始被认可。一个很有意思的细节是以前销售在微信或飞书里聊完客户经常会说“这事我记一下回头填到表里”然后就没有然后了。DeskcommCRM上线后我们把即时沟通的结论回填做成了“轻流程”聊天窗口旁边直接有个“记录摘要”按钮点一下弹出一个极简输入框只需要写一句话。这个按钮把记录动作从“打开CRM找客户再录入”简化成“点一下直接记”使用频率提升了至少一半。销售主管也明显省力了。以前每周一例会上主管要逐个问“你手上那几个客户进展怎么样”销售往往含糊带过。现在打开DeskcommCRM的看板每个客户的最后跟进时间、下一次跟进日期、当前商机阶段一目了然会议从“汇报工作”变成“讨论卡点”。团队里再也没人问“上个客户聊到哪了”这种问题因为历史记录就在那里。5.2 数据报表带来的管理价值有了准确、结构化的数据之后报表才真正有价值。DeskcommCRM后台主要看四个指标跟进完成率、首次响应时长、商机转化率、公海回收率。跟进完成率衡量的是“该联系的客户是否按时联系了”首次响应时长衡量的是“新线索进来多久被跟进”商机转化率衡量的是销售把客户推进到成交的能力公海回收率则是看沉睡客户有没有被重新激活。以前用Excel的时候这三个指标根本算不出来因为数据分散且格式不一。系统上线后主管每天只需要扫一眼Dashboard就能知道哪个区域、哪个销售的漏斗出了问题。有一次我们发现某个销售跟进完成率只有50%跨进公海被释放的客户不少私下了解才知道他手头客户太多分配机制不合理。这个发现不是靠经验猜出来的而是数据直接暴露了问题。关于是否把个人数据排名公开展示我的原则是只让每个销售看到自己的数据主管能看到全团队数据。如果公开排名短期内打鸡血效果好但长期容易引发恶性竞争尤其共享客户多的团队会很敏感。反而让每个人盯住自己的转化漏斗内部比较自然产生氛围更健康。5.3 后续可以扩展的方向语音转写、自动化规则、移动端DeskcommCRM目前是一个够用的版本但它还有几个我明确规划过但没在当前版本里实现的方向。第一个是语音转写把通话录音转成文字摘要再自动提取待办事项。技术上Speech-to-Text已经很成熟难的是销售专业术语的识别准确率需要收集团队历史通话录音做自训练。这个功能如果能落地跟进记录可以从“销售手写一句话”变成“系统自动生成摘要销售只需校对”。第二个是自动化规则引擎。目前公海释放、待办提醒这些规则都是写死在代码里的改动要发版。后续可以做成可视化配置主管在后台设置“超过25天未跟进就释放到公海”“A类客户超过48小时未联系则通知主管”这类规则不需要开发介入。这样系统可以逐步从“技术驱动”转成“业务驱动”更灵活。第三个是移动端。虽然我一直强调桌面端为主但销售外出拜访时查看客户历史和现场下单的需求确实存在。移动端不需要做复杂字段只要做到“查看客户、写跟进摘要、看待办、审批”四件事就好。这个定位在后续如果有团队愿意继续迭代建议优先考虑。一点个人体会如果让我重新做一遍DeskcommCRM我不会先写界面而是先把“客户、联系人、跟进记录、商机”这四个核心模型和各自权限边界定清楚。数据模型错了后面改schema的代价远比想象中大。另一个深刻的体会是CRM这类工具真正难的不是技术实现而是让销售愿意把信息交出来。DeskcommCRM之所以能撑住这一年的运营核心在于我们花了大量时间在减少销售录入成本上——电话自动生成记录、弹屏自动匹配客户、点两下完成跟进。工具不好用规则定得再严也白搭。后来我在做其他系统时也一直保持这个原则凡是需要用户主动填写的字段先问一遍能不能自动生成凡是需要多步操作的流程先想一步能不能省掉。
返回列表