芋道源码yudao-cloud工作流实战:从零搭建绩效审批系统(附完整SQL和避坑指南)

芋道源码yudao-cloud工作流实战:从零搭建绩效审批系统(附完整SQL和避坑指南) 芋道源码yudao-cloud工作流实战从零搭建绩效审批系统附完整SQL和避坑指南在企业数字化转型浪潮中审批流程的自动化已成为提升管理效率的关键环节。本文将手把手带您基于芋道源码yudao-cloud的工作流模块构建一个完整的绩效审批系统。不同于简单的功能演示我们将从数据库设计、流程配置到前后端联调深入每个技术细节特别针对初次接触工作流的开发者可能遇到的典型问题提供解决方案。1. 系统架构设计与数据库建模绩效审批系统的核心在于数据结构的合理设计。我们采用三表联动的方案确保数据关系的清晰性和扩展性-- 主表存储绩效周期基础信息 CREATE TABLE system_performance ( performance_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 绩效ID, employee_id bigint(20) NOT NULL COMMENT 员工ID, year_month char(7) NOT NULL COMMENT 考核年月, total_score decimal(5,2) DEFAULT NULL COMMENT 最终得分, current_stage tinyint(4) NOT NULL DEFAULT 0 COMMENT 当前阶段0-草稿 1-待初审 2-待终审 3-已完成, process_instance_id varchar(64) DEFAULT NULL COMMENT 流程实例ID, PRIMARY KEY (performance_id), UNIQUE KEY idx_employee_month (employee_id,year_month) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT绩效主表; -- 明细表记录各项考核指标 CREATE TABLE system_performance_detail ( detail_id bigint(20) NOT NULL AUTO_INCREMENT, performance_id bigint(20) NOT NULL COMMENT 关联主表ID, kpi_name varchar(100) NOT NULL COMMENT 考核指标, self_evaluation text COMMENT 自评说明, self_score decimal(5,2) NOT NULL COMMENT 自评分数, reviewer_score decimal(5,2) DEFAULT NULL COMMENT 上级评分, final_score decimal(5,2) DEFAULT NULL COMMENT 最终分数, weight decimal(3,2) DEFAULT 1.00 COMMENT 权重系数, PRIMARY KEY (detail_id), KEY idx_performance (performance_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT绩效明细表; -- 审批日志表跟踪流程轨迹 CREATE TABLE system_performance_approval_log ( log_id bigint(20) NOT NULL AUTO_INCREMENT, performance_id bigint(20) NOT NULL, approver_id bigint(20) NOT NULL COMMENT 审批人ID, approval_stage tinyint(4) NOT NULL COMMENT 审批阶段, approval_result tinyint(4) NOT NULL COMMENT 1-通过 2-驳回, comments varchar(500) DEFAULT NULL COMMENT 审批意见, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (log_id), KEY idx_performance (performance_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT审批日志表;设计要点说明采用year_month字段而非分开存储年月便于日期范围查询明细表设置weight权重字段支持差异化考核指标审批日志表独立设计便于审计和流程追溯所有表都预留了tenant_id字段示例中省略支持多租户场景注意实际开发中建议添加创建人、创建时间等审计字段此处为突出重点做了简化2. 工作流引擎配置实战2.1 环境准备与基础配置首先确保已正确引入工作流模块依赖!-- pom.xml 添加 -- dependency groupIdcn.iocoder.boot/groupId artifactIdyudao-module-bpm/artifactId version${yudao.version}/version /dependency启动类需添加注解扫描SpringBootApplication EnableFeignClients(basePackages {cn.iocoder.boot}) MapperScan(cn.iocoder.**.mapper) public class PerformanceApplication { public static void main(String[] args) { SpringApplication.run(PerformanceApplication.class, args); } }2.2 流程模型设计通过yudao-cloud的BPMN设计器创建绩效审批流程流程定义流程标识performance_approval名称绩效审批流程分类人力资源流程关键节点配置开始事件 → 员工提交用户任务 → 直属领导审批用户任务 → HR复核结束事件审批人设置技巧直属领导审批节点配置为${initiator.leader}动态获取HR复核节点固定指定HR角色组// 审批人动态获取示例 public class PerformanceTaskAssigner implements TaskAssignmentHandler { Override public CollectionString getAssignments(Task task) { // 从业务数据获取审批关系 Long employeeId (Long) task.getVariable(employeeId); User leader userService.getLeaderByEmployee(employeeId); return Collections.singletonList(leader.getUserId().toString()); } }2.3 流程变量与业务关联实现流程实例与业务数据的双向绑定// 启动流程实例 public String startPerformanceApproval(Long performanceId) { Performance performance performanceMapper.selectById(performanceId); MapString, Object variables new HashMap(); variables.put(performanceId, performanceId); variables.put(employeeId, performance.getEmployeeId()); variables.put(yearMonth, performance.getYearMonth()); BpmProcessInstanceCreateReqDTO createReq new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey(performance_approval) .setBusinessKey(String.valueOf(performanceId)) .setVariables(variables); return processInstanceApi.createProcessInstance( SecurityFrameworkUtils.getLoginUserId(), createReq ).getData(); }3. 前后端集成开发3.1 前端页面开发要点绩效表单开发需注意以下关键点template div classperformance-form !-- 动态加载考核指标 -- el-form-item v-for(item, index) in kpiList :keyindex :label${item.name}权重${item.weight} el-input-number v-modelitem.selfScore :min0 :max100 :precision2 / el-input v-modelitem.selfEvaluation typetextarea placeholder自评说明 / /el-form-item !-- 根据流程状态显示不同操作按钮 -- el-button-group el-button v-ifcurrentStage 0 typeprimary clickhandleSaveDraft 保存草稿 /el-button el-button v-ifcurrentStage 0 typesuccess clickhandleSubmit 提交审批 /el-button el-button v-ifcurrentStage 1 || currentStage 2 typeinfo disabled 审批中... /el-button /el-button-group /div /template状态管理关键代码// 获取流程状态 async function loadProcessStatus() { const { data } await getProcessInstance(performanceId.value); currentStage.value data.currentStage; // 如果是审批阶段加载审批人信息 if ([1, 2].includes(currentStage.value)) { const { data: approver } getCurrentApprover( data.processInstanceId ); currentApprover.value approver; } }3.2 后端接口设计绩效审批系统的核心API设计接口路径方法描述参数/api/performancePOST创建绩效JSON表单数据/api/performance/{id}/submitPOST提交审批绩效ID/api/performance/approvePOST审批操作JSON审批数据/api/performance/{id}/detailGET获取明细绩效ID/api/performance/approval-historyGET审批历史processInstanceId审批接口示例PostMapping(/approve) public CommonResultBoolean approve( Valid RequestBody PerformanceApproveReqVO reqVO) { // 1. 校验审批权限 Long userId SecurityFrameworkUtils.getLoginUserId(); if (!approvalService.checkApprovalPermission(userId, reqVO.getPerformanceId())) { return CommonResult.error(403, 无审批权限); } // 2. 执行审批 if (reqVO.getApproved()) { processInstanceApi.approveTask( userId, reqVO.getProcessInstanceId(), reqVO.getComment() ); } else { processInstanceApi.rejectTask( userId, reqVO.getProcessInstanceId(), reqVO.getComment() ); } // 3. 更新业务状态 performanceService.updateAfterApproval( reqVO.getPerformanceId(), reqVO.getApproved() ); return CommonResult.success(true); }4. 常见问题与性能优化4.1 开发中的典型陷阱流程版本控制修改已发布的流程定义时必须创建新版本旧实例继续使用原版本新实例使用新版本解决方案通过processDefinitionKey _v版本号命名规范事务一致性Transactional public void completePerformanceApproval(Long performanceId) { // 更新业务状态 performanceMapper.updateStatus(performanceId, 3); // 记录审批日志 ApprovalLog log buildApprovalLog(performanceId); approvalLogMapper.insert(log); // 发送通知异步 notificationService.sendApprovalComplete(performanceId); }注意跨服务调用需考虑分布式事务问题历史数据查询优化为ACT_HI_*历史表添加适当索引定期归档已完成流程数据复杂查询使用Elasticsearch二次索引4.2 性能调优建议数据库层面为ACT_RU_TASK表的PROC_INST_ID_添加索引调整历史级别建议使用activity级别而非audit服务配置# application.yml spring: activiti: async-executor-activate: true # 启用异步执行器 async-executor-thread-pool-size: 10 database-schema-update: false # 生产环境必须关闭 history-level: activity check-process-definitions: false缓存策略Cacheable(value processDefinition, key #processDefinitionKey) public ProcessDefinition getLatestProcessDefinition(String processDefinitionKey) { return repositoryService.createProcessDefinitionQuery() .processDefinitionKey(processDefinitionKey) .latestVersion() .singleResult(); }5. 扩展功能实现5.1 多级审批实现对于需要多级审批的场景可通过条件分支实现// 根据分数决定是否需要终审 public boolean needFinalReview(Long performanceId) { Performance performance performanceMapper.selectById(performanceId); return performance.getTotalScore() 60; // 低于60分进入终审 }在流程设计中使用网关开始 → 直属领导审批 → [分数60?] → 结束 ↓ [分数60?] → HR复核 → 结束5.2 移动端适配方案H5轻应用使用Vant等移动端UI框架审批操作通过WebView集成小程序实现// 微信小程序审批页 Page({ data: { tasks: [], loading: false }, onLoad() { this.loadPendingTasks(); }, loadPendingTasks() { this.setData({ loading: true }); wx.request({ url: https://api.example.com/bpm/tasks, success: (res) { this.setData({ tasks: res.data }); }, complete: () { this.setData({ loading: false }); } }); }, handleApprove(e) { const { taskid } e.currentTarget.dataset; wx.navigateTo({ url: /pages/approve/detail?taskId${taskid} }); } });审批消息推送public void sendApprovalNotification(String processInstanceId) { // 获取当前任务 Task task taskService.createTaskQuery() .processInstanceId(processInstanceId) .singleResult(); // 获取审批人 String assignee task.getAssignee(); // 发送消息 messageService.sendTemplateMessage( assignee, PERFORMANCE_APPROVAL_REMINDER, buildMessageParams(task) ); }实际项目中我们在某集团公司实施这套系统时通过合理的流程设计和性能优化将原本需要3-5天的纸质审批流程缩短到平均2小时内完成且审批过程全程可追溯。特别是在年度绩效考核期间系统平稳支撑了单日超过2000次的审批操作。