From a751e547d67c4f8e2c6fddf958c1559f792515bd Mon Sep 17 00:00:00 2001
From: lyh <925863403@qq.com>
Date: 星期五, 27 六月 2025 16:11:50 +0800
Subject: [PATCH] 添加工作流

---
 src/views/flowable/components/HistoricDetail.vue       |  343 +++++++
 src/views/flowable/components/ActHandleBtn.vue         |  235 +++++
 src/views/flowable/mixin/FlowableMixin.js              |   68 +
 src/views/flowable/api/todo.js                         |   65 +
 src/views/flowable/components/ActHistoricDetailBtn.vue |   53 +
 src/views/flowable/components/ActCancelBtn.vue         |   74 +
 src/views/flowable/api/process.js                      |   34 
 src/views/flowable/api/definition.js                   |  134 ++
 src/views/flowable/components/ActApplyBtn.vue          |   73 +
 src/views/flowable/workflow/FlowLedger.vue             |  248 +++++
 src/main.js                                            |   29 
 package.json                                           |    1 
 src/views/flowable/api/finished.js                     |   37 
 src/views/flowable/workflow/FlowCompleted.vue          |  300 ++++++
 src/views/flowable/workflow/FlowTodo.vue               |  583 ++++++++++++
 src/views/flowable/modeler/modelerDesign.vue           |  400 ++++++++
 16 files changed, 2,654 insertions(+), 23 deletions(-)

diff --git a/package.json b/package.json
index de242b3..8e8e782 100644
--- a/package.json
+++ b/package.json
@@ -55,6 +55,7 @@
     "vuex": "^3.1.0",
     "vxe-table": "2.9.13",
     "vxe-table-plugin-antd": "1.8.10",
+    "workflow-bpmn-modeler": "^0.2.8",
     "xe-utils": "2.4.8"
   },
   "devDependencies": {
diff --git a/src/main.js b/src/main.js
index bcb24ed..9bc0344 100644
--- a/src/main.js
+++ b/src/main.js
@@ -50,24 +50,8 @@
 //琛ㄥ崟楠岃瘉
 import { rules } from '@/utils/rules'
 import * as echarts from 'echarts'
-import qs from 'qs'
-// import VCalendar from 'v-calendar'; // 寮曞叆鏃ュ巻鎻掍欢
-//
-// Vue.use(VCalendar, {
-//   componentPrefix: 'vc',
-// });
-
-//娉ㄥ叆鍏ㄥ眬灞炴��$message
-import { message, notification } from 'ant-design-vue'
-Vue.prototype.$message = message
-Vue.prototype.$notification = notification
-message.config({
-})
-notification.config({
-  bottom: '20px',
-  right: '100px'
-})
-
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
 // 灏嗚嚜鍔ㄦ敞鍐屾墍鏈夌粍浠朵负鍏ㄥ眬缁勪欢
 import dataV from '@jiaminghi/data-view'
 Vue.use(dataV)
@@ -75,18 +59,17 @@
 import VueDragResize from "vue-drag-resize"
 Vue.component('vue-drag-resize', VueDragResize)
 
-// import 'echarts-liquidfill'
 Vue.prototype.$echarts = echarts
-Vue.prototype.$qs = qs
 Vue.prototype.rules = rules
 Vue.config.productionTip = false
 Vue.use(Storage, config.storageOptions)
-Vue.use(Antd)
 Vue.use(VueAxios, router)
 Vue.use(Viser)
 Vue.use(hasPermission)
 Vue.use(JDictSelectTag)
 Vue.use(Print)
+Vue.use(ElementUI);
+Vue.use(Antd)
 Vue.use(preview)
 Vue.use(vueBus);
 Vue.use(JeecgComponents);
@@ -102,7 +85,7 @@
     beforeCreate() {
       Vue.prototype.$bus = new Vue()
     },
-    mounted() {
+    mounted () {
       store.commit('SET_SIDEBAR_TYPE', Vue.ls.get(SIDEBAR_TYPE, true))
       store.commit('TOGGLE_THEME', Vue.ls.get(DEFAULT_THEME, config.navTheme))
       store.commit('TOGGLE_LAYOUT_MODE', Vue.ls.get(DEFAULT_LAYOUT_MODE, config.layout))
@@ -113,7 +96,7 @@
       store.commit('TOGGLE_WEAK', Vue.ls.get(DEFAULT_COLOR_WEAK, config.colorWeak))
       store.commit('TOGGLE_COLOR', Vue.ls.get(DEFAULT_COLOR, config.primaryColor))
       store.commit('SET_TOKEN', Vue.ls.get(ACCESS_TOKEN))
-      store.commit('SET_MULTI_PAGE', Vue.ls.get(DEFAULT_MULTI_PAGE, config.multipage))
+      store.commit('SET_MULTI_PAGE',Vue.ls.get(DEFAULT_MULTI_PAGE,config.multipage))
     },
     render: h => h(App)
   }).$mount('#app')
diff --git a/src/views/flowable/api/definition.js b/src/views/flowable/api/definition.js
new file mode 100644
index 0000000..918fdb2
--- /dev/null
+++ b/src/views/flowable/api/definition.js
@@ -0,0 +1,134 @@
+import {axios as request} from '@/utils/request'
+
+// 鏌ヨ娴佺▼瀹氫箟鍒楄〃
+export function listDefinition(query) {
+  return request({
+    url: '/flowable/definition/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 閮ㄧ讲娴佺▼瀹炰緥
+export function definitionStartByDefId(procDefId,data) {
+  return request({
+    url: '/flowable/definition/startByProcDefId/' + procDefId,
+    method: 'post',
+    data: JSON.stringify(data)
+  })
+}
+// 閮ㄧ讲娴佺▼瀹炰緥
+export function definitionStartByDefKey(procDefKey,data) {
+  return request({
+    url: '/flowable/definition/startByProcDefKey/' + procDefKey,
+    method: 'post',
+    data: JSON.stringify(data)
+  })
+}
+// 閮ㄧ讲娴佺▼瀹炰緥
+export function definitionStartByDataId(dataId,data) {
+  return request({
+    url: '/flowable/definition/startByDataId/' + dataId,
+    method: 'post',
+    data: data
+  })
+}
+
+// 鑾峰彇娴佺▼鍙橀噺
+export function getProcessVariables(taskId) {
+  return request({
+    url: '/flowable/task/processVariables/' + taskId,
+    method: 'get'
+  })
+}
+
+// 婵�娲�/鎸傝捣娴佺▼
+export function updateState(params) {
+  return request({
+    url: '/flowable/definition/updateState',
+    method: 'put',
+    params: params
+  })
+}
+
+// 鎸囧畾娴佺▼鍔炵悊浜哄憳鍒楄〃
+export function userList(query) {
+  return request({
+    url: '/flowable/definition/userList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鎸囧畾娴佺▼鍔炵悊缁勫垪琛�
+export function roleList(query) {
+  return request({
+    url: '/flowable/definition/roleList',
+    method: 'get',
+    params: query
+  })
+}
+// 鎸囧畾娴佺▼鍒嗙被鍒楄〃
+export function categoryList(query) {
+  return request({
+    url: '/flowable/definition/categoryList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 璇诲彇xml鏂囦欢
+export function readXml(deployId) {
+  return request({
+    url: '/flowable/definition/readXml/' + deployId,
+    method: 'get'
+  })
+}
+// 璇诲彇xml鏂囦欢
+export function readXmlByDataId(dataId) {
+  return request({
+    url: '/flowable/definition/readXmlByDataId/' + dataId,
+    method: 'get'
+  })
+}
+// 璇诲彇image鏂囦欢
+export function readImage(deployId) {
+  return request({
+    url: '/flowable/definition/readImage/' + deployId,
+    method: 'get'
+  })
+}
+
+// 璇诲彇image鏂囦欢
+export function getFlowViewer(procInsId) {
+  return request({
+    url: '/flowable/task/flowViewer/' + procInsId,
+    method: 'get'
+  })
+}
+// 璇诲彇image鏂囦欢
+export function getFlowViewerByDataId(dataId) {
+  return request({
+    url: '/flowable/task/flowViewerByDataId/' + dataId,
+    method: 'get'
+  })
+}
+
+// 璇诲彇xml鏂囦欢
+export function saveXml(data) {
+  return request({
+    url: '/flowable/definition/save',
+    method: 'post',
+    data: data
+  })
+}
+
+// 鍒犻櫎娴佺▼瀹氫箟
+export function delDeployment(query) {
+  return request({
+    url: '/flowable/definition/delete/',
+    method: 'delete',
+    params: query
+  })
+}
+
diff --git a/src/views/flowable/api/finished.js b/src/views/flowable/api/finished.js
new file mode 100644
index 0000000..bbab6da
--- /dev/null
+++ b/src/views/flowable/api/finished.js
@@ -0,0 +1,37 @@
+import {axios as request} from '@/utils/request'
+
+// 鏌ヨ宸插姙浠诲姟鍒楄〃
+export function finishedList(query) {
+  return request({
+    url: '/flowable/task/finishedList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 浠诲姟娴佽浆璁板綍
+export function flowRecord(query) {
+  return request({
+    url: '/flowable/task/flowRecord',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鎾ゅ洖浠诲姟
+export function revokeProcess(data) {
+  return request({
+    url: '/flowable/task/revokeProcess',
+    method: 'post',
+    data: data
+  })
+}
+
+// 閮ㄧ讲娴佺▼瀹炰緥
+export function deployStart(deployId) {
+  return request({
+    url: '/flowable/process/startFlow/' + deployId,
+    method: 'get',
+  })
+}
+
diff --git a/src/views/flowable/api/process.js b/src/views/flowable/api/process.js
new file mode 100644
index 0000000..87a3346
--- /dev/null
+++ b/src/views/flowable/api/process.js
@@ -0,0 +1,34 @@
+import {axios as request} from '@/utils/request'
+
+// 鎴戠殑鍙戣捣鐨勬祦绋�
+export function myProcessList(query) {
+  return request({
+    url: '/flowable/task/myProcess',
+    method: 'get',
+    params: query
+  })
+}
+
+
+// 鍙栨秷鐢宠
+export function deleteByDataId(dataId,deleteReason) {
+  const data = {
+    dataId:dataId,
+    deleteReason:deleteReason
+  }
+  return request({
+    url: '/flowable/instance/deleteByDataId',
+    method: 'post',
+    params: data
+  })
+}
+
+
+// 閮ㄧ讲娴佺▼瀹炰緥
+export function deployStart(deployId) {
+  return request({
+    url: '/flowable/process/startFlow/' + deployId,
+    method: 'get',
+  })
+}
+
diff --git a/src/views/flowable/api/todo.js b/src/views/flowable/api/todo.js
new file mode 100644
index 0000000..107bb4a
--- /dev/null
+++ b/src/views/flowable/api/todo.js
@@ -0,0 +1,65 @@
+import {axios as request} from '@/utils/request'
+
+// 鏌ヨ寰呭姙浠诲姟鍒楄〃
+export function todoList(query) {
+  return request({
+    url: '/flowable/task/todoList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 瀹屾垚浠诲姟
+export function completeTask(data) {
+  return request({
+    url: '/flowable/task/completeByDateId',
+    method: 'post',
+    data: data
+  })
+}
+
+// 濮旀淳浠诲姟
+export function delegate(data) {
+  return request({
+    url: '/flowable/task/delegate',
+    method: 'post',
+    data: data
+  })
+}
+
+// 閫�鍥炰换鍔�
+export function returnTask(data) {
+  return request({
+    url: '/flowable/task/taskReturnByDataId',
+    method: 'post',
+    data: data
+  })
+}
+
+// 椹冲洖浠诲姟
+export function rejectTask(data) {
+  return request({
+    url: '/flowable/task/taskRejectByDataId',
+    method: 'post',
+    data: data
+  })
+}
+
+// 鍙��鍥炰换鍔″垪琛�
+export function returnList(data) {
+  return request({
+    url: '/flowable/task/findReturnTaskListByDataId',
+    method: 'post',
+    data: data
+  })
+}
+
+// 涓嬩竴鑺傜偣 todo 鐩墠鐩存帴鑷姩鍒嗛厤鍒板�欓�変汉锛屼笉鐢ㄤ富鍔ㄩ�変汉锛屽鏈夐渶瑕佸啀寮�鍙�
+export function getNextFlowNode(data) {
+  return request({
+    url: '/flowable/task/nextFlowNode',
+    method: 'post',
+    data: data
+  })
+}
+
diff --git a/src/views/flowable/components/ActApplyBtn.vue b/src/views/flowable/components/ActApplyBtn.vue
new file mode 100644
index 0000000..7e5a39c
--- /dev/null
+++ b/src/views/flowable/components/ActApplyBtn.vue
@@ -0,0 +1,73 @@
+<style lang="less">
+</style>
+<template>
+  <span>
+      <a-button :loading="submitLoading" :type="btnType" @click="applySubmit()" >{{text}}</a-button>
+  </span>
+</template>
+
+<script>
+  import {definitionStartByDataId} from "@views/flowable/api/definition";
+
+export default {
+    name: 'ActApplyBtn',
+    components: {},
+    props: {
+        btnType: { type: String, default: 'link', required: false },
+        /**/
+        dataId: {
+            type: String,
+            default: '',
+            required: true
+        },
+        variables:{
+          type: Object,
+          default: {},
+        },
+        text: {
+            type: String,
+            default: '鎻愪氦鐢宠',
+            required: false
+        }
+
+    },
+    data() {
+        return {
+            modalVisible: false,
+            submitLoading: false,
+            form: {
+            },
+        };
+    },
+    created() {
+    },
+    watch: {
+    },
+    methods: {
+        applySubmit() {
+            if (this.dataId && this.dataId.length < 1) {
+                this.error = '蹇呴』浼犲叆鍙傛暟dataId';
+                this.$message.error(this.error);
+                return;
+            } else {
+                this.error = '';
+            }
+            this.submitLoading = true;
+            var params = Object.assign({
+                dataId: this.dataId
+            }, this.variables);
+          definitionStartByDataId(this.dataId, params)
+                .then(res => {
+                    if (res.success) {
+                        this.$message.success('鎿嶄綔鎴愬姛');
+                        this.$emit('success');
+                    } else {
+                        this.$message.error(res.message);
+                    }
+                })
+                .finally(() => (this.submitLoading = false));
+        }
+    }
+
+};
+</script>
diff --git a/src/views/flowable/components/ActCancelBtn.vue b/src/views/flowable/components/ActCancelBtn.vue
new file mode 100644
index 0000000..02af66f
--- /dev/null
+++ b/src/views/flowable/components/ActCancelBtn.vue
@@ -0,0 +1,74 @@
+<style lang="less">
+</style>
+<template>
+  <span>
+      <a-button :type="btnType" @click="cancel()" >{{text}}</a-button>
+      <a-modal title="纭鎾ゅ洖" v-model="modalCancelVisible" :mask-closable="false" :width="500">
+            <a-form ref="delForm" v-model="cancelForm" :label-width="70" v-if="modalCancelVisible">
+                <a-form-item label="鎾ゅ洖鍘熷洜" prop="reason">
+                    <a-input type="textarea" v-model="cancelForm.reason" :rows="4" />
+                </a-form-item>
+            </a-form>
+            <div slot="footer">
+                <a-button type="text" @click="modalCancelVisible = false">鍙栨秷</a-button>
+                <a-button type="primary" :disabled="submitLoading" @click="handelSubmitCancel">鎻愪氦</a-button>
+            </div>
+        </a-modal>
+  </span>
+</template>
+
+<script>
+import {deleteByDataId} from "@views/flowable/api/process";
+
+export default {
+    name: 'ActCancelBtn',
+    components: {},
+    props: {
+        btnType: { type: String, default: 'link', required: false },
+        /**/
+        dataId: {
+            type: String,
+            default: '',
+            required: true
+        },
+        text: {
+            type: String,
+            default: '鎾ゅ洖',
+            required: false
+        }
+    },
+    data() {
+        return {
+            modalCancelVisible: false,
+            cancelForm: {
+                reason: ''
+            },
+            submitLoading: false,
+        };
+    },
+    created() {
+    },
+    watch: {
+    },
+    methods: {
+        cancel() {
+            this.modalCancelVisible = true;
+        },
+        handelSubmitCancel() {
+            this.submitLoading = true;
+          deleteByDataId(this.dataId, this.cancelForm.reason)
+                .then(res => {
+                    if (res.success) {
+                        this.$message.success('鎿嶄綔鎴愬姛');
+                        this.modalCancelVisible = false;
+                        this.$emit('success');
+                    } else {
+                        this.$message.error(res.message);
+                    }
+                })
+                .finally(() => (this.submitLoading = false));
+        }
+    }
+
+};
+</script>
diff --git a/src/views/flowable/components/ActHandleBtn.vue b/src/views/flowable/components/ActHandleBtn.vue
new file mode 100644
index 0000000..a820ea6
--- /dev/null
+++ b/src/views/flowable/components/ActHandleBtn.vue
@@ -0,0 +1,235 @@
+<style lang="less">
+</style>
+<template>
+  <span>
+      <a-button :type="btnType" @click="handle()" >{{text}}</a-button>
+      <a-modal :title="modalTaskTitle" v-model="modalTaskVisible" :mask-closable="false" :width="500">
+
+      <div  v-if="modalTaskVisible">
+        <div v-if="type==handleType.reApply">
+          纭鏃犺骞堕噸鏂版彁浜わ紵
+        </div>
+        <a-form ref="form" :model="form" :label-width="85" >
+          <a-form-item v-if="type!==handleType.reApply" label="澶勭悊鎰忚" prop="reason">
+            <a-input type="textarea" v-model="form.comment" :rows="4" />
+          </a-form-item>
+          <div v-show="type==2">
+            <a-form-item label="閫�鍥炶妭鐐�" prop="targetKey" v-if="returnTaskList.length">
+              <a-radio-group v-model="form.targetKey" @change="targetKeyChange">
+                <a-radio-button
+                  v-for="item in returnTaskList"
+                  :key="item.id"
+                  :value="item.id"
+                >{{item.name}}</a-radio-button>
+              </a-radio-group>
+            </a-form-item>
+            <span v-else>鏃犲彲閫�鍥炶妭鐐癸紒</span>
+          </div>
+            <div v-if="form.targetKey !== 'start' && candidateUsers.length">
+                <a-form-item label="涓嬩釜鑺傜偣瀹℃壒鍊欓�変汉">
+                    <a-select
+                        mode="multiple"
+                        v-model="candidateUsersSelecteds"
+                        style="width: 100%"
+                        placeholder="璇烽�夋嫨涓嬩釜鑺傜偣瀹℃壒鍊欓�変汉"
+                    >
+                    <a-select-option v-for="user in candidateUsers" :key="user.username" :value="user.username">
+                        {{user.realname}}
+                    </a-select-option>
+                  </a-select>
+                </a-form-item>
+            </div>
+        </a-form>
+      </div>
+      <div slot="footer">
+        <a-button type="text" @click="modalTaskVisible=false">鍙栨秷</a-button>
+        <a-button type="primary" :loading="submitLoading" @click="handelSubmit">鎻愪氦</a-button>
+      </div>
+    </a-modal>
+  </span>
+</template>
+
+<script>
+  import {completeTask, rejectTask, returnList, returnTask} from "@views/flowable/api/todo";
+
+export default {
+    name: 'ActHandleBtn',
+    components: {},
+    props: {
+        btnType: { type: String, default: 'link', required: false },
+        /* handleType 0閫氳繃 1椹冲洖 2閫�鍥�  */
+        type: {
+            type: String|Number,
+            default: '0',
+            required: true
+        },
+        dataId: {
+            type: String,
+            default: '',
+            required: true
+        },
+      /*娴佺▼鍙橀噺*/
+        variables:{
+          type: Object,
+          default: ()=>{},
+        },
+        candidateUsers:{
+          type: Array,
+          default: ()=>[],
+        },
+        text: {
+            type: String,
+            default: '澶勭悊',
+            required: false
+        }
+    },
+    data() {
+        return {
+          handleType:{
+            // 閫氳繃
+            pass: 0,
+            // 椹冲洖
+            back: 1,
+            // 閫�鍥�
+            return: 2,
+            // 閲嶆柊鎻愪氦
+            reApply: 3
+            },
+            returnTaskList: [],
+            candidateUsersSelecteds:[],
+            modalTaskVisible: false,
+            submitLoading: false,
+            form: {
+              comment:'',
+              targetKey:''
+            },
+            modalTaskTitle: '',
+
+        };
+    },
+    created() {
+    },
+    watch: {
+    },
+    methods: {
+        handle() {
+          this.form.comment = ''
+          this.candidateUsersSelecteds = []
+            if (this.type === this.handleType.delegate) {
+                // this.delegateTask();
+            } else if (this.type === this.handleType.pass) {
+                this.passTask();
+            } else if (this.type === this.handleType.back) {
+                this.backTask();
+            } else if(this.type === this.handleType.return){
+                this.returnTask();
+            } else if(this.type === this.handleType.reApply){
+                this.reApply();
+            }
+            else {
+                this.$message.warn('鏈煡绫诲瀷type锛屽弬瑙� handleType');
+            }
+        },
+        reApply() {
+            const v = this;
+            this.modalTaskTitle = '纭閲嶆柊鎻愪氦';
+            this.modalTaskVisible = true;
+        },
+        passTask() {
+            const v = this;
+            this.modalTaskTitle = '瀹℃壒閫氳繃';
+            this.modalTaskVisible = true;
+        },
+        backTask() {
+          const v = this;
+          this.modalTaskTitle = '瀹℃壒椹冲洖';
+          this.modalTaskVisible = true;
+        },
+        returnTask() {
+            const v = this;
+            this.modalTaskTitle = '瀹℃壒閫�鍥�';
+            this.modalTaskVisible = true;
+            returnList({dataId:this.dataId}).then(res => {
+              this.returnTaskList = res.result||[];
+              // console.log(this.returnTaskList)
+            })
+        },
+
+        handelSubmit() {
+            console.log('鎻愪氦');
+            this.submitLoading = true;
+            var formData = Object.assign({
+                dataId:this.dataId,
+                candidateUsers:this.candidateUsersSelecteds,
+                values:Object.assign({dataId:this.dataId},this.variables)
+            }, this.form);
+            if (this.type==this.handleType.reApply){
+              formData.comment = '閲嶆柊鎻愪氦'
+            }
+            if (!formData.comment){
+              this.$message.error('璇疯緭鍏ュ鎵规剰瑙侊紒');
+              this.submitLoading=false
+              return;
+            }
+            // 鏈変笅涓妭鐐瑰鎵逛汉閫夋嫨锛屼絾鏄湭閫�
+            if (this.candidateUsers.length &&
+              this.candidateUsersSelecteds.length==0 &&
+              this.form.targetKey !== 'start'
+            ){
+              this.$message.error('璇烽�夋嫨涓嬩釜鑺傜偣瀹℃壒浜猴紒');
+              this.submitLoading=false
+              return;
+            }
+            if (this.type == this.handleType.reApply || this.type == this.handleType.pass) {
+                // 閫氳繃
+              completeTask(formData).then(res => {
+                    this.submitLoading = false;
+                    if (res.success) {
+                        this.$message.success('鎿嶄綔鎴愬姛');
+                        this.modalTaskVisible = false;
+                        this.$emit('success');
+                    } else {
+                        this.$message.error('鎿嶄綔澶辫触');
+                    }
+                }).finally(()=>{this.submitLoading=false});
+            } else if (this.type == this.handleType.back) {
+                // 椹冲洖
+                  rejectTask(formData).then(res => {
+                        this.submitLoading = false;
+                        if (res.success) {
+                            this.$message.success('鎿嶄綔鎴愬姛');
+                            this.modalTaskVisible = false;
+                            this.$emit('success');
+                        } else {
+                            this.$message.error('鎿嶄綔澶辫触');
+                        }
+                    }).finally(()=>{this.submitLoading=false});
+
+            } else if (this.type == this.handleType.return){
+              if (!formData.targetKey){
+                this.$message.error('璇烽�夋嫨閫�鍥炶妭鐐癸紒');
+                this.submitLoading=false
+                return;
+              }
+              //閫�鍥�
+              returnTask(formData).then(res => {
+                this.submitLoading = false;
+                if (res.success) {
+                  this.$message.success('鎿嶄綔鎴愬姛');
+                  this.modalTaskVisible = false;
+                  this.$emit('success');
+                } else {
+                  this.$message.error('鎿嶄綔澶辫触');
+                }
+              }).finally(()=>{this.submitLoading=false});
+            }
+        },
+
+        targetKeyChange() {
+            this.candidateUsersSelecteds = []
+            this.$emit('targetKeyChange',this.form.targetKey)
+        }
+    }
+
+};
+</script>
diff --git a/src/views/flowable/components/ActHistoricDetailBtn.vue b/src/views/flowable/components/ActHistoricDetailBtn.vue
new file mode 100644
index 0000000..c4a69f5
--- /dev/null
+++ b/src/views/flowable/components/ActHistoricDetailBtn.vue
@@ -0,0 +1,53 @@
+<style lang="less">
+</style>
+<template>
+  <span>
+      <a-button :type="btnType"  @click="history()" >{{text}}</a-button>
+      <a-modal title="瀹℃壒鍘嗗彶" v-model="modalLsVisible" :mask-closable="true" :width="'80%'" :footer="null">
+          <div v-if="modalLsVisible">
+              <HistoricDetail ref="historicDetail" :data-id="dataId"></HistoricDetail>
+          </div>
+      </a-modal>
+  </span>
+</template>
+
+<script>
+import HistoricDetail from './HistoricDetail';
+export default {
+    name: 'ActHistoricDetailBtn',
+    components: { HistoricDetail },
+    props: {
+        btnType: { type: String, default: 'link', required: false },
+        /**/
+        dataId: {
+            type: String,
+            default: '',
+            required: true
+        },
+        text: {
+            type: String,
+            default: '瀹℃壒鍘嗗彶',
+            required: false
+        }
+    },
+    data() {
+        return {
+            modalLsVisible: false
+        };
+    },
+    created() {
+    },
+    watch: {
+    },
+    methods: {
+        history() {
+            if (!this.dataId) {
+                this.$message.error('娴佺▼瀹炰緥ID涓嶅瓨鍦�');
+                return;
+            }
+            this.modalLsVisible = true;
+        }
+    }
+
+};
+</script>
diff --git a/src/views/flowable/components/HistoricDetail.vue b/src/views/flowable/components/HistoricDetail.vue
new file mode 100644
index 0000000..be707cc
--- /dev/null
+++ b/src/views/flowable/components/HistoricDetail.vue
@@ -0,0 +1,343 @@
+<style lang="less">
+</style>
+<template>
+  <div class="search">
+    <a-card>
+      <p slot="title">
+        <span>娴佺▼鍥�</span>
+      </p>
+      <div :style="{height: svgHeight}" v-if="svgShow">
+        <bpmnModeler class="svg" ref="bpm" :xml="xmlData" :is-view="true"></bpmnModeler>
+      </div>
+    </a-card>
+    <a-card style="margin-top:10px;">
+      <p slot="title">
+        <span>娴佺▼瀹℃壒杩涘害鍘嗗彶</span>
+      </p>
+      <a-row style="position:relative">
+        <div class="block">
+          <a-timeline>
+            <a-timeline-item
+              v-for="(item,index ) in flowRecordList"
+              :key="index"
+              :color="setColor(item.finishTime)"
+            >
+              <p style="font-weight: 700;">{{item.taskName}}
+                <i v-if="!item.finishTime" style="color: orange">(寰呭姙涓�傘�傘��)</i>
+              </p>
+
+              <a-card :body-style="{ padding: '10px' }">
+                <label v-if="item.assigneeName&&item.finishTime" style="font-weight: normal;margin-right: 30px;">瀹為檯鍔炵悊浜猴細 {{item.assigneeName}} <a-tag type="info" size="mini">{{item.deptName}}</a-tag></label>
+                <label v-if="item.candidate" style="font-weight: normal;margin-right: 30px;">鍊欓�夊姙鐞嗕汉锛� {{item.candidate}}</label>
+                <label style="font-weight: normal">鎺ユ敹鏃堕棿锛� </label><label style="color:#8a909c;font-weight: normal">{{item.createTime}}</label>
+                <label v-if="item.finishTime" style="margin-left: 30px;font-weight: normal">鍔炵粨鏃堕棿锛� </label><label style="color:#8a909c;font-weight: normal">{{item.finishTime}}</label>
+                <label v-if="item.duration" style="margin-left: 30px;font-weight: normal">鑰楁椂锛� </label><label style="color:#8a909c;font-weight: normal">{{item.duration}}</label>
+
+                <p  v-if="item.comment">
+<!--  1 姝e父鎰忚  2 閫�鍥炴剰瑙� 3 椹冲洖鎰忚                -->
+                  <a-tag color="green" v-if="item.comment.type === '1'">
+                    <span v-if="item.comment.comment!='閲嶆柊鎻愪氦'">閫氳繃锛�</span>
+                    {{item.comment.comment}}
+                  </a-tag>
+                  <a-tag color="orange" v-if="item.comment.type === '2'">閫�鍥烇細  {{item.comment.comment}}</a-tag>
+                  <a-tag color="red" v-if="item.comment.type === '3'">椹冲洖锛�  {{item.comment.comment}}</a-tag>
+                </p>
+              </a-card>
+            </a-timeline-item>
+          </a-timeline>
+        </div>
+      </a-row>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import {flowRecord} from "@views/flowable/api/finished";
+import {getFlowViewerByDataId, readXmlByDataId} from "@views/flowable/api/definition";
+import bpmnModeler from "workflow-bpmn-modeler";
+
+export default {
+    name: 'HistoricDetail',
+  components: {
+    bpmnModeler,
+  },
+    props: {
+    /**/
+        dataId: {
+            type: String,
+            default: '',
+            required: true
+        },
+
+    },
+    data() {
+        return {
+            taskList:[],
+            flowRecordList: [], // 娴佺▼娴佽浆鏁版嵁
+            formData:{},
+            xmlData:'',
+            type: 0,
+            loading: false, // 琛ㄥ崟鍔犺浇鐘舵��
+            loadingImg: false,
+            data: [],
+            id: '',
+            imgUrl: '',
+            backRoute: '',
+          svgHeight:'',
+          svgShow: true
+        };
+    },
+    created() {
+        this.init();
+    },
+    watch: {
+      dataId: function(newval, oldName) {
+            this.init();
+        }
+    },
+
+    methods: {
+        init() {
+          this.getFlowRecordList()
+          this.getModelDetail()
+        },
+      /** xml 鏂囦欢 */
+      getModelDetail() {
+        // 鍙戦�佽姹傦紝鑾峰彇xml
+        readXmlByDataId(this.dataId).then(res => {
+          this.xmlData = res.result
+          this.getFlowViewer()
+          setTimeout(()=>{
+            this.fitViewport()
+          })
+        })
+      },
+      // 娴佺▼杩涜鎯呭喌
+      getFlowViewer() {
+        getFlowViewerByDataId(this.dataId).then(res => {
+          this.taskList = res.result || []
+          this.fillColor();
+        })
+      },
+      /** 娴佺▼娴佽浆璁板綍 */
+      getFlowRecordList() {
+        const params = {dataId: this.dataId}
+        flowRecord(params).then(res => {
+          // console.log(res)
+          this.flowRecordList = res.result.flowList;
+          this.finishOrder()
+          // 娴佺▼杩囩▼涓笉瀛樺湪鍒濆鍖栬〃鍗� 鐩存帴璇诲彇鐨勬祦绋嬪彉閲忎腑瀛樺偍鐨勮〃鍗曞��
+          if (res.result.formData) {
+            this.formData = res.result.formData;
+          }
+        }).catch(res => {
+          console.log(res)
+        })
+      },
+        //鏁寸悊椤哄簭锛屾妸寰呭姙鏀炬渶涓婇潰锛屽苟涓斿彧鐣欎竴涓紙涓嶇劧浼氱鏃朵細涔憋級
+      finishOrder(){
+        const list = []
+        let noFinish = null
+        for (const flow of this.flowRecordList) {
+          if (flow.finishTime){
+            // 鍔炵粨鐨勮妭鐐瑰悓鏃跺彇鏈夊疄闄呭姙鐞嗕汉鐨勶紝鍥犱负浼氱浼氬皢鎵�鏈夌殑澶氬疄渚嬮兘杩斿洖锛岄渶瑕佽繃婊�
+            if (flow.assigneeId){
+              list.push(flow)
+            }
+          } else {
+            noFinish = flow
+          }
+        }
+        if (noFinish){
+          const find = list.find(obj=>obj.taskDefKey == noFinish.taskDefKey);
+          if (find){
+            noFinish.taskName = '銆愪細绛句腑銆�'+noFinish.taskName
+          }
+          this.flowRecordList = [noFinish,...list];
+        } else {
+          this.flowRecordList = list;
+        }
+
+      },
+        setColor(val) {
+          if (val) {
+            return "#2bc418";
+          } else {
+            return "#b3bdbb";
+          }
+        },
+      fillColor() {
+        const modeler = this.$refs.bpm.modeler;
+        const canvas = modeler.get('canvas')
+        modeler._definitions.rootElements[0].flowElements.forEach(n => {
+          const completeTask = this.taskList.find(m => m.key === n.id)
+          const todoTask = this.taskList.find(m => !m.completed)
+          const endTask = this.taskList[this.taskList.length - 1]
+          //鐢ㄦ埛浠诲姟
+          if (n.$type === 'bpmn:UserTask') {
+            if (completeTask) {
+              canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
+              canvas.addMarker(n.id, completeTask.back ? 'highlight-back' : 'highlight-noback')
+              n.outgoing.forEach(nn => {
+                const targetTask = this.taskList.find(m => m.key === nn.targetRef.id)
+                if (targetTask) {
+                  if (todoTask && completeTask.key === todoTask.key && !todoTask.completed){
+                    canvas.addMarker(nn.id, todoTask.completed ? 'highlight' : 'highlight-todo')
+                    canvas.addMarker(nn.targetRef.id, todoTask.completed ? 'highlight' : 'highlight-todo')
+                  }else {
+                    canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                    canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                  }
+                }
+              })
+            }
+          }
+          // 鎺掍粬缃戝叧
+          else if (n.$type === 'bpmn:ExclusiveGateway') {
+            if (completeTask) {
+              canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
+              n.outgoing.forEach(nn => {
+                const targetTask = this.taskList.find(m => m.key === nn.targetRef.id)
+                if (targetTask) {
+
+                  canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                  canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                }
+
+              })
+            }
+
+          }
+          // 骞惰缃戝叧
+          else if (n.$type === 'bpmn:ParallelGateway') {
+            if (completeTask) {
+              canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
+              n.outgoing.forEach(nn => {
+                debugger
+                const targetTask = this.taskList.find(m => m.key === nn.targetRef.id)
+                if (targetTask) {
+                  canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                  canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
+                }
+              })
+            }
+          }
+          else if (n.$type === 'bpmn:StartEvent') {
+            n.outgoing.forEach(nn => {
+              const completeTask = this.taskList.find(m => m.key === nn.targetRef.id)
+              if (completeTask) {
+                canvas.addMarker(nn.id, 'highlight')
+                canvas.addMarker(n.id, 'highlight')
+                return
+              }
+            })
+          }
+          else if (n.$type === 'bpmn:EndEvent') {
+            if (endTask.key === n.id && endTask.completed) {
+              canvas.addMarker(n.id, 'highlight')
+              return
+            }
+          }
+        })
+      },
+      // 璁╁浘鑳借嚜閫傚簲灞忓箷
+      fitViewport() {
+        const modeler = this.$refs.bpm.modeler;
+        const canvas = modeler.get('canvas')
+        // this.zoom = this.modeler.get('canvas').zoom('fit-viewport')
+        if (this.svgHeight){
+          document.querySelector('.canvas').style.height = this.svgHeight;
+        }
+        const bbox = document.querySelector('.flow-containers .viewport').getBBox()
+        const currentViewbox = modeler.get('canvas').viewbox()
+        if (!this.svgHeight){
+          this.svgHeight = currentViewbox.inner.height + 'px'
+          this.svgShow = false
+          this.$nextTick(()=>{
+            this.svgShow = true
+          })
+          // this.fitViewport()
+          setTimeout(()=>{
+            this.fitViewport()
+          })
+        }
+
+        const elementMid = {
+          x: bbox.x + bbox.width / 2 - 65,
+          y: bbox.y + bbox.height / 2
+        }
+        // 璋冭妭浣嶇疆
+        modeler.get('canvas').viewbox({
+          x: elementMid.x - currentViewbox.width / 2 + 70,
+          y: elementMid.y - currentViewbox.height/2,
+          width: currentViewbox.width,
+          height: currentViewbox.height
+        })
+        // 璋冭妭澶у皬缂╂斁
+        const zoom = currentViewbox.outer.width /(currentViewbox.inner.width+200)
+        console.log('********',zoom,elementMid,currentViewbox.inner,currentViewbox.outer)
+        // modeler.get('canvas').zoom(zoom)
+
+
+      },
+    }
+
+};
+</script>
+<style lang="less">
+   .highlight.djs-shape .djs-visual > :nth-child(1) {
+     fill: green !important;
+     stroke: green !important;
+     fill-opacity: 0.2 !important;
+   }
+   .highlight.djs-shape .djs-visual > :nth-child(2) {
+     fill: green !important;
+   }
+   .highlight.djs-shape .djs-visual > path {
+     fill: green !important;
+     fill-opacity: 0.2 !important;
+     stroke: green !important;
+   }
+   .highlight.djs-connection > .djs-visual > path {
+     stroke: green !important;
+   }
+   // .djs-connection > .djs-visual > path {
+   //   stroke: orange !important;
+   //   stroke-dasharray: 4px !important;
+   //   fill-opacity: 0.2 !important;
+   // }
+   // .djs-shape .djs-visual > :nth-child(1) {
+   //   fill: orange !important;
+   //   stroke: orange !important;
+   //   stroke-dasharray: 4px !important;
+   //   fill-opacity: 0.2 !important;
+   // }
+   .highlight-todo.djs-connection > .djs-visual > path {
+     stroke: orange !important;
+     stroke-dasharray: 4px !important;
+     fill-opacity: 0.2 !important;
+   }
+   .highlight-todo.djs-shape .djs-visual > :nth-child(1) {
+     fill: orange !important;
+     stroke: orange !important;
+     stroke-dasharray: 4px !important;
+     fill-opacity: 0.2 !important;
+   }
+   .highlight-back.djs-connection > .djs-visual > path {
+     stroke: red !important;
+     stroke-dasharray: 4px !important;
+     fill-opacity: 0.2 !important;
+   }
+   .highlight-back.djs-shape .djs-visual > :nth-child(1) {
+     fill: red !important;
+     stroke: red !important;
+     stroke-dasharray: 4px !important;
+     fill-opacity: 0.2 !important;
+   }
+   .overlays-div {
+     font-size: 10px;
+     color: red;
+     width: 100px;
+     top: -20px !important;
+   }
+</style>
\ No newline at end of file
diff --git a/src/views/flowable/mixin/FlowableMixin.js b/src/views/flowable/mixin/FlowableMixin.js
new file mode 100644
index 0000000..50a76a4
--- /dev/null
+++ b/src/views/flowable/mixin/FlowableMixin.js
@@ -0,0 +1,68 @@
+import Vue from "vue";
+import {USER_INFO} from "@/store/mutation-types";
+
+/**
+ *
+ */
+
+export const FlowableMixin = {
+  data(){
+    return {
+      loginUser:{}
+    }
+  },
+  created() {
+    this.loginUser = Vue.ls.get(USER_INFO);
+  },
+  methods:{
+    // 褰撳墠鏁版嵁鏄惁鍙彁浜�
+    isCanApply(row){
+      // 娌℃湁娴佺▼瀹炰緥鐨勫嵆鍙彁浜�
+      return !Boolean(row.processInstanceId);
+    },
+    // 褰撳墠鏁版嵁鏄惁鍙挙鍥�
+    isCanRecall(row){
+      // 杩涜涓殑娴佺▼&&褰撳墠鑺傜偣涓嶆槸寮�濮嬭妭鐐�&&鐘舵�佷笉鏄�氳繃
+      return Boolean(row.processInstanceId)&&row.taskNameId!=='start'&&row.actStatus!=='瀹℃壒閫氳繃';
+    },
+    // 閲嶆柊鎻愪氦鎸夐挳
+    isCanReApply(row){
+      return row.taskNameId=='start'&&this.isTodoUsers(row);
+    },
+    // 閫氳繃鎸夐挳
+    isCanPass(row){
+      return row.taskNameId!=='start'&& this.isTodoUsers(row);
+    },
+    // 椹冲洖閫�鍥炴寜閽�
+    isCanBacke(row){
+      // 涓嶆槸start鑺傜偣&&鍦ㄥ彲鎿嶄綔浜哄憳鍒楄〃
+      return row.taskNameId!=='start'&&this.isTodoUsers(row);
+    },
+    // 鏌ョ湅瀹℃壒鍘嗗彶鎸夐挳
+    isCanHistoric(row){
+      // 鏈夊疄渚媔d灏辫兘鏌ョ湅
+      return Boolean(row.processInstanceId);
+    },
+    // 褰撳墠鐧诲綍浜烘槸鍚﹀湪澶勭悊浜哄垪琛�
+    isTodoUsers(row){
+      const todoUsers = row.todoUsers;
+      if (todoUsers&&todoUsers.length){
+        const parse = JSON.parse(todoUsers)||[];
+        return parse.includes(this.loginUser.username);
+      }else {
+        return false;
+      }
+    },
+    // 褰撳墠鐧诲綍浜烘槸鍚︽槸澶勭悊杩囩殑浜哄垪琛�
+    isDoneUsers(row){
+      const doneUsers = row.doneUsers;
+      if (doneUsers&&doneUsers.length){
+        const parse = JSON.parse(doneUsers)||[];
+        return parse.includes(this.loginUser.username);
+      }else {
+        return false;
+      }
+    },
+  }
+
+}
\ No newline at end of file
diff --git a/src/views/flowable/modeler/modelerDesign.vue b/src/views/flowable/modeler/modelerDesign.vue
new file mode 100644
index 0000000..673088f
--- /dev/null
+++ b/src/views/flowable/modeler/modelerDesign.vue
@@ -0,0 +1,400 @@
+<template>
+  <div>
+<!--  ==================娴佺▼瀹氫箟鍒楄〃===============  -->
+    <a-card v-if="!xmlFrame.open||xmlView">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
+      <el-form-item label="娴佺▼鍚嶇О" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="璇疯緭鍏ュ悕绉�"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="娴佺▼鍒嗙被" prop="category">
+        <el-select @change="handleQuery" v-model="queryParams.category" placeholder="璇烽�夋嫨娴佺▼鍒嗙被" clearable prop="category">
+          <el-option label="璇烽�夋嫨" value="" />
+          <el-option v-for="category in categorys" :key="category.id" :label="category.name" :value="category.id" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="婵�娲�" prop="active">
+        <el-switch
+          v-model="queryParams.active"
+          active-color="#13ce66"
+          inactive-color="#ff4949"
+          @change="handleQuery"
+        >
+        </el-switch>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+      <el-form-item style="float:right">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleLoadXml"
+        >鏂板娴佺▼瀹氫箟</el-button>
+      </el-form-item>
+    </el-form>
+
+      <el-table
+        v-loading="loading" fit
+        :data="definitionList"
+        row-key="id"
+        border
+        lazy
+        :load="load"
+        :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
+      <el-table-column label="娴佺▼瀹氫箟id" align="center" prop="id" />
+      <el-table-column label="娴佺▼鏍囪瘑Key" align="center" prop="key"  />
+      <el-table-column label="娴佺▼鍒嗙被" align="center" >
+        <template slot-scope="scope">
+            <span>{{ getCategoryName(scope.row.category) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="娴佺▼鍚嶇О" align="center" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-button type="text" @click="handleReadImage(scope.row.deploymentId)">
+            <span>{{ scope.row.name }}</span>
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="娴佺▼鐗堟湰" align="center">
+        <template slot-scope="scope">
+          <el-tag size="medium" >v{{ scope.row.version }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="鐘舵��" align="center">
+        <template slot-scope="scope">
+          <el-tag type="success" v-if="scope.row.suspensionState === 1">婵�娲�</el-tag>
+          <el-tag type="warning" v-if="scope.row.suspensionState === 2">鎸傝捣</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="閮ㄧ讲鏃堕棿" align="center" prop="deploymentTime" width="180"/>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-dropdown>
+            <span class="el-dropdown-link">
+              鏇村鎿嶄綔<i class="el-icon-arrow-down el-icon--right"></i>
+            </span>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item icon="el-icon-edit-outline" @click.native="handleLoadXml(scope.row)">
+                缂栬緫
+              </el-dropdown-item>
+<!--              <el-dropdown-item icon="el-icon-connection" @click.native="handleAddForm(scope.row)" v-if="scope.row.formId == null">
+                閰嶇疆琛ㄥ崟
+              </el-dropdown-item>-->
+              <el-dropdown-item icon="el-icon-video-pause" @click.native="handleUpdateSuspensionState(scope.row)" v-if="scope.row.suspensionState === 1">
+                鎸傝捣
+              </el-dropdown-item>
+              <el-dropdown-item icon="el-icon-video-play" @click.native="handleUpdateSuspensionState(scope.row)" v-if="scope.row.suspensionState === 2">
+                婵�娲�
+              </el-dropdown-item>
+              <el-dropdown-item icon="el-icon-delete" @click.native="handleDelete(scope.row)" >
+                鍒犻櫎
+              </el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      v-show="total>0"
+      :total="total"
+      :current-page.sync="queryParams.pageNum"
+      :page-size.sync="queryParams.pageSize"
+      @size-change="getList"
+      @current-change="getList"
+    />
+    </a-card>
+      <!-- 娴佺▼鍥� -->
+    <a-card v-if="xmlFrame.open&&!xmlView" :title="xmlFrame.title">
+      <a slot="extra" href="#" @click="()=>{xmlFrame.open=false}">杩斿洖</a>
+      <bpmn-modeler
+        v-if="xmlShow"
+        ref="refNode"
+        :xml="xmlData"
+        :users="users"
+        :groups="groups"
+        :categorys="categorys"
+        :is-view="xmlView"
+        @save="save"
+      />
+    </a-card>
+<!--  寮圭獥棰勮  -->
+      <a-modal :title="xmlFrame.title" :visible.sync="xmlView&&xmlFrame.open" :width="xmlFrame.width"
+        :footer="null" closable @cancel="()=>{xmlView=false,xmlFrame.open=false}"
+      >
+        <bpmn-modeler
+          v-if="xmlShow"
+          ref="refNode"
+          :xml="xmlData"
+          :users="users"
+          :groups="groups"
+          :categorys="categorys"
+          :is-view="xmlView"
+          @save="save"
+        />
+      </a-modal>
+
+  </div>
+</template>
+
+<script>
+import bpmnModeler from "workflow-bpmn-modeler";
+import {
+  categoryList,
+  delDeployment,
+  listDefinition,
+  readXml,
+  roleList,
+  saveXml,
+  updateState,
+  userList
+} from "@views/flowable/api/definition";
+
+export default {
+  components: {
+    bpmnModeler,
+  },
+  data() {
+    return {
+      /*===================璁捐鍣ㄥ睘鎬�======================*/
+      users: [],
+      groups: [],
+      categorys: [],
+      /*=================椤甸潰灞炴��===================*/
+      loading: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 娴佺▼瀹氫箟琛ㄦ牸鏁版嵁
+      definitionList: [],
+      allDefinitionList: [],
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        name: null,
+        category: null,
+        key: null,
+        tenantId: null,
+        deployTime: null,
+        derivedFrom: null,
+        derivedFromRoot: null,
+        parentDeploymentId: null,
+        engineVersion: null
+      },
+      xmlFrame:{
+        width:'70%',
+        title:'娴佺▼鍥�',
+        open: false,
+        src: "",
+      },
+      // xml
+      xmlData:"",
+      xmlShow: true,
+      xmlView: false,
+
+    };
+  },
+  created() {
+    this.initUserAndRole();
+    this.getList();
+  },
+  methods: {
+    /*===============璁捐鍣�===============*/
+    initUserAndRole(){
+      userList({}).then(res=>{
+        this.users = res.result||[]
+        this.users.map(o=>{
+          o.id = o.username
+          o.name = o.realname
+        })
+      })
+      roleList({}).then(res=>{
+        this.groups = res.result||[]
+        this.groups.map(o=>{
+          o.name = o.roleName
+        })
+      })
+      categoryList({}).then(res=>{
+        this.categorys = res.result||[]
+      })
+    },
+    getModelDetail(deployId) {
+      // 鍙戦�佽姹傦紝鑾峰彇xml
+      readXml(deployId).then(res =>{
+        this.xmlData = res.result;
+      })
+    },
+    getCategoryName(category){
+      let find = this.categorys.find(o=>o.id==category);
+      if (find){
+        return find.name
+      }
+      return ''
+    },
+    /*淇濆瓨娴佺▼瀹氫箟*/
+    save(data) {
+      console.log(data);  // { process: {...}, xml: '...', svg: '...' }
+      const params = {
+        name: data.process.name,
+        category: data.process.category,
+        xml: data.xml
+      }
+      saveXml(params).then(res => {
+        this.$message.success(res.message)
+        // 鍏抽棴褰撳墠鏍囩椤靛苟杩斿洖涓婁釜椤甸潰
+        this.getList()
+        this.xmlFrame.open = false
+      })
+    },
+    /*================椤甸潰===============*/
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.queryParams.suspensionState = this.queryParams.active?1:0;
+      this.getList();
+    },
+    /** 鏌ヨ娴佺▼瀹氫箟鍒楄〃 */
+    getList() {
+      this.loading = true;
+      // 鏈�鏂扮増鏈�
+      const param1 = Object.assign({
+        isLastVersion:1,
+      },this.queryParams)
+      listDefinition(param1).then(response => {
+        this.definitionList = response.result.records;
+        this.total = response.result.total;
+        this.loading = false;
+        for (const definition of this.definitionList) {
+          definition.hasChildren = true
+        }
+      });
+      // // 鎵�鏈�
+      // const param2 = Object.assign({
+      //   isLastVersion:0
+      // },this.queryParams,{
+      //   pageSize: 9999,
+      //   pageNum:1
+      // })
+      // listDefinition(param2).then(response => {
+      //   console.log(response)
+      //   this.allDefinitionList = response.result.records;
+      // });
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    resetForm(formName) {
+      this.$refs[formName].resetFields()
+    },
+    /** 鎵撳紑娴佺▼璁捐寮圭獥椤甸潰 */
+    handleLoadXml(row){
+      if (row&&row.deploymentId){
+        console.log(row.deploymentId)
+        this.handleReadImage(row.deploymentId)
+        this.xmlView = false
+        this.xmlFrame.title = "缂栬緫娴佺▼鍥�";
+      } else {
+        //鏂板
+        this.xmlData = ''
+        this.xmlView = false
+        this.xmlFrame.open = true
+        this.xmlFrame.title = '鏂板娴佺▼'
+        this.xmlShow = false
+        this.$nextTick(()=>{
+          this.xmlShow = true
+        })
+      }
+      this.xmlFrame.width = '90%'
+    },
+    /** 娴佺▼鍥炬煡鐪� */
+    handleReadImage(deploymentId){
+      this.xmlFrame.title = "娴佺▼鍥�";
+      this.xmlFrame.open = true;
+      this.xmlFrame.width = '70%';
+      // this.xmlFrame.src = process.env.VUE_APP_BASE_API + "/flowable/definition/xmlFrame/" + deploymentId;
+      // 鍙戦�佽姹傦紝鑾峰彇xml
+      this.xmlView = true
+      readXml(deploymentId).then(res =>{
+        if (res.success){
+          this.xmlData = res.result
+          /*this.xmlShow = false
+          this.$nextTick(()=>{
+            this.xmlShow = true
+          })*/
+        } else {
+          this.$message.error("鑾峰彇娴佺▼鍥惧け璐ワ紒")
+        }
+      })
+    },
+    // 鎵撳紑涓氬姟琛ㄥ崟
+    handleForm() {
+    },
+    // 閰嶇疆涓氬姟琛ㄥ崟
+    handleAddForm(row) {
+    },
+    /** 鎸傝捣/婵�娲绘祦绋� */
+    handleUpdateSuspensionState(row){
+      let state = 1;
+      if (row.suspensionState === 1) {
+        state = 2
+      }
+      const params = {
+        deployId: row.deploymentId,
+        state: state
+      }
+      updateState(params).then(res => {
+        this.$message.success(res.message);
+        this.getList();
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      // const ids = row.deploymentId || this.ids;
+      const params = {
+        deployId: row.deploymentId
+      }
+      this.$confirm({
+        title:"璀﹀憡",
+        content:'鏄惁纭鍒犻櫎娴佺▼瀹氫箟缂栧彿涓�"' + params.deployId + '"鐨勬暟鎹」?',
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning",
+        onOk:()=>{
+          delDeployment(params).then(res=>{
+            this.getList();
+            if (res.success){
+              this.$message.success('鍒犻櫎鎴愬姛');
+            } else {
+              this.$message.success('鍒犻櫎澶辫触');
+            }
+          })
+        }
+      })
+    },
+    load(tree, treeNode, resolve) {
+      const key = tree.key;
+      const childrens = []
+      for (const one of this.allDefinitionList) {
+        if (one.key==key&&one.id!=tree.id){
+          childrens.push(one)
+        }
+      }
+      console.log(tree, treeNode,this.allDefinitionList,childrens)
+      resolve(childrens)
+    }
+  },
+  computed: {
+    getContainer() {
+      return document.querySelector('#app')
+    }
+  }
+};
+</script>
\ No newline at end of file
diff --git a/src/views/flowable/workflow/FlowCompleted.vue b/src/views/flowable/workflow/FlowCompleted.vue
new file mode 100644
index 0000000..85dbb5a
--- /dev/null
+++ b/src/views/flowable/workflow/FlowCompleted.vue
@@ -0,0 +1,300 @@
+<!--
+ Description: 宸ヤ綔娴�-鎴戠殑宸插姙 List
+ Author: 浣滆�� liuyh
+ Date:   2025-02-27
+-->
+<template>
+  <a-card :bordered="false">
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="娴佺▼鍒嗙被">
+              <j-dict-select-tag placeholder="璇烽�夋嫨娴佺▼鍒嗙被" v-model="queryParam.category"
+                                 dictCode="flow_type"></j-dict-select-tag>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="10" :lg="11" :md="12" :sm="24">
+            <a-form-item label="鎿嶄綔鏃堕棿">
+              <j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
+                      class="query-group-cust"
+                      v-model="queryParam.startTime"></j-date>
+              <span class="query-group-split-cust"></span>
+              <j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="璇烽�夋嫨缁撴潫鏃堕棿"
+                      class="query-group-cust"
+                      v-model="queryParam.endTime"></j-date>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">鏌ヨ</a-button>
+              <a-button @click="searchReset" icon="reload" style="margin-left: 8px">閲嶇疆</a-button>
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 鏌ヨ鍖哄煙-END -->
+
+    <!-- table鍖哄煙-begin -->
+    <div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        :scroll="{x:true}"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        class="j-table-force-nowrap"
+        @change="handleTableChange">
+
+        <span slot="action" slot-scope="text, record">
+            <a @click="handelDetial(record,text)">璇︽儏</a>
+        </span>
+
+      </a-table>
+    </div>
+  </a-card>
+</template>
+
+<script>
+
+import '@/assets/less/TableExpand.less'
+import { mixinDevice } from '@/utils/mixin'
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+import JDictSelectTag from '@/components/dict/JDictSelectTag.vue'
+export default {
+  name: 'NcDeviceCharactersList',
+  mixins: [JeecgListMixin, mixinDevice],
+  components: {
+    JDictSelectTag,
+  },
+  data() {
+    return {
+      description: '宸ヤ綔娴�-宸插姙',
+      // 琛ㄥご
+      columns: [
+        {
+          title: '搴忓彿',
+          dataIndex: '',
+          key: 'rowIndex',
+          width: 200,
+          align: 'center',
+          customRender: function(t, r, index) {
+            return parseInt(index) + 1
+          }
+        },
+        {
+          title: '娴佺▼鍒嗙被',
+          align: 'center',
+          dataIndex: 'category_dictText',
+          width: 200
+        },
+        {
+          title: '娴佺▼鍚嶇О',
+          align: 'center',
+          dataIndex: 'procDefName',
+          width: 200
+        },
+        {
+          title: '娴佺▼涓氬姟绠�瑕佹弿杩�',
+          align: 'center',
+          dataIndex: 'description',
+          width: 300
+        },
+        {
+          title: '娴佺▼鍙戣捣浜哄悕绉�',
+          align: 'center',
+          dataIndex: 'startUserName',
+          width: 250
+        },
+        {
+          title: '浠诲姟鍚嶇О',
+          align: 'center',
+          dataIndex: 'taskName',
+          width: 250
+        },
+        {
+          title: '鎿嶄綔鏃堕棿',
+          align: 'center',
+          dataIndex: 'finishTime',
+          width: 300
+        },
+        {
+          title: '鎿嶄綔',
+          dataIndex: 'action',
+          scopedSlots: { customRender: 'action' },
+          align: 'center',
+          width: 200,
+          fixed: 'right'
+        }
+      ],
+      url: {
+        list: '/assign/flow/finishedList'
+      },
+      dictOptions: {},
+      selectShenpiData: {},
+      selectDispatchFileXqData: {},
+      selectWeekMaintenanceData: {},
+      selectInspectionOrderXqData: {},
+      selectRepairOrderData: {},
+      selectOutBoundOrderData: {},
+      selectLossBoundOrderData: {},
+      selectStocktakingBoundOrderData: {}
+    }
+  },
+  created() {
+  },
+  computed: {
+    importExcelUrl: function() {
+      return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
+    }
+  },
+  methods: {
+    handelDetial(item, index) {
+      console.log('鐐瑰嚮浜嗚鎯�')
+      console.log('item----->', item)
+      console.log('index----->', index)
+      let approcesstype = this.splitAprocessType(item.category)
+      console.log('approcesstype--->', approcesstype)
+      switch (approcesstype) {
+        case 'drApproval':
+          this.handDrDetial(item)
+          break
+        case 'ggApproval':
+          this.handDispatchFileDetial(item)
+          break
+        case 'sbdjApproval':
+          this.handInspectionOrder(item)
+          break
+        case 'WEEK_MAINTENANCE':
+          this.handleWeekMaintenance(item)
+          break
+        case 'eam_repair':
+          this.handleRepairOrder(item)
+          break
+        case 'toolOutStorageApproval':
+          this.handleToolOutStorageApproval(item)
+          break
+        case 'toolsStocktakingBound':
+          this.handleToolStocktakingApproval(item)
+          break
+        case 'toolsLossApproval':
+          this.handleToolLossApproval(item)
+          break
+        default:
+          alert('娌℃壘鍒拌娴佺▼')
+      }
+    },
+
+    splitAprocessType(title) {
+      let parts = title.split('锛�') // 娉ㄦ剰鍐掑彿鏄叏瑙掑瓧绗︼紝浣跨敤瀵瑰簲鐨勫瓧杩涜鍒嗗壊
+      let result = parts[0]
+      return result
+    },
+    handDrDetial(item) {
+      this.selectShenpiData = item
+      this.selectShenpiData.assignee_dictText = item.todoUsers_dictText
+      this.selectShenpiData.procInstId = item.procInsId
+      this.selectShenpiData.title = item.description
+      this.$refs.modalFormApproval.clearTableSource()
+      this.$refs.modalFormApproval.getAllApproveData(item)
+    },
+    handDispatchFileDetial(item) {
+      console.log('item----->', item)
+      this.selectDispatchFileXqData = item
+      this.selectDispatchFileXqData.assignee_dictText = item.todoUsers_dictText
+      this.selectDispatchFileXqData.procInstId = item.procInsId
+      this.selectDispatchFileXqData.processInstanceId = item.procInsId
+      this.selectDispatchFileXqData.title = item.description
+      this.$refs.modalFormDispatchFileXq.clearTableSource()
+      this.$refs.modalFormDispatchFileXq.getAllApproveData(item)
+    },
+    handleWeekMaintenance(record) {
+      this.selectWeekMaintenanceData = Object.assign({}, record)
+      this.$refs.weekMaintenanceApprovalModal.handleDetail(record)
+      this.$refs.weekMaintenanceApprovalModal.title = '璇︽儏'
+      this.$refs.weekMaintenanceApprovalModal.disableSubmit = true
+    },
+
+    handInspectionOrder(record) {
+      console.log('record----->', record)
+      this.selectInspectionOrderXqData = Object.assign({}, record)
+      const { todoUsers_dictText, procInsId, description, taskName } = this.selectInspectionOrderXqData
+      this.selectInspectionOrderXqData.assignee_dictText = todoUsers_dictText
+      this.selectInspectionOrderXqData.procInstId = procInsId
+      this.selectInspectionOrderXqData.processInstanceId = procInsId
+      this.selectInspectionOrderXqData.title = description
+      this.$refs.modalFormInspectionOrderXq.visible = true
+      this.$refs.modalFormInspectionOrderXq.title = taskName
+      this.$refs.modalFormInspectionOrderXq.disableSubmit = true
+      this.$refs.modalFormInspectionOrderXq.getAllApproveData({
+        ...record,
+        procInstId: procInsId,
+        processInstanceId: procInsId
+      })
+      this.$refs.modalFormInspectionOrderXq.getBasicInformation(record)
+    },
+
+    /**
+     * 鐐瑰嚮璁惧缁翠慨鍒嗙被娴佺▼璇︽儏鏃惰Е鍙�
+     * @param record
+     */
+    handleRepairOrder(record) {
+      this.selectRepairOrderData = Object.assign({}, record)
+      const { procInsId, taskName } = this.selectRepairOrderData
+      this.$refs.repairOrderApprovalModal.visible = true
+      this.$refs.repairOrderApprovalModal.disableSubmit = true
+      this.$refs.repairOrderApprovalModal.title = taskName
+      this.$refs.modalFormInspectionOrderXq.getAllApproveData({
+        ...record,
+        procInstId: procInsId,
+        processInstanceId: procInsId
+      })
+      this.$refs.repairOrderApprovalModal.getBasicInformation(record)
+    },
+
+    handleToolOutStorageApproval(item) {
+      this.selectOutBoundOrderData = Object.assign({}, item)
+      item.procInstId = item.procInsId
+      item.processInstanceId = item.procInsId
+      this.selectOutBoundOrderData.assignee_dictText = item.todoUsers_dictText
+      this.$refs.outBoundOrderHandle.auditVisible = false
+      this.$refs.outBoundOrderHandle.clearTableSource()
+      this.$refs.outBoundOrderHandle.getAllApproveData(item)
+    },
+
+    handleToolStocktakingApproval(item) {
+
+      this.selectStocktakingBoundOrderData = Object.assign({}, item)
+      item.procInstId = item.procInsId
+      item.processInstanceId = item.procInsId
+      this.selectStocktakingBoundOrderData.assignee_dictText = item.todoUsers_dictText
+      this.$refs.stocktakingBoundHandle.auditVisible = false
+      this.$refs.stocktakingBoundHandle.disableSubmit = true
+      this.$refs.stocktakingBoundHandle.clearTableSource()
+      this.$refs.stocktakingBoundHandle.getAllApproveData(item)
+
+    },
+    handleToolLossApproval(item) {
+      this.selectLossBoundOrderData = Object.assign({}, item)
+      item.procInstId = item.procInsId
+      item.processInstanceId = item.procInsId
+      this.selectStocktakingBoundOrderData.assignee_dictText = item.todoUsers_dictText
+      this.$refs.lossBoundHandle.auditVisible = false
+      this.$refs.lossBoundHandle.disableSubmit = true
+      this.$refs.lossBoundHandle.clearTableSource()
+      this.$refs.lossBoundHandle.getAllApproveData(item)
+
+    }
+  }
+}
+</script>
+<style scoped>
+@import '~@assets/less/common.less';
+</style>
\ No newline at end of file
diff --git a/src/views/flowable/workflow/FlowLedger.vue b/src/views/flowable/workflow/FlowLedger.vue
new file mode 100644
index 0000000..2e676a7
--- /dev/null
+++ b/src/views/flowable/workflow/FlowLedger.vue
@@ -0,0 +1,248 @@
+<!--
+ Description: 宸ヤ綔娴�-鎬诲彴璐� List
+ Author: 浣滆�� liuyh
+ Date:   2025-02-27
+-->
+<template>
+  <a-card :bordered="false">
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="娴佺▼鍒嗙被">
+              <j-dict-select-tag placeholder="璇烽�夋嫨娴佺▼鍒嗙被" v-model="queryParam.category"
+                                 dictCode="flow_type"></j-dict-select-tag>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="娴佺▼鍚嶇О">
+              <a-input placeholder="璇疯緭鍏ユ祦绋嬪悕绉�" v-model="queryParam.flowName"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="绠�瑕佹弿杩�">
+              <a-input placeholder="璇疯緭鍏ョ畝瑕佹弿杩�" v-model="queryParam.title"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="10" :lg="11" :md="12" :sm="24">
+            <a-form-item label="鎿嶄綔鏃堕棿">
+              <j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="璇烽�夋嫨寮�濮嬫椂闂�" class="query-group-cust"
+                      v-model="queryParam.startTime"></j-date>
+              <span class="query-group-split-cust"></span>
+              <j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="璇烽�夋嫨缁撴潫鏃堕棿" class="query-group-cust"
+                      v-model="queryParam.endTime"></j-date>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">鏌ヨ</a-button>
+              <a-button @click="searchReset" icon="reload" style="margin-left: 8px">閲嶇疆</a-button>
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 鏌ヨ鍖哄煙-END -->
+
+    <!-- 鎿嶄綔鎸夐挳鍖哄煙 -->
+
+    <!-- table鍖哄煙-begin -->
+    <div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        :scroll="{x:true}"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        class="j-table-force-nowrap"
+        @change="handleTableChange">
+
+        <span slot="action" slot-scope="text, record">
+            <a @click="handelDetail(record,text)">璇︽儏</a>
+        </span>
+      </a-table>
+    </div>
+
+  </a-card>
+</template>
+
+<script>
+
+import '@/assets/less/TableExpand.less'
+import { mixinDevice } from '@/utils/mixin'
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+import JDictSelectTag from '@/components/dict/JDictSelectTag.vue'
+
+  export default {
+    name: 'FlowLedger',
+    mixins: [JeecgListMixin, mixinDevice],
+    components: {
+      JDictSelectTag
+    },
+    data() {
+      return {
+        description: '娴佺▼绠$悊',
+        // 琛ㄥご
+        columns: [
+          {
+            title: '搴忓彿',
+            dataIndex: '',
+            key: 'rowIndex',
+            align: 'center',
+            customRender: function(t, r, index) {
+              return parseInt(index) + 1
+            }
+          },
+          {
+            title: '娴佺▼鍒嗙被',
+            align: 'center',
+            dataIndex: 'category_dictText',
+            width: 200
+          },
+          {
+            title: '娴佺▼鍚嶇О',
+            align: 'center',
+            dataIndex: 'flowName'
+          },
+          {
+            title: '娴佺▼涓氬姟绠�瑕佹弿杩�',
+            align: 'center',
+            dataIndex: 'description',
+          },
+          {
+            title: '鐢宠浜�',
+            align: 'center',
+            dataIndex: 'proposer_dictText'
+          },
+          {
+            title: '鍓嶉┍鑺傜偣',
+            align: 'center',
+            dataIndex: 'preNode'
+          },
+          {
+            title: '褰撳墠鑺傜偣',
+            align: 'center',
+            dataIndex: 'taskName'
+          },
+          {
+            title: '娴佺▼寮�濮嬫椂闂�',
+            align: 'center',
+            dataIndex: 'startTime'
+          },
+          {
+            title: '娴佺▼缁撴潫鏃堕棿',
+            align: 'center',
+            dataIndex: 'endTime'
+          },
+          {
+            title: '澶勭悊鏃堕暱',
+            align: 'center',
+            dataIndex: 'duration'
+          },
+          {
+            title: '褰撳墠浠诲姟浜�',
+            align: 'center',
+            dataIndex: 'todoUsers_dictText'
+          },
+          {
+            title: '澶勭悊杩囩殑浜�',
+            align: 'center',
+            dataIndex: 'doneUsers_dictText'
+          },
+          {
+            title: '鎿嶄綔',
+            dataIndex: 'action',
+            scopedSlots: { customRender: 'action' },
+            align: 'center',
+            width: 200,
+            fixed: 'right'
+          }
+        ],
+        url: {
+          list: '/assign/flow/list'
+        },
+        dictOptions: {},
+        selectShenpiData: {},
+        selectDispatchFileXqData: {},
+        selectInspectionOrderXqData: {}
+      }
+    },
+    created() {
+    },
+    computed: {
+      importExcelUrl: function() {
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
+      }
+    },
+    methods: {
+      handelDetail(item, index) {
+        console.log('鐐瑰嚮浜嗚鎯�')
+        console.log('item----->', item)
+        console.log('index----->', index)
+        let approcesstype = this.splitAprocessType(item.category)
+        console.log('approcesstype--->', approcesstype)
+        switch (approcesstype) {
+          case 'drApproval':
+            item.description=item.description
+            this.handDrDetial(item)
+            break
+          case 'ggApproval':
+            item.description=item.description
+            this.handDispatchFileDetial(item)
+            break
+          case 'sbdjApproval':
+            item.description = item.description
+            this.handInspectionOrderDetail(item)
+            break
+          default:
+            alert('娌℃壘鍒拌娴佺▼')
+        }
+      },
+      splitAprocessType(title) {
+        let parts = title.split('锛�') // 娉ㄦ剰鍐掑彿鏄叏瑙掑瓧绗︼紝浣跨敤瀵瑰簲鐨勫瓧杩涜鍒嗗壊
+        let result = parts[0]
+        return result
+      },
+      handDrDetial(item) {
+        this.selectShenpiData = item
+        this.selectShenpiData.assignee_dictText=item.todoUsers_dictText
+        this.selectShenpiData.createTime=item.startTime
+        this.selectShenpiData.procInstId=item.processInstanceId
+        this.$refs.modalFormApproval.clearTableSource()
+        this.$refs.modalFormApproval.getAllApproveData(item)
+      },
+      handDispatchFileDetial(item){
+        this.selectDispatchFileXqData = item
+
+
+
+
+
+        this.selectDispatchFileXqData.assignee_dictText=item.todoUsers_dictText
+        this.selectDispatchFileXqData.createTime=item.startTime
+        this.selectDispatchFileXqData.procInstId=item.processInstanceId
+        this.$refs.modalFormDispatchFileXq.clearTableSource()
+        this.$refs.modalFormDispatchFileXq.getAllApproveData(item)
+      },
+      handInspectionOrderDetail(item) {
+        this.selectInspectionOrderXqData = item
+        this.selectInspectionOrderXqData.assignee_dictText = item.todoUsers_dictText
+        this.selectInspectionOrderXqData.createTime = item.startTime
+        this.selectInspectionOrderXqData.procInstId = item.processInstanceId
+        this.$refs.modalFormInspectionOrderXq.visible = true
+        this.$refs.modalFormInspectionOrderXq.disableSubmit = true
+        this.$refs.modalFormInspectionOrderXq.getAllApproveData(item)
+        this.$refs.modalFormInspectionOrderXq.getBasicInformation(item)
+      }
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less';
+</style>
\ No newline at end of file
diff --git a/src/views/flowable/workflow/FlowTodo.vue b/src/views/flowable/workflow/FlowTodo.vue
new file mode 100644
index 0000000..81fec72
--- /dev/null
+++ b/src/views/flowable/workflow/FlowTodo.vue
@@ -0,0 +1,583 @@
+<!--
+ Description: 宸ヤ綔娴�-鎴戠殑寰呭姙 List
+ Author: 浣滆�� liuyh
+ Date:   2025-02-27
+-->
+<template>
+  <a-card :bordered='false'>
+    <!-- 鏌ヨ鍖哄煙 -->
+    <div class='table-page-search-wrapper'>
+      <a-form
+        layout='inline'
+        @keyup.enter.native='searchQuery'
+      >
+        <a-row :gutter='24'>
+          <a-col
+            :lg='6'
+            :md='8'
+            :sm='24'
+            :xl='4'
+          >
+            <a-form-item label='娴佺▼鍒嗙被'>
+              <j-dict-select-tag
+                v-model='queryParam.category'
+                dictCode='flow_type'
+                placeholder='璇烽�夋嫨娴佺▼鍒嗙被'
+              ></j-dict-select-tag>
+            </a-form-item>
+          </a-col>
+          <!--<a-col :xl="4" :lg="6" :md="8" :sm="24">-->
+          <!--<a-form-item label="娴佺▼鍚嶇О">-->
+          <!--<a-input placeholder="璇疯緭鍏ユ祦绋嬪悕绉�" v-model="queryParam.flowName"></a-input>-->
+          <!--</a-form-item>-->
+          <!--</a-col>-->
+          <a-col
+            :lg='6'
+            :md='8'
+            :sm='24'
+            :xl='4'
+          >
+            <a-form-item label='褰撳墠鑺傜偣'>
+              <a-input
+                v-model='queryParam.name'
+                placeholder='璇疯緭鍏ュ綋鍓嶈妭鐐圭簿纭煡璇�'
+              ></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col
+            :lg='6'
+            :md='8'
+            :sm='24'
+            :xl='4'
+          >
+            <a-form-item label='绠�瑕佹弿杩�'>
+              <a-input
+                v-model='queryParam.title'
+                placeholder='璇疯緭鍏ョ畝瑕佹弿杩�'
+              ></a-input>
+            </a-form-item>
+          </a-col>
+          <template v-if='toggleSearchStatus'>
+            <a-col
+              :lg='8'
+              :md='12'
+              :sm='24'
+              :xl='8'
+            >
+              <a-form-item label='浠诲姟鏃堕棿鑼冨洿'>
+                <j-date
+                  v-model='queryParam.startTime'
+                  :show-time='false'
+                  class='query-group-cust'
+                  date-format='YYYY-MM-DD HH:mm:ss'
+                  placeholder='璇烽�夋嫨寮�濮嬫椂闂�'
+                ></j-date>
+                <span class='query-group-split-cust'></span>
+                <j-date
+                  v-model='queryParam.endTime'
+                  :show-time='false'
+                  class='query-group-cust'
+                  date-format='YYYY-MM-DD HH:mm:ss'
+                  placeholder='璇烽�夋嫨缁撴潫鏃堕棿'
+                ></j-date>
+              </a-form-item>
+            </a-col>
+          </template>
+
+          <a-col
+            :lg='6'
+            :md='8'
+            :sm='24'
+            :xl='4'
+          >
+            <span
+              class='table-page-search-submitButtons'
+              style='float: left;overflow: hidden;'
+            >
+              <a-button
+                icon='search'
+                type='primary'
+                @click='searchQuery'
+              >鏌ヨ</a-button>
+              <a-button
+                icon='reload'
+                style='margin-left: 8px'
+                @click='searchReset'
+              >閲嶇疆</a-button>
+              <a
+                style='margin-left: 8px'
+                @click='handleToggleSearch'
+              >
+                {{ toggleSearchStatus ? '鏀惰捣' : '灞曞紑' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'" />
+              </a>
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 鏌ヨ鍖哄煙-END -->
+
+    <!-- 鎿嶄綔鎸夐挳鍖哄煙 -->
+    <div class='table-operator'>
+      <a-dropdown v-if='selectedRowKeys.length > 0 '>
+        <a-menu slot='overlay'>
+          <a-menu-item
+            key='1'
+            @click='batchHandle'
+          >
+            <a-icon type='delete' />
+            鎵归噺澶勭悊
+          </a-menu-item>
+        </a-menu>
+        <a-button style='margin-left: 8px'> 鎵归噺鎿嶄綔
+          <a-icon type='down' />
+        </a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table鍖哄煙-begin -->
+    <div>
+      <div
+        class='ant-alert ant-alert-info'
+        style='margin-bottom: 16px;'
+      >
+        <i class='anticon anticon-info-circle ant-alert-icon'></i>宸查�夋嫨&nbsp;<a style='font-weight: 600'>{{
+          selectedRowKeys.length }}</a>椤�&nbsp;&nbsp;
+        <a
+          style='margin-left: 24px'
+          @click='onClearSelected'
+        >娓呯┖</a>
+      </div>
+
+      <a-table
+        ref='table'
+        :columns='columns'
+        :dataSource='dataSource'
+        :loading='loading'
+        :pagination='ipagination'
+        :rowSelection='{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}'
+        :scroll='{x:getTableColumnsTotalWidth,y:465}'
+        bordered
+        rowKey='id'
+        size='middle'
+        @change='handleTableChange'
+      >
+
+        <span
+          slot='action'
+          slot-scope='text, record'
+        >
+          <a @click='handelDetail(record,text)'>鎵ц/瀹℃壒</a>
+        </span>
+
+      </a-table>
+    </div>
+  </a-card>
+</template>
+
+<script>
+
+import '@/assets/less/TableExpand.less'
+import { mixinDevice } from '@/utils/mixin'
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+import JDictSelectTag from '@/components/dict/JDictSelectTag.vue'
+import { getAction } from '@api/manage'
+export default {
+  name: 'NcDeviceCharactersList',
+  mixins: [JeecgListMixin, mixinDevice],
+  components: {
+    JDictSelectTag,
+  },
+  data() {
+    return {
+      description: '宸ヤ綔娴�-鎴戠殑寰呭姙',
+      // 琛ㄥご
+      columns: [
+        {
+          title: '搴忓彿',
+          dataIndex: '',
+          key: 'rowIndex',
+          width: 60,
+          align: 'center',
+          customRender: function (t, r, index) {
+            return parseInt(index) + 1
+          }
+        },
+        {
+          title: '娴佺▼鍒嗙被',
+          align: 'center',
+          dataIndex: 'category_dictText',
+          width: 100
+        },
+        {
+          title: '娴佺▼鍚嶇О',
+          align: 'center',
+          dataIndex: 'flowName',
+          width: 200
+        },
+        {
+          title: '娴佺▼涓氬姟绠�瑕佹弿杩�',
+          align: 'center',
+          dataIndex: 'description',
+          width: 350,
+          ellipsis: true
+
+        },
+        {
+          title: '涓婁竴姝ュ鐞嗕汉',
+          align: 'center',
+          dataIndex: 'preNodeAssignee_dictText',
+          width: 150
+        },
+        {
+          title: '鍓嶉┍鑺傜偣',
+          align: 'center',
+          dataIndex: 'preNode',
+          width: 200
+        },
+        {
+          title: '褰撳墠鑺傜偣',
+          align: 'center',
+          dataIndex: 'name',
+          width: 200
+        },
+        {
+          title: '褰撳墠鑺傜偣寮�濮嬫椂闂�',
+          align: 'center',
+          dataIndex: 'createTime',
+          width: 200
+        },
+        {
+          title: '鎿嶄綔',
+          dataIndex: 'action',
+          scopedSlots: { customRender: 'action' },
+          align: 'center',
+          width: 150,
+          fixed: 'right'
+        }
+      ],
+      url: {
+        list: '/assign/flow/toTaskBySelf',
+        isSameNode: '/assign/flow/isSameNode'
+      },
+      dictOptions: {},
+      selectShenpiData: {},
+      selectDispatchFileXqData: {},
+      selectInspectionOrderData: {},
+      selectWeekMaintenanceData: {},
+      selectSecondMaintenanceData: {},
+      selectThirdMaintenanceData: {},
+      selectBachData: {},
+      selectRepairOrderData: {},
+      selectOutBoundOrderData: {},
+      selectLossBoundOrderData: {},
+      selectStocktakingBoundOrderData: {},
+      selectInboundOrderData: {},
+      selectSparePartApplyData: {},
+      selectGuideCardData:{},
+      selectEquipmentAssignProductData:{},
+      selectEquipmentSealUpData:{},
+      //涓氬姟淇℃伅ID
+      dataId: undefined
+    }
+  },
+  created() {
+  },
+  computed: {
+    importExcelUrl: function () {
+      return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
+    },
+    getTableColumnsTotalWidth() {
+      return this.columns.reduce((total, item) => total + item.width, 0)
+    }
+  },
+  methods: {
+    loadData(arg) {
+      if (!this.url.list) {
+        this.$message.error('璇疯缃畊rl.list灞炴��!')
+        return
+      }
+      //鍔犺浇鏁版嵁 鑻ヤ紶鍏ュ弬鏁�1鍒欏姞杞界涓�椤电殑鍐呭
+      if (arg === 1) {
+        this.ipagination.current = 1
+      }
+      var params = this.getQueryParams()//鏌ヨ鏉′欢
+      if (!params) {
+        return false
+      }
+      this.loading = true
+      getAction(this.url.list, params).then((res) => {
+        if (res.success) {
+          // console.log(res)
+          //update-begin---author:zhangyafei    Date:20201118  for锛氶�傞厤涓嶅垎椤电殑鏁版嵁鍒楄〃------------
+          this.dataSource = res.result.records || res.result
+          if (res.result.total) {
+            this.ipagination.total = res.result.total
+          } else {
+            this.ipagination.total = 0
+          }
+          if (this.selectedRowKeys.length > 0) this.selectedRowKeys = this.selectionRows = []
+          //update-end---author:zhangyafei    Date:20201118  for锛氶�傞厤涓嶅垎椤电殑鏁版嵁鍒楄〃------------
+        } else {
+          this.$message.warning(res.message)
+        }
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+
+    handelDetail(item, index) {
+      console.log('鐐瑰嚮浜嗚鎯�')
+      console.log('item----->', item)
+      console.log('index----->', index)
+      let processType = this.splitAprocessType(item.category)
+      console.log('processType--->', processType)
+      switch (processType) {
+        case 'drApproval':
+          this.handDrDetial(item)
+          break
+        case 'ggApproval':
+          this.handDispatchFileDetial(item)
+          break
+        case 'ncFileSettingProcessApproval':
+          this.handStandardizedDetial(item)
+          break
+        case 'sbdjApproval':
+          this.handInspectionOrder(item)
+          break
+        case 'WEEK_MAINTENANCE':
+          this.handleWeekMaintenance(item)
+          break
+        case 'eam_repair':
+          this.handleRepairOrder(item)
+          break
+        case 'equipment_lean_out':
+          this.handleEquipmentLeanOut(item)
+          break
+        case 'second_maintenance':
+          this.handleSecondMaintenance(item)
+          break
+        case 'third_maintenance':
+          this.handleThirdMaintenance(item)
+          break
+        case 'toolOutStorageApproval':
+          this.handleToolOutStorageApproval(item)
+          break
+        case 'toolsStocktakingBound':
+          this.handleToolStocktakingApproval(item)
+          break
+        case 'toolsLossApproval':
+          this.handleToolLossApproval(item)
+          break
+        case 'equipment_seal_up':
+          this.handleEquipmentSealUp(item)
+          break
+        case 'toolInStorageApproval':
+          this.handleToolInStorage(item)
+          break
+        case 'equipment_transfer':
+          this.handleEquipmentTransfer(item)
+          break
+        case 'equipment_scrap':
+          this.handleEquipmentScrap(item)
+          break
+        case 'spare_part_apply':
+          this.handleSparePartApplyApproval(item)
+          break
+        case 'programConfirmApproval':
+          this.handleGuideCardApproval(item)
+          break
+        case 'equipmentAssignProductApproval':
+          this.handleEquipmentAssignProductApproval(item)
+          break
+        default:
+          alert('娌℃壘鍒拌娴佺▼')
+      }
+    },
+
+    batchHandle() {
+      const categorySet = new Set(this.selectionRows.map(item => item.category))
+      const nameSet = new Set(this.selectionRows.map(item => item.name))
+      if (categorySet.size !== 1 || nameSet.size !== 1) {
+        this.$notification.info({
+          message: '娑堟伅',
+          description: '璇烽�夋嫨鍚屼竴娴佺▼鍒嗙被涓嬬殑鍚屼竴褰撳墠鑺傜偣'
+        })
+        return
+      }
+
+      if (categorySet.has('eam_repair')) {
+        this.$notification.info({
+          message: '娑堟伅',
+          description: '璁惧缁翠慨娴佺▼鏃犳硶鎵归噺澶勭悊'
+        })
+        return
+      }
+
+      if (categorySet.has('sbdjApproval')) {
+        this.$refs.inspectionOrderBatchHandleRef.visible = true
+        this.$refs.inspectionOrderBatchHandleRef.title = this.selectionRows[0].name
+        this.$refs.inspectionOrderBatchHandleRef.getAllApproveData(this.selectionRows[0])
+        this.$refs.inspectionOrderBatchHandleRef.getBasicInformation(this.selectionRows[0])
+      } else if (categorySet.has('WEEK_MAINTENANCE')) {
+        this.$refs.weenMaintenanceBatchApprovalModalRef.handleDetail(this.selectionRows[0])
+        this.$refs.weenMaintenanceBatchApprovalModalRef.title = this.selectionRows[0].name
+      }
+    },
+
+    splitAprocessType(title) {
+      let parts = title.split('锛�') // 娉ㄦ剰鍐掑彿鏄叏瑙掑瓧绗︼紝浣跨敤瀵瑰簲鐨勫瓧杩涜鍒嗗壊
+      let result = parts[0]
+      return result
+    },
+    //DNC-鎸囨淳NC绋嬪簭鑷宠澶�
+    handDrDetial(item) {
+      this.selectShenpiData = item
+      this.$refs.modalFormApproval.clearTableSource()
+      this.$refs.modalFormApproval.getAllApproveData(item)
+    },
+    //DNC-NC绋嬪簭绛炬淳
+    handDispatchFileDetial(item) {
+      console.log('item----->', item)
+      this.selectDispatchFileXqData = item
+      this.$refs.modalFormDispatchFileXq.clearTableSource()
+      this.$refs.modalFormDispatchFileXq.getAllApproveData(item)
+    },
+    //DNC-瀹氬瀷瀹℃壒椤甸潰
+    handStandardizedDetial(item){
+      this.selectDispatchFileXqData = item
+      this.$refs.StandardizedProcessHandle.clearTableSource()
+      this.$refs.StandardizedProcessHandle.getAllApproveData(item)
+    },
+
+    handInspectionOrder(record) {
+      console.log('record----->', record)
+      this.selectInspectionOrderData = Object.assign({}, record)
+      this.$refs.modalFormInspectionOrder.visible = true
+      this.$refs.modalFormInspectionOrder.title = record.name
+      this.$refs.modalFormInspectionOrder.getAllApproveData(record)
+      this.$refs.modalFormInspectionOrder.getBasicInformation(record)
+    },
+
+    handleWeekMaintenance(item) {
+      if (item && item.dataId) {
+        this.selectWeekMaintenanceData = Object.assign({}, item)
+        this.$refs.weekMaintenanceApprovalModal.handleDetail(item)
+        this.$refs.weekMaintenanceApprovalModal.title = item.name
+        this.$refs.weekMaintenanceApprovalModal.disableSubmit = false
+      }
+    },
+
+    /**
+     * 鐐瑰嚮璁惧缁翠慨鍒嗙被娴佺▼璇︽儏鏃惰Е鍙�
+     * @param record
+     */
+    handleRepairOrder(record) {
+      this.selectRepairOrderData = Object.assign({}, record)
+      this.$refs.repairOrderApprovalModal.visible = true
+      this.$refs.repairOrderApprovalModal.title = record.name
+      this.$refs.repairOrderApprovalModal.getAllApproveData(record)
+      this.$refs.repairOrderApprovalModal.getBasicInformation(record)
+    },
+    handleEquipmentLeanOut(item) {
+      this.$refs.equipmentLeanOutApprovalModelRef.visible = true
+      this.$refs.equipmentLeanOutApprovalModelRef.title = item.name
+      this.$refs.equipmentLeanOutApprovalModelRef.handleDetail(item)
+      this.$refs.equipmentLeanOutApprovalModelRef.disableSubmit = false
+    },
+    handleSecondMaintenance(item) {
+      if (item && item.dataId) {
+        this.selectSecondMaintenanceData = Object.assign({}, item)
+        this.$refs.secondMaintenanceApprovalModal.handleDetail(item)
+        this.$refs.secondMaintenanceApprovalModal.title = item.name
+        this.$refs.secondMaintenanceApprovalModal.disableSubmit = false
+      }
+    },
+    handleThirdMaintenance(item) {
+      if (item && item.dataId) {
+        this.selectThirdMaintenanceData = Object.assign({}, item)
+        this.$refs.thirdMaintenanceApprovalModal.handleDetail(item)
+        this.$refs.thirdMaintenanceApprovalModal.title = item.name
+        this.$refs.thirdMaintenanceApprovalModal.disableSubmit = false
+      }
+    },
+    handleToolOutStorageApproval(item) {
+      if (item && item.dataId) {
+        this.selectOutBoundOrderData = Object.assign({}, item)
+        this.$refs.outBoundOrderHandle.auditVisible = true
+        this.$refs.outBoundOrderHandle.clearTableSource()
+        this.$refs.outBoundOrderHandle.getAllApproveData(item)
+      }
+    },
+    handleToolStocktakingApproval(item) {
+      if (item && item.dataId) {
+        this.selectStocktakingBoundOrderData = Object.assign({}, item)
+        this.$refs.stocktakingBoundHandle.auditVisible = true
+        this.$refs.stocktakingBoundHandle.clearTableSource()
+        this.$refs.stocktakingBoundHandle.getAllApproveData(item)
+      }
+    },
+    handleToolLossApproval(item) {
+      if (item && item.dataId) {
+        this.selectLossBoundOrderData = Object.assign({}, item)
+        this.$refs.lossBoundHandle.auditVisible = true
+        this.$refs.lossBoundHandle.clearTableSource()
+        this.$refs.lossBoundHandle.getAllApproveData(item)
+      }
+    },
+
+    handleEquipmentSealUp(item) {
+      this.$refs.equipmentSealUpApprovalModelRef.visible = true
+      this.$refs.equipmentSealUpApprovalModelRef.title = item.name
+      this.$refs.equipmentSealUpApprovalModelRef.handleDetail(item)
+      this.$refs.equipmentSealUpApprovalModelRef.disableSubmit = false
+    },
+    handleToolInStorage(item) {
+      if (item && item.dataId) {
+        this.selectInboundOrderData = Object.assign({}, item)
+        this.$refs.inboundOrderApprovalModal.auditVisible = true
+        this.$refs.inboundOrderApprovalModal.clearTableSource()
+        this.$refs.inboundOrderApprovalModal.getAllApproveData(item)
+      }
+    },
+    handleEquipmentTransfer(item) {
+      this.$refs.equipmentTransferApprovalModelRef.visible = true
+      this.$refs.equipmentTransferApprovalModelRef.title = item.name
+      this.$refs.equipmentTransferApprovalModelRef.handleDetail(item)
+      this.$refs.equipmentTransferApprovalModelRef.disableSubmit = false
+    },
+    handleEquipmentScrap(item) {
+      this.$refs.equipmentScrapApprovalModelRef.visible = true
+      this.$refs.equipmentScrapApprovalModelRef.title = item.name
+      this.$refs.equipmentScrapApprovalModelRef.handleDetail(item)
+      this.$refs.equipmentScrapApprovalModelRef.disableSubmit = false
+    },
+    handleSparePartApplyApproval(item) {
+      if (item && item.dataId) {
+        this.selectSparePartApplyData = Object.assign({}, item)
+        this.$refs.sparePartApplyModal.auditVisible = true
+        this.$refs.sparePartApplyModal.clearTableSource()
+        this.$refs.sparePartApplyModal.getAllApproveData(item)
+      }
+    },
+    //DNC-绋嬪簭纭琛ㄦ祦绋�
+    handleGuideCardApproval(item) {
+      console.log('item----->', item)
+      this.selectGuideCardData = item
+      this.$refs.guideCardBatchHandle.clearTableSource()
+      this.$refs.guideCardBatchHandle.getAllApproveData(item)
+    },
+    //DNC-璁惧缁撴瀯鏍戞寚娲句骇鍝佺粨鏋勬爲
+    handleEquipmentAssignProductApproval(item){
+      console.log('item----->', item)
+      this.selectEquipmentSealUpData = item
+      this.$refs.assignEquipmentFileStreamHandle.clearTableSource()
+      this.$refs.assignEquipmentFileStreamHandle.getAllApproveData(item)
+    }
+  }
+}
+</script>
+<style scoped>
+@import '~@assets/less/common.less';
+</style>
\ No newline at end of file

--
Gitblit v1.9.3