
本文还有配套的精品资源点击获取简介这套工作流审批系统开箱即用后端用SpringBoot 2.x开发前端基于Vue.js实现响应式操作界面完整支持流程建模、任务分派、多级审批、实时状态追踪等常用功能。压缩包里包含可直接运行的前后端源码gongzuoliuchengguanli模块和Uhxn6nJrPfuY7GMZBiiw-master目录、MySQL数据库初始化脚本db.sql、Maven依赖配置pom.xml、项目结构说明README.md、使用前必读.txt文档、系统架构与设计思路PPTppt.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如leaveApplyId1001 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或ReactVue 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 :datataskList stripe el-table-column propname label任务名称 width180/el-table-column el-table-column propassignee label处理人 width120/el-table-column el-table-column label操作 width180 template slot-scope{row} el-button sizemini clickhandleApprove(row)审批/el-button el-button sizemini typedanger clickhandleReject(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/javaJava代码、src/main/resources配置文件、src/main/webapp静态资源。特别注意src/main/resources/application.yml它配置了MySQL连接spring.datasource.urljdbc:mysql://localhost:3306/workflow?useSSLfalseserverTimezoneAsia/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_names1”。这是因为Windows系统默认不区分表名大小写而Linux下区分。如果你在Windows开发、Linux部署不设这个参数db.sql里建的leave_apply表可能变成LEAVE_APPLY导致MyBatis找不到映射关系。解决方案修改MySQL配置文件my.ini在[mysqld]下添加lower_case_table_names1然后重启服务。3.2 流程定义与部署如何把画好的流程图变成可运行的审批链Activiti本身不提供图形化设计器但源码包里集成了activiti-modeler的简化版。实际操作中你不需要自己画BPMN——gongzuoliuchengguanli/src/main/resources/processes/目录下已经放好了leave.bpmn文件。用记事本打开它你会看到类似这样的XML片段process idleaveProcess name请假流程 isExecutabletrue startEvent idstartEvent1 name开始/ userTask idusertask1 name员工提交申请 activiti:assignee${initiator}/ sequenceFlow idflow1 sourceRefstartEvent1 targetRefusertask1/ userTask idusertask2 name部门经理审批 activiti:candidateGroupsmanager/ sequenceFlow idflow2 sourceRefusertask1 targetRefusertask2/ endEvent idendEvent1 name结束/ sequenceFlow idflow3 sourceRefusertask2 targetRefendEvent1/ /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_字段值为leaveProcessVERSION_为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.vuehandleApprove(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. 封装审批变量 MapString, 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] port3306 character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci lower_case_table_names1 # 关键必须设为13. 初始化数据库bin/mysqld --initialize --console记住临时密码4. 启动服务bin/mysqld --console5. 登录并修改密码mysql -u root -p执行ALTER USER rootlocalhost IDENTIFIED BY your_password;6. 创建数据库CREATE DATABASE workflow DEFAULT CHARSET utf8mb4;后端启动SpringBoot- 打开IntelliJ IDEAFile → 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 CodeFile → Open Folder选择Uhxn6nJrPfuY7GMZBiiw-master-...目录- 终端执行npm install如果卡在node-sass执行npm install node-sass4.14.1再重试- 修改src/utils/request.js里的基础URLconst service axios.create({baseURL: http://localhost:8080/api/})- 执行npm run serve- 浏览器访问http://localhost:8080输入admin/123456登录实测心得如果前端报Network Error90%是跨域问题。此时不要去配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_ 1Step 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}是adminStep 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?businessKey1001查到两条记录员工提交、经理审批意见内容、时间一目了然这个过程里你不需要写一行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末尾少了?useSSLfalseserverTimezoneAsia/Shanghai导致JDBC驱动连接失败排查1. 检查application.yml第12行spring.datasource.url确认端口3306、数据库名workflow、参数拼写2. 在MySQL命令行执行SHOW VARIABLES LIKE lower_case_table_names;必须返回13. 用Navicat连接localhost:3306测试能否登录workflow库5.2 前端空白页Cannot GET /现象浏览器打开http://localhost:8080显示空白F12看Network全是404原因Vue路由模式为history但后端没配fallback导致刷新页面时Nginx/Apache找不到/dashboard路径解决这不是生产环境问题开发时直接改vue.config.jsmodule.exports { devServer: { historyApiFallback: true // 添加这一行 } }源码包里已配置好如果你删了这行就会出现此问题。5.3 审批后任务不消失ACT_RU_TASK表还有记录现象点击“审批”按钮控制台显示success但待办列表没刷新数据库里任务还在原因Activiti任务完成时taskService.complete()必须传入正确的taskId而前端传的可能是row.idActiviti任务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包含characterEncodingutf8mb4独家避坑技巧在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) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;步骤2写BPMN文件复制leave.bpmn改名为reimburse.bpmn修改idreimburseProcess把userTask name员工提交申请改成userTask name员工提交报销userTask name部门经理审批改成userTask name财务审核步骤3加Controller新建ReimburseApplyController.javaRestController 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 idusertask2 name部门经理审批后面插入sequenceFlow idflow3 sourceRefusertask2 targetRefusertask3/ userTask idusertask3 nameHR终审 activiti:candidateGroupshr/ sequenceFlow idflow4 sourceRefusertask3 targetRefendEvent1/然后在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_) ListMapString, 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文档、系统架构与设计思路PPTppt.pptx以及两段高清实操视频一段是系统从启动到全流程审批的完整运行演示另一段是配套论文讲解与开发要点梳理。所有代码已在本地环境验证通过兼容IntelliJ IDEA和VS Code导入后一键启动后端服务SpringBoot和前端服务npm run serve无需额外配置即可查看界面、提交申请、处理待办任务。适用于高校课程设计、毕业设计选题参考也适合中小企业快速搭建轻量级内部审批流程。本文还有配套的精品资源点击获取