1. 当团队需要一个CRM时,我为什么没选现成的而是写了 DeskcommCRM
先交代一下背景,免得你们觉得我又在重复造轮子。团队从十几个人扩到四十多人之后,客户信息开始失控。销售手里各有一套表格,跟单进度写在自己的备忘录里,客服那边处理完的工单没有同步给销售,财务催回款还得挨个问。我问了一圈,发现大家其实都想要一套统一的客户管理系统,但对市面上的通用 CRM 又各有意见,核心矛盾集中在三件事上。
第一是线索流转不灵活。我们用企业微信承接广告流量,用邮件处理海外询盘,部分渠道还会打到办公室座机上。通用 CRM 要接这些渠道,要么买高昂的接口包,要么自己写中间层,而且线索分配规则经常改,改一次得找厂商提工单等排期。第二是数据字段差异太大。做服务交付的同事和做续费销售的同事,对“客户”这两个字的理解根本不一样。服务交付需要记录设备台账和维保到期日,销售需要记录预算规模和决策链关系,一套固定字段的表单谁都用不顺。第三是私有化部署和数据安全的要求。客户资料和往来合同存在第三方平台上,法务那边一直有顾虑。
所以当时我判断,与其内部凑合着用一套通用 SaaS,再花大量精力去适应它的逻辑,不如基于团队的真实工作流自己搭一套轻量 CRM。DeskcommCRM 就这么立项了。这个名字的含义很简单:Desk 代表桌面端工作台,Comm 代表客户沟通链路,合起来就是一套从沟通到管理再到协作的桌面客户关系管理系统。它不做大而全的功能堆砌,重点解决“线索能不能快速进来、客户资料能不能完整沉淀、跟单协作有没有卡点”这三个核心问题。
这篇文章就想把我从零搭建 DeskcommCRM 的完整过程整理出来,包括技术选型、数据建模、权限设计、踩坑记录和上线后的运维经验。如果你也在考虑自建一套客户管理系统,或者正在为公司选型纠结,这篇应该能给你一些参考。
2. 核心设计:工作台、客户池、沟通记录的三角结构
在动手写代码之前,我先把系统要解决的角色问题梳理了一遍。DeskcommCRM 的使用者只有三类角色:销售、客服、管理员。销售关心的是自己名下有多少条线索、分别处于什么阶段、最近一次跟进是什么时候;客服关心的是客户有没有报修、工单处理到哪一步了、需不需要转给销售跟进;管理员关心的是线索分配是否平衡、转化率怎么样、哪些环节卡住了。
基于这些需求,我把系统数据模型设计成三角结构:客户档案、沟通记录、跟进任务。客户档案是所有业务动作的载体,一条核心记录会关联若干个联系人、若干条沟通记录、若干个跟进任务。沟通记录可以是手动录入的,也可以是从邮件和企业微信导入的,统一按时间轴沉淀在客户详情页里。跟进任务则是待办性质的,到时间还没完成的会标红提醒。
这个设计的核心思路是:不让任何一个业务信息散落在流程之外。以前销售会把客户聊到一半的重要信息随手写在微信备注里,现在所有沟通都必须落到沟通记录中,而且系统会自动带上记录人和记录时间,没法事后补造。刚开始有人嫌麻烦,后来大家发现查历史记录特别方便,尤其是中途接手客户的同事,打开客户详情页就能完整看到前因后果,不需要再来回问。
客户池的设计也做了细化。字段上拆成基础信息区、交易信息区、服务信息区、自定义信息区四块。基础信息区放公司名称、行业、规模、地区;交易信息区放商机金额、预计成交日期、当前阶段;服务信息区放设备台账、维保到期日、合同编号;自定义信息区留给业务后续扩展。这个分区方式对使用者非常友好,销售只关注他需要填的那部分,客服也不会被一堆无关字段淹没。
数据字段之外,DeskcommCRM 还有一个比较重要的设计:阶段流转的可视化。我把客户生命周期分成了线索、初步沟通、需求确认、方案报价、商务谈判、成交、维护中、流失等八个阶段。每个客户在列表页都会显示一个阶段标记,管理员可以按阶段筛选并统计数量。这个功能看起来简单,但上线后大大降低了管理成本,每周例会不用再让销售挨个口述进度,直接打开后台看仪表盘就行。
3. 技术栈选型:为什么用 Python + FastAPI + Vue 这套组合
技术选型这部分我纠结了挺久。团队已有的技术储备是 Python 和 JavaScript,所以最终候选方案基本围绕这两门语言展开。后端我在 Django、Flask、FastAPI 三者之间对比了很久。
Django 自带 Admin 后台和 ORM,开发效率确实高,但对我来说太重了,很多内置功能用不上,而且项目结构约束比较强,跟我要做的这套轻量定制系统的调性不太匹配。Flask 足够轻,但很多东西都得自己拼,比如数据库迁移、请求参数校验、接口文档生成,都得额外接插件。考虑维护成本,我更倾向于第三方依赖少一些的方案。FastAPI 的优势正好契合我们的需求:基于类型注解自动生成 OpenAPI 文档,前端对接接口时有现成的文档可以查;自带 Pydantic 做参数校验,出错时错误信息非常明确;性能上基于 asyncio,虽然我们这种并发量并不敏感,但同样配置下比 Flask 更省资源。
数据库我选的是 PostgreSQL,没有第二条考虑。原因很简单:PostgreSQL 的 JSONB 字段能很好地配合我们“自定义信息区”的灵活需求,而且它的事务处理和数据完整性保障比 MySQL 在某些细节上更让人放心。全文检索和数组类型也是现成的,后期做客户搜索时很省事。
前端部分用了 Vue 3 + Element Plus。选择 Vue 而不选 React,纯粹是团队熟悉度的原因。Element Plus 的表格、表单、弹窗组件很成熟,拼办公后台特别快,而且它的表单校验和分页组件能省掉不少重复开发。图表统计这层我用了 ECharts,仪表盘上的阶段漏斗图、新客增长趋势图、线索来源分布饼图都是用它画的。ECharts 我用了很多年,文档全、坑少,图表交互也够用。
列一下最终的依赖清单,给你们做个参考:
| 模块 | 技术选型 | 说明 |
|---|---|---|
| 后端框架 | FastAPI | 异步支持、自动文档、Pydantic 校验 |
| 数据库 | PostgreSQL 15 | JSONB 灵活字段、全文检索 |
| ORM | SQLAlchemy 2.x | 配合 FastAPI 生态比较成熟 |
| 前端框架 | Vue 3 + Vite | 构建快、组件生态丰富 |
| UI 组件库 | Element Plus | 表格与表单组件成熟 |
| 图表 | ECharts 5 | 阶段漏斗、趋势统计 |
| 认证 | JWT + 角色权限中间件 | 无状态认证,前后端分离友好 |
| 部署 | Docker Compose + Nginx | 简单轻量,单机即可跑 |
这套组合在实际开发中确实顺手,但我得说实话,它不是唯一正确的答案。如果团队业务复杂到需要非常细腻的权限联动,或者需要处理海量数据写入,那可能要重新评估。但对一个几十人规模的团队来说,这套组合的性价比和可控性已经很高了。
4. 数据模型定义:客户怎么存、阶段怎么记、自定义字段怎么做
数据模型是 DeskcommCRM 的地基,我把核心表结构拆开来讲,这一块理解了,后面看任何功能逻辑都会很轻松。
第一张表是客户主表 customers。里面除了公司名称、所属行业、客户规模这些常规字段之外,我加了一个 status 字段,用整数 0-8 代表八个生命周期阶段,通过枚举映射表去做翻译。加这个中间枚举表的用意是,以后如果要加阶段或者调整阶段顺序,不需要改主表结构,只需要改枚举配置。另一个比较关键的设计是 owner_id 字段,也就是当前负责人的用户 ID。客户流转时只需要更新这个字段,所有权就变了,操作记录里会保留流转日志。
第二张表是联系人表 contacts。一个客户可以挂多个联系人,每个联系人拥有独立的电话、微信、邮箱和职务字段。这张表有一个备注字段,专门用来记录联系人的性格偏好、沟通习惯这种软信息。别小看这个设计,接手的同事能不能快速跟老客户熟络起来,全靠这些备注。
第三张表是沟通记录表 communications。每次客户来电、企微聊天、邮件往来,都落一条记录,类型字段区分电话、邮件、企微、面谈。正文支持纯文本,也可以附带文件链接。这张表的索引设计我特意做了复合索引:customer_id + created_at,按客户查时间轴时性能很好。数据量上来之后,这条索引省下的时间非常明显。
第四张表是任务表 tasks。字段包括关联客户、任务类型、负责人、截止时间、完成状态。任务类型划分为初次跟进、定期回访、催收款、送合同、技术方案发送等。这类数据对销售的日常工作节奏影响很大,我在系统里加了截止时间提醒逻辑:到期前 24 小时发提醒,超过截止时间还没完成的任务在待办列表里标红。
自定义字段这块,我用了 JSONB 的一个巧妙用法。customers 表里有一个 custom_fields 字段,类型是 JSONB,管理员在后台配置字段名、字段类型和是否必填。查询的时候通过 PostgreSQL 的表达式索引,可以在 JSONB 字段上做条件筛选,体验跟普通字段几乎一样。这套方案的维护成本极低,上线后业务部门提出要加“是否已回款”“OEM品牌”“服务器所在地”这类字段,我在后台配置界面点几下就搞定,完全不用发版改表结构。
需要提醒的是,JSONB 不是万能的。如果数据量到百万级,且高频按某个 JSONB 内部字段过滤,性能会明显下降。应对办法是:高频过滤字段抽成正式列,低频字段留在 JSONB 里。这算是我做完这个项目后比较深刻的体会。
5. 权限与数据安全:从按钮级别到操作审计的实现链路
很多 CRM 项目死在权限设计上。要么权限太粗,销售能看到全公司的客户数据,互相抢单闹得不可开交;要么权限太死,销售想把客户转给同事还得找管理员手动操作。DeskcommCRM 的权限模型分了三层:功能权限、数据权限、操作审计。
功能权限控制的是用户能不能看到某个菜单或按钮,比如只有管理员能看到系统设置页签,只有客服角色能进工单管理模块。数据权限控制的是用户能看到哪些客户记录,这是整个系统里最敏感也最复杂的一块。我的设计是:管理员能看全部客户;销售默认只能看自己名下和曾经流转给自己的客户;客服能看全部客户但只能编辑服务相关字段;部门主管能看到本部门销售名下的客户列表但只能查看不能修改。
这套数据权限不是简单地在每个查询接口里加一个 where user_id = current_user 就能搞定的。我抽了一个数据权限中间件,统一读取当前用户的角色和数据范围配置,然后拼装 SQL 查询条件。代码上用的是 SQLAlchemy 的 query filter 动态拼接,所有涉及到客户列表的接口都必须通过这个中间件,防止某个接口漏了权限判断。
操作审计是块硬骨头。系统里任何关键操作,包括客户创建、阶段变更、负责人转让、资料编辑、删除恢复,都会写入 audit_logs 表。字段包括操作人、操作时间、操作类型、对象 ID、操作前后 JSON 快照。这个表上线初期没什么存在感,但后来发生了一次客户数据误删,多亏了 JPEG 快照恢复,否则客户十几个合同信息全丢了。现在我的个人习惯是,不管项目多小,审计表必须建,哪怕是只记录登录日志,关键时刻都能救命。
再说数据安全。密码存储用的 bcrypt,这里多说一句,不要再用 MD5 或者 SHA 系列做密码哈希了,虽然加盐,但硬件发展到现在,彩虹表和暴力破解已经不是开玩笑的事。bcrypt 的计算开销天然抗 GPU 批量破解,实测在普通服务器上每个请求多几毫秒,完全是值得的投资。JWT 的签发有效期我设成 12 小时,刷新令牌有效期 7 天。生产环境全部跑在 HTTPS 下,敏感接口配合验证码做二次确认,例如删除客户和批量导出数据都需要输入验证码。
6. 开发过程中最容易翻车的五个环节
这个项目前后花了大概六周,从开发到上线。过程不算夸张复杂,但踩过的坑一个不少。我觉得最有代表性的有五个,每一个都能写一篇小作文,这里把重点提炼出来。
第一个是线索导入时的数据去重。第一版我直接按公司名称精确匹配去重,结果一个“北京xxxx科技有限公司”,有人录成“北京xxxx科技公司”,有人录成“xxxx科技有限公司北京分公司”,系统里跑出来三个客户。后来改成基于公司名称的归一化处理:去除公司后缀中的冗余词、移除全角半角空格、统一繁体简体,再做匹配。这个逻辑说不上多高级,但上线后重复建档率显著下降。如果你后续也要做类似系统,这个细节值得提前考虑。
第二个是企业微信消息回调的幂等处理。企业微信的服务器回调同一个事件可能会推送多次,如果处理逻辑不做好幂等,沟通记录里就会重复插入同一条消息。我在接收端根据消息 ID 做了唯一约束,重复回调直接被数据库拒绝。经验教训是:对接任何第三方 Webhook,必做幂等处理,不能相信对方只推一次。
第三个是时区问题。一开始时间字段全部用本地时间存储,接进来一个海外客户,那边下午发的询盘邮件,在这边显示了凌晨三点的时间戳,销售看到了以为客户半夜加班,回复时措辞都受影响。后来全部统一改成 UTC 存储,展示时按登录用户时区做转换,所有时间比较逻辑都用 UTC 计算。这个就是个基础意识问题,不做以后迟早出事。
第四个是大批量导入的乐观锁。销售部每月初会批量导入几百条 Excel 线索,如果导入过程中有人同时修改客户资料,容易造成数据覆盖。我引入了版本号机制,每次更新时比较版本号,不一致就提示用户“该客户信息已被其他同事修改,请刷新后再试”。虽然偶尔会有人抱怨多了一步,但再也没出现过数据互踢的问题。
第五个是邮件解析附件编码问题。我们接入了企业邮箱的 IMAP 通道,通过解析邮件内容自动创建沟通记录。各种邮箱客户端发送的附件文件名编码五花八门,有的用 Base64 编码,有的用 UTF-8 直接拼。第一版解析经常出现文件名乱码,调试了两天才发现是 MIME 头部解析时要用 email 库的标准库去 decode_header,而不是简单把字节流转成字符串。这个小问题卡了两天进度,最后把出现过的所有编码样例写进了测试用例,以后再没犯过。
7. 从开发到落地的完整链路:企微消息、邮件接入、外部 API 联调
DeskcommCRM 不只是内部用,它的数据入口必须接上外部业务系统,才能真正让客户信息流转起来。整个联调链路我分成了三块来搞。
第一块是企业微信消息的接入。团队平时主要在企微微信群跟客户沟通,所以我把企微的消息回调接进了系统。当员工在企微里收到客户消息时,如果该手机号或微信外部联系人 ID 能匹配到系统内的客户,消息内容会自动写入该客户的沟通记录时间轴;如果匹配不上,系统会在线索池里创建一条新线索,标记来源为企业微信。这里的技术关键点是获取外部联系人详情接口的调用频率限制,企微对这个接口的限制比较严,我用了一个令牌桶算法做限流,同时把获取到的联系人资料缓存了两小时,避免高频请求打爆额度。
第二块是邮件接入。团队有一个业务公共邮箱,客户发来的询盘和合同往来都在里面。我写了一个 IMAP 监听服务,每隔五分钟拉取一次未读邮件,解析发件人、标题、正文和附件,按发件人邮箱匹配客户联系人,匹配成功的关联到客户详情页,匹配不成功则转入线索池等待分配。这里涉及的难点是 HTML 邮件的正文提取,有些营销邮件大量嵌套 div 标签,提取出来的正文非常乱。我用了 BeautifulSoup 先移除 script、style 和导航区块,再提取主文本内容,实测大多数邮件都能提取出可读正文。
第三块是对外 API 联调。主要是跟企业内部的 ERP 对接,打通合同和回款数据。ERP 那边提供了一个只读 API,返回客户维度的合同金额和回款状态。DeskcommCRM 每天晚上定时拉取一次,更新客户详情页里的“累计合同金额”和“待回款金额”两个字段。联调中碰到的主要是认证问题,对方要求用 RSA 签名来认证请求方身份,我们费了点时间实现签名逻辑,不过这个一旦配好就很稳定,之后几乎没有出过问题。
联调过程中我还额外做了一个 Webhook outbound 推送。当客户进入“方案报价”阶段时,系统会推送一条消息给管理员的企业微信,提醒管理员检查报价单是否已发出。这类主动触达是内部系统最能提高协作效率的点,我发现团队里其实很多人不是不愿意跟进,而是总忘记在关键节点去检查。
8. 权限配置和部署上线:一套看得见摸得着的操作日志
部署这块我选了最省心也最容易维护的 Docker Compose 方案。一台 4 核 8G 的云服务器,上面跑了四个容器:后端 FastAPI 服务、前端 Nginx 静态资源服务、PostgreSQL 数据库、Redis 缓存服务。用 Docker Compose 管理的好处是所有依赖版本都固化在 docker-compose.yml 里,换服务器或者灾后重建时只需要一条命令就能拉起全部服务,不存在环境的玄学问题。
Nginx 做了两层作用:一层是托管前端打包后的 dist 静态文件,另一层是把 /api 路径反向代理到后端的 8000 端口。HTTPS 证书我用的是 Let‘s Encrypt,certbot 自动续期,三个月一更新,目前跑了半年多没遇到过证书过期问题。
上线前我做了三轮内部测试,分别由销售部、客服部、管理员三拨人参与。销售部测试重点关注:线索列表是否清晰、快速录入是否顺手、阶段流转是否符合实际操作习惯。客服部测试重点关注:客户搜索快不快、工单关联客户是否顺畅、能不能快速查看到历史沟通记录。管理员测试重点关注:分配线索是否方便、统计分析数字是否准确。三轮测试下来,整体反馈比较正向,但同时也暴露了几个 UAT 阶段没发现的问题,比如批量导入几百条线索之后,列表页滚动卡顿;客服部门希望客户详情页能多显示一列最近联系时间,销售部希望商机金额支持自定义币种等。这些问题大部分通过前端优化和配置调整解决,真正要改后端代码的只有一两个。
上线后第一周,我密切关注了两类数据:系统使用率和数据录入质量。使用率这一块,销售部每天登录系统的比例超过 90%,候补名单上几个没账号的同事催着开账号,说明大家是愿意用的。数据录入质量这一块,客户信息的填写完整率从最初的 61% 提升到了 85%,原因在于列表页增加了“信息完整度”打分列,低于 60% 的客户会以黄色警告标识展示。一个小细节带来了明显的行为变化。
操作日志这块,我不只是实现了,还做了一个“审计日视图”页面。管理员可以选某一天,系统用时间线形式展示那一天谁创建了什么客户、谁改了哪个字段、谁把某客户从 A 转给了 B。配合完整的 JSON 快照对比,几乎能精确还原每一次操作。这个页面在业务侧不一定频繁用,但它带来的心理影响是巨大的:默认情况下,员工会更谨慎地对待系统中的数据。谁都不想被管理员追问“昨天下午你把那个客户删了是为了什么”。
9. 生产环境真实数据下的性能优化与踩坑复盘
系统刚上线时用户量小,接口响应普遍在 50ms 以下,基本无感知。但用了三周之后,客户记录数冲到了 3 万多条,沟通记录超过 12 万条,一些最常用的接口开始变得迟钝。最明显的是客户列表页和全局搜索,一个带筛选条件的列表查询,高峰期要两到三秒才返回数据。
第一步优化是加索引。我在 customers 表里对 owner_id、status、created_at 分别建了索引,对 communications 表建了 customer_id + created_at 的复合索引。加完之后列表查询降到 800ms 左右,有提升但不够理想。第二步优化是把列表查询的关联子查询拆开。原来客户列表为了显示每个客户的最近沟通时间,做了一个相关子查询,数据量大后子查询开销非常夸张。我改成先查出目标客户 ID 列表,再一次性查出这些客户的最近沟通时间,用 Python 端做内存映射。改动之后,列表接口稳定在 200ms 以内,体验完全达标。
这里最大的一个教训是:不要过早优化,但必须在第一个性能拐点出现时马上处理,绝对不能拖。我最初把性能问题归结为“服务器带宽不够”,后来经过 EXPLAIN 分析才确定是索引缺失和 SQL 写法的问题。调优这个事情,靠猜是搞不定的,得依赖数据库提供的执行计划工具,PostgreSQL 的 EXPLAIN ANALYZE 就是最直接的诊断武器。
踩过比较伤的另一个坑是 PostgreSQL 连接池耗尽。FastAPI 每个请求都要从数据库连接池拿连接,默认大小设成 20,结果高峰期请求一多,连接池直接排队,表现为系统整体响应变慢甚至超时。后来的解决方法是把连接池大小调到 50,同时加了一层 SQLAlchemy 连接回收机制,超过 300 秒不用的连接自动销毁重建。改完后,数据库连接曲线平稳了很多。
缓存层我也做了些工作。Redis 主要缓存三类数据:一是客户列表页的筛选结果缓存,设置过期时间两分钟;二是系统配置和枚举映射,基本不变,缓存一天;三是企微和邮件外部联系人资料,缓存两小时。缓存命中之后,每次查询的响应时间能控制在几十毫秒。不过有一点要注意,缓存写错了很容易造成数据显示不及时,所以设计时我倾向于“强一致性的数据绝不能只靠缓存”,而是把缓存定位成加速层,数据库始终是最终真相。
上线这一个多月里,我还养成了一个习惯:每天早上去看一眼 PostgreSQL 的慢查询日志。发现哪个接口慢,第一时间写优化脚本,不急着改线上代码。很多慢查询其实就是某个同事在后台页面操作了一大批数据,单独一次不影响,但每天固定有一次就会积累成性能问题。慢查询日志基本成了我的值班资料,翻它比翻业务报表还能更快发现问题。
10. 上线后的迭代节奏和扩展方向
DeskcommCRM 第一版能跑顺,核心靠的是“功能克制”。初期我给团队承诺了客户管理、线索流转、沟通记录、权限控制、审计日志、仪表盘统计这六个模块,其他所有构想都先冻结。上线稳定后才开始排列迭代优先级。
第二个迭代周期主要加了批量操作能力,比如批量分配线索、批量阶段流转、批量导入和导出。销售部对这些功能呼声很高,尤其是月底整理数据时,没用之前他们一个个点,几个负责人快疯了。第三个迭代周期加了自定义仪表盘,每个角色最关心的指标不同,管理员可以在后台组件库里拖拽配置布局。
如果后续要继续发展,我设定了几个明确方向。
方向一是智能线索评分。通过历史成交客户数据,提取公司规模、来源渠道、沟通频率、询盘内容关键词等特征,写一个简单的加权评分算法,给新线索打一个“成交概率分”。先不用机器学习和深度学习那么重,逻辑回归或简单加权就够了,等数据积累到一定量再看要不要升级模型。
方向二是更细腻的工作流自动化引擎。现在系统只能做“阶段变更后推送给管理员”这种单一条件触发。后续我想支持用类似 if then 的可视化规则编辑器,让管理员自己配置复杂流程,比如“上海地区的客户询盘超过两次但没有进入需求确认阶段,自动分配给销售主管跟进”。这类规则比写死在代码里灵活得多,部门负责人可以自己调整业务节奏。
方向三是跟呼叫中心做对接。团队现在还有个 400 电话的入口,目前只能靠客服手动录入沟通记录。后续打算通过电话 API 自动识别来电号码,匹配客户信息,通话结束后把录音转写文本自动导入沟通记录。这对客服的工作效率提升会非常明显。
方向四是移动端适配。现在 DeskcommCRM 在手机上能通过浏览器打开,但不支持 PWA 离线缓存,接到客户电话时没法快速带出客户资料并建立沟通任务。后续计划做一套轻量的移动端页面,重点覆盖客户搜索、快速记录、任务提醒这三个高频场景。
11. 一些最想告诉后来者的经验
项目做到这个阶段,最大的感触不是技术本身,而是“系统好不好用,取决于它是否贴合真实的业务流程”。一开始我太关注技术细节,花费大量时间调整前端样式和后端接口,结果销售部反馈最强烈的功能却是“能不能让我少点两次鼠标”。后来我专门蹲在销售工位旁边看他们实际操作了一个下午,才发现他们有大量重复性录入动作,有些字段其实可以自动带出,有些客户资料可以从历史记录里直接复制。第二版我把表单默认值、复制上次记录、批量选择客户等细节做进去之后,使用率肉眼可见地提升了。
如果你也想给自己的团队搭一套类似系统,我有几条具体的建议。
第一,不要一上来就追求功能完整,先解决最痛的一两个点。我们最痛的点是客户资料分散和沟通记录无沉淀,第一版就把这两件事做到极致,其他功能延后再谈。
第二,在正式开发前,花至少两天时间跟实际使用系统的同事聊清楚他们的工作流程。特别是销售、客服这种一线角色,他们对“好用”的定义跟你看完竞品文档猜测的完全不同。你关心的漂亮界面和数据模型,在他们眼里可能远远不如“按一下回车就保存并新建下一条”来得实在。
第三,权限设计从第一天就搭建好。哪怕系统只有二十个人用,也建议把角色权限和审计日志做完整。团队人数增长后,再回头补权限体系会非常痛苦,还可能因为权限设得不够细导致客户信息泄露。
第四,数据库字段尽量用文本枚举替代数字枚举。当时沟通记录类型我用的是 text 字段直接存“电话”“邮件”“企微”,虽然不够严谨,但查询和排查都更直观。数字枚举在代码里看挺清晰,但丢了映射表之后就全靠猜。
第五,所有外部接口调用必须做超时和重试机制。企微接口在高峰期出现过几次响应超过五秒,如果不做超时控制,用户那边就会一直转圈,重试机制配合幂等处理可以保证数据最终一致。
DeskcommCRM 这套系统给我最大的收获是,它让我重新理解了客户关系管理本身:真正的 CRM 不该是表格的电子化,更不该是销售流程的枷锁,而是把零散的信息变成可复用的资产。系统里沉淀下来的每一段沟通记录、每一份合同文件、每一次阶段变更,都是团队集体记忆的一部分。关系管理靠人,但人的记忆力不靠谱,系统补上的正是这个短板。
我对现在的版本还称不上满意,但它的确每天都在帮团队省时间、防差错、促成交。这就够了。后续所有迭代,我会继续让一线同事先提需求,再由我评估技术实现。这套“需求驱动、技术实现”的循环,在我看来自建系统最健康、最可持续的运转方式。