lyh
2025-04-01 4e2be858f4ccbb7490b59ed584fd1c829eb4d556
修改审签问题
已修改18个文件
339 ■■■■ 文件已修改
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/request/DocInfoQueryRequest.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DocInfoServiceImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/utils/TreeBuilder.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/controller/DispatchFileController.java 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/service/IDispatchFileService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/service/impl/DispatchFileServiceImpl.java 162 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/apithird/business/mapper/xml/FlowMyBusinessMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/domain/dto/FlowTaskDto.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/domain/vo/FlowHistoricalVo.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/domain/vo/WorkTaskDataVo.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/mapper/xml/HisWorkTaskMapper.xml 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/mapper/xml/WorkTaskVoMapper.xml 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowTaskServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/HisWorkTaskServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/WorkTaskServiceImplVo.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserRoleMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/service/ISysUserRoleService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserRoleServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/request/DocInfoQueryRequest.java
@@ -30,6 +30,8 @@
    private String order;
    @ApiModelProperty(value = "文档状态")
    private String docStatus;
    @ApiModelProperty(value = "审签状态")
    private String docDispatchStatus;
    @ApiModelProperty(value = "出库状态")
    private String pullStatus;
    @ApiModelProperty(value = "同步状态 1 未同步 2 已同步")
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/DocInfoServiceImpl.java
@@ -528,6 +528,13 @@
        }else {
            queryWrapper.eq(StrUtil.isNotEmpty(docQuery.getDocStatus()),"u.doc_status",docQuery.getDocStatus());
        }
        if (docQuery.getDocDispatchStatus() != null && docQuery.getDocDispatchStatus().contains(",")) {
            String[] docDispatchStatusArray = docQuery.getDocDispatchStatus().split(",");
            List<Integer> docDispatchStatusList = Arrays.stream(docDispatchStatusArray).map(Integer::parseInt).collect(Collectors.toList());
            queryWrapper.in("u.doc_dispatch_status",docDispatchStatusList);
        }else {
            queryWrapper.eq(StrUtil.isNotEmpty(docQuery.getDocDispatchStatus()),"u.doc_dispatch_status",docQuery.getDocDispatchStatus());
        }
        if (StrUtil.isNotEmpty(docQuery.getPullStatus())){
            if (("1").equals(docQuery.getPullStatus())){
                queryWrapper.isNull("o.doc_id");
@@ -754,6 +761,13 @@
        }else {
            queryWrapper.eq(StrUtil.isNotEmpty(docQuery.getDocStatus()),"u.doc_status",docQuery.getDocStatus());
        }
        if (docQuery.getDocDispatchStatus() != null && docQuery.getDocDispatchStatus().contains(",")) {
            String[] docDispatchStatusArray = docQuery.getDocDispatchStatus().split(",");
            List<Integer> docDispatchStatusList = Arrays.stream(docDispatchStatusArray).map(Integer::parseInt).collect(Collectors.toList());
            queryWrapper.in("u.doc_dispatch_status",docDispatchStatusList);
        }else {
            queryWrapper.eq(StrUtil.isNotEmpty(docQuery.getDocDispatchStatus()),"u.doc_dispatch_status",docQuery.getDocDispatchStatus());
        }
        if (StrUtil.isNotEmpty(docQuery.getPullStatus())){
            if (("1").equals(docQuery.getPullStatus())){
                queryWrapper.isNull("o.doc_id");
lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/utils/TreeBuilder.java
@@ -91,11 +91,11 @@
            });
        }
        // 6. 循环检测
        if (sorted.size() != nodes.size()) {
            handleSortingFailure(nodes, sorted, nodeMap);
            return Collections.emptyList();
        }
//        // 6. 循环检测
//        if (sorted.size() != nodes.size()) {
//            handleSortingFailure(nodes, sorted, nodeMap);
//            return Collections.emptyList();
//        }
        return sorted;
    }
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/controller/DispatchFileController.java
@@ -13,6 +13,8 @@
import org.jeecg.modules.dncFlow.entity.DispatchFile;
import org.jeecg.modules.dncFlow.service.IDispatchFileService;
import org.jeecg.modules.dncFlow.vo.DispatchFileFlowTaskVo;
import org.jeecg.modules.flowable.domain.dto.FlowTaskDto;
import org.jeecg.modules.flowable.service.IHisWorkTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
@@ -35,6 +37,8 @@
    @Autowired
    private IDispatchFileService dispatchFileService;
    @Autowired
    private IHisWorkTaskService hisWorkTaskService;
    /**
     * 分页列表查询
     *
@@ -59,14 +63,14 @@
     /**
      * 重新启动
      * @param id
      * @param dispatchFileFlowTaskVo
      * @return
      */
     @AutoLog(value = "nc程序与电子图版签派-重新启动")
     @ApiOperation(value="nc程序与电子图版签派-重新启动", notes="nc程序与电子图版签派-重新启动")
     @GetMapping(value = "/saveDispatchFile")
     public Result<?> saveDispatchFile(String id){
         return dispatchFileService.reStartDispatchFile(id);
     @PostMapping(value = "/saveDispatchFile")
     public Result<?> saveDispatchFile(@RequestBody DispatchFileFlowTaskVo dispatchFileFlowTaskVo){
         return dispatchFileService.reStartDispatchFile(dispatchFileFlowTaskVo);
     }
@@ -77,11 +81,18 @@
      */
     @AutoLog(value = "nc程序与电子图版签派-审批操作")
     @ApiOperation(value="nc程序与电子图版签派-审批操作", notes="nc程序与电子图版签派-审批操作")
     @GetMapping(value = "/approval")
     public Result<?> approval(DispatchFileFlowTaskVo dispatchFileFlowTaskVo){
     @PostMapping(value = "/approval")
     public Result<?> approval(@RequestBody DispatchFileFlowTaskVo dispatchFileFlowTaskVo){
         return dispatchFileService.auditDispatchFile(dispatchFileFlowTaskVo);
     }
     @ApiOperation(value = "获取工作流历史任务", response = FlowTaskDto.class)
     @GetMapping(value = "/queryHisTaskList")
     public Result<?> queryHisTaskList(@RequestParam(name = "procInstId") String procInstId) {
         return Result.OK(hisWorkTaskService.queryHisTaskByProcInstId(procInstId));
     }
    /**
     *   添加
     *
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/service/IDispatchFileService.java
@@ -22,9 +22,9 @@
    /**
     * 重新启动
     * @param id
     * @param dispatchFileFlowTaskVo
     */
    Result<?> reStartDispatchFile(String id);
    Result<?> reStartDispatchFile(DispatchFileFlowTaskVo dispatchFileFlowTaskVo);
    /**
     * 审批操作
lxzn-module-dnc/src/main/java/org/jeecg/modules/dncFlow/service/impl/DispatchFileServiceImpl.java
@@ -1,11 +1,14 @@
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.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
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.*;
@@ -27,15 +30,14 @@
import org.jeecg.modules.flowable.apithird.service.FlowCommonService;
import org.jeecg.modules.flowable.service.IFlowDefinitionService;
import org.jeecg.modules.flowable.service.IFlowTaskService;
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.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
 * @Description: nc程序与电子图版签派
@@ -69,6 +71,8 @@
    private IFlowMyBusinessService flowMyBusinessService;
    @Autowired
    private DocInfoMapper docInfoMapper;
    @Autowired
    private ISysUserRoleService sysUserRoleService;
    /**
     * 流程启动,保存对应的数据
     * @param dispatchFile
@@ -95,6 +99,7 @@
        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()) {
@@ -108,26 +113,116 @@
    /**
     * 重新启动
     * @param id
     * @param dispatchFileFlowTaskVo
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Result<?> reStartDispatchFile(String id){
        DispatchFile dispatchFile = this.getById(id);
    public Result<?> reStartDispatchFile(DispatchFileFlowTaskVo dispatchFileFlowTaskVo) {
        try {
            // 1. 获取当前用户并校验登录状态
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (!dispatchFile.getCreateBy().equals(user.getUsername())){
            return Result.error("您没有权限重新启动");
            if (user == null) {
                return Result.error("用户未登录");
        }
        FlowMyBusiness flowMyBusiness=flowMyBusinessService.list(new QueryWrapper<FlowMyBusiness>()
                .eq("data_id",dispatchFile.getId())).get(0);
        String processInstanceId = flowMyBusiness.getProcessInstanceId();
            // 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", dispatchFile.getId());
        variables.put("organization", "重新启动");
        String TaskId=taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult().getId();
        taskService.complete(TaskId, variables);
        return Result.ok("重新启动成功");
            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);
    }
    /**
     * 审批操作
@@ -157,6 +252,33 @@
            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);
@@ -203,7 +325,6 @@
        values.put("organization", dispatchFile.getOrganization());
        values.put("assignee", userId);
        values.put("comment", dispatchFileFlowTaskVo.getComment());
        if (StrUtil.isNotBlank(dispatchFileFlowTaskVo.getProofreadStatus())) {
            values.put("proofreadStatus", dispatchFileFlowTaskVo.getProofreadStatus());
        }
@@ -352,8 +473,7 @@
    @Override
    public List<String> flowCandidateUsernamesOfTask(String taskNameId, Map<String, Object> values) {
        String dataId = values.get("dataId").toString();
        FlowMyBusiness flowMyBusiness=flowMyBusinessService.list(new QueryWrapper<FlowMyBusiness>().eq("data_id",dataId)).get(0);
        return Lists.newArrayList(flowMyBusiness.getCreateBy());
        //业务是否干预流程,业务干预,流程干预,指定人员进行处理
        return null;
    }
}
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/apithird/business/mapper/xml/FlowMyBusinessMapper.xml
@@ -8,6 +8,10 @@
        flow_my_business.proposer,
        flow_my_business.task_name,
        flow_my_business.task_id,
        flow_my_business.data_id AS 'dataId',
        flow_my_business.process_definition_key,
        flow_my_business.process_definition_id,
        flow_my_business.process_instance_id,
        ACT_RU_TASK.ASSIGNEE_ as todoUsers,
        flow_my_business.done_Users,
        ACT_HI_PROCINST.START_TIME_ AS start_time,
@@ -41,25 +45,27 @@
    </select>
    <select id="PageListMyBusiness" resultType="org.jeecg.modules.flowable.domain.dto.FlowTaskDto">
        SELECT
            task.ID_ as 'hisProcInsId',
            TASK.PROC_INST_ID_ AS 'taskId',
        task.ID_ AS 'taskId',
        TASK.PROC_INST_ID_ AS 'procInsId',
            ACT_RE_PROCDEF.CATEGORY_ AS 'category',
            ACT_RE_PROCDEF.NAME_ 'procDefName',
            flow_my_business.title AS 'Description',
            flow_my_business.data_id AS 'dataId',
            flow_my_business.process_definition_key AS 'processDefinitionKey',
            flow_my_business.process_definition_id AS 'processDefinitionId',
            flow_my_business.process_instance_id AS 'processInstanceId',
        ACT_HI_PROCINST.START_TIME_ AS createTime,
        ACT_RU_TASK.ASSIGNEE_ as todoUsers,
        task.END_TIME_ AS 'finishTime',
            TASK.EXECUTION_ID_ AS 'executionId',
            task.NAME_ AS 'taskName',
            task.DURATION_ 'duration',
            task.START_TIME_ AS 'createTime',
            task.END_TIME_ AS 'finishTime',
            task.TASK_DEF_KEY_ AS 'TaskDefKey'
        FROM
            ACT_HI_TASKINST TASK
                LEFT JOIN flow_my_business ON flow_my_business.process_instance_id = TASK.PROC_INST_ID_
                LEFT JOIN ACT_RE_PROCDEF ON flow_my_business.process_definition_id = ACT_RE_PROCDEF.ID_
        LEFT JOIN ACT_HI_PROCINST ON TASK.PROC_INST_ID_ = ACT_HI_PROCINST.ID_
        left join ACT_RU_TASK on flow_my_business.task_id = ACT_RU_TASK.ID_
        WHERE
           TASK.END_TIME_ IS NOT NULL
        <if test="flowMyBusinessDto.currentUser != null and flowMyBusinessDto.currentUser != ''">
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/domain/dto/FlowTaskDto.java
@@ -113,5 +113,9 @@
    @Excel(name = "流程业务实例id 一个流程业务唯一,本表中也唯一", width = 15)
    @ApiModelProperty(value = "流程业务实例id 一个流程业务唯一,本表中也唯一")
    private String processInstanceId;
    /**当前的节点可以处理的用户名,为username的集合json字符串*/
    @Excel(name = "当前的节点可以处理的用户名", width = 15)
    @ApiModelProperty(value = "当前的节点可以处理的用户名")
    @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname")
    private String todoUsers;
}
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/domain/vo/FlowHistoricalVo.java
@@ -3,6 +3,7 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@@ -61,6 +62,7 @@
    /**
     * 处理人
     */
    @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname")
    private String assignee;
    /**
     * 任务耗时
@@ -70,4 +72,8 @@
     * 任务描述
     */
    private String description;
    /**
     * 处理结果
     */
    private String sequenceFlowName;
}
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/domain/vo/WorkTaskDataVo.java
@@ -67,6 +67,9 @@
    private String dataId;
    @ApiModelProperty(value = "前驱节点")
    private String preNode;
    @ApiModelProperty(value = "前驱节点处理人")
    @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname")
    private String preNodeAssignee;
    @ApiModelProperty(value = "流程名称")
    private transient String flowName;
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/mapper/xml/HisWorkTaskMapper.xml
@@ -24,34 +24,52 @@
            aht.START_TIME_ ASC
    </select>
    <select id="queryHisTaskByProcInstId" resultType="org.jeecg.modules.flowable.domain.vo.FlowHistoricalVo">
        WITH ActivitySequence AS (
        SELECT
            p.PROC_INST_ID_ AS procInstId,
            p.BUSINESS_KEY_ AS businessKey,
            p.START_TIME_ AS startTime,
            p.END_TIME_ AS endTime,
            a.ACT_NAME_ AS actName,
                p.START_TIME_ AS procStartTime,
                p.END_TIME_ AS procEndTime,
                a.ACT_ID_,
                COALESCE ( a.ACT_NAME_, a.ACT_ID_ ) AS actName,
            a.ACT_TYPE_ AS actType,
            a.START_TIME_ AS actStartTime,
            a.END_TIME_ AS actEndTime,
            c.NAME_ AS taskName,
            c.ASSIGNEE_ AS assignee,
            CASE
                WHEN c.DURATION_ IS NOT NULL THEN
                    CASE
                        WHEN FLOOR(c.DURATION_ / 1000.0) = 0 THEN NULL
                        ELSE FLOOR(c.DURATION_ / 1000.0)
                        END
                ELSE NULL
                END AS duration,
            c.DESCRIPTION_ AS description
                c.DESCRIPTION_ AS description,
-- 使用 LEAD 获取下一个活动信息
                LEAD ( COALESCE ( a.ACT_NAME_, a.ACT_ID_ ) ) OVER ( PARTITION BY p.PROC_INST_ID_ ORDER BY a.START_TIME_ ) AS nextActName,
                LEAD ( a.ACT_TYPE_ ) OVER ( PARTITION BY p.PROC_INST_ID_ ORDER BY a.START_TIME_ ) AS nextActType,
                LEAD ( a.START_TIME_ ) OVER ( PARTITION BY p.PROC_INST_ID_ ORDER BY a.START_TIME_ ) AS nextActStartTime
        FROM
            act_hi_procinst p
                LEFT JOIN act_hi_actinst a ON p.PROC_INST_ID_ = a.PROC_INST_ID_
                    AND a.ACT_TYPE_ IN ( 'userTask', 'sequenceFlow' )
                LEFT JOIN ACT_HI_TASKINST c ON a.TASK_ID_ = c.ID_
        WHERE
            p.PROC_INST_ID_ = #{procInstId}
          AND a.ACT_NAME_ IS NOT NULL
        ) SELECT
              procInstId,
              businessKey,
-- 当前活动(userTask)信息
              actName AS userTaskName,
              taskName,
              assignee,
              actStartTime,
              actEndTime,
              description,
-- 下一个活动(sequenceFlow)信息
              nextActName AS sequenceFlowName,
              nextActStartTime AS sequenceFlowStartTime
        FROM
            ActivitySequence
        WHERE
            actType = 'userTask' -- 筛选当前活动为 userTask
          AND nextActType = 'sequenceFlow' -- 且下一个活动为 sequenceFlow
        ORDER BY
            COALESCE(a.END_TIME_, '9999-12-31') ASC;
            actStartTime;
    </select>
</mapper>
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/mapper/xml/WorkTaskVoMapper.xml
@@ -13,6 +13,7 @@
            atask.priority_ AS priority,
            atask.create_time_ AS createTime,
            atask.suspension_state_ AS suspensionState,
            atask.ASSIGNEE_ as assignee,
            fmb.act_status AS actStatus,
            fmb.title AS title,
            fmb.data_id AS dataId,
@@ -26,7 +27,9 @@
            LEFT JOIN flow_my_business fmb on atask.id_ = fmb.task_id
            LEFT JOIN ACT_RE_PROCDEF pro on atask.PROC_DEF_ID_ = pro.id_
        WHERE
            atask.assignee_ = #{flowMy.username}
            (atask.assignee_ = #{flowMy.username}
                OR ( atask.assignee_ IS NULL AND fmb.todo_users LIKE CONCAT('%',#{flowMy.username},'%'))
                )
          <if test="flowMy.flowName!= null and flowMy.flowName!= ''">
              AND pro.name_ LIKE CONCAT('%',#{flowMy.flowName},'%')
          </if>
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowTaskServiceImpl.java
@@ -994,16 +994,15 @@
            flowTaskDto.setCategory(pd.getCategory());
            // 流程发起人信息
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(flowTaskDto.getTaskId())
                    .processInstanceId(flowTaskDto.getProcInsId())
                    .singleResult();
            SysUser startUser = iFlowThirdService.getUserByUsername(historicProcessInstance.getStartUserId());
            flowTaskDto.setStartUserId(startUser.getUsername());
            flowTaskDto.setStartUserName(startUser.getRealname());
            List<String> departNamesByUsername = iFlowThirdService.getDepartNamesByUsername(historicProcessInstance.getStartUserId());
            flowTaskDto.setStartDeptName(CollUtil.join(departNamesByUsername,","));
            flowTaskDto.setTaskId(flowTaskDto.getHisProcInsId());
        });
        return Result.OK(page);
        return Result.OK(flowTaskDtoIPage);
    }
    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/HisWorkTaskServiceImpl.java
@@ -1,19 +1,22 @@
package org.jeecg.modules.flowable.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.ibatis.annotations.Param;
import org.flowable.engine.HistoryService;
import org.jeecg.modules.flowable.domain.vo.FlowHistoricalVo;
import org.jeecg.modules.flowable.domain.vo.HisWorkTask;
import org.jeecg.modules.flowable.mapper.IHisWorkTaskMapper;
import org.jeecg.modules.flowable.service.IHisWorkTaskService;
import org.jeecg.modules.flowable.util.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class HisWorkTaskServiceImpl extends ServiceImpl<IHisWorkTaskMapper,HisWorkTask> implements IHisWorkTaskService {
    @Autowired
    private HistoryService historyService;
    @Override
    public List<HisWorkTask> queryHisTaskList(String drapprovedataId) {
        return baseMapper.queryHisTaskList(drapprovedataId);
@@ -30,8 +33,8 @@
        List<FlowHistoricalVo> flowHistoricalVoList=baseMapper.queryHisTaskByProcInstId(procInstId);
        flowHistoricalVoList.forEach(flowHistoricalVo->{
            //计算时间
            if (StrUtil.isNotEmpty(flowHistoricalVo.getDuration())){
                flowHistoricalVo.setDuration(TimeUtil.howLongByMillis(Long.parseLong(flowHistoricalVo.getDuration()),2));
            if (flowHistoricalVo.getActStartTime()!=null && flowHistoricalVo.getActEndTime()!=null){
                flowHistoricalVo.setDuration(TimeUtil.howLong(flowHistoricalVo.getActStartTime(),flowHistoricalVo.getActEndTime(),2));
            }
        });
        return flowHistoricalVoList;
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/WorkTaskServiceImplVo.java
@@ -1,5 +1,6 @@
package org.jeecg.modules.flowable.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -23,7 +24,10 @@
            HistoricActivityInstance historicActivityInstance=flowMyBusinessService.getPreviousNode(workTaskDataVo.getId());
            if (historicActivityInstance != null){
                workTaskDataVo.setPreNode(historicActivityInstance.getActivityName());
                workTaskDataVo.setAssignee(historicActivityInstance.getAssignee());
                workTaskDataVo.setPreNodeAssignee(historicActivityInstance.getAssignee());
            }
            if (StrUtil.isEmpty(workTaskDataVo.getAssignee())){
                workTaskDataVo.setAssignee(flowMy.getUsername());
            }
        });
        return workTaskDataVoIPage;
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserRoleMapper.java
@@ -41,4 +41,11 @@
    List<SysUser> getUsersByRoles(@Param("roleList") List<String> roleList);
    /**
     * 通过角色id获取用户username
     * @param roleId
     */
    @Select("select username from sys_user where id in (select user_id from sys_user_role where role_id = #{roleId})")
    List<String> getUserNameByRoleId(@Param("roleId") String roleId);
}
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/service/ISysUserRoleService.java
@@ -22,4 +22,10 @@
     * */
    List<SysUser> queryUsersByRoles(List<String> roleList);
    /**
     * 通过角色id获取用户username
     * @param roleId
     */
    List<String> getUserNameByRoleId(String roleId);
}
lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserRoleServiceImpl.java
@@ -33,4 +33,13 @@
        return sysUserRoleMapper.getUsersByRoles(roleList);
    }
    /**
     * 通过角色id获取用户username
     * @param roleId
     */
    @Override
    public List<String> getUserNameByRoleId(String roleId){
        return sysUserRoleMapper.getUserNameByRoleId(roleId);
    }
}