1.pom文件
注意下:Activiti 8 需要从 Alfresco Nexus 仓库获取
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.15</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.acticiti.test</groupId>
<artifactId>activitiSpringBoot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>activitiSpringBoot</name>
<description>activitiSpringBoot</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
<!-- Activiti 8 稳定版本 -->
<activiti.version>8.0.0</activiti.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 连接池,Spring Boot 默认使用 HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<!-- Activiti 工作流引擎 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- Activiti 图像生成(用于查看流程图) -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-image-generator</artifactId>
<version>${activiti.version}</version>
</dependency>
</dependencies>
<!-- Activiti 8 需要从 Alfresco Nexus 仓库获取 -->
<repositories>
<repository>
<id>activiti-releases</id>
<url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>activiti-releases</id>
<url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</execution>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2.application.yml
这里主要做业务数据库和activiti数据库配置,activiti基本配置
yaml
spring:
datasource:
# 主数据源(业务数据库)
primary:
jdbc-url: jdbc:mysql://localhost:3306/activitidemo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 1234
type: com.zaxxer.hikari.HikariDataSource
hikari:
pool-name: PrimaryHikariPool
maximum-pool-size: 10
# Activiti 专用数据源
activiti:
jdbc-url: jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 1234
type: com.zaxxer.hikari.HikariDataSource
hikari:
pool-name: ActivitiHikariPool
maximum-pool-size: 10
activiti:
process-definition-location-prefix: classpath*:/processes/**/*.bpmn
database-schema-update: true
check-process-definitions: true
# MyBatis配置
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.activiti.**.entity
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml
3.bpmn测试文件
xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://www.activiti.org/test" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://activiti.org/bpmn" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1784192091813" name="" targetNamespace="http://activiti.org/bpmn" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="myProcess" isClosed="false" isExecutable="true" processType="None">
<startEvent id="_2" name="StartEvent"/>
<userTask activiti:assignee="${applyUser}" activiti:exclusive="true" id="_3" name="员工提交请假申请"/>
<userTask activiti:assignee="${managerUser}" activiti:exclusive="true" id="_4" name="部门经理审批"/>
<endEvent id="_5" name="EndEvent"/>
<sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/>
<sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/>
<exclusiveGateway gatewayDirection="Unspecified" id="_9" name="ExclusiveGateway"/>
<sequenceFlow id="_10" sourceRef="_4" targetRef="_9"/>
<sequenceFlow id="_11" sourceRef="_9" targetRef="_5">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${auditResult == 'pass'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="_12" sourceRef="_9" targetRef="_3">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${auditResult == 'reject'}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram documentation="background=#2B2D30;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="myProcess">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<dc:Bounds height="32.0" width="32.0" x="270.0" y="50.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
<dc:Bounds height="55.0" width="85.0" x="250.0" y="130.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
<dc:Bounds height="55.0" width="85.0" x="250.0" y="270.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
<dc:Bounds height="32.0" width="32.0" x="130.0" y="310.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_9" id="Shape-_9" isMarkerVisible="false">
<dc:Bounds height="32.0" width="32.0" x="130.0" y="210.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_9" targetElement="_3">
<di:waypoint x="162.0" y="226.0"/>
<di:waypoint x="250.0" y="157.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3">
<di:waypoint x="286.0" y="82.0"/>
<di:waypoint x="286.0" y="130.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_4">
<di:waypoint x="292.5" y="185.0"/>
<di:waypoint x="292.5" y="270.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_9" targetElement="_5">
<di:waypoint x="146.0" y="242.0"/>
<di:waypoint x="146.0" y="310.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_4" targetElement="_9">
<di:waypoint x="250.0" y="297.5"/>
<di:waypoint x="162.0" y="226.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
4.ActivitiDataSourceConfig标记主数据库
kotlin
package com.activiti.config;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
@Configuration
public class ActivitiDataSourceConfig {
// 1. 创建业务数据源 Bean,并标记为 @Primary
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
// 2. 创建 Activiti 数据源 Bean
@Bean(name = "activitiDataSource")
@ConfigurationProperties(prefix = "spring.datasource.activiti")
public DataSource activitiDataSource() {
return DataSourceBuilder.create().build();
}
// 3. 配置 Activiti 引擎使用 activitiDataSource
@Bean
public ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer() {
return configuration -> {
// 强制设置 Activiti 使用专用数据源
configuration.setDataSource(activitiDataSource());
// 配置数据库表更新策略,开发时可设为 true 以自动建表/更新表
configuration.setDatabaseSchemaUpdate("true");
// 启用历史记录
configuration.setDbHistoryUsed(true);
configuration.setHistoryLevel(org.activiti.engine.impl.history.HistoryLevel.FULL);
};
}
}
5.entity
Leave
package com.activiti.entity;
import lombok.Data;
import java.util.Date;
@Data
public class Leave {
private Long id;
private String applyUser;
private String managerUser;
private Integer leaveDays;
private String reason;
private String rejectComment;
private Date startTime;
private Date endTime;
// 0待审批 1通过 2驳回待重提
private Integer auditStatus;
private Date createTime;
private Date updateTime;
}
LeaveDTO
package com.activiti.entity.dto;
import lombok.Data;
import java.util.Date;
@Data
public class LeaveDTO {
private String applyUser;
private String managerUser;
private Integer leaveDays;
private String reason;
private String rejectComment;
private Date startTime;
private Date endTime;
// 业务主键,启动流程后赋值
private Long businessKey;
}
AuditDTO
package com.activiti.entity.dto;
import lombok.Data;
@Data
public class AuditDTO {
private String taskId;
// pass / reject
private String auditResult;
// 驳回意见
private String rejectComment;
}
6.三层架构
less
package com.activiti.controller;
import com.activiti.entity.dto.AuditDTO;
import com.activiti.entity.dto.LeaveDTO;
import com.activiti.entity.Leave;
import com.activiti.service.LeaveService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/leave")
public class LeaveController {
@Autowired
private LeaveService leaveService;
/**
* 新建请假单,启动流程
*/
@PostMapping("/start")
public Map<String, Object> start(@RequestBody LeaveDTO dto) {
return leaveService.startProcess(dto);
}
/**
* 经理审批:通过 / 驳回(带驳回意见)
*/
@PostMapping("/audit")
public String audit(@RequestBody AuditDTO auditDTO) {
return leaveService.audit(auditDTO);
}
/**
* 驳回后员工修改单据重新提交
*/
@PostMapping("/resubmit/{businessKey}")
public String resubmit(@PathVariable Long businessKey, @RequestBody LeaveDTO dto) {
return leaveService.resubmit(businessKey, dto);
}
/**
* 查询用户待办任务
*/
@GetMapping("/todo/{userId}")
public List<Task> todo(@PathVariable String userId) {
return leaveService.getTodoTask(userId);
}
/**
* 根据业务ID查询单据详情
*/
@GetMapping("/detail/{businessKey}")
public Leave detail(@PathVariable Long businessKey) {
return leaveService.getLeaveDetail(businessKey);
}
/**
* 根据业务ID查询运行中流程
*/
@GetMapping("/proc/running/{businessKey}")
public ProcessInstance runningProc(@PathVariable Long businessKey) {
return leaveService.getRunningProc(businessKey);
}
/**
* 根据业务ID查询历史流程
*/
@GetMapping("/proc/history/{businessKey}")
public HistoricProcessInstance historyProc(@PathVariable Long businessKey) {
return leaveService.getHistoryProc(businessKey);
}
/**
* 根据业务ID查询当前待办任务
*/
@GetMapping("/task/{businessKey}")
public Task getTask(@PathVariable Long businessKey) {
return leaveService.getTaskByBusinessKey(businessKey);
}
/**
* 查询用户全部历史审批记录
*/
@GetMapping("/history/{userId}")
public List<HistoricTaskInstance> history(@PathVariable String userId) {
return leaveService.getHistoryTask(userId);
}
}
scss
package com.activiti.service;
import com.activiti.entity.dto.AuditDTO;
import com.activiti.entity.dto.LeaveDTO;
import com.activiti.entity.Leave;
import com.activiti.mapper.LeaveMapper;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class LeaveService {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
@Autowired
private LeaveMapper leaveMapper;
/**
* 1. 新建请假单并启动流程,绑定businessKey
*/
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> startProcess(LeaveDTO dto) {
// 保存业务单据
Leave leave = new Leave();
leave.setApplyUser(dto.getApplyUser());
leave.setManagerUser(dto.getManagerUser());
leave.setLeaveDays(dto.getLeaveDays());
leave.setReason(dto.getReason());
leave.setStartTime(dto.getStartTime());
leave.setEndTime(dto.getEndTime());
leaveMapper.insert(leave);
Long businessKey = leave.getId();
dto.setBusinessKey(businessKey);
// 流程变量
Map<String, Object> vars = buildProcessVars(dto);
System.out.println("////////////*********"+vars);
// 绑定businessKey启动流程
ProcessInstance instance = runtimeService.startProcessInstanceByKey(
"myProcess",
businessKey.toString(),
vars
);
Map<String, Object> res = new HashMap<>();
res.put("businessKey", businessKey);
res.put("processInstanceId", instance.getId());
return res;
}
/**
* 2. 经理审批:支持通过/驳回,保存驳回意见
*/
@Transactional(rollbackFor = Exception.class)
public String audit(AuditDTO auditDTO) {
Task task = taskService.createTaskQuery().taskId(auditDTO.getTaskId()).singleResult();
ProcessInstance procInst = runtimeService.createProcessInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.singleResult();
Long businessKey = Long.valueOf(procInst.getBusinessKey());
Map<String, Object> vars = new HashMap<>();
vars.put("auditResult", auditDTO.getAuditResult());
vars.put("rejectComment", auditDTO.getRejectComment());
// 完成审批任务,驱动流程流转
taskService.complete(auditDTO.getTaskId(), vars);
if ("pass".equals(auditDTO.getAuditResult())) {
// 审批通过,更新状态1
leaveMapper.updateStatusAndComment(businessKey, 1, "");
return "审批通过,流程办结";
} else {
// 驳回,更新状态2,保存驳回意见
leaveMapper.updateStatusAndComment(businessKey, 2, auditDTO.getRejectComment());
return "驳回成功,请申请人修改后重新提交";
}
}
/**
* 3. 驳回后员工修改单据、重新提交申请
*/
@Transactional(rollbackFor = Exception.class)
public String resubmit(Long businessKey, LeaveDTO dto) {
// 1. 更新业务单据信息,状态重置为待审批
leaveMapper.updateLeaveInfo(businessKey, dto.getLeaveDays(), dto.getReason(), dto.getStartTime(), dto.getEndTime());
// 2. 根据businessKey查询当前流程实例
ProcessInstance procInst = runtimeService.createProcessInstanceQuery()
.processInstanceBusinessKey(businessKey.toString())
.singleResult();
// 3. 查询当前员工提交任务
Task applyTask = taskService.createTaskQuery()
.processInstanceId(procInst.getId())
.taskAssignee(dto.getApplyUser())
.singleResult();
// 4. 更新流程变量并完成提交任务,流转到经理审批
Map<String, Object> vars = buildProcessVars(dto);
taskService.complete(applyTask.getId(), vars);
return "修改后重新提交成功,等待经理审批";
}
/**
* 组装流程公共变量
*/
private Map<String, Object> buildProcessVars(LeaveDTO dto) {
Map<String, Object> vars = new HashMap<>();
vars.put("applyUser", dto.getApplyUser());
vars.put("managerUser", dto.getManagerUser());
vars.put("leaveDays", dto.getLeaveDays());
vars.put("reason", dto.getReason());
vars.put("startTime", dto.getStartTime());
vars.put("endTime", dto.getEndTime());
// 初始化审批结果,避免网关表达式找不到变量
vars.put("auditResult", "");
return vars;
}
// ===================== 查询接口 =====================
// 根据业务ID查询运行中流程
public ProcessInstance getRunningProc(Long businessKey) {
return runtimeService.createProcessInstanceQuery()
.processInstanceBusinessKey(businessKey.toString())
.singleResult();
}
// 根据业务ID查询历史流程
public HistoricProcessInstance getHistoryProc(Long businessKey) {
return historyService.createHistoricProcessInstanceQuery()
.processInstanceBusinessKey(businessKey.toString())
.singleResult();
}
// 查询用户待办
public List<Task> getTodoTask(String assignee) {
return taskService.createTaskQuery()
.taskAssignee(assignee)
.orderByTaskCreateTime()
.desc()
.list();
}
// 查询历史任务
public List<HistoricTaskInstance> getHistoryTask(String userId) {
return historyService.createHistoricTaskInstanceQuery()
.taskAssignee(userId)
.orderByHistoricTaskInstanceEndTime().desc()
.list();
}
// 查询单据详情
public Leave getLeaveDetail(Long businessKey) {
return leaveMapper.selectById(businessKey);
}
// 根据业务ID查询当前待办任务
public Task getTaskByBusinessKey(Long businessKey) {
ProcessInstance procInst = getRunningProc(businessKey);
if (procInst == null) return null;
return taskService.createTaskQuery()
.processInstanceId(procInst.getId())
.singleResult();
}
}
LeaveMapper
package com.activiti.mapper;
import com.activiti.entity.Leave;
import org.apache.ibatis.annotations.*;
import java.util.Date;
@Mapper
public interface LeaveMapper {
// 新增请假单
@Insert("INSERT INTO t_leave(apply_user,manager_user,leave_days,reason,start_time,end_time,audit_status) " +
"VALUES(#{applyUser},#{managerUser},#{leaveDays},#{reason},#{startTime},#{endTime},0)")
Long insert(Leave leave);
// 根据业务ID查询
@Select("SELECT * FROM t_leave WHERE id = #{id}")
Leave selectById(@Param("id") Long id);
// 更新单据状态+驳回意见
@Update("UPDATE t_leave SET audit_status=#{auditStatus},reject_comment=#{rejectComment} WHERE id=#{id}")
void updateStatusAndComment(@Param("id") Long id,
@Param("auditStatus") Integer auditStatus,
@Param("rejectComment") String rejectComment);
// 修改请假内容(驳回后重提交)
@Update("UPDATE t_leave SET leave_days=#{leaveDays},reason=#{reason},start_time=#{startTime},end_time=#{endTime},audit_status=0,reject_comment='' WHERE id=#{id}")
void updateLeaveInfo(@Param("id") Long id,
@Param("leaveDays") Integer leaveDays,
@Param("reason") String reason,
@Param("startTime") Date startTime,
@Param("endTime") Date endTime);
}
业务表
sql
create table activitidemo.t_leave
(
id bigint auto_increment comment '业务主键=BusinessKey'
primary key,
apply_user varchar(50) not null comment '申请人账号',
manager_user varchar(50) not null comment '审批经理账号',
leave_days int not null comment '请假天数',
reason varchar(500) not null comment '请假原因',
reject_comment varchar(500) default '' null comment '驳回意见',
start_time date not null comment '请假开始时间',
end_time date not null comment '请假结束时间',
audit_status tinyint default 0 null comment '0待审批 1审批通过 2驳回待重提',
create_time datetime default CURRENT_TIMESTAMP null,
update_time datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP
)
comment '请假业务单据';
