【feat】增加OA审批业务流程

This commit is contained in:
Kris 2025-02-21 15:16:56 +08:00
parent 8b75cc85a2
commit d333edb0ba
25 changed files with 1988 additions and 0 deletions

View File

@ -0,0 +1,136 @@
package com.czsj.web.controller.oaLeave;
import com.czsj.common.annotation.Log;
import com.czsj.common.core.controller.BaseController;
import com.czsj.common.core.domain.AjaxResult;
import com.czsj.common.core.page.TableDataInfo;
import com.czsj.common.enums.BusinessType;
import com.czsj.common.utils.poi.ExcelUtil;
import com.czsj.oaLeave.domain.TestLeave;
import com.czsj.oaLeave.service.ITestLeaveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* OA 请假申请Controller
*
* @author czsj
* @date 2024-03-07
*/
@RestController
@RequestMapping("/system/leave")
public class TestLeaveController extends BaseController
{
@Autowired
private ITestLeaveService testLeaveService;
/**
* 查询OA 请假申请列表
*/
@PreAuthorize("@ss.hasPermi('system:leave:list')")
@GetMapping("/list")
public TableDataInfo list(TestLeave testLeave)
{
startPage();
List<TestLeave> list = testLeaveService.selectTestLeaveList(testLeave);
return getDataTable(list);
}
/**
* 导出OA 请假申请列表
*/
@PreAuthorize("@ss.hasPermi('system:leave:export')")
@Log(title = "OA 请假申请", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, TestLeave testLeave)
{
List<TestLeave> list = testLeaveService.selectTestLeaveList(testLeave);
ExcelUtil<TestLeave> util = new ExcelUtil<TestLeave>(TestLeave.class);
util.exportExcel(response, list, "OA 请假申请数据");
}
/**
* 获取OA 请假申请详细信息
*/
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") String id)
{
return success(testLeaveService.selectTestLeaveById(id));
}
/**
* 新增OA 请假申请
*/
@PreAuthorize("@ss.hasPermi('system:leave:add')")
@Log(title = "OA 请假申请", businessType = BusinessType.INSERT)
@PostMapping
@Transactional(rollbackFor = Exception.class)
public AjaxResult add(@RequestBody TestLeave testLeave, String flowStatus)
{
return toAjax(testLeaveService.insertTestLeave(testLeave, flowStatus));
}
/**
* 修改OA 请假申请
*/
@PreAuthorize("@ss.hasPermi('system:leave:edit')")
@Log(title = "OA 请假申请", businessType = BusinessType.UPDATE)
@PutMapping
@Transactional(rollbackFor = Exception.class)
public AjaxResult edit(@RequestBody TestLeave testLeave)
{
return toAjax(testLeaveService.updateTestLeave(testLeave));
}
/**
* 删除OA 请假申请
*/
@PreAuthorize("@ss.hasPermi('system:leave:remove')")
@Log(title = "OA 请假申请", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@Transactional(rollbackFor = Exception.class)
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(testLeaveService.deleteTestLeaveByIds(ids));
}
/**
* 提交审批
*/
@PreAuthorize("@ss.hasPermi('system:leave:submit')")
@Log(title = "OA 请假申请", businessType = BusinessType.OTHER)
@GetMapping(value = "/submit")
@Transactional(rollbackFor = Exception.class)
public AjaxResult submit(String id, String flowStatus) {
return toAjax(testLeaveService.submit(id, flowStatus));
}
/**
* 办理
*/
@Log(title = "流程实例", businessType = BusinessType.OTHER)
@PostMapping("/handle")
@Transactional(rollbackFor = Exception.class)
public AjaxResult handle(@RequestBody TestLeave testLeave, Long taskId, String skipType, String message
, String nodeCode, String flowStatus) {
return toAjax(testLeaveService.handle(testLeave, taskId, skipType, message, nodeCode, flowStatus));
}
/**
* 终止流程提前结束
*
* @param testLeave
* @return
*/
@PostMapping("/termination")
@Transactional(rollbackFor = Exception.class)
public AjaxResult termination(@RequestBody TestLeave testLeave) {
return toAjax(testLeaveService.termination(testLeave));
}
}

View File

@ -0,0 +1,41 @@
package com.czsj.oaLeave.config;
import com.czsj.oaLeave.handle.CustomDataFillHandler;
import com.czsj.oaLeave.handle.CustomPermissionHandler;
import org.dromara.warm.flow.core.handler.DataFillHandler;
import org.dromara.warm.flow.core.handler.PermissionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* warm-flow配置文件
*
* @author warm
*/
@Configuration
public class WarmFlowConfig {
/**
* 自定义填充 可配置文件注入也可用@Bean/@Component方式
*/
@Bean
public DataFillHandler dataFillHandler() {
return new CustomDataFillHandler();
}
/**
* 权限校验器 可配置文件注入也可用@Bean/@Component方式
*/
@Bean
public PermissionHandler permissionHandler() {
return new CustomPermissionHandler();
}
// /**
// * 全局租户处理器可配置文件注入也可用@Bean/@Component方式
// */
// @Bean
// public TenantHandler tenantHandler() {
// return new CustomTenantHandler();
// }
}

View File

@ -0,0 +1,211 @@
package com.czsj.oaLeave.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.czsj.common.annotation.Excel;
import com.czsj.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.Date;
import java.util.List;
/**
* OA 请假申请对象 test_leave
*
* @author czsj
* @date 2024-03-07
*/
public class TestLeave extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private String id;
/** 请假类型 */
@Excel(name = "请假类型")
private Long type;
/** 请假原因 */
private String reason;
/** 开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date startTime;
/** 结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date endTime;
/** 请假天数 */
@Excel(name = "请假天数")
private Long day;
/** 流程实例的id */
private Long instanceId;
/** 节点编码 */
private String nodeCode;
/** 流程节点名称 */
@Excel(name = "流程节点名称")
private String nodeName;
/**
* 节点类型0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关
*/
private Integer nodeType;
/** 流程状态0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效 */
@Excel(name = "流程状态", readConverterExp = "0=待提交,1=审批中,2=,审=批通过,8=已完成,9=已退回,1=0失效")
private String flowStatus;
/**抄送人*/
private List<String> additionalHandler;
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
public void setId(String id)
{
this.id = id;
}
public String getId()
{
return id;
}
public void setType(Long type)
{
this.type = type;
}
public Long getType()
{
return type;
}
public void setReason(String reason)
{
this.reason = reason;
}
public String getReason()
{
return reason;
}
public void setStartTime(Date startTime)
{
this.startTime = startTime;
}
public Date getStartTime()
{
return startTime;
}
public void setEndTime(Date endTime)
{
this.endTime = endTime;
}
public Date getEndTime()
{
return endTime;
}
public void setDay(Long day)
{
this.day = day;
}
public Long getDay()
{
return day;
}
public void setInstanceId(Long instanceId)
{
this.instanceId = instanceId;
}
public Long getInstanceId()
{
return instanceId;
}
public void setNodeCode(String nodeCode)
{
this.nodeCode = nodeCode;
}
public String getNodeCode()
{
return nodeCode;
}
public void setNodeName(String nodeName)
{
this.nodeName = nodeName;
}
public String getNodeName()
{
return nodeName;
}
public Integer getNodeType() {
return nodeType;
}
public TestLeave setNodeType(Integer nodeType) {
this.nodeType = nodeType;
return this;
}
public void setFlowStatus(String flowStatus)
{
this.flowStatus = flowStatus;
}
public String getFlowStatus()
{
return flowStatus;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public List<String> getAdditionalHandler()
{
return additionalHandler;
}
public void setAdditionalHandler(List<String> additionalHandler)
{
this.additionalHandler=additionalHandler;
}
public String getDelFlag()
{
return delFlag;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("type", getType())
.append("reason", getReason())
.append("startTime", getStartTime())
.append("endTime", getEndTime())
.append("day", getDay())
.append("instanceId", getInstanceId())
.append("nodeCode", getNodeCode())
.append("nodeName", getNodeName())
.append("nodeType", getNodeType())
.append("flowStatus", getFlowStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("delFlag", getDelFlag())
.toString();
}
}

View File

@ -0,0 +1,55 @@
package com.czsj.oaLeave.enums;
/**
* 流程类型枚举
*
* @author warm
* @since 2023/3/31 12:16
*/
public enum FlowType {
/**
* 请假流程
*/
TEST_LEAVE_SERIAL1("leaveFlow-serial1", "串行-简单"),
TEST_LEAVE_FORM1("leaveFlow-form1", "表单-简单"),
TEST_LEAVE_SERIAL2("leaveFlow-serial2", "串行-通过互斥"),
TEST_LEAVE_SERIAL3("leaveFlow-serial3", "串行-退回互斥"),
TEST_LEAVE_PARALLEL1("leaveFlow-parallel1", "并行-汇聚"),
TEST_LEAVE_PARALLEL2("leaveFlow-parallel2", "并行-分开"),
leaveFlow_meet_sign("leaveFlow-meet-sign", "会签"),
leaveFlow_vote_sign("leaveFlow-vote-sign", "票签");
private String key;
private String value;
FlowType(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
public static String getKeyByValue(String value) {
for (FlowType item : FlowType.values()) {
if (item.getValue().equals(value)) {
return item.getKey();
}
}
return null;
}
public static String getValueByKey(String key) {
for (FlowType item : FlowType.values()) {
if (item.getKey().equals(key)) {
return item.getValue();
}
}
return null;
}
}

View File

@ -0,0 +1,44 @@
package com.czsj.oaLeave.handle;
import org.dromara.warm.flow.core.entity.RootEntity;
import org.dromara.warm.flow.core.handler.DataFillHandler;
import org.dromara.warm.flow.core.utils.IdUtils;
import org.dromara.warm.flow.core.utils.ObjectUtil;
import java.util.Date;
import java.util.Objects;
/**
* 填充器 可通过配置文件注入也可用@Bean/@Component方式
*
* @author warm
*/
public class CustomDataFillHandler implements DataFillHandler {
@Override
public void idFill(Object object) {
RootEntity entity = (RootEntity) object;
if (ObjectUtil.isNotNull(entity)) {
if (Objects.isNull(entity.getId())) {
entity.setId(IdUtils.nextId());
}
}
}
@Override
public void insertFill(Object object) {
RootEntity entity = (RootEntity) object;
if (ObjectUtil.isNotNull(entity)) {
entity.setCreateTime(ObjectUtil.isNotNull(entity.getCreateTime()) ? entity.getCreateTime() : new Date());
entity.setUpdateTime(ObjectUtil.isNotNull(entity.getUpdateTime()) ? entity.getUpdateTime() : new Date());
}
}
@Override
public void updateFill(Object object) {
RootEntity entity = (RootEntity) object;
if (ObjectUtil.isNotNull(entity)) {
entity.setUpdateTime(ObjectUtil.isNotNull(entity.getUpdateTime()) ? entity.getUpdateTime() : new Date());
}
}
}

View File

@ -0,0 +1,49 @@
package com.czsj.oaLeave.handle;
import com.czsj.common.core.domain.entity.SysRole;
import com.czsj.common.core.domain.entity.SysUser;
import com.czsj.common.utils.SecurityUtils;
import org.dromara.warm.flow.core.handler.PermissionHandler;
import org.dromara.warm.flow.core.utils.StreamUtils;
import java.util.List;
/**
* 办理人权限处理器可通过配置文件注入也可用@Bean/@Component方式
*
* @author shadow
*/
public class CustomPermissionHandler implements PermissionHandler {
/**
* 获取当前操作用户所有权限
*/
@Override
public List<String> permissions() {
// 办理人权限标识比如用户角色部门等, 流程设计时未设置办理人或者ignore为true可不传 [按需传输]
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
List<SysRole> roles = sysUser.getRoles();
List<String> permissionList = StreamUtils.toList(roles, role -> "role:" + role.getRoleId());
if (sysUser.getUserId() != null) {
permissionList.add(String.valueOf(sysUser.getUserId()));
}
if (sysUser.getDeptId() != null) {
permissionList.add("dept:" + sysUser.getDeptId());
}
return permissionList;
}
/**
* 获取当前办理人
* @return 当前办理人
*/
@Override
public String getHandler() {
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
if (sysUser.getUserId() != null) {
return String.valueOf(sysUser.getUserId());
}
return null;
}
}

View File

@ -0,0 +1,18 @@
package com.czsj.oaLeave.handle;
import org.dromara.warm.flow.core.handler.TenantHandler;
/**
* 全局租户处理器可通过配置文件注入也可用@Bean/@Component方式
*
* @author warm
*/
public class CustomTenantHandler implements TenantHandler {
@Override
public String getTenantId() {
// 这里返回系统中的当前办理人的租户ID一般会有工具类获取
return "000000";
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2024-2025, Warm-Flow (290631660@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.czsj.oaLeave.listener;
import org.dromara.warm.flow.core.constant.FlowCons;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.entity.Task;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.dromara.warm.flow.core.utils.CollUtil;
import org.dromara.warm.flow.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 分派监听器表达式
*/
@Component
public class AssignmentExpListener {
private static final Logger log = LoggerFactory.getLogger(AssignmentExpListener.class);
public void notify(ListenerVariable listenerVariable) {
log.info("分派监听器表达式开始执行......");
List<Task> tasks = listenerVariable.getNextTasks();
Instance instance = listenerVariable.getInstance();
if (CollUtil.isNotEmpty(tasks)) {
for (Task task : tasks) {
List<String> permissionList = task.getPermissionList();
// 如果设置了发起人审批则需要动态替换权限标识
for (int i = 0; i < permissionList.size(); i++) {
String permission = permissionList.get(i);
if (StringUtils.isNotEmpty(permission) && permission.contains(FlowCons.WARMFLOWINITIATOR)) {
permissionList.set(i, permission.replace(FlowCons.WARMFLOWINITIATOR, instance.getCreateBy()));
}
}
}
}
log.info("分派监听器表达式执行结束......");
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 2024-2025, Warm-Flow (290631660@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.czsj.oaLeave.listener;
import org.dromara.warm.flow.core.constant.FlowCons;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.entity.Task;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.dromara.warm.flow.core.utils.CollUtil;
import org.dromara.warm.flow.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 分派监听器
*/
@Component
public class AssignmentListener implements Listener {
private static final Logger log = LoggerFactory.getLogger(AssignmentListener.class);
@Override
public void notify(ListenerVariable listenerVariable) {
log.info("分派监听器开始执行......");
List<Task> tasks = listenerVariable.getNextTasks();
Instance instance = listenerVariable.getInstance();
if (CollUtil.isNotEmpty(tasks)) {
for (Task task : tasks) {
List<String> permissionList = task.getPermissionList();
// 如果设置了发起人审批则需要动态替换权限标识
for (int i = 0; i < permissionList.size(); i++) {
String permission = permissionList.get(i);
if (StringUtils.isNotEmpty(permission) && permission.contains(FlowCons.WARMFLOWINITIATOR)) {
permissionList.set(i, permission.replace(FlowCons.WARMFLOWINITIATOR, instance.getCreateBy()));
}
}
}
}
log.info("分派监听器执行结束......");
}
}

View File

@ -0,0 +1,34 @@
package com.czsj.oaLeave.listener;
import com.czsj.common.utils.StringUtils;
import com.czsj.oaLeave.mapper.TestLeaveMapper;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
@Component
public class CreateListener implements Listener {
@Resource
private TestLeaveMapper testLeaveMapper;
private static final Logger log = LoggerFactory.getLogger(CreateListener.class);
@Override
public void notify(ListenerVariable listenerVariable) {
log.info("创建监听器......");
Instance instance = listenerVariable.getInstance();
Map<String, Object> variable = listenerVariable.getVariable();
if (StringUtils.isNotNull(variable)) {
String businessId = instance.getBusinessId();
Object businessType = variable.get("businessType");
}
log.info("创建监听器结束......");
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2024-2025, Warm-Flow (290631660@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.czsj.oaLeave.listener;
import org.dromara.warm.flow.core.listener.GlobalListener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 全局监听器: 整个系统只有一个任务开始分派完成和创建时期执行
*
* @author warm
* @since 2024/11/17
*/
@Component
public class CustomGlobalListener implements GlobalListener {
private static final Logger log = LoggerFactory.getLogger(CustomGlobalListener.class);
/**
* 开始监听器任务开始办理时执行
* @param listenerVariable 监听器变量
*/
public void start(ListenerVariable listenerVariable) {
log.info("全局开始监听器开始执行......");
log.info("全局开始监听器执行结束......");
}
/**
* 分派监听器动态修改代办任务信息
* @param listenerVariable 监听器变量
*/
public void assignment(ListenerVariable listenerVariable) {
log.info("全局分派监听器开始执行......");
log.info("全局分派监听器执行结束......");
}
/**
* 完成监听器当前任务完成后执行
* @param listenerVariable 监听器变量
*/
public void finish(ListenerVariable listenerVariable) {
log.info("全局完成监听器开始执行......");
log.info("全局完成监听器执行结束......");
}
/**
* 创建监听器任务创建时执行
* @param listenerVariable 监听器变量
*/
public void create(ListenerVariable listenerVariable) {
log.info("全局创建监听器开始执行......");
log.info("全局创建监听器执行结束......");
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 2024-2025, Warm-Flow (290631660@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.czsj.oaLeave.listener;
import org.dromara.warm.flow.core.constant.FlowCons;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.entity.Task;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.dromara.warm.flow.core.utils.CollUtil;
import org.dromara.warm.flow.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 流程分派监听器
*/
@Component
public class DefAssignmentListener implements Listener {
private static final Logger log = LoggerFactory.getLogger(DefAssignmentListener.class);
@Override
public void notify(ListenerVariable listenerVariable) {
log.info("流程分派监听器开始执行......");
List<Task> tasks = listenerVariable.getNextTasks();
Instance instance = listenerVariable.getInstance();
if (CollUtil.isNotEmpty(tasks)) {
for (Task task : tasks) {
List<String> permissionList = task.getPermissionList();
// 如果设置了发起人审批则需要动态替换权限标识
for (int i = 0; i < permissionList.size(); i++) {
String permission = permissionList.get(i);
if (StringUtils.isNotEmpty(permission) && permission.contains(FlowCons.WARMFLOWINITIATOR)) {
permissionList.set(i, permission.replace(FlowCons.WARMFLOWINITIATOR, instance.getCreateBy()));
}
}
}
}
log.info("流程分派监听器执行结束......");
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2024-2025, Warm-Flow (290631660@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.czsj.oaLeave.listener;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class DefCreateListener implements Listener {
private static final Logger log = LoggerFactory.getLogger(DefCreateListener.class);
@Override
public void notify(ListenerVariable listenerVariable) {
log.info("流程创建监听器......");
Instance instance = listenerVariable.getInstance();
Map<String, Object> variable = listenerVariable.getVariable();
log.info("流程创建监听器结束......");
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2024-2025, Warm-Flow (290631660@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.czsj.oaLeave.listener;
import com.czsj.common.utils.StringUtils;
import com.czsj.oaLeave.mapper.TestLeaveMapper;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
@Component
public class DefFinishListener implements Listener {
private static final Logger log = LoggerFactory.getLogger(DefFinishListener.class);
@Resource
private TestLeaveMapper testLeaveMapper;
/**
* 组件办理完成后通常需要业务表新增或者更新操作
* 也可以放到业务代码中办理完成后或者节点监听器
* @param listenerVariable 监听器变量
*/
@Override
public void notify(ListenerVariable listenerVariable) {
log.info("流程完成监听器......");
Instance instance = listenerVariable.getInstance();
Map<String, Object> variable = listenerVariable.getVariable();
if (StringUtils.isNotNull(variable)) {
String businessId = instance.getBusinessId();
Object businessType = variable.get("businessType");
// /** 如果{@link com.czsj.system.service.impl.TestLeaveServiceImpl}中更新了,这里就不用更新了*/
// // 更新业务数据
// if ("testLeave".equals(businessType)) {
// // 可以统一使用一个流程监听器不同实体类不同的操作
// TestLeave testLeave = testLeaveMapper.selectTestLeaveById(businessId);
// if (ObjectUtil.isNull(testLeave)) {
// testLeave = (TestLeave) variable.get("businessData");
// }
// testLeave.setNodeCode(instance.getNodeCode());
// testLeave.setNodeName(instance.getNodeName());
// testLeave.setNodeType(instance.getNodeType());
// testLeave.setFlowStatus(instance.getFlowStatus());
// // 如果没有实例id说明是新增
// if (ObjectUtil.isNull(testLeave.getInstanceId())) {
// testLeave.setInstanceId(instance.getId());
// testLeaveMapper.insertTestLeave(testLeave);
// testLeave.setCreateTime(DateUtils.getNowDate());
// // 新增抄送人方法也可发送通知
// if (StringUtils.isNotNull(testLeave.getAdditionalHandler())) {
// List<User> users = FlowEngine.userService().structureUser(instance.getId()
// , testLeave.getAdditionalHandler(), "4");
// FlowEngine.userService().saveBatch(users);
// }
// } else {
// testLeave.setUpdateTime(DateUtils.getNowDate());
// testLeaveMapper.updateTestLeave(testLeave);
// }
// }
}
log.info("流程完成监听器结束......");
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright 2024-2025, Warm-Flow (290631660@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.czsj.oaLeave.listener;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class DefStartListener implements Listener {
private static final Logger log = LoggerFactory.getLogger(DefStartListener.class);
/**
* 在开始监听器中预先设置办理人id所拥有的权限等操作减少重复代码
* 也可以放到业务代码中办理前设置或者节点监听器
* @param listenerVariable 监听器变量
*/
@Override
public void notify(ListenerVariable listenerVariable) {
log.info("流程开始监听器......");
// /** 如果{@link com.czsj.system.service.impl.TestLeaveServiceImpl}中传值了,这里就不用设置*/
// FlowParams flowParams = listenerVariable.getFlowParams();
// LoginUser user = SecurityUtils.getLoginUser();
// // 设置当前办理人id
// flowParams.handler(user.getUser().getUserId().toString());
//
// // 设置办理人所拥有的权限比如角色部门用户等
// List<String> permissionList = flowParams.getPermissionFlag();
// if (StringUtils.isEmpty(permissionList)) {
// permissionList = new ArrayList<>();
// }
//
// List<SysRole> roles = user.getUser().getRoles();
// if (Objects.nonNull(roles)) {
// permissionList.addAll(roles.stream().map(role -> "role:" + role.getRoleId()).collect(Collectors.toList()));
// }
// permissionList.add("dept:" + SecurityUtils.getLoginUser().getUser().getDeptId());
// permissionList.add(user.getUser().getUserId().toString());
// flowParams.permissionFlag(permissionList);
log.info("流程开始监听器结束......");
}
}

View File

@ -0,0 +1,34 @@
package com.czsj.oaLeave.listener;
import com.czsj.common.utils.StringUtils;
import com.czsj.oaLeave.mapper.TestLeaveMapper;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
@Component
public class FinishListener implements Listener {
@Resource
private TestLeaveMapper testLeaveMapper;
private static final Logger log = LoggerFactory.getLogger(FinishListener.class);
@Override
public void notify(ListenerVariable listenerVariable) {
log.info("完成监听器......");
Instance instance = listenerVariable.getInstance();
Map<String, Object> variable = listenerVariable.getVariable();
if (StringUtils.isNotNull(variable)) {
String businessId = instance.getBusinessId();
Object businessType = variable.get("businessType");
}
log.info("完成监听器结束......");
}
}

View File

@ -0,0 +1,59 @@
package com.czsj.oaLeave.listener;
import com.czsj.oaLeave.domain.TestLeave;
import com.czsj.oaLeave.service.ITestLeaveService;
import org.apache.commons.lang3.time.DateUtils;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.text.ParseException;
import java.util.Map;
/**
* @author vanlin
* @className LeaveEditFormHandleListener
* @description 用于流程表单项目保存数据演示 属于 完成监听器
* @since 2024-11-2 17:01
*/
@Component
public class LeaveEditFormHandleListener implements Listener {
@Resource
private ITestLeaveService testLeaveService;
@Override
public void notify(ListenerVariable listenerVariable) {
// 获取请假详情
// 表单处理监听器修改业务参数
String businessId = listenerVariable.getInstance().getBusinessId();
TestLeave testLeave = testLeaveService.selectTestLeaveById(businessId);
Map<String, Object> formData = listenerVariable.getVariable();
// reason 请假原因
// startTime 开始时间
// endTime 结束时间
// day 天数
try {
testLeave.setReason(formData.get("reason").toString());
testLeave.setStartTime(DateUtils.parseDate(formData.get("startTime").toString(), "yyyy-MM-dd"));
testLeave.setEndTime(DateUtils.parseDate(formData.get("endTime").toString(), "yyyy-MM-dd"));
testLeave.setDay(Long.valueOf(formData.get("day").toString()));
} catch (ParseException e) {
throw new RuntimeException(e);
}
// 更新请假表,以下字段需要在 formHandleAfter处理
// testLeave.setNodeCode(listenerVariable.getInstance().getNodeCode());
// testLeave.setNodeName(listenerVariable.getInstance().getNodeName());
// testLeave.setNodeType(listenerVariable.getInstance().getNodeType());
// testLeave.setFlowStatus(listenerVariable.getInstance().getFlowStatus());
testLeaveService.updateTestLeave(testLeave);
// 流程变量传递业务数据按实际业务需求传递 按需传
listenerVariable.getFlowParams().getVariable().put("businessData", testLeave);
// 办理人变量表达式替换 按需传
listenerVariable.getFlowParams().getVariable().put("flag", String.valueOf(testLeave.getDay()));
}
}

View File

@ -0,0 +1,48 @@
package com.czsj.oaLeave.listener;
import com.czsj.oaLeave.domain.TestLeave;
import com.czsj.oaLeave.service.ITestLeaveService;
import org.dromara.warm.flow.core.constant.FlowCons;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author vanlin
* @className LeaveFormLoadListener
* @description 用于流程表单从业务功能加载数据演示
* @since 2024-11-2 17:01
*/
@Component
public class LeaveFormLoadListener implements Listener {
@Resource
private ITestLeaveService testLeaveService;
@Override
public void notify(ListenerVariable listenerVariable) {
// 获取请假详情
// 全局表单加载器加载表单业务数据按map返回
String businessId = listenerVariable.getInstance().getBusinessId();
TestLeave testLeave = testLeaveService.selectTestLeaveById(businessId);
final Map<String, Object> formData = new HashMap<String, Object>();
// reason 请假原因
// startTime 开始时间
// endTime 结束时间
// day 天数
formData.put("reason", testLeave.getReason());
List<String> time = new ArrayList<String>();
time.add(String.valueOf(testLeave.getStartTime()));
time.add(String.valueOf(testLeave.getEndTime()));
formData.put("time", time);
formData.put("day", testLeave.getDay());
listenerVariable.getInstance().getVariableMap().put(FlowCons.FORM_DATA, formData);
}
}

View File

@ -0,0 +1,25 @@
package com.czsj.oaLeave.listener;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.listener.Listener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class StartListener implements Listener {
private static final Logger log = LoggerFactory.getLogger(StartListener.class);
@Override
public void notify(ListenerVariable listenerVariable) {
log.info("开始监听器......");
Instance instance = listenerVariable.getInstance();
Map<String, Object> variableMap = listenerVariable.getVariable();
log.info("开始监听器结束......");
}
}

View File

@ -0,0 +1,70 @@
package com.czsj.oaLeave.mapper;
import com.czsj.oaLeave.domain.TestLeave;
import java.util.List;
/**
* OA 请假申请Mapper接口
*
* @author czsj
* @date 2024-03-07
*/
public interface TestLeaveMapper
{
/**
* 查询OA 请假申请
*
* @param id OA 请假申请主键
* @return OA 请假申请
*/
public TestLeave selectTestLeaveById(String id);
/**
* 查询OA 请假申请
*
* @param ids OA 请假申请主键s
* @return OA 请假申请
*/
public List<TestLeave> selectTestLeaveByIds(String[] ids);
/**
* 查询OA 请假申请列表
*
* @param testLeave OA 请假申请
* @return OA 请假申请集合
*/
public List<TestLeave> selectTestLeaveList(TestLeave testLeave);
/**
* 新增OA 请假申请
*
* @param testLeave OA 请假申请
* @return 结果
*/
public int insertTestLeave(TestLeave testLeave);
/**
* 修改OA 请假申请
*
* @param testLeave OA 请假申请
* @return 结果
*/
public int updateTestLeave(TestLeave testLeave);
/**
* 删除OA 请假申请
*
* @param id OA 请假申请主键
* @return 结果
*/
public int deleteTestLeaveById(String id);
/**
* 批量删除OA 请假申请
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteTestLeaveByIds(String[] ids);
}

View File

@ -0,0 +1,166 @@
package com.czsj.oaLeave.service;
import com.github.pagehelper.PageInfo;
import com.czsj.common.core.domain.entity.SysDept;
import com.czsj.common.core.domain.entity.SysRole;
import com.czsj.common.core.domain.entity.SysUser;
import com.czsj.common.utils.DateUtils;
import com.czsj.system.mapper.SysDeptMapper;
import com.czsj.system.mapper.SysRoleMapper;
import com.czsj.system.mapper.SysUserMapper;
import org.dromara.warm.flow.core.utils.MathUtil;
import org.dromara.warm.flow.ui.dto.HandlerFunDto;
import org.dromara.warm.flow.ui.dto.HandlerQuery;
import org.dromara.warm.flow.ui.dto.TreeFunDto;
import org.dromara.warm.flow.ui.service.HandlerSelectService;
import org.dromara.warm.flow.ui.vo.HandlerSelectVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import static com.czsj.common.utils.PageUtils.startPage;
/**
* 流程设计器-获取办理人权限设置列表接口实现类
*
* @author warm
*/
@Component
public class HandlerSelectServiceImpl implements HandlerSelectService {
@Autowired
private SysUserMapper userMapper;
@Autowired
private SysRoleMapper roleMapper;
@Autowired
private SysDeptMapper deptMapper;
/**
* 获取办理人权限设置列表tabs页签用户角色和部门等可以返回其中一种或者多种按业务需求决定
* @return tabs页签
*/
@Override
public List<String> getHandlerType() {
return Arrays.asList("用户", "角色", "部门");
}
/**
* 获取用户列表角色列表部门列表等可以返回其中一种或者多种按业务需求决定
* @param query 查询参数
* @return 结果
*/
@Override
public HandlerSelectVo getHandlerSelect(HandlerQuery query) {
if ("角色".equals(query.getHandlerType())) {
return getRole(query);
}
if ("部门".equals(query.getHandlerType())) {
return getDept(query);
}
if ("用户".equals(query.getHandlerType())) {
return getUser(query);
}
return new HandlerSelectVo();
}
/**
* 获取角色列表
*
* @param query 查询条件
* @return HandlerSelectVo
*/
private HandlerSelectVo getRole(HandlerQuery query) {
startPage();
SysRole sysRole = new SysRole();
sysRole.setRoleKey(query.getHandlerCode());
sysRole.setRoleName(query.getHandlerName());
sysRole.getParams().put("beginTime", query.getBeginTime());
sysRole.getParams().put("endTime", query.getEndTime());
// 查询角色列表
List<SysRole> roleList = roleMapper.selectRoleList(sysRole);
long total = new PageInfo<>(roleList).getTotal();
// 业务系统数据转成组件内部能够显示的数据, total是业务数据总数用于分页显示
HandlerFunDto<SysRole> handlerFunDto = new HandlerFunDto<>(roleList, total)
// 以下设置获取内置变量的Function
.setStorageId(role -> "role:" + role.getRoleId()) // 前面拼接role: 是为了防止用户角色的主键重复
.setHandlerCode(SysRole::getRoleKey) // 权限编码
.setHandlerName(SysRole::getRoleName) // 权限名称
.setCreateTime(role -> DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, role.getCreateTime()));
return getHandlerSelectVo(handlerFunDto);
}
/**
* 获取用户列表
*
* @param query 查询条件
* @return HandlerSelectVo
*/
private HandlerSelectVo getDept(HandlerQuery query) {
startPage();
SysDept sysDept = new SysDept();
sysDept.setDeptName(query.getHandlerName());
sysDept.getParams().put("beginTime", query.getBeginTime());
sysDept.getParams().put("endTime", query.getEndTime());
// 查询部门列表
List<SysDept> deptList = deptMapper.selectDeptList(sysDept);
long total = new PageInfo<>(deptList).getTotal();
// 业务系统数据转成组件内部能够显示的数据, total是业务数据总数用于分页显示
HandlerFunDto<SysDept> handlerFunDto = new HandlerFunDto<>(deptList, total)
.setStorageId(dept -> "dept:" + dept.getDeptId()) // 前面拼接dept: 是为了防止用户部门的主键重复
.setHandlerName(SysDept::getDeptName) // 权限名称
.setCreateTime(dept -> DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, dept.getCreateTime()));
return getHandlerSelectVo(handlerFunDto);
}
/**
* 获取用户列表, 同时构建左侧部门树状结构
*
* @param query 查询条件
* @return HandlerSelectVo
*/
private HandlerSelectVo getUser(HandlerQuery query) {
startPage();
SysUser sysUser = new SysUser();
sysUser.setUserName(query.getHandlerCode());
sysUser.setNickName(query.getHandlerName());
// 办理人用户选择列表需要展示左侧树状部门所以可能会通过部门id
if (MathUtil.isNumeric(query.getGroupId())) {
sysUser.setDeptId(Long.valueOf(query.getGroupId()));
}
sysUser.getParams().put("beginTime", query.getBeginTime());
sysUser.getParams().put("endTime", query.getEndTime());
// 查询用户列表
List<SysUser> userList = userMapper.selectUserList(sysUser);
long total = new PageInfo<>(userList).getTotal();
// 查询部门列表构建树状结构
List<SysDept> deptList = deptMapper.selectDeptList(new SysDept());
// 业务系统数据转成组件内部能够显示的数据, total是业务数据总数用于分页显示
HandlerFunDto<SysUser> handlerFunDto = new HandlerFunDto<>(userList, total)
.setStorageId(user -> user.getUserId().toString())
.setHandlerCode(SysUser::getUserName) // 权限编码
.setHandlerName(SysUser::getNickName) // 权限名称
.setCreateTime(user -> DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, user.getCreateTime()))
.setGroupName(user -> user.getDept() != null ? user.getDept().getDeptName() : "");
// 业务系统机构转成组件内部左侧树列表能够显示的数据
TreeFunDto<SysDept> treeFunDto = new TreeFunDto<>(deptList)
.setId(dept -> dept.getDeptId().toString()) // 左侧树ID
.setName(SysDept::getDeptName) // 左侧树名称
.setParentId(dept -> dept.getParentId().toString()); // 左侧树父级ID
return getHandlerSelectVo(handlerFunDto, treeFunDto);
}
}

View File

@ -0,0 +1,92 @@
package com.czsj.oaLeave.service;
import com.czsj.oaLeave.domain.TestLeave;
import java.util.List;
/**
* OA 请假申请Service接口
*
* @author czsj
* @date 2024-03-07
*/
public interface ITestLeaveService
{
/**
* 查询OA 请假申请
*
* @param id OA 请假申请主键
* @return OA 请假申请
*/
public TestLeave selectTestLeaveById(String id);
/**
* 查询OA 请假申请列表
*
* @param testLeave OA 请假申请
* @return OA 请假申请集合
*/
public List<TestLeave> selectTestLeaveList(TestLeave testLeave);
/**
* 新增OA 请假申请
*
* @param testLeave OA 请假申请
* @param flowStatus 自定义流程状态扩展
* @return 结果
*/
public int insertTestLeave(TestLeave testLeave, String flowStatus);
/**
* 修改OA 请假申请
*
* @param testLeave OA 请假申请
* @return 结果
*/
public int updateTestLeave(TestLeave testLeave);
/**
* 批量删除OA 请假申请
*
* @param ids 需要删除的OA 请假申请主键集合
* @return 结果
*/
public int deleteTestLeaveByIds(String[] ids);
/**
* 删除OA 请假申请信息
*
* @param id OA 请假申请主键
* @return 结果
*/
public int deleteTestLeaveById(String id);
/**
* 提交审批
*
* @param id
* @param flowStatus 自定义流程状态扩展
* @return
*/
public int submit(String id, String flowStatus);
/**
* 办理
*
* @param testLeave
* @param taskId
* @param skipType
* @param message
* @param nodeCode
* @param flowStatus 自定义流程状态扩展
* @return
*/
int handle(TestLeave testLeave, Long taskId, String skipType, String message, String nodeCode, String flowStatus);
/**
* 终止流程提前结束
* @param testLeave
* @return
*/
int termination(TestLeave testLeave);
}

View File

@ -0,0 +1,42 @@
package com.czsj.oaLeave.service;
import org.dromara.warm.flow.core.entity.Task;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
/**
* 用户类
*/
@Component("user")
public class User {
/**
* spel条件表达判断大于等4
* @param flag 待判断的字符串
* @return boolean
*/
public boolean eval(String flag) {
BigDecimal a = new BigDecimal(flag);
BigDecimal b = new BigDecimal("4");
return a.compareTo(b) > 0;
}
/**
* spel办理人变量表达式
* @param handler 办理人
* @return String
*/
public Object evalVar(Object handler) {
return handler;
}
/**
* spel办理人变量表达式
* @param handler 办理人
* @return String
*/
public Long evalVarEntity(Task handler) {
return handler.getId();
}
}

View File

@ -0,0 +1,304 @@
package com.czsj.oaLeave.service.impl;
import com.alibaba.fastjson2.JSON;
import com.czsj.common.core.domain.entity.SysDictData;
import com.czsj.common.core.domain.entity.SysRole;
import com.czsj.common.core.domain.model.LoginUser;
import com.czsj.common.exception.ServiceException;
import com.czsj.common.utils.DateUtils;
import com.czsj.common.utils.SecurityUtils;
import com.czsj.common.utils.StringUtils;
import com.czsj.oaLeave.domain.TestLeave;
import com.czsj.oaLeave.mapper.TestLeaveMapper;
import com.czsj.system.service.ISysDictTypeService;
import com.czsj.oaLeave.service.ITestLeaveService;
import org.dromara.warm.flow.core.FlowEngine;
import org.dromara.warm.flow.core.dto.FlowParams;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.entity.Task;
import org.dromara.warm.flow.core.entity.User;
import org.dromara.warm.flow.core.enums.SkipType;
import org.dromara.warm.flow.core.service.InsService;
import org.dromara.warm.flow.core.service.TaskService;
import org.dromara.warm.flow.core.utils.CollUtil;
import org.dromara.warm.flow.core.utils.IdUtils;
import org.dromara.warm.flow.core.utils.StreamUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
/**
* OA 请假申请Service业务层处理
*
* @author czsj
* @date 2024-03-07
*/
@Service
public class TestLeaveServiceImpl implements ITestLeaveService
{
@Resource
private TestLeaveMapper testLeaveMapper;
@Resource
private InsService insService;
@Resource
private TaskService taskService;
@Resource
private ISysDictTypeService sysDictTypeService;
/**
* 查询OA 请假申请
*
* @param id OA 请假申请主键
* @return OA 请假申请
*/
@Override
public TestLeave selectTestLeaveById(String id)
{
TestLeave testLeave = testLeaveMapper.selectTestLeaveById(id);
List<String> permission = FlowEngine.userService().getPermission(testLeave.getInstanceId(), "4");
if (CollUtil.isNotEmpty(permission)) {
testLeave.setAdditionalHandler(permission);
}else {
testLeave.setAdditionalHandler(new ArrayList<>());
}
return testLeave;
}
/**
* 查询OA 请假申请列表
*
* @param testLeave OA 请假申请
* @return OA 请假申请
*/
@Override
public List<TestLeave> selectTestLeaveList(TestLeave testLeave)
{
return testLeaveMapper.selectTestLeaveList(testLeave);
}
/**
* 新增OA 请假申请
*
* @param testLeave OA 请假申请
* @return 结果
*/
@Override
public int insertTestLeave(TestLeave testLeave, String flowStatus)
{
// 设置流转参数
String id = IdUtils.nextIdStr();
testLeave.setId(id);
LoginUser user = SecurityUtils.getLoginUser();
// 从字典表中获取流程编码
String flowCode = getFlowType(testLeave);
// 传递流程编码绑定流程定义 必传
FlowParams flowParams = FlowParams.build().flowCode(flowCode);
// 设置办理人唯一标识保存为流程实例的创建人 必传
flowParams.handler(user.getUser().getUserId().toString());
// 流程变量
Map<String, Object> variable = new HashMap<>();
// 流程变量传递业务数据按实际业务需求传递 按需传
variable.put("businessData", testLeave);
variable.put("businessType", "testLeave");
// 条件表达式替换判断是否满足某个任务的跳转条件 按需传
variable.put("flag", String.valueOf(testLeave.getDay()));
// 办理人变量表达式替换 按需传
variable.put("handler1", Arrays.asList(4, "5", 100L));
variable.put("handler2", 12L);
variable.put("handler3", new Object[] {9, "10", 102L});
variable.put("handler4", "15");
Task task = FlowEngine.newTask().setId(55L);
variable.put("handler5", task);
variable.put("handler6", 77L);
flowParams.variable(variable);
// 自定义流程状态扩展
if (StringUtils.isNotEmpty(flowStatus)) {
flowParams.flowStatus(flowStatus).hisStatus(flowStatus);
}
// 新增请假表
Instance instance = insService.start(id, flowParams);
testLeave.setInstanceId(instance.getId());
testLeave.setNodeCode(instance.getNodeCode());
testLeave.setNodeName(instance.getNodeName());
testLeave.setNodeType(instance.getNodeType());
testLeave.setFlowStatus(instance.getFlowStatus());
testLeave.setCreateTime(DateUtils.getNowDate());
// 新增抄送人方法 按需
if (StringUtils.isNotNull(testLeave.getAdditionalHandler())) {
List<User> users = FlowEngine.userService().structureUser(instance.getId()
, testLeave.getAdditionalHandler(), "4");
FlowEngine.userService().saveBatch(users);
}
// 此处可以发送消息通知比如短信通知邮件通知等代码自己实现
return testLeaveMapper.insertTestLeave(testLeave);
}
/**
* 修改OA 请假申请
*
* @param testLeave OA 请假申请
* @return 结果
*/
@Override
public int updateTestLeave(TestLeave testLeave)
{
testLeave.setUpdateTime(DateUtils.getNowDate());
return testLeaveMapper.updateTestLeave(testLeave);
}
/**
* 批量删除OA 请假申请
*
* @param ids 需要删除的OA 请假申请主键
* @return 结果
*/
@Override
public int deleteTestLeaveByIds(String[] ids)
{
List<TestLeave> testLeaveList = testLeaveMapper.selectTestLeaveByIds(ids);
if (testLeaveMapper.deleteTestLeaveByIds(ids) > 0) {
List<Long> instanceIds = testLeaveList.stream().map(TestLeave::getInstanceId).collect(Collectors.toList());
return insService.remove(instanceIds) ? 1: 0;
}
return 0;
}
/**
* 删除OA 请假申请信息
*
* @param id OA 请假申请主键
* @return 结果
*/
@Override
public int deleteTestLeaveById(String id)
{
return testLeaveMapper.deleteTestLeaveById(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int submit(String id, String flowStatus) {
// 设置流转参数
TestLeave testLeave = testLeaveMapper.selectTestLeaveById(id);
LoginUser user = SecurityUtils.getLoginUser();
// 是通过流程还是退回流程 必传
FlowParams flowParams = FlowParams.build().skipType(SkipType.PASS.getKey());
// 作为办理人保存到历史记录表 必传
flowParams.handler(user.getUser().getUserId().toString());
// 设置办理人拥有的权限办理中需要校验是否有权限办理 必传
List<SysRole> roles = user.getUser().getRoles();
List<String> permissionList = new ArrayList<>();
if (Objects.nonNull(roles)) {
permissionList = roles.stream().map(role -> "role:" + role.getRoleId()).collect(Collectors.toList());
}
permissionList.add("dept:" + SecurityUtils.getLoginUser().getUser().getDeptId());
permissionList.add(user.getUser().getUserId().toString());
flowParams.permissionFlag(permissionList);
// 自定义流程状态扩展 按需传
if (StringUtils.isNotEmpty(flowStatus)) {
flowParams.flowStatus(flowStatus).hisStatus(flowStatus);
}
// 流程变量
Map<String, Object> variable = new HashMap<>();
// 流程变量传递业务数据按实际业务需求传递 按需传
variable.put("businessType", "testLeave");
// 办理人变量表达式替换 按需传
variable.put("flag", String.valueOf(testLeave.getDay()));
flowParams.variable(variable);
// 更新请假表
Instance instance = insService.skipByInsId(testLeave.getInstanceId(), flowParams);
testLeave.setNodeCode(instance.getNodeCode());
testLeave.setNodeName(instance.getNodeName());
testLeave.setNodeType(instance.getNodeType());
testLeave.setFlowStatus(instance.getFlowStatus());
testLeave.setUpdateTime(DateUtils.getNowDate());
return testLeaveMapper.updateTestLeave(testLeave);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int handle(TestLeave testLeave, Long taskId, String skipType, String message, String nodeCode, String flowStatus) {
// 设置流转参数
LoginUser user = SecurityUtils.getLoginUser();
// 是通过流程还是退回流程 必传
FlowParams flowParams = FlowParams.build().skipType(skipType);
// 作为办理人保存到历史记录表 必传
flowParams.handler(user.getUser().getUserId().toString());
// 如果需要任意跳转流程传入此参数 按需传
flowParams.nodeCode(nodeCode);
// 作为审批意见保存到历史记录表 按需传
flowParams.message(message);
// 流程变量
Map<String, Object> variable = new HashMap<>();
// 流程变量传递业务数据按实际业务需求传递 按需传
variable.put("businessType", "testLeave");
// 办理人变量表达式替换 按需传
variable.put("flag", String.valueOf(testLeave.getDay()));
flowParams.variable(variable);
// 自定义流程状态扩展 按需传
if (StringUtils.isNotEmpty(flowStatus)) {
flowParams.flowStatus(flowStatus).hisStatus(flowStatus);
}
// 请假信息存入flowParams,方便查看历史审批数据 按需传
flowParams.hisTaskExt(JSON.toJSONString(testLeave));
Instance instance = taskService.skip(taskId, flowParams);
// 更新请假表
testLeave.setNodeCode(instance.getNodeCode());
testLeave.setNodeName(instance.getNodeName());
testLeave.setNodeType(instance.getNodeType());
testLeave.setFlowStatus(instance.getFlowStatus());
return testLeaveMapper.updateTestLeave(testLeave);
}
@Override
public int termination(TestLeave testLeave) {
// 设置流转参数
FlowParams flowParams = new FlowParams();
LoginUser user = SecurityUtils.getLoginUser();
// 作为审批意见保存到历史记录表 按需传
flowParams.message("终止流程");
// 作为办理人保存到历史记录表 必传
flowParams.handler(user.getUserId().toString());
Map<String, Object> variable = new HashMap<>();
// 流程变量传递业务数据按实际业务需求传递 按需传
variable.put("businessType", "testLeave");
flowParams.variable(variable);
Instance instance = insService.termination(testLeave.getInstanceId(), flowParams);
if (instance == null) {
throw new ServiceException("流程实例不存在");
}
// 更新请假表
testLeave.setNodeCode(instance.getNodeCode());
testLeave.setNodeName(instance.getNodeName());
testLeave.setNodeType(instance.getNodeType());
testLeave.setFlowStatus(instance.getFlowStatus());
return testLeaveMapper.updateTestLeave(testLeave);
}
/**
* 从字典表中获取流程编码
* @param testLeave 请假信息
* @return 流程编码
*/
private String getFlowType(TestLeave testLeave) {
List<SysDictData> leaveType = sysDictTypeService.selectDictDataByType("leave_type");
Map<String, String> map = StreamUtils.toMap(leaveType, SysDictData::getDictValue, SysDictData::getRemark);
return map.get(testLeave.getType().toString());
}
}

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czsj.oaLeave.mapper.TestLeaveMapper">
<resultMap type="TestLeave" id="TestLeaveResult">
<result property="id" column="id" />
<result property="type" column="type" />
<result property="reason" column="reason" />
<result property="startTime" column="start_time" />
<result property="endTime" column="end_time" />
<result property="day" column="day" />
<result property="instanceId" column="instance_id" />
<result property="nodeCode" column="node_code" />
<result property="nodeName" column="node_name" />
<result property="nodeType" column="node_type" />
<result property="flowStatus" column="flow_status" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="delFlag" column="del_flag" />
</resultMap>
<sql id="selectTestLeaveVo">
select id, type, reason, start_time, end_time, day, instance_id, node_code, node_name, node_type, flow_status, create_by, create_time, update_by, update_time, del_flag from test_leave
</sql>
<select id="selectTestLeaveList" parameterType="TestLeave" resultMap="TestLeaveResult">
<include refid="selectTestLeaveVo"/>
<where>
<if test="type != null "> and type = #{type}</if>
<if test="day != null "> and day = #{day}</if>
<if test="flowStatus != null and flowStatus != ''"> and flow_status = #{flowStatus}</if>
<if test="createBy != null and createBy != ''"> and create_by = #{createBy}</if>
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
</where>
order by create_time desc
</select>
<select id="selectTestLeaveById" parameterType="String" resultMap="TestLeaveResult">
<include refid="selectTestLeaveVo"/>
where id = #{id}
</select>
<select id="selectTestLeaveByIds" parameterType="String" resultMap="TestLeaveResult">
<include refid="selectTestLeaveVo"/>
where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<insert id="insertTestLeave" parameterType="TestLeave">
insert into test_leave
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="type != null">type,</if>
<if test="reason != null and reason != ''">reason,</if>
<if test="startTime != null">start_time,</if>
<if test="endTime != null">end_time,</if>
<if test="day != null">day,</if>
<if test="instanceId != null">instance_id,</if>
<if test="nodeCode != null">node_code,</if>
<if test="nodeName != null">node_name,</if>
<if test="nodeType != null and nodeType != ''">node_type,</if>
<if test="flowStatus != null and flowStatus != ''">flow_status,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="delFlag != null">del_flag,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="type != null">#{type},</if>
<if test="reason != null and reason != ''">#{reason},</if>
<if test="startTime != null">#{startTime},</if>
<if test="endTime != null">#{endTime},</if>
<if test="day != null">#{day},</if>
<if test="instanceId != null">#{instanceId},</if>
<if test="nodeCode != null">#{nodeCode},</if>
<if test="nodeName != null">#{nodeName},</if>
<if test="nodeType != null and nodeType != ''">#{nodeType},</if>
<if test="flowStatus != null and flowStatus != ''">#{flowStatus},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="delFlag != null">#{delFlag},</if>
</trim>
</insert>
<update id="updateTestLeave" parameterType="TestLeave">
update test_leave
<trim prefix="SET" suffixOverrides=",">
<if test="type != null">type = #{type},</if>
<if test="reason != null and reason != ''">reason = #{reason},</if>
<if test="startTime != null">start_time = #{startTime},</if>
<if test="endTime != null">end_time = #{endTime},</if>
<if test="day != null">day = #{day},</if>
<if test="instanceId != null">instance_id = #{instanceId},</if>
<if test="nodeCode != null">node_code = #{nodeCode},</if>
<if test="nodeName != null">node_name = #{nodeName},</if>
<if test="nodeType != null and nodeType != ''">node_type = #{nodeType},</if>
<if test="flowStatus != null and flowStatus != ''">flow_status = #{flowStatus},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteTestLeaveById" parameterType="String">
delete from test_leave where id = #{id}
</delete>
<delete id="deleteTestLeaveByIds" parameterType="String">
delete from test_leave where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>