芋道-------如何实现工作流退回后重新提交到之前退回的节点

本文介绍了在工作流系统中,如何处理任务退回后重新提交的情况,包括判断节点状态、修改审批界面、代码实现(如判断上一个节点状态、传递参数等)以及后台的流程更新和任务状态管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

      上一节,我们讲过了工作流如何退回到申请人,接下来我们来讲一讲,如何重新提交。这里重新提交可以是再走一遍正常流程,同时也可以是直接跳过中间的步骤,直接继续给上一步退回的人审批。文章中会提及这两种情况。

       首先,我们可以看到,在芋道的工作流中有一个好处是在业务表中与工作流关联起来了,同时也为当前的状态设置了单独的字段。所以这样我们能很容易的判断出来,当前节点处于什么状态。

二、逻辑梳理

    思路如下:首先在流程详情页面中,判断当前的节点的上一个节点是什么状态,然后拿到退回节点的状态,因为下一步我们将根据这个状态,把原本不可更改的详情页,改成可编辑的,这样用户才可以修改后重新提交。然后重新提交后,我们需要对业务表进行更新,同时需要继续启动流程。

总结:1、将task中所有任务按照时间进行排序,找到倒数第二个task即当前节点的上一个。

           2、然后判断result是否为‘5’(驳回),如果是,将标识isRerurn改成true。

           3、修改页面信息,对于申请信息,我们要考虑,何时可编辑,何时只能查看;对于审批任务何时可以显示,何时不需要显示。

           4、后台更新业务表、继续启动流程。

三、代码实现

1、判断当前节点的任务是否是被退回的

      为什么判断的是上一个节点,而不是当前节点,因为,当前节点一定是已经由上一个节点处理过后,才得到的结果。因此,我们要判断是由退回走到当前节点的还是正常流程通过走过来的。

     经过查看后台代码,发现result为5的表示的是当前任务节点是被驳回状态,同时在前台我们可以看到他已经按照时间顺序排好,因此我们只要判断数组中第二个位置的result是否为5即可,这个时候将标识isReturn设为true。

2、修改审批界面 --- 审批任务

    由于如果是重新提交,根据业务需求页面上就不需要审批任务这个模块,只留一个编辑表单信息就可以,所以这里加了条件限制,判断如果不是申请人就不显示审批任务。

3、修改审批界面 --- 申请信息组件值传递

      然后我们将 isReturn 和 runningTasks 这两个参数传到组件中,isReturn是是否是退回的标识,runningTasks是,当前登录人的任务列表。

      因为具体业务的表单信息,属于动态的,所以这里面他们引用了组件,我们需要把参数信息传到对应的表单页面,这样表单页面拿到信息,进而判断出什么时候可以编辑的,什么时候显示的。

     这里讲一下为什么传递这两个参数,首先,我们单纯的知道了什么时候退回,并不能控制住审批信息的显示和编辑,因为如果只是知道当前节点属于退回后的节点,其他人再进入到页面的时候,也会显示重新提交这个界面。

    所以我们还需要判断当前登录的人,是否是要退回到某个节点的人,在进行处理。这个时候,我们发现既有的代码中有一段runningTasks的逻辑,他其实就是将当前任务中需要登录用户处理的任务存起来,这样我们其实只要判断,这个runningTasks中是否有值即可,如果他有值,证明这个节点其实已经走到了当前登录的用户这里了,如果同时他又是退回后的节点,那么它就可以编辑该界面。

4、修改审批界面 --- 申请信息界面
<template>
  <div class="app-container">
    <!-- <el-form ref="form" :model="form" label-width="100px">
      <el-form-item label="开始时间:" prop="startTime">
        {{ parseTime(form.startTime, "{y}-{m}-{d}") }}
      </el-form-item>
      <el-form-item label="结束时间:" prop="endTime">
        {{ parseTime(form.endTime, "{y}-{m}-{d}") }}
      </el-form-item>
      <el-form-item label="请假类型:" prop="type">
        <dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="form.type" />
      </el-form-item>
      <el-form-item label="原因:" prop="reason"> {{ form.reason }}</el-form-item>
    </el-form> -->
    <!-- 对话框(添加 / 修改) -->
    <el-form ref="form" :model="form" label-width="100px">
      <el-form-item label="开始时间:" prop="startTime">
        <template v-if="isReturn && runningTasks.length != 0">
          <el-date-picker
            v-model="form.startTime"
            type="date"
            :editable="!isReturn"
          ></el-date-picker>
        </template>
        <template v-else>
          {{ parseTime(form.startTime, "{y}-{m}-{d}") }}
        </template>
      </el-form-item>
      <el-form-item label="结束时间:" prop="endTime">
        <template v-if="isReturn && runningTasks.length != 0">
          <el-date-picker
            v-model="form.endTime"
            type="date"
            :editable="!isReturn"
          ></el-date-picker>
        </template>
        <template v-else>
          {{ parseTime(form.endTime, "{y}-{m}-{d}") }}
        </template>
      </el-form-item>
      <el-form-item label="请假类型:" prop="type">
        <template v-if="isReturn && runningTasks.length != 0">
          <el-select v-model="form.type">
            <el-option
              v-for="dict in typeDictData"
              :key="parseInt(dict.value)"
              :label="dict.label"
              :value="parseInt(dict.value)"
            />
          </el-select>
        </template>
        <template v-else>
          <dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="form.type" />
        </template>
      </el-form-item>
      <el-form-item label="原因:" prop="reason">
        <template v-if="isReturn && runningTasks.length != 0">
          <el-input v-model="form.reason"></el-input>
        </template>
        <template v-else>
          {{ form.reason }}
        </template>
      </el-form-item>
      <el-form-item v-if="isReturn && runningTasks.length != 0">
        <el-button type="primary" @click="submitForm">重新提交</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import { updateLeave, getLeave } from "@/api/bpm/leave";
import { getDictDatas, DICT_TYPE } from "@/utils/dict";
export default {
  name: "BpmOALeaveDetail",
  components: {},
  props: {
    id: {
      type: [String, Number],
      default: undefined,
    },
    isReturn: {
      type: [Boolean],
      default: undefined,
    },
    runningTasks: {
      type: [Array],
      default: undefined,
    },
  },

  data() {
    return {
      leaveId: Number, // 请假编号
      // 表单参数
      form: {
        startTime: undefined,
        endTime: undefined,
        type: undefined,
        reason: undefined,
      },

      typeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
    };
  },
  created() {
    this.leaveId = this.id || this.$route.query.id;
    if (!this.leaveId) {
      this.$message.error("未传递 id 参数,无法查看 OA 请假信息");
      return;
    }
    console.log(
      "🚀 ~ runningTasks:",
      this.isReturn,
      this.runningTasks,
      this.runningTasks.length
    );
    this.getDetail();
  },
  methods: {
    /** 获得请假信息 */
    getDetail() {
      getLeave(this.leaveId).then((response) => {
        this.form = response.data;
      });
    },
    /** 提交按钮 */
    submitForm() {
      this.$refs["form"].validate((valid) => {
        if (!valid) {
          return;
        }
        // 添加的提交
        updateLeave(this.form).then((response) => {
          this.$modal.msgSuccess("重新提交成功!");
          this.$tab.closeOpenPage({ path: "/bpm/oa/leave" });
        });
      });
    },
  },
};
</script>
5、后台处理
Controller:
    @PutMapping("/update")
    public CommonResult<Long> updateLeave(@RequestBody BpmOALeaveUpdateReqVO updateReqVO){
        return success(leaveService.updateLeave(updateReqVO));
    }
Service :
    Long updateLeave( BpmOALeaveUpdateReqVO updateReqVO);

ServiceIml:

    public Long updateLeave(BpmOALeaveUpdateReqVO updateReqVO) {
        // 插入 OA 请假单
        long day = LocalDateTimeUtil.between(updateReqVO.getStartTime(), updateReqVO.getEndTime()).toDays();
        BpmOALeaveDO leave = BpmOALeaveConvert.INSTANCE.convert(updateReqVO).setUserId(SecurityFrameworkUtils.getLoginUserId()).setDay(day)
                .setId(updateReqVO.getId())
                .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
        leaveMapper.updateById(leave);
        List<BpmTaskRespVO> taskList = taskService.getTaskListByProcessInstanceId(updateReqVO.getProcessInstanceId());
        List<String> returnTaskKeyList = new ArrayList<>();
        returnTaskKeyList.add(taskList.get(0).getDefinitionKey());
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(updateReqVO.getProcessInstanceId())
                .moveActivityIdsToSingleActivityId(returnTaskKeyList, // 当前要跳转的节点列表( 1 或多)
                        taskList.get(1).getDefinitionKey()) // targetKey 跳转到的节点(1)
                .changeState();
        // 更新任务拓展表为通过 审批记录中添加对应节点信息
        taskExtMapper.updateByTaskId(
                new BpmTaskExtDO().setTaskId(taskList.get(0).getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
                        .setReason("重新提交"));
        // 更新 BPM 流程
        //taskService.approveTask(getLoginUserId(), reqVO);

        leaveMapper.updateById(new BpmOALeaveDO().setId(leave.getId()).setProcessInstanceId(updateReqVO.getProcessInstanceId()));
        return leave.getId();
    }

注释中的 taskService.approveTask(getLoginUserId(), reqVO); 就是退回后还按照正常顺序流程走的写法 ;而现在的写法是重新提交后直接跳到退回的那个节点

以上就是实现工作流退回后重新提交到之前退回的节点全部流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿土不土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值