一、项目背景与痛点
在商贸、服务、科技类企业中,客户资源是核心资产。传统客户管理普遍采用Excel表格、纸质档案、销售私人笔记的方式,随着客户数量增多、销售团队扩张、业务流程复杂化,管理漏洞不断凸显,核心痛点如下:
- 客户资料分散易流失:客户信息存放于销售个人电脑、手机或纸质台账,员工离职直接带走资源,企业客户资产严重流失;
- 跟进过程无记录:销售拜访、电话沟通、需求对接仅靠记忆,管理层无法掌握跟进进度,也难以复盘沟通内容;
- 商机管控混乱:潜在意向客户、待洽谈商机没有统一划分,跟进优先级不明,易造成意向客户被冷落、错失订单;
- 合同与回款脱节:签约合同、收款计划、实际回款无联动,逾期款项无法及时预警,坏账风险升高;
- 客户群体无分层:无法按照活跃度、成交价值、意向等级划分客户,不能针对性开展维护与营销;
- 团队协作效率低:销售之间无法共享客户资源与跟进记录,重复对接客户,造成人力浪费;
- 经营数据难统计:客户总量、成交率、销售额、回款率等数据依靠人工汇总,效率低且误差大。
针对以上行业痛点,本次基于Python+Django4.2 + MySQL + Ajax + ECharts 搭建轻量化企业CRM客户关系管理系统,实现客户全生命周期管理、销售跟进、商机追踪、合同管理、回款管控、客户分层、数据统计全套闭环。本项目开辟企业客户关系管理 全新赛道,和日志、天气、在线考试、智能图书、考勤、租赁、物业、记账、音乐、进销存等所有往期项目业务、功能、代码完全无重复。
二、核心目标与定位
本项目核心目标:搭建轻量化企业CRM平台,实现客户档案统一建档→销售日常跟进→意向商机挖掘与追踪→合同拟定签约→回款计划与逾期提醒→客户分层运营→团队协作共享→经营数据分析完整闭环,把分散的客户资源转为企业公有资产,规范销售流程、提升成交率、降低坏账风险。
项目精准定位:面向中小商贸、服务、科技公司的轻量化CRM系统,采用Django原生MVT架构,部署简单、运维成本低;划分超级管理员、销售主管、普通销售三类角色,权限分级、数据隔离,支持团队资源共享;主打客户统一管控、流程标准化、跟进可追溯、回款可预警、数据可视化。
核心设计理念:客户资产公有化、销售流程规范化、商机跟进全程化、合同回款联动化、客户运营精细化,解决客户流失、跟进无序、回款滞后、数据缺失等核心问题。
三、整体技术方案
3.1 技术栈选型
本项目采用轻量化、高可维护的技术栈组合,确保系统稳定运行的同时降低运维成本:
- Web后端:Python 3.11 + Django 4.2 原生MVT架构
- 数据库:MySQL 8.0,结构化存储CRM全业务数据
- 时间处理:datetime 模块实现账期、逾期、跟进时间计算
- 异步交互:Ajax 完成无刷新表单提交、状态变更
- 状态管控:自定义枚举类,定义客户、商机、合同多状态
- 权限控制:自定义中间件,实现三级角色权限隔离
- 文件管理:Django Media 存放合同、资料附件
- 数据可视化:ECharts 制作销售报表、客户分析图表
3.2 系统分层架构
基于上述技术栈,我们设计了清晰的分层架构,确保各业务模块职责分离、数据流转有序:
#mermaid-svg-36zmQW0tefkNuhsc{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-36zmQW0tefkNuhsc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-36zmQW0tefkNuhsc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-36zmQW0tefkNuhsc .error-icon{fill:#552222;}#mermaid-svg-36zmQW0tefkNuhsc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-36zmQW0tefkNuhsc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-36zmQW0tefkNuhsc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-36zmQW0tefkNuhsc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-36zmQW0tefkNuhsc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-36zmQW0tefkNuhsc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-36zmQW0tefkNuhsc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-36zmQW0tefkNuhsc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-36zmQW0tefkNuhsc .marker.cross{stroke:#333333;}#mermaid-svg-36zmQW0tefkNuhsc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-36zmQW0tefkNuhsc p{margin:0;}#mermaid-svg-36zmQW0tefkNuhsc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-36zmQW0tefkNuhsc .cluster-label text{fill:#333;}#mermaid-svg-36zmQW0tefkNuhsc .cluster-label span{color:#333;}#mermaid-svg-36zmQW0tefkNuhsc .cluster-label span p{background-color:transparent;}#mermaid-svg-36zmQW0tefkNuhsc .label text,#mermaid-svg-36zmQW0tefkNuhsc span{fill:#333;color:#333;}#mermaid-svg-36zmQW0tefkNuhsc .node rect,#mermaid-svg-36zmQW0tefkNuhsc .node circle,#mermaid-svg-36zmQW0tefkNuhsc .node ellipse,#mermaid-svg-36zmQW0tefkNuhsc .node polygon,#mermaid-svg-36zmQW0tefkNuhsc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-36zmQW0tefkNuhsc .rough-node .label text,#mermaid-svg-36zmQW0tefkNuhsc .node .label text,#mermaid-svg-36zmQW0tefkNuhsc .image-shape .label,#mermaid-svg-36zmQW0tefkNuhsc .icon-shape .label{text-anchor:middle;}#mermaid-svg-36zmQW0tefkNuhsc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-36zmQW0tefkNuhsc .rough-node .label,#mermaid-svg-36zmQW0tefkNuhsc .node .label,#mermaid-svg-36zmQW0tefkNuhsc .image-shape .label,#mermaid-svg-36zmQW0tefkNuhsc .icon-shape .label{text-align:center;}#mermaid-svg-36zmQW0tefkNuhsc .node.clickable{cursor:pointer;}#mermaid-svg-36zmQW0tefkNuhsc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-36zmQW0tefkNuhsc .arrowheadPath{fill:#333333;}#mermaid-svg-36zmQW0tefkNuhsc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-36zmQW0tefkNuhsc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-36zmQW0tefkNuhsc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-36zmQW0tefkNuhsc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-36zmQW0tefkNuhsc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-36zmQW0tefkNuhsc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-36zmQW0tefkNuhsc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-36zmQW0tefkNuhsc .cluster text{fill:#333;}#mermaid-svg-36zmQW0tefkNuhsc .cluster span{color:#333;}#mermaid-svg-36zmQW0tefkNuhsc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-36zmQW0tefkNuhsc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-36zmQW0tefkNuhsc rect.text{fill:none;stroke-width:0;}#mermaid-svg-36zmQW0tefkNuhsc .icon-shape,#mermaid-svg-36zmQW0tefkNuhsc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-36zmQW0tefkNuhsc .icon-shape p,#mermaid-svg-36zmQW0tefkNuhsc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-36zmQW0tefkNuhsc .icon-shape .label rect,#mermaid-svg-36zmQW0tefkNuhsc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-36zmQW0tefkNuhsc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-36zmQW0tefkNuhsc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-36zmQW0tefkNuhsc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 底层技术底座
Python3.11 + Django4.2
原生MVT架构
MySQL 8.0
全业务数据存储
datetime
账期与逾期计算
Ajax
无刷新交互
枚举类
全生命周期状态管理
中间件
多角色权限控制
ECharts
销售数据可视化
Media
文件托管
客户档案层
新增客户、基础信息录入、公海分配
日常跟进层
拜访/通话记录登记、跟进提醒
商机管理层
意向商机创建、状态流转、优先级划分
合同签约层
合同录入、附件上传、签约归档
回款管控层
回款计划、逾期判断、收款登记
客户分层层
按等级/活跃度划分客户群体
数据统计层
客户量、成交率、销售额图表统计
3.3 数据流转与模块协作
各层之间通过标准化的数据接口进行通信,确保业务流程的连贯性:
- 客户档案层 → 日常跟进层:新客户录入后自动生成首次跟进任务
- 日常跟进层 → 商机管理层:有效跟进记录触发商机创建流程
- 商机管理层 → 合同签约层:商机状态转为"已成交"时启动合同创建
- 合同签约层 → 回款管控层:合同生效后自动生成回款计划
- 回款管控层 → 客户分层层:回款记录更新客户价值评级
- 客户分层层 → 数据统计层:分层数据汇总为经营分析报表
所有业务层均基于底层技术底座提供的统一能力,包括数据持久化、权限校验、时间计算和前端交互,确保技术实现的一致性。
四、核心能力模块详解
1. 客户档案与公海管理模块
统一收拢客户资源,防止员工离职造成资产流失,支持公海流转分配:
- 完整档案录入:记录客户名称、行业、联系人、联系方式、地址、来源、合作状态;
- 客户公海机制:长时间无跟进、员工离职客户自动流入公海,可重新分配给其他销售;
- 分配与转移:管理员/主管可手动分配客户、跨销售转移客户;
- 多条件检索:按行业、来源、合作状态、归属人快速筛选客户。
2. 销售跟进记录模块(核心亮点)
全程记录对接过程,做到每一次沟通可追溯、可复盘:
- 跟进类型区分:支持电话沟通、线下拜访、线上洽谈、需求对接等类型;
- 跟进内容登记:记录沟通要点、客户诉求、后续计划,支持上传沟通凭证;
- 定时提醒:设置下次跟进时间,到期自动提醒销售;
- 历史追溯:完整查看该客户所有历史跟进记录,掌握合作全过程。
3. 意向商机管理模块
挖掘潜在订单,区分商机等级,优先跟进高意向客户:
- 商机创建:绑定对应客户,填写产品意向、预估金额、预计成交时间;
- 商机分级:分为高/中/低三级意向,区分跟进优先级;
- 状态流转:待洽谈、跟进中、已成交、已流失四种状态自动切换;
- 流失原因登记:商机未成交时记录流失原因,用于后期复盘。
4. 合同管理模块
标准化电子合同归档,关联客户与商机,实现业务链路打通:
- 合同录入:填写合同编号、签约日期、合作产品、合同金额、服务周期;
- 附件上传:支持上传合同扫描件、电子版,在线预览下载;
- 合同状态:正常执行、已到期、已终止状态管控;
- 关联溯源:一键查看合同对应的客户、前期跟进、商机记录。
5. 回款计划与逾期提醒模块
搭建回款全流程管控,降低坏账与逾期风险:
- 回款计划配置:根据合同设置多期回款、每期金额、回款截止日期;
- 收款登记:实际到账后在线登记,标记已回款;
- 逾期判定:系统自动对比当前时间,标记逾期款项;
- 逾期提醒:集中展示所有逾期账单,督促销售跟进催收。
6. 客户分层运营模块
按照价值与活跃度划分客户群体,实现精细化运营:
- 等级划分:VIP客户、重点客户、普通客户、潜在客户四级分层;
- 活跃度统计:根据跟进频次、成交记录自动判定客户活跃度;
- 分层筛选:按客户等级分组,针对性开展回访、营销活动;
- 等级调整:管理员可手动调整客户等级。
7. 团队权限与协作模块
区分岗位权限,兼顾资源管控与团队协作:
- 角色权限:管理员全局配置;主管查看全员数据、分配客户;普通销售仅管理自有客户;
- 数据共享:团队内可按需共享客户资料与跟进记录;
- 操作日志:客户分配、转移、编辑全程留痕;
- 数据隔离:不同销售之间默认不可查看对方私有客户。
8. 经营数据分析模块
多维度统计销售与客户数据,为管理决策提供依据:
- 客户统计:总客户数、新增客户、公海客户、各等级客户占比;
- 商机分析:商机总量、成交率、流失率、各级意向分布;
- 业绩统计:合同总额、已回款、待回款、逾期金额;
- 员工业绩:按销售个人统计跟进量、成交单、销售额排行。
五、创新价值与亮点
- 客户资产企业化 客户统一入系统,依托公海机制避免员工离职带走资源,牢牢把控企业核心资产;
- 全流程可追溯 跟进、商机、合同、回款每一步均有记录,业务复盘、问题排查有据可依;
- 商机+合同+回款联动 业务链路打通,从意向到成交再到收款全闭环管控;
- 双重预警机制 跟进提醒+回款逾期提醒,减少漏跟进、款项逾期问题;
- 精细化客户分层 区分客户价值,实现差异化维护,提升复购与成交概率。
六、应用前景与落地场景
- 中小型商贸企业 产品销售类公司统一管理经销商、终端客户与销售团队;
- 软件/服务型公司 科技、咨询、服务企业管理意向客户与签约项目;
- 线下实体门店/渠道商
- 区域代理商、渠道商家管理下游客户资源;
- 创业团队/销售小组 小团队轻量化客户与业绩管理,低成本替代商用CRM;
- 毕业设计/求职项目 企业级业务系统,CRM属于职场主流技术场景,差异化极强。
七、完整代码结构示例
1. 项目整体目录结构
python
django-crm-system/
├── manage.py
├── crm_project/
│ ├── settings.py # 数据库、文件、权限、超时配置
│ ├── urls.py # 全局路由分发
│ └── middleware.py # 角色权限中间件
├── apps/
│ ├── user_role/ # 用户、角色、员工账号模块
│ ├── customer/ # 客户档案、公海分配模块
│ ├── follow_record/ # 销售跟进、提醒模块
│ ├── business/ # 意向商机、状态流转模块
│ ├── contract/ # 合同管理、附件模块
│ ├── payment/ # 回款计划、逾期提醒模块
│ ├── customer_level/ # 客户分层、等级管理模块
│ └── data_stat/ # 销售数据分析、图表模块
├── core/
│ ├── time_calc.py # 逾期、跟进时间计算工具
│ ├── status_flow.py # 状态流转工具
│ ├── data_filter.py # 数据筛选工具
│ └── file_handle.py # 附件处理工具
├── static/
├── templates/
├── media/ # 合同、资料附件存储
├── requirements.txt
└── readme.md
</pre>
### 2. 核心可运行代码片段
#### 示例1:客户、跟进、商机、合同、回款核心模型
```python
from django.db import models
from django.contrib.auth.models
# 客户合作状态
CUSTOMER_STATUS = (
("potential", "潜在客户"),
("cooper", "合作中"),
("stop", "终止合作"),
("public", "公海客户"),
)
# 商机意向等级
BUSINESS_LEVEL = (
("high", "高意向"),
("mid", "中意向"),
("low", "低意向"),
)
# 商机状态
BUSINESS_STATUS = (
("talk", "待洽谈"),
("follow", "跟进中"),
("success", "已成交"),
("lose", "已流失"),
)
# 回款状态
PAY_STATUS = (
("wait", "待回款"),
("payed", "已回款"),
("overdue", "已逾期"),
)
class Customer(models.Model):
"""客户档案模型"""
name = models.CharField(max=60, verbose="客户名称")
industry = models.CharField(max=40, verbose="所属行业")
contact = models.CharField(max=30, verbose="联系人")
phone = models.CharField(max=11, verbose="联系电话")
source = models.CharField(max=30, verbose="客户来源")
owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose="归属销售")
cus_status = models.CharField(max=12, choices=CUSTOMER_STATUS, default="potential")
create_time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class FollowRecord(models.Model):
"""跟进记录模型"""
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
follow_user = models.ForeignKey(User, on_delete=models.CASCADE)
follow_type = models.CharField(max=20, verbose="跟进类型")
content = models.TextField(verbose="沟通内容")
next_follow = models.DateTime(null=True, blank=True, verbose="下次跟进时间")
create_time = models.DateTime(auto_now_add=True)
class BusinessOpp(models.Model):
"""意向商机模型"""
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.CharField(max=100, verbose="意向产品")
estimate_money = models.DecimalField(max_digits=10, decimal_places=2)
bus_level = models.CharField(max=8, choices=BUSINESS_LEVEL)
bus_status = models.CharField(max=10, choices=BUSINESS_STATUS, default="talk")
lose_reason = models.CharField(max=200, blank=True, verbose="流失原因")
create_time = models.DateTime(auto_now_add=True)
class Contract(models.Model):
"""合同模型"""
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
business = models.ForeignKey(BusinessOpp, on_delete=models.SET_NULL, null=True)
contract_sn = models.CharField(max=32, unique=True, verbose="合同编号")
total_money = models.DecimalField(max_digits=10, decimal_places=2)
sign_date = models.DateField(verbose="签约日期")
contract_file = models.FileField(upload="contract/", blank=True)
create_time = models.DateTime(auto_now_add=True)
class PaymentPlan(models.Model):
"""回款计划模型"""
contract = models.ForeignKey(Contract, on_delete=models.CASCADE)
plan_money = models.DecimalField(max_digits=10, decimal_places=2)
plan_date = models.DateField(verbose="回款截止日")
pay_status = models.CharField(max=10, choices=PAY_STATUS, default="wait")
actual_date = models.DateField(null=True, blank=True, verbose="实际回款日")
create_time = models.DateTime(auto_now_add=True)
示例2 逾期&跟进时间计算工具(core/time_calc.py)
python
from datetime import date, datetime
class TimeCalc:
@classmethod
def is_overdue(cls, plan_date):
"""判断回款是否逾期"""
return date.today() > plan_date
@classmethod
def is_need_follow(cls, next_follow):
"""判断是否到达跟进提醒时间"""
if not next_follow:
return False
return datetime.now() >= next_follow
示例3 客户新增视图
python
from django.views import View
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.shortcuts import redirect, render
from django.contrib import messages
from apps.customer.models import Customer
@method_decorator(login_required, name="dispatch")
class CustomerAddView(View):
def get(self, request):
return render(request, "customer_add.html")
def post(self, request):
name = request.POST.get("name")
industry = request.POST.get("industry")
contact = request.POST.get("contact")
phone = request.POST.get("phone")
source = request.POST.get("source")
if not all([name, contact, phone]):
messages.error("请填写必填客户信息!")
return redirect("customer_add")
Customer.objects.create(
name=name,
industry=industry,
contact=contact,
phone=phone,
source=source,
owner=request.user
)
messages.success("客户信息新增成功!")
return redirect("customer_list")
八、总结与展望
本篇聚焦企业CRM客户关系管理 赛道,基于Python+Django打造全链路客户管理系统,和日志、天气、在线考试、智能图书、进销存、租赁、考勤、物业、记账、音乐等所有往期项目完全独立。项目结合状态流转、时间判定、多角色权限、文件附件、聚合统计、数据可视化等技术,完全贴合中小企业销售团队真实业务流程,是职场高频应用的企业级系统。
代码结构规范、模块化清晰,可直接私有化部署使用;同时作为毕设、求职项目,CRM系统业务专业性强、技术覆盖面广,具备很高竞争力。
后续迭代规划
- 新增客户跟进、回款逾期短信/站内消息提醒;
- 集成客户公海自动回收规则,自定义无跟进天数自动流转;
- 新增销售绩效考核模块,结合业绩自动核算绩效;
- 对接简单工作流,实现合同多级线上审批。