From 829b451481bc3737ad3d56679860d9601fa25490 Mon Sep 17 00:00:00 2001
From: ludc
Date: 星期三, 02 八月 2023 20:02:31 +0800
Subject: [PATCH] Merge branch 'master' of http://dev.vci-tech.com:1065/r/ubcs

---
 Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/utils/FlowableUtils.java                  |  727 +++++++++++++++++++++++++
 Source/UBCS-WEB/src/components/MasterCrud/VciMasterCrud.vue                                                     |   45 
 Source/UBCS-WEB/src/components/template/SetPersonnel.vue                                                        |    9 
 Source/UBCS-WEB/src/views/work/start.vue                                                                        |    2 
 Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/envent/FlowStatusListener.java            |  123 ++++
 Source/UBCS-WEB/src/views/work/process/leave/detail.vue                                                         |    2 
 Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClient.java              |   24 
 Source/UBCS-WEB/src/views/work/send.vue                                                                         |    2 
 Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/vo/FlowTaskHisVO.java               |  345 ++++++++++++
 Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/business/feign/FlowClient.java                   |   34 +
 Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClstemplateServiceImpl.java |   39 
 Source/UBCS-WEB/src/views/work/todo.vue                                                                         |    4 
 Source/UBCS-WEB/src/components/Theme/ThemeAttrCrud.vue                                                          |   56 +
 Source/UBCS/ubcs-service/ubcs-omd/src/main/java/com/vci/ubcs/omd/service/impl/BtmAttributeServiceImpl.java      |    2 
 Source/UBCS-WEB/src/components/Theme/ThemeClassifyTreeform.vue                                                  |   20 
 Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/constant/FlowEngineConstant.java          |   20 
 Source/UBCS/ubcs-service/ubcs-code/src/main/resources/mapper/CodeCLassifyMapper.xml                             |   23 
 Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/dto/FlowStatusDTO.java              |   80 ++
 Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClassifyServiceImpl.java    |   28 
 Source/UBCS-WEB/src/views/work/process/leave/form.vue                                                           |    6 
 Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java       |   19 
 Source/UBCS-WEB/src/components/Theme/ThemeClassifyTrees.vue                                                     |   18 
 Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClientFallback.java      |   13 
 Source/UBCS-WEB/src/views/work/process/leave/handle.vue                                                         |    1 
 Source/UBCS-WEB/src/views/work/done.vue                                                                         |    2 
 Source/UBCS-WEB/src/components/Theme/ThemeTemplatePro.vue                                                       |    2 
 Source/UBCS-WEB/src/views/work/claim.vue                                                                        |    2 
 Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/mapper/CodeClassifyMapper.java               |   13 
 28 files changed, 1,556 insertions(+), 105 deletions(-)

diff --git a/Source/UBCS-WEB/src/components/MasterCrud/VciMasterCrud.vue b/Source/UBCS-WEB/src/components/MasterCrud/VciMasterCrud.vue
index 61fbfc8..430e090 100644
--- a/Source/UBCS-WEB/src/components/MasterCrud/VciMasterCrud.vue
+++ b/Source/UBCS-WEB/src/components/MasterCrud/VciMasterCrud.vue
@@ -18,6 +18,15 @@
               <el-input v-model="WupinFindValue" placeholder="璇疯緭鍏ュ叧閿瓧鎸夊洖杞︽煡璇�"
                         size="small" style="width: 180px; margin-left: 5px; margin-top: 10px"
                         @keyup.enter.native="tableFindInp"  v-if="tableData.length != 0"></el-input>
+              <span style="margin-left: 10px" v-if="tableData.length != 0">
+               <p style="font-size: 13px;display: inline-block;"> 鐘舵�侊細</p>
+                <el-select v-model="statusSelect" slot="prepend" placeholder="璇烽�夋嫨" size="small" @change="cellSelectHandler">
+                <el-option label="鍏ㄩ儴" value="all"></el-option>
+                <el-option label="宸插彂甯�" value="Released"></el-option>
+                <el-option label="缂栬緫涓�" value="Editing"></el-option>
+                <el-option label="宸插仠鐢�" value="Disabled"></el-option>
+                <el-option label="瀹℃牳涓�" value="Auditing"></el-option>
+              </el-select></span>
             </div>
             <el-table  ref="dataTable" v-loading="isLoading" :data="tableData"
                       :height="tableHeight"
@@ -156,6 +165,7 @@
   },
   data() {
     return {
+      statusSelect:"",
       searchResults: [],
       //棣栭〉鍙充晶鎼滅储
       WupinFindValue: "",
@@ -234,11 +244,14 @@
         hasDownload: true,
         hasUpload: true,
         height: 100
-      }
+      },
+      result:''
     };
   },
   computed: {},
   created() {
+   const index = this.$route.query.id.indexOf('@');
+   this.result = this.$route.query.id.substring(0, index);
   },
   mounted() {
   },
@@ -263,6 +276,7 @@
     },
     tableDataArray: {
       handler(newval, oldval) {
+        this.statusSelect=''
         this.tableData = newval;
         this.searchResults = newval
         this.doLayout()
@@ -311,6 +325,10 @@
     }
   },
   methods: {
+    //鐘舵�佹悳绱�
+    cellSelectHandler(row){
+      console.log(row)
+    },
     //灞曞紑闄勪欢
     handleCollapse(activeNames) {
       if (activeNames.length > 0) {
@@ -386,7 +404,7 @@
             processTS({templateId: this.templateOid, buttonTypeKey: 'PUBLIC'}).then(res => {
               if (res.data.data.records && res.data.data.records.length!=0)  {
                 this.userName = localStorage.getItem("username");
-                this.parameter.template = this.userName + "-鍙戝竷" + "[鐗╁搧]";
+                this.parameter.template = this.userName + '-鍙戝竷['+this.result+'-' + this.selectRow[0].name + ']';
                 this.parameter.type = 'PUBLIC';
                 this.parameter.code=this.templateOid
                 this.title = '娴佺▼瀹℃壒'
@@ -397,11 +415,8 @@
                   cancelButtonText: '鍙栨秷',
                   type: 'warning'
                 }).then(() => {
-                  const index = this.$route.query.id.indexOf('@');
-                  const result = this.$route.query.id.substring(0, index);
-                  console.log(this.$route.query)
                   const oid = this.selectRow.map(obj => obj.oid).join(",");
-                  changeStatus({ oid: oid, btmname: result, lcStatus: 'Released' }).then(res => {
+                  changeStatus({ oid: oid, btmname: this.result, lcStatus: 'Released' }).then(res => {
                     if(res.data.code == 200 ){
                       this.$message.success('鍙戝竷鎴愬姛')
                       this.onLoad()
@@ -439,7 +454,7 @@
             processTS({ templateId: this.templateOid, buttonTypeKey: 'PUBLIC' }).then(res => {
               if (res.data.records != [] && res.data.data.records.length!=0) {
                 this.userName = localStorage.getItem("username");
-                this.parameter.template = this.userName + "鍋滅敤" + "[鐗╁搧]";
+                this.parameter.template = this.userName + '-鍋滅敤['+this.result+'-' + this.selectRow[0].name + ']';
                 this.parameter.type = 'DISABLE';
                 this.parameter.code=this.templateOid
                 this.title = '鍋滅敤锛堝喕缁擄級缂栫爜鏁版嵁'
@@ -452,10 +467,8 @@
                     cancelButtonText: '鍙栨秷',
                     type: 'warning'
                   }).then(() => {
-                    const index = this.$route.query.id.indexOf('@');
-                    const result = this.$route.query.id.substring(0, index);
                     const oid = this.selectRow.map(obj => obj.oid).join(",");
-                      changeStatus({ oid: oid, btmname: result, lcStatus: 'Disabled' }).then(res => {
+                      changeStatus({ oid: oid, btmname: this.result, lcStatus: 'Disabled' }).then(res => {
                         if(res.data.code == 200 ){
                           this.$message.success('鍋滅敤鎴愬姛')
                           this.onLoad()
@@ -492,7 +505,7 @@
               if (res.data.data.records && res.data.data.records.length!=0)  {
                 this.parameter=res.data.data.records[0]
                 this.userName = localStorage.getItem("username");
-                this.parameter.template = this.userName + "鍚敤" + "[鐗╁搧]";
+                this.parameter.template = this.userName + '-鍚敤['+this.result+'-' + this.selectRow[0].name + ']';
                 this.parameter.type = 'Released';
                 this.parameter.code=this.templateOid
                 this.title = '鍚敤缂栫爜鏁版嵁'
@@ -505,10 +518,8 @@
                     cancelButtonText: '鍙栨秷',
                     type: 'warning'
                   }).then(() => {
-                    const index = this.$route.query.id.indexOf('@');
-                    const result = this.$route.query.id.substring(0, index);
                     const oid = this.selectRow.map(obj => obj.oid).join(",");
-                    changeStatus({ oid: oid, btmname: result, lcStatus: 'Released' }).then(res => {
+                    changeStatus({ oid: oid, btmname: this.result, lcStatus: 'Released' }).then(res => {
                       if(res.data.code == 200 ){
                         this.$message.success('鍚敤鎴愬姛')
                         this.onLoad()
@@ -551,7 +562,7 @@
             processTS({ templateId: this.templateOid, buttonTypeKey: 'PUBLIC' }).then(res => {
               if (res.data.records != [] && res.data.data.records.length!=0) {
                 this.userName = localStorage.getItem("username");
-                this.parameter.template = this.userName + "鍥炴敹" + "[鐗╁搧]";
+                this.parameter.template = this.userName + '-鍥炴敹['+this.result+'-' + this.selectRow[0].name + ']';
                 this.parameter.type = 'TakeBack';
                 this.parameter.code=this.templateOid
                 this.title = '鍥炴敹缂栫爜鏁版嵁'
@@ -564,10 +575,8 @@
                     cancelButtonText: '鍙栨秷',
                     type: 'warning'
                   }).then(() => {
-                    const index = this.$route.query.id.indexOf('@');
-                    const result = this.$route.query.id.substring(0, index);
                     const oid = this.selectRow.map(obj => obj.oid).join(",");
-                    changeStatus({ oid: oid, btmname: result, lcStatus: 'TakeBack' }).then(res => {
+                    changeStatus({ oid: oid, btmname: this.result, lcStatus: 'TakeBack' }).then(res => {
                       if(res.data.code == 200 ){
                         this.$message.success('鍥炴敹鎴愬姛')
                         this.onLoad()
diff --git a/Source/UBCS-WEB/src/components/Theme/ThemeAttrCrud.vue b/Source/UBCS-WEB/src/components/Theme/ThemeAttrCrud.vue
index 56e9efa..5c1747a 100644
--- a/Source/UBCS-WEB/src/components/Theme/ThemeAttrCrud.vue
+++ b/Source/UBCS-WEB/src/components/Theme/ThemeAttrCrud.vue
@@ -88,6 +88,12 @@
       <el-dialog :visible.sync="enumVisible" append-to-body title="鏋氫妇娉ㄥ叆" :before-close="this.enumBeforeClose">
         <!-- 娓叉煋琛ㄦ牸鍙婃寜閽� -->
         <!-- 娓叉煋琛ㄦ牸鍙婃寜閽� -->
+        <el-alert
+          title="璇锋柊澧炲悗鐐瑰嚮鍗曞厓鏍艰緭鍏ユ灇涓炬暟鎹�"
+          type="success"
+          style="margin-bottom: 10px;display: inline-block"
+          :closable="false">
+        </el-alert>
         <div>
           <el-button icon="el-icon-plus" type="primary" @click="addRow">鏂板</el-button>
           <el-table :data="tableData" style="width: 100%" @cell-click="handleCellClick"
@@ -1799,29 +1805,33 @@
     },
     //鏋氫妇娉ㄥ叆淇濆瓨
     enumAddHandle() {
-      let hasError = false; // 娣诲姞涓�涓彉閲�
-      this.tableData.forEach((item, index) => {
-        if (item.key === '') {
-          this.$message.warning(`绗�${index + 1}琛岀殑閫夐」鍊间笉鑳戒负绌篳);
-          hasError = true;
-          return;
-        } else if (item.value === '') {
-          this.$message.warning(`绗�${index + 1}琛岀殑閫夐」涓枃鏍囩涓嶈兘涓虹┖`);
-          hasError = true;
-          return;
-        }
-      });
-        // 淇濆瓨鎵ц閫昏緫
-      if (!hasError) {
-        if (this.CurrentCell) {
-          this.$set(this.CurrentCell, 'enumString', JSON.stringify(this.tableData));
-          this.enumVisible = false;
-        } else {
-          this.$set(this.attrSelectList[0], 'enumString', JSON.stringify(this.tableData));
-          this.tableData=[];
-          this.enumVisible = false;
-        }
-      }
+     if(this.tableData.length>=1){
+       let hasError = false; // 娣诲姞涓�涓彉閲�
+       this.tableData.forEach((item, index) => {
+         if (item.key === '') {
+           this.$message.warning(`绗�${index + 1}琛岀殑閫夐」鍊间笉鑳戒负绌篳);
+           hasError = true;
+           return;
+         } else if (item.value === '') {
+           this.$message.warning(`绗�${index + 1}琛岀殑閫夐」涓枃鏍囩涓嶈兘涓虹┖`);
+           hasError = true;
+           return;
+         }
+       });
+       // 淇濆瓨鎵ц閫昏緫
+       if (!hasError) {
+         if (this.CurrentCell) {
+           this.$set(this.CurrentCell, 'enumString', JSON.stringify(this.tableData));
+           this.enumVisible = false;
+         } else {
+           this.$set(this.attrSelectList[0], 'enumString', JSON.stringify(this.tableData));
+           this.tableData=[];
+           this.enumVisible = false;
+         }
+       }
+     }else {
+       this.$message.warning('璇锋坊鍔犳灇涓炬敞鍏ユ暟鎹紒')
+     }
     },
     // 灏嗘鍦ㄧ紪杈戠殑琛岀殑鐘舵�佸彉涓� null锛屽嵆閫�鍑虹紪杈戠姸鎬�
     saveRow() {
diff --git a/Source/UBCS-WEB/src/components/Theme/ThemeClassifyTreeform.vue b/Source/UBCS-WEB/src/components/Theme/ThemeClassifyTreeform.vue
index 02f63df..7aa38b3 100644
--- a/Source/UBCS-WEB/src/components/Theme/ThemeClassifyTreeform.vue
+++ b/Source/UBCS-WEB/src/components/Theme/ThemeClassifyTreeform.vue
@@ -92,7 +92,11 @@
           <el-input style="width: 260px;margin-left: 15px" placeholder="杈撳叆鍊煎悗杩涜妯$硦鏌ヨ" v-model="SelectFInd"></el-input>
           <el-button size="small"  type="primary" plain @click="BtmSelectFindeHandler" style="margin-left: 20px">鏌ヨ</el-button>
         </template>
-        <avue-crud :data="BtmData" :option="masterOption" @select="btmSelect"></avue-crud>
+        <avue-crud :data="BtmData" :option="masterOption" @row-click="btmSelect">
+          <template slot="radio" slot-scope="{row}">
+            <el-radio v-model="masterRow" :label="row.$index" style="padding-left: 10px !important;">{{''}}</el-radio>
+          </template>
+        </avue-crud>
         <div style="height: 30px">
           <div style="display: inline-block;float: left;border: 1px solid #eee;padding: 5px;margin-top: 5px;font-size: 14px " >宸茶缃殑鍊间负:[{{this.loneTreeNewForm.btmTypeName}}]</div>
           <div style="padding-top: 10px;display: flex; justify-content: flex-end;float: right;overflow: hidden" >
@@ -113,6 +117,7 @@
   props: ['loneTreeNewForm','flag','Editclose','TreeFlag','nodeClickList'],
   data() {
     return {
+      masterRow:0,
       SelectFInd:"",
       masterName:"",
       masterOid:"",
@@ -166,10 +171,15 @@
         addBtn:false,
         index:true,
         border:true,
-        selection:true,
         menu:false,
         height:380,
         column:[
+          {
+            label: '',
+            prop: 'radio',
+            width: 60,
+            display: false
+          },
           {
             label:'鑻辨枃鍚嶇О',
             prop:'id'
@@ -567,9 +577,9 @@
     //涓氬姟绫诲瀷澶氶��
     btmSelect(row){
       this.btmSelectList=row;
-      this.btmName=row[0].name;
-      this.btmOid=row[0].oid;
-      this.btmId=row[0].id;
+      this.btmName=row.name;
+      this.btmOid=row.oid;
+      this.btmId=row.id;
     },
     //涓氬姟绫诲瀷鎺ュ彛
     btmdefaultRend(masterParameter){
diff --git a/Source/UBCS-WEB/src/components/Theme/ThemeClassifyTrees.vue b/Source/UBCS-WEB/src/components/Theme/ThemeClassifyTrees.vue
index 3710c01..84d410f 100644
--- a/Source/UBCS-WEB/src/components/Theme/ThemeClassifyTrees.vue
+++ b/Source/UBCS-WEB/src/components/Theme/ThemeClassifyTrees.vue
@@ -303,7 +303,11 @@
             <el-input style="width: 260px;margin-left: 15px" placeholder="杈撳叆鍊煎悗杩涜妯$硦鏌ヨ" v-model="SelectFInd"></el-input>
             <el-button size="small"  type="primary" plain @click="BtmSelectFindeHandler" style="margin-left: 20px">鏌ヨ</el-button>
           </template>
-          <avue-crud :data="BtmData" :option="masterOption" @select="btmSelect"></avue-crud>
+          <avue-crud :data="BtmData" :option="masterOption" @row-click="btmSelect">
+            <template slot="radio" slot-scope="{row}">
+              <el-radio v-model="masterRow" :label="row.$index" style="padding-left: 10px !important;">{{''}}</el-radio>
+            </template>
+          </avue-crud>
           <div style="height: 30px">
             <div style="display: inline-block;float: left;border: 1px solid #eee;padding: 5px;margin-top: 5px;font-size: 14px " >宸茶缃殑鍊间负:[{{this.TreeAddform.btmTypeName}}]</div>
             <div style="padding-top: 10px;display: flex; justify-content: flex-end;float: right;overflow: hidden" >
@@ -350,6 +354,7 @@
   inject: ["crudTreeData"],
   data() {
     return {
+      masterRow:0,
       AddLoading:false,
       // 瀹氫箟涓�涓彉閲忔潵淇濆瓨鏍戣姹傜殑鏁伴噺
       requestCount:0,
@@ -389,10 +394,15 @@
         addBtn:false,
         index:true,
         border:true,
-        selection:true,
         menu:false,
         height:380,
         column:[
+          {
+            label: '',
+            prop: 'radio',
+            width: 60,
+            display: false
+          },
           {
             label:'鑻辨枃鍚嶇О',
             prop:'id'
@@ -956,8 +966,8 @@
     //涓氬姟绫诲瀷澶氶��
     btmSelect(row){
       this.btmSelectList=row;
-      this.btmName=row[0].name;
-      this.btmOid=row[0].id;
+      this.btmName=row.name;
+      this.btmOid=row.id;
     },
     //涓氬姟绫诲瀷鎺ュ彛
     btmdefaultRend(masterParameter){
diff --git a/Source/UBCS-WEB/src/components/Theme/ThemeTemplatePro.vue b/Source/UBCS-WEB/src/components/Theme/ThemeTemplatePro.vue
index dbfef25..e53c6cc 100644
--- a/Source/UBCS-WEB/src/components/Theme/ThemeTemplatePro.vue
+++ b/Source/UBCS-WEB/src/components/Theme/ThemeTemplatePro.vue
@@ -35,7 +35,7 @@
           prop: 'tab3',
         }]
       },
-      checkStatus:true,//鏄惁闇�瑕侀獙璇佹ā鏉跨姸鎬�,
+      checkStatus:false,//鏄惁闇�瑕侀獙璇佹ā鏉跨姸鎬�,
     }
   },
   created() {
diff --git a/Source/UBCS-WEB/src/components/template/SetPersonnel.vue b/Source/UBCS-WEB/src/components/template/SetPersonnel.vue
index 59f6533..29cec50 100644
--- a/Source/UBCS-WEB/src/components/template/SetPersonnel.vue
+++ b/Source/UBCS-WEB/src/components/template/SetPersonnel.vue
@@ -10,7 +10,7 @@
                 <el-input placeholder="娴佺▼妯℃澘" v-model="saveParam.modelName" disabled></el-input>
             </el-form-item>
             <el-form-item label="娴佺▼鍚嶇О" prop="processName">
-                <el-input placeholder="娴佺▼鍚嶇О" v-model="saveParam.processName">
+                <el-input placeholder="娴佺▼鍚嶇О" v-model="saveParam.template">
                 </el-input>
             </el-form-item>
             <el-form-item label="娴佺▼鎻忚堪">
@@ -92,9 +92,10 @@
         },
       parameter:{
           handler(newval,oldval){
-			this.saveParam=newval
-          },deep:true,
-		  immediate:true
+			      this.saveParam=newval;
+          },
+        deep:true,
+		    immediate:true
       }
     },
     data() {
diff --git a/Source/UBCS-WEB/src/views/work/claim.vue b/Source/UBCS-WEB/src/views/work/claim.vue
index 60dcb16..6eb9ce6 100644
--- a/Source/UBCS-WEB/src/views/work/claim.vue
+++ b/Source/UBCS-WEB/src/views/work/claim.vue
@@ -175,7 +175,7 @@
           });
       },
       handleDetail(row) {
-        this.$router.push({path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/detail/${row.processInstanceId}/${row.businessId}`});
+        this.$router.push({path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/detail/${row.processInstanceId}/${row.businessId}?name=` +row.categoryName+'璇︽儏'});
       },
       handleImage(row) {
         this.processInstanceId = row.processInstanceId;
diff --git a/Source/UBCS-WEB/src/views/work/done.vue b/Source/UBCS-WEB/src/views/work/done.vue
index 677ee06..09160ea 100644
--- a/Source/UBCS-WEB/src/views/work/done.vue
+++ b/Source/UBCS-WEB/src/views/work/done.vue
@@ -152,7 +152,7 @@
         this.$refs.crud.toggleSelection();
       },
       handleDetail(row) {
-        this.$router.push({path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/detail/${row.processInstanceId}/${row.businessId}`});
+        this.$router.push({path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/detail/${row.processInstanceId}/${row.businessId}?name=` +row.categoryName+'璇︽儏'});
       },
       handleImage(row) {
         this.processInstanceId = row.processInstanceId;
diff --git a/Source/UBCS-WEB/src/views/work/process/leave/detail.vue b/Source/UBCS-WEB/src/views/work/process/leave/detail.vue
index 18a8e30..9dc6b12 100644
--- a/Source/UBCS-WEB/src/views/work/process/leave/detail.vue
+++ b/Source/UBCS-WEB/src/views/work/process/leave/detail.vue
@@ -25,7 +25,7 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <el-form-item label="璇峰亣鐞嗙敱">
+        <el-form-item label="鎻忚堪">
           <el-input :disabled="true" type="textarea" v-model="form.reason" />
         </el-form-item>
       </el-card>
diff --git a/Source/UBCS-WEB/src/views/work/process/leave/form.vue b/Source/UBCS-WEB/src/views/work/process/leave/form.vue
index 5f15d44..de380a2 100644
--- a/Source/UBCS-WEB/src/views/work/process/leave/form.vue
+++ b/Source/UBCS-WEB/src/views/work/process/leave/form.vue
@@ -21,7 +21,7 @@
           group: [
             {
               icon: 'el-icon-info',
-              label: '璇峰亣鍩虹淇℃伅',
+              label: '鍩虹淇℃伅',
               prop: 'group1',
               column: [
                 {
@@ -69,14 +69,14 @@
                   ]
                 },
                 {
-                  label: '璇峰亣鐞嗙敱',
+                  label: '鎻忚堪',
                   prop: 'reason',
                   type: 'textarea',
                   span: 24,
                   rules: [
                     {
                       required: true,
-                      message: '璇疯緭鍏ヨ鍋囩悊鐢�',
+                      message: '璇疯緭鍏ュ唴瀹�',
                       trigger: 'blur'
                     }
                   ]
diff --git a/Source/UBCS-WEB/src/views/work/process/leave/handle.vue b/Source/UBCS-WEB/src/views/work/process/leave/handle.vue
index c63ebc4..bb59a71 100644
--- a/Source/UBCS-WEB/src/views/work/process/leave/handle.vue
+++ b/Source/UBCS-WEB/src/views/work/process/leave/handle.vue
@@ -146,6 +146,7 @@
       this.templateId=res.data.variables.templateId;
       this.modelKey=res.data.variables.modelKey;
       this.codeClassifyOid=res.data.variables.codeClassifyOid;
+      this.title='11';
       //this.taskId=res.data.variables.taskId;
       if (res.success) {
         console.log(res)
diff --git a/Source/UBCS-WEB/src/views/work/send.vue b/Source/UBCS-WEB/src/views/work/send.vue
index 54e54d7..c1931ee 100644
--- a/Source/UBCS-WEB/src/views/work/send.vue
+++ b/Source/UBCS-WEB/src/views/work/send.vue
@@ -162,7 +162,7 @@
         this.$refs.crud.toggleSelection();
       },
       handleDetail(row) {
-        this.$router.push({ path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/detail/${row.processInstanceId}/${row.businessId}` });
+        this.$router.push({ path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/detail/${row.processInstanceId}/${row.businessId}?name=` +row.categoryName+'璇︽儏' });
       },
       handleImage(row) {
         this.processInstanceId = row.processInstanceId;
diff --git a/Source/UBCS-WEB/src/views/work/start.vue b/Source/UBCS-WEB/src/views/work/start.vue
index 7298ed5..7451c91 100644
--- a/Source/UBCS-WEB/src/views/work/start.vue
+++ b/Source/UBCS-WEB/src/views/work/start.vue
@@ -187,7 +187,7 @@
         this.$refs.crud.toggleSelection();
       },
       handleStart(row) {
-        this.$router.push({path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/form/${row.id}`});
+        this.$router.push({path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/form/${row.id}?name=` +row.categoryName});
       },
       handleImage(row) {
         this.processDefinitionId = row.id;
diff --git a/Source/UBCS-WEB/src/views/work/todo.vue b/Source/UBCS-WEB/src/views/work/todo.vue
index c03cc4c..ca53516 100644
--- a/Source/UBCS-WEB/src/views/work/todo.vue
+++ b/Source/UBCS-WEB/src/views/work/todo.vue
@@ -158,10 +158,10 @@
         this.$refs.crud.toggleSelection();
       },
       handleWork(row) {
-        this.$router.push({ path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/handle/${row.taskId}/${row.processInstanceId}/${row.businessId}` });
+        this.$router.push({ path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/handle/${row.taskId}/${row.processInstanceId}/${row.businessId}?name=`+'澶勭悊'+row.categoryName });
       },
       handleDetail(row) {
-        this.$router.push({ path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/detail/${row.processInstanceId}/${row.businessId}` });
+        this.$router.push({ path: `/work/process/${flowRoute(this.flowRoutes, row.category)}/detail/${row.processInstanceId}/${row.businessId}?name=` +row.categoryName+'璇︽儏'});
       },
       handleImage(row) {
         this.processInstanceId = row.processInstanceId;
diff --git a/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/dto/FlowStatusDTO.java b/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/dto/FlowStatusDTO.java
new file mode 100644
index 0000000..ebbba0d
--- /dev/null
+++ b/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/dto/FlowStatusDTO.java
@@ -0,0 +1,80 @@
+package com.vci.ubcs.flow.core.dto;
+
+import com.vci.ubcs.flow.core.vo.FlowTaskHisVO;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 娴佺▼鐨勬墽琛屼俊鎭�
+ * @author dangsn
+ * @Date 2023/07/31
+ */
+public class FlowStatusDTO implements java.io.Serializable{
+
+    /**
+     * 搴忓垪鍖�
+     */
+	private static final long serialVersionUID = 7539176109676429282L;
+    /**
+     * 涓氬姟绫诲瀷
+     */
+    private String btmType;
+
+    /**
+     * 鏁版嵁鐨勪富閿�
+     */
+    private List<String> oids;
+
+    /**
+     * 鍙橀噺鐨勫唴瀹�
+     */
+    private Map<String,Object> variableMap;
+
+    /**
+     * 鎵ц鍘嗗彶
+     */
+    private List<FlowTaskHisVO> taskHisVOList;
+
+    public String getBtmType() {
+        return btmType;
+    }
+
+    public void setBtmType(String btmType) {
+        this.btmType = btmType;
+    }
+
+    public List<String> getOids() {
+        return oids;
+    }
+
+    public void setOids(List<String> oids) {
+        this.oids = oids;
+    }
+
+    public Map<String, Object> getVariableMap() {
+        return variableMap;
+    }
+
+    public void setVariableMap(Map<String, Object> variableMap) {
+        this.variableMap = variableMap;
+    }
+
+    public List<FlowTaskHisVO> getTaskHisVOList() {
+        return taskHisVOList;
+    }
+
+    public void setTaskHisVOList(List<FlowTaskHisVO> taskHisVOList) {
+        this.taskHisVOList = taskHisVOList;
+    }
+
+	@Override
+	public String toString() {
+		return "FlowStatusDTO{" +
+			"btmType='" + btmType + '\'' +
+			", oids=" + oids +
+			", variableMap=" + variableMap +
+			", taskHisVOList=" + taskHisVOList +
+			'}';
+	}
+}
diff --git a/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClient.java b/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClient.java
index d65e7f3..c94f81f 100644
--- a/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClient.java
+++ b/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClient.java
@@ -16,7 +16,9 @@
  */
 package com.vci.ubcs.flow.core.feign;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.vci.ubcs.flow.core.entity.BladeFlow;
+import com.vci.ubcs.flow.core.entity.ProcessTemplate;
 import org.springblade.core.launch.constant.AppConstant;
 import org.springblade.core.tool.api.R;
 import org.springframework.cloud.openfeign.FeignClient;
@@ -25,6 +27,7 @@
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -44,6 +47,8 @@
 	String COMPLETE_TASK = API_PREFIX + "/complete-task";
 	String TASK_VARIABLE = API_PREFIX + "/task-variable";
 	String TASK_VARIABLES = API_PREFIX + "/task-variables";
+	String SELECT_BY_WRAPPER = API_PREFIX + "/select-by-wrapper";
+	String PROCESS_BATCH_SAVE = API_PREFIX + "/PROCESS-BATCH-SAVE";
 
 	/**
 	 * 寮�鍚祦绋�
@@ -97,4 +102,23 @@
 	 */
 	@GetMapping(TASK_VARIABLES)
 	R<Map<String, Object>> taskVariables(@RequestParam("taskId") String taskId);
+
+	/**
+	 * 鏌ヨ鏁版嵁wrapper鏂瑰紡
+	 *
+	 * @param wrapperMap 鏉′欢
+	 * @return R
+	 */
+	@PostMapping(SELECT_BY_WRAPPER)
+	R<List<ProcessTemplate>> selectByWrapper(@RequestBody Map<String,Object> wrapperMap);
+
+	/**
+	 * 鎵归噺淇濆瓨娴佺▼鏁版嵁
+	 *
+	 * @param listProcessTemplate 淇濆瓨鏁版嵁
+	 * @return R
+	 */
+	@PostMapping(PROCESS_BATCH_SAVE)
+	R processBatchSave(@RequestBody List<ProcessTemplate> listProcessTemplate);
+
 }
diff --git a/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClientFallback.java b/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClientFallback.java
index 5148a22..29790de 100644
--- a/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClientFallback.java
+++ b/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/feign/IFlowClientFallback.java
@@ -16,10 +16,13 @@
  */
 package com.vci.ubcs.flow.core.feign;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.vci.ubcs.flow.core.entity.BladeFlow;
+import com.vci.ubcs.flow.core.entity.ProcessTemplate;
 import org.springblade.core.tool.api.R;
 import org.springframework.stereotype.Component;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -55,4 +58,14 @@
 		return R.fail("杩滅▼璋冪敤澶辫触");
 	}
 
+	@Override
+	public R<List<ProcessTemplate>> selectByWrapper( Map<String,Object> wrapperMap) {
+		return R.fail("杩滅▼璋冪敤澶辫触");
+	}
+
+	@Override
+	public R processBatchSave(List<ProcessTemplate> listProcessTemplate) {
+		return R.fail("杩滅▼璋冪敤澶辫触");
+	}
+
 }
diff --git a/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/vo/FlowTaskHisVO.java b/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/vo/FlowTaskHisVO.java
new file mode 100644
index 0000000..c06c737
--- /dev/null
+++ b/Source/UBCS/ubcs-ops-api/ubcs-flow-api/src/main/java/com/vci/ubcs/flow/core/vo/FlowTaskHisVO.java
@@ -0,0 +1,345 @@
+package com.vci.ubcs.flow.core.vo;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 娴佺▼浠诲姟鍘嗗彶鏄剧ず瀵硅薄
+ * @author dangsn
+ * @date 2023/07/31
+ */
+public class FlowTaskHisVO implements java.io.Serializable{
+
+    /**
+     * 绂佹淇敼杩欎釜鍊�
+     */
+	private static final long serialVersionUID = -5305339505741718337L;
+    /**
+     * 鍘嗗彶璁板綍涓婚敭
+     */
+    private String oid;
+
+    /**
+     * 娲诲姩涓婚敭
+     */
+    private String activityId;
+
+    /**
+     * 浠诲姟鍚嶇О
+     */
+    private String activityName;
+
+    /**
+     * 浠诲姟绫诲瀷
+     */
+    private String activityType;
+
+    /**
+     * 娴佺▼瀹氫箟涓婚敭
+     */
+    private String processDefinitionId;
+
+    /**
+     * 娴佺▼瀹炰緥涓婚敭
+     */
+    private String processInstanceId;
+
+    /**
+     * 娴佺▼鐨勫悕绉�
+     */
+    private String processName;
+
+    /**
+     * 娴佺▼妯℃澘鍚嶇О
+     */
+    private String processDefinitionName;
+
+    /**
+     * 鎵ц涓婚敭
+     */
+    private String executionId;
+
+    /**
+     * 浠诲姟涓婚敭
+     */
+    private String taskId;
+
+    /**
+     * 璋冪敤娴佺▼涓婚敭
+     */
+    private String calledProcessInstanceId;
+
+    /**
+     * 鎵ц浜鸿处鍙�
+     */
+    private String assignee;
+
+    /**
+     * 鎵ц浜哄鍚�
+     */
+    private String assigneeName;
+
+    /**
+     * 寮�濮嬫椂闂�
+     */
+    private Date startTime;
+
+    /**
+     * 瀹屾垚鏃堕棿
+     */
+    private Date endTime;
+
+    /**
+     * 鑰楁椂
+     */
+    private Long durationInMillis;
+
+    /**
+     * 鍒犻櫎鍘熷洜
+     */
+    private String deleteReason;
+
+    /**
+     * 绉熸埛涓婚敭
+     */
+    private String tenantId;
+
+    /**
+     * 瀹℃壒鎰忚
+     */
+    private String description;
+
+    /**
+     * 鍙橀噺
+     */
+    private Map<String,Object> variablesMap;
+
+    /**
+     * 澶氭潯鏁版嵁鏃跺叧鑱旂殑涓氬姟鏁版嵁涓婚敭
+     */
+    private List<String> linkBusinessOids;
+
+    /**
+     * 鏄剧ず璺緞
+     */
+    private String displayUrl;
+
+    /**
+     * 鍙戣捣娴佺▼鐨勪笟鍔$被鍨�
+     */
+    private String btmType;
+
+    public String getProcessName() {
+        return processName;
+    }
+
+    public void setProcessName(String processName) {
+        this.processName = processName;
+    }
+
+    public String getProcessDefinitionName() {
+        return processDefinitionName;
+    }
+
+    public void setProcessDefinitionName(String processDefinitionName) {
+        this.processDefinitionName = processDefinitionName;
+    }
+
+    public String getBtmType() {
+        return btmType;
+    }
+
+    public void setBtmType(String btmType) {
+        this.btmType = btmType;
+    }
+
+    public String getOid() {
+        return oid;
+    }
+
+    public void setOid(String oid) {
+        this.oid = oid;
+    }
+
+    public List<String> getLinkBusinessOids() {
+        return linkBusinessOids;
+    }
+
+    public void setLinkBusinessOids(List<String> linkBusinessOids) {
+        this.linkBusinessOids = linkBusinessOids;
+    }
+
+    public String getDisplayUrl() {
+        return displayUrl;
+    }
+
+    public void setDisplayUrl(String displayUrl) {
+        this.displayUrl = displayUrl;
+    }
+
+    public String getActivityId() {
+        return activityId;
+    }
+
+    public void setActivityId(String activityId) {
+        this.activityId = activityId;
+    }
+
+    public String getActivityName() {
+        return activityName;
+    }
+
+    public void setActivityName(String activityName) {
+        this.activityName = activityName;
+    }
+
+    public String getActivityType() {
+        return activityType;
+    }
+
+    public void setActivityType(String activityType) {
+        this.activityType = activityType;
+    }
+
+    public String getProcessDefinitionId() {
+        return processDefinitionId;
+    }
+
+    public void setProcessDefinitionId(String processDefinitionId) {
+        this.processDefinitionId = processDefinitionId;
+    }
+
+    public String getProcessInstanceId() {
+        return processInstanceId;
+    }
+
+    public void setProcessInstanceId(String processInstanceId) {
+        this.processInstanceId = processInstanceId;
+    }
+
+    public String getExecutionId() {
+        return executionId;
+    }
+
+    public void setExecutionId(String executionId) {
+        this.executionId = executionId;
+    }
+
+    public String getTaskId() {
+        return taskId;
+    }
+
+    public void setTaskId(String taskId) {
+        this.taskId = taskId;
+    }
+
+    public String getCalledProcessInstanceId() {
+        return calledProcessInstanceId;
+    }
+
+    public void setCalledProcessInstanceId(String calledProcessInstanceId) {
+        this.calledProcessInstanceId = calledProcessInstanceId;
+    }
+
+    public String getAssignee() {
+        return assignee;
+    }
+
+    public void setAssignee(String assignee) {
+        this.assignee = assignee;
+    }
+
+    public String getAssigneeName() {
+        return assigneeName;
+    }
+
+    public void setAssigneeName(String assigneeName) {
+        this.assigneeName = assigneeName;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public Long getDurationInMillis() {
+        return durationInMillis;
+    }
+
+    public void setDurationInMillis(Long durationInMillis) {
+        this.durationInMillis = durationInMillis;
+    }
+
+    public String getDeleteReason() {
+        return deleteReason;
+    }
+
+    public void setDeleteReason(String deleteReason) {
+        this.deleteReason = deleteReason;
+    }
+
+    public String getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(String tenantId) {
+        this.tenantId = tenantId;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Map<String, Object> getVariablesMap() {
+        return variablesMap;
+    }
+
+    public void setVariablesMap(Map<String, Object> variablesMap) {
+        this.variablesMap = variablesMap;
+    }
+
+	@Override
+	public String toString() {
+		return "FlowTaskHisVO{" +
+			"oid='" + oid + '\'' +
+			", activityId='" + activityId + '\'' +
+			", activityName='" + activityName + '\'' +
+			", activityType='" + activityType + '\'' +
+			", processDefinitionId='" + processDefinitionId + '\'' +
+			", processInstanceId='" + processInstanceId + '\'' +
+			", processName='" + processName + '\'' +
+			", processDefinitionName='" + processDefinitionName + '\'' +
+			", executionId='" + executionId + '\'' +
+			", taskId='" + taskId + '\'' +
+			", calledProcessInstanceId='" + calledProcessInstanceId + '\'' +
+			", assignee='" + assignee + '\'' +
+			", assigneeName='" + assigneeName + '\'' +
+			", startTime=" + startTime +
+			", endTime=" + endTime +
+			", durationInMillis=" + durationInMillis +
+			", deleteReason='" + deleteReason + '\'' +
+			", tenantId='" + tenantId + '\'' +
+			", description='" + description + '\'' +
+			", variablesMap=" + variablesMap +
+			", linkBusinessOids=" + linkBusinessOids +
+			", displayUrl='" + displayUrl + '\'' +
+			", btmType='" + btmType + '\'' +
+			'}';
+	}
+}
diff --git a/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/business/feign/FlowClient.java b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/business/feign/FlowClient.java
index d093953..e79076e 100644
--- a/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/business/feign/FlowClient.java
+++ b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/business/feign/FlowClient.java
@@ -16,9 +16,12 @@
  */
 package com.vci.ubcs.flow.business.feign;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.vci.ubcs.flow.core.entity.BladeFlow;
+import com.vci.ubcs.flow.core.entity.ProcessTemplate;
 import com.vci.ubcs.flow.core.feign.IFlowClient;
 import com.vci.ubcs.flow.core.utils.TaskUtil;
+import com.vci.ubcs.flow.engine.service.ProcessTemplateService;
 import lombok.AllArgsConstructor;
 import org.flowable.engine.IdentityService;
 import org.flowable.engine.RuntimeService;
@@ -34,6 +37,7 @@
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -49,6 +53,7 @@
 	private final RuntimeService runtimeService;
 	private final IdentityService identityService;
 	private final TaskService taskService;
+	private final ProcessTemplateService processTemplateService;
 
 	@Override
 	@PostMapping(START_PROCESS_INSTANCE_BY_ID)
@@ -104,4 +109,33 @@
 		return R.data(taskService.getVariables(taskId));
 	}
 
+
+	/**
+	 * 鏌ヨ鏁版嵁wrapper鏂瑰紡
+	 *
+	 * @param wrapperMap 鏉′欢
+	 * @return R
+	 */
+	@Override
+	@PostMapping(SELECT_BY_WRAPPER)
+	public R<List<ProcessTemplate>> selectByWrapper(@RequestBody Map<String,Object> wrapperMap){
+		return R.data(processTemplateService.listByMap(wrapperMap));
+	}
+
+	/**
+	 * 鎵归噺淇濆瓨娴佺▼鏁版嵁
+	 *
+	 * @param listProcessTemplate 淇濆瓨鏁版嵁
+	 * @return R
+	 */
+	@Override
+	@PostMapping(PROCESS_BATCH_SAVE)
+	public R processBatchSave(@RequestBody List<ProcessTemplate> listProcessTemplate) {
+		if(listProcessTemplate.size() == 0){
+			return R.fail("涓轰紶鍏ユ暟鎹紝璇锋鏌ワ紒");
+		}
+		boolean b = processTemplateService.saveBatch(listProcessTemplate);
+		return R.data(b);
+	}
+
 }
diff --git a/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/constant/FlowEngineConstant.java b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/constant/FlowEngineConstant.java
index 509b0b9..5750d2b 100644
--- a/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/constant/FlowEngineConstant.java
+++ b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/constant/FlowEngineConstant.java
@@ -51,4 +51,24 @@
 
 	String USR_TASK = "userTask";
 
+	/**
+	 * 鐘舵�佸��
+	 */
+	String STATUS_VALUE = "statusValue";
+
+	/**
+	 * 杩滅▼璋冪敤鐨勫湴鍧�
+	 */
+	String REMOTE_METHOD = "remoteMethod";
+
+	/**
+	 * 涓婚敭
+	 */
+	String OIDS = "oids";
+
+	/**
+	 * 涓氬姟绫诲瀷
+	 */
+	String BTMTYPE = "btmtype";
+
 }
diff --git a/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/envent/FlowStatusListener.java b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/envent/FlowStatusListener.java
new file mode 100644
index 0000000..f932e49
--- /dev/null
+++ b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/envent/FlowStatusListener.java
@@ -0,0 +1,123 @@
+package com.vci.ubcs.flow.engine.envent;
+
+import com.vci.ubcs.flow.core.constant.ProcessConstant;
+import com.vci.ubcs.flow.core.dto.FlowStatusDTO;
+import com.vci.ubcs.flow.engine.constant.FlowEngineConstant;
+import com.vci.ubcs.flow.engine.utils.FlowableUtils;
+import com.vci.ubcs.starter.exception.VciBaseException;
+import com.vci.ubcs.starter.web.util.LangBaseUtil;
+import com.vci.ubcs.starter.web.util.VciBaseUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.TaskService;
+import org.flowable.engine.delegate.TaskListener;
+import org.flowable.engine.impl.el.FixedValue;
+import org.flowable.task.service.delegate.DelegateTask;
+import org.springblade.core.jwt.JwtUtil;
+import org.springblade.core.launch.constant.TokenConstant;
+import org.springblade.core.tool.utils.WebUtil;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+
+@Slf4j
+@Component
+public class FlowStatusListener implements TaskListener, ApplicationContextAware {
+
+	/**
+	 * 杩滅▼璋冪敤鍦板潃銆傚垏璁帮細鍚嶇О瑕佷笌娴佺▼涓畾涔夌殑涓�鏍�
+	 */
+	private FixedValue remoteMethod;
+
+	/**
+	 * 鐘舵�佸�笺�傚垏璁帮細鍚嶇О瑕佷笌娴佺▼涓畾涔夌殑涓�鏍�
+	 */
+	private FixedValue statusValue;
+
+	private static  ApplicationContext applicationContext;
+
+	@Override
+	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
+		applicationContext = arg0;
+	}
+
+	@Override
+	public void notify(DelegateTask delegateTask) {
+		Map taskVariable = delegateTask.getVariables();
+		boolean pass = (boolean) taskVariable.get(ProcessConstant.PASS_KEY);
+
+		//鑾峰彇鐘舵�佷慨鏀逛俊鎭�
+		if(pass){
+			String restURL = remoteMethod.getExpressionText();
+			String status = statusValue.getExpressionText();
+			//鑾峰彇涓氬姟鏁版嵁淇℃伅
+			String oids = (String) taskVariable.get(FlowEngineConstant.OIDS);
+			String btmType = (String) taskVariable.get(FlowEngineConstant.BTMTYPE);
+
+			taskVariable.put(FlowEngineConstant.REMOTE_METHOD,restURL);
+			taskVariable.put(FlowEngineConstant.STATUS_VALUE,status);
+
+			if(StringUtils.isEmpty(oids)){
+				throw new VciBaseException("鎵ц鐘舵�佷慨鏀逛簨浠舵椂锛屼笟鍔℃暟鎹畂id涓虹┖锛�");
+			}
+			if(StringUtils.isEmpty(btmType)){
+				throw new VciBaseException("鎵ц鐘舵�佷慨鏀逛簨浠舵椂锛屼笟鍔$被鍨媌tmType涓虹┖锛�");
+			}
+			if(StringUtils.isEmpty(restURL)){
+				throw new VciBaseException("鎵ц鐘舵�佷慨鏀逛簨浠舵椂锛岃繙绋嬭皟鐢ㄥ湴鍧�涓虹┖锛�");
+			}
+			if(StringUtils.isEmpty(status)){
+				throw new VciBaseException("鎵ц鐘舵�佷慨鏀逛簨浠舵椂锛岀姸鎬佷负绌猴紒");
+			}
+
+			HistoryService historyService = applicationContext.getBean(HistoryService.class);
+			TaskService taskService = applicationContext.getBean(TaskService.class);
+
+			FlowStatusDTO flowStatusDTO = new FlowStatusDTO();
+			flowStatusDTO.setBtmType(btmType);
+			flowStatusDTO.setOids(VciBaseUtil.str2List(oids));
+			flowStatusDTO.setVariableMap(taskVariable);
+			flowStatusDTO.setTaskHisVOList(FlowableUtils.listTaskHistory(delegateTask.getProcessInstanceId(),historyService,taskService));
+
+			String token = JwtUtil.getToken(WebUtil.getRequest().getHeader(TokenConstant.HEADER));
+
+			HttpComponentsClientHttpRequestFactory requestFactory=new HttpComponentsClientHttpRequestFactory();
+			requestFactory.setReadTimeout(300000);
+			requestFactory.setConnectionRequestTimeout(300000);
+			requestFactory.setConnectTimeout(300000);
+			RestTemplate restTemplate = new RestTemplate(requestFactory);
+			HttpHeaders headers = new HttpHeaders();
+			headers.add(TokenConstant.HEADER,token);
+			headers.setContentType(MediaType.APPLICATION_JSON);
+			HttpEntity httpEntity = new HttpEntity<>(flowStatusDTO,headers);
+			Map<String, Object> result = null;
+			try {
+				result = restTemplate.postForObject(restURL, httpEntity, Map.class);
+			} catch (HttpClientErrorException e) {
+				throw new VciBaseException(LangBaseUtil.getErrorMsg(e),new String[]{},e);
+			}catch (Throwable e){
+				throw new VciBaseException(LangBaseUtil.getErrorMsg(e),new String[]{},e);
+			}
+			if(result == null){
+				throw new VciBaseException("涓氬姟浜嬩欢鏃跺�欐病鏈夎繑鍥炲�硷紝涓嶇‘瀹氭槸鍚︽墽琛屾垚鍔�");
+			}
+			if(CollectionUtils.isEmpty(result) && !(Boolean) result.get("success")){
+				throw new VciBaseException((String) result.get("message"));
+			}
+
+		}
+	}
+
+
+}
diff --git a/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/utils/FlowableUtils.java b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/utils/FlowableUtils.java
new file mode 100644
index 0000000..087c43d
--- /dev/null
+++ b/Source/UBCS/ubcs-ops/ubcs-flow/src/main/java/com/vci/ubcs/flow/engine/utils/FlowableUtils.java
@@ -0,0 +1,727 @@
+package com.vci.ubcs.flow.engine.utils;
+
+import com.vci.ubcs.flow.core.utils.TaskUtil;
+import com.vci.ubcs.flow.core.vo.FlowTaskHisVO;
+import com.vci.ubcs.flow.engine.constant.FlowEngineConstant;
+import com.vci.ubcs.starter.exception.VciBaseException;
+import com.vci.ubcs.starter.web.util.VciBaseUtil;
+import com.vci.ubcs.system.user.cache.UserCache;
+import com.vci.ubcs.system.user.entity.User;
+import com.vci.ubcs.system.user.vo.UserVO;
+import org.apache.commons.lang3.StringUtils;
+import org.flowable.bpmn.model.*;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.TaskService;
+import org.flowable.engine.history.HistoricActivityInstance;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
+import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
+import org.flowable.engine.task.Comment;
+import org.flowable.variable.api.history.HistoricVariableInstance;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author weidy
+ * @date 2021/4/2
+ */
+public class FlowableUtils {
+    /**
+     * 鏍规嵁鑺傜偣锛岃幏鍙栧叆鍙h繛绾�
+     * @param source 鑺傜偣
+     * @return 鍖呭惈鐨勭嚎
+     */
+    public static List<SequenceFlow> getElementIncomingFlows(FlowElement source) {
+        List<SequenceFlow> sequenceFlows = null;
+        if (source instanceof Task) {
+            sequenceFlows = ((Task) source).getIncomingFlows();
+        } else if (source instanceof Gateway) {
+            sequenceFlows = ((Gateway) source).getIncomingFlows();
+        } else if (source instanceof SubProcess) {
+            sequenceFlows = ((SubProcess) source).getIncomingFlows();
+        } else if (source instanceof StartEvent) {
+            sequenceFlows = ((StartEvent) source).getIncomingFlows();
+        } else if (source instanceof EndEvent) {
+            sequenceFlows = ((EndEvent) source).getIncomingFlows();
+        }
+        return sequenceFlows;
+    }
+
+    /**
+     * 鏍规嵁鑺傜偣锛岃幏鍙栧嚭鍙h繛绾�
+     * @param source 鑺傜偣
+     * @return 鍑哄彛鐨勭嚎
+     */
+    public static List<SequenceFlow> getElementOutgoingFlows(FlowElement source) {
+        List<SequenceFlow> sequenceFlows = null;
+        if (source instanceof Task) {
+            sequenceFlows = ((Task) source).getOutgoingFlows();
+        } else if (source instanceof Gateway) {
+            sequenceFlows = ((Gateway) source).getOutgoingFlows();
+        } else if (source instanceof SubProcess) {
+            sequenceFlows = ((SubProcess) source).getOutgoingFlows();
+        } else if (source instanceof StartEvent) {
+            sequenceFlows = ((StartEvent) source).getOutgoingFlows();
+        } else if (source instanceof EndEvent) {
+            sequenceFlows = ((EndEvent) source).getOutgoingFlows();
+        }
+        return sequenceFlows;
+    }
+
+    /**
+     * 鑾峰彇鍏ㄩ儴鑺傜偣鍒楄〃锛屽寘鍚瓙娴佺▼鑺傜偣
+     * @param flowElements 鑺傜偣
+     * @param allElements 鎵�鏈夌殑鑺傜偣
+     * @return 鑺傜偣鐨勫唴瀹�
+     */
+    public static Collection<FlowElement> getAllElements(Collection<FlowElement> flowElements, Collection<FlowElement> allElements) {
+        allElements = allElements == null ? new ArrayList<>() : allElements;
+
+        for (FlowElement flowElement : flowElements) {
+            allElements.add(flowElement);
+            if (flowElement instanceof SubProcess) {
+                // 缁х画娣卞叆瀛愭祦绋嬶紝杩涗竴姝ヨ幏鍙栧瓙娴佺▼
+                allElements = FlowableUtils.getAllElements(((SubProcess) flowElement).getFlowElements(), allElements);
+            }
+        }
+        return allElements;
+    }
+
+    /**
+     * 杩唬鑾峰彇鐖剁骇浠诲姟鑺傜偣鍒楄〃锛屽悜鍓嶆壘
+     * @param source 璧峰鑺傜偣
+     * @param hasSequenceFlow 宸茬粡缁忚繃鐨勮繛绾跨殑 ID锛岀敤浜庡垽鏂嚎璺槸鍚﹂噸澶�
+     * @param userTaskList 宸叉壘鍒扮殑鐢ㄦ埛浠诲姟鑺傜偣
+     * @return
+     */
+    public static List<UserTask> iteratorFindParentUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
+        userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList;
+        hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
+
+        // 濡傛灉璇ヨ妭鐐逛负寮�濮嬭妭鐐癸紝涓斿瓨鍦ㄤ笂绾у瓙鑺傜偣锛屽垯椤虹潃涓婄骇瀛愯妭鐐圭户缁凯浠�
+        if (source instanceof StartEvent && source.getSubProcess() != null) {
+            userTaskList = iteratorFindParentUserTasks(source.getSubProcess(), hasSequenceFlow, userTaskList);
+        }
+
+        // 鏍规嵁绫诲瀷锛岃幏鍙栧叆鍙h繛绾�
+        List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
+
+        if (sequenceFlows != null) {
+            // 寰幆鎵惧埌鐩爣鍏冪礌
+            for (SequenceFlow sequenceFlow: sequenceFlows) {
+                // 濡傛灉鍙戠幇杩炵嚎閲嶅锛岃鏄庡惊鐜簡锛岃烦杩囪繖涓惊鐜�
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                // 娣诲姞宸茬粡璧拌繃鐨勮繛绾�
+                hasSequenceFlow.add(sequenceFlow.getId());
+                // 绫诲瀷涓虹敤鎴疯妭鐐癸紝鍒欐柊澧炵埗绾ц妭鐐�
+                if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
+                    userTaskList.add((UserTask) sequenceFlow.getSourceFlowElement());
+                    continue;
+                }
+                // 绫诲瀷涓哄瓙娴佺▼锛屽垯娣诲姞瀛愭祦绋嬪紑濮嬭妭鐐瑰嚭鍙e鐩歌繛鐨勮妭鐐�
+                if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) {
+                    // 鑾峰彇瀛愭祦绋嬬敤鎴蜂换鍔¤妭鐐�
+                    List<UserTask> childUserTaskList = findChildProcessUserTasks((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, null);
+                    // 濡傛灉鎵惧埌鑺傜偣锛屽垯璇存槑璇ョ嚎璺壘鍒拌妭鐐癸紝涓嶇户缁悜涓嬫壘锛屽弽涔嬬户缁�
+                    if (childUserTaskList != null && childUserTaskList.size() > 0) {
+                        userTaskList.addAll(childUserTaskList);
+                        continue;
+                    }
+                }
+                // 缁х画杩唬
+                // 娉ㄦ剰锛氬凡缁忕粡杩囩殑鑺傜偣涓庤繛绾块兘搴旇鐢ㄦ祬鎷疯礉鍑烘潵鐨勫璞�
+                // 姣斿鍒嗘敮锛歛->b->c涓巃->d->c锛岃蛋瀹宎->b->c鍚庤蛋鍙︿竴涓矾绾挎槸锛屽凡缁忕粡杩囩殑鑺傜偣搴旇涓嶅寘鍚玜->b->c璺嚎鐨勬暟鎹�
+                userTaskList = iteratorFindParentUserTasks(sequenceFlow.getSourceFlowElement(), new HashSet<>(hasSequenceFlow), userTaskList);
+            }
+        }
+        return userTaskList;
+    }
+
+    /**
+     * 鏍规嵁姝e湪杩愯鐨勪换鍔¤妭鐐癸紝杩唬鑾峰彇瀛愮骇浠诲姟鑺傜偣鍒楄〃锛屽悜鍚庢壘
+     * @param source 璧峰鑺傜偣
+     * @param runActiveIdList 姝e湪杩愯鐨勪换鍔� Key锛岀敤浜庢牎楠屼换鍔¤妭鐐规槸鍚︽槸姝e湪杩愯鐨勮妭鐐�
+     * @param hasSequenceFlow 宸茬粡缁忚繃鐨勮繛绾跨殑 ID锛岀敤浜庡垽鏂嚎璺槸鍚﹂噸澶�
+     * @param flowElementList 闇�瑕佹挙鍥炵殑鐢ㄦ埛浠诲姟鍒楄〃
+     * @return 鑺傜偣鐨勪俊鎭�
+     */
+    public static List<FlowElement> iteratorFindChildUserTasks(FlowElement source, List<String> runActiveIdList, Set<String> hasSequenceFlow, List<FlowElement> flowElementList) {
+        hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
+        flowElementList = flowElementList == null ? new ArrayList<>() : flowElementList;
+
+        // 濡傛灉璇ヨ妭鐐逛负寮�濮嬭妭鐐癸紝涓斿瓨鍦ㄤ笂绾у瓙鑺傜偣锛屽垯椤虹潃涓婄骇瀛愯妭鐐圭户缁凯浠�
+        if (source instanceof EndEvent && source.getSubProcess() != null) {
+            flowElementList = iteratorFindChildUserTasks(source.getSubProcess(), runActiveIdList, hasSequenceFlow, flowElementList);
+        }
+
+        // 鏍规嵁绫诲瀷锛岃幏鍙栧嚭鍙h繛绾�
+        List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
+
+        if (sequenceFlows != null) {
+            // 寰幆鎵惧埌鐩爣鍏冪礌
+            for (SequenceFlow sequenceFlow: sequenceFlows) {
+                // 濡傛灉鍙戠幇杩炵嚎閲嶅锛岃鏄庡惊鐜簡锛岃烦杩囪繖涓惊鐜�
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                // 娣诲姞宸茬粡璧拌繃鐨勮繛绾�
+                hasSequenceFlow.add(sequenceFlow.getId());
+                // 濡傛灉涓虹敤鎴蜂换鍔$被鍨嬶紝鎴栬�呬负缃戝叧
+                // 娲诲姩鑺傜偣ID 鍦ㄨ繍琛岀殑浠诲姟涓瓨鍦紝娣诲姞
+                if ((sequenceFlow.getTargetFlowElement() instanceof UserTask || sequenceFlow.getTargetFlowElement() instanceof Gateway) && runActiveIdList.contains((sequenceFlow.getTargetFlowElement()).getId())) {
+                    flowElementList.add(sequenceFlow.getTargetFlowElement());
+                    continue;
+                }
+                // 濡傛灉鑺傜偣涓哄瓙娴佺▼鑺傜偣鎯呭喌锛屽垯浠庤妭鐐逛腑鐨勭涓�涓妭鐐瑰紑濮嬭幏鍙�
+                if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
+                    List<FlowElement> childUserTaskList = iteratorFindChildUserTasks((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), runActiveIdList, hasSequenceFlow, null);
+                    // 濡傛灉鎵惧埌鑺傜偣锛屽垯璇存槑璇ョ嚎璺壘鍒拌妭鐐癸紝涓嶇户缁悜涓嬫壘锛屽弽涔嬬户缁�
+                    if (childUserTaskList != null && childUserTaskList.size() > 0) {
+                        flowElementList.addAll(childUserTaskList);
+                        continue;
+                    }
+                }
+                // 缁х画杩唬
+                // 娉ㄦ剰锛氬凡缁忕粡杩囩殑鑺傜偣涓庤繛绾块兘搴旇鐢ㄦ祬鎷疯礉鍑烘潵鐨勫璞�
+                // 姣斿鍒嗘敮锛歛->b->c涓巃->d->c锛岃蛋瀹宎->b->c鍚庤蛋鍙︿竴涓矾绾挎槸锛屽凡缁忕粡杩囩殑鑺傜偣搴旇涓嶅寘鍚玜->b->c璺嚎鐨勬暟鎹�
+                flowElementList = iteratorFindChildUserTasks(sequenceFlow.getTargetFlowElement(), runActiveIdList, new HashSet<>(hasSequenceFlow), flowElementList);
+            }
+        }
+        return flowElementList;
+    }
+
+    /**
+     * 杩唬鑾峰彇瀛愭祦绋嬬敤鎴蜂换鍔¤妭鐐�
+     * @param source 璧峰鑺傜偣
+     * @param hasSequenceFlow 宸茬粡缁忚繃鐨勮繛绾跨殑 ID锛岀敤浜庡垽鏂嚎璺槸鍚﹂噸澶�
+     * @param userTaskList 闇�瑕佹挙鍥炵殑鐢ㄦ埛浠诲姟鍒楄〃
+     * @return 浠诲姟
+     */
+    public static List<UserTask> findChildProcessUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
+        hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
+        userTaskList = userTaskList == null ? new ArrayList<>() : userTaskList;
+
+        // 鏍规嵁绫诲瀷锛岃幏鍙栧嚭鍙h繛绾�
+        List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
+
+        if (sequenceFlows != null) {
+            // 寰幆鎵惧埌鐩爣鍏冪礌
+            for (SequenceFlow sequenceFlow: sequenceFlows) {
+                // 濡傛灉鍙戠幇杩炵嚎閲嶅锛岃鏄庡惊鐜簡锛岃烦杩囪繖涓惊鐜�
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                // 娣诲姞宸茬粡璧拌繃鐨勮繛绾�
+                hasSequenceFlow.add(sequenceFlow.getId());
+                // 濡傛灉涓虹敤鎴蜂换鍔$被鍨嬶紝涓斾换鍔¤妭鐐圭殑 Key 姝e湪杩愯鐨勪换鍔′腑瀛樺湪锛屾坊鍔�
+                if (sequenceFlow.getTargetFlowElement() instanceof UserTask) {
+                    userTaskList.add((UserTask) sequenceFlow.getTargetFlowElement());
+                    continue;
+                }
+                // 濡傛灉鑺傜偣涓哄瓙娴佺▼鑺傜偣鎯呭喌锛屽垯浠庤妭鐐逛腑鐨勭涓�涓妭鐐瑰紑濮嬭幏鍙�
+                if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
+                    List<UserTask> childUserTaskList = findChildProcessUserTasks((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, null);
+                    // 濡傛灉鎵惧埌鑺傜偣锛屽垯璇存槑璇ョ嚎璺壘鍒拌妭鐐癸紝涓嶇户缁悜涓嬫壘锛屽弽涔嬬户缁�
+                    if (childUserTaskList != null && childUserTaskList.size() > 0) {
+                        userTaskList.addAll(childUserTaskList);
+                        continue;
+                    }
+                }
+                // 缁х画杩唬
+                // 娉ㄦ剰锛氬凡缁忕粡杩囩殑鑺傜偣涓庤繛绾块兘搴旇鐢ㄦ祬鎷疯礉鍑烘潵鐨勫璞�
+                // 姣斿鍒嗘敮锛歛->b->c涓巃->d->c锛岃蛋瀹宎->b->c鍚庤蛋鍙︿竴涓矾绾挎槸锛屽凡缁忕粡杩囩殑鑺傜偣搴旇涓嶅寘鍚玜->b->c璺嚎鐨勬暟鎹�
+                userTaskList = findChildProcessUserTasks(sequenceFlow.getTargetFlowElement(), new HashSet<>(hasSequenceFlow), userTaskList);
+            }
+        }
+        return userTaskList;
+    }
+
+    /**
+     * 浠庡悗鍚戝墠瀵昏矾锛岃幏鍙栨墍鏈夎剰绾胯矾涓婄殑鐐�
+     * @param source 璧峰鑺傜偣
+     * @param passRoads 宸茬粡缁忚繃鐨勭偣闆嗗悎
+     * @param hasSequenceFlow 宸茬粡缁忚繃鐨勮繛绾跨殑 ID锛岀敤浜庡垽鏂嚎璺槸鍚﹂噸澶�
+     * @param targets 鐩爣鑴忕嚎璺粓鐐�
+     * @param dirtyRoads 纭畾涓鸿剰鏁版嵁鐨勭偣锛屽洜涓轰笉闇�瑕侀噸澶嶏紝鍥犳浣跨敤 set 瀛樺偍
+     * @return 璺嚎
+     */
+    public static Set<String> iteratorFindDirtyRoads(FlowElement source, List<String> passRoads, Set<String> hasSequenceFlow, List<String> targets, Set<String> dirtyRoads) {
+        passRoads = passRoads == null ? new ArrayList<>() : passRoads;
+        dirtyRoads = dirtyRoads == null ? new HashSet<>() : dirtyRoads;
+        hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
+
+        // 濡傛灉璇ヨ妭鐐逛负寮�濮嬭妭鐐癸紝涓斿瓨鍦ㄤ笂绾у瓙鑺傜偣锛屽垯椤虹潃涓婄骇瀛愯妭鐐圭户缁凯浠�
+        if (source instanceof StartEvent && source.getSubProcess() != null) {
+            dirtyRoads = iteratorFindDirtyRoads(source.getSubProcess(), passRoads, hasSequenceFlow, targets, dirtyRoads);
+        }
+
+        // 鏍规嵁绫诲瀷锛岃幏鍙栧叆鍙h繛绾�
+        List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
+
+        if (sequenceFlows != null) {
+            // 寰幆鎵惧埌鐩爣鍏冪礌
+            for (SequenceFlow sequenceFlow: sequenceFlows) {
+                // 濡傛灉鍙戠幇杩炵嚎閲嶅锛岃鏄庡惊鐜簡锛岃烦杩囪繖涓惊鐜�
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                // 娣诲姞宸茬粡璧拌繃鐨勮繛绾�
+                hasSequenceFlow.add(sequenceFlow.getId());
+                // 鏂板缁忚繃鐨勮矾绾�
+                passRoads.add(sequenceFlow.getSourceFlowElement().getId());
+                // 濡傛灉姝ょ偣涓虹洰鏍囩偣锛岀‘瀹氱粡杩囩殑璺嚎涓鸿剰绾胯矾锛屾坊鍔犵偣鍒拌剰绾胯矾涓紝鐒跺悗鎵句笅涓繛绾�
+                if (targets.contains(sequenceFlow.getSourceFlowElement().getId())) {
+                    dirtyRoads.addAll(passRoads);
+                    continue;
+                }
+                // 濡傛灉璇ヨ妭鐐逛负寮�濮嬭妭鐐癸紝涓斿瓨鍦ㄤ笂绾у瓙鑺傜偣锛屽垯椤虹潃涓婄骇瀛愯妭鐐圭户缁凯浠�
+                if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) {
+                    dirtyRoads = findChildProcessAllDirtyRoad((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, dirtyRoads);
+                    // 鏄惁瀛樺湪瀛愭祦绋嬩笂锛宼rue 鏄紝false 鍚�
+                    Boolean isInChildProcess = dirtyTargetInChildProcess((StartEvent) ((SubProcess) sequenceFlow.getSourceFlowElement()).getFlowElements().toArray()[0], null, targets, null);
+                    if (isInChildProcess) {
+                        // 宸插湪瀛愭祦绋嬩笂鎵惧埌锛岃璺嚎缁撴潫
+                        continue;
+                    }
+                }
+                // 缁х画杩唬
+                // 娉ㄦ剰锛氬凡缁忕粡杩囩殑鑺傜偣涓庤繛绾块兘搴旇鐢ㄦ祬鎷疯礉鍑烘潵鐨勫璞�
+                // 姣斿鍒嗘敮锛歛->b->c涓巃->d->c锛岃蛋瀹宎->b->c鍚庤蛋鍙︿竴涓矾绾挎槸锛屽凡缁忕粡杩囩殑鑺傜偣搴旇涓嶅寘鍚玜->b->c璺嚎鐨勬暟鎹�
+                dirtyRoads = iteratorFindDirtyRoads(sequenceFlow.getSourceFlowElement(), new ArrayList<>(passRoads), new HashSet<>(hasSequenceFlow), targets, dirtyRoads);
+            }
+        }
+        return dirtyRoads;
+    }
+
+    /**
+     * 杩唬鑾峰彇瀛愭祦绋嬭剰璺嚎
+     * 璇存槑锛屽亣濡傚洖閫�鐨勭偣灏辨槸瀛愭祦绋嬶紝閭d箞涔熻偗瀹氫細鍥為��鍒板瓙娴佺▼鏈�鍒濈殑鐢ㄦ埛浠诲姟鑺傜偣锛屽洜姝ゅ瓙娴佺▼涓殑鑺傜偣鍏ㄦ槸鑴忚矾绾�
+     * @param source 璧峰鑺傜偣
+     * @param hasSequenceFlow 宸茬粡缁忚繃鐨勮繛绾跨殑 ID锛岀敤浜庡垽鏂嚎璺槸鍚﹂噸澶�
+     * @param dirtyRoads 纭畾涓鸿剰鏁版嵁鐨勭偣锛屽洜涓轰笉闇�瑕侀噸澶嶏紝鍥犳浣跨敤 set 瀛樺偍
+     * @return 璺嚎
+     */
+    public static Set<String> findChildProcessAllDirtyRoad(FlowElement source, Set<String> hasSequenceFlow, Set<String> dirtyRoads) {
+        hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
+        dirtyRoads = dirtyRoads == null ? new HashSet<>() : dirtyRoads;
+
+        // 鏍规嵁绫诲瀷锛岃幏鍙栧嚭鍙h繛绾�
+        List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
+
+        if (sequenceFlows != null) {
+            // 寰幆鎵惧埌鐩爣鍏冪礌
+            for (SequenceFlow sequenceFlow: sequenceFlows) {
+                // 濡傛灉鍙戠幇杩炵嚎閲嶅锛岃鏄庡惊鐜簡锛岃烦杩囪繖涓惊鐜�
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                // 娣诲姞宸茬粡璧拌繃鐨勮繛绾�
+                hasSequenceFlow.add(sequenceFlow.getId());
+                // 娣诲姞鑴忚矾绾�
+                dirtyRoads.add(sequenceFlow.getTargetFlowElement().getId());
+                // 濡傛灉鑺傜偣涓哄瓙娴佺▼鑺傜偣鎯呭喌锛屽垯浠庤妭鐐逛腑鐨勭涓�涓妭鐐瑰紑濮嬭幏鍙�
+                if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
+                    dirtyRoads = findChildProcessAllDirtyRoad((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, dirtyRoads);
+                }
+                // 缁х画杩唬
+                // 娉ㄦ剰锛氬凡缁忕粡杩囩殑鑺傜偣涓庤繛绾块兘搴旇鐢ㄦ祬鎷疯礉鍑烘潵鐨勫璞�
+                // 姣斿鍒嗘敮锛歛->b->c涓巃->d->c锛岃蛋瀹宎->b->c鍚庤蛋鍙︿竴涓矾绾挎槸锛屽凡缁忕粡杩囩殑鑺傜偣搴旇涓嶅寘鍚玜->b->c璺嚎鐨勬暟鎹�
+                dirtyRoads = findChildProcessAllDirtyRoad(sequenceFlow.getTargetFlowElement(), new HashSet<>(hasSequenceFlow), dirtyRoads);
+            }
+        }
+        return dirtyRoads;
+    }
+
+    /**
+     * 鍒ゆ柇鑴忚矾绾跨粨鏉熻妭鐐规槸鍚﹀湪瀛愭祦绋嬩笂
+     * @param source 璧峰鑺傜偣
+     * @param hasSequenceFlow 宸茬粡缁忚繃鐨勮繛绾跨殑 ID锛岀敤浜庡垽鏂嚎璺槸鍚﹂噸澶�
+     * @param targets 鍒ゆ柇鑴忚矾绾胯妭鐐规槸鍚﹀瓨鍦ㄥ瓙娴佺▼涓婏紝鍙瀛樺湪涓�涓紝璇存槑鑴忚矾绾垮彧鍒板瓙娴佺▼涓烘
+     * @param inChildProcess 鏄惁瀛樺湪瀛愭祦绋嬩笂锛宼rue 鏄紝false 鍚�
+     * @return 鏄惁
+     */
+    public static Boolean dirtyTargetInChildProcess(FlowElement source, Set<String> hasSequenceFlow, List<String> targets, Boolean inChildProcess) {
+        hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
+        inChildProcess = inChildProcess == null ? false : inChildProcess;
+
+        // 鏍规嵁绫诲瀷锛岃幏鍙栧嚭鍙h繛绾�
+        List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
+
+        if (sequenceFlows != null && !inChildProcess) {
+            // 寰幆鎵惧埌鐩爣鍏冪礌
+            for (SequenceFlow sequenceFlow: sequenceFlows) {
+                // 濡傛灉鍙戠幇杩炵嚎閲嶅锛岃鏄庡惊鐜簡锛岃烦杩囪繖涓惊鐜�
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                // 娣诲姞宸茬粡璧拌繃鐨勮繛绾�
+                hasSequenceFlow.add(sequenceFlow.getId());
+                // 濡傛灉鍙戠幇鐩爣鐐瑰湪瀛愭祦绋嬩笂瀛樺湪锛岃鏄庡彧鍒板瓙娴佺▼涓烘
+                if (targets.contains(sequenceFlow.getTargetFlowElement().getId())) {
+                    inChildProcess = true;
+                    break;
+                }
+                // 濡傛灉鑺傜偣涓哄瓙娴佺▼鑺傜偣鎯呭喌锛屽垯浠庤妭鐐逛腑鐨勭涓�涓妭鐐瑰紑濮嬭幏鍙�
+                if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
+                    inChildProcess = dirtyTargetInChildProcess((FlowElement) (((SubProcess) sequenceFlow.getTargetFlowElement()).getFlowElements().toArray()[0]), hasSequenceFlow, targets, inChildProcess);
+                }
+                // 缁х画杩唬
+                // 娉ㄦ剰锛氬凡缁忕粡杩囩殑鑺傜偣涓庤繛绾块兘搴旇鐢ㄦ祬鎷疯礉鍑烘潵鐨勫璞�
+                // 姣斿鍒嗘敮锛歛->b->c涓巃->d->c锛岃蛋瀹宎->b->c鍚庤蛋鍙︿竴涓矾绾挎槸锛屽凡缁忕粡杩囩殑鑺傜偣搴旇涓嶅寘鍚玜->b->c璺嚎鐨勬暟鎹�
+                inChildProcess = dirtyTargetInChildProcess(sequenceFlow.getTargetFlowElement(), new HashSet<>(hasSequenceFlow), targets, inChildProcess);
+            }
+        }
+        return inChildProcess;
+    }
+
+    /**
+     * 杩唬浠庡悗鍚戝墠鎵弿锛屽垽鏂洰鏍囪妭鐐圭浉瀵逛簬褰撳墠鑺傜偣鏄惁鏄覆琛�
+     * 涓嶅瓨鍦ㄧ洿鎺ュ洖閫�鍒板瓙娴佺▼涓殑鎯呭喌锛屼絾瀛樺湪浠庡瓙娴佺▼鍑哄幓鍒扮埗娴佺▼鎯呭喌
+     * @param source 璧峰鑺傜偣
+     * @param isSequential 鏄惁涓茶
+     * @param hasSequenceFlow 宸茬粡缁忚繃鐨勮繛绾跨殑 ID锛岀敤浜庡垽鏂嚎璺槸鍚﹂噸澶�
+     * @param targetKsy 鐩爣鑺傜偣
+     * @return 鏄惁
+     */
+    public static Boolean iteratorCheckSequentialReferTarget(FlowElement source, String targetKsy, Set<String> hasSequenceFlow, Boolean isSequential) {
+        isSequential = isSequential == null ? true : isSequential;
+        hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
+
+        // 濡傛灉璇ヨ妭鐐逛负寮�濮嬭妭鐐癸紝涓斿瓨鍦ㄤ笂绾у瓙鑺傜偣锛屽垯椤虹潃涓婄骇瀛愯妭鐐圭户缁凯浠�
+        if (source instanceof StartEvent && source.getSubProcess() != null) {
+            isSequential = iteratorCheckSequentialReferTarget(source.getSubProcess(), targetKsy, hasSequenceFlow, isSequential);
+        }
+
+        // 鏍规嵁绫诲瀷锛岃幏鍙栧叆鍙h繛绾�
+        List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
+
+        if (sequenceFlows != null) {
+            // 寰幆鎵惧埌鐩爣鍏冪礌
+            for (SequenceFlow sequenceFlow: sequenceFlows) {
+                // 濡傛灉鍙戠幇杩炵嚎閲嶅锛岃鏄庡惊鐜簡锛岃烦杩囪繖涓惊鐜�
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                // 娣诲姞宸茬粡璧拌繃鐨勮繛绾�
+                hasSequenceFlow.add(sequenceFlow.getId());
+                // 濡傛灉鐩爣鑺傜偣宸茶鍒ゆ柇涓哄苟琛岋紝鍚庨潰閮戒笉闇�瑕佹墽琛岋紝鐩存帴杩斿洖
+                if (isSequential == false) {
+                    break;
+                }
+                // 杩欐潯绾胯矾瀛樺湪鐩爣鑺傜偣锛岃繖鏉$嚎璺畬鎴愶紝杩涘叆涓嬩釜绾胯矾
+                if (targetKsy.equals(sequenceFlow.getSourceFlowElement().getId())) {
+                    continue;
+                }
+                if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
+                    isSequential = false;
+                    break;
+                }
+                // 鍚﹀垯灏辩户缁凯浠�
+                // 娉ㄦ剰锛氬凡缁忕粡杩囩殑鑺傜偣涓庤繛绾块兘搴旇鐢ㄦ祬鎷疯礉鍑烘潵鐨勫璞�
+                // 姣斿鍒嗘敮锛歛->b->c涓巃->d->c锛岃蛋瀹宎->b->c鍚庤蛋鍙︿竴涓矾绾挎槸锛屽凡缁忕粡杩囩殑鑺傜偣搴旇涓嶅寘鍚玜->b->c璺嚎鐨勬暟鎹�
+                isSequential = iteratorCheckSequentialReferTarget(sequenceFlow.getSourceFlowElement(), targetKsy, new HashSet<>(hasSequenceFlow), isSequential);
+            }
+        }
+        return isSequential;
+    }
+
+    /**
+     * 浠庡悗鍚戝墠瀵昏矾锛岃幏鍙栧埌杈捐妭鐐圭殑鎵�鏈夎矾绾�
+     * 涓嶅瓨鍦ㄧ洿鎺ュ洖閫�鍒板瓙娴佺▼锛屼絾鏄瓨鍦ㄥ洖閫�鍒扮埗绾ф祦绋嬬殑鎯呭喌
+     * @param source 璧峰鑺傜偣
+     * @param passRoads 宸茬粡缁忚繃鐨勭偣闆嗗悎
+     * @param roads 璺嚎
+     * @return 浠诲姟
+     */
+    public static List<List<UserTask>> findRoad(FlowElement source, List<UserTask> passRoads, Set<String> hasSequenceFlow, List<List<UserTask>> roads) {
+        passRoads = passRoads == null ? new ArrayList<>() : passRoads;
+        roads = roads == null ? new ArrayList<>() : roads;
+        hasSequenceFlow = hasSequenceFlow == null ? new HashSet<>() : hasSequenceFlow;
+
+        // 濡傛灉璇ヨ妭鐐逛负寮�濮嬭妭鐐癸紝涓斿瓨鍦ㄤ笂绾у瓙鑺傜偣锛屽垯椤虹潃涓婄骇瀛愯妭鐐圭户缁凯浠�
+        if (source instanceof StartEvent && source.getSubProcess() != null) {
+            roads = findRoad(source.getSubProcess(), passRoads, hasSequenceFlow, roads);
+        }
+
+        // 鏍规嵁绫诲瀷锛岃幏鍙栧叆鍙h繛绾�
+        List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
+
+        if (sequenceFlows != null && sequenceFlows.size() != 0) {
+            for (SequenceFlow sequenceFlow: sequenceFlows) {
+                // 濡傛灉鍙戠幇杩炵嚎閲嶅锛岃鏄庡惊鐜簡锛岃烦杩囪繖涓惊鐜�
+                if (hasSequenceFlow.contains(sequenceFlow.getId())) {
+                    continue;
+                }
+                // 娣诲姞宸茬粡璧拌繃鐨勮繛绾�
+                hasSequenceFlow.add(sequenceFlow.getId());
+                // 娣诲姞缁忚繃璺嚎
+                if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
+                    passRoads.add((UserTask) sequenceFlow.getSourceFlowElement());
+                }
+                // 缁х画杩唬
+                // 娉ㄦ剰锛氬凡缁忕粡杩囩殑鑺傜偣涓庤繛绾块兘搴旇鐢ㄦ祬鎷疯礉鍑烘潵鐨勫璞�
+                // 姣斿鍒嗘敮锛歛->b->c涓巃->d->c锛岃蛋瀹宎->b->c鍚庤蛋鍙︿竴涓矾绾挎槸锛屽凡缁忕粡杩囩殑鑺傜偣搴旇涓嶅寘鍚玜->b->c璺嚎鐨勬暟鎹�
+                roads = findRoad(sequenceFlow.getSourceFlowElement(), new ArrayList<>(passRoads), new HashSet<>(hasSequenceFlow), roads);
+            }
+        } else {
+            // 娣诲姞璺嚎
+            roads.add(passRoads);
+        }
+        return roads;
+    }
+
+    /**
+     * 鍘嗗彶鑺傜偣鏁版嵁娓呮礂锛屾竻娲楁帀鍙堝洖婊氬鑷寸殑鑴忔暟鎹�
+     * @param allElements 鍏ㄩ儴鑺傜偣淇℃伅
+     * @param historicActivityIdList 鍘嗗彶浠诲姟瀹炰緥淇℃伅锛屾暟鎹噰鐢ㄥ紑濮嬫椂闂村崌搴�
+     * @return 鍘嗗彶鏁版嵁
+     */
+    public static List<String> historicTaskInstanceClean(Collection<FlowElement> allElements, List<HistoricActivityInstance> historicActivityIdList) {
+        // 浼氱鑺傜偣鏀堕泦
+        List<String> multiTask = new ArrayList<>();
+        allElements.forEach(flowElement -> {
+            if (flowElement instanceof UserTask) {
+                // 濡傛灉璇ヨ妭鐐圭殑琛屼负涓轰細绛捐涓猴紝璇存槑璇ヨ妭鐐逛负浼氱鑺傜偣
+                if (((UserTask) flowElement).getBehavior() instanceof ParallelMultiInstanceBehavior || ((UserTask) flowElement).getBehavior() instanceof SequentialMultiInstanceBehavior) {
+                    multiTask.add(flowElement.getId());
+                }
+            }
+        });
+        // 寰幆鏀惧叆鏍堬紝鏍� LIFO锛氬悗杩涘厛鍑�
+        Stack<HistoricActivityInstance> stack = new Stack<>();
+        historicActivityIdList.forEach(item -> stack.push(item));
+        // 娓呮礂鍚庣殑鍘嗗彶浠诲姟瀹炰緥
+        List<String> lastHistoricTaskInstanceList = new ArrayList<>();
+        // 缃戝叧瀛樺湪鍙兘鍙蛋浜嗛儴鍒嗗垎鏀儏鍐碉紝涓旇繕瀛樺湪璺宠浆搴熷純鏁版嵁浠ュ強鍏朵粬鍒嗘敮鏁版嵁鐨勫共鎵帮紝鍥犳闇�瑕佸鍘嗗彶鑺傜偣鏁版嵁杩涜娓呮礂
+        // 涓存椂鐢ㄦ埛浠诲姟 key
+        StringBuilder userTaskKey = null;
+        // 涓存椂琚垹鎺夌殑浠诲姟 key锛屽瓨鍦ㄥ苟琛屾儏鍐�
+        List<String> deleteKeyList = new ArrayList<>();
+        // 涓存椂鑴忔暟鎹嚎璺�
+        List<Set<String>> dirtyDataLineList = new ArrayList<>();
+        // 鐢辨煇涓偣璺冲埌浼氱鐐�,姝ゆ椂鍑虹幇澶氫釜浼氱瀹炰緥瀵瑰簲 1 涓烦杞儏鍐碉紝闇�瑕佹妸杩欎簺杩炵画鑴忔暟鎹兘鎵惧埌
+        // 浼氱鐗规畩澶勭悊涓嬫爣
+        int multiIndex = -1;
+        // 浼氱鐗规畩澶勭悊 key
+        StringBuilder multiKey = null;
+        // 浼氱鐗规畩澶勭悊鎿嶄綔鏍囪瘑
+        boolean multiOpera = false;
+        while (!stack.empty()) {
+            // 浠庤繖閲屽紑濮� userTaskKey 閮借繕鏄笂涓爤鐨� key
+            // 鏄惁鏄剰鏁版嵁绾胯矾涓婄殑鐐�
+            final boolean[] isDirtyData = {false};
+            for (Set<String> oldDirtyDataLine : dirtyDataLineList) {
+                if (oldDirtyDataLine.contains(stack.peek().getActivityId())) {
+                    isDirtyData[0] = true;
+                }
+            }
+            // 鍒犻櫎鍘熷洜涓嶄负绌猴紝璇存槑浠庤繖鏉℃暟鎹紑濮嬪洖璺虫垨鑰呭洖閫�鐨�
+            // MI_END锛氫細绛惧畬鎴愬悗锛屽叾浠栨湭绛惧埌鑺傜偣鐨勫垹闄ゅ師鍥狅紝涓嶅湪澶勭悊鑼冨洿鍐�
+            if (stack.peek().getDeleteReason() != null && !stack.peek().getDeleteReason().equals("MI_END")) {
+                // 鍙互鐞嗚В涓鸿剰绾胯矾璧风偣
+                String dirtyPoint = "";
+                if (stack.peek().getDeleteReason().indexOf("Change activity to ") >= 0) {
+                    dirtyPoint = stack.peek().getDeleteReason().replace("Change activity to ", "");
+                }
+                // 浼氱鍥為��鍒犻櫎鍘熷洜鏈夌偣涓嶅悓
+                if (stack.peek().getDeleteReason().indexOf("Change parent activity to ") >= 0) {
+                    dirtyPoint = stack.peek().getDeleteReason().replace("Change parent activity to ", "");
+                }
+                FlowElement dirtyTask = null;
+                // 鑾峰彇鍙樻洿鑺傜偣鐨勫搴旂殑鍏ュ彛澶勮繛绾�
+                // 濡傛灉鏄綉鍏冲苟琛屽洖閫�鎯呭喌锛屼細鍙樻垚涓ゆ潯鑴忔暟鎹矾绾匡紝鏁堟灉涓�鏍�
+                for (FlowElement flowElement : allElements) {
+                    if (flowElement.getId().equals(stack.peek().getActivityId())) {
+                        dirtyTask = flowElement;
+                    }
+                }
+                // 鑾峰彇鑴忔暟鎹嚎璺�
+                Set<String> dirtyDataLine = FlowableUtils.iteratorFindDirtyRoads(dirtyTask, null, null, Arrays.asList(dirtyPoint.split(",")), null);
+                // 鑷繁鏈韩涔熸槸鑴忕嚎璺笂鐨勭偣锛屽姞杩涘幓
+                dirtyDataLine.add(stack.peek().getActivityId());
+                //logger.info(stack.peek().getActivityId() + "鐐硅剰璺嚎闆嗗悎锛�" + dirtyDataLine);
+                // 鏄叏鏂扮殑闇�瑕佹坊鍔犵殑鑴忕嚎璺�
+                boolean isNewDirtyData = true;
+                for (int i = 0; i < dirtyDataLineList.size(); i++) {
+                    // 濡傛灉鍙戠幇浠栫殑涓婁釜鑺傜偣鍦ㄨ剰绾胯矾鍐咃紝璇存槑杩欎釜鐐瑰彲鑳芥槸骞惰鐨勮妭鐐癸紝鎴栬�呰繛缁┏鍥�
+                    // 杩欐椂锛岄兘浠ヤ箣鍓嶇殑鑴忕嚎璺妭鐐逛负鏍囧噯锛屽彧闇�鍚堝苟鑴忕嚎璺嵆鍙紝涔熷氨鏄矾绾胯ˉ鍏�
+                    if (dirtyDataLineList.get(i).contains(userTaskKey.toString())) {
+                        isNewDirtyData = false;
+                        dirtyDataLineList.get(i).addAll(dirtyDataLine);
+                    }
+                }
+                // 宸茬‘瀹氭椂鍏ㄦ柊鐨勮剰绾胯矾
+                if (isNewDirtyData) {
+                    // deleteKey 鍗曚竴璺嚎椹冲洖鍒板苟琛岋紝杩欑鍚屾椂鐢熸垚澶氫釜鏂板疄渚嬭褰曟儏鍐碉紝杩欐椂 deleteKey 鍏跺疄鏄敱澶氫釜鍊肩粍鎴�
+                    // 鎸夌収閫昏緫锛屽洖閫�鍚庣珛鍒荤敓鎴愮殑瀹炰緥璁板綍灏辨槸鍥為��鐨勮褰�
+                    // 鑷充簬椹冲洖鎵�鐢熸垚鐨� Key锛岀洿鎺ヤ粠鍒犻櫎鍘熷洜涓幏鍙栵紝鍥犱负瀛樺湪椹冲洖鍒板苟琛岀殑鎯呭喌
+                    deleteKeyList.add(dirtyPoint + ",");
+                    dirtyDataLineList.add(dirtyDataLine);
+                }
+                // 娣诲姞鍚庯紝鐜板湪杩欎釜鐐瑰彉鎴愯剰绾胯矾涓婄殑鐐逛簡
+                isDirtyData[0] = true;
+            }
+            // 濡傛灉涓嶆槸鑴忕嚎璺笂鐨勭偣锛岃鏄庢槸鏈夋晥鏁版嵁锛屾坊鍔犲巻鍙插疄渚� Key
+            if (!isDirtyData[0]) {
+                lastHistoricTaskInstanceList.add(stack.peek().getActivityId());
+            }
+            // 鏍¢獙鑴忕嚎璺槸鍚︾粨鏉�
+            for (int i = 0; i < deleteKeyList.size(); i ++) {
+                // 濡傛灉鍙戠幇鑴忔暟鎹睘浜庝細绛撅紝璁板綍涓嬩笅鏍囦笌瀵瑰簲 Key锛屼互澶囧悗缁瘮瀵癸紝浼氱鑴忔暟鎹寖鐣村紑濮�
+                if (multiKey == null && multiTask.contains(stack.peek().getActivityId())
+                        && deleteKeyList.get(i).contains(stack.peek().getActivityId())) {
+                    multiIndex = i;
+                    multiKey = new StringBuilder(stack.peek().getActivityId());
+                }
+                // 浼氱鑴忔暟鎹鐞嗭紝鑺傜偣閫�鍥炰細绛炬竻绌�
+                // 濡傛灉鍦ㄤ細绛捐剰鏁版嵁鑼冪暣涓彂鐜� Key鏀瑰彉锛岃鏄庝細绛捐剰鏁版嵁鍦ㄤ笂涓妭鐐瑰氨缁撴潫浜嗭紝鍙互鎶婁細绛捐剰鏁版嵁鍒犳帀
+                if (multiKey != null && !multiKey.toString().equals(stack.peek().getActivityId())) {
+                    deleteKeyList.set(multiIndex , deleteKeyList.get(multiIndex).replace(stack.peek().getActivityId() + ",", ""));
+                    multiKey = null;
+                    // 缁撴潫杩涜涓嬫牎楠屽垹闄�
+                    multiOpera = true;
+                }
+                // 鍏朵粬鑴忔暟鎹鐞�
+                // 鍙戠幇璇ヨ矾绾挎渶鍚庝竴鏉¤剰鏁版嵁锛岃鏄庤繖鏉¤剰鏁版嵁绾胯矾澶勭悊瀹屼簡锛屽垹闄よ剰鏁版嵁淇℃伅
+                // 鑴忔暟鎹骇鐢熺殑鏂板疄渚嬩腑鏄惁鍖呭惈杩欐潯鏁版嵁
+                if (multiKey == null && deleteKeyList.get(i).contains(stack.peek().getActivityId())) {
+                    // 鍒犻櫎鍖归厤鍒扮殑閮ㄥ垎
+                    deleteKeyList.set(i , deleteKeyList.get(i).replace(stack.peek().getActivityId() + ",", ""));
+                }
+                // 濡傛灉姣忕粍涓殑鍏冪礌閮戒互鍖归厤杩囷紝璇存槑鑴忔暟鎹粨鏉�
+                if ("".equals(deleteKeyList.get(i))) {
+                    // 鍚屾椂鍒犻櫎鑴忔暟鎹�
+                    deleteKeyList.remove(i);
+                    dirtyDataLineList.remove(i);
+                    break;
+                }
+            }
+            // 浼氱鏁版嵁澶勭悊闇�瑕佸湪寰幆澶栧鐞嗭紝鍚﹀垯鍙兘瀵艰嚧婧㈠嚭
+            // 浼氱鐨勬暟鎹偗瀹氭槸涔嬪墠鏀捐繘鍘荤殑鎵�浠ョ悊璁轰笂涓嶄細婧㈠嚭锛屼絾杩樻槸鏍¢獙涓�
+            if (multiOpera && deleteKeyList.size() > multiIndex && "".equals(deleteKeyList.get(multiIndex))) {
+                // 鍚屾椂鍒犻櫎鑴忔暟鎹�
+                deleteKeyList.remove(multiIndex);
+                dirtyDataLineList.remove(multiIndex);
+                multiIndex = -1;
+                multiOpera = false;
+            }
+            // pop() 鏂规硶涓� peek() 鏂规硶涓嶅悓锛屽湪杩斿洖鍊肩殑鍚屾椂锛屼細鎶婂�间粠鏍堜腑绉婚櫎
+            // 淇濆瓨鏂扮殑 userTaskKey 鍦ㄤ笅涓惊鐜腑浣跨敤
+            userTaskKey = new StringBuilder(stack.pop().getActivityId());
+        }
+        //logger.info("娓呮礂鍚庣殑鍘嗗彶鑺傜偣鏁版嵁锛�" + lastHistoricTaskInstanceList);
+        return lastHistoricTaskInstanceList;
+    }
+
+    /**
+     * 鑾峰彇鐩稿叧鐨勫巻鍙�
+     * @param processInstanceId 娴佺▼瀹炰緥鐨勪富閿�
+     * @param historyService 鍘嗗彶鏈嶅姟
+     * @param taskService 浠诲姟鏈嶅姟
+     * @return 鍘嗗彶鐨勪俊鎭�
+     */
+    public static List<FlowTaskHisVO> listTaskHistory(String processInstanceId, HistoryService historyService, TaskService taskService){
+        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
+        if(processInstance == null || StringUtils.isBlank(processInstance.getId())){
+            throw new VciBaseException("娴佺▼鏈壘鍒�");
+        }
+        List<HistoricActivityInstance> hisList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityType("userTask").orderByHistoricActivityInstanceEndTime().desc().list();
+        Map<String,FlowTaskHisVO> hisVOList = new HashMap<>();
+        if(!CollectionUtils.isEmpty(hisList)){
+            List<HistoricActivityInstance> allowTaskInstances = new ArrayList<>();
+            Map<String,List<Comment>> taskOidCommentsMap = new HashMap<>();
+            for(int i = 0 ; i < hisList.size(); i ++){
+                HistoricActivityInstance his = hisList.get(i);
+                //鎴戜滑鎵惧綋鏃剁殑瀹℃壒淇℃伅锛岃繖鏍峰彲浠ュ垽鏂槸鍚︿负涓嶅悓鎰�
+                List<Comment> comments = taskService.getTaskComments(his.getTaskId());
+                if(!CollectionUtils.isEmpty(comments)){
+                    taskOidCommentsMap.put(his.getId(),comments);
+                    //鏌ヨ
+                }//绗竴涓彲鑳芥病鏈�
+                allowTaskInstances.add(his);
+            }
+            if(!CollectionUtils.isEmpty(allowTaskInstances)){
+                List<HistoricVariableInstance> variableInstances = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();
+                Map<String,Object> variableMap = switchVariable(variableInstances);
+                Set<Long> userIds = new HashSet<>();
+                Set<String> processInstanceIds = new HashSet<>();
+                for(int i = 0 ; i < allowTaskInstances.size() ; i ++){
+                    HistoricActivityInstance activityInstance = allowTaskInstances.get(i);
+                    if(!hisVOList.containsKey(activityInstance.getId())) {
+                        FlowTaskHisVO hisVO = new FlowTaskHisVO();
+                        hisVO.setOid(activityInstance.getId());
+                        hisVO.setActivityId(activityInstance.getActivityId());
+                        hisVO.setActivityName(activityInstance.getActivityName());
+                        hisVO.setActivityType(activityInstance.getActivityType());
+                        hisVO.setProcessDefinitionId(activityInstance.getProcessDefinitionId());
+                        hisVO.setProcessInstanceId(activityInstance.getProcessInstanceId());
+                        hisVO.setExecutionId(activityInstance.getExecutionId());
+                        hisVO.setTaskId(activityInstance.getTaskId());
+                        hisVO.setCalledProcessInstanceId(activityInstance.getCalledProcessInstanceId());
+                        hisVO.setAssignee(activityInstance.getAssignee());
+                        if (StringUtils.isNotBlank(hisVO.getAssignee())) {
+                            userIds.add(TaskUtil.getUserId(hisVO.getAssignee()));
+                        }
+                        hisVO.setStartTime(activityInstance.getStartTime());
+                        hisVO.setEndTime(activityInstance.getEndTime());
+                        hisVO.setDurationInMillis(activityInstance.getDurationInMillis());
+                        hisVO.setDeleteReason(activityInstance.getDeleteReason());
+                        hisVO.setTenantId(activityInstance.getTenantId());
+                        hisVO.setVariablesMap(variableMap);
+                        hisVO.setBtmType(variableMap.getOrDefault(FlowEngineConstant.BTMTYPE,"").toString());
+                        hisVO.setLinkBusinessOids(VciBaseUtil.str2List(variableMap.getOrDefault(FlowEngineConstant.OIDS,"").toString()));
+                        List<Comment> comments = taskOidCommentsMap.getOrDefault(activityInstance.getId(),new ArrayList<>());
+                        hisVO.setDescription(comments.stream().map(s->{
+                            String fullMsg = s.getFullMessage();
+                            if(StringUtils.isNotBlank(fullMsg) && fullMsg.contains(":")){
+                                fullMsg = fullMsg.substring(fullMsg.indexOf(":")+1);
+                            }
+                            return fullMsg;
+                        }).collect(Collectors.joining(";")));
+                        processInstanceIds.add(activityInstance.getProcessInstanceId());
+                        hisVO.setProcessName(processInstance.getName());
+                        hisVO.setProcessDefinitionName(processInstance.getProcessDefinitionName());
+                        hisVOList.put(hisVO.getActivityId(), hisVO);
+                    }
+                }
+                if(!CollectionUtils.isEmpty(userIds) && !CollectionUtils.isEmpty(hisVOList)){
+					List<User> userList = new ArrayList<>();
+                    for(Long userId : userIds){
+						userList.add(UserCache.getUser(userId));
+					}
+                    if(!CollectionUtils.isEmpty(userList)){
+                        Map<Long, User> userVOMap = userList.stream().collect(Collectors.toMap(s -> s.getId(), t -> t, (o1, o2) -> o1));
+                        hisVOList.values().forEach(history->{
+                            List<String> thisUserIds = VciBaseUtil.str2List(TaskUtil.getTaskUser(history.getAssignee()));
+                            List<String> thisUserNames = new ArrayList<>();
+                            if(!CollectionUtils.isEmpty(thisUserIds)) {
+                                thisUserIds.forEach(userId -> {
+                                    thisUserNames.add(userVOMap.getOrDefault(userId, new User()).getName());
+                                });
+                            }
+                            history.setAssigneeName(thisUserNames.stream().collect(Collectors.joining(",")));
+                        });
+                    }
+                }
+            }
+        }
+        return hisVOList.values().stream().collect(Collectors.toList());
+    }
+
+    /**
+     * 杞崲鍙橀噺
+     * @param variableInstances 鍙橀噺鐨勫疄渚�
+     * @return 鍙橀噺
+     */
+    public static Map<String,Object> switchVariable(List<HistoricVariableInstance> variableInstances){
+        Map<String,Object> variableMap = new HashMap<>();
+        if(!CollectionUtils.isEmpty(variableInstances)){
+            variableMap = variableInstances.stream().collect(Collectors.toMap(s->s.getVariableName(),t->t.getValue() == null?"":t.getValue()));
+        }
+        return variableMap;
+    }
+}
diff --git a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/mapper/CodeClassifyMapper.java b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/mapper/CodeClassifyMapper.java
index 3772ae2..0a38d9b 100644
--- a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/mapper/CodeClassifyMapper.java
+++ b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/mapper/CodeClassifyMapper.java
@@ -148,4 +148,17 @@
 	 * @return
 	 */
 	List<CodeClassify>  selectAllParenClassifytByOid(@Param("oid")String oid,@Param("tenantId") String tenantId);
+
+	/**
+	 * 涓婚敭鏌ヨ褰撳墠鑺傜偣鍙婂叾瀛愯妭鐐�
+	 * @param oid 褰撳墠鑺傜偣涓婚敭
+	 * @return 鏌ヨ缁撴灉
+	 */
+    List<CodeClassify> selectStartWithCurrentOid(String oid);
+
+	/**
+	 * 鎵归噺鏇存柊鍒嗙被鐘舵��
+	 * @param classifyList
+	 */
+	void batchUpdateLcStatus(@Param("records") List<CodeClassify> classifyList);
 }
diff --git a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClassifyServiceImpl.java b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClassifyServiceImpl.java
index 6f1dbdf..a2ec15e 100644
--- a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClassifyServiceImpl.java
+++ b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClassifyServiceImpl.java
@@ -359,20 +359,32 @@
 	@Override
 	public R updateLcStatus(String oid, String lcStatus){
 
-		//鏌ヨ淇敼鍓峵s
-		CodeClassify codeClassify = codeClassifyMapper.selectById(oid);//涓昏鏄负浜嗘煡璇s
-		codeClassify.setLcStatus(lcStatus);
-		codeClassify.setTs(new Date());
-		codeClassify.setLastModifyTime(new Date());
-		codeClassify.setLastModifier(String.valueOf(AuthUtil.getUser().getUserId()));
+		List<CodeClassify> classifyList = codeClassifyMapper.selectStartWithCurrentOid(oid);
+		Date now = new Date();
+		String userId = String.valueOf(AuthUtil.getUserId());
+		classifyList = classifyList.stream().map(s -> {
+			s.setLcStatus(lcStatus);
+			s.setTs(now);
+			s.setLastModifier(userId);
+			s.setLastModifyTime(now);
+			return s;
+		}).collect(Collectors.toList());
+//		//鏌ヨ淇敼鍓峵s
+//		CodeClassify codeClassify = codeClassifyMapper.selectById(oid);//涓昏鏄负浜嗘煡璇s
+//		codeClassify.setLcStatus(lcStatus);
+//		codeClassify.setTs(new Date());
+//		codeClassify.setLastModifyTime(new Date());
+//		codeClassify.setLastModifier(String.valueOf(AuthUtil.getUser().getUserId()));
 		//鍚敤銆佸仠鐢�
 //		int u = codeClassifyMapper.updateLcStatus(oid,lcStatus);
-		int count = codeClassifyMapper.updateById(codeClassify);
+//		int count = codeClassifyMapper.updateById(codeClassify);
+		codeClassifyMapper.batchUpdateLcStatus(classifyList);
 //        //澶勭悊鏁版嵁闆嗘垚閫昏緫,鎴愬姛鍚庢墽琛岄泦鎴愮涓�姝�,鍒嗙被鏁版嵁鐗规畩澶勭悊銆�
 //        if(u!=0) {
 //            codeDuckingServiceI.insertCache1(lcStatus,lcStatus,DOCKING_DEFAULT_CLASSIFY, DOCKING_DEFAULT_CLASSIFYOID, oid, codeClassifyDO_old.getTs());
 //        }
-		return R.data(SqlHelper.retBool(count));
+//		return R.data(SqlHelper.retBool(count));
+		return R.success("");
 	}
 
 	/**
diff --git a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClstemplateServiceImpl.java b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClstemplateServiceImpl.java
index 6ff578d..80894c7 100644
--- a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClstemplateServiceImpl.java
+++ b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeClstemplateServiceImpl.java
@@ -31,6 +31,8 @@
 import com.vci.ubcs.code.service.ICodeClstemplateService;
 import com.vci.ubcs.code.vo.pagemodel.CodeClassifyTemplateAttrVO;
 import com.vci.ubcs.code.vo.pagemodel.CodeClassifyTemplateVO;
+import com.vci.ubcs.flow.core.entity.ProcessTemplate;
+import com.vci.ubcs.flow.core.feign.IFlowClient;
 import com.vci.ubcs.starter.exception.VciBaseException;
 import com.vci.ubcs.starter.revision.model.TreeQueryObject;
 import com.vci.ubcs.starter.revision.model.TreeWrapperOptions;
@@ -106,6 +108,8 @@
 	private CodeClassifyTemplateMapper codeClassifyTemplateMapper;
 	@Autowired(required = false)
 	private CodePhaseAttrServiceImpl codePhaseattrServiceImpl;
+	@Autowired(required = false)
+	private IFlowClient iFlowClient;
 
 	@Override
 	public IPage<CodeClassifyTemplateVO> selectPlCodeClstemplatePage(IPage<CodeClassifyTemplateVO> page, CodeClassifyTemplateVO plCodeClstemplate) {
@@ -545,7 +549,7 @@
 		}
 
 		//澶嶅埗妯℃澘娴佺▼
-		List<CodeClassifyProcessTemp>  codeClassifyProcessTempDOList = copyTemplateProcess(templateOldOid,templateNewOid);
+		List<ProcessTemplate>  codeClassifyProcessTempDOList = copyTemplateProcess(templateOldOid,templateNewOid);
 		//澶嶅埗妯℃澘闃舵锛岄樁娈靛睘鎬�
 		Map phase_attrMap = copyTemplatePhase_attr(templateOldOid,templateNewOid);
 
@@ -557,7 +561,7 @@
 
 		//淇濆瓨妯℃澘娴佺▼
 		if(!CollectionUtils.isEmpty(codeClassifyProcessTempDOList)) {
-			codeClsflowtempServiceImpl.saveBatch(codeClassifyProcessTempDOList);
+			iFlowClient.processBatchSave(codeClassifyProcessTempDOList);
 		}
 		//妯℃澘闃舵
 		if(!CollectionUtils.isEmpty(codeClassifyPhaseDOList)) {
@@ -619,7 +623,7 @@
 		List<CodeClassifyTemplateAttr> codeClassifyTemplateAttrDOList = copyTemplateAttr(oldOid,newOid);
 
 		//澶嶅埗妯℃澘娴佺▼
-		List<CodeClassifyProcessTemp> codeClassifyProcessTempDOList = copyTemplateProcess(oldOid,newOid);
+		List<ProcessTemplate> codeClassifyProcessTempDOList = copyTemplateProcess(oldOid,newOid);
 
 		//澶嶅埗妯℃澘闃舵锛岄樁娈靛睘鎬�
 		Map  phase_attrMap = copyTemplatePhase_attr(oldOid,newOid);
@@ -633,7 +637,7 @@
 //		baseMapper.insert(codeClassifyTemplateDOList);
 		this.saveBatch(codeClassifyTemplateDOList);
 		codeTempbuttonServiceImpl.saveBatch(codeClassifyTemplateButtonDOList);
-		codeClsflowtempServiceImpl.saveBatch(codeClassifyProcessTempDOList);
+		iFlowClient.processBatchSave(codeClassifyProcessTempDOList);
 		codeClstempattrService.saveBatch(codeClassifyTemplateAttrDOList);
 		codeTempphaseServiceImpl.saveBatch(codeClassifyPhaseDOList);
 		codePhaseattrServiceImpl.saveBatch(codePhaseAttrDOList);
@@ -696,22 +700,17 @@
 	/**
 	 * 澶嶅埗妯℃澘娴佺▼
 	 */
-	public List<CodeClassifyProcessTemp> copyTemplateProcess(String templateOldOid,String templateNewOid){
-//		VciQueryWrapperForDO processWrapper = new VciQueryWrapperForDO(CodeClassifyProcessTempDO.class);
-//		processWrapper.addQueryMap("classifyTemplateOid",templateOldOid);
-
-//		Map<String,Object> condition = new HashMap<>(1);
-//		condition.put("classifyTemplateOid",templateOldOid);
-		QueryWrapper<CodeClassifyProcessTemp> wrapper = new QueryWrapper<>();
-		wrapper.eq("classifyTemplateOid",templateOldOid);
-		List<CodeClassifyProcessTemp> codeClsflowtempEntities = codeClsflowtempServiceImpl.list(wrapper);
-//		List<CodeClassifyProcessTempDO>  codeClassifyProcessTempDOList = codeClassifyProcessTempDaoI.selectByWrapper(processWrapper);//瑕佷繚瀛樼殑鏂扮殑妯℃澘娴佺▼
-		for (CodeClassifyProcessTemp codeClassifyProcessTempDO:codeClsflowtempEntities){
-//			String newOid = VciBaseUtil.getPk();
-			codeClassifyProcessTempDO.setOid(null);
-			//codeClassifyProcessTempDO.setCodeClassifyOid(templateNewOid);
-			codeClassifyProcessTempDO.setClassifyTemplateOid(templateNewOid);
-//			codeClsflowtempMapper.insert(codeClassifyProcessTempDO);
+	public List<ProcessTemplate> copyTemplateProcess(String templateOldOid,String templateNewOid){
+		Map<String,Object> wrapperMap = new HashMap();
+		wrapperMap.put("template_id",templateOldOid);
+		R<List<ProcessTemplate>> listR = iFlowClient.selectByWrapper(wrapperMap);
+		if(!listR.isSuccess()){
+			throw new VciBaseException("鏌ヨ妯℃澘娴佺▼鏃跺嚭閿欙紝璇烽噸璇曪紒");
+		}
+		List<ProcessTemplate> codeClsflowtempEntities = listR.getData();
+		for (ProcessTemplate codeClassifyProcessTempDO:codeClsflowtempEntities){
+			codeClassifyProcessTempDO.setId(null);
+			codeClassifyProcessTempDO.setTemplateId(templateNewOid);
 			//modify by lihang - @20220406 璁剧疆妯℃澘涓婚敭浣嶇疆鍑洪敊锛屽鑷村崌鐗堢殑妯℃澘涓殑娴佺▼鏄┖鐨勩��
 		}
 		return codeClsflowtempEntities;
diff --git a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java
index 5871992..e6dcb80 100644
--- a/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java
+++ b/Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java
@@ -355,15 +355,10 @@
             throw new VciBaseException("鏈煡璇㈠埌鐩稿叧鏁版嵁銆�");
         }
         //杩橀渶瑕佷慨鏀筧llCode鐨勭敓鍛藉懆鏈�
-//		Map<String, String> conditionMap = new HashMap<>();
         QueryWrapper<CodeAllCode> allCodeWrapper = new QueryWrapper<>();
         allCodeWrapper.eq("createcodebtm", baseModelDTO.getBtmname());
         allCodeWrapper.in("createcodeoid", oids);
-//		conditionMap.put("createcodeoid", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(oids.toArray(new String[0])) + ")");
-//		conditionMap.put("createcodebtm", baseModelDTO.getBtmname());
-        List<CodeAllCode> codeCbos = codeAllCodeService.selectByWrapper(allCodeWrapper);
-//		List<ClientBusinessObject> codeCbos = boService.queryCBO(MdmBtmTypeConstant.CODE_ALL_CODE, conditionMap);
-        // 鍥炴敹闇�瑕佷笟鍔℃暟鎹垹闄�
+        List<CodeAllCode> codeCbos = codeAllCodeService.selectByWrapper(allCodeWrapper);// 鍥炴敹闇�瑕佷笟鍔℃暟鎹垹闄�
         if (CodeDefaultLC.TASK_BACK.getValue().equals(baseModelDTO.getLcStatus())) {
             R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(baseModelDTO.getBtmname()));
             if (!listR.isSuccess() || listR.getData().size() == 0) {
@@ -376,8 +371,11 @@
             for (BaseModel baseModel : baseModels) {
                 baseModel.setLcStatus(baseModelDTO.getLcStatus());
             }
-            updateBatchByBaseModel(baseModelDTO.getBtmname(), baseModels);
-        }
+			R r = updateBatchByBaseModel(baseModelDTO.getBtmname(), baseModels);
+			if(!r.isSuccess()){
+				throw new VciBaseException("鏇存柊鏁版嵁鍑洪敊锛岄噸璇曪紒"+r.getMsg());
+			}
+		}
         for (CodeAllCode codeCbo : codeCbos) {
             codeCbo.setLcStatus(baseModelDTO.getLcStatus());
         }
@@ -651,6 +649,7 @@
             }
             wrapperKeyAttrConditionMap(value, keyRuleVO, attrId, trim, ignoreCase, ignoreWidth, trimAll, conditionMap);
         });
+		conditionMap.put("CODETEMPLATEOID","'" + orderDTO.getTemplateOid() + "'");
 
         //娌℃湁闄愬埗鍒嗙被锛屼絾鏄竴涓ā鏉垮彧鍙兘鍦ㄤ竴涓笟鍔$被鍨嬮噷闈紝鎵�浠ョ洿鎺ユ煡璇㈣繖涓笟鍔$被鍨嬪嵆鍙�
 
@@ -3396,9 +3395,9 @@
                                 && ("Integer").equals(setter.getParameterTypes()[0].getSimpleName())) {
                             setter.invoke(obj, ((BigDecimal) map.get(property.getName().toUpperCase())).intValue());
                             map.remove(property.getName().toUpperCase());
-                        } else if (map.get(property.getName().toUpperCase()) != null) {
+                        } else if (map.containsKey(property.getName().toUpperCase())) {
 							if(setter.getParameterTypes()[0].getSimpleName().equals("String")){
-								setter.invoke(obj, String.valueOf(map.get(property.getName().toUpperCase())));
+								setter.invoke(obj, map.get(property.getName().toUpperCase()) == null ? null:String.valueOf(map.get(property.getName().toUpperCase())));
 							}else{
 								setter.invoke(obj, map.get(property.getName().toUpperCase()));
 							}
diff --git a/Source/UBCS/ubcs-service/ubcs-code/src/main/resources/mapper/CodeCLassifyMapper.xml b/Source/UBCS/ubcs-service/ubcs-code/src/main/resources/mapper/CodeCLassifyMapper.xml
index 8015984..f84bca4 100644
--- a/Source/UBCS/ubcs-service/ubcs-code/src/main/resources/mapper/CodeCLassifyMapper.xml
+++ b/Source/UBCS/ubcs-service/ubcs-code/src/main/resources/mapper/CodeCLassifyMapper.xml
@@ -39,7 +39,9 @@
         <result column="CODERESEMBLERULEOID" property="codeResembleRuleOid"/>
         <result column="TENANT_ID" property="tenantId"/>
     </resultMap>
-
+    <sql id="tableName">
+        pl_code_classify
+    </sql>
     <select id="selectPlCodeClassifyPage" resultMap="plCodeClassifyResultMap">
         select * from PL_CODE_CLASSIFY where is_deleted = 0
     </select>
@@ -487,4 +489,23 @@
           </if>
             connect by prior PARENTCODECLASSIFYOID = codeclassify0.oid
     </select>
+
+    <select id="selectStartWithCurrentOid" resultMap="plCodeClassifyResultMap">
+        select * from <include refid="tableName"/>
+                          start with oid = #{oid}
+        connect by prior oid = parentcodeclassifyoid;
+    </select>
+
+    <update id="batchUpdateLcStatus" parameterType="java.util.List">
+        BEGIN
+        <foreach collection="records" item="item" index="index" separator=";">
+            update <include refid="tableName"/> set
+            lcstatus = #{item.lcStatus},
+            ts = #{item.ts},
+            lastModifyTime = #{item.lastModifyTime},
+            lastModifier = #{item.lastModifier}
+            where oid = #{item.oid,jdbcType=VARCHAR}
+        </foreach>
+        ;END;
+    </update>
 </mapper>
diff --git a/Source/UBCS/ubcs-service/ubcs-omd/src/main/java/com/vci/ubcs/omd/service/impl/BtmAttributeServiceImpl.java b/Source/UBCS/ubcs-service/ubcs-omd/src/main/java/com/vci/ubcs/omd/service/impl/BtmAttributeServiceImpl.java
index 99d2e3c..1e0b59b 100644
--- a/Source/UBCS/ubcs-service/ubcs-omd/src/main/java/com/vci/ubcs/omd/service/impl/BtmAttributeServiceImpl.java
+++ b/Source/UBCS/ubcs-service/ubcs-omd/src/main/java/com/vci/ubcs/omd/service/impl/BtmAttributeServiceImpl.java
@@ -215,7 +215,7 @@
 				// 鐗堟湰瑙勫垯瀛楁涓嶈兘涓虹┖
 //				vo.setNullableFlag(false);
 				vo.setAttributeLength(150);
-				if (Arrays.asList("lastr","firstr","lastv","firstv").contains(id)){
+				if (Arrays.asList("lastr","firstr","lastv","firstv","revisionseq","versionseq").contains(id)){
 					vo.setAttributeLength(5);
 					vo.setAttrDataType(VciFieldTypeEnum.VTInteger.name());
 				}

--
Gitblit v1.9.3