Procházet zdrojové kódy

前台约检批量上报

xy před 6 dny
rodič
revize
ed02e0dcc1

+ 4 - 0
yudao-ui-admin-vue3/src/api/pressure2/equipboilerscheduling/index.ts

@@ -177,4 +177,8 @@ export const EquipBoilerSchedulingApi = {
     return request.put({ url: '/pressure2/equip-boiler/batch-update-district', data })
   },
 
+  // 前台约检,设备批量上报
+  batchEquipmentReport: async (data: any) => {
+    return request.post({ url: '/pressure2/equip-boiler-scheduling/refuseItem', data })
+  },
 }

+ 5 - 0
yudao-ui-admin-vue3/src/api/pressure2/pipescheduling/index.ts

@@ -208,4 +208,9 @@ export const EquipPipeSchedulingApi = {
   copyEquipPipeScheduling: async (data: any) => {
     return request.post({ url: `/pressure2/equip-pipe-scheduling/copy`, data })
   },
+
+  // 前台约检,设备批量上报
+  batchEquipmentReport: async (data: any) => {
+    return request.post({ url: '/pressure2/equip-pipe-scheduling/refuseItem', data })
+  },
 }

+ 156 - 0
yudao-ui-admin-vue3/src/views/pressure2/planNew/boilerDetail.vue

@@ -194,6 +194,9 @@
         <el-button type="primary" @click="handleBatchEditLocationFn" :disabled="selectedRows.length === 0">
           <Icon icon="ep:edit" class="mr-5px" /> 批量修改地址
         </el-button>
+        <el-button type="primary" @click="handleBatchEquipmentReport" :disabled="selectedRows.length === 0">
+          设备上报
+        </el-button>
         <el-button type="primary" @click="() => handleToRoute('AcceptOrder1')">约检单</el-button>
         <el-button type="primary" @click="() => handleToRoute('TaskOrder')">任务单</el-button>
       </el-row>
@@ -206,6 +209,7 @@
         ref="tableRef"
         @row-click="handleRowClick"
         :row-class-name="getRowClassName"
+        :cell-class-name="handleCellClassName"
       >
         <el-table-column type="selection" width="40" fixed="left" />
         <el-table-column
@@ -452,6 +456,60 @@
     </template>
   </Dialog>
 
+  <!-- 设备上报弹窗 -->
+  <Dialog
+    v-model="batchEquipmentReportDialogVisible"
+    title="设备上报"
+    width="500px"
+    draggable
+    :close-on-click-modal="false"
+    append-to-body
+    @close="handleBatchEquipmentReportCancel"
+  >
+    <el-form ref="batchEquipmentReportFormRef" :model="batchEquipmentReportFormData" label-width="100px">
+      <el-form-item label="上报类型" prop="type" :rules="[{ required: true, message: '请选择上报类型', trigger: 'change' }]">
+        <el-radio-group v-model="batchEquipmentReportFormData.type">
+          <el-radio v-for="(label, key) in PressureBoilerCheckTypeMap" :key="key" :label="Number(key)" :value="Number(key)">
+            {{ label }}
+          </el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="上报原因" prop="reasonDict" :rules="[{ required: true, message: '请选择上报原因', trigger: 'change' }]">
+        <el-select
+          v-model="batchEquipmentReportFormData.reasonDict"
+          placeholder="请选择上报原因"
+          @change="() => { batchEquipmentReportFormData.reason = '' }"
+        >
+          <el-option
+            v-for="dict in getStrDictOptions('refuseInspectedCategory')"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item
+        v-if="batchEquipmentReportFormData.reasonDict == '5'"
+        label="其他"
+        prop="reason"
+        :rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
+      >
+        <el-input
+          v-model="batchEquipmentReportFormData.reason"
+          placeholder="请输入其他原因"
+          maxlength="150"
+          show-word-limit
+          :autosize="{ minRows: 5, maxRows: 20 }"
+          type="textarea"
+        />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="handleBatchEquipmentReportCancel">取消</el-button>
+      <el-button type="primary" @click="handleSubmitBatchEquipmentReport">确定</el-button>
+    </template>
+  </Dialog>
+
   <unitContainerForm ref="unitContainerFormRef" />
 </template>
 
@@ -464,6 +522,7 @@ import {
   PlanNewPageVO,
   PlanSchedulingEquipVO
 } from '@/api/pressure/planScheduling'
+import { PressureBoilerCheckTypeMap } from '@/utils/constants'
 import AreaSelect from '../../system/equipcontainer/components/AreaSelect.vue'
 import StreetSelect from '../../system/equipcontainer/components/StreetSelect.vue'
 import DeptSelect from './components/DeptSelect.vue'
@@ -477,6 +536,7 @@ import { isEmpty } from '@/utils/is'
 import { useRouter } from 'vue-router'
 import { usePlanNewStore } from '@/store/modules/planNew'
 import { ArrowDown, ArrowUp } from '@element-plus/icons-vue'
+import { FormInstance, ElMessageBox } from 'element-plus'
 import {
   EquipBoilerSchedulingApi,
   EquipBoilerSchedulingEquipVO,
@@ -672,6 +732,11 @@ const handleSelectionChange = (selection: EquipBoilerSchedulingEquipVO[]) => {
 type scheduleType = 'in' | 'out' | 'pressure' | 'all' |''
 /** 处理单条记录排期 */
 const handleSingleSchedule = (row: EquipBoilerSchedulingEquipVO, type: scheduleType) => {
+  // 已上报设备不允许约检
+  if (row.refuseReasonDict) {
+    message.warning(`设备${row.equipCode}正在上报市局审核状态,不支持约检`)
+    return
+  }
   // 处理已经有排期
   if (type === 'in' && row.planInCheckDate){
     return
@@ -690,6 +755,11 @@ const handleSingleSchedule = (row: EquipBoilerSchedulingEquipVO, type: scheduleT
   scheduleEquipDialogRef.value?.open(type)
 }
 const handleSchedule = (row: EquipBoilerSchedulingVO,type?) => {
+  // 已上报设备不允许约检
+  if ((row as any).refuseReasonDict) {
+    message.warning(`设备${(row as any).equipCode}正在上报市局审核状态,不支持约检`)
+    return
+  }
   selectedRows.value.forEach(item => {
     tableRef.value?.toggleRowSelection(item,false)
   })
@@ -720,6 +790,12 @@ const handleBatchSchedule = (type: scheduleType) => {
     message.warning('请至少选择一条记录')
     return
   }
+  // 已上报设备不允许约检
+  const refusedList = selectedRows.value.filter((row: any) => row.refuseReasonDict)
+  if (refusedList.length > 0) {
+    message.warning(`设备${refusedList.map((item: any) => item.equipCode).join('、')}正在上报市局审核状态,不支持约检`)
+    return
+  }
   selectedInRows.value = []
   selectedOutRows.value = []
   selectedPreRows.value = []
@@ -898,6 +974,17 @@ const getRowClassName = ({ row, rowIndex }) => {
   return isSelected ? 'selected-row' : ''
 }
 
+/** 单元格着色:上报后对应日期列变红 */
+const handleCellClassName = ({ row, column }: { row: any; column: any }) => {
+  if (row.refuseReasonDict || row.refuseReason) {
+    const refuseCols = ['nextInCheckDate', 'nextOutCheckDate', 'nextPressureCheckDate']
+    if (refuseCols.includes(column.property)) {
+      return 'cell-bg-color-red'
+    }
+  }
+  return ''
+}
+
 // 监听日期类型变化
 watch(datePickerType, (newVal) => {
   // 清空日期相关字段
@@ -933,6 +1020,71 @@ const handleUnitCodeFn = (id) => {
   }
   unitContainerFormRef.value?.open(id)
 }
+
+// 批量上报设备
+const batchEquipmentReportDialogVisible = ref(false)
+const batchEquipmentReportFormRef = ref<FormInstance>()
+const batchEquipmentReportFormData = ref({
+  type: undefined as number | undefined,
+  reasonDict: '',
+  reason: ''
+})
+
+const handleBatchEquipmentReport = () => {
+  if (selectedRows.value.length === 0) {
+    message.warning('请选择需要进行上报的设备!')
+    return
+  }
+  batchEquipmentReportFormData.value = { type: undefined, reasonDict: '', reason: '' }
+  batchEquipmentReportDialogVisible.value = true
+}
+
+const handleBatchEquipmentReportCancel = () => {
+  batchEquipmentReportDialogVisible.value = false
+}
+
+const handleSubmitBatchEquipmentReport = async () => {
+  try {
+    await batchEquipmentReportFormRef.value?.validate()
+  } catch {
+    return
+  }
+
+  const params = {
+    equipIds: selectedRows.value.map((item: any) => item.id),
+    checkType: batchEquipmentReportFormData.value.type,
+    reasonDict: batchEquipmentReportFormData.value.reasonDict,
+    reason: batchEquipmentReportFormData.value.reason,
+  }
+
+  EquipBoilerSchedulingApi.batchEquipmentReport(params).then((res: any) => {
+    if (Array.isArray(res) && res.length > 0) {
+      const successList = res.filter((item: any) => item.success)
+      const failList = res.filter((item: any) => !item.success)
+      const successNum = successList.length
+      const failNum = failList.length
+
+      let messageHtml = ''
+      if (successNum > 0) {
+        const successMsg = successList.map((item: any) => `<div style="margin-left: 24px;">设备代码「${item.equipCode}」${item.message || '上报成功'}</div>`).join('')
+        messageHtml += `<div style="margin-bottom: 12px;"><span style="color: #67c23a;">✓</span> <span style="color: #67c23a; font-weight: bold;">${successNum}台设备上报成功:</span>${successMsg}</div>`
+      }
+      if (failNum > 0) {
+        const failMsg = failList.map((item: any) => `<div style="margin-left: 24px;">设备代码「${item.equipCode}」${item.message || '上报失败'}</div>`).join('')
+        messageHtml += `<div><span style="color: #f56c6c;">✗</span> <span style="color: #f56c6c; font-weight: bold;">${failNum}台设备上报失败:</span>${failMsg}</div>`
+      }
+
+      ElMessageBox.alert(messageHtml, '设备上报结果', {
+        dangerouslyUseHTMLString: true,
+        confirmButtonText: '确定',
+        callback: () => {
+          batchEquipmentReportDialogVisible.value = false
+          handleQuery()
+        }
+      })
+    }
+  })
+}
 </script>
 
 <style lang="scss" scoped>
@@ -967,4 +1119,8 @@ const handleUnitCodeFn = (id) => {
 :deep(.selected-row){
   background-color: #ecf5ff !important;
 }
+:deep(.cell-bg-color-red) {
+  background-color: #f56c6ccc !important;
+  color: #000000;
+}
 </style>

+ 165 - 12
yudao-ui-admin-vue3/src/views/pressure2/planNew/pipeDetail.vue

@@ -242,6 +242,9 @@
         <el-button type="primary" @click="handleBatchEditLocationFn" :disabled="selectedRows.length === 0">
           <Icon icon="ep:edit" class="mr-5px" /> 批量修改地址
         </el-button>
+        <el-button type="primary" @click="handleBatchEquipmentReport" :disabled="selectedDetailRows.length === 0">
+          设备上报
+        </el-button>
         <el-button type="primary" @click="() => handleToRoute('AcceptOrder1')">约检单</el-button>
         <el-button type="primary" @click="() => handleToRoute('TaskOrder')">任务单</el-button>
       </el-row>
@@ -254,6 +257,7 @@
         @sort-change="handleSortChange"
         :row-key="(row) => row.id"
         :row-class-name="getMainRowClassName"
+        :cell-class-name="handleMainCellClassName"
         @row-click="handleMainRowClick"
         @expand-change="handleExpandChange"
         :expand-row-keys="expandRowKeys"
@@ -269,6 +273,7 @@
                 :ref="(el) => setDetailTableRef(el, props.row.id)"
                 @selection-change="(selection) => handleDetailSelectionChange(selection, props.row)"
                 :row-class-name="getRowClassName"
+                :cell-class-name="handleCellClassName"
                 class="inner-table"
                 @row-click="handleRowClick"
               >
@@ -522,6 +527,60 @@
     </template>
   </Dialog>
 
+  <!-- 设备上报弹窗 -->
+  <Dialog
+    v-model="batchEquipmentReportDialogVisible"
+    title="设备上报"
+    width="500px"
+    draggable
+    :close-on-click-modal="false"
+    append-to-body
+    @close="handleBatchEquipmentReportCancel"
+  >
+    <el-form ref="batchEquipmentReportFormRef" :model="batchEquipmentReportFormData" label-width="100px">
+      <el-form-item label="上报类型" prop="type" :rules="[{ required: true, message: '请选择上报类型', trigger: 'change' }]">
+        <el-radio-group v-model="batchEquipmentReportFormData.type">
+          <el-radio v-for="(label, key) in PressurePipeCheckTypeMap" :key="key" :label="Number(key)" :value="Number(key)">
+            {{ label }}
+          </el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="上报原因" prop="reasonDict" :rules="[{ required: true, message: '请选择上报原因', trigger: 'change' }]">
+        <el-select
+          v-model="batchEquipmentReportFormData.reasonDict"
+          placeholder="请选择上报原因"
+          @change="() => { batchEquipmentReportFormData.reason = '' }"
+        >
+          <el-option
+            v-for="dict in getStrDictOptions('refuseInspectedCategory')"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item
+        v-if="batchEquipmentReportFormData.reasonDict == '5'"
+        label="其他"
+        prop="reason"
+        :rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
+      >
+        <el-input
+          v-model="batchEquipmentReportFormData.reason"
+          placeholder="请输入其他原因"
+          maxlength="150"
+          show-word-limit
+          :autosize="{ minRows: 5, maxRows: 20 }"
+          type="textarea"
+        />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="handleBatchEquipmentReportCancel">取消</el-button>
+      <el-button type="primary" @click="handleSubmitBatchEquipmentReport">确定</el-button>
+    </template>
+  </Dialog>
+
   <unitContainerForm ref="unitContainerFormRef" />
 </template>
 
@@ -541,6 +600,8 @@ import {isEmpty} from '@/utils/is'
 import {useRouter} from 'vue-router'
 import {usePlanNewStore} from '@/store/modules/planNew'
 import {ArrowDown, ArrowUp} from '@element-plus/icons-vue'
+import { FormInstance, ElMessageBox } from 'element-plus'
+import { PressurePipeCheckTypeMap } from '@/utils/constants'
 import {EquipBoilerSchedulingEquipVO} from "@/api/pressure2/equipboilerscheduling";
 import {
   PipeEquipmentApi,
@@ -659,6 +720,17 @@ const getMainRowClassName = ({row}) => {
   )
   return isSelected ? 'selected-row' : ''
 }
+
+/** 父工程单元格着色:按检验类型分别给下次定检/下次年检列着色 */
+const handleMainCellClassName = ({ row, column }: { row: any; column: any }) => {
+  if (row.allLegalRefused && column.property === 'nextLegalCheckDate') {
+    return 'cell-bg-color-red'
+  }
+  if (row.allYearRefused && column.property === 'nextYearCheckDate') {
+    return 'cell-bg-color-red'
+  }
+  return ''
+}
 const getRowClassName = ({row}) => {
   // 找到当前行所在的分组,从 Map 中获取对应的表格实例
   const tableRef = getDetailTableRef(row.equipPipeId)
@@ -671,6 +743,17 @@ const getRowClassName = ({row}) => {
 
   return ''
 }
+
+/** 单元格着色:管道上报后按校验类型分别给对应日期列着色(支持同时变色) */
+const handleCellClassName = ({ row, column }: { row: any; column: any }) => {
+  if (row.legalRefuseReasonDict && column.property === 'nextLegalCheckDate') {
+    return 'cell-bg-color-red'
+  }
+  if (row.yearRefuseReasonDict && column.property === 'nextYearCheckDate') {
+    return 'cell-bg-color-red'
+  }
+  return ''
+}
 /** 处理行点击勾选 */
 const handleMainRowClick = (row) => {
   mainTableRef.value?.toggleRowSelection(row)
@@ -964,11 +1047,12 @@ const handleBatchSchedule = () => {
   selectedRows.value.forEach(item => {
     if (!ids.includes(item.id)) {
       item.pipes.forEach(pipe => {
-        if (!pipe.hasLegalScheduling && pipe.planLegalCheckDate == null) {
+        // 已上报定期检验的管道不加入定期约检列表
+        if (!pipe.hasLegalScheduling && pipe.planLegalCheckDate == null && !pipe.legalRefuseReasonDict) {
           selectedLegalList.value.push(pipe)
         }
-
-        if (!pipe.hasYearScheduling && pipe.planYearCheckDate == null) {
+        // 已上报年度检查的管道不加入年度约检列表
+        if (!pipe.hasYearScheduling && pipe.planYearCheckDate == null && !pipe.yearRefuseReasonDict) {
           selectedYearList.value.push(pipe)
         }
       })
@@ -976,12 +1060,12 @@ const handleBatchSchedule = () => {
     }
   })
   selectedDetailRows.value.forEach(item => {
-
-    if (!item.hasLegalScheduling && item.planLegalCheckDate == null){
+    // 已上报定期检验的管道不加入定期约检列表
+    if (!item.hasLegalScheduling && item.planLegalCheckDate == null && !item.legalRefuseReasonDict){
       selectedLegalList.value.push(item)
     }
-
-    if (!item.hasYearScheduling  && item.planYearCheckDate == null){
+    // 已上报年度检查的管道不加入年度约检列表
+    if (!item.hasYearScheduling  && item.planYearCheckDate == null && !item.yearRefuseReasonDict){
       selectedYearList.value.push(item)
     }
 
@@ -1001,24 +1085,24 @@ const handleSchedule = async (row: any,checkType?: string) => {
   selectedYearList.value = []
   row.pipes.forEach(item => {
     if (selectedDetailRows.value.includes(item)) {
-      if (!item.hasLegalScheduling && item.planLegalCheckDate == null) {
+      if (!item.hasLegalScheduling && item.planLegalCheckDate == null && !item.legalRefuseReasonDict) {
         selectedLegalList.value.push(item)
       }
 
-      if (!item.hasYearScheduling && item.planYearCheckDate == null) {
+      if (!item.hasYearScheduling && item.planYearCheckDate == null && !item.yearRefuseReasonDict) {
         selectedYearList.value.push(item)
       }
     }
   })
   if (selectedLegalList.value.length == 0 && selectedYearList.value.length == 0) {
-    // 默认带出全部
+    // 默认带出全部(同样过滤已上报的)
     row.pipes.forEach(item => {
 
-      if (!item.hasLegalScheduling && item.planLegalCheckDate == null) {
+      if (!item.hasLegalScheduling && item.planLegalCheckDate == null && !item.legalRefuseReasonDict) {
         selectedLegalList.value.push(item)
       }
 
-      if (!item.hasYearScheduling && item.planYearCheckDate == null) {
+      if (!item.hasYearScheduling && item.planYearCheckDate == null && !item.yearRefuseReasonDict) {
         selectedYearList.value.push(item)
       }
 
@@ -1243,6 +1327,71 @@ const handleUnitCodeFn = (id) => {
   }
   unitContainerFormRef.value?.open(id)
 }
+
+// 批量上报设备
+const batchEquipmentReportDialogVisible = ref(false)
+const batchEquipmentReportFormRef = ref<FormInstance>()
+const batchEquipmentReportFormData = ref({
+  type: undefined as number | undefined,
+  reasonDict: '',
+  reason: ''
+})
+
+const handleBatchEquipmentReport = () => {
+  if (selectedDetailRows.value.length === 0) {
+    message.warning('请选择需要进行上报的管道设备!')
+    return
+  }
+  batchEquipmentReportFormData.value = { type: undefined, reasonDict: '', reason: '' }
+  batchEquipmentReportDialogVisible.value = true
+}
+
+const handleBatchEquipmentReportCancel = () => {
+  batchEquipmentReportDialogVisible.value = false
+}
+
+const handleSubmitBatchEquipmentReport = async () => {
+  try {
+    await batchEquipmentReportFormRef.value?.validate()
+  } catch {
+    return
+  }
+
+  const params = {
+    equipDetailIds: selectedDetailRows.value.map((item: any) => item.id),
+    checkType: batchEquipmentReportFormData.value.type,
+    reasonDict: batchEquipmentReportFormData.value.reasonDict,
+    reason: batchEquipmentReportFormData.value.reason,
+  }
+
+  EquipPipeSchedulingApi.batchEquipmentReport(params).then((res: any) => {
+    if (Array.isArray(res) && res.length > 0) {
+      const successList = res.filter((item: any) => item.success)
+      const failList = res.filter((item: any) => !item.success)
+      const successNum = successList.length
+      const failNum = failList.length
+
+      let messageHtml = ''
+      if (successNum > 0) {
+        const successMsg = successList.map((item: any) => `<div style="margin-left: 24px;">管道代码「${item.pipeRegCode}」${item.message || '上报成功'}</div>`).join('')
+        messageHtml += `<div style="margin-bottom: 12px;"><span style="color: #67c23a;">✓</span> <span style="color: #67c23a; font-weight: bold;">${successNum}台设备上报成功:</span>${successMsg}</div>`
+      }
+      if (failNum > 0) {
+        const failMsg = failList.map((item: any) => `<div style="margin-left: 24px;">管道代码「${item.pipeRegCode}」${item.message || '上报失败'}</div>`).join('')
+        messageHtml += `<div><span style="color: #f56c6c;">✗</span> <span style="color: #f56c6c; font-weight: bold;">${failNum}台设备上报失败:</span>${failMsg}</div>`
+      }
+
+      ElMessageBox.alert(messageHtml, '设备上报结果', {
+        dangerouslyUseHTMLString: true,
+        confirmButtonText: '确定',
+        callback: () => {
+          batchEquipmentReportDialogVisible.value = false
+          handleQuery()
+        }
+      })
+    }
+  })
+}
 </script>
 
 <style lang="scss" scoped>
@@ -1301,4 +1450,8 @@ const handleUnitCodeFn = (id) => {
     text-decoration: underline;
   }
 }
+:deep(.cell-bg-color-red) {
+  background-color: #f56c6ccc !important;
+  color: #000000;
+}
 </style>