ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

CRM客户管理PRD落地拆解:主数据、权限、状态机与验收

CRM客户管理PRD落地拆解:主数据、权限、状态机与验收

简介:《客户关系管理CRM-客户管理-PRD-V1.0》是一份面向产品经理、需求分析师、CRM实施人员及开发测试团队的软件需求说明书,聚焦客户档案、联系人跟踪、销售漏斗、市场营销自动化与客户服务等模块的规范化设计,可用于理解CRM项目从需求来源到功能落地的完整思路。文档共54页,按项目介绍、方案概述、业务流程、业务用例、功能列表和基本流程等章节展开,并涉及平台政策、竞品分析、名词解释、系统用例与角色用例,便于读者对照梳理功能边界和业务建模线索。资源包内含1个PDF文件,大小约3.11MB,单文件结构便于检索、传阅和评审参考。目前已有318人学习,产品、研发与测试人员可从中获取需求组织方式、模块拆解方法及文档变更管理思路。

1. 一份 2017 年的客户管理 PRD,今天照着做会不会翻车

上周有个做企业服务的朋友拿来一份 2017 年 8 月定稿的客户关系管理 CRM 客户管理模块 PRD,问我能不能直接照着开工。我的判断是:里面关于客户主数据、角色权限、状态流转的定义,八成今天还用得上;但如果照着它的页面结构直接建表,后面大概率要返工。原因不复杂——那一代客户管理 PRD 普遍把「客户」当成一张静态档案表来设计,字段堆在同一个页面里,权限靠人配,状态靠手改;而今天的业务对一个客户的要求是带生命周期、带归属变更、带跟进轨迹的活对象。这份文档真正值钱的部分不在页面长什么样,而在它把哪些字段定义成唯一、把哪些动作定义成不可逆。下面我按自己落地这类 PRD 的顺序,把它拆成能开发、能验收、能排错的六块内容,中间穿插几条血泪经验。

2. 先划边界:客户管理里谁是主数据,谁只是附属

动手建表之前,先把「客户」这个词的边界划清楚,这一步偷懒,后面每一层都要还债。客户管理里最容易混淆的是三个对象:客户、联系人、线索。客户是主数据,一个客户在企业视角下应当是唯一的;联系人是客户的附属,一个客户可以有多个联系人,联系人离职了客户还在;线索是未经验证的原始信息,可以重复、可以脏、可以来自任何渠道。三者混在一张表里,最典型的后果是列表页搜「某公司」出来七八条记录,销售各自跟进,老板看到的业绩数字永远对不上。

我一般会用一句话把边界钉在 PRD 的首页上:客户是唯一实体,线索是客户的候选池,联系人是客户的挂件。这句话决定了后面所有唯一性校验、权限范围、合并逻辑怎么写。

2.1 客户主数据字段:进主表的和进从表的分开算

一份 2017 年的客户管理 PRD,字段清单通常密密麻麻写两三页,但真正决定系统好不好用的是「哪些字段进主表」。我的划分标准只有一条:会被高频筛选、排序、做权限判断或者做唯一性校验的字段,进主表;其余全部进从表或扩展表。按这个标准,客户主表保留的字段大致如下。

字段类型必填说明
customer_idbigint是主键,自增或雪花
customer_novarchar(32)是对外客户编号,业务生成,唯一
customer_namevarchar(200)是客户全称
customer_typetinyint是1 企业 / 2 个人
social_credit_codevarchar(32)否企业统一社会信用代码
mobilevarchar(20)否个人客户手机号
industryvarchar(64)否所属行业,字典值
leveltinyint是客户等级,默认 3 级
sourcevarchar(64)是来源渠道,字典值
owner_idbigint是归属销售
dept_idbigint是归属部门,随归属人冗余
region_codevarchar(16)否所属区域
statustinyint是生命周期状态,见第 4 章
in_pooltinyint是是否在公海,0 否 1 是
last_follow_timedatetime否最后跟进时间,冗余字段
next_follow_timedatetime否下次跟进时间
versionint是乐观锁版本号
created_at / updated_atdatetime是创建与更新时间
is_deletedtinyint是软删除标记

这张表里有两个字段值得单独说。一个是dept_id,它其实可以从归属人反查组织树得到,但我仍然冗余存一份,原因是数据权限过滤是列表页最高频的查询条件,每次 join 组织表会让分页查询变慢,而组织调整是低频动作,归属人换部门时同步刷一次dept_id就够了。另一个是last_follow_time,它由跟进记录写入时同步更新,列表页默认排序、公海回收规则都依赖它,属于典型的用写放大换读性能。

至于从表,联系人、地址、开票信息、银行账号、附件、自定义扩展字段,一律拆出去。自定义扩展字段尤其要注意,2017 年的 PRD 喜欢在客户表上预留ext1到ext20,这种设计三年内一定失控,常见做法是单独建一张crm_customer_ext,用field_key、field_value的纵表结构存,或者干脆用 JSON 字段,但 JSON 字段不要拿来做筛选条件。

唯一性约束是这一节最容易被跳过的地方。企业客户按名称去重会误杀同名不同主体的情况,我一般用customer_name + social_credit_code做联合唯一索引,信用代码为空时降级为「名称 + 归属部门」做软校验,只在新建时提示不阻断。个人客户直接按mobile做唯一,手机号是个人客户最强的识别项。

2.2 角色与数据权限:销售只能看自己的客户,这句话要拆成矩阵

PRD 里写「销售只能看自己负责的客户」只有一行字,落到实现上是一张二维矩阵:角色决定能做什么操作,数据范围决定能看到哪些行。这两件事必须分开设计,否则后面加一个「区域经理」角色就要改一遍代码。

角色数据范围查看编辑转移删除导出
销售本人是是否否否
销售主管本团队是是是否是
区域经理本部门及下级是是是是是
客服本人 + 指派是仅跟进记录否否否
运营全部(只读)是否否否是
管理员全部是是是是是

数据范围的实现,我一般用「范围类型 + 范围值」两个字段挂在角色上,范围类型取本人、本团队、本部门及下级、指定部门、全部五档,查询时翻译成一段where条件拼进列表 SQL。不要用「给每个用户配一条可见客户 ID 列表」的做法,客户量过万之后这张关联表会变成灾难,而且人员变动时同步逻辑极难写对。

这里有个细节:数据权限必须在服务端拼进查询条件,不能只靠前端隐藏按钮。我见过一个项目,列表接口做了权限过滤,详情接口忘了做,结果销售改一下 URL 里的 ID 就能看到别人的客户,这种问题在验收阶段基本发现不了,只能靠代码评审兜。

2.3 线索、客户、商机三段式:转化时的唯一性怎么保证

客户管理的主线是「线索 → 客户 → 商机」,三段各自的职责要写死:线索负责承载未验证信息,可以重复、可以批量导入、可以来自表单和展会名单;客户负责承载已验证的、要长期经营的实体;商机负责承载一次具体的成交机会。一个客户可以有多个商机,一个线索最多转成一个客户。

转化动作是这条链上最容易出问题的一环。我一般会把转化做成一个显式接口,而不是让用户在客户列表里手工新建,因为转化时要处理三件事:查重、合并、留痕。查重按企业名称和信用代码双条件模糊匹配,命中已有客户时不是直接拦截,而是弹出一个选择框,让操作人选「关联到已有客户」或「仍然新建」,选择结果写进线索的转化日志。合并的动作要谨慎,两个客户合并意味着联系人、跟进记录、商机、合同全部要改挂,这个动作我一般只开放给主管角色,并且要求填写合并原因。

还有一条经验:线索表上要留converted_customer_id和converted_at两个字段,转化后线索不删除,只打标记。否则半年后有人问「这条线索到底转没转」,你只能去翻操作日志,那就成了黑匣子。

3. 把 PRD 拆成可开发的功能清单与页面流

PRD 是给人看的,功能清单是给开发和测试看的。这两者之间的差距,主要差在参数上:PRD 写「客户列表支持按条件筛选」,功能清单要写清楚筛哪些条件、默认值是什么、多选怎么拼、空值算不算命中。这一章按客户管理最核心的三个页面——列表页、详情页、表单页——把参数一条条摊开。

3.1 客户列表页的筛选、排序与分页参数

列表页是销售每天打开次数最多的页面,它的默认行为直接决定用户觉得这个系统「顺不顺手」。我一般会定这几条:默认按最后跟进时间倒序,默认每页 20 条,默认只查「跟进中」和「待分配」两种状态,已成交和流失的客户要主动切标签才看得到。

筛选参数清单如下,开发时直接照这张表实现。

参数类型默认值匹配方式备注
keywordstring空名称/编号/手机号模糊长度限制 50,前后空格 trim
statusarray跟进中、待分配精确 in多选
levelarray空精确 in多选
owner_idarray空精确 in受数据权限二次约束
dept_idarray空含下级则用树查询与组织树联动
sourcearray空精确 in字典值
tag_idsarray空交集匹配多标签取同时命中
created_rangedate range空闭区间跨度不超过 365 天
last_follow_rangedate range空闭区间同上
pageint1—上限 10000
page_sizeint20—上限 100

几个参数背后的取舍值得说清楚。关键词搜索不要对customer_name做%关键词%的全模糊,客户量到几十万之后这个查询会拖垮整个列表,常见做法是用前缀匹配关键词%走索引,或者单独维护一张搜索引擎的索引表,关键词走搜索服务,其余条件走数据库。标签多选用交集而不是并集,是因为销售筛标签的真实意图通常是「既是重点客户又属于制造业」,并集会把结果撑得没法看。

排序字段只开放三个:最后跟进时间、创建时间、客户等级。不要开放任意字段排序,否则前端传个没建索引的字段进来,一次排序就是一次全表扫描。

分页用 limit offset 在深翻页时会变慢,客户量大的系统我一般加一条约束:超过 100 页的翻页强制要求用户先加筛选条件,或者改用「上一页 / 下一页」的游标分页,游标用last_follow_time + customer_id组合。

3.2 客户详情页的 360 视图分区

详情页的核心诉求是「一眼看完这个客户的全部信息」,但全部信息往往意味着十几个模块、上百个字段,首屏一次性加载完会让打开速度很难看。我的做法是分 tab 懒加载,首屏只加载基础信息加最近 5 条跟进记录,其余 tab 点开时再请求。

分区内容加载时机数据来源
基础信息名称、等级、归属、状态、来源、标签首屏客户主表
联系人姓名、职务、手机、是否关键人首屏折叠联系人表
跟进记录时间轴,按时间倒序首屏 5 条,滚动加载跟进记录表
商机商机名称、阶段、金额、预计成交日点击 tab商机表
合同订单合同编号、金额、回款状态点击 tab合同表
附件文件名、大小、上传人点击 tab附件表
变更日志归属变更、状态变更、字段修改点击 tab日志表

基础信息区顶部要放三个东西:客户状态标签、归属人、下次跟进时间。前两个是判断「这个客户现在归谁、处于什么阶段」,第三个是销售自己的行动提醒,这三个信息放在一起,用户扫一眼就知道下一步该干什么。跟进记录的时间轴要支持按类型筛选(电话、拜访、邮件、微信),但不要在时间轴上做分页器,滚动加载加「加载更多」按钮的体验更贴近真实使用。

详情页还有一个容易漏的点:所有 tab 的数据请求都要带一次权限校验,尤其是通过 URL 直接访问详情页的场景。

3.3 新建与编辑表单的校验规则表

表单校验是客户管理里翻车最集中的地方,因为这里的规则最多、最琐碎,而且每一条都直接对应用户的一次挫败感。我一般把校验分成三类:阻断型(不通过不能提交)、提示型(可以提交但给警告)、异步型(需要请求后端判断)。

字段规则类型提示文案方向
customer_name必填,2~200 字符,去首尾空格阻断请填写客户全称
customer_type必选,默认企业阻断—
social_credit_code18 位,字母数字,企业类型必填阻断信用代码格式不正确
mobile11 位手机号正则,个人类型必填阻断请填写正确的手机号
level必选,默认 3阻断—
owner_id必选,只能是当前用户或其下级阻断无权将客户分配给该人员
customer_name + 信用代码联合查重异步已存在同名客户,是否继续
富文本备注长度 2000,过滤脚本标签阻断备注最多 2000 字

异步查重要做防抖,输入停顿 500 毫秒再请求,且只在新建时触发,编辑时不重复校验自己。手机号正则不要写得过分严格,170、171、162 这些号段要放进来,我见过一个项目的正则漏了虚商号段,导致一批客户建不进去,排查了半天才发现是前端正则的问题。

编辑表单还要处理并发:两个人同时打开同一个客户,A 先改了归属人,B 后提交把归属人改回去了。解决办法是在提交时带上version,服务端update ... where version = ?,影响行数为 0 就返回「数据已被他人修改,请刷新后重试」。这条规则写进 PRD 只需要一行,但不写就一定会在上线后被投诉。

4. 数据模型与状态机:客户生命周期怎么落表

页面是皮,数据模型是骨。客户管理这类系统的数据模型并不复杂,难点在于「一个客户的一生」要在几张表里被完整记录:谁创建的、归谁、被谁改过归属、跟进了几次、什么时候被回收进公海。这一章给出我常用的五张核心表和一套状态机,可以直接对照着建。

4.1 五张表撑起客户管理:主表、联系人、跟进、日志、标签

表名作用关键字段索引建议
crm_customer客户主表见 2.1 字段清单唯一索引 (customer_no),联合索引 (owner_id, status),索引 (last_follow_time)
crm_contact联系人customer_id、name、title、mobile、is_key索引 (customer_id),唯一索引 (customer_id, mobile)
crm_follow_up跟进记录customer_id、type、content、next_follow_time、creator_id索引 (customer_id, created_at desc)
crm_owner_log归属变更日志customer_id、from_owner、to_owner、reason、operator_id索引 (customer_id, created_at)
crm_customer_tag客户标签关联customer_id、tag_id联合主键 (customer_id, tag_id)

索引这块说两个坑。crm_follow_up的索引必须带created_at desc,因为详情页时间轴永远是按时间倒序取,只建customer_id单列索引会导致每次都要回表排序。crm_customer的(owner_id, status)联合索引顺序不能反,列表页最高频的查询就是「某人的跟进中客户」,把status放前面选择性太低,索引基本失效。

跟进记录表要不要冗余客户名称?我一般冗余一份customer_name快照,因为销售看跟进列表时希望直接看到客户名,不冗余就要 join,而客户改名是低频动作,快照过期可以接受。

4.2 客户状态机的六个状态与流转条件

状态字段最忌讳「谁都能改」。我一般把状态设计成只能通过动作接口变更,每个动作对应一条明确的流转规则,前端不提供「直接改状态」的下拉框。

当前状态触发动作目标状态前置条件可操作角色
待分配领取跟进中客户在公海,且当前用户有领取额度销售
待分配指派跟进中指定归属人存在且在职主管及以上
跟进中成交已成交至少关联一个已赢单商机销售及主管
跟进中暂缓暂缓填写暂缓原因与唤醒日期销售及主管
跟进中公海回收待分配超过 N 天无跟进记录,N 可配系统
暂缓唤醒跟进中到达唤醒日期或手动唤醒销售及主管
已成交流失流失填写流失原因主管及以上
任意合并被合并目标客户存在且未删除主管及以上

这张表里有两个设计决策值得展开。第一,「成交」不提供手动按钮给销售自由点,必须挂在商机上,原因是成交状态直接关联业绩统计,如果允许空手点成交,财务口径一定对不上。第二,「公海回收」是系统动作,不占用人工操作权限,但要在日志里留一条系统记录,方便销售事后申诉。

状态和公海是两套概念:状态描述客户的生命周期阶段,公海描述归属关系。一个客户可以处于「跟进中」但被标记为待回收,这两个字段不要合并成一个。

4.3 跟进记录与归属变更:留痕要留到能复盘的程度

跟进记录的字段不多,但每一条都要有用:类型(电话/拜访/邮件/其他)、内容(富文本,限 2000 字)、下次跟进时间、附件、创建人、创建时间。防重复提交用「同一客户 30 秒内相同内容不重复写入」的规则,比前端按钮置灰更可靠,因为网络慢的时候用户会连点。

归属变更日志要记五个要素:谁操作的、什么时候、从谁转到谁、变更原因、是单条还是批量。批量的场景在人员离职交接时特别常见,一次转几百个客户,如果日志只记一条「批量转移」,事后根本没法复盘哪个客户被转到了哪里,所以批量操作要拆成 N 条明细写。

公海回收规则我一般做成可配置的:超过 N 天未跟进自动回收、回收前 M 天给销售发提醒、每人最多持有 X 个客户。这三个参数在 PRD 里要写默认值,比如 N=30、M=3、X=200,并且明确说明「参数由管理员在后台修改,修改后次日生效」。规则一旦写死,业务侧调整一次就要发一次版,这是很多人踩过的坑。

5. 避坑与排查:客户管理 PRD 落地最容易翻车的五个地方

前面讲的是怎么把 PRD 变成能跑的系统,这一章讲的是上线之后一定会遇到的事。下面五条都是我在实际项目里撞过的,按「现象 → 原因 → 解决」记下来,照着排查能省不少时间。

5.1 数据层的三个坑:重复客户、脏手机号、删不干净

现象一:同一家公司在系统里出现三到五条记录,销售各跟各的,老板看到的客户总数虚高。原因不是查重没做,而是查重做在了前端,导入、接口、手工新建三条入口里只有手工新建走了查重。解决:把查重下沉到服务层,所有写入口统一走一个createCustomer方法,方法内部先按「名称 + 信用代码」查一次,命中就返回已有 ID 并提示关联;批量导入走单独的导入处理器,导入前先跑一遍全量比对,把疑似重复的行标黄让运营人工确认。

现象二:客户列表里手机号格式五花八门,带空格、带横杠、带 +86,按手机号搜不到人。原因是输入时没做归一化,前端校验只管提交,不管存储。解决:入库前统一清洗,去掉空格和横杠,去掉 +86 前缀,只保留 11 位数字;历史数据用一次性脚本刷一遍,刷之前先导出备份,脚本按「清洗后是否与其他记录冲突」分两批处理,冲突的进人工队列。

现象三:客户被删除后,跟进记录、商机、合同还在,详情页点进去一片空白但数据仍在库里。原因是用了物理删除,且没有处理关联表。解决:客户表统一软删除,is_deleted置 1,所有查询默认带is_deleted = 0;关联表不删,靠客户的软删除标记在查询时过滤。这条规则要写进开发规范,不能靠每个人自觉。

5.2 流程与权限的两个坑:公海误伤、导出泄数据

现象四:销售休了三天假回来,名下十几个客户被系统自动收进公海,客户直接投诉。原因是回收规则只看「最后跟进时间」,没有考虑请假、出差这些状态。解决:回收前加一道校验,归属人在请假状态或者在出差审批单有效期内的,跳过回收并记录一条「豁免」日志;同时把回收动作从「直接改归属」改成「先进入待回收池,24 小时后执行」,给销售留一个后悔药窗口。

现象五:一次导出操作把全公司的客户名单导了出去,导出的还是带手机号的完整表格。原因是导出接口复用了列表查询,只校验了「登录」,没校验「数据范围」。解决:导出走独立接口,独立权限点,导出前二次校验数据范围,导出字段做白名单(手机号中间四位打码),单次导出上限 5000 条,超过上限要求分批并记录导出日志。导出日志要记谁、什么时候、导了哪些条件、多少条,这条日志在出问题时是唯一的追溯依据。

这五条里,有三条的共同点都是「校验只做在一个入口」。客户管理这类系统入口多、角色多、批量操作多,任何一条规则如果只在前端或者只在某一个接口里实现,早晚会被绕过去。

6. 验收与迭代:怎么判断这份 PRD 真的落地了

PRD 写完不算落地,功能上线也不算落地,真正的验收标准是「运营能自己配、销售能自己用、出问题能自己查」。我一般会在上线前跑一张验收表,每一项都要有明确的判定标准和验证方法,测试同学照着点,产品同学照着签字。

验收项判定标准验证方法
客户唯一性同名同信用代码无法重复创建手工新建两次,第二次提示关联
数据权限销售 A 无法通过 URL 访问销售 B 的客户换 ID 直接请求详情接口,返回 403
状态流转所有状态变更只能在动作接口中发生直接改库状态后,页面刷新应被日志纠正
公海回收N 天未跟进客户进入待回收池造一条 31 天前的数据,跑定时任务
跟进留痕每次归属变更产生一条明细日志批量转移 10 个客户,日志应有 10 条
导出打码导出文件手机号中间四位为星号导出一份,打开检查
并发编辑两人同时编辑,后提交者收到冲突提示两个浏览器同时打开同一客户提交

这张表里我最看重「数据权限」和「状态流转」两项,因为这两项出问题不会报错,只会悄悄错,等到发现的时候数据已经乱了。验收之外,还有一件我每次都会做的事:在上线后第一周,每天拉一次操作日志,看有没有人反复执行同一个失败动作。比如某个销售一天内连续 20 次点「领取」都失败,大概率是领取额度或者公海规则配错了,这比等用户来投诉快得多。

迭代节奏上,客户管理模块我建议按「字段 → 流程 → 报表」的顺序推进,先把字段和唯一性做扎实,再做状态机和公海规则,最后才是统计报表。反过来做,报表口径一变就要回头改数据模型,返工量是前者的好几倍。

我自己在这类项目上养成的习惯是:每加一个字段,先问一句「它会不会被用来筛选或者做权限判断」,会,就进主表并建索引;不会,就进扩展表。这个习惯帮我躲过了很多次「列表页越用越慢」的投诉。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表