基于jeecgboot-vue3的Flowable流程-自定义业务表单处理(一)支持同一个业务多个关联流程的选择支持

news2024/12/23 17:28:04
因为这个项目license问题无法开源,更多技术支持与服务请加入我的知识星球。

这部分先讲讲支持自定义业务表单一个业务服务表单多个流程的支持处理

1、后端mapper部分

如下,修改selectSysCustomFormByServiceName为list对象,以便支持多个

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.flowable.mapper.SysCustomFormMapper">
	<resultMap type="org.jeecg.modules.flowable.entity.SysCustomForm" id="sysCustomFormResult">
        <result property="id" column="id"/>
        <result property="businessName" column="business_name"/>
        <result property="businessService" column="business_service"/>
        <result property="flowName" column="flow_name"/>
        <result property="deployId" column="deploy_id"/>
        <result property="routeName" column="route_name"/>
        <result property="component" column="component"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="sysOrgCode" column="sys_org_code"/>
    </resultMap>
	
    <select id="selectSysCustomFormById" parameterType="String" resultType="org.jeecg.modules.flowable.entity.SysCustomForm">
         select id, business_name, business_service, deploy_id, route_name,component,create_time, update_time, create_by, update_by, sys_org_code 
         from sys_custom_form where id = #{formId}
    </select>
    
    <select id="selectSysCustomFormByServiceName" parameterType="String" resultMap="sysCustomFormResult">
         select id, business_name, business_service, flow_name, deploy_id, route_name,component,create_time, update_time, create_by, update_by, sys_org_code 
         from sys_custom_form where business_service = #{serviceName}
    </select>
    
    <update id="updateCustom" parameterType="Object">
         update sys_custom_form set deploy_id= #{customFormVo.deployId}, flow_name=#{customFormVo.flowName} where id = #{customFormVo.id}
    </update>
    
    <select id="selectBussinessKeyByDeployId" parameterType="String" resultType="String">
         select id from sys_custom_form where deploy_id = #{deployid}
    </select>
    
</mapper>

2、对流程启动也要修改,因为根据用户选择出来的id进行处理

 public Result startProcessInstanceByDataId(String dataId, String selectFlowId, String serviceName, Map<String, Object> variables) {
    	//提交审批的时候进行流程实例关联初始化
    	if (StringUtils.isEmpty(selectFlowId)){
            return Result.error("未找到关联流程selectFlowId:"+selectFlowId);
        }
    	/*
        if (serviceName==null){
             return Result.error("未找到serviceName:"+serviceName);
        }*/
        SysCustomForm sysCustomForm = sysCustomFormService.getById(selectFlowId);
        if(sysCustomForm ==null){
        	 return Result.error("未找到sysCustomForm:"+serviceName);
        }
        //优先考虑自定义业务表是否关联流程,再看通用的表单流程关联表
        ProcessDefinition processDefinition;
        String deployId = sysCustomForm.getDeployId();
        if(StringUtils.isEmpty(deployId)) {
        	SysDeployForm sysDeployForm  = sysDeployFormService.selectSysDeployFormByFormId(sysCustomForm.getId());
            if(sysDeployForm ==null){          	
       	       return Result.error("自定义表单也没关联流程定义表,流程没定义关联自定义表单"+sysCustomForm.getId());
            }
            processDefinition = repositoryService.createProcessDefinitionQuery()
        		.parentDeploymentId(sysDeployForm.getDeployId()).latestVersion().singleResult();
        }
        else {
        	processDefinition = repositoryService.createProcessDefinitionQuery()
            		.parentDeploymentId(deployId).latestVersion().singleResult();
        }
        
        LambdaQueryWrapper<FlowMyBusiness> flowMyBusinessLambdaQueryWrapper = new LambdaQueryWrapper<>();
        flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId, dataId);
        FlowMyBusiness business = flowMyBusinessService.getOne(flowMyBusinessLambdaQueryWrapper);
        if (business==null){
        	if(processDefinition==null) {
        		return Result.error("自定义表单也没关联流程定义表,流程没定义关联自定义表单"+sysCustomForm.getId());
        	}
        	boolean binit = flowCommonService.initActBusiness(sysCustomForm.getBusinessName(), dataId, serviceName, 
        	processDefinition.getKey(), processDefinition.getId(), sysCustomForm.getRouteName());
        	if(!binit) {
        		return Result.error("自定义表单也没关联流程定义表,流程没定义关联自定义表单"+sysCustomForm.getId());
        	}
            FlowMyBusiness businessnew = flowMyBusinessService.getOne(flowMyBusinessLambdaQueryWrapper);
           //流程实例关联初始化结束
            if (StrUtil.isNotBlank(businessnew.getProcessDefinitionId())){
              return this.startProcessInstanceById(businessnew.getProcessDefinitionId(),variables);
            }
            return this.startProcessInstanceByKey(businessnew.getProcessDefinitionKey(),variables);
        }
        else {
        	 return Result.error("已经存在这个dataid实例,不要重复申请:"+dataId);
        }
        
    }

3、前端代码如下:

<template>
  <span>
    <a-button :type="btnType" @click="applySubmit()" :loading="submitLoading">{{text}}</a-button>
    <a-modal :z-index="100" :title="firstInitiatorTitle" @cancel="firstInitiatorOpen = false" v-model:open="firstInitiatorOpen"
      :width="'50%'" append-to-body>
       <a-descriptions bordered layout="vertical">
         <a-descriptions-item :span="3">
               <a-badge status="processing" text="选择提醒" />
          </a-descriptions-item>
          <a-descriptions-item label="重新发起新流程按钮" labelStyle="{ color: '#fff', fontWeight: 'bold', fontSize='18px'}">
            重新发起新流程会删除之前发起的任务,重新开始.
          </a-descriptions-item>
          <a-descriptions-item label="继续发起老流程按钮">
            继续发起流程就在原来流程基础上继续流转.
          </a-descriptions-item>
       </a-descriptions>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="ReStartByDataId(true)">重新发起新流程</el-button>
        <el-button type="primary" @click="ReStartByDataId(false)">继续发起老流程</el-button>
        <el-button @click="firstInitiatorOpen = false">取 消</el-button>
      </span>
    </a-modal>

    <!--挂载关联多个流程-->
    <a-modal @cancel="flowOpen = false" :title="flowTitle" v-model:open="flowOpen" width="70%" append-to-body>
      <el-row :gutter="64">
        <el-col :span="20" :xs="64" style="width: 100%">
          <el-table ref="singleTable" :data="processList" border highlight-current-row style="width: 100%">
             <el-table-column type="selection" width="55" align="center" />
             <el-table-column label="主键" align="center" prop="id" v-if="true"/>
             <el-table-column label="业务表单名称" align="center" prop="businessName" />
             <el-table-column label="业务服务名称" align="center" prop="businessService" />
             <el-table-column label="流程名称" align="center" prop="flowName" />
             <el-table-column label="关联流程发布主键" align="center" prop="deployId" />
             <el-table-column label="前端路由地址" align="center" prop="routeName" />
             <el-table-column label="组件注入方法" align="center" prop="component" />
             <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
               <template #default="scope">
                 <el-button size="small" type="primary" @click="selectProcess(scope.row)">确定</el-button>
               </template>
             </el-table-column>
            </el-table>
        </el-col>
      </el-row>
    </a-modal>

  </span>
</template>

<script lang="ts" setup>
  import { ref, reactive  } from 'vue';
  import { useRouter, useRoute } from 'vue-router';
  import {
    definitionStartByDataId,
    isFirstInitiator,
    deleteActivityAndJoin,
    getProcesss
  } from "/@/views/flowable/api/definition";
  
  import { useMessage } from '/@/hooks/web/useMessage';
  
  const { createMessage, createConfirm } = useMessage();

  defineOptions({ name: 'ActApplyBtn' })
  const props = defineProps({
    btnType: {
      type: String,
      default: 'link',
      required: false
    },
    dataId: {
      type: String,
      default: '',
      required: true
    },
    serviceName: {
      type: String,
      default: '',
      required: true
    },
    variables: {
      type: Object,
      default: {},
    },
    text: {
      type: String,
      default: '提交申请',
      required: false
    }
  })

  const emit = defineEmits([
    'success'
  ])

  // 获取路由器对象 href跳转用到
  const router = useRouter();
  const route = useRoute();

  const modalVisible = ref(false)
  const submitLoading = ref(false)
  const form = ref<any>({})
  const firstInitiatorOpen = ref(false)
  const firstInitiatorTitle = ref('')
  // 关联流程数据
  const processList = ref<any>([])
  const flowOpen = ref(false)
  const flowTitle = ref('')
  const selectFlowId = ref('')  //选择或使用的流程ID
  const error = ref('')

  const selectProcess = (row) => {
    selectFlowId.value = row.id;
    flowOpen.value = false;
    var params = Object.assign({
      dataId: props.dataId
    }, props.variables);
    definitionStartByDataId(props.dataId, selectFlowId.value, props.serviceName, params)
      .then(res => {
        //console.log("startByDataId res",res);
        if (res.code == 200 ) {
          createMessage.success(res.msg);
          emit('success');
        } else {
          createMessage.error(res.msg);
        }
      })
      .finally(() => (submitLoading.value = false));
  }
  const ReStartByDataId = (isNewFlow: boolean) => {
    if(isNewFlow) {
      submitLoading.value = true;
      deleteActivityAndJoin(props.dataId,props.variables)
      .then(res => {
        if (res.code == 200 && res.result) { //若删除成功
          var params = Object.assign({
            dataId: props.dataId
          }, props.variables);
          definitionStartByDataId(props.dataId, selectFlowId.value, props.serviceName, params)
            .then(res => {
              if (res.code == 200) {
                firstInitiatorOpen.value = false;
                createMessage.success(res.message);
                emit('success');
              } else {
                createMessage.error(res.message);
              }
            })
        }
      })
      .finally(() => (submitLoading.value = false));
    }
    else {//继续原有流程流转,跳到流程处理界面上
      //console.log("props.variables",props.variables);
      router.push({
        path: '/flowable/task/record/index',
        query: {
          procInsId: props.variables.processInstanceId,
          deployId: props.variables.deployId,
          taskId: props.variables.taskId,
          businessKey: props.dataId,
          nodeType: "",
          appType: "ZDYYW",
          finished: true
        },
      })
    }
  }
  const applySubmit = () => {
    if (props.dataId && props.dataId.length < 1) {
      error.value = '必须传入参数dataId';
      createMessage.error(error.value);
      return;
    }
    if (props.serviceName && props.serviceName.length < 1) {
      error.value = '必须传入参数serviceName';
      createMessage.error(error.value);
      return;
    } else {
      error.value = '';
    }
    //对于自定义业务,判断是否是驳回或退回的第一个发起人节点
    submitLoading.value = true;
    isFirstInitiator(props.dataId, props.variables)
      .then(res => {
        if (res.code === 200 && res.result) { //若是,弹出窗口选择重新发起新流程还是继续老流程
          firstInitiatorTitle.value = "根据自己需要进行选择"
          firstInitiatorOpen.value = true;
        }
        else {
          submitLoading.value = true;
          const processParams = {
             serviceName: props.serviceName
          }
          /**查询关联流程信息 */
          getProcesss(processParams).then(res => {
            processList.value = res.result;
              submitLoading.value = false;
              if (processList.value && processList.value.length > 1) {
                flowOpen.value = true;
              }
              else if (processList.value && processList.value.length === 1) {
                selectFlowId.value = res.result[0].id;
                var params = Object.assign({
                  dataId: props.dataId
                }, props.variables);
                definitionStartByDataId(props.dataId, selectFlowId.value, props.serviceName, params)
                  .then(res => {
                    console.log("definitionStartByDataId res",res);
                    if (res.code == 200 ) {
                      createMessage.success(res.message);
                      emit('success');
                    } else {
                      createMessage.error(res.message);
                    }
                  })
                  .finally(() => (submitLoading.value = false));
              } else {
                createMessage.error("检查该业务是否已经关联流程!");
              }
          })
          .finally(() => (submitLoading.value = false));
        }
      })
      .finally(() => (submitLoading.value = false));
    }
</script>

4、效果图如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1847490.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

苹果手机短信删除了怎么恢复?有那些方法?

IPhone短信删除怎么恢复&#xff1f;现在大多数人都会使用社交软件沟通交流&#xff0c;短信的用武之地已经没以前那么多&#xff0c;但是它的重要性一点都不能忽视&#xff0c;有些重要的短信内容值得我们保留&#xff0c;如果不小心删除了这些短信内容该怎么恢复&#xff1f;…

全网首测!文生软件平台码上飞CodeFlying,效果炸裂!

前言&#xff1a; 提到AIGC&#xff0c;在大家的印象中应该就是让AI自己生成文字&#xff0c;图片等内容吧。随着今年Sora&#xff0c;Suno的爆火&#xff0c;将AIGC的应用场景又拉到了一个新的高度&#xff0c;为人们带来了更多的遐想。在未来&#xff0c;或许可以用AI来生成…

【LLM-多模态】高效多模态大型语言模型综述

一、结论写在前面 模型规模的庞大及训练和推理成本的高昂&#xff0c;限制了MLLMs在学术界和工业界的广泛应用。因此&#xff0c;研究高效轻量级的MLLMs具有巨大潜力&#xff0c;特别是在边缘计算场景中。 论文深入探讨了高效MLLM文献的领域&#xff0c;提供了一个全面的视角…

简易人工智能入门

一、监督or非监督 监督学习&#xff08;Supervised Learning&#xff09;&#xff1a;训练集有标记信息&#xff08;Y&#xff09;&#xff0c;学习方式有分类和回归 无监督学习&#xff08;Unsupervised Learning&#xff09;&#xff1a;训练集没有标记信息&#xff0c;学习…

20240621将需要自启动的部分放到RK3588平台的Buildroot系统的rcS文件中

20240621将需要自启动的部分放到RK3588平台的Buildroot系统的rcS文件中 2024/6/21 17:15 开发板&#xff1a;飞凌OK3588-C SDK&#xff1a;Rockchip原厂的Buildroot 缘起&#xff1a;在凌OK3588-C的LINUX R4系统启动的时候&#xff0c;需要拉高GPIO4_B5、GPIO3_B7和GPIO3_D0。…

高通Android 12 aapt报错问题踩坑

背景 最近因为要做多module模块&#xff0c;出现aapt报错&#xff0c;于是简单记录下&#xff0c;踩坑过程。 1、我一开始项目中三个module&#xff0c;然后在build.gradle设置androidApplication plugins {alias(libs.plugins.androidApplication) }2、运行完之后都是报下面…

中服云产品远程运维系统

中服云产品远程运维系统主要针对设备售后市场服务的管理&#xff0c;利用工业物联网技术&#xff0c;一方面面向设备生产厂商&#xff0c;将分散的经销商、客户、销售出去的设备统一管理&#xff1b;另一方面面向设备使用厂家&#xff0c;实现设备实时运行监控&#xff1b;系统…

五种实用方法!手把手教你系统盘瘦身

随着电脑的使用时间变长&#xff0c;电脑硬盘会逐渐被各种类型的数据占满&#xff0c;其中系统盘的可用空间也在慢慢变小。这是因为系统在运行过程中会产生大量临时文件和缓存文件&#xff0c;同时&#xff0c;系统的每一次更新升级也都会生成相关的文件夹存放在系统盘中&#…

C语言:生命周期和作用域,static和extern

关键字static与extern 1.作用域&#xff08;scope&#xff09;&#xff1a;代码中能够访问到变量的范围&#xff08;变量可以被使用的文本区间&#xff09;。&#xff08;分为全局作用域和局部作用域&#xff09; ☺全局作用域&#xff1a;在整个程序中都能访问的变量。通常…

机器学习算法的电影推荐系统以及票房预测系统

一、实验概述 1. 实验目标 本项目希望基于电影数据集&#xff0c;依据电影的简介、关键词、预算、票房、用户评分等特征来对电影进行分析&#xff0c;并完成以下任务&#xff1a; 对电影特征的可视化分析对电影票房的预测多功能个性化的电影推荐算法 2. 数据集 针对票房预…

58-DOS与DDOS分析(正常TCP会话与SYN Flood攻击、ICMP Flood 攻击、SNMP放大攻击等)

目录 正常 TCP 会话与 SYN Flood 攻击 1、正常的三次握手过程&#xff1a; 2、 SYN Flood 攻击 一、攻击windows系统&#xff1a; 二、攻击web网站 &#xff1a; 拒绝服务攻击工具-Hping3-Syn Flood 攻击 拒绝服务攻击工具--Hping3--ICMP Flood 攻击 sockstress攻击 So…

Studying-代码随想录训练营day16| 513找到左下角的值、112.路径总和、106从中序与后序遍历序列构造二叉树

第十六天&#xff0c;二叉树part03&#x1f4aa;&#x1f4aa;&#x1f4aa;&#xff0c;编程语言&#xff1a;C 目录 513找到左下角的值 112.路径总和 113.路径总和II 106从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树 总结 513找到左下角的值…

【计算机毕业设计】​206校园顺路代送微信小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

思聪私生女能继位吗?王健林表态,家族不会亏待

黄一鸣坚称&#xff1a;这绝对是王思聪的骨肉&#xff01;常言道&#xff0c;常在河边走&#xff0c;哪能不湿鞋。换女友如换装的王思聪&#xff0c;这次终于跌入了陷阱&#xff01;他的网红女友们如繁星点点&#xff0c;但选择标准始终如一——年轻、美丽。在金钱上&#xff0…

Nodejs 第七十九章(Kafka进阶)

kafka前置知识在上一章讲过了 不再复述 kafka进阶 1. server.properties配置文件 server.properties是Kafka服务器的配置文件&#xff0c;它用于配置Kafka服务的各个方面&#xff0c;包括网络设置、日志存储、消息保留策略、安全认证 #broker的全局唯一编号&#xff0c;不能…

市场价格到底是因为什么而变动?

在外汇及广泛的金融市场中&#xff0c;影响金融工具价格起伏的因素纷繁复杂。然而&#xff0c;万变不离其宗&#xff0c;无论是哪个市场&#xff0c;价格的最终决定力量始终是供需之间的平衡法则。 对于外汇、大宗商品等金融市场而言&#xff0c;表面上似乎受宏观经济数据、央…

极速查询:StarRocks 存算分离 Compaction 原理 调优指南

作者&#xff1a;丁凯&#xff0c;StarRocks TSC member/镜舟科技云原生技术负责人 StarRocks 在数据摄入过程中&#xff0c;每次操作都会创建一个新的数据版本。在查询时&#xff0c;为了得到准确的结果&#xff0c;必须将所有版本合并。然而&#xff0c;随着历史数据版本的累…

Midjourney v6 快速入门指南

Midjourney V6快速入门教程来了&#xff0c;这是Midjourney的AI图像生成器的又一次令人印象深刻的升级。最显著的是&#xff0c;V6在逼真渲染和图像中的文字功能方面取得了重大进展。 在这篇文章中&#xff0c;我们将探讨如何开始使用Midjourney V6&#xff0c;并提供一些示例…

【单片机毕业设计选题24018】-基于STM32和阿里云的农业大棚系统

系统功能: 系统分为手动和自动模式&#xff0c;上电默认为自动模式&#xff0c;自动模式下系统根据采集到的传感器值 自动控制&#xff0c;温度过低后自动开启加热&#xff0c;湿度过高后自动开启通风&#xff0c;光照过低后自动开启补 光&#xff0c;水位过低后自动开启水泵…

【LeetCode最详尽解答】42-接雨水 Trapping-Rain-Water

欢迎收藏Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog。如果收藏star, 有问题可以随时与我交流, 谢谢大家&#xff01; 链接: 42-接雨水 直觉 通过可视化图形来解决这个问题会更容易理解和解决。 给定输入: height [0,1,…