package org.jeecg.modules.dncFlow.service.impl;
|
|
import cn.hutool.core.util.StrUtil;
|
import com.alibaba.fastjson.JSON;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import org.apache.commons.beanutils.BeanUtils;
|
import org.apache.shiro.SecurityUtils;
|
import org.flowable.common.engine.api.FlowableException;
|
import org.flowable.engine.TaskService;
|
import org.flowable.identitylink.api.IdentityLink;
|
import org.flowable.task.api.Task;
|
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.system.vo.LoginUser;
|
import org.jeecg.modules.dnc.entity.DocInfo;
|
import org.jeecg.modules.dnc.entity.PermissionStreamNew;
|
import org.jeecg.modules.dnc.exception.ExceptionCast;
|
import org.jeecg.modules.dnc.mapper.DocInfoMapper;
|
import org.jeecg.modules.dnc.request.DocInfoQueryRequest;
|
import org.jeecg.modules.dnc.response.ActivitiCode;
|
import org.jeecg.modules.dnc.response.CommonCode;
|
import org.jeecg.modules.dnc.response.UcenterCode;
|
import org.jeecg.modules.dnc.service.IDocInfoService;
|
import org.jeecg.modules.dnc.utils.ValidateUtil;
|
import org.jeecg.modules.dncFlow.entity.DispatchFile;
|
import org.jeecg.modules.dncFlow.mapper.DispatchFileMapper;
|
import org.jeecg.modules.dncFlow.service.IDispatchFileService;
|
import org.jeecg.modules.dncFlow.vo.DispatchFileFlowTaskVo;
|
import org.jeecg.modules.flowable.apithird.business.entity.FlowMyBusiness;
|
import org.jeecg.modules.flowable.apithird.business.service.IFlowMyBusinessService;
|
import org.jeecg.modules.flowable.apithird.service.FlowCallBackServiceI;
|
import org.jeecg.modules.flowable.apithird.service.FlowCommonService;
|
import org.jeecg.modules.flowable.domain.vo.FlowHistoricalVo;
|
import org.jeecg.modules.flowable.service.IFlowDefinitionService;
|
import org.jeecg.modules.flowable.service.IFlowTaskService;
|
import org.jeecg.modules.flowable.service.IHisWorkTaskService;
|
import org.jeecg.modules.system.service.ISysUserRoleService;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.context.annotation.Lazy;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import javax.annotation.Resource;
|
import java.lang.reflect.InvocationTargetException;
|
import java.util.*;
|
|
/**
|
* @Description: nc程序与电子图版签派
|
* @Author: jeecg-boot
|
* @Date: 2025-03-19
|
* @Version: V1.0
|
*/
|
@Service("IDispatchFileService")
|
public class DispatchFileServiceImpl extends ServiceImpl<DispatchFileMapper, DispatchFile> implements IDispatchFileService, FlowCallBackServiceI {
|
|
@Autowired
|
@Lazy
|
private IDocInfoService docInfoService;
|
@Resource
|
private FlowCommonService flowCommonService;
|
@Resource
|
private IFlowDefinitionService flowDefinitionService;
|
@Autowired
|
private IFlowTaskService flowTaskService;
|
@Autowired
|
private TaskService taskService;
|
@Autowired
|
private IFlowMyBusinessService flowMyBusinessService;
|
@Autowired
|
private DocInfoMapper docInfoMapper;
|
@Autowired
|
private ISysUserRoleService sysUserRoleService;
|
@Autowired
|
private PermissionService permissionService;
|
@Autowired
|
private IHisWorkTaskService hisWorkTaskService;
|
/**
|
* 流程启动,保存对应的数据
|
* @param dispatchFile
|
* @return
|
*/
|
@Override
|
@Transactional(rollbackFor = {Exception.class})
|
public Result<?> saveDispatchFile(DispatchFile dispatchFile){
|
//校验参数
|
checkParam(dispatchFile);
|
//获取文件信息
|
DocInfo docInfo = docInfoService.getById(dispatchFile.getDocId());
|
PermissionStreamNew permissionStreams = getPermissionStreams(dispatchFile);
|
if (permissionStreams==null){
|
return Result.error("用户没有权限");
|
}
|
dispatchFile.setAttributionType(dispatchFile.getAttributionType());
|
dispatchFile.setAttributionId(dispatchFile.getAttributionId());
|
dispatchFile.setDocClassCode(dispatchFile.getDocClassCode());
|
super.save(dispatchFile);
|
System.out.println("NC程序和电子样板审签流程:" + dispatchFile.getDocId());
|
flowCommonService.initActBusiness(docInfo.getDocName()+"."+docInfo.getDocSuffix()+"文件进行审签",
|
dispatchFile.getId(), "IDispatchFileService", "nc_dispatch_file", null);
|
Map<String, Object> variables = new HashMap<>();
|
variables.put("dataId", dispatchFile.getId());
|
variables.put("organization", "导入文档默认启动流程");
|
variables.put("comment", "导入文档默认启动流程");
|
variables.put("proofreading",true);
|
Result result= flowDefinitionService.startProcessInstanceByKey("nc_dispatch_file", variables);
|
if (!result.isSuccess()) {
|
super.removeById(dispatchFile.getId());
|
}else {
|
docInfo.setDocDispatchStatus(1);
|
docInfoService.updateById(docInfo);
|
}
|
return result;
|
}
|
|
/**
|
* 文件查询审签流程
|
* @param attributionId,attributionType,docId
|
* @return
|
*/
|
@Override
|
public Result<?> queryDispatchDocFile(String attributionId, String attributionType, String docId){
|
DispatchFile dispatchFile=super.getOne(new LambdaQueryWrapper<DispatchFile>()
|
.eq(DispatchFile::getAttributionId, attributionId).eq(DispatchFile::getAttributionType, attributionType)
|
.eq(DispatchFile::getDocId, docId));
|
if (dispatchFile==null){
|
return Result.error("未找到对应审签文件");
|
}else {
|
FlowMyBusiness flowMyBusiness=flowMyBusinessService.selectByDataId(dispatchFile.getId());
|
if (flowMyBusiness==null){
|
return Result.error("未找到对应审签流程");
|
}else {
|
List<FlowHistoricalVo> queryHisTaskByProcInstId=hisWorkTaskService.queryHisTaskByProcInstId(flowMyBusiness.getProcessInstanceId());
|
return Result.ok(queryHisTaskByProcInstId);
|
}
|
}
|
}
|
|
/**
|
* 重新启动
|
* @param dispatchFileFlowTaskVo
|
*/
|
@Override
|
@Transactional(rollbackFor = {Exception.class})
|
public Result<?> reStartDispatchFile(DispatchFileFlowTaskVo dispatchFileFlowTaskVo) {
|
try {
|
// 1. 获取当前用户并校验登录状态
|
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
if (user == null) {
|
return Result.error("用户未登录");
|
}
|
|
// 2. 查询流程业务记录(处理空结果)
|
List<FlowMyBusiness> businessList = flowMyBusinessService.list(
|
new QueryWrapper<FlowMyBusiness>()
|
.eq("process_instance_id", dispatchFileFlowTaskVo.getInstanceId())
|
);
|
if (businessList.isEmpty()) {
|
return Result.error("流程记录不存在");
|
}
|
FlowMyBusiness flowMyBusiness = businessList.get(0);
|
|
// 3. 校验用户是否为候选处理人
|
List<String> todoUsers = JSON.parseArray(flowMyBusiness.getTodoUsers(), String.class);
|
if (todoUsers == null || !todoUsers.contains(user.getUsername())) {
|
return Result.error("用户无权操作此任务");
|
}
|
|
// 4. 认领任务(处理已被认领的情况)
|
String taskId = flowMyBusiness.getTaskId();
|
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
if (task == null) {
|
return Result.error("任务不存在或已完成");
|
}
|
if (task.getAssignee() != null && !task.getAssignee().equals(user.getUsername())) {
|
return Result.error("任务已被他人认领");
|
}
|
taskService.claim(taskId, user.getUsername());
|
|
// 5. 完成任务并传递变量
|
Map<String, Object> variables = new HashMap<>();
|
variables.put("dataId", flowMyBusiness.getDataId());
|
variables.put("organization", dispatchFileFlowTaskVo.getComment());
|
variables.put("assignee", user.getUsername());
|
variables.put("comment", dispatchFileFlowTaskVo.getComment());
|
taskService.complete(taskId, variables);
|
|
// 6. 获取下一任务并更新业务记录
|
List<Task> nextTasks = taskService.createTaskQuery()
|
.processInstanceId(dispatchFileFlowTaskVo.getInstanceId())
|
.list();
|
if (!nextTasks.isEmpty()) {
|
Task nextTask = nextTasks.get(0); // 假设取第一个任务
|
flowMyBusiness.setTaskId(nextTask.getId());
|
flowMyBusiness.setTaskName(nextTask.getName());
|
|
// 动态获取下一节点候选人(示例)
|
List<String> nextTodoUsers = getNextTaskCandidates(nextTask.getId());
|
flowMyBusiness.setTodoUsers(JSON.toJSONString(nextTodoUsers));
|
} else {
|
// 流程已结束,清空任务信息
|
flowMyBusiness.setTaskId(null);
|
flowMyBusiness.setTaskName(null);
|
flowMyBusiness.setTodoUsers(null);
|
}
|
flowMyBusinessService.updateById(flowMyBusiness);
|
|
return Result.ok("流程重启成功");
|
} catch (FlowableException e) {
|
return Result.error("流程操作失败: " + e.getMessage());
|
} catch (Exception e) {
|
return Result.error("系统错误: " + e.getMessage());
|
}
|
}
|
|
// 辅助方法:获取下一任务的所有候选信息(处理人、候选用户、候选组)
|
private List<String> getNextTaskCandidates(String taskId) {
|
List<IdentityLink> links = taskService.getIdentityLinksForTask(taskId);
|
List<String> candidates = new ArrayList<>();
|
|
// 1. 获取直接处理人(assignee)
|
links.stream()
|
.filter(link -> "assignee".equals(link.getType()))
|
.map(IdentityLink::getUserId)
|
.filter(Objects::nonNull)
|
.forEach(candidates::add);
|
|
// 2. 获取候选用户和候选组
|
links.stream()
|
.filter(link -> "candidate".equals(link.getType()))
|
.forEach(link -> {
|
if (link.getUserId() != null) {
|
// 候选用户直接添加
|
candidates.add(link.getUserId());
|
} else if (link.getGroupId() != null) {
|
// 候选组转换为实际用户(示例逻辑,需根据业务实现)
|
List<String> groupUsers = convertGroupToUsers(link.getGroupId());
|
candidates.addAll(groupUsers);
|
}
|
});
|
|
return candidates;
|
}
|
|
// 示例方法:将候选组ID转换为用户列表(需自定义实现)
|
private List<String> convertGroupToUsers(String groupId) {
|
// 实际业务中调用服务接口获取组成员
|
return sysUserRoleService.getUserNameByRoleId(groupId);
|
}
|
|
|
/**
|
* 审批操作
|
* @param dispatchFileFlowTaskVo
|
* @return
|
*/
|
@Override
|
@Transactional
|
public Result<?> auditDispatchFile(DispatchFileFlowTaskVo dispatchFileFlowTaskVo) {
|
try {
|
// 参数校验
|
if (!ValidateUtil.validateString(dispatchFileFlowTaskVo.getTaskId()) || !ValidateUtil.validateString(dispatchFileFlowTaskVo.getDataId())) {
|
return Result.error(CommonCode.INVALID_PARAM.toString());
|
}
|
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
String userId = user.getId();
|
dispatchFileFlowTaskVo.setAssignee(user.getUsername());
|
if (!ValidateUtil.validateString(userId)) {
|
return Result.error(UcenterCode.UCENTER_ACCOUNT_NOT_EXIST.toString());
|
}
|
|
// 数据查询
|
DispatchFile dispatchFile = this.getById(dispatchFileFlowTaskVo.getDataId());
|
if (dispatchFile == null) {
|
return Result.error(CommonCode.INVALID_PARAM.toString());
|
}
|
DocInfo docInfo = docInfoService.getById(dispatchFile.getDocId());
|
if (docInfo == null) {
|
return Result.error(ActivitiCode.ACT_DOC_ERROR.toString());
|
}
|
|
// 2. 查询流程业务记录(处理空结果)
|
List<FlowMyBusiness> businessList = flowMyBusinessService.list(
|
new QueryWrapper<FlowMyBusiness>()
|
.eq("process_instance_id", dispatchFileFlowTaskVo.getInstanceId())
|
);
|
if (businessList.isEmpty()) {
|
return Result.error("流程记录不存在");
|
}
|
FlowMyBusiness flowMyBusiness = businessList.get(0);
|
|
// 3. 校验用户是否为候选处理人
|
List<String> todoUsers = JSON.parseArray(flowMyBusiness.getTodoUsers(), String.class);
|
if (todoUsers == null || !todoUsers.contains(user.getUsername())) {
|
return Result.error("用户无权操作此任务");
|
}
|
|
// 4. 认领任务(处理已被认领的情况)
|
String taskId = flowMyBusiness.getTaskId();
|
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
if (task == null) {
|
return Result.error("任务不存在或已完成");
|
}
|
if (task.getAssignee() != null && !task.getAssignee().equals(user.getUsername())) {
|
return Result.error("任务已被他人认领");
|
}
|
taskService.claim(taskId, user.getUsername());
|
|
// 设置流程变量
|
Map<String, Object> values = setProcessVariables(dispatchFile, userId, dispatchFileFlowTaskVo);
|
dispatchFileFlowTaskVo.setValues(values);
|
|
// 完成流程任务
|
Result result = flowTaskService.complete(dispatchFileFlowTaskVo);
|
if (result.isSuccess()) {
|
// 更新状态
|
updateStatus(dispatchFile, docInfo, dispatchFileFlowTaskVo);
|
docInfoService.updateById(docInfo);
|
this.updateById(dispatchFile);
|
} else {
|
return result;
|
}
|
|
return Result.OK("操作成功");
|
} catch (Exception e) {
|
return Result.error("操作失败:" + e.getMessage());
|
}
|
}
|
|
/**
|
* 批量审批操作
|
* @param dispatchFileFlowTaskVo
|
* @return
|
*/
|
@Override
|
@Transactional
|
public Result<?> auditBatchDispatchFile(DispatchFileFlowTaskVo dispatchFileFlowTaskVo) throws InvocationTargetException, IllegalAccessException {
|
if (dispatchFileFlowTaskVo.getTaskIds()==null || dispatchFileFlowTaskVo.getTaskIds().isEmpty()) {
|
return Result.error(CommonCode.INVALID_PARAM.toString());
|
}
|
if (dispatchFileFlowTaskVo.getTaskIds().contains(",")){
|
String[] taskIds = dispatchFileFlowTaskVo.getTaskIds().split(",");
|
for (String taskId : taskIds) {
|
FlowMyBusiness flowMyBusiness=flowMyBusinessService.getOne(new QueryWrapper<FlowMyBusiness>().eq("task_id",taskId));
|
DispatchFileFlowTaskVo dispatchFileFlowTaskVoNew=new DispatchFileFlowTaskVo();
|
BeanUtils.copyProperties(dispatchFileFlowTaskVoNew, dispatchFileFlowTaskVo);
|
dispatchFileFlowTaskVoNew.setTaskId(taskId);
|
dispatchFileFlowTaskVoNew.setDataId(flowMyBusiness.getDataId());
|
dispatchFileFlowTaskVoNew.setInstanceId(flowMyBusiness.getProcessInstanceId());
|
if (dispatchFileFlowTaskVo.getTargetKey().equals("task_prepare")){
|
reStartDispatchFile(dispatchFileFlowTaskVoNew);
|
}else {
|
auditDispatchFile(dispatchFileFlowTaskVoNew);
|
}
|
}
|
}
|
return Result.OK("操作成功");
|
}
|
|
/**
|
* 查询审签基本信息
|
* @param id
|
*/
|
public Result<?> queryDispatchFile(String id){
|
DispatchFile dispatchFile=this.getById(id);
|
if (dispatchFile==null){
|
return Result.error("审签基本信息不存在");
|
}
|
DocInfoQueryRequest docInfoQueryRequest=new DocInfoQueryRequest();
|
docInfoQueryRequest.setDocId(dispatchFile.getDocId());
|
docInfoQueryRequest.setAttributionId(dispatchFile.getAttributionId());
|
docInfoQueryRequest.setAttributionType(Integer.valueOf(dispatchFile.getAttributionType()));
|
docInfoQueryRequest.setDocClassCode(dispatchFile.getDocClassCode());
|
List<DocInfo> docInfoList = docInfoService.findList(docInfoQueryRequest);
|
return Result.OK(docInfoList);
|
}
|
/**
|
* 发起定型流程
|
*/
|
@Override
|
public Result<?> submitProccess(DispatchFile dispatchFile) {
|
checkParam(dispatchFile);
|
super.save(dispatchFile);
|
//获取文件信息
|
DocInfo docInfo = docInfoService.getById(dispatchFile.getDocId());
|
flowCommonService.initActBusiness(docInfo.getDocName()+"."+docInfo.getDocSuffix()+"文件进行定型",
|
dispatchFile.getId(), "IDispatchFileService", "process_rf27duhy", null);
|
Map<String, Object> variables = new HashMap<>();
|
variables.put("dataId", dispatchFile.getId());
|
variables.put("organization", "导入文档默认启动流程");
|
variables.put("comment", "导入文档默认启动流程");
|
variables.put("proofreading",true);
|
Result result= flowDefinitionService.startProcessInstanceByKey("process_rf27duhy", variables);
|
if (!result.isSuccess())
|
super.removeById(dispatchFile.getId());
|
return result;
|
}
|
|
private Map<String, Object> setProcessVariables(DispatchFile dispatchFile, String userId, DispatchFileFlowTaskVo dispatchFileFlowTaskVo) {
|
Map<String, Object> values = new HashMap<>();
|
values.put("dataId", dispatchFile.getId());
|
values.put("organization", dispatchFile.getOrganization());
|
values.put("assignee", userId);
|
values.put("comment", dispatchFileFlowTaskVo.getComment());
|
if (StrUtil.isNotBlank(dispatchFileFlowTaskVo.getProofreadStatus())) {
|
values.put("proofreadStatus", dispatchFileFlowTaskVo.getProofreadStatus());
|
}
|
if (dispatchFileFlowTaskVo.getRatify() != null) {
|
values.put("ratify", dispatchFileFlowTaskVo.getRatify());
|
}
|
if (dispatchFileFlowTaskVo.getCut() != null) {
|
values.put("cut", dispatchFileFlowTaskVo.getCut());
|
}
|
if (dispatchFileFlowTaskVo.getStereotype() != null) {
|
values.put("stereotype", dispatchFileFlowTaskVo.getStereotype());
|
}
|
return values;
|
}
|
|
private void updateStatus(DispatchFile dispatchFile, DocInfo docInfo, DispatchFileFlowTaskVo dispatchFileFlowTaskVo) {
|
if (StrUtil.isNotBlank(dispatchFileFlowTaskVo.getProofreadStatus())) {
|
switch (dispatchFileFlowTaskVo.getProofreadStatus()) {
|
case "1":
|
// 直接定型
|
dispatchFile.setCurrentNode("5");
|
docInfo.setDocDispatchStatus(5);
|
break;
|
case "2":
|
// 校对通过
|
dispatchFile.setCurrentNode("2");
|
docInfo.setDocDispatchStatus(2);
|
break;
|
default:
|
// 校对不通过
|
dispatchFile.setCurrentNode("1");
|
docInfo.setDocDispatchStatus(1);
|
break;
|
}
|
}
|
if (dispatchFileFlowTaskVo.getRatify() != null && dispatchFileFlowTaskVo.getRatify()) {
|
dispatchFile.setCurrentNode("3");
|
docInfo.setDocDispatchStatus(3);
|
}
|
if (dispatchFileFlowTaskVo.getCut() != null && dispatchFileFlowTaskVo.getCut()) {
|
dispatchFile.setCurrentNode("4");
|
docInfo.setDocDispatchStatus(4);
|
}
|
if (dispatchFileFlowTaskVo.getStereotype() != null && dispatchFileFlowTaskVo.getStereotype()) {
|
dispatchFile.setCurrentNode("5");
|
docInfo.setDocDispatchStatus(5);
|
}
|
}
|
|
//传参验证
|
public boolean checkParam(DispatchFile dispatchFile) {
|
if (dispatchFile == null) {
|
ExceptionCast.cast(CommonCode.INVALID_PARAM);
|
}
|
if (!ValidateUtil.validateString(dispatchFile.getAttributionId()) || !ValidateUtil.validateString(dispatchFile.getDocId())
|
|| !ValidateUtil.validateString(dispatchFile.getFileId()) || !ValidateUtil.validateString(dispatchFile.getAttributionType())) {
|
ExceptionCast.cast(CommonCode.INVALID_PARAM);
|
}
|
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
String userId = user.getId();
|
if (!ValidateUtil.validateString(userId)) {
|
ExceptionCast.cast(UcenterCode.UCENTER_ACCOUNT_NOT_EXIST);
|
}
|
return true;
|
}
|
|
private PermissionStreamNew getPermissionStreams(DispatchFile dispatchFile) {
|
PermissionStreamNew permissionStreamNew = permissionService.getPermissionStreams(dispatchFile);
|
if (permissionStreamNew == null) {
|
ExceptionCast.cast(ActivitiCode.ACT_NODE_DEPART_NONE);
|
}
|
return permissionStreamNew;
|
}
|
|
@Override
|
public void afterFlowHandle(FlowMyBusiness business) {
|
business.getTaskNameId();//接下来审批的节点
|
business.getValues();//前端传进来的参数
|
business.getActStatus();
|
}
|
|
@Override
|
public Object getBusinessDataById(String dataId) {
|
return this.getById(dataId);
|
}
|
|
@Override
|
public Map<String, Object> flowValuesOfTask(String taskNameId, Map<String, Object> values) {
|
return null;
|
}
|
|
@Override
|
public List<String> flowCandidateUsernamesOfTask(String taskNameId, Map<String, Object> values) {
|
//业务是否干预流程,业务干预,流程干预,指定人员进行处理
|
return null;
|
}
|
}
|