本文还有配套的精品资源,点击获取
简介:这套工作流审批系统开箱即用,后端用SpringBoot 2.x开发,前端基于Vue.js实现响应式操作界面,完整支持流程建模、任务分派、多级审批、实时状态追踪等常用功能。压缩包里包含可直接运行的前后端源码(gongzuoliuchengguanli模块和Uhxn6nJrPfuY7GMZBiiw-master目录)、MySQL数据库初始化脚本db.sql、Maven依赖配置pom.xml、项目结构说明README.md、使用前必读.txt文档、系统架构与设计思路PPT(ppt.pptx),以及两段高清实操视频:一段是系统从启动到全流程审批的完整运行演示,另一段是配套论文讲解与开发要点梳理。所有代码已在本地环境验证通过,兼容IntelliJ IDEA和VS Code,导入后一键启动后端服务(SpringBoot)和前端服务(npm run serve),无需额外配置即可查看界面、提交申请、处理待办任务。适用于高校课程设计、毕业设计选题参考,也适合中小企业快速搭建轻量级内部审批流程。
1. 项目概述:这不是一个“玩具系统”,而是一套能真正跑起来的流程管理骨架
你手头拿到的这个压缩包,不是网上常见的那种“只有登录页、点开就404”的Demo级代码,也不是删减了核心逻辑、只留个壳子的教学示例。它是一套经过真实环境验证、具备完整业务闭环、可直接用于课程设计答辩甚至小团队试运行的工作流审批系统。我带过十几届毕业设计,见过太多学生花三个月搭环境、调依赖、查404,最后连流程图都画不全。这套源码的价值,恰恰在于它把“从零开始”中最耗时、最易踩坑的底层基建全部铺平了——SpringBoot后端已封装好Activiti 6.x流程引擎与MyBatis-Plus数据层的深度集成,Vue前端已实现动态表单渲染、待办任务卡片式布局、审批意见富文本编辑等真实场景功能。关键词里反复出现的“工作流审批”“SpringBoot源码”“Vue前端”,不是标签堆砌,而是三个不可拆解的技术锚点:后端用SpringBoot 2.3.12.RELEASE(兼容JDK 8/11),解决了传统SSM框架中流程引擎与Spring事务、AOP的耦合难题;前端用Vue 2.6.14 + Element UI 2.15.6,没有上Vue 3或Vite这些新潮但对毕设不友好的技术栈,确保你在VS Code里敲npm install就能装全依赖;而“流程管理系统”这个定位,决定了它没做过度设计——没有微服务拆分、没有分布式事务、没有消息队列,所有审批状态变更、任务流转、历史记录查询,都在单体应用内通过数据库事务+流程引擎事件监听完成,既保证数据一致性,又极大降低理解门槛。适合谁?高校计算机、软件工程、信息管理专业的本科生做课程设计或毕业设计,因为它的代码结构清晰、注释完整、PPT里连ER图和流程图都给你画好了;也适合5人以下的初创团队或部门,拿来改改表单字段、加几个审批节点,就能替代钉钉审批里那些模板化程度高、自定义成本大的轻量级流程。
2. 整体架构设计与技术选型逻辑:为什么是这套组合,而不是其他方案?
2.1 后端为何锁定SpringBoot 2.x + Activiti 6.x?
很多同学第一反应是:“现在都SpringBoot 3了,为啥还用2.x?” 这不是技术守旧,而是面向交付场景的务实选择。SpringBoot 3要求JDK 17+,而高校实验室、学生个人电脑普遍还是JDK 8或11,强行升级会导致UnsupportedClassVersionError满天飞。更重要的是,Activiti 7虽然支持SpringBoot 3,但它转向了Cloud Native架构,核心流程引擎被拆成独立服务,本地调试需要Docker、K8s等额外环境——这对毕设场景是灾难性的。而Activiti 6.x与SpringBoot 2.x的整合是业界验证最成熟的方案:它把BPMN 2.0规范的XML流程定义文件(.bpmn)编译成数据库里的ACT_RE_PROCDEF(流程定义)、ACT_RU_EXECUTION(运行时执行实例)等7张核心表,所有流程启动、任务分配、审批提交的操作,最终都转化为对这几张表的增删改查+触发器事件。比如你点击“提交请假申请”,后端代码实际执行的是:
// 启动流程实例,传入业务ID(如leaveApplyId=1001) ProcessInstance processInstance = runtimeService.startProcessInstanceByKey( "leaveProcess", Collections.singletonMap("businessKey", "1001") );这行代码背后,Activiti会自动在ACT_RU_EXECUTION插入一条记录,在ACT_RU_TASK生成第一个待办任务(通常是“部门经理审批”),并把businessKey关联到ACT_HI_PROCINST历史表中。这种“数据库即状态中心”的设计,让你调试时直接看MySQL里的表数据就能明白流程走到哪一步,比看一堆微服务日志直观得多。我们提供的db.sql脚本里,不仅建了Activiti的23张系统表,还额外创建了leave_apply(请假申请主表)、leave_approve_record(审批记录明细表)等业务表,并通过外键约束与ACT_HI_PROCINST.PROC_INST_ID_关联——这是很多开源项目忽略的关键细节:流程引擎管状态流转,业务系统管数据沉淀,二者必须通过业务主键强绑定,否则审批完成后你根本找不到这条申请对应的业务数据在哪。
2.2 前端为何坚持Vue 2 + Element UI而非Vue 3或React?
Vue 2的选择,本质是降低学习曲线与调试成本。Vue 3的Composition API虽然更优雅,但对刚接触前端的学生来说,setup()函数里一堆ref()、reactive()、onMounted()的嵌套,远不如Vue 2的data()返回对象、methods写函数来得直白。更重要的是,Element UI 2.x对表格(el-table)、表单(el-form)、弹窗(el-dialog)的封装,已经覆盖了审批系统90%的UI需求。比如待办任务列表,你只需要这样写:
<el-table :data="taskList" stripe> <el-table-column prop="name" label="任务名称" width="180"></el-table-column> <el-table-column prop="assignee" label="处理人" width="120"></el-table-column> <el-table-column label="操作" width="180"> <template slot-scope="{row}"> <el-button size="mini" @click="handleApprove(row)">审批</el-button> <el-button size="mini" type="danger" @click="handleReject(row)">驳回</el-button> </template> </el-table-column> </el-table>这段代码里没有虚拟DOM、没有Hooks、没有JSX,就是纯粹的HTML模板语法,复制粘贴到你的.vue文件里就能跑。而handleApprove(row)方法内部,调用的是this.$axios.post('/api/task/approve', {taskId: row.id, opinion: this.opinion}),后端Controller接收后,一行taskService.complete(taskId, variables)就完成了Activiti的任务提交。这种前后端职责分明、接口契约清晰的设计,让你能把精力聚焦在“业务逻辑怎么串起来”,而不是“为什么this指向不对”或者“useEffect依赖数组漏写了”。PPT里第12页的“前后端交互时序图”,画的就是这个过程:用户点击按钮 → 前端发POST请求 → 后端解析参数 → 调用Activiti API → 更新数据库 → 返回成功响应 → 前端刷新列表。没有中间件、没有代理层、没有复杂的鉴权拦截,就是最朴素的HTTP请求-响应模型。
2.3 数据库设计如何兼顾流程引擎与业务需求?
db.sql脚本里的表结构,是我反复调整三次才定稿的。它不是简单地把Activiti官方SQL脚本复制过来,而是做了三处关键增强:第一,业务主键穿透。Activiti默认的ACT_HI_PROCINST.BUSINESS_KEY_字段是VARCHAR(255),但我们的业务表(如leave_apply.id)是BIGINT类型。如果直接把1001存进去,后续关联查询时会出现隐式类型转换,导致索引失效。所以我们在db.sql里强制将BUSINESS_KEY_改为BIGINT,并在建表语句里加上注释-- 此字段存储业务表主键,需与leave_apply.id类型一致。第二,审批意见结构化存储。很多Demo把审批意见存在ACT_HI_COMMENT表里,但那是纯文本,无法做统计分析。我们的设计是在leave_approve_record表里增加opinion_type(枚举:同意/驳回/转交)、opinion_content(富文本)、next_assignee_id(转交目标人ID)三个字段,每次审批都生成一条记录,这样导出审批报表时,SELECT COUNT(*) FROM leave_approve_record WHERE opinion_type='驳回' AND create_time > '2024-01-01'就能直接算出本月驳回率。第三,历史数据归档机制。db.sql里特意建了leave_apply_archive表,结构与leave_apply完全一致,只是多了archive_time字段。PPT第18页的“数据生命周期管理”图示说明:当流程结束超过90天,定时任务会把leave_apply里的记录迁移到归档表,主表只保留热数据——这解决了学生项目常犯的错误:把所有历史数据堆在一张表里,后期查询越来越慢。
3. 核心模块解析与实操要点:从代码目录到功能落地的逐层拆解
3.1 目录结构解读:哪些文件夹是必须关注的“心脏地带”
拿到源码包,别急着导入IDE,先用记事本打开README.md,再对照资源包里的目录树,重点盯住这几个路径:
gongzuoliuchengguanli/:这是整个SpringBoot后端项目的根目录,不是子模块。里面包含标准的src/main/java(Java代码)、src/main/resources(配置文件)、src/main/webapp(静态资源)。特别注意src/main/resources/application.yml,它配置了MySQL连接(spring.datasource.url=jdbc:mysql://localhost:3306/workflow?useSSL=false&serverTimezone=Asia/Shanghai)、Activiti开关(activiti.async-executor-enabled: false——关闭异步执行器,避免本地调试时任务莫名消失)、MyBatis-Plus分页插件(mybatis-plus.configuration.map-underscore-to-camel-case: true)。如果你的MySQL密码不是root,就在这里改spring.datasource.password。Uhxn6nJrPfuY7GMZBiiw-master-5c4e76142da609ea60f57acf0823e0a513afc023/:这是Vue前端项目的完整目录,名字虽长,但它是独立的。进入该目录,package.json里明确写着"dependencies": {"vue": "^2.6.14", "element-ui": "^2.15.6"},src/router/index.js定义了路由:/login(登录页)、/dashboard(首页)、/task/todo(待办任务)、/process/define(流程定义)。这里有个隐藏技巧:src/utils/request.js里封装了Axios拦截器,所有API请求都会自动带上AuthorizationHeader,但后端其实没做JWT鉴权——这是为后续扩展留的钩子,你暂时可以忽略,直接看src/api/task.js里的getTodoList()方法,它调用的是/api/task/todo接口,对应后端TaskController.java的@GetMapping("/todo")。db.sql:不是一次性执行完就扔掉的脚本。它分为三块:前100行是Activiti系统表(以ACT_开头),中间200行是业务表(leave_apply,leave_approve_record等),最后50行是初始化数据(插入管理员账号admin/123456、预置请假流程定义)。执行时务必按顺序:先建库CREATE DATABASE workflow DEFAULT CHARSET utf8mb4;,再执行db.sql,否则外键约束会报错。ppt.pptx:别当成摆设。第7页的“系统功能模块图”里,把“流程定义”拆成了“BPMN设计器”和“流程发布”,这暗示了代码里有两个关键类:ProcessDefinitionController.java(处理BPMN文件上传)和DeploymentService.java(调用repositoryService.createDeployment().addClasspathResource("processes/leave.bpmn").deploy()发布流程)。而第22页的“数据库ER图”,标红了leave_apply.business_key与ACT_HI_PROCINST.BUSINESS_KEY_的关联线——这就是你写联表查询时必须加的ON条件。
提示:
使用前必读.txt里有一条容易被忽略的警告:“首次启动前,请确认MySQL已开启lower_case_table_names=1”。这是因为Windows系统默认不区分表名大小写,而Linux下区分。如果你在Windows开发、Linux部署,不设这个参数,db.sql里建的leave_apply表可能变成LEAVE_APPLY,导致MyBatis找不到映射关系。解决方案:修改MySQL配置文件my.ini,在[mysqld]下添加lower_case_table_names=1,然后重启服务。
3.2 流程定义与部署:如何把画好的流程图变成可运行的审批链
Activiti本身不提供图形化设计器,但源码包里集成了activiti-modeler的简化版。实际操作中,你不需要自己画BPMN——gongzuoliuchengguanli/src/main/resources/processes/目录下,已经放好了leave.bpmn文件。用记事本打开它,你会看到类似这样的XML片段:
<process id="leaveProcess" name="请假流程" isExecutable="true"> <startEvent id="startEvent1" name="开始"/> <userTask id="usertask1" name="员工提交申请" activiti:assignee="${initiator}"/> <sequenceFlow id="flow1" sourceRef="startEvent1" targetRef="usertask1"/> <userTask id="usertask2" name="部门经理审批" activiti:candidateGroups="manager"/> <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"/> <endEvent id="endEvent1" name="结束"/> <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="endEvent1"/> </process>这段XML定义了一个三节点流程:开始 → 员工提交 → 部门经理审批 → 结束。关键参数是activiti:assignee和activiti:candidateGroups:前者指定具体处理人(${initiator}是Activiti内置变量,值为启动流程的用户ID),后者指定候选组(manager组,对应数据库act_id_group表里的group_id)。部署流程的代码在ProcessDefinitionController.java的deployProcess()方法里:
@PostMapping("/deploy") public Result deploy(@RequestParam("file") MultipartFile file) { Deployment deployment = repositoryService.createDeployment() .addInputStream(file.getOriginalFilename(), file.getInputStream()) .deploy(); // 这行代码把BPMN文件解析并存入ACT_RE_PROCDEF等表 return Result.success(deployment.getId()); }实操时,你只需在浏览器访问http://localhost:8080/process/define,点击“上传BPMN文件”,选择leave.bpmn,点击部署。后台会返回部署ID,同时ACT_RE_PROCDEF表里会多一条记录,KEY_字段值为leaveProcess,VERSION_为1。这时流程就“活”了——你可以调用runtimeService.startProcessInstanceByKey("leaveProcess")启动实例,Activiti会自动按XML里的sequenceFlow顺序创建任务。
注意:
leave.bpmn里<userTask>的id属性(如usertask1)必须全局唯一,且不能含中文或特殊符号。我曾见过学生把ID写成部门经理审批,结果启动流程时报Invalid activity id。正确做法是用英文下划线,如dept_manager_approval。
3.3 审批任务处理:从前端点击到数据库落库的完整链路
以“部门经理审批”为例,梳理一次完整审批的代码链路:
前端触发:在/task/todo页面,点击“审批”按钮,执行handleApprove(row)方法(src/views/task/TodoList.vue):
handleApprove(row) { this.taskId = row.id; this.dialogVisible = true; // 弹出审批弹窗 } // 点击弹窗里的“确定”按钮 confirmApprove() { this.$axios.post('/api/task/approve', { taskId: this.taskId, opinion: this.opinion, opinionType: 'agree' }).then(res => { this.$message.success('审批成功'); this.fetchTodoList(); // 刷新待办列表 }); }后端接收:TaskController.java的approve()方法:
@PostMapping("/approve") public Result approve(@RequestBody ApproveRequest request) { // 1. 封装审批变量 Map<String, Object> variables = new HashMap<>(); variables.put("opinion", request.getOpinion()); variables.put("opinionType", request.getOpinionType()); // 2. 调用Activiti完成任务 taskService.complete(request.getTaskId(), variables); // 3. 保存业务审批记录 LeaveApproveRecord record = new LeaveApproveRecord(); record.setTaskId(request.getTaskId()); record.setOpinionType(request.getOpinionType()); record.setOpinionContent(request.getOpinion()); record.setCreateTime(new Date()); approveRecordMapper.insert(record); return Result.success(); }数据库变化:执行后,三张表同时更新:
-ACT_RU_TASK:删除ID_ = ?的记录(任务完成,从运行时表移除)
-ACT_HI_TASKINST:新增一条历史任务记录,END_TIME_字段填入当前时间
-leave_approve_record:插入新记录,TASK_ID字段值等于Activiti任务ID
这个链路清晰展示了流程引擎与业务逻辑的协同:Activiti负责状态流转(任务完成→下一个任务生成),业务代码负责数据沉淀(把审批意见存到自己的表里)。PPT第15页的“审批数据流向图”,用箭头标明了这三张表之间的数据同步关系,避免你只改Activiti不存业务数据,导致审批完成却查不到记录。
4. 实操全流程:从环境搭建到全流程跑通的每一步详解
4.1 环境准备与依赖安装:避开90%的“启动失败”问题
MySQL配置(最容易翻车的环节):
1. 下载MySQL 5.7(推荐免安装版,解压即用)
2. 修改my.ini,确保包含:ini [mysqld] port=3306 character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci lower_case_table_names=1 # 关键!必须设为1
3. 初始化数据库:bin/mysqld --initialize --console,记住临时密码
4. 启动服务:bin/mysqld --console
5. 登录并修改密码:mysql -u root -p,执行ALTER USER 'root'@'localhost' IDENTIFIED BY 'your_password';
6. 创建数据库:CREATE DATABASE workflow DEFAULT CHARSET utf8mb4;
后端启动(SpringBoot):
- 打开IntelliJ IDEA,File → Open,选择gongzuoliuchengguanli目录
- 等待Maven自动导入依赖(pom.xml里已声明spring-boot-starter-web、activiti-spring-boot-starter-basic、mybatis-plus-boot-starter)
- 检查application.yml中的MySQL配置是否匹配你的环境
- 右键GongzuoliuchengguanliApplication.java→Run,控制台输出Started GongzuoliuchengguanliApplication in X seconds即成功
- 访问http://localhost:8080/swagger-ui.html,能看到所有API接口文档(/api/task/todo、/api/task/approve等)
前端启动(Vue):
- 打开VS Code,File → Open Folder,选择Uhxn6nJrPfuY7GMZBiiw-master-...目录
- 终端执行:npm install(如果卡在node-sass,执行npm install node-sass@4.14.1再重试)
- 修改src/utils/request.js里的基础URL:const service = axios.create({baseURL: 'http://localhost:8080/api/'})
- 执行:npm run serve
- 浏览器访问http://localhost:8080,输入admin/123456登录
实测心得:如果前端报
Network Error,90%是跨域问题。此时不要去配Vue的proxy,直接在后端GongzuoliuchengguanliApplication.java上加@EnableWebMvc和@Configuration类,重写addCorsMappings方法,允许http://localhost:8080来源。这个配置已在源码的config/WebMvcConfig.java里写好,你只需确认它被@ComponentScan扫描到即可。
4.2 全流程跑通演示:手把手带你走完一次请假审批
Step 1:登录与流程部署
- 前端访问http://localhost:8080,用admin/123456登录
- 左侧菜单点击“流程管理” → “流程定义”,点击“上传BPMN”,选择gongzuoliuchengguanli/src/main/resources/processes/leave.bpmn,点击“部署”
- 查看ACT_RE_PROCDEF表,确认KEY_ = 'leaveProcess'且VERSION_ = 1
Step 2:员工提交申请
- 前端点击“新建申请”,填写请假类型、天数、事由,点击“提交”
- 后端LeaveApplyController.java的submit()方法被调用,执行:java // 1. 保存业务申请 leaveApplyMapper.insert(apply); // 2. 启动流程,传入业务ID作为businessKey runtimeService.startProcessInstanceByKey("leaveProcess", Collections.singletonMap("businessKey", String.valueOf(apply.getId())));
- 此时ACT_RU_TASK表出现一条新记录,NAME_ = '员工提交申请',ASSIGNEE_ = 'admin'(因为${initiator}是admin)
Step 3:部门经理审批
- 前端刷新“待办任务”,看到“员工提交申请”任务(注意:此时任务是员工自己处理,因为activiti:assignee="${initiator}")
- 点击“审批”,填写意见,提交
-ACT_RU_TASK里该任务被删除,新生成一条NAME_ = '部门经理审批',CANDIDATE_GROUP_ID_ = 'manager'
- 因为当前用户admin属于manager组(ACT_ID_MEMBERSHIP表里有记录),所以该任务出现在admin的待办列表
Step 4:审批完成与状态追踪
- admin再次审批“部门经理审批”任务,选择“同意”
-ACT_RU_TASK清空,ACT_HI_PROCINST里END_TIME_被填充,STATUS_ = 'completed'
- 前端访问“审批历史”,调用/api/record/history?businessKey=1001,查到两条记录:员工提交、经理审批,意见内容、时间一目了然
这个过程里,你不需要写一行Activiti的XML,不需要配一个流程变量,所有逻辑都在leave.bpmn和Controller方法里固化好了。视频springboot190论文录像.mp4的03:22-08:15,完整录制了这四步操作,包括控制台日志和数据库实时查询画面,建议边看边操作。
5. 常见问题与排查技巧实录:那些文档里不会写的“血泪教训”
5.1 启动报错:Failed to configure a DataSource
现象:后端启动时控制台报Consider defining a bean of type 'javax.sql.DataSource' in your configuration,然后退出
原因:application.yml里的MySQL配置有误,最常见的是url末尾少了?useSSL=false&serverTimezone=Asia/Shanghai,导致JDBC驱动连接失败
排查:
1. 检查application.yml第12行spring.datasource.url,确认端口(3306)、数据库名(workflow)、参数拼写
2. 在MySQL命令行执行SHOW VARIABLES LIKE 'lower_case_table_names';,必须返回1
3. 用Navicat连接localhost:3306,测试能否登录workflow库
5.2 前端空白页:Cannot GET /
现象:浏览器打开http://localhost:8080显示空白,F12看Network全是404
原因:Vue路由模式为history,但后端没配fallback,导致刷新页面时Nginx/Apache找不到/dashboard路径
解决:这不是生产环境问题,开发时直接改vue.config.js:
module.exports = { devServer: { historyApiFallback: true // 添加这一行 } }源码包里已配置好,如果你删了这行,就会出现此问题。
5.3 审批后任务不消失:ACT_RU_TASK表还有记录
现象:点击“审批”按钮,控制台显示success,但待办列表没刷新,数据库里任务还在
原因:Activiti任务完成时,taskService.complete()必须传入正确的taskId,而前端传的可能是row.id(Activiti任务ID)或row.processInstanceId(流程实例ID)
排查:
1. 在TodoList.vue的handleApprove(row)里加console.log(row),确认row.id字段值
2. 对照ACT_RU_TASK.ID_字段,看是否匹配
3. 如果不匹配,检查TaskController.java的getTodoList()方法,taskQuery.taskAssignee()是否用了正确的查询条件
5.4 流程启动后无任务:ACT_RU_TASK为空
现象:调用startProcessInstanceByKey()后,流程实例在ACT_RU_EXECUTION里,但ACT_RU_TASK没生成
原因:BPMN文件里<startEvent>后跟的不是<userTask>,而是<serviceTask>或其他非人工任务节点
解决:打开leave.bpmn,确认<startEvent>后的<sequenceFlow>的targetRef指向一个<userTask>,且该<userTask>有activiti:assignee或activiti:candidateGroups属性
5.5 中文乱码:数据库存的是????
现象:请假事由、审批意见存进数据库后变成问号
原因:MySQL数据库、表、字段的字符集不是utf8mb4
解决:
1. 执行ALTER DATABASE workflow CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
2. 执行ALTER TABLE leave_apply CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
3. 确认application.yml里spring.datasource.url包含characterEncoding=utf8mb4
独家避坑技巧:在
pom.xml的mysql-connector-java依赖里,强制指定版本为8.0.28,因为新版驱动对serverTimezone参数更敏感。源码包里已写死该版本,如果你升级了,务必同步检查URL参数。
6. 二次开发指南:如何基于此框架快速定制你的业务流程
6.1 新增一种审批类型(如“报销申请”)
步骤1:建业务表
在db.sql末尾添加:
CREATE TABLE `reimburse_apply` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `employee_id` varchar(50) NOT NULL COMMENT '申请人ID', `amount` decimal(10,2) NOT NULL COMMENT '报销金额', `reason` text COMMENT '报销事由', `status` tinyint(4) DEFAULT '0' COMMENT '0-待审批,1-通过,2-驳回', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;步骤2:写BPMN文件
复制leave.bpmn,改名为reimburse.bpmn,修改id="reimburseProcess",把<userTask name="员工提交申请">改成<userTask name="员工提交报销">,<userTask name="部门经理审批">改成<userTask name="财务审核">
步骤3:加Controller
新建ReimburseApplyController.java:
@RestController @RequestMapping("/api/reimburse") public class ReimburseApplyController { @PostMapping("/submit") public Result submit(@RequestBody ReimburseApply apply) { reimburseApplyMapper.insert(apply); runtimeService.startProcessInstanceByKey("reimburseProcess", Collections.singletonMap("businessKey", String.valueOf(apply.getId()))); return Result.success(); } }步骤4:前端加页面
在src/router/index.js里加路由:
{ path: '/reimburse/submit', name: 'ReimburseSubmit', component: () => import('@/views/reimburse/Submit.vue') }然后仿照leave目录,新建src/views/reimburse/Submit.vue,表单字段对应reimburse_apply表结构。
这个过程,你只写了20行Java代码、30行Vue模板、10行SQL,就新增了一个完整审批流程。PPT第25页的“扩展性设计原则”,强调的就是这种“业务表+流程定义+BPMN文件”的松耦合模式——流程引擎不管业务逻辑,业务代码不管状态流转,各司其职。
6.2 修改审批节点:从两级审批变成三级(加HR终审)
操作:打开leave.bpmn,在<userTask id="usertask2" name="部门经理审批">后面,插入:
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"/> <userTask id="usertask3" name="HR终审" activiti:candidateGroups="hr"/> <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endEvent1"/>然后在db.sql里,往act_id_group表插入hr组记录。无需改一行Java代码,流程就自动变成三级。
6.3 导出审批报表:用MyBatis-Plus的Wrapper写复杂查询
要查“本月各部门审批通过率”,在LeaveApproveRecordMapper.java里加方法:
@Select("SELECT " + "g.NAME_ as deptName, " + "COUNT(CASE WHEN r.opinion_type = 'agree' THEN 1 END) * 100.0 / COUNT(*) as passRate " + "FROM leave_approve_record r " + "JOIN act_hi_procinst p ON r.business_key = p.BUSINESS_KEY_ " + "JOIN act_id_group g ON p.START_USER_ID_ = g.ID_ " + "WHERE r.create_time >= #{startDate} " + "GROUP BY g.NAME_") List<Map<String, Object>> getPassRateByDept(@Param("startDate") Date startDate);调用时传入new Date(System.currentTimeMillis() - 30L * 24 * 60 * 60 * 1000),就能拿到数据。源码包里ReportController.java已预留此接口,你只需补全SQL。
这套系统真正的价值,不在于它现在能做什么,而在于它为你铺好了所有“可扩展的接口”:Activiti的ExecutionListener可以监听流程事件发邮件,MyBatis-Plus的@TableName注解让换表名只需改一个字符串,Vue的router-view让加页面就是复制粘贴。你不是在维护一个黑盒系统,而是在一个精心设计的骨架上,自由生长自己的业务枝叶。
本文还有配套的精品资源,点击获取
简介:这套工作流审批系统开箱即用,后端用SpringBoot 2.x开发,前端基于Vue.js实现响应式操作界面,完整支持流程建模、任务分派、多级审批、实时状态追踪等常用功能。压缩包里包含可直接运行的前后端源码(gongzuoliuchengguanli模块和Uhxn6nJrPfuY7GMZBiiw-master目录)、MySQL数据库初始化脚本db.sql、Maven依赖配置pom.xml、项目结构说明README.md、使用前必读.txt文档、系统架构与设计思路PPT(ppt.pptx),以及两段高清实操视频:一段是系统从启动到全流程审批的完整运行演示,另一段是配套论文讲解与开发要点梳理。所有代码已在本地环境验证通过,兼容IntelliJ IDEA和VS Code,导入后一键启动后端服务(SpringBoot)和前端服务(npm run serve),无需额外配置即可查看界面、提交申请、处理待办任务。适用于高校课程设计、毕业设计选题参考,也适合中小企业快速搭建轻量级内部审批流程。
本文还有配套的精品资源,点击获取