毕业设计实战:基于SSM的客户关系管理系统毕设全流程指南✨

86 阅读10分钟

毕业设计实战:基于SSM的客户关系管理系统毕设全流程指南✨

去年做客户关系管理系统毕设时,我在客户积分和沟通记录的关联逻辑上卡了整整4天——一开始没处理"积分自动计算"问题,客户沟通后积分没实时更新,导师演示时直接发现了这个重大业务漏洞😫 经过反复修改优化,终于总结出了这套客户关系管理系统毕设实战经验!

一、需求分析:抓住客户管理核心业务

刚开始我想做一个"万能企业管理系统",包含了OA办公、财务管理、人力资源等模块,结果导师说"重点不突出,核心客户关系管理不清晰"。后来明白,客户关系管理系统要围绕线索-客户-沟通-积分这个核心业务链展开。

1. 核心用户角色与功能

系统主要面向两类用户,功能定位要精准:

  • 管理员端(系统管理核心):

    • 员工管理:管理员工信息、设置员工权限、禁用/启用账号
    • 客户管理:审核客户信息、分配客户给员工、查看客户详情
    • 线索管理:管理潜在客户线索、分配线索跟进、转化线索为客户
    • 数据统计:客户数据分析、员工业绩统计、积分排名统计
  • 员工端(业务执行核心):

    • 客户跟进:管理分配到的客户、记录客户信息、更新客户状态
    • 沟通记录:记录与客户的沟通内容、设置下次跟进时间、上传沟通附件
    • 积分管理:为客户添加积分、查看积分明细、兑换积分奖励
    • 线索转化:跟进潜在客户线索、将合格线索转化为正式客户

2. 需求分析实战技巧

  • 企业调研很重要:我联系了几个销售团队,发现他们最需要"客户状态跟踪"功能,于是重点设计了客户生命周期管理
  • 绘制业务流程图:用DrawIO画出"线索获取→员工跟进→转化为客户→持续沟通→积分管理"的完整流程,答辩时清晰展示业务逻辑
  • 明确业务规则:如"沟通后自动记录积分""线索7天内必须跟进""客户分配给员工后不能重复分配"等约束条件

3. 可行性分析要点

  • 技术可行性:SSM+MySQL技术成熟,企业应用广泛
  • 经济可行性:全部使用开源工具,零开发成本
  • 操作可行性:界面设计参考主流CRM系统,销售易上手

二、技术选型:企业级开发方案

曾经尝试用Spring Boot,但为了体现传统框架掌握程度,最终选择SSM框架,更显技术功底!

1. 技术栈选择理由

技术组件选择理由避坑提醒
Spring 5.xIOC和AOP支持完善注意bean的配置管理
Spring MVC请求处理流程清晰注意拦截器配置
MyBatisSQL可控性强,方便优化注意XML映射文件配置
MySQL 8.0事务支持完善,适合企业系统配置连接池参数
Maven依赖管理规范注意依赖冲突解决
Tomcat 9稳定可靠配置虚拟内存大小

2. 开发环境搭建

<!-- pom.xml 关键依赖 -->
<dependencies>
    <!-- Spring MVC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.8.RELEASE</version>
    </dependency>
    <!-- MyBatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.5</version>
    </dependency>
    <!-- MyBatis-Spring -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.5</version>
    </dependency>
    <!-- MySQL驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.21</version>
    </dependency>
</dependencies>

三、数据库设计:客户关系业务数据建模

最初设计时把客户信息和沟通记录放在同一张表,导致查询性能低下。重新设计后按业务模块分表,系统响应速度大幅提升。

1. 核心数据表设计

客户表(kehu)

CREATE TABLE `kehu` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `yuangong_id` int(11) NOT NULL COMMENT '负责员工ID',
  `kehu_name` varchar(100) NOT NULL COMMENT '客户姓名',
  `kehu_phone` varchar(20) NOT NULL COMMENT '客户手机号',
  `kehu_id_number` varchar(20) DEFAULT NULL COMMENT '客户身份证号',
  `kehu_photo` varchar(255) DEFAULT NULL COMMENT '客户照片',
  `sex_types` int(11) DEFAULT NULL COMMENT '性别',
  `kehu_email` varchar(100) DEFAULT NULL COMMENT '电子邮箱',
  `kehu_jifen_number` decimal(10,2) DEFAULT '0.00' COMMENT '积分',
  `kehu_level` int(11) DEFAULT '1' COMMENT '客户等级:1普通/2VIP/3SVIP',
  `kehu_status` int(11) DEFAULT '1' COMMENT '客户状态:1潜在/2活跃/3沉默/4流失',
  `kehu_content` text COMMENT '客户详细介绍',
  `last_contact_time` datetime DEFAULT NULL COMMENT '最后联系时间',
  `next_contact_time` datetime DEFAULT NULL COMMENT '下次联系时间',
  `insert_time` datetime DEFAULT NULL COMMENT '添加时间',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_phone` (`kehu_phone`),
  KEY `idx_yuangong` (`yuangong_id`),
  KEY `idx_status` (`kehu_status`),
  KEY `idx_level` (`kehu_level`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户表';

沟通记录表(goutongjilu)

CREATE TABLE `goutongjilu` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `yuangong_id` int(11) NOT NULL COMMENT '员工ID',
  `kehu_id` int(11) NOT NULL COMMENT '客户ID',
  `goutong_name` varchar(200) NOT NULL COMMENT '沟通标题',
  `goutong_types` int(11) DEFAULT NULL COMMENT '沟通类型',
  `goutong_time` datetime NOT NULL COMMENT '沟通时间',
  `goutong_content` text NOT NULL COMMENT '沟通详情',
  `goutong_result` text COMMENT '沟通结果',
  `next_plan` text COMMENT '下次计划',
  `jifen_add` decimal(10,2) DEFAULT '0.00' COMMENT '本次增加积分',
  `insert_time` datetime DEFAULT NULL COMMENT '添加时间',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_yuangong` (`yuangong_id`),
  KEY `idx_kehu` (`kehu_id`),
  KEY `idx_time` (`goutong_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='沟通记录表';

客户积分表(kehujifen)

CREATE TABLE `kehujifen` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `yuangong_id` int(11) NOT NULL COMMENT '员工ID',
  `kehu_id` int(11) NOT NULL COMMENT '客户ID',
  `kehujifen_types` int(11) NOT NULL COMMENT '增加类型',
  `kehujifen_content` text COMMENT '备注',
  `kehujifen_number` decimal(10,2) NOT NULL COMMENT '增加积分数量',
  `related_id` int(11) DEFAULT NULL COMMENT '关联记录ID',
  `related_type` varchar(50) DEFAULT NULL COMMENT '关联类型',
  `insert_time` datetime DEFAULT NULL COMMENT '增加时间',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_kehu` (`kehu_id`),
  KEY `idx_yuangong` (`yuangong_id`),
  KEY `idx_time` (`insert_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户积分表';

2. 表关系设计要点

  • 状态字段设计:客户状态(潜在/活跃/沉默/流失)、客户等级(普通/VIP/SVIP)
  • 积分关联:沟通记录与积分变动关联,实现积分自动计算
  • 时间跟踪:记录最后联系时间和下次联系时间,方便跟进

四、核心功能实现与代码详解

1. 客户管理模块(核心业务功能)

Service层实现:

@Service
public class KehuServiceImpl implements KehuService {
    
    @Autowired
    private KehuMapper kehuMapper;
    
    @Autowired
    private KehujifenMapper kehujifenMapper;
    
    @Autowired
    private GoutongjiluMapper goutongjiluMapper;

    @Override
    @Transactional
    public void addKehu(KehuEntity kehu) {
        // 1. 检查手机号是否重复
        Integer count = kehuMapper.selectCount(
            new EntityWrapper<KehuEntity>()
                .eq("kehu_phone", kehu.getKehuPhone())
        );
        if (count > 0) {
            throw new RuntimeException("客户手机号已存在");
        }
        
        // 2. 设置初始状态
        kehu.setKehuStatus(1); // 潜在客户
        kehu.setKehuLevel(1); // 普通客户
        kehu.setKehuJifenNumber(new BigDecimal("0")); // 初始积分
        kehu.setInsertTime(new Date());
        
        kehuMapper.insert(kehu);
    }

    @Override
    @Transactional
    public void updateKehuStatus(Integer kehuId, Integer status) {
        KehuEntity kehu = new KehuEntity();
        kehu.setId(kehuId);
        kehu.setKehuStatus(status);
        kehuMapper.updateById(kehu);
        
        // 记录状态变更日志
        logKehuStatusChange(kehuId, status);
    }
    
    @Override
    public PageUtils queryKehuPage(Map<String, Object> params, Integer yuangongId) {
        Page<KehuEntity> page = new Page<>(
            Integer.parseInt(params.get("page").toString()),
            Integer.parseInt(params.get("limit").toString())
        );
        
        EntityWrapper<KehuEntity> ew = new EntityWrapper<>();
        
        // 员工只能查看自己的客户
        if (yuangongId != null) {
            ew.eq("yuangong_id", yuangongId);
        }
        
        // 客户姓名模糊查询
        if (params.get("kehuName") != null) {
            ew.like("kehu_name", params.get("kehuName").toString());
        }
        
        // 客户状态筛选
        if (params.get("kehuStatus") != null) {
            ew.eq("kehu_status", params.get("kehuStatus"));
        }
        
        // 客户等级筛选
        if (params.get("kehuLevel") != null) {
            ew.eq("kehu_level", params.get("kehuLevel"));
        }
        
        ew.orderBy("insert_time", false);
        
        IPage<KehuEntity> result = kehuMapper.selectPage(page, ew);
        return new PageUtils(result);
    }
}

Controller层:

@Controller
@RequestMapping("/kehu")
public class KehuController {
    
    @Autowired
    private KehuService kehuService;

    @RequestMapping("/list")
    public String list(@RequestParam Map<String, Object> params, 
                      HttpServletRequest request, Model model) {
        // 获取当前登录员工
        YuangongEntity yuangong = (YuangongEntity) request.getSession().getAttribute("yuangong");
        
        PageUtils page = kehuService.queryKehuPage(params, yuangong.getId());
        model.addAttribute("page", page);
        model.addAttribute("params", params);
        return "kehu/list";
    }

    @PostMapping("/save")
    @ResponseBody
    public R save(@RequestBody KehuEntity kehu, HttpServletRequest request) {
        try {
            // 设置负责员工
            YuangongEntity yuangong = (YuangongEntity) request.getSession().getAttribute("yuangong");
            kehu.setYuangongId(yuangong.getId());
            
            kehuService.addKehu(kehu);
            return R.ok();
        } catch (Exception e) {
            return R.error(e.getMessage());
        }
    }
}

2. 沟通记录与积分管理模块

Service层实现:

@Service
public class GoutongjiluServiceImpl implements GoutongjiluService {
    
    @Autowired
    private GoutongjiluMapper goutongjiluMapper;
    
    @Autowired
    private KehuMapper kehuMapper;
    
    @Autowired
    private KehujifenMapper kehujifenMapper;

    @Override
    @Transactional
    public void addGoutong(GoutongjiluEntity goutong) {
        // 1. 保存沟通记录
        goutong.setInsertTime(new Date());
        goutongjiluMapper.insert(goutong);
        
        // 2. 自动计算并添加积分
        BigDecimal jifenAdd = calculateJifen(goutong);
        if (jifenAdd.compareTo(BigDecimal.ZERO) > 0) {
            addKehuJifen(goutong, jifenAdd);
        }
        
        // 3. 更新客户最后联系时间
        updateKehuContactTime(goutong.getKehuId());
    }
    
    private BigDecimal calculateJifen(GoutongjiluEntity goutong) {
        // 根据沟通类型计算积分
        // 1-电话沟通:10分,2-面谈:20分,3-微信沟通:5分,4-邮件沟通:3分
        switch (goutong.getGoutongTypes()) {
            case 1: return new BigDecimal("10");
            case 2: return new BigDecimal("20");
            case 3: return new BigDecimal("5");
            case 4: return new BigDecimal("3");
            default: return BigDecimal.ZERO;
        }
    }
    
    private void addKehuJifen(GoutongjiluEntity goutong, BigDecimal jifenAdd) {
        // 添加积分记录
        KehujifenEntity jifen = new KehujifenEntity();
        jifen.setYuangongId(goutong.getYuangongId());
        jifen.setKehuId(goutong.getKehuId());
        jifen.setKehujifenTypes(1); // 沟通增加
        jifen.setKehujifenContent("沟通记录积分:" + goutong.getGoutongName());
        jifen.setKehujifenNumber(jifenAdd);
        jifen.setRelatedId(goutong.getId());
        jifen.setRelatedType("goutong");
        jifen.setInsertTime(new Date());
        kehujifenMapper.insert(jifen);
        
        // 更新客户总积分
        KehuEntity kehu = kehuMapper.selectById(goutong.getKehuId());
        kehu.setKehuJifenNumber(kehu.getKehuJifenNumber().add(jifenAdd));
        kehuMapper.updateById(kehu);
        
        // 检查是否需要升级客户等级
        checkKehuLevel(kehu);
    }
    
    private void checkKehuLevel(KehuEntity kehu) {
        BigDecimal totalJifen = kehu.getKehuJifenNumber();
        Integer newLevel = kehu.getKehuLevel();
        
        if (totalJifen.compareTo(new BigDecimal("1000")) >= 0) {
            newLevel = 3; // SVIP
        } else if (totalJifen.compareTo(new BigDecimal("500")) >= 0) {
            newLevel = 2; // VIP
        } else {
            newLevel = 1; // 普通
        }
        
        if (!newLevel.equals(kehu.getKehuLevel())) {
            kehu.setKehuLevel(newLevel);
            kehuMapper.updateById(kehu);
        }
    }
}

3. 客户线索转化模块

Service层实现:

@Service
public class KehuxiansuoServiceImpl implements KehuxiansuoService {
    
    @Autowired
    private KehuxiansuoMapper kehuxiansuoMapper;
    
    @Autowired
    private KehuMapper kehuMapper;

    @Override
    @Transactional
    public void convertToKehu(Integer xiansuoId, Integer yuangongId) {
        KehuxiansuoEntity xiansuo = kehuxiansuoMapper.selectById(xiansuoId);
        if (xiansuo == null) {
            throw new RuntimeException("客户线索不存在");
        }
        
        // 检查是否已转化
        if (xiansuo.getConvertStatus() == 1) {
            throw new RuntimeException("该线索已转化为客户");
        }
        
        // 创建客户
        KehuEntity kehu = new KehuEntity();
        kehu.setYuangongId(yuangongId);
        kehu.setKehuName(xiansuo.getKehuxiansuoName());
        kehu.setKehuPhone(xiansuo.getKehuxiansuoPhone());
        kehu.setKehuIdNumber(xiansuo.getKehuxiansuoIdNumber());
        kehu.setKehuPhoto(xiansuo.getKehuxiansuoPhoto());
        kehu.setSexTypes(xiansuo.getSexTypes());
        kehu.setKehuEmail(xiansuo.getKehuxiansuoEmail());
        kehu.setKehuJifenNumber(BigDecimal.ZERO);
        kehu.setKehuStatus(1); // 潜在客户
        kehu.setKehuLevel(1); // 普通客户
        kehu.setInsertTime(new Date());
        
        kehuMapper.insert(kehu);
        
        // 更新线索状态
        xiansuo.setConvertStatus(1); // 已转化
        xiansuo.setConvertTime(new Date());
        xiansuo.setConvertKehuId(kehu.getId());
        kehuxiansuoMapper.updateById(xiansuo);
    }
}

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

五、系统测试:确保客户管理业务流程可靠

曾经以为功能实现就完成了,结果测试时发现沟通后积分没自动计算,紧急加了积分自动计算逻辑。

1. 功能测试用例

客户管理测试:

测试场景操作步骤预期结果
重复客户添加手机号重复的客户提示"客户手机号已存在"
客户转化将线索转化为客户客户创建成功,线索状态更新
状态变更修改客户状态状态更新成功,记录变更日志

沟通积分测试:

测试场景操作步骤预期结果
电话沟通记录电话沟通自动增加10积分
面谈沟通记录面谈沟通自动增加20积分
等级提升积分达到阈值自动升级客户等级

2. 业务规则测试

  • 积分自动计算:不同沟通类型对应不同积分值
  • 等级自动调整:积分达到阈值自动调整客户等级
  • 状态流转:线索转化为客户的状态同步
  • 权限控制:员工只能操作自己的客户数据

六、部署与演示准备

1. 数据库初始化脚本

-- 插入测试数据
INSERT INTO `yuangong` VALUES 
(1, '张三', '13800138000', '110101199001011234', '/images/emp1.jpg', 'zhangsan@qq.com', 1, NOW());

INSERT INTO `kehu` VALUES 
(1, 1, '李客户', '13800138001', '110101199001011235', '/images/cus1.jpg', 1, 'likehu@qq.com', 0.00, 1, 1, '重要客户', NOW(), NULL, NOW(), NOW());

INSERT INTO `kehuxiansuo` VALUES 
(1, 1, '王线索', '13800138002', '110101199001011236', '/images/lead1.jpg', 1, 'wangxiansuo@qq.com', 1, '潜在客户线索', 0, NULL, NULL, NOW(), NOW());

2. 演示流程设计

按照真实业务流程演示:

  1. 员工登录→查看客户列表→添加新客户
  2. 记录客户沟通→查看积分自动增加→确认等级变化
  3. 跟进客户线索→转化为正式客户→查看客户详情
  4. 管理员登录→查看员工业绩→统计数据报表

3. 答辩重点准备

  • 业务逻辑亮点:积分自动计算、等级自动调整、状态流转管理
  • 技术实现亮点:事务管理、MyBatis灵活使用、业务规则封装
  • 系统特色:完整的客户生命周期管理、智能化积分体系

结语

基于SSM的客户关系管理系统毕设成功的关键在于:抓住客户管理核心业务,设计合理的积分体系,保证数据一致性。这套系统虽然业务逻辑相对复杂,但一旦掌握,无论是技术深度还是业务完整性都能得到导师认可。

记住:积分自动计算、客户等级管理、线索转化流程是三大得分点!需要完整源码、数据库脚本、部署文档的同学可以在评论区留言。

点赞收藏这篇,下次找流程不迷路~祝宝子们毕设顺利,轻松毕业!😘