1. 项目概述:全栈CRM系统架构解析
这套基于Java技术栈的CRM系统采用了典型的前后端分离架构,前端使用Vue.js框架开发移动端小程序,后端基于Spring Boot构建RESTful API服务,数据存储选用MySQL关系型数据库。这种技术组合在当前企业级应用开发中具有显著优势:Vue的轻量级特性特别适合移动端开发,Spring Boot的约定优于配置理念大幅降低了后端开发复杂度,而MySQL作为久经考验的关系型数据库,在保证事务完整性的同时也能满足大多数CRM场景的性能需求。
从技术实现角度看,系统包含三个核心模块:
- 移动端小程序:采用Vue 2.x + Vant组件库实现,支持微信小程序和H5双端运行
- 管理后台:同样基于Vue技术栈,使用Element UI构建管理界面
- 后端服务:Spring Boot 2.7 + MyBatis Plus实现业务逻辑,采用多模块Maven项目结构
实际开发中发现,Vue 2.x在移动端的性能表现优于Vue 3.x,特别是在低端安卓设备上。这是因为Vue 3的Composition API虽然更灵活,但运行时开销略大,而Vue 2的Options API在编译后生成的代码更精简。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术栈深度剖析
2.1 Vue前端架构设计
前端工程采用Vue CLI 4.x搭建,通过配置vue.config.js实现多环境打包。为解决移动端适配问题,我们采用了postcss-px-to-viewport插件实现自动视口单位转换。核心代码结构如下:
code复制src/
├── api/ # 接口请求封装
├── components/ # 公共组件
├── pages/ # 页面组件
├── router/ # 路由配置
├── store/ # Vuex状态管理
├── utils/ # 工具函数
└── styles/ # 全局样式
小程序端特别处理了以下问题:
- 登录鉴权:采用JWT + 微信openId双重验证
- 数据缓存:使用localStorage配合内存缓存,减少API请求
- 性能优化:对长列表实现虚拟滚动,图片采用懒加载
2.2 Spring Boot后端实现
后端采用经典的Controller-Service-DAO三层架构,通过Spring Security实现基于角色的访问控制(RBAC)。一个典型的客户管理接口实现如下:
java复制@RestController
@RequestMapping("/api/customer")
public class CustomerController {
@Autowired
private CustomerService customerService;
@GetMapping("/{id}")
public Result<CustomerVO> getCustomer(@PathVariable Long id) {
return Result.success(customerService.getById(id));
}
@PostMapping
public Result<Void> addCustomer(@Valid @RequestBody CustomerDTO dto) {
return customerService.addCustomer(dto) ?
Result.success() : Result.fail("添加失败");
}
}
数据库事务管理采用声明式事务,在Service层使用@Transactional注解:
java复制@Service
public class CustomerServiceImpl implements CustomerService {
@Transactional(rollbackFor = Exception.class)
public boolean addCustomer(CustomerDTO dto) {
// 业务逻辑实现
}
}
2.3 MySQL数据库设计
数据库设计遵循第三范式,主要表结构包括:
| 表名 | 主要字段 | 说明 |
|---|---|---|
| sys_user | id, username, password, role_id | 系统用户表 |
| crm_customer | id, name, phone, source, status | 客户信息表 |
| crm_contact | id, customer_id, name, position, phone | 联系人表 |
| crm_business | id, customer_id, name, amount, stage | 商机表 |
| sys_role | id, name, permissions | 角色表 |
索引优化方案:
- 为所有外键字段创建普通索引
- 为高频查询条件(如customer.phone)创建唯一索引
- 对联合查询字段建立组合索引
3. 关键功能实现细节
3.1 客户生命周期管理
系统实现了完整的客户生命周期管理流程:
- 线索获取:支持Excel导入和API对接
- 客户分配:采用轮询算法自动分配销售代表
- 跟进记录:支持文字、语音、图片多种形式
- 商机转化:自定义销售漏斗阶段
- 合同管理:在线生成PDF合同
移动端特别优化了客户地图展示功能,集成腾讯地图SDK实现:
- 客户位置标记
- 拜访路线规划
- 地理围栏提醒
3.2 数据权限控制
通过注解+AOP实现细粒度的数据权限控制:
java复制@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataScope {
String deptAlias() default "";
String userAlias() default "";
}
@Aspect
@Component
public class DataScopeAspect {
@Before("@annotation(dataScope)")
public void doBefore(DataScope dataScope) {
// 权限过滤逻辑实现
}
}
3.3 消息推送机制
采用WebSocket实现实时消息推送,关键配置:
java复制@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOrigins("*");
}
}
前端连接示例:
javascript复制const socket = new SockJS('/ws');
const stompClient = Stomp.over(socket);
stompClient.connect({}, () => {
stompClient.subscribe('/topic/notice', (message) => {
showNotification(JSON.parse(message.body));
});
});
4. 部署与性能优化
4.1 多环境部署方案
通过Maven Profile实现多环境配置:
xml复制<profiles>
<profile>
<id>dev</id>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
</properties>
</profile>
</profiles>
对应的Spring Boot配置文件:
- application-dev.yml:开发环境配置
- application-prod.yml:生产环境配置
4.2 缓存策略优化
采用多级缓存架构提升性能:
- 本地缓存:Caffeine实现高频数据缓存
- 分布式缓存:Redis缓存共享数据
- 数据库缓存:MySQL查询缓存
缓存更新策略:
- 读多写少:设置较长过期时间,通过消息队列更新
- 写多读少:采用Cache Aside Pattern
- 强一致性要求:采用双写模式
4.3 数据库性能调优
针对CRM系统的特点进行MySQL优化:
- 参数调整:
sql复制innodb_buffer_pool_size = 4G # 缓冲池大小
innodb_log_file_size = 256M # 日志文件大小
query_cache_size = 0 # 禁用查询缓存
- SQL优化原则:
- 避免SELECT *,只查询需要的字段
- 使用EXPLAIN分析执行计划
- 对大数据量表采用分页查询
- 连接池配置:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
5. 常见问题解决方案
5.1 跨域问题处理
前后端分离项目常见的跨域问题解决方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
5.2 文件上传限制
Spring Boot默认文件上传限制为1MB,需要调整:
yaml复制spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
前端分片上传实现:
javascript复制function uploadFile(file) {
const chunkSize = 2 * 1024 * 1024; // 2MB
const chunks = Math.ceil(file.size / chunkSize);
for (let i = 0; i < chunks; i++) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
const formData = new FormData();
formData.append('file', chunk);
formData.append('chunkNumber', i);
formData.append('totalChunks', chunks);
axios.post('/api/upload', formData);
}
}
5.3 并发修改冲突
采用乐观锁解决并发更新问题:
java复制public class Customer {
@Version
private Integer version;
// 其他字段...
}
@Transactional
public void updateCustomer(Customer customer) {
Customer existing = customerDao.selectById(customer.getId());
if (existing.getVersion() != customer.getVersion()) {
throw new OptimisticLockingFailureException("数据已被修改");
}
customerDao.updateById(customer);
}
6. 扩展与二次开发
6.1 插件机制设计
通过SPI机制实现系统扩展:
- 定义插件接口:
java复制public interface CrmPlugin {
String getName();
void initialize();
void destroy();
}
- 创建META-INF/services文件:
code复制com.example.crm.plugin.CustomerExportPlugin
com.example.crm.plugin.DataAnalysisPlugin
- 插件加载实现:
java复制ServiceLoader<CrmPlugin> plugins = ServiceLoader.load(CrmPlugin.class);
plugins.forEach(plugin -> {
plugin.initialize();
});
6.2 工作流引擎集成
集成Activiti实现业务流程管理:
java复制@Autowired
private RuntimeService runtimeService;
public void startCustomerApprovalProcess(Long customerId) {
Map<String, Object> variables = new HashMap<>();
variables.put("customerId", customerId);
runtimeService.startProcessInstanceByKey(
"customerApproval", variables);
}
6.3 微服务化改造
逐步迁移到Spring Cloud架构:
- 服务拆分方案:
- 用户服务
- 客户服务
- 订单服务
- 消息服务
- 关键配置:
yaml复制spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
routes:
- id: customer-service
uri: lb://customer-service
predicates:
- Path=/api/customer/**
这套CRM系统源码在实际部署时,建议先从小规模团队试用开始,逐步扩展到全公司范围。我们在实施过程中发现,用户培训比技术实现更重要 - 只有销售团队真正用起来,系统才能发挥价值。对于技术团队,建议重点关注数据迁移方案和系统集成点,这两个环节最容易出现问题。
