包头待办bug修改

This commit is contained in:
guoshengxiong 2025-02-10 17:26:56 +08:00
parent b38dc8dcc8
commit e604c2f435
10 changed files with 270 additions and 80 deletions

View File

@ -0,0 +1,39 @@
package com.wflow.bean.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WflowCcmeRead implements Serializable {
private static final long serialVersionUID = 685445053985109974L;
@TableId(type = IdType.AUTO)
private Integer readId;
/**
* 实例ID
*/
private String instanceId;
/**
* 节点ID
*/
private String nodeId;
/**
* 用户id
*/
private Long userId;
/**
* 创建时间
*/
private Date created;
}

View File

@ -0,0 +1,19 @@
package com.wflow.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wflow.bean.entity.WflowCcmeRead;
import com.wflow.bean.entity.WflowRoles;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author : willian fu
* @date : 2022/6/27
*/
@Mapper
public interface WflowCcmeReadMapper extends BaseMapper<WflowCcmeRead> {
}

View File

@ -55,4 +55,9 @@ public class ProcessInstanceVo {
//流程实例创建时间
private Date startTime;
private Date finishTime;
//是否抄送我的
private Boolean isCCme;
//是否审批驳回
private Boolean isRefuse;
}

View File

@ -1,6 +1,7 @@
package com.wflow.workflow.bean.vo;
import com.wflow.workflow.bean.process.OrgUser;
import com.wflow.workflow.bean.process.enums.ProcessResultEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -63,5 +64,16 @@ public class ProcessTaskVo {
private Date taskCreateTime;
//task完成时间
private Date taskEndTime;
//是否抄送我的
private Boolean isCCme;
//是否已读抄送我的1已读0未读
private Integer cCmeRead;
//是否审批驳回
private Boolean isRefuse;
//流程状态
private String status;
//流程结果
private ProcessResultEnum result;
//模型表单定义ID
private String formId;
}

View File

@ -1,5 +1,6 @@
package com.wflow.workflow.controller;
import cn.hutool.core.map.MapUtil;
import com.wflow.utils.R;
import com.wflow.utils.UserUtil;
import com.wflow.workflow.bean.vo.ProcessStartParamsVo;
@ -8,6 +9,8 @@ import com.zhgd.annotation.OperLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
/**
* @author : willian fu
* @date : 2022/8/24
@ -56,11 +59,12 @@ public class ProcessInstanceController {
/**
* 获取系统待我处理的流程
* @param pageSize 每页数量
* @param pageNo 页码
* @param code 表单流程ID流程定义KEY
* @param finished 流程是否已经结束
* @param customStatus 1待催办2已办结只有PASS3审批进行中4审批被撤销5审批被驳回
*
* @param pageSize 每页数量
* @param pageNo 页码
* @param code 表单流程ID流程定义KEY
* @param finished 流程是否已经结束
* @param customStatus 1待催办2已办结3审批进行中4审批被撤销5审批被驳回
* @return 列表数据
*/
@OperLog(operModul = "审批管理",operType = "获取系统待我处理的流程",operDesc = "获取系统待我处理的流程")
@ -137,14 +141,23 @@ public class ProcessInstanceController {
/**
* 删除流程实例
*
* @param instanceId 实例ID
* @return 操作结果
*/
@OperLog(operModul = "审批管理",operType = "删除流程实例",operDesc = "删除流程实例")
@OperLog(operModul = "审批管理", operType = "删除流程实例", operDesc = "删除流程实例")
@DeleteMapping("instance/{instanceId}")
public Object delProcessInstance(@PathVariable String instanceId) {
processService.delProcessInstance(instanceId);
return R.ok("删除流程实例成功");
}
@OperLog(operModul = "审批管理", operType = "已读抄送我的", operDesc = "已读抄送我的")
@PostMapping("read/ccMe")
public Object readCCme(@RequestBody HashMap<String, Object> param) {
String instanceId = param.get("instanceId").toString();
String nodeId = param.get("nodeId").toString();
processService.readCCme(instanceId, nodeId);
return R.ok("成功");
}
}

View File

@ -38,6 +38,25 @@ public class ProcessInstanceTaskController {
return R.ok(taskService.getUserTodoList(pageSize, pageNo, code, startTimes, startUser, key));
}
/**
* 包头查询用户待办
*
* @param pageSize 每页条数
* @param pageNo 页码
* @param code 流程定义key模型ID
* @return 分页列表数据
*/
@OperLog(operModul = "审批管理", operType = "查询用户待办待处理的任务", operDesc = "查询用户待办待处理的任务")
@GetMapping("todoListBaotou")
public Object todoListBaotou(@RequestParam(defaultValue = "20") Integer pageSize,
@RequestParam(defaultValue = "1") Integer pageNo,
@RequestParam(required = false) String code,
@RequestParam(required = false) String[] startTimes,
@RequestParam(required = false) String startUser,
@RequestParam(required = false) String key) {
return R.ok(taskService.todoListBaotou(pageSize, pageNo, code, startTimes, startUser, key));
}
/**
* 查询用户已审批的流程实例
*
@ -46,7 +65,7 @@ public class ProcessInstanceTaskController {
* @param code 流程定义key模型ID
* @return 分页列表数据
*/
@OperLog(operModul = "审批管理",operType = "查询用户已审批的流程实例",operDesc = "查询用户已审批的流程实例")
@OperLog(operModul = "审批管理", operType = "查询用户已审批的流程实例", operDesc = "查询用户已审批的流程实例")
@GetMapping("idoList")
public Object getUserIdoList(@RequestParam(defaultValue = "20") Integer pageSize,
@RequestParam(defaultValue = "1") Integer pageNo,

View File

@ -30,4 +30,6 @@ public interface ProcessInstanceService {
String startUser, Boolean finished, String key);
InstanceCountVo getProcessInstanceCount();
void readCCme(String instanceId, String nodeId);
}

View File

@ -78,4 +78,5 @@ public interface ProcessTaskService {
*/
NodeSettingsVo getNodeTaskSettings(String taskId);
Page<ProcessTaskVo> todoListBaotou(Integer pageSize, Integer pageNo, String code, String[] startTimes, String startUser, String key);
}

View File

@ -1,4 +1,5 @@
package com.wflow.workflow.service.impl;
import java.util.Date;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
@ -10,16 +11,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wflow.bean.do_.DeptDo;
import com.wflow.bean.do_.UserDo;
import com.wflow.bean.entity.WflowCcTasks;
import com.wflow.bean.entity.WflowModelHistorys;
import com.wflow.bean.entity.WflowModels;
import com.wflow.bean.entity.WflowSubProcess;
import com.wflow.bean.entity.*;
import com.wflow.bean.vo.UserVo;
import com.wflow.exception.BusinessException;
import com.wflow.mapper.WflowCcTasksMapper;
import com.wflow.mapper.WflowModelHistorysMapper;
import com.wflow.mapper.WflowModelsMapper;
import com.wflow.mapper.WflowSubProcessMapper;
import com.wflow.mapper.*;
import com.wflow.service.OrgRepositoryService;
import com.wflow.utils.UserUtil;
import com.wflow.workflow.bean.dto.ProcessInstanceOwnerDto;
@ -37,6 +32,8 @@ import com.wflow.workflow.bean.vo.*;
import com.wflow.workflow.config.WflowGlobalVarDef;
import com.wflow.workflow.service.*;
import com.wflow.workflow.utils.Executor;
import com.zhgd.xmgl.security.SecurityUtil;
import com.zhgd.xmgl.security.util.SecurityUtils;
import com.zhgd.xmgl.tenant.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@ -68,6 +65,9 @@ import java.util.stream.Collectors;
@Service
public class ProcessInstanceServiceImpl implements ProcessInstanceService {
@Autowired
private WflowCcmeReadMapper ccmeReadMapper;
@Autowired
private OrgRepositoryService orgRepositoryService;
@ -428,14 +428,20 @@ public class ProcessInstanceServiceImpl implements ProcessInstanceService {
@Override
public Page<ProcessInstanceVo> getUserSubmittedList(Integer pageSize, Integer pageNo, String startUser, String code,
Boolean finished, String[] startTimes, String keyword, String fieldId, String fieldVal, String key, Integer customStatus) {
Long userId = SecurityUtils.getUser().getUserId();
HistoricProcessInstanceQuery instanceQuery = historyService.createHistoricProcessInstanceQuery();
//TODO 多租户
instanceQuery.processInstanceTenantId(TenantContextHolder.getTenantId());
//(x=1 or x=2) and
if (Objects.equals(customStatus, 1)) {
instanceQuery.or().startedBy(userId + "").involvedUser(userId + "").endOr();
} else if (Objects.equals(customStatus, 2)) {
instanceQuery.or().processInstanceBusinessStatus(ProcessStatus.PASS.toString()).processInstanceBusinessStatus(ProcessStatus.PRE_CANCEL.toString()).endOr();
}
Executor.builder()
//customStatus 1待催办2已办结只有PASS3审批进行中4审批被撤销5审批被驳回
.ifNotBlankNext(Objects.equals(customStatus, 2) ? ProcessStatus.PASS.toString() : null, instanceQuery::processInstanceBusinessStatus)
//customStatus 1待催办2已办结3审批进行中4审批被撤销5审批被驳回
.ifTrueNext(Objects.equals(customStatus, 1), instanceQuery::unfinished)
.ifTrueNext(Objects.equals(customStatus, 3), instanceQuery::unfinished)
.ifNotBlankNext(Objects.equals(customStatus, 4) ? ProcessStatus.PRE_CANCEL.toString() : null, instanceQuery::processInstanceBusinessStatus)
.ifNotBlankNext(Objects.equals(customStatus, 5) ? ProcessStatus.PRE_REFUSE.toString() : null, instanceQuery::processInstanceBusinessStatus)
.ifNotBlankNext(startUser, instanceQuery::startedBy)
.ifNotBlankNext(code, instanceQuery::processDefinitionKey)
@ -454,9 +460,6 @@ public class ProcessInstanceServiceImpl implements ProcessInstanceService {
instanceQuery.variableValueLike(fieldId, "%" + fieldVal + "%");
}
});
if (Objects.equals(customStatus, 1)) {
instanceQuery.or().processInstanceBusinessStatusLike("PRE_%").unfinished().endOr();
}
List<HistoricProcessInstance> historicProcessInstances = new ArrayList<>();
if (StringUtils.isNotBlank(key)) {
historicProcessInstances = instanceQuery
@ -569,6 +572,19 @@ public class ProcessInstanceServiceImpl implements ProcessInstanceService {
return InstanceCountVo.builder().todo(todo).mySubmited(mySubmited).cc(cc.intValue()).build();
}
@Override
public void readCCme(String instanceId, String nodeId) {
Long userId = SecurityUtils.getUser().getUserId();
WflowCcmeRead read = ccmeReadMapper.selectOne(new LambdaQueryWrapper<WflowCcmeRead>().eq(WflowCcmeRead::getInstanceId, instanceId).eq(WflowCcmeRead::getNodeId, nodeId).eq(WflowCcmeRead::getUserId, userId));
if (read == null) {
read = new WflowCcmeRead();
read.setInstanceId(instanceId);
read.setNodeId(nodeId);
read.setUserId(userId);
ccmeReadMapper.insert(read);
}
}
/**
* 获取抄送的流程实例信息
*

View File

@ -2,6 +2,8 @@ package com.wflow.workflow.service.impl;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.date.DateUtil;
@ -13,9 +15,11 @@ import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wflow.bean.do_.UserDeptDo;
import com.wflow.bean.entity.WflowCcmeRead;
import com.wflow.bean.entity.WflowModelHistorys;
import com.wflow.bean.entity.WflowModels;
import com.wflow.exception.BusinessException;
import com.wflow.mapper.WflowCcmeReadMapper;
import com.wflow.mapper.WflowModelHistorysMapper;
import com.wflow.mapper.WflowModelsMapper;
import com.wflow.service.OrgRepositoryService;
@ -24,16 +28,15 @@ import com.wflow.workflow.UELTools;
import com.wflow.workflow.bean.dto.NotifyDto;
import com.wflow.workflow.bean.dto.ProcessInstanceOwnerDto;
import com.wflow.workflow.bean.process.OrgUser;
import com.wflow.workflow.bean.process.enums.ProcessResultEnum;
import com.wflow.workflow.bean.process.props.ApprovalProps;
import com.wflow.workflow.bean.process.props.CcProps;
import com.wflow.workflow.bean.vo.*;
import com.wflow.workflow.config.WflowGlobalVarDef;
import com.wflow.workflow.extension.cmd.RecallToHisApprovalNodeCmd;
import com.wflow.workflow.service.BusinessDataStorageService;
import com.wflow.workflow.service.NotifyService;
import com.wflow.workflow.service.ProcessTaskService;
import com.wflow.workflow.service.UserDeptOrLeaderService;
import com.wflow.workflow.service.*;
import com.wflow.workflow.utils.FlowableUtils;
import com.zhgd.xmgl.security.SecurityUtil;
import com.zhgd.xmgl.security.util.SecurityUtils;
import com.zhgd.xmgl.tenant.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
@ -60,7 +63,9 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@ -70,49 +75,11 @@ import java.util.stream.Collectors;
@Slf4j
@Service("processTaskService")
public class ProcessTaskServiceImpl implements ProcessTaskService {
@Lazy
@Autowired
private WflowModelHistorysMapper modelHistorysMapper;
@Autowired
private UELTools uelTools;
@Autowired
private TaskService taskService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private NotifyService notifyService;
@Autowired
private BusinessDataStorageService businessDataService;
@Autowired
private UserDeptOrLeaderService userDeptOrLeaderService;
@Autowired
private OrgRepositoryService orgRepositoryService;
@Autowired
private HistoryService historyService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ManagementService managementService;
@Autowired
private WflowModelHistorysMapper historysMapper;
@Autowired
private WflowModelsMapper wflowModelsMapper;
private WflowCcmeReadMapper ccmeReadMapper;
//超时缓存数据缓存20秒用来存储审批人防止flowable高频调用
private static final TimedCache<String, List<String>> taskCache = CacheUtil.newTimedCache(20000);
//用来存储正在处理的节点防止并发处理
private static final Set<String> HANDLER_NODE_LOCK = new ConcurrentHashSet<>();
@ -120,6 +87,37 @@ public class ProcessTaskServiceImpl implements ProcessTaskService {
taskCache.schedulePrune(10000);
}
@Lazy
@Autowired
private ProcessInstanceService processService;
@Lazy
@Autowired
private WflowModelHistorysMapper modelHistorysMapper;
@Autowired
private UELTools uelTools;
@Autowired
private TaskService taskService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private NotifyService notifyService;
@Autowired
private BusinessDataStorageService businessDataService;
@Autowired
private UserDeptOrLeaderService userDeptOrLeaderService;
@Autowired
private OrgRepositoryService orgRepositoryService;
@Autowired
private HistoryService historyService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ManagementService managementService;
@Autowired
private WflowModelHistorysMapper historysMapper;
@Autowired
private WflowModelsMapper wflowModelsMapper;
@Override
public Page<ProcessTaskVo> getUserTodoList(Integer pageSize, Integer pageNo, String code, String[] startTimes, String startUser, String key) {
String userId = UserUtil.getLoginUserId();
@ -275,17 +273,17 @@ public class ProcessTaskServiceImpl implements ProcessTaskService {
//批量获取所有任务的发起部门信息
Map<String, Object> startDept = FlowableUtils.getProcessVars(instanceMap.keySet(), "startDept");
List<ProcessTaskVo> taskVos = taskInstances.stream().map(task -> {
HistoricProcessInstance instance = instanceMap.get(task.getProcessInstanceId());
HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(instance.getId()).variableName("approve_" + task.getId()).singleResult();
if (StringUtils.isNotBlank(result)) {
System.out.println("11111" + variableInstance.getValue());
if (!variableInstance.getValue().toString().equals(result)) {
return null;
}
HistoricProcessInstance instance = instanceMap.get(task.getProcessInstanceId());
HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(instance.getId()).variableName("approve_" + task.getId()).singleResult();
if (StringUtils.isNotBlank(result)) {
System.out.println("11111" + variableInstance.getValue());
if (!variableInstance.getValue().toString().equals(result)) {
return null;
}
//构造用户id -> 部门id
staterUsers.add(instance.getStartUserId() + "_" + startDept.getOrDefault(instance.getId(),
}
//构造用户id -> 部门id
staterUsers.add(instance.getStartUserId() + "_" + startDept.getOrDefault(instance.getId(),
//如果没有就从流程变量 owner 里取之前是存owner变量
FlowableUtils.getOwnerDept(instance.getId(), false)));
return ProcessTaskVo.builder()
@ -353,6 +351,7 @@ public class ProcessTaskServiceImpl implements ProcessTaskService {
/**
* 获取表单id的现在时间
*
* @param instanceId
* @param fieldId
*/
@ -448,7 +447,7 @@ public class ProcessTaskServiceImpl implements ProcessTaskService {
if (ProcessHandlerParamsVo.Action.cancel.equals(params.getAction())) {
params.getComment().setText("撤销:" + params.getComment().getText());
}
if (!(isComment || putComment)){
if (!(isComment || putComment)) {
throw new BusinessException("任务不存在,请刷新数据");
}
taskService.addComment(params.getTaskId(), instanceId, JSONObject.toJSONString(params.getComment()));
@ -511,11 +510,11 @@ public class ProcessTaskServiceImpl implements ProcessTaskService {
//throw new BusinessException("暂不支持单独评论");
break;
}
}catch (Exception e) {
} catch (Exception e) {
log.error("处理任务异常", e);
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new BusinessException(e.getMessage());
}finally {
} finally {
//移除锁
HANDLER_NODE_LOCK.remove(lockKey);
}
@ -641,17 +640,82 @@ public class ProcessTaskServiceImpl implements ProcessTaskService {
return NodeSettingsVo.builder().enableSign(nodeProps instanceof ApprovalProps && ((ApprovalProps) nodeProps).isSign()).build();
}
@Override
public Page<ProcessTaskVo> todoListBaotou(Integer pageSize, Integer pageNo, String code, String[] startTimes, String startUser, String key) {
int firstSize = pageSize * pageNo;
Page<ProcessTaskVo> userTodoList = this.getUserTodoList(firstSize, 1, code, startTimes, startUser, key);
Page<ProcessInstanceVo> ccMeInstance = processService.getCcMeInstance(firstSize, 1, code, startTimes, startUser, null, key);
Page<ProcessInstanceVo> refuseListPage = processService.getUserSubmittedList(firstSize, 1, startUser, code, true, startTimes, null, null, null, key, 5);
ccMeInstance.getRecords().forEach(o -> o.setIsCCme(true));
refuseListPage.getRecords().forEach(o -> {
o.setIsRefuse(true);
});
List<ProcessInstanceVo> ccMeInstanceList = ccMeInstance.getRecords();
ccMeInstanceList.addAll(refuseListPage.getRecords());
List<ProcessTaskVo> ccMeList = ccMeInstanceList.stream().map(o -> {
ProcessTaskVo vo = new ProcessTaskVo();
BeanUtil.copyProperties(o, vo);
vo.setCreateTime(o.getStartTime());
if (vo.getOwner() == null) {
vo.setOwner(o.getStaterUser());
vo.setOwnerId(o.getStaterUserId());
}
return vo;
}).collect(Collectors.toList());
userTodoList.getRecords().forEach(o -> {
o.setStatus("审批进行中");
o.setResult(ProcessResultEnum.RUNNING);
});
List<ProcessTaskVo> allRecords = userTodoList.getRecords();
allRecords.addAll(ccMeList);
allRecords.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
Page<ProcessTaskVo> page = new Page<>();
page.setCurrent(pageNo);
page.setSize(pageSize);
page.setTotal(userTodoList.getTotal() + ccMeInstance.getTotal() + refuseListPage.getTotal());
int startIndex = (int) ((page.getCurrent() - 1) * page.getSize());
int toIndex = (int) (page.getCurrent() * page.getSize());
if (toIndex > page.getTotal()) {
toIndex = (int) page.getTotal();
}
List<ProcessTaskVo> records = allRecords.subList(startIndex, toIndex);
page.setRecords(records);
if (CollUtil.isNotEmpty(records)) {
List<String> instanceIds = records.stream().map(ProcessTaskVo::getInstanceId).collect(Collectors.toList());
Map<String, WflowCcmeRead> uniqueMap = ccmeReadMapper.selectList(new LambdaQueryWrapper<WflowCcmeRead>()
.in(WflowCcmeRead::getInstanceId, instanceIds).eq(WflowCcmeRead::getUserId, SecurityUtils.getUser().getUserId())).stream().collect(Collectors.toMap(o -> {
return o.getInstanceId() + o.getNodeId();
}, Function.identity(), (o1, o2) -> o1));
for (ProcessTaskVo vo : records) {
WflowCcmeRead read = uniqueMap.get(vo.getInstanceId() + vo.getNodeId());
if (read != null) {
vo.setCCmeRead(1);
} else {
vo.setCCmeRead(0);
}
if (vo.getIsCCme() == null) {
vo.setIsCCme(false);
}
if (vo.getIsRefuse() == null) {
vo.setIsRefuse(false);
}
}
}
return page;
}
/**
* 获取审批人
*
* @param props 节点熟悉
* @param props 节点熟悉
* @param tenantId
* @return 审批人ID列表
*/
public List<String> getApprovalUsers(String instanceId, String nodeId, ApprovalProps props, String tenantId) {
String userId = runtimeService.getVariable(instanceId, WflowGlobalVarDef.INITIATOR, String.class);
String deptId = runtimeService.getVariable(instanceId, WflowGlobalVarDef.START_DEPT, String.class);
deptId = StrUtil.isNotBlank(deptId) ? deptId : runtimeService.getVariable(instanceId, WflowGlobalVarDef.OWNER, ProcessInstanceOwnerDto.class).getOwnerDeptId();;
deptId = StrUtil.isNotBlank(deptId) ? deptId : runtimeService.getVariable(instanceId, WflowGlobalVarDef.OWNER, ProcessInstanceOwnerDto.class).getOwnerDeptId();
;
Set<String> userSet = new LinkedHashSet<>();
switch (props.getAssignedType()) {
case REFUSE: