前言
我的待办具体区分为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