Flowable7.x学习笔记(十六)分页查询我的待办

前言

        我的待办具体区分为3种情况,第一个就是办理人指定就是我,我可以直接审批;第二种就是我是候选人,我需要先拾取任务然后再办理;第三种是我是候选组,我需要切换到指定的角色去拾取任务再办理。如果任务已经拾取过,应该还要支持归还任务。

        接下来我从动作解析以及代码实现完整的实现整体的功能,需要说明的是文章中代码只有比较核心的代码,完整代码我会在文章结尾标明gitee仓库地址和分支。

一、任务拾取和归还

① 拾取

        拾取操作将某个任务从候选人/候选组池中分配给具体用户,使其成为该任务的受理人,认领后它将从候选池中移除。

        组任务分配:对于指定了“候选组”而非“受理人”的用户任务,不同用户可以竞相拾取,完成后再进行归还或流转。

        防止重复处理:一旦某人认领,其他候选人即不能再拾取,避免重复处理同一任务。

        工作量可见性:通过查询已认领任务,可以统计各人的工作量和进度。

② 归还

        归还操作则是将已认领的任务放回到候选池,取消当前用户的受理人身份,使任务重新回到候选组或候选用户队列中。

        任务重分配:当拾取任务的用户无法继续处理(例如休假、权限不足等),可归还让其他候选人再拾取。

        防止任务滞留:若一人长时间未处理,可自动或手动归还以避免流程阻塞。

        动态负载均衡:系统或管理员可根据当前负载情况,将任务归还后由空闲人员重新拾取,提升整体吞吐。

二、Feign接口

        由于我把Flowable单独设置为一个模块,所有查询用户信息比如角色列表,用户具体信息这些需要从别的模块通过feign接口rpc远程调用,如果架构和我一样可以参考,如果是单体服务可以直接本服务调用。

① 定义远程接口

        这里是要有两个接口,一个是根据用户ID查询角色ID列表;一个是根据用户ID查询用户信息;后续在查询我的待办任务时候会用到。

/**
 * 根据用户ID查询角色ID列表
 *
 * @param userId 用户ID,可选参数,用于查询角色ID列表
 * @return 返回一个Result对象,其中包含用户的角色ID列表
 */
@PostMapping("/systemClient/api/v1/user/queryRoleIdsByUserId")
Result<List<Long>> queryRoleIdsByUserId(@RequestParam(required = false , name = "userId") Long userId);

/**
 * 根据用户ID查询用户信息
 *
 * @param userId 用户ID,作为查询条件,用于定位特定的用户信息
 * @return 返回一个Result对象,其中包含查询到的Oauth2BasicUserVO用户信息
 */
@PostMapping("/systemClient/api/v1/user/queryUserById")
Result<Oauth2BasicUserVO> queryUserById(@RequestParam(required = false , name = "userId") Long userId);

② 远程服务实现远程接口

Ⅰ 定义接口

/**
 * 根据用户ID查询角色ID列表
 *
 * @param userId 用户ID,可选参数,如果未提供,则默认为null
 * @return 返回一个Result对象,其中包含角色ID列表
 */
@PostMapping("/queryRoleIdsByUserId")
public Result<List<Long>> queryRoleIdsByUserId(@RequestParam(required = false, name = "userId") Long userId) {
    try {
        // 查询所有未删除的角色信息
        List<Long> roleIds = sysRoleService.queryRoleIdsByUserId(userId);

        // 返回成功结果
        return Result.success(roleIds);
    } catch (Exception e) {
        // 记录错误日志并返回错误结果
        log.error("查询所有角色失败,失败原因:{}", e.getMessage(), e);
        return Result.error("查询所有角色失败,失败原因:" + e.getMessage());
    }
}

/**
 * 根据用户ID查询用户信息
 *
 * @param userId 用户ID,可选参数,用于指定要查询的用户
 * @return 返回一个Result对象,其中包含查询到的用户信息
 */
@PostMapping("/queryUserById")
public Result<Oauth2BasicUserVO> queryUserById(@RequestParam(required = false, name = "userId") Long userId) {
    try {
        // 查询所有未删除的角色信息
        Oauth2BasicUser oauth2BasicUser = oauth2BasicUserService.getById(userId);

        // 使用 Oauth2BasicUserStructMapper 转换输出结果
        Oauth2BasicUserVO oauth2BasicUserVO =
                Oauth2BasicUserStructMapper.INSTANCE.toApiVO(oauth2BasicUser);

        return Result.success(oauth2BasicUserVO);
    } catch (Exception e) {
        // 记录错误日志并返回错误结果
        log.error("根据用户ID查询用户信息失败,失败原因:{}", e.getMessage(), e);
        return Result.error("根据用户ID查询用户信息失败,失败原因:" + e.getMessage());
    }
}

Ⅱ 定义接口的服务

/**
 * 根据用户ID查询角色ID列表
 *
 * @param userId 用户ID,用于查询角色信息
 * @return 返回一个包含用户所拥有的角色ID的列表如果用户没有关联任何角色,则返回空列表
 */
List<Long> queryRoleIdsByUserId(Long userId);

Ⅲ 实现接口的服务

/**
 * 根据用户ID查询角色ID清单
 *
 * @param userId 用户ID,用于查询角色ID
 * @return 用户的角色ID清单,如果用户没有角色或查询失败,则返回空列表
 */
@Override
public List<Long> queryRoleIdsByUserId(Long userId) {
    // 参数判空
    if (userId == null) {
        return List.of();
    }

    try {
        // 根据用户ID查询用户角色绑定关系,并只获取角色ID字段
        List<SysUserRole> sysUserRoles = sysUserRoleService.lambdaQuery()
                .select(SysUserRole::getRoleId)  // 只查询需要的字段
                .eq(SysUserRole::getUserId, userId)
                .list();

        // 返回用户角色ID清单
        return sysUserRoles.stream().map(SysUserRole::getRoleId).toList();
    } catch (Exception e) {
        log.error("根据用户ID查询用户角色ID清单失败,失败原因:", e);
    }

    // 如果查询过程中出现异常,返回空列表
    return List.of();
}

三、我的待办接口

① 定义请求参数

        这里只需要简单的分页信息即可,我的信息直接从当前登陆人的session种获取。

package com.ceair.entity.request;

import lombok.Data;

import java.io.Serial;
import java.io.Serializable;

/**
 * @author wangbaohai
 * @ClassName PageReq
 * @description: 分页请求参数
 * @date 2025年02月16日
 * @version: 1.0.0
 */
@Data
public class PageReq implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 分页查询的页码和每页大小。
     *
     * pageNo: 当前页码,默认为1。
     * pageSize: 每页显示的记录数,默认为10。
     */
    private Long current = 1L;

    private Long size = 10L;

}

② 定义响应参数

        每个参数的定义请参考代码中的字段注释吧,也不是页面都要展示,不过多一些以防后续要用。

package com.ceair.entity.vo;

import lombok.Data;

import java.io.Serial;
import java.io.Serializable;
import java.util.List;

/**
 * @author wangbaohai
 * @ClassName TaskListInfoVO
 * @description: 任务列表信息VO
 * @date 2025年04月30日
 * @version: 1.0.0
 */
@Data
public class TaskListInfoVO implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    // 任务清单
    List<TaskVO> taskList;

    // 任务总数
    Long taskCount;

}

package com.ceair.entity.vo;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.flowable.variable.api.persistence.entity.VariableInstance;
import org.springframework.format.annotation.DateTimeFormat;

import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * @author wangbaohai
 * @ClassName TaskVO
 * @description: 任务实体VO
 * @date 2025年04月30日
 * @version: 1.0.0
 */
@Data
public class TaskVO implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    // 任务编号
    private String taskId;

    // 任务执行编号
    private String executionId;

    // 任务名称
    private String taskName;

    //  任务Key
    private String taskDefKey;

    // 任务执行人Id
    private String assigneeId;

    // 任务执行人名称
    private String assigneeName;

    // 流程发起人Id
    private String startUserId;

    // 流程发起人名称
    private String startUserName;

    // 流程类型
    private String category;

    // 流程变量信息
    private Object procVars;

    // 局部变量信息
    private Object taskLocalVars;

    // 流程部署编号
    private String deployId;

    // 流程ID
    private String procDefId;

    // 流程key
    private String procDefKey;

    // 流程定义名称
    private String procDefName;

    // 流程定义内置使用版本
    private int procDefVersion;

    // 流程实例ID
    private String procInsId;

    // 历史流程实例ID
    private String hisProcInsId;

    // 任务耗时
    private String duration;

    // 候选执行人
    private String candidate;

    // 关联的流程变量信息
    private Map<String, VariableInstance> variableInstances;
    private Map<String, Object> variables;

    // 任务发起时间
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    private LocalDateTime startTime;

    //任务创建时间
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    private LocalDateTime createTime;

    //任务完成时间
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    private LocalDateTime finishTime;

    // 审批人当前操作的标识 0:审批 1:拾取 2:审批或者归还
    private Integer status;

}

③ 定义功能接口

package com.ceair.controller;

import com.ceair.entity.request.PageReq;
import com.ceair.entity.result.Result;
import com.ceair.entity.vo.TaskListInfoVO;
import com.ceair.service.IMayTaskService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author wangbaohai
 * @ClassName MyTaskController
 * @description: 任务信息相关接口
 * @date 2025年05月01日
 * @version: 1.0.0
 */
@RestController
@RequestMapping("/api/v1/myTask")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "我的任务信息管理", description = "我的任务信息相关接口")
public class MyTaskController {

    private final IMayTaskService mayTaskService;

    /**
     * 分页查询我的待办任务。
     * <p>
     * 权限控制:需要拥有 '/api/v1/task/myTodoTask' 权限才能访问。
     * 接口参数:分页请求对象(pageReq),用于指定分页信息。
     * 接口用途:在API文档中标识该接口的功能为“分页查询我的待办任务”。
     * 请求方式:POST 请求,路径为 "/myTodoTask"。
     *
     * @param pageReq 分页请求对象,包含分页参数(页码、页大小等)。
     * @return Result<TaskListInfoVO> 返回封装后的分页任务列表信息。
     */
    @PreAuthorize("hasAnyAuthority('/api/v1/myTask/myTodoTask')")
    @Parameter(name = "pageReq", description = "分页请求对象", required = true)
    @Operation(summary = "分页查询我的待办任务")
    @PostMapping("/myTodoTask")
    public Result<TaskListInfoVO> myTodoTask(@RequestBody PageReq pageReq) {
        try {
            // 调用业务层查询我的待办任务
            TaskListInfoVO taskListInfoVO = mayTaskService.myTodoTask(pageReq);

            // 返回封装后的分页任务列表信息
            return Result.success(taskListInfoVO);
        } catch (Exception e) {
            log.error("查询我的待办任务失败,原因:{}", e.getMessage());
            return Result.error("查询我的待办任务失败,原因:" + e.getMessage());
        }
    }


}

④ 定义服务接口

⑤ 实现服务接口

        这块其实就是本文最核心的代码,其中要使用到Flowable引擎的TaskQuery创建查询工具实现查询功能,另外需要使用Flowable引擎的RepositoryService工具查询流程定义数据补充任务信息,以及需要使用Flowable引擎的HistoryService工具查询流程的发起人信息。

        其中查询当前用户的角色id列表和用户名称都需要用到我们第二步创建的feign接口实现。

package com.ceair.service.impl;

import cn.hutool.core.date.DateUtil;
import com.ceair.api.SystemFeignClient;
import com.ceair.entity.model.UserInfo;
import com.ceair.entity.request.PageReq;
import com.ceair.entity.result.Result;
import com.ceair.entity.vo.Oauth2BasicUserVO;
import com.ceair.entity.vo.TaskListInfoVO;
import com.ceair.entity.vo.TaskVO;
import com.ceair.exception.BusinessException;
import com.ceair.service.IMayTaskService;
import com.ceair.util.UserInfoUtils;
import io.micrometer.common.util.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wangbaohai
 * @ClassName MayTaskServiceImpl
 * @description: 我的任务信息接口实现
 * @date 2025年05月01日
 * @version: 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MayTaskServiceImpl implements IMayTaskService {

    private final RepositoryService repositoryService;
    private final SystemFeignClient systemFeignClient;
    private final TaskService taskService;
    private final HistoryService historyService;

    // 用户工具
    private final UserInfoUtils userInfoUtils;

    /**
     * 查询当前用户代办的任务列表
     *
     * @param pageReq 分页请求对象,包含当前页码和每页大小
     * @return 返回包含任务列表和总任务数的TaskListInfoVO对象
     * @throws IllegalArgumentException 如果分页信息为空,则抛出此异常
     * @throws BusinessException        如果用户未登录或查询角色ID失败,则抛出此异常
     */
    @Override
    public TaskListInfoVO myTodoTask(PageReq pageReq) {
        try {
            // 初始化
            TaskListInfoVO taskListInfoVO = new TaskListInfoVO();

            // 分页信息判空
            if (pageReq == null) {
                log.error("查询我的待办任务失败,原因:分页信息不能为空");
                throw new IllegalArgumentException("查询我的待办任务失败,原因:分页信息不能为空");
            }

            // 获取分页信息,如果不存在默认查询第一页,每页10条数据
            long current = (Objects.nonNull(pageReq.getCurrent()) && pageReq.getCurrent() > 0) ? pageReq.getCurrent() :
                    1L;
            long size = (Objects.nonNull(pageReq.getSize()) && pageReq.getSize() > 0) ? pageReq.getSize() : 10L;

            // 获取当前用户
            UserInfo userInfo = userInfoUtils.getUserInfoFromAuthentication();
            if (userInfo == null) {
                log.error("查询我的待办任务失败,原因:用户未登录");
                throw new BusinessException("查询我的待办任务失败,原因:用户未登录");
            }

            // 缓存用户ID字符串形式,避免重复调用
            String userIdStr = userInfo.getId().toString();
            String account = userInfo.getAccount();

            // 通过 feign 接口获取当前用的角色ID清单
            Collection<String> roleIds;
            Result<List<Long>> roleResult = systemFeignClient.queryRoleIdsByUserId(userInfo.getId());
            if (roleResult.getCode() != 200 || roleResult.getData() == null) {
                log.warn("查询我的待办任务失败,原因:{}", roleResult.getMessage());
                roleIds = Collections.emptyList();
            } else {
                roleIds = roleResult.getData().stream().map(String::valueOf).collect(Collectors.toList());
            }

            // 设置查询工具(需要查询激活的,办理人/候选人/候选组是我的任务)
            TaskQuery taskQuery = taskService.createTaskQuery()
                    .active()
                    .or()
                    .taskAssignee(userIdStr)
                    .taskCandidateUser(userIdStr);

            if (!roleIds.isEmpty()) {
                taskQuery.taskCandidateGroupIn(roleIds);
            }

            taskQuery.endOr()
                    .orderByTaskCreateTime()
                    .desc();

            // 查询工具设置分页属性并且实行查询动作
            List<Task> tasks = taskQuery.listPage((int) ((current - 1) * size), (int) (current * size));

            // 记录待办任务数量
            long count = taskQuery.count();

            // 初始化结果数据list
            List<TaskVO> taskVOS = new ArrayList<>();

            // 翻译任务数据
            tasks.stream()
                    .filter(Objects::nonNull)
                    .forEach(task -> {
                        TaskVO taskVO = new TaskVO();
                        taskVO.setTaskId(task.getId());
                        taskVO.setExecutionId(task.getExecutionId());
                        taskVO.setTaskName(task.getName());
                        taskVO.setProcDefId(task.getProcessDefinitionId());
                        taskVO.setTaskDefKey(task.getTaskDefinitionKey());
                        taskVO.setAssigneeId(task.getAssignee());
                        taskVO.setAssigneeName(StringUtils.isBlank(task.getAssignee()) ? "" : account);

                        // 查询确认 流程定义数据
                        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                                .processDefinitionId(task.getProcessDefinitionId())
                                .singleResult();
                        if (processDefinition != null) {
                            taskVO.setProcDefName(processDefinition.getName());
                            taskVO.setProcDefKey(processDefinition.getKey());
                            taskVO.setProcInsId(task.getProcessInstanceId());
                        }

                        // 查询确认 流程发起人
                        HistoricProcessInstance historicProcessInstance =
                                historyService.createHistoricProcessInstanceQuery()
                                        .processInstanceId(task.getProcessInstanceId()).singleResult();
                        if (historicProcessInstance != null
                                && StringUtils.isNotBlank(historicProcessInstance.getStartUserId())) {
                            // 确认 流程发起人
                            String startUserId = historicProcessInstance.getStartUserId();
                            taskVO.setStartUserId(startUserId);
                            // 确认流程发起时间
                            taskVO.setStartTime(DateUtil.toLocalDateTime(historicProcessInstance.getStartTime()));
                            // 通过feign接口使用用户ID获取用户信息
                            Result<Oauth2BasicUserVO> userResult =
                                    systemFeignClient.queryUserById(Long.valueOf(startUserId));
                            if (userResult.getCode() == 200 && userResult.getData() != null) {
                                taskVO.setStartUserName(userResult.getData().getName());
                            }
                        }

                        // 确认任务对于当前办理人是需要办理还是拾取还是归还
                        taskVO.setStatus(judgeStatus(task.getProcessDefinitionId(), task.getTaskDefinitionKey(),
                                task.getAssignee()));

                        // 集成封装
                        taskVOS.add(taskVO);
                    });

            // 返回结果
            taskListInfoVO.setTaskCount(count);
            taskListInfoVO.setTaskList(taskVOS);
            return taskListInfoVO;
        } catch (IllegalArgumentException e) {
            log.error("查询我的待办任务失败,原因:参数错误", e);
            throw new BusinessException("查询我的待办任务失败,原因:参数错误", e);
        } catch (BusinessException e) {
            log.error("查询我的待办任务失败,原因:业务异常", e);
            throw new BusinessException("查询我的待办任务失败,原因:业务异常", e);
        } catch (Exception e) {
            log.error("查询我的待办任务失败,原因:未知异常", e);
            throw new BusinessException("查询我的待办任务失败,原因:未知异常", e);
        }
    }

    /**
     * 根据流程定义ID、任务定义键和指定的办理人判断任务状态
     *
     * @param processDefinitionId 流程定义ID,用于识别特定的业务流程
     * @param taskDefinitionKey   任务定义键,用于在流程中定位特定的任务
     * @param assignee            指定的办理人,用于判断任务的当前状态
     * @return 返回任务的状态代码:0-审批,1-拾取,2-审批或归还;如果无法判断状态,则返回null
     */
    private Integer judgeStatus(String processDefinitionId, String taskDefinitionKey, String assignee) {
        // 参数校验
        if (StringUtils.isBlank(processDefinitionId) || StringUtils.isBlank(taskDefinitionKey)) {
            return null;
        }

        try {
            // 获取 BpmnModel 对象
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
            Process mainProcess = bpmnModel != null ? bpmnModel.getMainProcess() : null;

            if (mainProcess == null) {
                return null;
            }

            Collection<FlowElement> flowElements = mainProcess.getFlowElements();

            // 查找目标用户任务
            return flowElements.stream()
                    .filter(Objects::nonNull)
                    .filter(flowElement -> flowElement instanceof UserTask)
                    .map(flowElement -> (UserTask) flowElement)
                    .filter(userTask -> taskDefinitionKey.equals(userTask.getId()))
                    .findFirst()
                    .map(userTask -> {
                        if (!StringUtils.isBlank(userTask.getAssignee())) {
                            // 流程节点指定办理人:审批状态
                            return 0; // 审批
                        } else {
                            if (StringUtils.isBlank(assignee)) {
                                // 未指定实际办理人:拾取状态
                                return 1; // 拾取
                            } else {
                                // 已有实际办理人:审批/归还状态
                                return 2; // 审批或归还
                            }
                        }
                    })
                    .orElse(null);

        } catch (Exception e) {
            log.error("判断流程状态失败,具体原因为: {}", e.getMessage(), e);
            return null;
        }
    }

}

四、我的待办界面

① 定义前端实体

// 任务实体 VO
export interface TaskVO {
  taskId: string // 任务编号 (Java String)
  executionId: string // 任务执行编号
  taskName: string // 任务名称
  taskDefKey: string // 任务 Key
  assigneeId: string // 任务执行人 Id
  assigneeName: string // 任务执行人名称
  startUserId: string // 流程发起人 Id
  startUserName: string // 流程发起人名称
  category: string // 流程类型
  procVars: any // 流程变量信息 (Java Object)
  taskLocalVars: any // 局部变量信息
  deployId: string // 流程部署编号
  procDefId: string // 流程定义 ID
  procDefKey: string // 流程 Key
  procDefName: string // 流程定义名称
  procDefVersion: number // 流程定义版本号 (Java int)
  procInsId: string // 流程实例 ID
  hisProcInsId: string // 历史流程实例 ID
  duration: string // 任务耗时 (Java String)
  candidate: string // 候选执行人
  variableInstances: Record<string, any> // 关联的流程变量信息 (Java Map<String,VariableInstance>)
  variables: Record<string, any> // 关联的流程变量 (Java Map<String,Object>)
  startTime: string // 任务发起时间 (Java LocalDateTime → string)
  createTime: string // 任务创建时间
  finishTime: string // 任务完成时间
  status: number // 审批人当前操作的标识 (Java Integer)
}

// 任务列表信息 VO
export interface TaskListInfoVO {
  taskList: TaskVO[] // 任务清单 (Java List<TaskVO>)
  taskCount: number // 任务总数 (Java Long → number)
}

export interface PageReq {
  current: number // 当前页码,后端默认 1
  size: number // 每页记录数,后端默认 10
}

② 封装前端接口

import type { PageReq } from './taskType'
import request from '@/utils/http/request'

/**
 * 分页查询我的待办任务
 */
export function getMyTaskPage(data: PageReq) {
  return request.post<any>({
    url: '/pm-process/api/v1/myTask/myTodoTask',
    data,
  })
}

③ 绘制页面

        界面里包含了一个列表,列表里的操作列有3个按钮,但是会根据数据的状态动态调整是否展示。

<script lang="ts" setup>
import type { TaskVO } from '@/api/task/taskType'
import { getMyTaskPage } from '@/api/task/taskApi'
import { ElMessage } from 'element-plus'
import { onMounted, ref } from 'vue'

// 定义当前页码
const currentPage = ref<number>(1)
// 默认页行数
const pageSize = ref<number>(10)
// 数据总数
const total = ref<number>(0)
// 定义响应式数据 myTaskList,用于存储我的任务列表数据
const myTaskList = ref<TaskVO[]>([])
// 表格列定义
const tableColumns = [
  { label: '#', type: 'index', align: 'center', width: '50px' },
  { label: '任务编号', prop: 'taskId', align: 'center' },
  { label: '任务名称', prop: 'taskName', align: 'center' },
  { label: '任务执行人名称', prop: 'assigneeName', align: 'center' },
  { label: '流程发起人名称', prop: 'startUserName', align: 'center' },
  { label: '任务发起时间', prop: 'startTime', align: 'center' },
  { label: '流程定义名称', prop: 'procDefName', align: 'center' },
  { label: '流程实例ID', prop: 'procInsId', align: 'center' },
  { label: '操作', align: 'center', width: '200px' },
]

onMounted(() => {
  // 初始化分页参数并加载第一页任务数据
  currentPage.value = 1 // 设置当前页为第一页
  pageSize.value = 10 // 每页展示10条任务记录
  getMyTaskPageData() // 调用获取我的任务分页数据的方法
})

/**
 * 异步函数:获取我的任务列表数据
 * 该函数通过调用后端接口,获取当前用户的任务列表,并根据分页参数进行数据更新
 */
async function getMyTaskPageData() {
  try {
    // 设置分页参数
    const pageReq = {
      current: currentPage.value,
      size: pageSize.value,
    }

    // 调用接口获取我的任务列表数据
    const result: any = await getMyTaskPage(pageReq)

    // 如果接口调用成功且返回的状态码为200,则更新数据
    if (result.success && result.code === 200) {
      // 更新数据
      myTaskList.value = result.data.taskList
      // 收集数据总数
      total.value = result.data.taskCount
    }
    else {
      // 如果接口调用失败,显示错误提示信息
      ElMessage({
        message: '查询失败',
        type: 'error',
      })
    }
  }
  catch (error) {
    // 捕获异常并提取错误信息
    let errorMessage = '未知错误'
    if (error instanceof Error) {
      errorMessage = error.message
    }

    // 显示操作失败的错误提示信息
    ElMessage({
      message: `查询失败: ${errorMessage || '未知错误'}`,
      type: 'error',
    })
  }
}

/**
 * 处理页面数据函数
 * 本函数用于重新获取当前页面所需的数据
 * 它通过调用 getMyTaskPageData 函数来实现数据的重新加载
 */
function handerPageData() {
  // 重新加载数据
  getMyTaskPageData()
}
</script>

<template>
  <el-table style="margin: 10px 0px;" :border="true" :data="myTaskList">
    <!-- ID 区域 -->
    <el-table-column type="selection" align="center" width="50px" />
    <!-- 表格数据 区域 -->
    <el-table-column
      v-for="(column, index) in tableColumns"
      :key="index"
      :type="column.type"
      :label="column.label"
      :prop="column.prop"
      :align="column.align"
      :width="column.width"
    >
      <!-- 使用单个 template 包裹所有条件 -->
      <template #default="scope">
        <!-- 判断是否是操作列 -->
        <div v-if="column.label === '操作'">
          <el-button v-if="scope.row.status === 0 || scope.row.status === 2" type="primary">
            审批
          </el-button>
          <el-button v-if="scope.row.status === 1" type="primary">
            拾取
          </el-button>
          <el-button v-if="scope.row.status === 2" type="primary">
            归还
          </el-button>
        </div>
      </template>
    </el-table-column>
  </el-table>
  <!-- 分页器 -->
  <el-pagination
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    :page-sizes="[10, 20, 30, 40, 50]"
    layout="prev, pager, next, jumper,->, sizes, total"
    :total="Math.max(total, 0)"
    @current-change="getMyTaskPageData"
    @size-change="handerPageData"
  />
</template>

<style scoped>

</style>

五、增加菜单以及按钮权限

六、功能验证

① 指定办理人的场景

        这种场景我们应该点亮办理按钮

        验证下来是ok的,能看到任务并且任务是直接审批的。

② 指定候选人的场景

        这种场景我们应该只能点亮拾取按钮

        验证下来是ok的,能看到任务并且任务是可拾取的。

③ 指定候选组的场景

        admin的角色是超级管理员

        验证下来是ok的,能看到任务并且任务是可拾取的。

七、后记

        任务的归还点亮需要完整拾取功能,这个我在下一个文章中再来实现吧,本文的完整代码仓库地址请查看专栏第一篇文章的说明。

本文的后端分支是 process-9

本文的前端分支是 process-11

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值