|
|
@@ -10,27 +10,27 @@
|
|
|
<el-option label="管道" value="pipe" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<!-- 使用单位 -->
|
|
|
<el-form-item label="使用单位">
|
|
|
<el-input v-model="searchFormDataTable.unitName" placeholder="请输入使用单位" clearable />
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<!-- 设备代码/工程号 -->
|
|
|
<el-form-item :label="selectedEquipMainType === 'boiler' ? '设备注册代码' : '工程号'">
|
|
|
<el-input v-model="searchFormDataTable.equipCode" placeholder="请输入" clearable />
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<!-- 区域 -->
|
|
|
<el-form-item label="区域">
|
|
|
<AreaSelect v-model="searchFormDataTable.equipDistrict" />
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<!-- 联系电话 -->
|
|
|
<el-form-item label="联系电话">
|
|
|
<el-input v-model="searchFormDataTable.contactPhone" placeholder="请输入联系电话" clearable />
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<!-- 操作按钮 -->
|
|
|
<el-form-item>
|
|
|
<el-button type="primary" @click="getListPageFn">
|
|
|
@@ -44,7 +44,7 @@
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<!-- 工具栏区域 -->
|
|
|
<div class="toolbar">
|
|
|
<div class="toolbar-left">
|
|
|
@@ -68,13 +68,22 @@
|
|
|
</el-radio-group>
|
|
|
</div>
|
|
|
<div class="toolbar-right">
|
|
|
+ <el-button type="primary" :disabled="!canBatchAppointment()" @click="handleBatchAppointment">
|
|
|
+ 批量约检
|
|
|
+ </el-button>
|
|
|
+ <el-button type="primary" :disabled="selectedRows.length === 0" @click="handleBatchEditContact">
|
|
|
+ 修改约检联系人
|
|
|
+ </el-button>
|
|
|
+ <el-button type="primary" :disabled="selectedRows.length === 0" @click="handleBatchRemark">
|
|
|
+ 批量添加备注
|
|
|
+ </el-button>
|
|
|
<el-button type="primary" @click="handleExportFn">
|
|
|
<el-icon><Download /></el-icon>
|
|
|
导出Excel
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<!-- 设备类型筛选区域 -->
|
|
|
<div class="equip-type-filter" v-if="selectedEquipMainType">
|
|
|
<span class="label-text">{{ selectedEquipMainType === 'boiler' ? '锅炉归类' : '管道类别' }}:</span>
|
|
|
@@ -88,7 +97,7 @@
|
|
|
</el-checkbox>
|
|
|
</el-checkbox-group>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<!-- 表格区域 -->
|
|
|
<div class="table-container">
|
|
|
<el-table
|
|
|
@@ -100,17 +109,20 @@
|
|
|
@selection-change="handleSelectionChange"
|
|
|
>
|
|
|
<el-table-column type="selection" width="55" />
|
|
|
- <el-table-column label="操作" width="80" fixed="left">
|
|
|
+ <el-table-column label="操作" width="120" fixed="left">
|
|
|
<template #default="scope">
|
|
|
- <el-button type="primary" link @click="handleAppointment(scope.row)">
|
|
|
+ <el-button v-if="canAppointment(scope.row)" type="primary" link @click="handleAppointment(scope.row)">
|
|
|
约检
|
|
|
</el-button>
|
|
|
+ <el-button type="primary" link @click="openRemarkDialog(scope.row)">
|
|
|
+ 备注
|
|
|
+ </el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
-
|
|
|
+
|
|
|
<!-- 使用单位 -->
|
|
|
<el-table-column label="使用单位" prop="unitName" min-width="150" show-overflow-tooltip />
|
|
|
-
|
|
|
+
|
|
|
<!-- 锅炉/管道特有列 -->
|
|
|
<template v-if="selectedEquipMainType === 'boiler'">
|
|
|
<el-table-column label="设备注册代码" prop="equipCode" min-width="180" show-overflow-tooltip>
|
|
|
@@ -124,14 +136,14 @@
|
|
|
<el-table-column label="设备分类" prop="equipTypeName" min-width="120" show-overflow-tooltip />
|
|
|
<el-table-column label="设备名称" prop="equipName" min-width="150" show-overflow-tooltip />
|
|
|
</template>
|
|
|
-
|
|
|
+
|
|
|
<template v-if="selectedEquipMainType === 'pipe'">
|
|
|
<el-table-column label="工程号" prop="projectNo" min-width="150" show-overflow-tooltip />
|
|
|
<el-table-column label="使用证编号" prop="useRegisterNo" min-width="150" show-overflow-tooltip />
|
|
|
<el-table-column label="设备分类" prop="equipTypeName" min-width="120" show-overflow-tooltip />
|
|
|
<el-table-column label="工程名称" prop="projectName" min-width="180" show-overflow-tooltip />
|
|
|
</template>
|
|
|
-
|
|
|
+
|
|
|
<!-- 通用列 -->
|
|
|
<el-table-column label="区域" min-width="100" show-overflow-tooltip>
|
|
|
<template #default="scope">
|
|
|
@@ -146,11 +158,72 @@
|
|
|
<el-table-column label="联系人" prop="contact" min-width="100" show-overflow-tooltip />
|
|
|
<el-table-column label="联系电话" prop="contactPhone" min-width="120" show-overflow-tooltip />
|
|
|
<el-table-column label="检验性质" prop="checkNature" min-width="100" show-overflow-tooltip />
|
|
|
- <el-table-column label="下次检验日期" prop="nextCheckDate" min-width="120" show-overflow-tooltip />
|
|
|
+
|
|
|
+ <!-- 下次检验日期(带颜色和拒检提示) -->
|
|
|
+ <el-table-column label="下次检验日期" min-width="140" show-overflow-tooltip>
|
|
|
+ <template #default="scope">
|
|
|
+ <el-popover
|
|
|
+ v-if="scope.row.isRefused && getRefuseTip(scope.row).length > 0"
|
|
|
+ placement="top"
|
|
|
+ :width="250"
|
|
|
+ trigger="hover"
|
|
|
+ >
|
|
|
+ <template #reference>
|
|
|
+ <div :style="getCellStyle(scope.row)">
|
|
|
+ <span>{{ scope.row.nextCheckDate || '-' }}</span>
|
|
|
+ <span v-if="scope.row.isExceedTimeLimit && showExceedTag" class="exceed-tag">超</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #default>
|
|
|
+ <div v-for="(line, idx) in getRefuseTip(scope.row)" :key="idx">{{ line }}</div>
|
|
|
+ </template>
|
|
|
+ </el-popover>
|
|
|
+ <el-popover
|
|
|
+ v-else-if="scope.row.hasPendingAppointment"
|
|
|
+ placement="top"
|
|
|
+ :width="200"
|
|
|
+ trigger="hover"
|
|
|
+ >
|
|
|
+ <template #reference>
|
|
|
+ <div :style="getCellStyle(scope.row)">
|
|
|
+ <span>{{ scope.row.nextCheckDate || '-' }}</span>
|
|
|
+ <span v-if="scope.row.isExceedTimeLimit && showExceedTag" class="exceed-tag">超</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #default>
|
|
|
+ <div>待约检</div>
|
|
|
+ <div>检验时间:{{ scope.row.appointmentDate || '-' }}</div>
|
|
|
+ </template>
|
|
|
+ </el-popover>
|
|
|
+ <el-popover
|
|
|
+ v-else-if="isRowScheduled(scope.row)"
|
|
|
+ placement="top"
|
|
|
+ :width="200"
|
|
|
+ trigger="hover"
|
|
|
+ >
|
|
|
+ <template #reference>
|
|
|
+ <div :style="getCellStyle(scope.row)">
|
|
|
+ <span>{{ scope.row.nextCheckDate || '-' }}</span>
|
|
|
+ <span v-if="scope.row.isExceedTimeLimit && showExceedTag" class="exceed-tag">超</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #default>
|
|
|
+ <div>已排期</div>
|
|
|
+ <div>排期时间:{{ getScheduledDate(scope.row) || '-' }}</div>
|
|
|
+ </template>
|
|
|
+ </el-popover>
|
|
|
+ <div v-else :style="getCellStyle(scope.row)">
|
|
|
+ <span>{{ scope.row.nextCheckDate || '-' }}</span>
|
|
|
+ <span v-if="scope.row.isExceedTimeLimit && showExceedTag" class="exceed-tag">超</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="备注" prop="pendingInspectionRemark" min-width="120" show-overflow-tooltip />
|
|
|
<el-table-column label="部门" prop="deptName" min-width="120" show-overflow-tooltip />
|
|
|
</el-table>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<!-- 分页区域 -->
|
|
|
<div class="pagination-container">
|
|
|
<el-pagination
|
|
|
@@ -164,20 +237,54 @@
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<!-- 设备详情弹窗 -->
|
|
|
<EquipContainerForm ref="equipContainerFormRef" />
|
|
|
<EquipBoilerForm ref="equipBoilerFormRef" />
|
|
|
<EquipPipeForm ref="equipPipeFormRef" />
|
|
|
+
|
|
|
+ <!-- 备注弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="remarkDialogVisible"
|
|
|
+ :title="Array.isArray(currentRemarkRow) ? '批量添加备注' : '备注'"
|
|
|
+ width="500px"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ :close-on-press-escape="false"
|
|
|
+ >
|
|
|
+ <el-form :model="remarkForm" label-width="80px">
|
|
|
+ <el-form-item label="备注内容">
|
|
|
+ <el-input
|
|
|
+ v-model="remarkForm.pendingInspectionRemark"
|
|
|
+ type="textarea"
|
|
|
+ :rows="4"
|
|
|
+ :placeholder="Array.isArray(currentRemarkRow) ? `已选择 ${currentRemarkRow.length} 台设备,请输入备注内容` : '请输入备注内容'"
|
|
|
+ maxlength="300"
|
|
|
+ show-word-limit
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button :loading="remarkDialogLoading" @click="handleRemarkCancel">取消</el-button>
|
|
|
+ <el-button type="primary" :loading="remarkDialogLoading" @click="handleRemarkConfirm">
|
|
|
+ 确定
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 批量修改约检联系人弹窗 -->
|
|
|
+ <BatchEditForm ref="batchEditFormRef" @success="handleBatchEditFormSuccess" />
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup name="EquipmentAppointment">
|
|
|
-import { ref, onMounted } from 'vue'
|
|
|
+import { ref, onMounted, onUnmounted, computed, nextTick, watch } from 'vue'
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
import { Search, Refresh, Download } from '@element-plus/icons-vue'
|
|
|
import EquipContainerForm from '@/components/EquipContainerForm/index.vue'
|
|
|
import EquipBoilerForm from '@/components/EquipBoilerForm/index.vue'
|
|
|
import EquipPipeForm from '@/components/EquipPipeForm/index.vue'
|
|
|
+import BatchEditForm from './components/batchEditForm.vue'
|
|
|
import AreaSelect from '@/views/system/equipcontainer/components/AreaSelect.vue'
|
|
|
import { getStrDictOptions, getDictLabel, DICT_TYPE } from '@/utils/dict'
|
|
|
import FetchApis from './index.api'
|
|
|
@@ -196,10 +303,11 @@ const equipContainerFormRef = ref()
|
|
|
const equipBoilerFormRef = ref()
|
|
|
const equipPipeFormRef = ref()
|
|
|
const { addPlanNewData } = usePlanNewStore()
|
|
|
+const { setPageParams, getPageParams, deletePageParams } = usePageParamsStore('qtyj')
|
|
|
const router = useRouter()
|
|
|
|
|
|
// 设备类型
|
|
|
-const selectedEquipMainType = ref('boiler') // 默认锅炉
|
|
|
+const selectedEquipMainType = ref('boiler')
|
|
|
|
|
|
// 初始化默认日期值
|
|
|
const getDefaultDate = () => {
|
|
|
@@ -211,7 +319,7 @@ const getDefaultDate = () => {
|
|
|
const searchFormDataTable = ref({
|
|
|
deptId: userStore?.user?.deptId,
|
|
|
checkDate: getDefaultDate(),
|
|
|
- equipMainType: 'boiler', // 默认锅炉
|
|
|
+ equipMainType: 'boiler',
|
|
|
unitName: '',
|
|
|
equipCode: '',
|
|
|
equipDistrict: '',
|
|
|
@@ -237,6 +345,145 @@ const pageSize = ref(10)
|
|
|
const total = ref(0)
|
|
|
const loading = ref(false)
|
|
|
|
|
|
+// 备注弹窗相关
|
|
|
+const remarkDialogVisible = ref(false)
|
|
|
+const remarkDialogLoading = ref(false)
|
|
|
+const remarkForm = ref({
|
|
|
+ pendingInspectionRemark: ''
|
|
|
+})
|
|
|
+const currentRemarkRow = ref<Record<string, any> | Array<Record<string, any>> | null>(null)
|
|
|
+
|
|
|
+// 拒检原因字典映射
|
|
|
+const refuseReasonDictMap: Record<number, string> = {
|
|
|
+ 1: '客户准备注销',
|
|
|
+ 2: '客户准备报停',
|
|
|
+ 3: '无法联系用户',
|
|
|
+ 4: '数据有误',
|
|
|
+ 5: '其他'
|
|
|
+}
|
|
|
+
|
|
|
+// 年检处理状态字典映射
|
|
|
+const yearCheckProcessStatusMap: Record<number, string> = {
|
|
|
+ 0: '待处理',
|
|
|
+ 1: '无需处理',
|
|
|
+ 2: '拒绝年检'
|
|
|
+}
|
|
|
+
|
|
|
+// 定检拒绝状态字典映射
|
|
|
+const checkRefuseStatusMap: Record<number, string> = {
|
|
|
+ 1: '待处理',
|
|
|
+ 2: '无需处理',
|
|
|
+ 3: '审核中',
|
|
|
+ 4: '审核已拒绝',
|
|
|
+ 5: '已作废',
|
|
|
+ 6: '待上报',
|
|
|
+ 7: '已上报'
|
|
|
+}
|
|
|
+
|
|
|
+// 是否显示"超"字标签(当前 tab 为定检/超年限检验时显示)
|
|
|
+const showExceedTag = computed(() => {
|
|
|
+ if (selectedEquipMainType.value === 'boiler') return checkType.value === 100 || checkType.value === 300
|
|
|
+ if (selectedEquipMainType.value === 'pipe') return checkType.value === 100
|
|
|
+ return false
|
|
|
+})
|
|
|
+
|
|
|
+const getRefuseTip = (row: Record<string, any>) => {
|
|
|
+ if (!row) return []
|
|
|
+ const checkTypeVal = row.checkType
|
|
|
+ if (checkTypeVal === 200) {
|
|
|
+ const { processStatus, refuseYearItemDict, refuseYearItemReason } = row
|
|
|
+ if (processStatus !== undefined && processStatus !== null) {
|
|
|
+ const statusText = yearCheckProcessStatusMap[processStatus] || ''
|
|
|
+ let reasonText = ''
|
|
|
+ if (refuseYearItemDict) {
|
|
|
+ const reasonCategory = refuseReasonDictMap[refuseYearItemDict] || ''
|
|
|
+ if (refuseYearItemDict == 5 && refuseYearItemReason) {
|
|
|
+ reasonText = `${reasonCategory}(${refuseYearItemReason})`
|
|
|
+ } else if (refuseYearItemReason) {
|
|
|
+ reasonText = refuseYearItemReason
|
|
|
+ } else if (reasonCategory) {
|
|
|
+ reasonText = reasonCategory
|
|
|
+ }
|
|
|
+ } else if (refuseYearItemReason) {
|
|
|
+ reasonText = refuseYearItemReason
|
|
|
+ }
|
|
|
+ const lines: string[] = []
|
|
|
+ if (statusText) lines.push(`拒绝年检状态:${statusText}`)
|
|
|
+ if (reasonText) lines.push(`拒绝年检原因:${reasonText}`)
|
|
|
+ return lines
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ const { refuseCheckStatus, reasonDict, reason } = row
|
|
|
+ if (refuseCheckStatus !== undefined && refuseCheckStatus !== null) {
|
|
|
+ const statusText = checkRefuseStatusMap[refuseCheckStatus] || ''
|
|
|
+ let reasonText = ''
|
|
|
+ if (reasonDict) {
|
|
|
+ const reasonCategory = refuseReasonDictMap[reasonDict] || ''
|
|
|
+ if (reasonDict == 5 && reason) {
|
|
|
+ reasonText = `${reasonCategory}(${reason})`
|
|
|
+ } else if (reason) {
|
|
|
+ reasonText = reason
|
|
|
+ } else if (reasonCategory) {
|
|
|
+ reasonText = reasonCategory
|
|
|
+ }
|
|
|
+ } else if (reason) {
|
|
|
+ reasonText = reason
|
|
|
+ }
|
|
|
+ const lines: string[] = []
|
|
|
+ if (statusText) lines.push(`拒绝定检状态:${statusText}`)
|
|
|
+ if (reasonText) lines.push(`拒绝定检原因:${reasonText}`)
|
|
|
+ return lines
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return []
|
|
|
+}
|
|
|
+
|
|
|
+const getCellStyle = (row: Record<string, any>) => {
|
|
|
+ const baseStyle: Record<string, any> = {
|
|
|
+ display: 'flex',
|
|
|
+ alignItems: 'center',
|
|
|
+ justifyContent: 'center',
|
|
|
+ gap: '4px',
|
|
|
+ width: '100%',
|
|
|
+ height: '100%',
|
|
|
+ padding: '0',
|
|
|
+ margin: '0',
|
|
|
+ minHeight: '40px'
|
|
|
+ }
|
|
|
+ if (row.isRefused) {
|
|
|
+ baseStyle.backgroundColor = '#ff3d33'
|
|
|
+ baseStyle.color = 'white'
|
|
|
+ } else if (row.hasPendingAppointment) {
|
|
|
+ baseStyle.backgroundColor = '#54aeea'
|
|
|
+ baseStyle.color = 'white'
|
|
|
+ } else if (isRowScheduled(row)) {
|
|
|
+ baseStyle.backgroundColor = '#ffd89b'
|
|
|
+ baseStyle.color = '#333'
|
|
|
+ }
|
|
|
+ return baseStyle
|
|
|
+}
|
|
|
+
|
|
|
+const isRowScheduled = (row: Record<string, any>) => {
|
|
|
+ return (row.checkType == 200 && row.yearSchedulingPlanDate) ||
|
|
|
+ (row.checkType == 100 && row.schedulingPlanDate) ||
|
|
|
+ (row.checkType == 300 && row.expiredSchedulingPlanDate)
|
|
|
+}
|
|
|
+
|
|
|
+const getScheduledDate = (row: Record<string, any>) => {
|
|
|
+ if (row.checkType == 200) return row.yearSchedulingPlanDate
|
|
|
+ if (row.checkType == 100) return row.schedulingPlanDate
|
|
|
+ if (row.checkType == 300) return row.expiredSchedulingPlanDate
|
|
|
+ return null
|
|
|
+}
|
|
|
+
|
|
|
+const canAppointment = (row: Record<string, any>) => {
|
|
|
+ if (row.hasPendingAppointment === true) return false
|
|
|
+ if (row.checkType == 200 && row.yearSchedulingPlanDate) return false
|
|
|
+ if (row.checkType == 100 && row.schedulingPlanDate) return false
|
|
|
+ if (row.checkType == 300 && row.expiredSchedulingPlanDate) return false
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
// 设备类型变化处理
|
|
|
const handleEquipTypeChange = (value: string) => {
|
|
|
selectedEquipMainType.value = value
|
|
|
@@ -246,7 +493,7 @@ const handleEquipTypeChange = (value: string) => {
|
|
|
getListPageFn()
|
|
|
}
|
|
|
|
|
|
-// 构建通用请求参数(匹配后端 PendingInspectionEquipReqVO)
|
|
|
+// 构建通用请求参数
|
|
|
const buildCommonRequestParams = (baseParams: any) => {
|
|
|
const data: any = {
|
|
|
...cloneDeep(baseParams),
|
|
|
@@ -257,14 +504,12 @@ const buildCommonRequestParams = (baseParams: any) => {
|
|
|
pageSize: pageSize.value
|
|
|
}
|
|
|
|
|
|
- // 清理空值
|
|
|
for (const key in data) {
|
|
|
if (isEmpty(data[key])) {
|
|
|
delete data[key]
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 处理检验日期范围:checkDate 数组 → checkDateStart / checkDateEnd
|
|
|
if (data?.checkDate) {
|
|
|
if (Array.isArray(data.checkDate) && data.checkDate.length === 2) {
|
|
|
data.checkDateStart = data.checkDate[0]
|
|
|
@@ -273,7 +518,6 @@ const buildCommonRequestParams = (baseParams: any) => {
|
|
|
delete data.checkDate
|
|
|
}
|
|
|
|
|
|
- // 处理拒检设备筛选:'flag'→不筛选, 'true'/'false'→布尔
|
|
|
if (data.isRefused === 'flag') {
|
|
|
delete data.isRefused
|
|
|
} else if (data.isRefused !== undefined) {
|
|
|
@@ -286,11 +530,9 @@ const buildCommonRequestParams = (baseParams: any) => {
|
|
|
// 将后端返回的设备数据映射为表格列所需的字段名
|
|
|
const mapEquipDataForTable = (item: any) => {
|
|
|
const mapped = { ...item }
|
|
|
- // 检验性质:后端直接返回 checkTypeStr
|
|
|
if (mapped.checkTypeStr !== undefined && mapped.checkTypeStr !== null && mapped.checkTypeStr !== '') {
|
|
|
mapped.checkNature = mapped.checkTypeStr
|
|
|
}
|
|
|
- // 设备分类:后端 equipType(dict ID) → 前端 equipTypeName(dict label)
|
|
|
if (mapped.equipType !== undefined && mapped.equipType !== null) {
|
|
|
if (selectedEquipMainType.value === 'boiler') {
|
|
|
mapped.equipTypeName = getDictLabel(DICT_TYPE.SYSTEM_EQUIP_BOILER_TYPE, mapped.equipType)
|
|
|
@@ -298,7 +540,6 @@ const mapEquipDataForTable = (item: any) => {
|
|
|
mapped.equipTypeName = getDictLabel(DICT_TYPE.PIPE_TYPE, mapped.equipType)
|
|
|
}
|
|
|
}
|
|
|
- // 管道特殊映射:后端 equipCode → 前端 projectNo,equipName → projectName
|
|
|
if (selectedEquipMainType.value === 'pipe') {
|
|
|
mapped.projectNo = mapped.equipCode
|
|
|
mapped.projectName = mapped.equipName
|
|
|
@@ -314,19 +555,15 @@ const getListPageFn = async () => {
|
|
|
let result
|
|
|
|
|
|
if (equipMainType === 'container') {
|
|
|
- // 容器使用 pressure 模块的 POST 接口
|
|
|
result = await FetchApis.getContainerPage(data)
|
|
|
} else if (equipMainType === 'boiler') {
|
|
|
- // 锅炉使用 pressure2 模块的 GET 接口
|
|
|
result = await FetchApis.getBoilerPage(data)
|
|
|
} else if (equipMainType === 'pipe') {
|
|
|
- // 管道使用 pressure2 模块的 GET 接口
|
|
|
result = await FetchApis.getPipePage(data)
|
|
|
}
|
|
|
|
|
|
if (result) {
|
|
|
const list = result.list || []
|
|
|
- // 将后端字段映射为前端表格列所需的字段名
|
|
|
tableData.value = list.map(mapEquipDataForTable)
|
|
|
total.value = result.total || 0
|
|
|
}
|
|
|
@@ -355,16 +592,10 @@ const handleReset = () => {
|
|
|
}
|
|
|
|
|
|
const handleExportFn = async () => {
|
|
|
- const equipMainType = selectedEquipMainType.value
|
|
|
- if (equipMainType !== 'container') {
|
|
|
- ElMessage.warning('锅炉和管道的导出功能暂未开放,请使用容器设备导出')
|
|
|
- return
|
|
|
- }
|
|
|
loading.value = true
|
|
|
try {
|
|
|
const data = buildCommonRequestParams(searchFormDataTable.value)
|
|
|
data.ids = selectedRows.value.map((item: any) => item.id)
|
|
|
- // 导出时如果没有选中行,则导出全部
|
|
|
if (!selectedRows.value.length) {
|
|
|
data.pageSize = total.value
|
|
|
}
|
|
|
@@ -390,11 +621,9 @@ const handleExportFn = async () => {
|
|
|
}
|
|
|
|
|
|
const handleAppointment = (row: any) => {
|
|
|
- const { deletePageParams } = usePageParamsStore('qtyj')
|
|
|
deletePageParams()
|
|
|
|
|
|
if (selectedEquipMainType.value === 'container') {
|
|
|
- // 容器使用原来的压力模块
|
|
|
const routerValue = {
|
|
|
name: 'PlanNewDetail',
|
|
|
path: '/planNew/detail'
|
|
|
@@ -403,32 +632,152 @@ const handleAppointment = (row: any) => {
|
|
|
addPlanNewData(row)
|
|
|
router.push({
|
|
|
name: 'PlanNewDetail',
|
|
|
- query: {
|
|
|
- id: row.id || row.taskId,
|
|
|
- equipCode: row.equipCode
|
|
|
- }
|
|
|
+ query: { id: row.id, equipCode: row.equipCode, t: Date.now() }
|
|
|
})
|
|
|
} else if (selectedEquipMainType.value === 'boiler') {
|
|
|
- // 锅炉使用pressure2模块的锅炉详情页
|
|
|
+ const routerValue = {
|
|
|
+ name: 'BoilerDetail',
|
|
|
+ path: '/planNew/boilerDetail'
|
|
|
+ }
|
|
|
+ tagsViewStore.delVisitedNameView(routerValue)
|
|
|
+ addPlanNewData(row)
|
|
|
router.push({
|
|
|
path: '/ywgl/planNew/boilerDetail',
|
|
|
- query: {
|
|
|
- id: row.id || row.taskId,
|
|
|
- equipCode: row.equipCode
|
|
|
- }
|
|
|
+ query: { id: row.id, equipCode: row.equipCode, t: Date.now() }
|
|
|
})
|
|
|
} else if (selectedEquipMainType.value === 'pipe') {
|
|
|
- // 管道使用pressure2模块的管道详情页
|
|
|
+ const routerValue = {
|
|
|
+ name: 'PipeDetail',
|
|
|
+ path: '/planNew/pipeDetail'
|
|
|
+ }
|
|
|
+ tagsViewStore.delVisitedNameView(routerValue)
|
|
|
+ addPlanNewData(row)
|
|
|
router.push({
|
|
|
path: '/ywgl/planNew/pipeDetail',
|
|
|
- query: {
|
|
|
- id: row.id || row.taskId,
|
|
|
- equipCode: row.equipCode
|
|
|
- }
|
|
|
+ query: { id: row.id, equipCode: row.equipCode, t: Date.now() }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 批量约检
|
|
|
+const canBatchAppointment = () => {
|
|
|
+ const selectionRows = selectedRows.value
|
|
|
+ if (selectionRows.length === 0) return false
|
|
|
+ const firstUnitId = selectionRows[0].unitId
|
|
|
+ if (!selectionRows.every((row: any) => row.unitId === firstUnitId)) return false
|
|
|
+ return selectionRows.every((row: any) => canAppointment(row))
|
|
|
+}
|
|
|
+
|
|
|
+const handleBatchAppointment = () => {
|
|
|
+ const selectionRows = selectedRows.value
|
|
|
+ if (selectionRows.length === 0) {
|
|
|
+ ElMessage.warning('请先选择设备')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const firstUnitId = selectionRows[0].unitId
|
|
|
+ if (!selectionRows.every((row: any) => row.unitId === firstUnitId)) {
|
|
|
+ ElMessage.warning('请选择同一使用单位的设备')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const cannotRows = selectionRows.filter((row: any) => !canAppointment(row))
|
|
|
+ if (cannotRows.length > 0) {
|
|
|
+ ElMessage.warning('所选设备中存在不符合约检条件的设备,无法批量约检')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const equipCodes = selectionRows.map((row: any) => row.equipCode).filter(Boolean)
|
|
|
+ if (equipCodes.length === 0) {
|
|
|
+ ElMessage.warning('选中的设备没有设备注册代码')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const firstRow = selectionRows[0]
|
|
|
+ deletePageParams()
|
|
|
+ addPlanNewData(firstRow)
|
|
|
+
|
|
|
+ if (selectedEquipMainType.value === 'container') {
|
|
|
+ const routerValue = { name: 'PlanNewDetail', path: '/planNew/detail' }
|
|
|
+ tagsViewStore.delVisitedNameView(routerValue)
|
|
|
+ router.push({
|
|
|
+ name: 'PlanNewDetail',
|
|
|
+ query: { id: firstRow.id, equipCode: firstRow.equipCode, t: Date.now() }
|
|
|
})
|
|
|
+ } else if (selectedEquipMainType.value === 'boiler') {
|
|
|
+ router.push({
|
|
|
+ path: '/ywgl/planNew/boilerDetail',
|
|
|
+ query: { id: firstRow.id, equipCode: firstRow.equipCode, t: Date.now() }
|
|
|
+ })
|
|
|
+ } else if (selectedEquipMainType.value === 'pipe') {
|
|
|
+ router.push({
|
|
|
+ path: '/ywgl/planNew/pipeDetail',
|
|
|
+ query: { id: firstRow.id, equipCode: firstRow.equipCode, t: Date.now() }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 批量修改约检联系人
|
|
|
+const batchEditFormRef = ref()
|
|
|
+const handleBatchEditContact = () => {
|
|
|
+ if (selectedRows.value.length === 0) {
|
|
|
+ ElMessage.warning('请先选择设备')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ batchEditFormRef.value?.open(selectedRows.value, selectedEquipMainType.value)
|
|
|
+}
|
|
|
+const handleBatchEditFormSuccess = () => {
|
|
|
+ getListPageFn()
|
|
|
+}
|
|
|
+
|
|
|
+// 备注弹窗
|
|
|
+const openRemarkDialog = (row: Record<string, any>) => {
|
|
|
+ currentRemarkRow.value = row
|
|
|
+ remarkForm.value.pendingInspectionRemark = row.pendingInspectionRemark || ''
|
|
|
+ remarkDialogVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const handleBatchRemark = () => {
|
|
|
+ if (selectedRows.value.length === 0) {
|
|
|
+ ElMessage.warning('请先选择设备')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ currentRemarkRow.value = selectedRows.value
|
|
|
+ remarkForm.value.pendingInspectionRemark = ''
|
|
|
+ remarkDialogVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const handleRemarkConfirm = async () => {
|
|
|
+ if (!currentRemarkRow.value) return
|
|
|
+ remarkDialogLoading.value = true
|
|
|
+ try {
|
|
|
+ const isBatch = Array.isArray(currentRemarkRow.value)
|
|
|
+ const ids = isBatch
|
|
|
+ ? (currentRemarkRow.value as Record<string, any>[]).map((row: any) => row.id)
|
|
|
+ : [(currentRemarkRow.value as Record<string, any>).id]
|
|
|
+ await FetchApis.updatePendingInspectionRemark({
|
|
|
+ ids,
|
|
|
+ pendingInspectionRemark: remarkForm.value.pendingInspectionRemark
|
|
|
+ }, selectedEquipMainType.value)
|
|
|
+ ElMessage.success(isBatch ? '批量备注保存成功' : '备注保存成功')
|
|
|
+ remarkDialogVisible.value = false
|
|
|
+ getListPageFn()
|
|
|
+ } catch (error) {
|
|
|
+ console.error('保存备注失败:', error)
|
|
|
+ } finally {
|
|
|
+ remarkDialogLoading.value = false
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+const handleRemarkCancel = () => {
|
|
|
+ remarkDialogLoading.value = true
|
|
|
+ setTimeout(() => {
|
|
|
+ remarkDialogVisible.value = false
|
|
|
+ remarkDialogLoading.value = false
|
|
|
+ remarkForm.value.pendingInspectionRemark = ''
|
|
|
+ currentRemarkRow.value = null
|
|
|
+ }, 300)
|
|
|
+}
|
|
|
+
|
|
|
+// 设备详情弹窗
|
|
|
const handleEquipCodeFn = (id: string) => {
|
|
|
if (selectedEquipMainType.value === 'container') {
|
|
|
equipContainerFormRef.value?.open(id)
|
|
|
@@ -461,9 +810,95 @@ const handleQuery = () => {
|
|
|
const selectedRows = ref([])
|
|
|
const checkType = ref(100)
|
|
|
|
|
|
+// 监听搜索表单 checkDate 变化
|
|
|
+watch(
|
|
|
+ () => searchFormDataTable.value.checkDate,
|
|
|
+ (newVal) => {
|
|
|
+ if (isResetting.value) return
|
|
|
+ if (newVal && Array.isArray(newVal) && newVal.length === 2) {
|
|
|
+ savedCheckDate.value = newVal
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+)
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
+ const route = router.currentRoute.value
|
|
|
+ const query = route.query || {}
|
|
|
+
|
|
|
+ // 优先从 store 恢复搜索条件(切换 tab 回来时)
|
|
|
+ const savedParams = getPageParams()
|
|
|
+ if (savedParams) {
|
|
|
+ if (savedParams.selectedEquipMainType) {
|
|
|
+ selectedEquipMainType.value = savedParams.selectedEquipMainType
|
|
|
+ searchFormDataTable.value.equipMainType = savedParams.selectedEquipMainType
|
|
|
+ }
|
|
|
+ if (savedParams.checkType !== undefined) {
|
|
|
+ checkType.value = savedParams.checkType
|
|
|
+ }
|
|
|
+ if (savedParams.searchFormDataTable) {
|
|
|
+ Object.assign(searchFormDataTable.value, savedParams.searchFormDataTable)
|
|
|
+ }
|
|
|
+ if (savedParams.searchFormData) {
|
|
|
+ Object.assign(searchFormData.value, savedParams.searchFormData)
|
|
|
+ }
|
|
|
+ if (savedParams.pageNo) pageNo.value = savedParams.pageNo
|
|
|
+ if (savedParams.pageSize) pageSize.value = savedParams.pageSize
|
|
|
+ getListPageFn()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 其次从路由 query 恢复(外部跳转进来时)
|
|
|
+ if (query.isClaim !== undefined) {
|
|
|
+ // 兼容 isClaim 参数
|
|
|
+ }
|
|
|
+ if (query.equipMainType !== undefined) {
|
|
|
+ const type = String(query.equipMainType)
|
|
|
+ if (['boiler', 'pipe', 'container'].includes(type)) {
|
|
|
+ selectedEquipMainType.value = type
|
|
|
+ searchFormDataTable.value.equipMainType = type
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (query.deptId !== undefined && query.deptId !== null && query.deptId !== '') {
|
|
|
+ searchFormDataTable.value.deptId = String(query.deptId)
|
|
|
+ }
|
|
|
+ if (query.equipDistrict !== undefined && query.equipDistrict !== null && query.equipDistrict !== '') {
|
|
|
+ searchFormDataTable.value.equipDistrict = String(query.equipDistrict)
|
|
|
+ }
|
|
|
+ if (query.unitName !== undefined && query.unitName !== null && query.unitName !== '') {
|
|
|
+ searchFormDataTable.value.unitName = String(query.unitName)
|
|
|
+ }
|
|
|
+ if (query.contactPhone !== undefined && query.contactPhone !== null && query.contactPhone !== '') {
|
|
|
+ searchFormDataTable.value.contactPhone = String(query.contactPhone)
|
|
|
+ }
|
|
|
+ if (query.equipCode !== undefined && query.equipCode !== null && query.equipCode !== '') {
|
|
|
+ searchFormDataTable.value.equipCode = String(query.equipCode)
|
|
|
+ }
|
|
|
+ if (query.checkType !== undefined && query.checkType !== null) {
|
|
|
+ checkType.value = Number(query.checkType)
|
|
|
+ }
|
|
|
+ if (query.isRefused !== undefined && query.isRefused !== null) {
|
|
|
+ searchFormData.value.isRefused = String(query.isRefused)
|
|
|
+ }
|
|
|
+ if (query.checkDateStart !== undefined && query.checkDateEnd !== undefined) {
|
|
|
+ searchFormDataTable.value.checkDate = [String(query.checkDateStart), String(query.checkDateEnd)]
|
|
|
+ savedCheckDate.value = [String(query.checkDateStart), String(query.checkDateEnd)]
|
|
|
+ }
|
|
|
+
|
|
|
getListPageFn()
|
|
|
})
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ // 保存当前搜索条件,切换 tab 回来时恢复
|
|
|
+ setPageParams({
|
|
|
+ selectedEquipMainType: selectedEquipMainType.value,
|
|
|
+ checkType: checkType.value,
|
|
|
+ pageNo: pageNo.value,
|
|
|
+ pageSize: pageSize.value,
|
|
|
+ searchFormDataTable: { ...searchFormDataTable.value },
|
|
|
+ searchFormData: { ...searchFormData.value }
|
|
|
+ })
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
@@ -486,18 +921,19 @@ onMounted(() => {
|
|
|
align-items: center;
|
|
|
padding: 12px 0;
|
|
|
margin-bottom: 16px;
|
|
|
-
|
|
|
+
|
|
|
.toolbar-left {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 16px;
|
|
|
flex-wrap: wrap;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.toolbar-right {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 12px;
|
|
|
+ flex-wrap: wrap;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -507,7 +943,7 @@ onMounted(() => {
|
|
|
margin-bottom: 16px;
|
|
|
flex-wrap: wrap;
|
|
|
gap: 12px;
|
|
|
-
|
|
|
+
|
|
|
.label-text {
|
|
|
font-size: 14px;
|
|
|
color: #606266;
|
|
|
@@ -525,4 +961,16 @@ onMounted(() => {
|
|
|
justify-content: flex-end;
|
|
|
padding: 12px 0;
|
|
|
}
|
|
|
+
|
|
|
+.exceed-tag {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ background-color: red;
|
|
|
+ color: white;
|
|
|
+ padding: 2px 6px;
|
|
|
+ border-radius: 2px;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 1;
|
|
|
+}
|
|
|
</style>
|