基于 Spring Cloud 的企业级全业务管理平台架构设计与模块实现

基于 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 Boot2.7.18
微服务Spring Cloud + Spring Cloud Alibaba2021.0.9 / 2021.0.6.2
注册/配置中心Nacos2.3.2
服务网关Spring Cloud Gateway3.4.1
工作流Flowable6.8.0
ORMMyBatis Plus + Dynamic Datasource3.5.10 / 4.3.1
缓存Redis + Redisson3.41.0
消息队列RocketMQ5.2.0
分布式事务Seata1.6.1
限流熔断Sentinel1.8.6
链路追踪SkyWalking8.12.0
定时任务XXL-Job2.4.0
前端框架Vue 3 + Element Plus + Vite3.5 / 2.9 / 5.1
移动端uni-app + wot-ui3.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 后只需定义公文特有字段(titlecontentsecretLeveldraftStatussendStatus 等),流程相关字段由基类提供。

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 引擎,实现以下流程类功能:

功能流程定义 Key特殊流程变量技术要点
日报OA_DAILY_REPORT按日期查重,标题自动拼接
周报OA_WEEKLY_REPORT按年份+周数查重,自动计算周起止日期
公文管理OA_OFFICIAL_DOCHTML 组装 + iText PDF 生成 + 电子签章
费用报销OA_REIMBURSE_APPLY主子表设计,费用明细差异更新(diffList)
请假/调休OA_TIME_OFF_APPLYday, hours根据起止时间自动计算天数和小时数
会议室预约OA_MEETINGROOM_APPLY时间段连续性校验,占用数据查询
企业云盘不走 BPMMD5 秒传,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 表存储菜单树结构,包含 pathcomponentpermission 等字段,前端根据 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.endpointMinIO/阿里云 OSS/AWS S3
FTPfile.ftp.host传统文件服务器

OA 云盘、公文 PDF、合同附件等均通过 FileApi 统一上传和读取,切换存储后端只需修改配置,无需改动业务代码。


九、监控与运维

监控维度工具说明
链路追踪SkyWalking 8.12.0全链路请求追踪,定位慢调用
应用监控Spring Boot Admin 2.7.15JVM、线程池、数据库连接池监控
日志中心Redis Stream统一日志收集与查询
接口文档Knife4j 4.5.0OpenAPI3 自动生成接口文档
MySQL 监控Druid 1.2.24SQL 执行监控、慢查询分析
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设备管理、物模型、场景联动、OTAMQTT 接入、规则引擎、固件升级
Mall商品、订单、营销、会员、支付SPU/SKU、优惠券/秒杀/拼团、分销佣金
PM项目、任务、WBS、成本、风险甘特图(dhtmlx-gantt)、里程碑、资源分配
Report报表设计、大屏设计积木报表、GoView 拖拽式数据看板

十一、总结

本文从架构设计角度剖析了一套基于 Spring Cloud Alibaba 的企业级全业务管理平台,核心设计思路包括:

  1. 模块化拆分:23 个 Maven 模块按 API + Server 分层,业务隔离、依赖清晰
  2. 流程统一接入BaseBpmService 泛型基类 + BpmBaseDO 单据基类,新增流程类单据只需实现抽象方法
  3. 多租户行级隔离:MyBatis Plus 拦截器自动追加 tenant_id,业务代码无感知
  4. 后端驱动路由:菜单数据后端管理,前端动态注册,权限控制到按钮级
  5. 文件存储抽象FileApi 统一接口,支持本地/S3/FTP 切换
  6. 双模部署:单体聚合打包 + 微服务集群,按需选择

平台数据库兼容 MySQL、Oracle、PostgreSQL、达梦、人大金仓等,可满足国产化信创要求。前端 Vue 3 + Element Plus,移动端 uni-app 一套代码发布 H5、微信小程序、APP 多端。


参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值