From 099189efd5d9cc94eee918351dc302ce9dfefbeb Mon Sep 17 00:00:00 2001
From: zhangherong <571457620@qq.com>
Date: 星期二, 20 五月 2025 13:56:03 +0800
Subject: [PATCH] art: 设备管理-二保、三保-审批表单添加

---
 src/views/flowable/workflow/secondMaintenance/SecondMaintenanceApprovalModal.vue |  536 ++++++++++++++++++++++++++++
 src/views/flowable/workflow/thirdMaintenance/ThirdMaintenanceApprovalModal.vue   |  536 ++++++++++++++++++++++++++++
 src/views/flowable/workflow/FlowTodo.vue                                         |   36 +
 3 files changed, 1,106 insertions(+), 2 deletions(-)

diff --git a/src/views/flowable/workflow/FlowTodo.vue b/src/views/flowable/workflow/FlowTodo.vue
index 0791ea4..c488506 100644
--- a/src/views/flowable/workflow/FlowTodo.vue
+++ b/src/views/flowable/workflow/FlowTodo.vue
@@ -120,6 +120,10 @@
                                            :taskList="selectionRows"/>
     <equipment-lean-out-approval-modal ref="equipmentLeanOutApprovalModelRef" @searchReset="searchReset"/>
 
+    <second-maintenance-approval-modal ref="secondMaintenanceApprovalModal" :selectShenpiData="selectSecondMaintenanceData"
+                                     @searchReset="searchReset"></second-maintenance-approval-modal>
+    <third-maintenance-approval-modal ref="thirdMaintenanceApprovalModal" :selectShenpiData="selectThirdMaintenanceData"
+                                       @searchReset="searchReset"></third-maintenance-approval-modal>
   </a-card>
 </template>
 
@@ -141,6 +145,8 @@
   import DispatchFileBachHandleStyle from '@views/flowable/workflow/dispatchFile/DispatchFileBachHandleStyle#Drawer.vue'
 
   import EquipmentLeanOutApprovalModal from '@views/flowable/workflow/leanOut/EquipmentLeanOutApprovalModal.vue'
+  import SecondMaintenanceApprovalModal from '@views/flowable/workflow/secondMaintenance/SecondMaintenanceApprovalModal.vue'
+  import ThirdMaintenanceApprovalModal from '@views/flowable/workflow/thirdMaintenance/ThirdMaintenanceApprovalModal.vue'
 
   export default {
     name: 'NcDeviceCharactersList',
@@ -155,7 +161,9 @@
       WeekMaintenanceApprovalModal,
       RepairOrderApprovalModal,
       InspectionOrderHandle,
-      EquipmentLeanOutApprovalModal
+      EquipmentLeanOutApprovalModal,
+      SecondMaintenanceApprovalModal,
+      ThirdMaintenanceApprovalModal
     },
     data() {
       return {
@@ -233,6 +241,8 @@
         selectDispatchFileXqData:{},
         selectInspectionOrderData: {},
         selectWeekMaintenanceData: {},
+        selectSecondMaintenanceData: {},
+        selectThirdMaintenanceData: {},
         selectBachData: {},
         selectRepairOrderData: {},
         //涓氬姟淇℃伅ID
@@ -308,6 +318,12 @@
             break
           case 'equipment_lean_out':
             this.handleEquipmentLeanOut(item)
+            break
+          case 'second_maintenance':
+            this.handleSecondMaintenance(item)
+            break
+          case 'third_maintenance':
+            this.handleThirdMaintenance(item)
             break
           default:
             alert('娌℃壘鍒拌娴佺▼')
@@ -398,7 +414,23 @@
         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
+        }
+      },
     }
   }
 </script>
diff --git a/src/views/flowable/workflow/secondMaintenance/SecondMaintenanceApprovalModal.vue b/src/views/flowable/workflow/secondMaintenance/SecondMaintenanceApprovalModal.vue
new file mode 100644
index 0000000..cffdeaa
--- /dev/null
+++ b/src/views/flowable/workflow/secondMaintenance/SecondMaintenanceApprovalModal.vue
@@ -0,0 +1,536 @@
+<template>
+  <j-modal
+    :title="title"
+    :width="1200"
+    :visible="visible"
+    :confirmLoading="confirmLoading"
+    :okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
+    switchFullscreen
+    @ok="handleOk"
+    @cancel="handleCancel"
+    centered
+    cancelText="鍏抽棴">
+
+    <a-spin :spinning="spinning">
+      <a-form-model ref="form" :model="model" :rules="validatorRules">
+        <a-divider orientation="center" style="font-size: large;font-style: italic;color: #66aeed;"> 淇濆吇鍩虹淇℃伅
+        </a-divider>
+        <a-row :gutter="24">
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="orderNum" label="宸ュ崟鍙�">
+              <a-input placeholder="宸ュ崟鍙风郴缁熻嚜鍔ㄧ敓鎴�" v-model="model.orderNum" disabled/>
+            </a-form-model-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="equipmentId" label="璁惧缂栫爜">
+              <maintenance-equipment-select placeholder="璇疯緭鍏ヨ澶囩紪鍙锋垨鍚嶇О鎼滅储" v-model="model.equipmentId"
+                                            :maintenanceCategory="maintenanceCategory"
+                                            @autocompleteForm="autocompleteForm"
+                                            disabled></maintenance-equipment-select>
+            </a-form-model-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="standardName" label="鏍囧噯鍚嶇О">
+              <a-input placeholder="閫夋嫨璁惧鍚庤嚜鍔ㄥ甫鍑�" v-model="model.standardName" disabled/>
+            </a-form-model-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="maintenanceDate" label="淇濆吇鏃ユ湡">
+              <a-date-picker placeholder="璇烽�夋嫨璁″垝淇濆吇鏃ユ湡" v-model="model.maintenanceDate" format="YYYY-MM-DD"
+                             disabled
+                             style="width: 100%"/>
+            </a-form-model-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="operator" label="淇濆吇浜�">
+              <j-search-select-tag v-model="model.operator" placeholder="璇烽�夋嫨淇濆吇浜�" disabled
+                                   :dictOptions="maintenanceOperatorOptions"/>
+            </a-form-model-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="maintenancePeriod" label="淇濆吇鍛ㄦ湡">
+              <a-input placeholder="閫夋嫨璁惧鍚庤嚜鍔ㄥ甫鍑�" v-model="model.maintenancePeriod" disabled/>
+            </a-form-model-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-form-model-item :labelCol="labelColLong" :wrapperCol="wrapperColLong" prop="remark" label="澶囨敞">
+            <a-textarea placeholder="璇疯緭鍏ュ娉�" v-model="model.remark" disabled/>
+          </a-form-model-item>
+        </a-row>
+        <a-row :gutter="24">
+          <a-form-model-item :labelCol="labelColLong" :wrapperCol="wrapperColLong" label="淇濆吇鍥剧墖">
+            <lx-upload :returnUrl="false"
+                       :isMultiple="true"
+                       file-type="image"
+                       :disabled="confirmDisable"
+                       :number="3"
+                       v-model="model.imageFilesResult"/>
+          </a-form-model-item>
+        </a-row>
+        <a-divider orientation="center" style="font-size: large;font-style: italic;color: #66aeed;"> 淇濆吇椤逛俊鎭�
+        </a-divider>
+        <a-row :gutter="24">
+          <a-tabs v-model="activeTabKey">
+            <a-tab-pane key="1" tab="淇濆吇椤规槑缁�">
+              <j-vxe-table
+                ref="editableDetailTable"
+                :rowNumber="false"
+                :rowSelection="true"
+                :bordered="true"
+                :alwaysEdit="true"
+                :toolbar="false"
+                keep-source
+                :height="300"
+                :loading="detail.loading"
+                :dataSource="detail.dataSource"
+                :columns="detail.columns"
+                @selectRowChange="handleTableSelectRowChange"
+              >
+                <template v-slot:maintenanceResult="props">
+                  <j-dict-select-tag v-model="props.row.maintenanceResult" dictCode="eam_inspection_result"
+                                     placeholder="璇烽�夋嫨淇濆吇缁撴灉"
+                                     :disabled="disableSubmit || confirmDisable"
+                                     @change="handleInspectionResultSelectChange($event,props.row)"
+                                     style="width: 100%"/>
+                </template>
+
+                <template v-slot:exceptionDescription="props">
+                  <a-textarea style="height: 32px" v-model="props.row.exceptionDescription"
+                              :disabled="disableSubmit || confirmDisable || !props.row.maintenanceResult || props.row.maintenanceResult === '1'"/>
+                </template>
+
+                <template v-slot:reportFlag="props">
+                  <j-dict-select-tag v-model="props.row.reportFlag"
+                                     :disabled="disableSubmit || confirmDisable || !props.row.maintenanceResult || props.row.maintenanceResult === '1'"
+                                     dictCode="yn"
+                                     style="width: 100%"/>
+                </template>
+              </j-vxe-table>
+            </a-tab-pane>
+            <template v-if="selectShenpiData.procInstId">
+              <a-tab-pane key='2' tab='娴佺▼鑺傜偣'>
+                <a-card :bordered="false">
+                  <a-timeline>
+                    <a-timeline-item v-for="(item,index) in taskData" :key="index">
+                      <div>
+                        <h3 style="font-weight: bold;">{{item.taskName}}</h3>
+                        <div>澶勭悊浜猴細{{item.assignee_dictText}}</div>
+                        <div v-if="index !==0">澶勭悊鏃堕暱锛歿{item.duration}}</div>
+                        <div v-if="item.name !== '鎻愪氦鐢宠'">澶勭悊绫诲瀷锛歿{item.sequenceFlowName}}</div>
+                        <div v-if="item.description">澶勭悊鎰忚锛歿{item.description}}</div>
+                      </div>
+                    </a-timeline-item>
+                  </a-timeline>
+                </a-card>
+              </a-tab-pane>
+              <a-tab-pane key='3' tab='娴佺▼鍥�'>
+                <img :src="imageSrc" alt="Fetched Image"/>
+              </a-tab-pane>
+            </template>
+            <a-button v-if="!disableSubmit &&!confirmDisable&& selectedRowKeys.length > 0" slot="tabBarExtraContent"
+                      type="primary" @click="handleSelectAllInspectionResult">淇濆吇姝e父
+            </a-button>
+          </a-tabs>
+        </a-row>
+        <div v-if="confirmDisable">
+          <a-divider orientation="center" style="font-size: large;font-style: italic;color: #66aeed;"> 绠$悊鍛樼‘璁や俊鎭�
+          </a-divider>
+          <a-row :gutter="24">
+            <a-col :span="12">
+              <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="confirmDealType" label="纭绫诲瀷">
+                <j-dict-select-tag type='radio' v-model='model.confirmDealType' dictCode='approved_rejected'
+                                   placeholder="璇烽�夋嫨澶勭悊绫诲瀷" :disabled="disableSubmit || leaderConfirmDisable"/>
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="12">
+              <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="confirmComment" label="纭鎰忚">
+                <a-textarea placeholder="璇疯緭鍏ユ剰瑙�" v-model="model.confirmComment"
+                            :disabled="disableSubmit || leaderConfirmDisable"/>
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+        </div>
+        <div v-if="leaderConfirmDisable">
+          <a-divider orientation="center" style="font-size: large;font-style: italic;color: #66aeed;"> 棰嗗纭淇℃伅
+          </a-divider>
+          <a-row :gutter="24">
+            <a-col :span="24">
+              <a-form-model-item :labelCol="labelColLong" :wrapperCol="wrapperColLong" prop="leaderConfirmComment"
+                                 label="棰嗗鎰忚">
+                <a-textarea placeholder="璇疯緭鍏ユ剰瑙�" v-model="model.leaderConfirmComment"
+                            :disabled="disableSubmit || completionDisable"/>
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+        </div>
+      </a-form-model>
+    </a-spin>
+  </j-modal>
+</template>
+
+<script>
+  import { downFile, getAction, httpAction } from '@/api/manage'
+  import { JVxeTableModelMixin } from '@/mixins/JVxeTableModelMixin.js'
+  import { JVXETypes } from '@comp/jeecg/JVxeTable'
+  import MaintenanceEquipmentSelect from '@views/eam/equipment/modules/MaintenanceEquipmentSelect'
+
+  export default {
+    name: 'SecondMaintenanceApprovalModal',
+    mixins: [JVxeTableModelMixin],
+    components: {
+      MaintenanceEquipmentSelect
+    },
+    props: {
+      selectShenpiData: {
+        type: Object
+      }
+    },
+    data() {
+      return {
+        title: '鎿嶄綔',
+        visible: false,
+        //鐘舵�佹帶鍒�
+        //淇濆吇涓� 涓嶅彲缂栬緫
+        // confirmDisable: false,
+        // initialAcceptanceDisable: false,
+        // finalAcceptanceDisable: false,
+        editable: false,
+        model: {},
+        maintenanceCategory: 'SECOND_MAINTENANCE',
+        maintenanceOperatorOptions: [],
+        labelCol: {
+          xs: { span: 24 },
+          sm: { span: 6 }
+        },
+        wrapperCol: {
+          xs: { span: 24 },
+          sm: { span: 16 }
+        },
+        labelColLong: {
+          xs: { span: 24 },
+          sm: { span: 2 }
+        },
+        wrapperColLong: {
+          xs: { span: 24 },
+          sm: { span: 21 }
+        },
+        confirmLoading: false,
+        spinning: false,
+        imageSrc: null,
+        activeTabKey: '1',
+        validatorRules: {
+          confirmDealType: [
+            { required: true, message: '璇烽�夋嫨閫氳繃鎴栭┏鍥�!' }
+          ],
+          confirmComment: [
+            { required: true, message: '璇疯緭鍏ョ‘璁ゆ剰瑙�!' }
+          ],
+          leaderConfirmComment: [
+            { required: true, message: '璇疯緭鍏ュ垵楠屾敹鎰忚!' }
+          ],
+        },
+        url: {
+          queryById: '/eam/secondMaintenanceOrder/queryById',
+          detail: '/eam/secondMaintenanceOrderDetail/queryList',
+          approval: '/eam/secondMaintenanceOrder/approval',
+          userSelect: '/eam/user_select/list',
+          queryHisTaskList: '/assign/flow/queryHisTaskList',
+          diagramView: '/assign/flow/diagramView'
+        },
+        disableSubmit: false,
+        taskData: [],
+        isDisplayBmp: false,
+        showBmpButtonLoading: false,
+        selectedRowKeys: [],
+        detail: {
+          loading: false,
+          dataSource: [],
+          columns: [
+            {
+              title: 'ID',
+              key: 'id',
+              type: JVXETypes.hidden
+            },
+            {
+              title: 'orderId',
+              key: 'orderId',
+              type: JVXETypes.hidden
+            },
+            {
+              title: '搴忓彿',
+              key: 'itemCode',
+              type: JVXETypes.normal,
+              width: '5%',
+              align: 'center'
+            },
+            {
+              title: '淇濆吇椤�',
+              key: 'itemName',
+              type: JVXETypes.normal,
+              width: '10%',
+              align: 'center'
+            },
+            {
+              title: '瀛愪繚鍏婚」',
+              key: 'subItemName',
+              type: JVXETypes.normal,
+              width: '10%',
+              align: 'center'
+            },
+            {
+              title: '淇濆吇瑕佹眰',
+              key: 'itemDemand',
+              type: JVXETypes.normal,
+              width: '20%',
+              align: 'center'
+            },
+            {
+              title: '淇濆吇缁撴灉',
+              key: 'maintenanceResult',
+              type: JVXETypes.slot,
+              width: '10%',
+              align: 'center',
+              slotName: 'maintenanceResult',
+              validateRules: [
+                { required: true, message: '淇濆吇缁撴灉涓嶈兘涓虹┖锛�' }
+              ]
+            },
+            {
+              title: '寮傚父鎻忚堪',
+              key: 'exceptionDescription',
+              type: JVXETypes.slot,
+              width: '20%',
+              align: 'center',
+              slotName: 'exceptionDescription',
+              validateRules: [
+                { handler: this.customValidator }
+              ]
+            },
+            {
+              title: '鏄惁鎶ヤ慨',
+              key: 'reportFlag',
+              type: JVXETypes.slot,
+              width: '10%',
+              align: 'center',
+              slotName: 'reportFlag',
+              validateRules: [
+                { handler: this.customValidator }
+              ]
+            }
+          ],
+          toolbarConfig: {
+            // prefix 鍓嶇紑锛泂uffix 鍚庣紑
+            slot: ['prefix', 'suffix'],
+            // add 鏂板鎸夐挳锛況emove 鍒犻櫎鎸夐挳锛沜learSelection 娓呯┖閫夋嫨鎸夐挳
+            btn: ['clearSelection']
+          }
+        }
+      }
+    },
+    created() {
+    },
+    computed: {
+      confirmDisable: function() {
+        return ['WAIT_CONFIRM', 'WAIT_LEADER_CONFIRM', 'COMPLETE'].includes(this.model.maintenanceStatus)
+      },
+      leaderConfirmDisable: function() {
+        return ['WAIT_LEADER_CONFIRM', 'COMPLETE'].includes(this.model.maintenanceStatus)
+      },
+      completionDisable: function() {
+        return ['COMPLETE', 'ABOLISH'].includes(this.model.maintenanceStatus)
+      }
+    },
+    methods: {
+      async handleDetail(item) {
+        this.initParams()
+        this.model = {}
+        if (item.procInstId) {
+          const { processDefinitionId, processInstanceId, processDefinitionKey, procInstId } = item
+
+          let taskDataList = await getAction(this.url.queryHisTaskList, { procInstId })
+          this.taskData = [...taskDataList.result]
+
+          downFile(this.url.diagramView, {
+            processDefinitionId,
+            processInstanceId,
+            TaskDefinitionKey: processDefinitionKey
+          }, 'get')
+            .then((res => {
+              const urlObject = window.URL.createObjectURL(new Blob([res]))
+              this.imageSrc = urlObject
+            }))
+            .catch(err => {
+              this.$notification.error({
+                message: '娑堟伅',
+                description: res.message
+              })
+            })
+        }
+        let res = await getAction(this.url.queryById, { id: item.dataId })
+        this.model = Object.assign({}, res.result)
+        if (this.model.imageFiles) {
+          let obj = JSON.parse(this.model.imageFiles)
+          this.model.imageFilesResult = [...obj]
+        }
+        this.model.dataId = item.dataId
+        this.model.taskId = item.id
+        this.model.userId = item.assignee
+        this.model.instanceId = item.procInstId
+        this.model.values = item.variables
+        await this.loadDetail(item.dataId)
+      },
+
+      recordDetail(record) {
+        console.log('record', record)
+        this.initParams()
+        this.model = Object.assign({}, record)
+        if (this.model.imageFiles) {
+          let obj = JSON.parse(this.model.imageFiles)
+          this.model.imageFilesResult = [...obj]
+        }
+        this.loadDetail(record.id)
+      },
+
+      initParams() {
+        this.detail.dataSource = []
+        this.visible = true
+        this.activeTabKey = '1'
+        this.spinning = true
+      },
+
+      async handleOk() {
+        const that = this
+        let errMap = await that.$refs.editableDetailTable.validateTable()
+        if (errMap) {
+          this.$message.warning('鏁版嵁鏍¢獙澶辫触锛�')
+          return
+        }
+        // 瑙﹀彂琛ㄥ崟楠岃瘉
+        this.$refs.form.validate(valid => {
+          if (valid) {
+            that.confirmLoading = that.spinning = true
+            let tableData = that.$refs.editableDetailTable.getTableData()
+            that.model.tableDetailList = [...tableData]
+            let httpurl = this.url.approval
+            let method = 'put'
+
+            httpAction(httpurl, this.model, method).then((res) => {
+              if (res.success) {
+                that.$message.success(res.message)
+                that.$emit('searchReset')
+                that.close()
+              } else {
+                that.$message.warning(res.message)
+              }
+            }).finally(() => {
+              that.confirmLoading = that.spinning = false
+            })
+          } else {
+            return false
+          }
+        })
+      },
+
+      autocompleteForm(selectObj) {
+        this.$set(this.model, 'standardName', selectObj.standardName)
+        this.$set(this.model, 'maintenancePeriod', selectObj.maintenancePeriod)
+        this.$set(this.model, 'standardId', selectObj.id)
+        this.$set(this.model, 'equipmentId', selectObj.equipmentId)
+        // console.log('model', this.model)
+        if (!this.model.id) {
+          this.loadStandardDetail(selectObj.id)
+        }
+        this.loadMaintenanceOperatorList(this.model.equipmentId)
+      },
+
+      //鏍囧噯閫夋嫨鍙樺寲
+      loadDetail(orderId) {
+        if (orderId) {
+          getAction(this.url.detail, { orderId: orderId })
+            .then(res => {
+              if (res.success) {
+                this.detail.dataSource = [...res.result]
+              }
+            })
+            .finally(() => {
+              this.spinning = false
+            })
+        }
+      },
+
+      loadMaintenanceOperatorList(equipmentId) {
+        this.maintenanceOperatorOptions = []
+        let params = { positionCode: 'PCR0001' }
+        if (equipmentId) {
+          params.equipmentId = equipmentId
+        }
+        getAction(this.url.userSelect, params).then(res => {
+          if (res.success) {
+            this.maintenanceOperatorOptions = res.result.map(item => ({
+              key: item.id,
+              value: item.username,
+              text: item.realname
+            }))
+          }
+        })
+      },
+
+      handleInspectionResultSelectChange(value, record) {
+        if (record.exceptionDescription) delete record.exceptionDescription
+        if (record.reportFlag) delete record.reportFlag
+      },
+
+      // 鎵归噺閫夋嫨鎵�鏈夌偣妫�缁撴灉
+      handleSelectAllInspectionResult() {
+        this.selectedRowKeys.forEach(key => {
+          const dataItem = this.detail.dataSource.find(item => item.id === key)
+          if (dataItem && dataItem.maintenanceResult !== '1') {
+            console.log('dataItem', dataItem)
+            delete dataItem.exceptionDescription
+            delete dataItem.reportFlag
+            dataItem.maintenanceResult = '1'
+          }
+        })
+        this.$refs.editableDetailTable.clearCheckboxRow()
+        this.selectedRowKeys = []
+      },
+
+      /**
+       * 琛ㄦ牸澶氶�夋鍙戠敓鏀瑰彉鏃惰Е鍙�
+       * @param {selectedRowIds} 琛ㄦ牸涓凡閫夋嫨鐨処D鍒楄〃
+       */
+      handleTableSelectRowChange({ selectedRowIds }) {
+        this.selectedRowKeys = selectedRowIds
+      },
+
+      customValidator({ cellValue, row }, callback) {
+        if (row.maintenanceResult === '2') {
+          if (!cellValue) {
+            callback(false, '${title}涓嶈兘涓虹┖锛�') // false = 鏈�氳繃锛屽彲浠ヨ窡鑷畾涔夋彁绀�
+          } else {
+            callback(true) // true = 閫氳繃楠岃瘉
+          }
+        } else {
+          callback(true)
+        }
+      },
+
+      handleCancel() {
+        this.close()
+      },
+
+      close() {
+        this.$emit('close')
+        this.visible = false
+        this.$refs.form.clearValidate()
+      }
+    }
+  }
+</script>
+
+<style lang="less" scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/flowable/workflow/thirdMaintenance/ThirdMaintenanceApprovalModal.vue b/src/views/flowable/workflow/thirdMaintenance/ThirdMaintenanceApprovalModal.vue
new file mode 100644
index 0000000..6c9d5fa
--- /dev/null
+++ b/src/views/flowable/workflow/thirdMaintenance/ThirdMaintenanceApprovalModal.vue
@@ -0,0 +1,536 @@
+<template>
+  <j-modal
+    :title="title"
+    :width="1200"
+    :visible="visible"
+    :confirmLoading="confirmLoading"
+    :okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
+    switchFullscreen
+    @ok="handleOk"
+    @cancel="handleCancel"
+    centered
+    cancelText="鍏抽棴">
+
+    <a-spin :spinning="spinning">
+      <a-form-model ref="form" :model="model" :rules="validatorRules">
+        <a-divider orientation="center" style="font-size: large;font-style: italic;color: #66aeed;"> 淇濆吇鍩虹淇℃伅
+        </a-divider>
+        <a-row :gutter="24">
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="orderNum" label="宸ュ崟鍙�">
+              <a-input placeholder="宸ュ崟鍙风郴缁熻嚜鍔ㄧ敓鎴�" v-model="model.orderNum" disabled/>
+            </a-form-model-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="equipmentId" label="璁惧缂栫爜">
+              <maintenance-equipment-select placeholder="璇疯緭鍏ヨ澶囩紪鍙锋垨鍚嶇О鎼滅储" v-model="model.equipmentId"
+                                            :maintenanceCategory="maintenanceCategory"
+                                            @autocompleteForm="autocompleteForm"
+                                            disabled></maintenance-equipment-select>
+            </a-form-model-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="standardName" label="鏍囧噯鍚嶇О">
+              <a-input placeholder="閫夋嫨璁惧鍚庤嚜鍔ㄥ甫鍑�" v-model="model.standardName" disabled/>
+            </a-form-model-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="maintenanceDate" label="淇濆吇鏃ユ湡">
+              <a-date-picker placeholder="璇烽�夋嫨璁″垝淇濆吇鏃ユ湡" v-model="model.maintenanceDate" format="YYYY-MM-DD"
+                             disabled
+                             style="width: 100%"/>
+            </a-form-model-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="operator" label="淇濆吇浜�">
+              <j-search-select-tag v-model="model.operator" placeholder="璇烽�夋嫨淇濆吇浜�" disabled
+                                   :dictOptions="maintenanceOperatorOptions"/>
+            </a-form-model-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="maintenancePeriod" label="淇濆吇鍛ㄦ湡">
+              <a-input placeholder="閫夋嫨璁惧鍚庤嚜鍔ㄥ甫鍑�" v-model="model.maintenancePeriod" disabled/>
+            </a-form-model-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-form-model-item :labelCol="labelColLong" :wrapperCol="wrapperColLong" prop="remark" label="澶囨敞">
+            <a-textarea placeholder="璇疯緭鍏ュ娉�" v-model="model.remark" disabled/>
+          </a-form-model-item>
+        </a-row>
+        <a-row :gutter="24">
+          <a-form-model-item :labelCol="labelColLong" :wrapperCol="wrapperColLong" label="淇濆吇鍥剧墖">
+            <lx-upload :returnUrl="false"
+                       :isMultiple="true"
+                       file-type="image"
+                       :disabled="confirmDisable"
+                       :number="3"
+                       v-model="model.imageFilesResult"/>
+          </a-form-model-item>
+        </a-row>
+        <a-divider orientation="center" style="font-size: large;font-style: italic;color: #66aeed;"> 淇濆吇椤逛俊鎭�
+        </a-divider>
+        <a-row :gutter="24">
+          <a-tabs v-model="activeTabKey">
+            <a-tab-pane key="1" tab="淇濆吇椤规槑缁�">
+              <j-vxe-table
+                ref="editableDetailTable"
+                :rowNumber="false"
+                :rowSelection="true"
+                :bordered="true"
+                :alwaysEdit="true"
+                :toolbar="false"
+                keep-source
+                :height="300"
+                :loading="detail.loading"
+                :dataSource="detail.dataSource"
+                :columns="detail.columns"
+                @selectRowChange="handleTableSelectRowChange"
+              >
+                <template v-slot:maintenanceResult="props">
+                  <j-dict-select-tag v-model="props.row.maintenanceResult" dictCode="eam_inspection_result"
+                                     placeholder="璇烽�夋嫨淇濆吇缁撴灉"
+                                     :disabled="disableSubmit || confirmDisable"
+                                     @change="handleInspectionResultSelectChange($event,props.row)"
+                                     style="width: 100%"/>
+                </template>
+
+                <template v-slot:exceptionDescription="props">
+                  <a-textarea style="height: 32px" v-model="props.row.exceptionDescription"
+                              :disabled="disableSubmit || confirmDisable || !props.row.maintenanceResult || props.row.maintenanceResult === '1'"/>
+                </template>
+
+                <template v-slot:reportFlag="props">
+                  <j-dict-select-tag v-model="props.row.reportFlag"
+                                     :disabled="disableSubmit || confirmDisable || !props.row.maintenanceResult || props.row.maintenanceResult === '1'"
+                                     dictCode="yn"
+                                     style="width: 100%"/>
+                </template>
+              </j-vxe-table>
+            </a-tab-pane>
+            <template v-if="selectShenpiData.procInstId">
+              <a-tab-pane key='2' tab='娴佺▼鑺傜偣'>
+                <a-card :bordered="false">
+                  <a-timeline>
+                    <a-timeline-item v-for="(item,index) in taskData" :key="index">
+                      <div>
+                        <h3 style="font-weight: bold;">{{item.taskName}}</h3>
+                        <div>澶勭悊浜猴細{{item.assignee_dictText}}</div>
+                        <div v-if="index !==0">澶勭悊鏃堕暱锛歿{item.duration}}</div>
+                        <div v-if="item.name !== '鎻愪氦鐢宠'">澶勭悊绫诲瀷锛歿{item.sequenceFlowName}}</div>
+                        <div v-if="item.description">澶勭悊鎰忚锛歿{item.description}}</div>
+                      </div>
+                    </a-timeline-item>
+                  </a-timeline>
+                </a-card>
+              </a-tab-pane>
+              <a-tab-pane key='3' tab='娴佺▼鍥�'>
+                <img :src="imageSrc" alt="Fetched Image"/>
+              </a-tab-pane>
+            </template>
+            <a-button v-if="!disableSubmit &&!confirmDisable&& selectedRowKeys.length > 0" slot="tabBarExtraContent"
+                      type="primary" @click="handleSelectAllInspectionResult">淇濆吇姝e父
+            </a-button>
+          </a-tabs>
+        </a-row>
+        <div v-if="confirmDisable">
+          <a-divider orientation="center" style="font-size: large;font-style: italic;color: #66aeed;"> 鏈哄姩鍔炵‘璁や俊鎭�
+          </a-divider>
+          <a-row :gutter="24">
+            <a-col :span="12">
+              <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="confirmDealType" label="纭绫诲瀷">
+                <j-dict-select-tag type='radio' v-model='model.confirmDealType' dictCode='approved_rejected'
+                                   placeholder="璇烽�夋嫨澶勭悊绫诲瀷" :disabled="disableSubmit || leaderConfirmDisable"/>
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="12">
+              <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="confirmComment" label="纭鎰忚">
+                <a-textarea placeholder="璇疯緭鍏ユ剰瑙�" v-model="model.confirmComment"
+                            :disabled="disableSubmit || leaderConfirmDisable"/>
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+        </div>
+        <div v-if="leaderConfirmDisable">
+          <a-divider orientation="center" style="font-size: large;font-style: italic;color: #66aeed;"> 棰嗗纭淇℃伅
+          </a-divider>
+          <a-row :gutter="24">
+            <a-col :span="24">
+              <a-form-model-item :labelCol="labelColLong" :wrapperCol="wrapperColLong" prop="leaderConfirmComment"
+                                 label="棰嗗鎰忚">
+                <a-textarea placeholder="璇疯緭鍏ユ剰瑙�" v-model="model.leaderConfirmComment"
+                            :disabled="disableSubmit || completionDisable"/>
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+        </div>
+      </a-form-model>
+    </a-spin>
+  </j-modal>
+</template>
+
+<script>
+  import { downFile, getAction, httpAction } from '@/api/manage'
+  import { JVxeTableModelMixin } from '@/mixins/JVxeTableModelMixin.js'
+  import { JVXETypes } from '@comp/jeecg/JVxeTable'
+  import MaintenanceEquipmentSelect from '@views/eam/equipment/modules/MaintenanceEquipmentSelect'
+
+  export default {
+    name: 'ThirdMaintenanceApprovalModal',
+    mixins: [JVxeTableModelMixin],
+    components: {
+      MaintenanceEquipmentSelect
+    },
+    props: {
+      selectShenpiData: {
+        type: Object
+      }
+    },
+    data() {
+      return {
+        title: '鎿嶄綔',
+        visible: false,
+        //鐘舵�佹帶鍒�
+        //淇濆吇涓� 涓嶅彲缂栬緫
+        // confirmDisable: false,
+        // initialAcceptanceDisable: false,
+        // finalAcceptanceDisable: false,
+        editable: false,
+        model: {},
+        maintenanceCategory: 'SECOND_MAINTENANCE',
+        maintenanceOperatorOptions: [],
+        labelCol: {
+          xs: { span: 24 },
+          sm: { span: 6 }
+        },
+        wrapperCol: {
+          xs: { span: 24 },
+          sm: { span: 16 }
+        },
+        labelColLong: {
+          xs: { span: 24 },
+          sm: { span: 2 }
+        },
+        wrapperColLong: {
+          xs: { span: 24 },
+          sm: { span: 21 }
+        },
+        confirmLoading: false,
+        spinning: false,
+        imageSrc: null,
+        activeTabKey: '1',
+        validatorRules: {
+          confirmDealType: [
+            { required: true, message: '璇烽�夋嫨閫氳繃鎴栭┏鍥�!' }
+          ],
+          confirmComment: [
+            { required: true, message: '璇疯緭鍏ョ‘璁ゆ剰瑙�!' }
+          ],
+          leaderConfirmComment: [
+            { required: true, message: '璇疯緭鍏ュ垵楠屾敹鎰忚!' }
+          ],
+        },
+        url: {
+          queryById: '/eam/thirdMaintenanceOrder/queryById',
+          detail: '/eam/thirdMaintenanceOrderDetail/queryList',
+          approval: '/eam/thirdMaintenanceOrder/approval',
+          userSelect: '/eam/user_select/list',
+          queryHisTaskList: '/assign/flow/queryHisTaskList',
+          diagramView: '/assign/flow/diagramView'
+        },
+        disableSubmit: false,
+        taskData: [],
+        isDisplayBmp: false,
+        showBmpButtonLoading: false,
+        selectedRowKeys: [],
+        detail: {
+          loading: false,
+          dataSource: [],
+          columns: [
+            {
+              title: 'ID',
+              key: 'id',
+              type: JVXETypes.hidden
+            },
+            {
+              title: 'orderId',
+              key: 'orderId',
+              type: JVXETypes.hidden
+            },
+            {
+              title: '搴忓彿',
+              key: 'itemCode',
+              type: JVXETypes.normal,
+              width: '5%',
+              align: 'center'
+            },
+            {
+              title: '淇濆吇椤�',
+              key: 'itemName',
+              type: JVXETypes.normal,
+              width: '10%',
+              align: 'center'
+            },
+            {
+              title: '瀛愪繚鍏婚」',
+              key: 'subItemName',
+              type: JVXETypes.normal,
+              width: '10%',
+              align: 'center'
+            },
+            {
+              title: '淇濆吇瑕佹眰',
+              key: 'itemDemand',
+              type: JVXETypes.normal,
+              width: '20%',
+              align: 'center'
+            },
+            {
+              title: '淇濆吇缁撴灉',
+              key: 'maintenanceResult',
+              type: JVXETypes.slot,
+              width: '10%',
+              align: 'center',
+              slotName: 'maintenanceResult',
+              validateRules: [
+                { required: true, message: '淇濆吇缁撴灉涓嶈兘涓虹┖锛�' }
+              ]
+            },
+            {
+              title: '寮傚父鎻忚堪',
+              key: 'exceptionDescription',
+              type: JVXETypes.slot,
+              width: '20%',
+              align: 'center',
+              slotName: 'exceptionDescription',
+              validateRules: [
+                { handler: this.customValidator }
+              ]
+            },
+            {
+              title: '鏄惁鎶ヤ慨',
+              key: 'reportFlag',
+              type: JVXETypes.slot,
+              width: '10%',
+              align: 'center',
+              slotName: 'reportFlag',
+              validateRules: [
+                { handler: this.customValidator }
+              ]
+            }
+          ],
+          toolbarConfig: {
+            // prefix 鍓嶇紑锛泂uffix 鍚庣紑
+            slot: ['prefix', 'suffix'],
+            // add 鏂板鎸夐挳锛況emove 鍒犻櫎鎸夐挳锛沜learSelection 娓呯┖閫夋嫨鎸夐挳
+            btn: ['clearSelection']
+          }
+        }
+      }
+    },
+    created() {
+    },
+    computed: {
+      confirmDisable: function() {
+        return ['WAIT_CONFIRM', 'WAIT_LEADER_CONFIRM', 'COMPLETE'].includes(this.model.maintenanceStatus)
+      },
+      leaderConfirmDisable: function() {
+        return ['WAIT_LEADER_CONFIRM', 'COMPLETE'].includes(this.model.maintenanceStatus)
+      },
+      completionDisable: function() {
+        return ['COMPLETE', 'ABOLISH'].includes(this.model.maintenanceStatus)
+      }
+    },
+    methods: {
+      async handleDetail(item) {
+        this.initParams()
+        this.model = {}
+        if (item.procInstId) {
+          const { processDefinitionId, processInstanceId, processDefinitionKey, procInstId } = item
+
+          let taskDataList = await getAction(this.url.queryHisTaskList, { procInstId })
+          this.taskData = [...taskDataList.result]
+
+          downFile(this.url.diagramView, {
+            processDefinitionId,
+            processInstanceId,
+            TaskDefinitionKey: processDefinitionKey
+          }, 'get')
+            .then((res => {
+              const urlObject = window.URL.createObjectURL(new Blob([res]))
+              this.imageSrc = urlObject
+            }))
+            .catch(err => {
+              this.$notification.error({
+                message: '娑堟伅',
+                description: res.message
+              })
+            })
+        }
+        let res = await getAction(this.url.queryById, { id: item.dataId })
+        this.model = Object.assign({}, res.result)
+        if (this.model.imageFiles) {
+          let obj = JSON.parse(this.model.imageFiles)
+          this.model.imageFilesResult = [...obj]
+        }
+        this.model.dataId = item.dataId
+        this.model.taskId = item.id
+        this.model.userId = item.assignee
+        this.model.instanceId = item.procInstId
+        this.model.values = item.variables
+        await this.loadDetail(item.dataId)
+      },
+
+      recordDetail(record) {
+        console.log('record', record)
+        this.initParams()
+        this.model = Object.assign({}, record)
+        if (this.model.imageFiles) {
+          let obj = JSON.parse(this.model.imageFiles)
+          this.model.imageFilesResult = [...obj]
+        }
+        this.loadDetail(record.id)
+      },
+
+      initParams() {
+        this.detail.dataSource = []
+        this.visible = true
+        this.activeTabKey = '1'
+        this.spinning = true
+      },
+
+      async handleOk() {
+        const that = this
+        let errMap = await that.$refs.editableDetailTable.validateTable()
+        if (errMap) {
+          this.$message.warning('鏁版嵁鏍¢獙澶辫触锛�')
+          return
+        }
+        // 瑙﹀彂琛ㄥ崟楠岃瘉
+        this.$refs.form.validate(valid => {
+          if (valid) {
+            that.confirmLoading = that.spinning = true
+            let tableData = that.$refs.editableDetailTable.getTableData()
+            that.model.tableDetailList = [...tableData]
+            let httpurl = this.url.approval
+            let method = 'put'
+
+            httpAction(httpurl, this.model, method).then((res) => {
+              if (res.success) {
+                that.$message.success(res.message)
+                that.$emit('searchReset')
+                that.close()
+              } else {
+                that.$message.warning(res.message)
+              }
+            }).finally(() => {
+              that.confirmLoading = that.spinning = false
+            })
+          } else {
+            return false
+          }
+        })
+      },
+
+      autocompleteForm(selectObj) {
+        this.$set(this.model, 'standardName', selectObj.standardName)
+        this.$set(this.model, 'maintenancePeriod', selectObj.maintenancePeriod)
+        this.$set(this.model, 'standardId', selectObj.id)
+        this.$set(this.model, 'equipmentId', selectObj.equipmentId)
+        // console.log('model', this.model)
+        if (!this.model.id) {
+          this.loadStandardDetail(selectObj.id)
+        }
+        this.loadMaintenanceOperatorList(this.model.equipmentId)
+      },
+
+      //鏍囧噯閫夋嫨鍙樺寲
+      loadDetail(orderId) {
+        if (orderId) {
+          getAction(this.url.detail, { orderId: orderId })
+            .then(res => {
+              if (res.success) {
+                this.detail.dataSource = [...res.result]
+              }
+            })
+            .finally(() => {
+              this.spinning = false
+            })
+        }
+      },
+
+      loadMaintenanceOperatorList(equipmentId) {
+        this.maintenanceOperatorOptions = []
+        let params = { positionCode: 'PCR0001' }
+        if (equipmentId) {
+          params.equipmentId = equipmentId
+        }
+        getAction(this.url.userSelect, params).then(res => {
+          if (res.success) {
+            this.maintenanceOperatorOptions = res.result.map(item => ({
+              key: item.id,
+              value: item.username,
+              text: item.realname
+            }))
+          }
+        })
+      },
+
+      handleInspectionResultSelectChange(value, record) {
+        if (record.exceptionDescription) delete record.exceptionDescription
+        if (record.reportFlag) delete record.reportFlag
+      },
+
+      // 鎵归噺閫夋嫨鎵�鏈夌偣妫�缁撴灉
+      handleSelectAllInspectionResult() {
+        this.selectedRowKeys.forEach(key => {
+          const dataItem = this.detail.dataSource.find(item => item.id === key)
+          if (dataItem && dataItem.maintenanceResult !== '1') {
+            console.log('dataItem', dataItem)
+            delete dataItem.exceptionDescription
+            delete dataItem.reportFlag
+            dataItem.maintenanceResult = '1'
+          }
+        })
+        this.$refs.editableDetailTable.clearCheckboxRow()
+        this.selectedRowKeys = []
+      },
+
+      /**
+       * 琛ㄦ牸澶氶�夋鍙戠敓鏀瑰彉鏃惰Е鍙�
+       * @param {selectedRowIds} 琛ㄦ牸涓凡閫夋嫨鐨処D鍒楄〃
+       */
+      handleTableSelectRowChange({ selectedRowIds }) {
+        this.selectedRowKeys = selectedRowIds
+      },
+
+      customValidator({ cellValue, row }, callback) {
+        if (row.maintenanceResult === '2') {
+          if (!cellValue) {
+            callback(false, '${title}涓嶈兘涓虹┖锛�') // false = 鏈�氳繃锛屽彲浠ヨ窡鑷畾涔夋彁绀�
+          } else {
+            callback(true) // true = 閫氳繃楠岃瘉
+          }
+        } else {
+          callback(true)
+        }
+      },
+
+      handleCancel() {
+        this.close()
+      },
+
+      close() {
+        this.$emit('close')
+        this.visible = false
+        this.$refs.form.clearValidate()
+      }
+    }
+  }
+</script>
+
+<style lang="less" scoped>
+
+</style>
\ No newline at end of file

--
Gitblit v1.9.3