基于 Spring Cloud 的企业级全业务管理平台架构设计与模块实现
本文剖析一套基于 Spring Cloud Alibaba 微服务架构的企业级全业务管理平台,涵盖 OA、HRM、CRM、ERP、MES、BPM 等 18 个业务模块的架构设计、模块划分、工作流集成、多租户实现与前端动态路由等核心技术方案。

一、项目背景与架构选型
企业级管理软件长期面临一个架构矛盾:业务模块众多(OA、HRM、CRM、ERP、MES 等),如果每个模块独立部署为微服务,运维成本极高;如果全部揉进一个单体应用,代码耦合又难以维护。
本平台采用 Spring Cloud Alibaba 微服务架构 + 单体打包模式 的双模设计:开发期按模块拆分为 23+ 个 Maven 子模块,部署时可通过 pointlion-server 聚合为单个 JAR 启动,也可通过 Nacos + Gateway 拆分为微服务集群。这种设计兼顾了开发隔离与部署灵活性。
核心技术栈
| 基础框架 | Spring Boot | 2.7.18 |
| 微服务 | Spring Cloud + Spring Cloud Alibaba | 2021.0.9 / 2021.0.6.2 |
| 注册/配置中心 | Nacos | 2.3.2 |
| 服务网关 | Spring Cloud Gateway | 3.4.1 |
| 工作流 | Flowable | 6.8.0 |
| ORM | MyBatis Plus + Dynamic Datasource | 3.5.10 / 4.3.1 |
| 缓存 | Redis + Redisson | 3.41.0 |
| 消息队列 | RocketMQ | 5.2.0 |
| 分布式事务 | Seata | 1.6.1 |
| 限流熔断 | Sentinel | 1.8.6 |
| 链路追踪 | SkyWalking | 8.12.0 |
| 定时任务 | XXL-Job | 2.4.0 |
| 前端框架 | Vue 3 + Element Plus + Vite | 3.5 / 2.9 / 5.1 |
| 移动端 | uni-app + wot-ui | 3.0 / 2.0 |
二、微服务模块划分设计
2.1 模块拓扑
平台后端共划分为 23 个 Maven 模块,按职责分为四类:
pointlion-cloud/
├── pointlion-dependencies # 依赖版本管理(BOM)
├── pointlion-framework # Java 框架拓展(安全、缓存、MyBatis 等)
├── pointlion-gateway # API 网关(路由、鉴权、限流)
├── pointlion-server # 聚合启动模块(单体模式)
│
├── pointlion-module-system # 系统管理(用户/角色/菜单/租户/字典)
├── pointlion-module-infra # 基础设施(代码生成/文件服务/定时任务/监控)
├── pointlion-module-bpm # 工作流(Flowable 集成)
├── pointlion-module-oa # OA 办公自动化
├── pointlion-module-hrm # 人力资源
├── pointlion-module-crm # 客户关系
├── pointlion-module-erp # 企业资源
├── pointlion-module-mes # 制造执行
├── pointlion-module-wms # 仓储管理
├── pointlion-module-ams # 资产管理
├── pointlion-module-ct # 合同管理
├── pointlion-module-pm # 项目管理
├── pointlion-module-im # 即时通讯
├── pointlion-module-ai # AI 大模型
├── pointlion-module-iot # 物联网
├── pointlion-module-mp # 公众号
├── pointlion-module-mall # 商城(含 product/trade/promotion/member/pay)
├── pointlion-module-report # 数据报表
└── pointlion-module-mail # 邮件系统
2.2 模块内部分层
每个业务模块统一采用 API + Server 两层分离设计:
pointlion-module-oa/
├── pointlion-module-oa-api/ # 对外暴露的 API 接口 + 枚举 + DTO
│ └── src/main/java/…/oa/
│ └── enums/ # 错误码、字典常量、流程变量常量
│
└── pointlion-module-oa-server/ # 服务端实现
└── src/main/java/…/oa/
├── controller/
│ ├── admin/ # 管理后台 Controller(/admin-api 前缀)
│ └── app/ # 移动端 Controller(/app-api 前缀)
├── service/ # 业务逻辑层
│ └── bpm/ # BPM 流程通用基类
├── dal/
│ ├── dataobject/ # DO 数据对象
│ └── mysql/ # MyBatis Mapper 接口
└── handler/ # BPM 流程回调处理器
这种分层使得其他模块只需依赖 *-api 包即可调用该模块的能力,避免了循环依赖和服务间耦合。
2.3 数据库兼容方案
通过 MyBatis Plus 的 Dynamic Datasource(4.3.1)实现多数据源切换,底层适配以下数据库:
MySQL 5.7/8.0+ / Oracle / PostgreSQL / SQL Server / MariaDB
达梦 DM / 人大金仓 Kingbase / OpenGauss / TiDB
国产化适配主要通过 MyBatis Plus 的 DBType 枚举 + 方言自动切换实现,业务代码无需感知底层数据库类型。
三、BPM 工作流引擎集成设计
BPM 是平台的流程中枢,OA、HRM、CRM 等模块的所有审批类单据(请假、报销、公文、合同等)均通过统一接口接入 Flowable 6.8.0 引擎。
3.1 BaseBpmService 通用流程基类
平台将所有需要走审批流程的单据抽象为 BaseBpmService 基类,核心方法 submitProcessApply() 封装了从单据创建到流程实例启动的完整链路:
public abstract class BaseBpmService<V> {
public String submitProcessApply(V createReqVO) {
// 1. 获取流程定义 Key(子类实现)
String processDefKey = getProcessDefinitionKey(createReqVO);
// 2. 生成单据编号
String billCode = billCodeGenerateService.generateSerialCode(
createReqVO.getBillType());
// 3. 构建业务实体,设置流程状态为 RUNNING
BpmBaseDO entity = buildEntity(createReqVO);
entity.setBillCode(billCode);
entity.setProcessDefKey(processDefKey);
entity.setProcessStatus(BpmTaskStatusEnum.RUNNING.getStatus());
entity.setSubmitTime(LocalDateTime.now());
// 4. 持久化业务数据
if (createReqVO.getId() == null) {
insertEntity(entity);
} else {
updateEntity(entity);
}
// 5. 准备流程变量
Map<String, Object> variables = new HashMap<>();
variables.put(OaProcInsVarConstants.PROC_INS_VAR_MODULE_CODE, "OA");
variables.put(OaProcInsVarConstants.PROC_INS_VAR_BILL_TYPE,
createReqVO.getBillType());
addProcessVariables(variables, entity); // 子类扩展点
// 6. 创建 Flowable 流程实例
String processInstanceId = bpmProcessInstanceApi.createProcessInstance(
processDefKey, variables, entity.getId());
// 7. 回写流程实例 ID
updateProcessInstanceId(entity.getId(), processInstanceId);
return processInstanceId;
}
// 子类实现的抽象方法
protected abstract String getProcessDefinitionKey(V reqVO);
protected abstract BpmBaseDO buildEntity(V reqVO);
protected abstract void insertEntity(BpmBaseDO entity);
protected abstract void updateEntity(BpmBaseDO entity);
protected abstract void addProcessVariables(Map<String, Object> vars, BpmBaseDO entity);
protected abstract void updateProcessInstanceId(String id, String processInstanceId);
}
3.2 BpmBaseDO 单据基类
所有流程类单据的 DO 继承统一基类,消除重复字段定义:
public abstract class BpmBaseDO extends BaseDO {
@TableId(type = IdType.ASSIGN_UUID)
private String id;
private String billCode; // 单据编号(自动生成)
private String billType; // 单据类型(关联流程定义 Key)
private String processInstanceId; // BPM 流程实例 ID
private Integer processStatus; // 流程状态
private String processDefKey; // 流程定义 Key
private LocalDateTime submitTime; // 提交时间
}
以 OA 公文为例,OfficialDocDO 继承 BpmBaseDO 后只需定义公文特有字段(title、content、secretLevel、draftStatus、sendStatus 等),流程相关字段由基类提供。
3.3 双流程设计器
| SIMPLE 设计器 | 自研前端组件,仿钉钉/飞书拖拽式 | 简单审批流,业务人员可自行配置 |
| BPMN 2.0 设计器 | bpmn-js(17.9.2) | 复杂流程,含会签/或签/条件分支/并行分支 |
两种设计器最终都生成 Flowable 兼容的 BPMN XML,由同一套 Flowable 引擎执行。
3.4 流程回调机制
流程状态变更通过 BpmProcessInstanceHandler 回调业务模块:
@Component
public class OaBpmProcessInstanceHandler implements BpmProcessInstanceApi {
@Override
public void notifyProcessInstanceStatus(String businessKey,
Integer status) {
// 根据 businessKey 找到业务单据
// 更新 processStatus 字段
// 触发后续业务逻辑(如审批通过后进入签章环节)
}
}
四、多租户架构实现
4.1 租户隔离方案
平台采用 共享数据库 + 行级隔离 的多租户方案,通过 MyBatis Plus 的 TenantLineInnerInterceptor 自动在 SQL 中追加 tenant_id 条件:
@Component
public class TenantDatabaseInterceptor implements TenantLineHandler {
@Override
public Expression getTenantId() {
// 从当前请求上下文获取租户 ID
Long tenantId = TenantContextHolder.getTenantId();
return new LongValue(tenantId);
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public boolean ignoreTable(String tableName) {
// 系统表(如字典表)不进行租户隔离
return IGNORE_TABLES.contains(tableName);
}
}
业务表均包含 tenant_id 字段,所有查询和写入自动隔离,业务代码无需手动处理租户过滤。
4.2 租户权限体系
每个租户可独立配置:
- 菜单权限(哪些模块可用)
- 角色与数据权限
- 流程定义(独立配置审批流)
- 红头模板、编号规则等业务配置
五、权限与安全体系
5.1 认证机制
采用 Spring Security + Token + Redis 的无状态认证方案:
用户登录
→ Spring Security 校验用户名密码
→ 生成 UUID Token,写入 Redis(key = token, value = 用户信息)
→ 返回 Token 给前端
→ 后续请求携带 Token
→ Gateway 拦截器从 Redis 读取用户信息,注入请求头
→ Controller 通过 @RequestHeader 获取当前用户
5.2 RBAC 权限模型
权限控制基于 用户 → 角色 → 菜单/按钮 三级模型:
| 用户 | system_users | 平台用户账号 |
| 角色 | system_role | 角色定义,关联菜单权限 |
| 菜单 | system_menu | 菜单/按钮权限项,树形结构 |
| 用户角色 | system_user_role | 用户与角色多对多关联 |
| 角色菜单 | system_role_menu | 角色与菜单多对多关联 |
5.3 数据权限
通过 MyBatis Plus 拦截器实现行级数据权限:
@DataPermission({
@DataColumn(alias = "u", name = "dept_id"),
@DataColumn(alias = "u", name = "user_id")
})
public PageResult<UserDO> selectPage(UserPageReqVO reqVO) {
return userMapper.selectPage(reqVO);
}
拦截器自动根据当前用户的角色数据权限范围(全部、本部门、本部门及子部门、仅本人)拼接 SQL 条件。
六、核心业务模块技术实现
6.1 OA 办公模块
OA 模块通过 BaseBpmService 接入 BPM 引擎,实现以下流程类功能:
| 日报 | OA_DAILY_REPORT | 无 | 按日期查重,标题自动拼接 |
| 周报 | OA_WEEKLY_REPORT | 无 | 按年份+周数查重,自动计算周起止日期 |
| 公文管理 | OA_OFFICIAL_DOC | 无 | HTML 组装 + iText PDF 生成 + 电子签章 |
| 费用报销 | OA_REIMBURSE_APPLY | 无 | 主子表设计,费用明细差异更新(diffList) |
| 请假/调休 | OA_TIME_OFF_APPLY | day, hours | 根据起止时间自动计算天数和小时数 |
| 会议室预约 | OA_MEETINGROOM_APPLY | 无 | 时间段连续性校验,占用数据查询 |
| 企业云盘 | 不走 BPM | 无 | MD5 秒传,30 天回收站,递归文件夹操作 |
公文管理技术链路是 OA 模块中最复杂的,涉及 HTML 模板组装 → iText HTML 转 PDF → 公章图片坐标合成签章 → 发文状态控制,具体实现可参考后续专题文章。
6.2 报销申请的主子表差异更新
报销申请采用主表(oa_reimburse_apply)+ 子表(oa_reimburse_feeitem)设计,更新时通过差异比较实现精确更新:
public void updateReimburseApply(ReimburseApplyUpdateReqVO updateReqVO) {
ReimburseApplyDO entity = BeanUtils.toBean(updateReqVO, ReimburseApplyDO.class);
// 查询旧的费用明细
List<ReimburseFeeitemDO> oldList = feeitemMapper
.selectListByReimburseId(updateReqVO.getId());
// 新的费用明细
List<ReimburseFeeitemDO> newList = BeanUtils.toBean(
updateReqVO.getFeeitems(), ReimburseFeeitemDO.class);
// 差异比较:新增 / 更新 / 删除
diffList(oldList, newList,
(oldDO, newDO) -> oldDO.getId().equals(newDO.getId()),
(oldDO, newDO) -> { // 匹配到的执行更新
newDO.setId(oldDO.getId());
feeitemMapper.updateById(newDO);
},
oldDO -> feeitemMapper.deleteById(oldDO.getId()), // 旧有新无 → 删除
newDO -> feeitemMapper.insert(newDO) // 新有旧无 → 新增
);
reimburseApplyMapper.updateById(entity);
}
6.3 企业云盘秒传实现
文件上传时通过 MD5 校验实现秒传,避免重复文件占满存储空间:
public OaCloudFileDO uploadFile(MultipartFile file, String parentId) {
// 1. 计算文件 MD5
String md5 = DigestUtil.md5Hex(file.getInputStream());
// 2. 查询是否已存在相同 MD5 的文件
OaCloudFileDO existFile = cloudFileMapper.selectByMd5(md5);
if (existFile != null) {
// 3. 秒传:复用原文件的物理路径,只创建新的文件记录
OaCloudFileDO newRecord = new OaCloudFileDO();
newRecord.setName(file.getOriginalFilename());
newRecord.setParentId(parentId);
newRecord.setPath(existFile.getPath()); // 复用物理路径
newRecord.setUrl(existFile.getUrl()); // 复用访问 URL
newRecord.setMd5(md5);
newRecord.setSize(existFile.getSize());
newRecord.setType(2); // 文件
cloudFileMapper.insert(newRecord);
return newRecord; // 无需再次上传物理文件
}
// 4. 首次上传:调用文件服务存储
String url = fileApi.createFile(file.getBytes(), fileName, "cloud", contentType);
// … 创建文件记录
}
6.4 会议室时间段连续性校验
会议室预约支持多时间段选择,后端校验时间段必须连续:
private void validateTimeRangeContinuity(List<String> rangeTimes) {
if (CollUtil.isEmpty(rangeTimes)) {
throw exception(MEETINGROOM_TIME_RANGE_EMPTY);
}
if (rangeTimes.size() == 1) return; // 单段不校验
// 按 HH:mm-HH:mm 解析并按开始时间排序
List<TimeRange> ranges = rangeTimes.stream()
.map(this::parseTimeRange)
.sorted(Comparator.comparing(TimeRange::getStart))
.collect(Collectors.toList());
// 校验相邻时间段是否连续
for (int i = 0; i < ranges.size() – 1; i++) {
if (!ranges.get(i).getEnd().equals(ranges.get(i + 1).getStart())) {
throw exception(MEETINGROOM_TIME_RANGE_NOT_CONTINUOUS);
}
}
}
6.5 CRM 模块数据架构
CRM 模块采用线索 → 客户 → 商机 → 合同 → 回款的漏斗模型:
线索 (clue) → 客户 (customer) → 商机 (business) → 合同 (contract) → 回款 (receivable)
↓ ↓ ↓ ↓ ↓
转化跟踪 跟进记录 阶段推进 审批流程 回款登记
统计层基于 ECharts 5.5 实现销售漏斗图、客户画像雷达图、业绩排行榜等可视化分析。
6.6 ERP 库存核算
ERP 模块的核心是库存实时核算,采购入库和销售出库自动更新库存表:
采购入库单审批通过 → stock_in (warehouse_id, product_id, qty)
→ UPDATE erp_stock SET qty = qty + #{qty}
→ INSERT erp_stock_record (type=IN, before_qty, after_qty)
销售出库单审批通过 → stock_out (warehouse_id, product_id, qty)
→ UPDATE erp_stock SET qty = qty – #{qty}
→ INSERT erp_stock_record (type=OUT, before_qty, after_qty)
→ 库存不足时抛出异常,回滚事务
七、前端架构设计
7.1 动态路由机制
Web 管理后台采用 后端驱动路由 方案,菜单数据由后端接口返回,前端按权限过滤后动态注册路由:
// permission.ts 路由守卫
router.beforeEach(async (to, from, next) => {
if (getAccessToken()) {
// 首次进入:从后端加载菜单
if (!permissionStore.getIsDynamicAddedRoute()) {
await permissionStore.generateRoutes();
// 动态注册路由
permissionStore.getAddRouters().forEach(route => {
router.addRoute(route as RouteRecordRaw);
});
// 重新导航,确保路由生效
next({ …to, replace: true });
} else {
next();
}
} else {
next('/login');
}
});
后端 system_menu 表存储菜单树结构,包含 path、component、permission 等字段,前端根据 component 字段动态导入对应的 Vue 组件。
7.2 多端共享 API 层
移动端(uni-app)与 Web 端共享同一套后端 API,通过 /admin-api 和 /app-api 前缀区分端类型。移动端拦截器自动处理 Token 注入和租户 ID 传递:
// interceptor.ts 请求拦截
http.interceptors.request.use((config) => {
const token = getAccessToken();
if (token) {
config.header.Authorization = `Bearer ${token}`;
}
// 根据接口前缀自动路由到 admin-api 或 app-api
config.url = import.meta.env.VITE_API_URL + config.url;
return config;
});
7.3 BPM 表单组件复用
BPM 审批表单通过 FormCreate(3.2.6)动态渲染,流程设计器配置的表单 JSON 由前端解析为表单组件,实现了流程与表单的解耦。同一套表单组件在 Web 端和移动端复用,移动端通过 wd-form + wd-cell-group 适配移动端交互。
八、文件服务与存储抽象
文件存储通过 FileApi 接口抽象,支持多种存储后端:
public interface FileApi {
// 上传文件,返回访问 URL
String createFile(byte[] content, String name, String dir, String contentType);
// 根据 URL 获取文件内容
byte[] getFileContentByUrl(String url);
}
| 本地存储 | file.base-path | 开发环境、单机部署 |
| S3 兼容 | file.s3.endpoint | MinIO/阿里云 OSS/AWS S3 |
| FTP | file.ftp.host | 传统文件服务器 |
OA 云盘、公文 PDF、合同附件等均通过 FileApi 统一上传和读取,切换存储后端只需修改配置,无需改动业务代码。
九、监控与运维
| 链路追踪 | SkyWalking 8.12.0 | 全链路请求追踪,定位慢调用 |
| 应用监控 | Spring Boot Admin 2.7.15 | JVM、线程池、数据库连接池监控 |
| 日志中心 | Redis Stream | 统一日志收集与查询 |
| 接口文档 | Knife4j 4.5.0 | OpenAPI3 自动生成接口文档 |
| MySQL 监控 | Druid 1.2.24 | SQL 执行监控、慢查询分析 |
| Redis 监控 | 内置监控页 | 连接数、内存、命中率 |
十、业务模块概览
| OA | 日报/周报、公文管理、报销、请假、会议室、云盘 | BaseBpmService 流程基类、HTML→PDF→签章、MD5 秒传 |
| HRM | 员工档案、考勤打卡、薪酬计算、绩效、招聘 | 高德地图定位打卡、个税计算引擎、薪资结构模板 |
| CRM | 线索、客户、商机、合同、回款、统计分析 | 漏斗模型、公海池机制、ECharts 数据可视化 |
| ERP | 采购、销售、库存、财务 | 库存实时核算、多仓库管理、应付应收联动 |
| MES | 工单、排产、报工、质检、设备 | BOM 管理、工艺路线、IQC/IPQC/OQC 质检、安灯看板 |
| BPM | 流程设计、审批、抄送、驳回、加签 | Flowable 6.8.0、双设计器、会签/或签 |
| AMS | 资产台账、领用、折旧、盘点、报废 | 折旧自动计算、全生命周期状态机 |
| WMS | 入库/出库/调拨/盘点 | 实时库存、库存流水追溯 |
| CT | 合同起草、审批、签章、归档、风险预警 | 模板库/条款库、电子签章、合规检查 |
| IM | 单聊/群聊、消息管理 | WebSocket 实时推送、敏感词过滤 |
| AI | 对话、绘图、写作、知识库 | 多模型适配、文档分片检索、AI 工作流编排 |
| IoT | 设备管理、物模型、场景联动、OTA | MQTT 接入、规则引擎、固件升级 |
| Mall | 商品、订单、营销、会员、支付 | SPU/SKU、优惠券/秒杀/拼团、分销佣金 |
| PM | 项目、任务、WBS、成本、风险 | 甘特图(dhtmlx-gantt)、里程碑、资源分配 |
| Report | 报表设计、大屏设计 | 积木报表、GoView 拖拽式数据看板 |
十一、总结
本文从架构设计角度剖析了一套基于 Spring Cloud Alibaba 的企业级全业务管理平台,核心设计思路包括:
平台数据库兼容 MySQL、Oracle、PostgreSQL、达梦、人大金仓等,可满足国产化信创要求。前端 Vue 3 + Element Plus,移动端 uni-app 一套代码发布 H5、微信小程序、APP 多端。
参考链接
- 演示环境:http://admin.dianshixinxi.com:90
- H5 移动端:http://h5.dianshixinxi.com:90
- 官网:http://www.dianshixinxi.com
网硕互联帮助中心




评论前必须登录!
注册