| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-tabs v-model="activeTab" @tab-click="handleTabClick"> |
| | | <div class="app-container safety-facility-page"> |
| | | <el-tabs v-model="activeTab" |
| | | class="facility-tabs" |
| | | @tab-click="handleTabClick"> |
| | | <!-- 安全设施台账 --> |
| | | <el-tab-pane label="安全设施台账" name="ledger"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <div class="facility-toolbar"> |
| | | <div class="toolbar-filters"> |
| | | <span class="search_title">设施编号:</span> |
| | | <el-input v-model="ledgerSearchForm.facilityCode" |
| | | style="width: 200px" |
| | |
| | | <el-option label="报废" value="报废" /> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleLedgerQuery" |
| | | style="margin-left: 10px"> |
| | | @click="handleLedgerQuery"> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetLedgerQuery">重置</el-button> |
| | | </div> |
| | | <div> |
| | | <div class="toolbar-actions"> |
| | | <el-button type="danger" |
| | | plain |
| | | :disabled="ledgerSelectedIds.length === 0" |
| | | @click="handleBatchDeleteLedger">批量删除</el-button> |
| | | <el-button type="primary" |
| | | @click="openLedgerForm('add')">新增设施</el-button> |
| | | </div> |
| | |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 安全设施巡检 --> |
| | | <el-tab-pane label="安全设施巡检" name="inspection"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <!-- 巡检任务 --> |
| | | <el-tab-pane label="巡检任务" name="task"> |
| | | <div class="facility-toolbar"> |
| | | <div class="toolbar-filters"> |
| | | <span class="search_title">巡检任务名称:</span> |
| | | <el-input v-model="taskSearchForm.inspectionName" |
| | | style="width: 220px" |
| | | placeholder="请输入巡检任务名称" |
| | | @change="handleTaskQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">设施名称:</span> |
| | | <el-input v-model="taskSearchForm.facilityName" |
| | | style="width: 200px" |
| | | placeholder="请输入设施名称" |
| | | @change="handleTaskQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">是否启用:</span> |
| | | <el-select v-model="taskSearchForm.isEnabled" |
| | | clearable |
| | | @change="handleTaskQuery" |
| | | style="width: 150px"> |
| | | <el-option label="是" :value="1" /> |
| | | <el-option label="否" :value="0" /> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleTaskQuery"> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetTaskQuery">重置</el-button> |
| | | </div> |
| | | <div class="toolbar-actions"> |
| | | <el-button type="danger" |
| | | plain |
| | | :disabled="taskSelectedIds.length === 0" |
| | | @click="handleBatchDeleteTask">删除</el-button> |
| | | <el-button type="primary" |
| | | @click="openTaskDialog('add')">新增巡检任务</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="id" |
| | | :column="taskTableColumn" |
| | | :tableData="taskTableData" |
| | | :page="taskPage" |
| | | :isSelection="true" |
| | | @selection-change="handleTaskSelectionChange" |
| | | :tableLoading="taskTableLoading" |
| | | @pagination="taskPagination" |
| | | :total="taskPage.total"></PIMTable> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 巡检记录 --> |
| | | <el-tab-pane label="巡检记录" name="inspection"> |
| | | <div class="facility-toolbar"> |
| | | <div class="toolbar-filters"> |
| | | <span class="search_title">巡检编号:</span> |
| | | <el-input v-model="inspectionSearchForm.inspectionCode" |
| | | style="width: 200px" |
| | |
| | | <el-option label="已巡检" value="已巡检" /> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleInspectionQuery" |
| | | style="margin-left: 10px"> |
| | | @click="handleInspectionQuery"> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetInspectionQuery">重置</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | |
| | | <!-- 整改跟踪 --> |
| | | <el-tab-pane label="整改跟踪" name="rectification"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <div class="facility-toolbar"> |
| | | <div class="toolbar-filters"> |
| | | <span class="search_title">状态:</span> |
| | | <el-select v-model="rectificationSearchForm.status" |
| | | clearable |
| | |
| | | <el-option label="已验收" value="已验收" /> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleRectificationQuery" |
| | | style="margin-left: 10px"> |
| | | @click="handleRectificationQuery"> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetRectificationQuery">重置</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="有效期(天)" |
| | | prop="validPeriod"> |
| | | <el-input-number v-model="ledgerForm.validPeriod" |
| | | :min="0" |
| | | placeholder="请输入有效期" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="状态" |
| | | prop="status"> |
| | | <el-select v-model="ledgerForm.status" |
| | |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 巡检表单弹窗 --> |
| | | <el-dialog v-model="inspectionDialogVisible" |
| | | :title="inspectionDialogTitle" |
| | | width="600px" |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="inspectionFormRef" |
| | | :model="inspectionForm" |
| | | :rules="inspectionRules" |
| | | <!-- 设施台账详情弹窗 --> |
| | | <el-dialog v-model="ledgerDetailVisible" |
| | | title="设施详情" |
| | | width="760px" |
| | | class="detail-dialog"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="设施编号">{{ ledgerDetail.facilityCode || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="设施名称">{{ ledgerDetail.facilityName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="设施类型">{{ ledgerDetail.facilityType || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="规格型号">{{ ledgerDetail.facilitySpec || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="安装位置">{{ ledgerDetail.installLocation || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="安装时间">{{ ledgerDetail.installTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="生产日期">{{ ledgerDetail.productionDate || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="状态"> |
| | | <el-tag :type="ledgerStatusType(ledgerDetail.status)">{{ ledgerDetail.status || '-' }}</el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="备注" :span="2">{{ ledgerDetail.remark || '-' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" @click="ledgerDetailVisible = false">关闭</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 巡检任务表单弹窗 --> |
| | | <el-dialog v-model="taskDialogVisible" |
| | | :title="taskDialogTitle" |
| | | width="920px" |
| | | :close-on-click-modal="false" |
| | | @closed="resetTaskForm"> |
| | | <el-form ref="taskFormRef" |
| | | :model="taskForm" |
| | | :rules="taskRules" |
| | | label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="巡检编号" |
| | | prop="inspectionCode"> |
| | | <el-input v-model="inspectionForm.inspectionCode" |
| | | placeholder="请输入巡检编号" /> |
| | | <el-form-item label="巡检任务名称" |
| | | prop="inspectionName"> |
| | | <el-input v-model="taskForm.inspectionName" |
| | | placeholder="请输入巡检任务名称" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="巡检类型" |
| | | prop="inspectionType"> |
| | | <el-select v-model="inspectionForm.inspectionType" |
| | | placeholder="请选择巡检类型" |
| | | style="width: 100%"> |
| | | <el-option label="定期巡检" value="定期巡检" /> |
| | | <el-option label="临时巡检" value="临时巡检" /> |
| | | <el-form-item label="安全设施" |
| | | prop="facilityId"> |
| | | <el-select v-model="taskForm.facilityId" |
| | | placeholder="请选择安全设施" |
| | | filterable |
| | | clearable |
| | | style="width: 100%" |
| | | @change="handleTaskFacilityChange"> |
| | | <el-option v-for="item in facilityOptions" |
| | | :key="item.id" |
| | | :label="`${item.facilityName}(${item.facilityCode || '-'})`" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="计划巡检时间" |
| | | prop="planTime"> |
| | | <el-date-picker v-model="inspectionForm.planTime" |
| | | type="datetime" |
| | | placeholder="请选择计划巡检时间" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <template v-if="inspectionDialogTitle === '巡检'"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="巡检人" |
| | | prop="inspectorId"> |
| | | <el-select v-model="taskForm.inspectorId" |
| | | placeholder="请选择巡检人" |
| | | filterable |
| | | clearable |
| | | style="width: 100%"> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否启用" |
| | | prop="isEnabled"> |
| | | <el-radio-group v-model="taskForm.isEnabled"> |
| | | <el-radio :label="1">是</el-radio> |
| | | <el-radio :label="0">否</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="巡检项目" |
| | | prop="inspectionProject"> |
| | | <el-input v-model="taskForm.inspectionProject" |
| | | type="textarea" |
| | | :autosize="{ minRows: 3, maxRows: 6 }" |
| | | placeholder="请输入巡检项目" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="备注"> |
| | | <el-input v-model="taskForm.remark" |
| | | type="textarea" |
| | | :autosize="{ minRows: 3, maxRows: 6 }" |
| | | placeholder="请输入备注" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="任务频率" |
| | | prop="frequencyType"> |
| | | <el-select v-model="taskForm.frequencyType" |
| | | placeholder="请选择" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="handleFrequencyTypeChange"> |
| | | <el-option label="每日" value="DAILY" /> |
| | | <el-option label="每周" value="WEEKLY" /> |
| | | <el-option label="每月" value="MONTHLY" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col v-if="taskForm.frequencyType === 'DAILY'" :span="12"> |
| | | <el-form-item class="frequency-detail-item" |
| | | label="执行时间" |
| | | prop="frequencyDetail"> |
| | | <el-time-picker v-model="taskForm.frequencyDetail" |
| | | placeholder="选择时间" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col v-if="taskForm.frequencyType === 'WEEKLY'" :span="12"> |
| | | <el-form-item class="frequency-detail-item" |
| | | label="执行时间" |
| | | prop="frequencyDetail"> |
| | | <div class="frequency-row"> |
| | | <el-select v-model="taskForm.week" |
| | | class="frequency-day-select" |
| | | placeholder="请选择星期" |
| | | clearable> |
| | | <el-option v-for="item in weekOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | <el-time-picker v-model="taskForm.time" |
| | | class="frequency-time-picker" |
| | | placeholder="选择时间" |
| | | format="HH:mm" |
| | | value-format="HH:mm" /> |
| | | </div> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col v-if="taskForm.frequencyType === 'MONTHLY'" :span="12"> |
| | | <el-form-item class="frequency-detail-item" |
| | | label="执行时间" |
| | | prop="frequencyDetail"> |
| | | <div class="frequency-row"> |
| | | <el-select v-model="taskForm.day" |
| | | class="frequency-day-select" |
| | | placeholder="请选择日期" |
| | | clearable> |
| | | <el-option v-for="item in dayOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | <el-time-picker v-model="taskForm.time" |
| | | class="frequency-time-picker" |
| | | placeholder="选择时间" |
| | | format="HH:mm" |
| | | value-format="HH:mm" /> |
| | | </div> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitTaskForm">保存</el-button> |
| | | <el-button @click="taskDialogVisible = false">取消</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 巡检任务详情 --> |
| | | <el-dialog v-model="taskDetailVisible" |
| | | title="巡检任务详情" |
| | | width="860px"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="巡检任务名称">{{ taskDetail.inspectionName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="安全设施">{{ taskDetail.facilityName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="设施编号">{{ taskDetail.facilityCode || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="巡检人">{{ taskDetail.inspectorName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="是否启用">{{ taskDetail.isEnabled === 1 ? '是' : '否' }}</el-descriptions-item> |
| | | <el-descriptions-item label="频次">{{ frequencyTypeMap[taskDetail.frequencyType] || taskDetail.frequencyType || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="执行时间">{{ formatFrequencyDetail(taskDetail.frequencyDetail) }}</el-descriptions-item> |
| | | <el-descriptions-item label="下次执行时间">{{ taskDetail.nextExecutionTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="巡检项目" :span="2">{{ taskDetail.inspectionProject || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="备注" :span="2">{{ taskDetail.remark || '-' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" @click="taskDetailVisible = false">关闭</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 历史巡检记录 --> |
| | | <el-dialog v-model="taskHistoryVisible" |
| | | title="历史巡检记录" |
| | | width="1100px"> |
| | | <el-descriptions class="history-summary" :column="3" border> |
| | | <el-descriptions-item label="巡检任务名称">{{ taskHistoryTask.inspectionName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="安全设施">{{ taskHistoryTask.facilityName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="频次">{{ frequencyTypeMap[taskHistoryTask.frequencyType] || taskHistoryTask.frequencyType || '-' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | <PIMTable rowKey="id" |
| | | :column="taskHistoryTableColumn" |
| | | :tableData="taskHistoryTableData" |
| | | :page="taskHistoryPage" |
| | | :isSelection="false" |
| | | :tableLoading="taskHistoryTableLoading" |
| | | @pagination="taskHistoryPagination" |
| | | :total="taskHistoryPage.total"></PIMTable> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" @click="taskHistoryVisible = false">关闭</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 巡检表单弹窗 --> |
| | | <el-dialog v-model="inspectionDialogVisible" |
| | | :title="inspectionDialogTitle" |
| | | width="720px" |
| | | class="facility-form-dialog" |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="inspectionFormRef" |
| | | :model="inspectionForm" |
| | | :rules="inspectionRules" |
| | | label-position="top" |
| | | class="inspection-form"> |
| | | <div v-if="inspectionForm.facilityName || inspectionForm.facilityCode" |
| | | class="dialog-summary"> |
| | | <div class="summary-item"> |
| | | <span>设施名称</span> |
| | | <strong>{{ inspectionForm.facilityName || '-' }}</strong> |
| | | </div> |
| | | <div class="summary-item"> |
| | | <span>设施编号</span> |
| | | <strong>{{ inspectionForm.facilityCode || '-' }}</strong> |
| | | </div> |
| | | </div> |
| | | <div class="inspection-form-grid"> |
| | | <el-form-item label="巡检编号" |
| | | prop="inspectionCode"> |
| | | <el-input v-model="inspectionForm.inspectionCode" |
| | | placeholder="请输入巡检编号" |
| | | :disabled="isInspectionBaseReadonly" /> |
| | | </el-form-item> |
| | | <el-form-item label="巡检类型" |
| | | prop="inspectionType"> |
| | | <el-select v-model="inspectionForm.inspectionType" |
| | | placeholder="请选择巡检类型" |
| | | style="width: 100%" |
| | | :disabled="isInspectionBaseReadonly"> |
| | | <el-option label="定期巡检" value="定期巡检" /> |
| | | <el-option label="临时巡检" value="临时巡检" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="计划巡检时间" |
| | | prop="planTime" |
| | | class="form-grid-full"> |
| | | <el-date-picker v-model="inspectionForm.planTime" |
| | | type="datetime" |
| | | placeholder="请选择计划巡检时间" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | style="width: 100%" |
| | | :disabled="isInspectionBaseReadonly" /> |
| | | </el-form-item> |
| | | <el-form-item label="巡检项目" |
| | | class="form-grid-full"> |
| | | <el-input v-model="inspectionForm.inspectionProject" |
| | | type="textarea" |
| | | :rows="3" |
| | | disabled /> |
| | | </el-form-item> |
| | | </div> |
| | | <template v-if="inspectionDialogType !== 'add'"> |
| | | <el-form-item label="检查结果" |
| | | prop="checkResult"> |
| | | <el-radio-group v-model="inspectionForm.checkResult"> |
| | | <el-radio-group v-model="inspectionForm.checkResult" :disabled="isInspectionView"> |
| | | <el-radio label="正常">正常</el-radio> |
| | | <el-radio label="异常">异常</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="检查说明"> |
| | | <el-form-item label="检查说明" |
| | | prop="checkDesc"> |
| | | <el-input v-model="inspectionForm.checkDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入检查说明" /> |
| | | placeholder="请输入检查说明" |
| | | :disabled="isInspectionView" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="inspectionForm.checkResult === '异常'" label="现场照片"> |
| | | <ImageUpload v-model:file-list="inspectionForm.storageBlobDTOs" |
| | | :limit="6" |
| | | button-text="上传照片" |
| | | :disabled="isInspectionView" /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | <el-button v-if="!isInspectionView" |
| | | type="primary" |
| | | @click="submitInspectionForm">确定</el-button> |
| | | <el-button @click="inspectionDialogVisible = false">取消</el-button> |
| | | <el-button @click="inspectionDialogVisible = false">{{ isInspectionView ? '关闭' : '取消' }}</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 巡检详情弹窗 --> |
| | | <el-dialog v-model="inspectionDetailVisible" |
| | | title="巡检详情" |
| | | width="920px" |
| | | class="detail-dialog"> |
| | | <el-descriptions :column="3" border> |
| | | <el-descriptions-item label="巡检编号">{{ inspectionDetail.inspectionCode || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="设施名称">{{ inspectionDetail.facilityName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="巡检人">{{ inspectionDetail.inspectorName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="计划巡检时间">{{ inspectionDetail.planTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="实际巡检时间">{{ inspectionDetail.actualTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="状态"> |
| | | <el-tag :type="inspectionStatusType(inspectionDetail.status)">{{ inspectionDetail.status || '-' }}</el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="检查结果"> |
| | | <el-tag :type="inspectionResultType(inspectionDetail.checkResult)">{{ inspectionDetail.checkResult || '未填写' }}</el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="巡检项目" :span="2">{{ inspectionDetail.inspectionProject || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="检查说明" :span="3">{{ inspectionDetail.checkDesc || '-' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | <div v-if="inspectionDetailImageUrls.length" class="detail-section"> |
| | | <div class="detail-section-title">现场照片</div> |
| | | <div class="detail-image-list"> |
| | | <el-image v-for="(url, index) in inspectionDetailImageUrls" |
| | | :key="`${url}-${index}`" |
| | | :src="url" |
| | | :preview-src-list="inspectionDetailImageUrls" |
| | | :initial-index="index" |
| | | fit="cover" |
| | | class="detail-image" /> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" @click="inspectionDetailVisible = false">关闭</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="rectificationFormRef" |
| | | :model="rectificationForm" |
| | | :rules="rectificationRules" |
| | | label-width="120px"> |
| | | <template v-if="rectificationDialogTitle !== '验收'"> |
| | | <el-form-item label="问题描述"> |
| | | <el-input v-model="rectificationForm.problemDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入问题描述" /> |
| | | </el-form-item> |
| | | <el-form-item label="问题等级"> |
| | | <el-select v-model="rectificationForm.problemLevel" |
| | | placeholder="请选择问题等级" |
| | | style="width: 100%"> |
| | | <el-option label="一般" value="一般" /> |
| | | <el-option label="重大" value="重大" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </template> |
| | | <el-form-item label="整改说明" v-if="rectificationDialogTitle === '整改'"> |
| | | <div v-if="rectificationForm.facilityName || rectificationForm.inspectionCode" |
| | | class="dialog-summary"> |
| | | <div class="summary-item"> |
| | | <span>设施名称</span> |
| | | <strong>{{ rectificationForm.facilityName || '-' }}</strong> |
| | | </div> |
| | | <div class="summary-item"> |
| | | <span>巡检编号</span> |
| | | <strong>{{ rectificationForm.inspectionCode || '-' }}</strong> |
| | | </div> |
| | | </div> |
| | | <el-form-item label="问题描述" |
| | | :prop="isRectificationCreate ? 'problemDesc' : undefined"> |
| | | <el-input v-model="rectificationForm.problemDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入问题描述" |
| | | :disabled="!isRectificationCreate" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="rectificationInspectionImageUrls.length" |
| | | label="巡检异常图片"> |
| | | <div class="rectification-image-list"> |
| | | <el-image v-for="(url, index) in rectificationInspectionImageUrls" |
| | | :key="`${url}-${index}`" |
| | | :src="url" |
| | | :preview-src-list="rectificationInspectionImageUrls" |
| | | :initial-index="index" |
| | | fit="cover" |
| | | class="rectification-image" /> |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item label="问题等级" |
| | | :prop="isRectificationCreate ? 'problemLevel' : undefined"> |
| | | <el-select v-model="rectificationForm.problemLevel" |
| | | placeholder="请选择问题等级" |
| | | style="width: 100%" |
| | | :disabled="!isRectificationCreate"> |
| | | <el-option label="一般" value="一般" /> |
| | | <el-option label="重大" value="重大" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="计划整改时间" |
| | | :prop="isRectificationCreate ? 'planTime' : undefined"> |
| | | <el-date-picker v-model="rectificationForm.planTime" |
| | | type="datetime" |
| | | placeholder="请选择计划整改时间" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | style="width: 100%" |
| | | :disabled="!isRectificationCreate" /> |
| | | </el-form-item> |
| | | <el-form-item label="整改责任人" |
| | | :prop="isRectificationCreate ? 'rectifyUserId' : undefined"> |
| | | <el-select v-if="isRectificationCreate" |
| | | v-model="rectificationForm.rectifyUserId" |
| | | placeholder="请选择整改责任人" |
| | | filterable |
| | | clearable |
| | | style="width: 100%"> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | <el-input v-else |
| | | :model-value="rectificationForm.rectifyUserName || getUserName(rectificationForm.rectifyUserId) || '-'" |
| | | disabled /> |
| | | </el-form-item> |
| | | <el-form-item v-if="showVerifyUser" |
| | | label="验收人" |
| | | :prop="isRectificationFix ? 'verifyUserId' : undefined"> |
| | | <el-select v-if="isRectificationFix" |
| | | v-model="rectificationForm.verifyUserId" |
| | | placeholder="请选择验收人" |
| | | filterable |
| | | clearable |
| | | style="width: 100%"> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | <el-input v-else |
| | | :model-value="rectificationForm.verifyUserName || getUserName(rectificationForm.verifyUserId) || '-'" |
| | | disabled /> |
| | | </el-form-item> |
| | | <el-form-item v-if="showRectifyDesc" |
| | | label="整改说明" |
| | | :prop="isRectificationFix ? 'rectifyDesc' : undefined"> |
| | | <el-input v-model="rectificationForm.rectifyDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入整改说明" /> |
| | | placeholder="请输入整改说明" |
| | | :disabled="!isRectificationFix" /> |
| | | </el-form-item> |
| | | <el-form-item label="验收说明" v-if="rectificationDialogTitle === '验收'"> |
| | | <el-form-item v-if="showVerifyDesc" |
| | | label="验收说明" |
| | | :prop="isRectificationVerify ? 'verifyDesc' : undefined"> |
| | | <el-input v-model="rectificationForm.verifyDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入验收说明" /> |
| | | placeholder="请输入验收说明" |
| | | :disabled="!isRectificationVerify" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | <el-button v-if="!isRectificationView" |
| | | type="primary" |
| | | @click="submitRectificationForm">确定</el-button> |
| | | <el-button @click="rectificationDialogVisible = false">取消</el-button> |
| | | <el-button @click="rectificationDialogVisible = false">{{ isRectificationView ? '关闭' : '取消' }}</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 整改详情弹窗 --> |
| | | <el-dialog v-model="rectificationDetailVisible" |
| | | title="整改详情" |
| | | width="920px" |
| | | class="detail-dialog"> |
| | | <el-descriptions :column="3" border> |
| | | <el-descriptions-item label="巡检编号">{{ rectificationDetail.inspectionCode || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="设施名称">{{ rectificationDetail.facilityName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="问题等级"> |
| | | <el-tag :type="rectificationLevelType(rectificationDetail.problemLevel)"> |
| | | {{ rectificationDetail.problemLevel || '-' }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="整改责任人">{{ rectificationDetail.rectifyUserName || getUserName(rectificationDetail.rectifyUserId) || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="计划整改时间">{{ rectificationDetail.planTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="实际整改时间">{{ rectificationDetail.actualTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="状态"> |
| | | <el-tag :type="rectificationStatusType(rectificationDetail.status)">{{ rectificationDetail.status || '-' }}</el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="验收人">{{ rectificationDetail.verifyUserName || getUserName(rectificationDetail.verifyUserId) || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="验收时间">{{ rectificationDetail.verifyTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="问题描述" :span="3">{{ rectificationDetail.problemDesc || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="整改说明" :span="3">{{ rectificationDetail.rectifyDesc || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="验收说明" :span="3">{{ rectificationDetail.verifyDesc || '-' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | <div v-if="rectificationDetailImageUrls.length" class="detail-section"> |
| | | <div class="detail-section-title">巡检异常图片</div> |
| | | <div class="detail-image-list"> |
| | | <el-image v-for="(url, index) in rectificationDetailImageUrls" |
| | | :key="`${url}-${index}`" |
| | | :src="url" |
| | | :preview-src-list="rectificationDetailImageUrls" |
| | | :initial-index="index" |
| | | fit="cover" |
| | | class="detail-image" /> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" @click="rectificationDetailVisible = false">关闭</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { onMounted, ref, reactive, toRefs } from "vue"; |
| | | import { onMounted, ref, reactive, toRefs, computed, provide } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import ImageUpload from "@/components/AttachmentUpload/image/index.vue"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { |
| | | getFacilityLedgerList, |
| | | addFacilityLedger, |
| | | updateFacilityLedger, |
| | | deleteFacilityLedger, |
| | | getFacilityInspectionTaskList, |
| | | addFacilityInspectionTask, |
| | | updateFacilityInspectionTask, |
| | | deleteFacilityInspectionTask, |
| | | getFacilityInspectionList, |
| | | addFacilityInspection, |
| | | updateFacilityInspection, |
| | | deleteFacilityInspection, |
| | | getFacilityRectificationList, |
| | | addFacilityRectification, |
| | | updateFacilityRectification |
| | | } from "@/api/safeProduction/safetyFacility"; |
| | | |
| | | const userStore = useUserStore(); |
| | | const userList = ref([]); |
| | | const currentUserId = computed(() => Number(userStore.id) || null); |
| | | const ENABLED = 1; |
| | | |
| | | const weekOptions = [ |
| | | { label: "周一", value: "MON" }, |
| | | { label: "周二", value: "TUE" }, |
| | | { label: "周三", value: "WED" }, |
| | | { label: "周四", value: "THU" }, |
| | | { label: "周五", value: "FRI" }, |
| | | { label: "周六", value: "SAT" }, |
| | | { label: "周日", value: "SUN" } |
| | | ]; |
| | | |
| | | const dayOptions = Array.from({ length: 31 }, (_, index) => { |
| | | const value = String(index + 1).padStart(2, "0"); |
| | | return { label: `${index + 1}日`, value }; |
| | | }); |
| | | |
| | | const frequencyTypeMap = { |
| | | DAILY: "每日", |
| | | WEEKLY: "每周", |
| | | MONTHLY: "每月" |
| | | }; |
| | | |
| | | const weekLabelMap = weekOptions.reduce((map, item) => { |
| | | map[item.value] = item.label; |
| | | return map; |
| | | }, {}); |
| | | |
| | | const createTaskForm = () => ({ |
| | | id: null, |
| | | inspectionName: "", |
| | | facilityId: null, |
| | | facilityCode: "", |
| | | facilityName: "", |
| | | inspectionProject: "", |
| | | inspectorId: "", |
| | | frequencyType: "", |
| | | frequencyDetail: "", |
| | | week: "", |
| | | day: "", |
| | | time: "", |
| | | isEnabled: ENABLED, |
| | | remark: "" |
| | | }); |
| | | |
| | | const validateFrequencyDetail = (rule, value, callback) => { |
| | | if (!taskForm.value.frequencyType) { |
| | | callback(new Error("请选择任务频率")); |
| | | return; |
| | | } |
| | | if (taskForm.value.frequencyType === "DAILY" && !taskForm.value.frequencyDetail) { |
| | | callback(new Error("请选择执行时间")); |
| | | return; |
| | | } |
| | | if (taskForm.value.frequencyType === "WEEKLY" && (!taskForm.value.week || !taskForm.value.time)) { |
| | | callback(new Error("请选择星期和时间")); |
| | | return; |
| | | } |
| | | if (taskForm.value.frequencyType === "MONTHLY" && (!taskForm.value.day || !taskForm.value.time)) { |
| | | callback(new Error("请选择日期和时间")); |
| | | return; |
| | | } |
| | | callback(); |
| | | }; |
| | | |
| | | // 表单验证规则 |
| | | const ledgerRules = { |
| | |
| | | installLocation: [{ required: true, message: "请输入安装位置", trigger: "blur" }] |
| | | }; |
| | | |
| | | const taskRules = { |
| | | inspectionName: [{ required: true, message: "请输入巡检任务名称", trigger: "blur" }], |
| | | facilityId: [{ required: true, message: "请选择安全设施", trigger: "change" }], |
| | | inspectionProject: [{ required: true, message: "请输入巡检项目", trigger: "blur" }], |
| | | inspectorId: [{ required: true, message: "请选择巡检人", trigger: "change" }], |
| | | frequencyType: [{ required: true, message: "请选择任务频率", trigger: "change" }], |
| | | frequencyDetail: [{ required: true, validator: validateFrequencyDetail, trigger: "change" }] |
| | | }; |
| | | |
| | | const inspectionRules = { |
| | | inspectionCode: [{ required: true, message: "请输入巡检编号", trigger: "blur" }] |
| | | inspectionCode: [{ required: true, message: "请输入巡检编号", trigger: "blur" }], |
| | | inspectionType: [{ required: true, message: "请选择巡检类型", trigger: "change" }], |
| | | planTime: [{ required: true, message: "请选择计划巡检时间", trigger: "change" }], |
| | | checkResult: [{ required: true, message: "请选择检查结果", trigger: "change" }] |
| | | }; |
| | | |
| | | const rectificationRules = { |
| | | problemDesc: [{ required: true, message: "请输入问题描述", trigger: "blur" }], |
| | | problemLevel: [{ required: true, message: "请选择问题等级", trigger: "change" }], |
| | | planTime: [{ required: true, message: "请选择计划整改时间", trigger: "change" }], |
| | | rectifyUserId: [{ required: true, message: "请选择整改责任人", trigger: "change" }], |
| | | verifyUserId: [{ required: true, message: "请选择验收人", trigger: "change" }], |
| | | rectifyDesc: [{ required: true, message: "请输入整改说明", trigger: "blur" }], |
| | | verifyDesc: [{ required: true, message: "请输入验收说明", trigger: "blur" }] |
| | | }; |
| | | |
| | | // 响应式数据 |
| | |
| | | ledgerSelectedIds: [], |
| | | ledgerForm: { |
| | | id: null, facilityCode: "", facilityName: "", facilityType: "", facilitySpec: "", |
| | | installLocation: "", installTime: "", productionDate: "", validPeriod: null, |
| | | installLocation: "", installTime: "", productionDate: "", |
| | | status: "正常", remark: "" |
| | | }, |
| | | ledgerDialogVisible: false, |
| | | ledgerDialogTitle: "", |
| | | ledgerDialogType: "add", |
| | | ledgerDetailVisible: false, |
| | | ledgerDetail: {}, |
| | | // 巡检任务 |
| | | taskSearchForm: { inspectionName: "", facilityName: "", isEnabled: "" }, |
| | | taskTableLoading: false, |
| | | taskPage: { current: 1, size: 20, total: 0 }, |
| | | taskTableData: [], |
| | | taskSelectedIds: [], |
| | | taskForm: createTaskForm(), |
| | | taskDialogVisible: false, |
| | | taskDialogTitle: "新增巡检任务", |
| | | taskDetailVisible: false, |
| | | taskDetail: {}, |
| | | taskHistoryVisible: false, |
| | | taskHistoryTask: {}, |
| | | taskHistoryTableLoading: false, |
| | | taskHistoryPage: { current: 1, size: 10, total: 0 }, |
| | | taskHistoryTableData: [], |
| | | facilityOptions: [], |
| | | // 巡检记录 |
| | | inspectionSearchForm: { inspectionCode: "", status: "" }, |
| | | inspectionTableLoading: false, |
| | | inspectionPage: { current: 1, size: 20, total: 0 }, |
| | | inspectionTableData: [], |
| | | inspectionForm: { |
| | | id: null, facilityId: null, inspectionCode: "", inspectionType: "定期巡检", |
| | | planTime: "", checkResult: "", checkDesc: "" |
| | | id: null, scheduleTaskId: null, facilityId: null, inspectionCode: "", inspectionType: "定期巡检", |
| | | facilityCode: "", facilityName: "", inspectionProject: "", planTime: "", checkResult: "", checkDesc: "", storageBlobDTOs: [] |
| | | }, |
| | | inspectionDialogVisible: false, |
| | | inspectionDialogTitle: "", |
| | | inspectionDialogType: "add", |
| | | inspectionDialogType: "do", |
| | | inspectionDetailVisible: false, |
| | | inspectionDetail: {}, |
| | | // 整改跟踪 |
| | | rectificationSearchForm: { status: "" }, |
| | | rectificationTableLoading: false, |
| | |
| | | rectificationTableData: [], |
| | | rectificationForm: { |
| | | id: null, inspectionId: null, facilityId: null, problemDesc: "", |
| | | problemLevel: "", rectifyDesc: "", verifyDesc: "" |
| | | problemLevel: "", rectifyUserId: "", rectifyUserName: "", verifyUserId: "", |
| | | verifyUserName: "", facilityName: "", facilityCode: "", inspectionCode: "", |
| | | planTime: "", actualTime: "", rectifyDesc: "", verifyTime: "", verifyDesc: "", |
| | | status: "", storageBlobVOs: [] |
| | | }, |
| | | rectificationDialogVisible: false, |
| | | rectificationDialogTitle: "", |
| | | rectificationDialogType: "add" |
| | | rectificationDialogType: "add", |
| | | rectificationDetailVisible: false, |
| | | rectificationDetail: {} |
| | | }); |
| | | |
| | | const { |
| | | activeTab, |
| | | ledgerSearchForm, ledgerTableLoading, ledgerPage, ledgerTableData, ledgerSelectedIds, |
| | | ledgerForm, ledgerDialogVisible, ledgerDialogTitle, ledgerDialogType, |
| | | ledgerForm, ledgerDialogVisible, ledgerDialogTitle, ledgerDialogType, ledgerDetailVisible, ledgerDetail, |
| | | taskSearchForm, taskTableLoading, taskPage, taskTableData, taskSelectedIds, |
| | | taskForm, taskDialogVisible, taskDialogTitle, taskDetailVisible, taskDetail, |
| | | taskHistoryVisible, taskHistoryTask, taskHistoryTableLoading, taskHistoryPage, taskHistoryTableData, |
| | | facilityOptions, |
| | | inspectionSearchForm, inspectionTableLoading, inspectionPage, inspectionTableData, |
| | | inspectionForm, inspectionDialogVisible, inspectionDialogTitle, inspectionDialogType, |
| | | inspectionForm, inspectionDialogVisible, inspectionDialogTitle, inspectionDialogType, inspectionDetailVisible, inspectionDetail, |
| | | rectificationSearchForm, rectificationTableLoading, rectificationPage, rectificationTableData, |
| | | rectificationForm, rectificationDialogVisible, rectificationDialogTitle, rectificationDialogType |
| | | rectificationForm, rectificationDialogVisible, rectificationDialogTitle, rectificationDialogType, |
| | | rectificationDetailVisible, rectificationDetail |
| | | } = toRefs(data); |
| | | |
| | | // 表单引用 |
| | | const ledgerFormRef = ref(); |
| | | const taskFormRef = ref(); |
| | | const inspectionFormRef = ref(); |
| | | const rectificationFormRef = ref(); |
| | | const isInspectionView = computed(() => inspectionDialogType.value === "view"); |
| | | const isInspectionBaseReadonly = computed(() => inspectionDialogType.value !== "add"); |
| | | const isRectificationView = computed(() => rectificationDialogType.value === "view"); |
| | | const isRectificationCreate = computed(() => rectificationDialogType.value === "add"); |
| | | const isRectificationFix = computed(() => rectificationDialogType.value === "do"); |
| | | const isRectificationVerify = computed(() => rectificationDialogType.value === "verify"); |
| | | const showRectifyDesc = computed( |
| | | () => |
| | | isRectificationFix.value || |
| | | isRectificationVerify.value || |
| | | (isRectificationView.value && !!rectificationForm.value.rectifyDesc) |
| | | ); |
| | | const showVerifyDesc = computed( |
| | | () => |
| | | isRectificationVerify.value || |
| | | (isRectificationView.value && |
| | | (rectificationForm.value.status === "已验收" || !!rectificationForm.value.verifyDesc)) |
| | | ); |
| | | const showVerifyUser = computed( |
| | | () => |
| | | isRectificationFix.value || |
| | | isRectificationVerify.value || |
| | | isRectificationView.value || |
| | | !!rectificationForm.value.verifyUserId |
| | | ); |
| | | const getAttachmentUrl = item => { |
| | | if (!item) return ""; |
| | | if (typeof item === "string") return item; |
| | | return item.url || item.previewURL || item.previewUrl || item.downloadURL || ""; |
| | | }; |
| | | const rectificationInspectionImageUrls = computed(() => { |
| | | const list = rectificationForm.value.storageBlobVOs || rectificationForm.value.storageBlobDTOs || []; |
| | | return list.map(getAttachmentUrl).filter(Boolean); |
| | | }); |
| | | const inspectionDetailImageUrls = computed(() => { |
| | | const list = inspectionDetail.value.storageBlobVOs || inspectionDetail.value.storageBlobDTOs || []; |
| | | return list.map(getAttachmentUrl).filter(Boolean); |
| | | }); |
| | | const rectificationDetailImageUrls = computed(() => { |
| | | const list = rectificationDetail.value.storageBlobVOs || rectificationDetail.value.storageBlobDTOs || []; |
| | | return list.map(getAttachmentUrl).filter(Boolean); |
| | | }); |
| | | |
| | | const ledgerStatusType = value => { |
| | | const map = { 正常: "success", 异常: "danger", 报废: "info" }; |
| | | return map[value] || "info"; |
| | | }; |
| | | const inspectionResultType = value => { |
| | | const map = { 正常: "success", 异常: "danger", 未填写: "info" }; |
| | | return map[value || "未填写"] || "info"; |
| | | }; |
| | | const inspectionStatusType = value => value === "待巡检" ? "info" : "success"; |
| | | const rectificationLevelType = value => value === "重大" ? "danger" : "warning"; |
| | | const rectificationStatusType = value => { |
| | | const map = { 待整改: "danger", 整改中: "warning", 已整改: "success", 已验收: "info" }; |
| | | return map[value] || "info"; |
| | | }; |
| | | |
| | | const padTime = value => String(value).padStart(2, "0"); |
| | | const formatDateTime = (date = new Date()) => { |
| | | const target = date instanceof Date ? date : new Date(date); |
| | | return `${target.getFullYear()}-${padTime(target.getMonth() + 1)}-${padTime(target.getDate())} ${padTime(target.getHours())}:${padTime(target.getMinutes())}:${padTime(target.getSeconds())}`; |
| | | }; |
| | | const addDaysDateTime = days => { |
| | | const target = new Date(); |
| | | target.setDate(target.getDate() + days); |
| | | target.setHours(18, 0, 0, 0); |
| | | return formatDateTime(target); |
| | | }; |
| | | const getUserName = userId => { |
| | | const user = userList.value.find(item => Number(item.userId) === Number(userId)); |
| | | return user?.nickName || ""; |
| | | }; |
| | | const formatFrequencyDetail = value => { |
| | | if (!value) return "--"; |
| | | if (!value.includes(",")) return value; |
| | | const [firstPart, timePart] = value.split(","); |
| | | if (weekLabelMap[firstPart]) { |
| | | return `${weekLabelMap[firstPart]} ${timePart || ""}`.trim(); |
| | | } |
| | | if (firstPart) { |
| | | return `${Number(firstPart)}日 ${timePart || ""}`.trim(); |
| | | } |
| | | return value; |
| | | }; |
| | | const isPendingInspection = row => row?.status === "待巡检"; |
| | | const isCheckedInspection = row => row?.status === "已巡检"; |
| | | const isAbnormalInspection = row => row?.checkResult === "异常"; |
| | | const isPendingRectification = row => row?.status === "待整改" || row?.status === "整改中"; |
| | | const isRectified = row => row?.status === "已整改"; |
| | | const isNotAssignedVerifier = row => |
| | | row?.verifyUserId && Number(row.verifyUserId) !== Number(currentUserId.value); |
| | | |
| | | provide("parentMethods", { |
| | | openLedgerDetail: row => openLedgerDetail(row), |
| | | openTaskDetail: row => openTaskDetail(row), |
| | | openInspectionDetail: row => openInspectionDetail(row) |
| | | }); |
| | | |
| | | // 设施台账表格列配置 |
| | | const ledgerTableColumn = ref([ |
| | | { label: "设施编号", prop: "facilityCode", showOverflowTooltip: true, minWidth: 120 }, |
| | | { label: "设施名称", prop: "facilityName", showOverflowTooltip: true, minWidth: 150 }, |
| | | { label: "设施类型", prop: "facilityType", showOverflowTooltip: true, minWidth: 100 }, |
| | | { label: "规格型号", prop: "facilitySpec", showOverflowTooltip: true, minWidth: 120 }, |
| | | { label: "安装位置", prop: "installLocation", showOverflowTooltip: true, minWidth: 150 }, |
| | | { label: "安装时间", prop: "installTime", minWidth: 120 }, |
| | | { label: "下次检查时间", prop: "nextCheckTime", minWidth: 120 }, |
| | | { |
| | | label: "状态", prop: "status", minWidth: 80, dataType: "tag", |
| | | label: "设施编号", |
| | | prop: "facilityCode", |
| | | dataType: "link", |
| | | linkMethod: "openLedgerDetail", |
| | | showOverflowTooltip: true, |
| | | minWidth: 120, |
| | | align: "center", |
| | | }, |
| | | { label: "设施名称", prop: "facilityName", showOverflowTooltip: true, minWidth: 150 , align: "center"}, |
| | | { label: "设施类型", prop: "facilityType", showOverflowTooltip: true, minWidth: 120 , align: "center"}, |
| | | { label: "安装位置", prop: "installLocation", showOverflowTooltip: true, minWidth: 150 , align: "center"}, |
| | | { label: "安装时间", prop: "installTime", minWidth: 120 , align: "center"}, |
| | | { |
| | | label: "状态", prop: "status", minWidth: 100, dataType: "tag", align: "center", |
| | | formatType: params => { |
| | | const map = { 正常: "success", 异常: "danger", 报废: "info" }; |
| | | return map[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | dataType: "action", label: "操作", align: "center", fixed: "right", width: 200, |
| | | dataType: "action", label: "操作", align: "center", fixed: "right", width: 140, |
| | | operation: [ |
| | | { name: "编辑", type: "text", clickFun: row => openLedgerForm("edit", row) }, |
| | | { name: "发起巡检", type: "text", clickFun: row => openInspectionForm("add", row) }, |
| | | { name: "删除", type: "text", style: { color: "#F56C6C" }, clickFun: row => handleDeleteLedger(row) } |
| | | { name: "删除", type: "text", clickFun: row => handleDeleteLedger(row) } |
| | | ] |
| | | } |
| | | ]); |
| | | |
| | | // 巡检任务表格列配置 |
| | | const taskTableColumn = ref([ |
| | | { |
| | | label: "巡检任务名称", |
| | | prop: "inspectionName", |
| | | dataType: "link", |
| | | linkMethod: "openTaskDetail", |
| | | showOverflowTooltip: true, |
| | | minWidth: 170, |
| | | align: "left" |
| | | }, |
| | | { label: "设施名称", prop: "facilityName", showOverflowTooltip: true, minWidth: 155, align: "left" }, |
| | | { label: "巡检项目", prop: "inspectionProject", showOverflowTooltip: true, minWidth: 190, align: "left" }, |
| | | { label: "执行巡检人", prop: "inspectorName", minWidth: 120, align: "center" }, |
| | | { |
| | | label: "是否启用", |
| | | prop: "isEnabled", |
| | | minWidth: 90, |
| | | align: "center", |
| | | dataType: "tag", |
| | | formatData: value => value === 1 ? "是" : "否", |
| | | formatType: value => value === 1 ? "success" : "info" |
| | | }, |
| | | { |
| | | label: "频次", |
| | | prop: "frequencyType", |
| | | minWidth: 90, |
| | | align: "center", |
| | | formatData: value => frequencyTypeMap[value] || value || "--" |
| | | }, |
| | | { |
| | | label: "执行时间", |
| | | prop: "frequencyDetail", |
| | | minWidth: 120, |
| | | align: "center", |
| | | formatData: value => formatFrequencyDetail(value) |
| | | }, |
| | | { label: "下次执行时间", prop: "nextExecutionTime", minWidth: 170, showOverflowTooltip: true, align: "center" }, |
| | | { |
| | | dataType: "action", label: "操作", align: "center", fixed: "right", width: 220, |
| | | operation: [ |
| | | { name: "历史巡检", type: "text", clickFun: row => openTaskHistory(row) }, |
| | | { name: "编辑", type: "text", clickFun: row => openTaskDialog("edit", row) }, |
| | | { name: "删除", type: "text", clickFun: row => handleDeleteTask(row) } |
| | | ] |
| | | } |
| | | ]); |
| | | |
| | | const taskHistoryTableColumn = ref([ |
| | | { |
| | | label: "巡检编号", |
| | | prop: "inspectionCode", |
| | | dataType: "link", |
| | | linkMethod: "openInspectionDetail", |
| | | showOverflowTooltip: true, |
| | | minWidth: 180, |
| | | align: "center" |
| | | }, |
| | | { label: "设施名称", prop: "facilityName", showOverflowTooltip: true, minWidth: 150, align: "left" }, |
| | | { label: "巡检项目", prop: "inspectionProject", showOverflowTooltip: true, minWidth: 180, align: "left" }, |
| | | { label: "计划巡检时间", prop: "planTime", minWidth: 170, align: "center" }, |
| | | { label: "巡检人", prop: "inspectorName", minWidth: 110, align: "center" }, |
| | | { label: "实际巡检时间", prop: "actualTime", minWidth: 170, align: "center" }, |
| | | { |
| | | label: "检查结果", prop: "checkResult", minWidth: 100, align: "center", dataType: "tag", |
| | | formatData: params => params || "未填写", |
| | | formatType: params => { |
| | | const map = { 正常: "success", 异常: "danger", 未填写: "info" }; |
| | | return map[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "状态", prop: "status", minWidth: 100, align: "center", dataType: "tag", |
| | | formatType: params => params === "待巡检" ? "info" : "success" |
| | | } |
| | | ]); |
| | | |
| | | // 巡检记录表格列配置 |
| | | const inspectionTableColumn = ref([ |
| | | { label: "巡检编号", prop: "inspectionCode", showOverflowTooltip: true, minWidth: 150 }, |
| | | { label: "设施名称", prop: "facilityName", showOverflowTooltip: true, minWidth: 150 }, |
| | | { label: "设施编号", prop: "facilityCode", showOverflowTooltip: true, minWidth: 120 }, |
| | | { label: "巡检类型", prop: "inspectionType", minWidth: 100 }, |
| | | { label: "计划巡检时间", prop: "planTime", minWidth: 180 }, |
| | | { label: "巡检人", prop: "inspectorName", minWidth: 100 }, |
| | | { label: "实际巡检时间", prop: "actualTime", minWidth: 180 }, |
| | | { |
| | | label: "巡检编号", |
| | | dataType: "link", |
| | | linkMethod: "openInspectionDetail", |
| | | width: 200, |
| | | align: "center", |
| | | prop: "inspectionCode", |
| | | showOverflowTooltip: true, |
| | | minWidth: 150 |
| | | }, |
| | | { |
| | | label: "设施名称", |
| | | prop: "facilityName", |
| | | showOverflowTooltip: true, |
| | | minWidth: 150 |
| | | }, |
| | | { |
| | | label: "巡检项目", |
| | | prop: "inspectionProject", |
| | | showOverflowTooltip: true, |
| | | minWidth: 180 |
| | | }, |
| | | { |
| | | label: "计划巡检时间", |
| | | prop: "planTime", |
| | | minWidth: 180 |
| | | }, |
| | | { |
| | | label: "巡检人", |
| | | prop: "inspectorName", |
| | | minWidth: 100 |
| | | }, |
| | | { |
| | | label: "实际巡检时间", |
| | | prop: "actualTime", |
| | | minWidth: 180 |
| | | }, |
| | | { |
| | | label: "检查结果", prop: "checkResult", minWidth: 100, dataType: "tag", |
| | | formatType: params => params === "正常" ? "success" : "danger" |
| | | formatData: params => params || "未填写", |
| | | formatType: params => { |
| | | const map = { 正常: "success", 异常: "danger", 未填写: "info" }; |
| | | return map[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "状态", prop: "status", minWidth: 100, dataType: "tag", |
| | |
| | | { |
| | | name: "巡检", type: "text", |
| | | clickFun: row => openInspectionForm("do", row), |
| | | show: row => row.status === "待巡检" |
| | | show: isPendingInspection |
| | | }, |
| | | { |
| | | name: "查看", type: "text", |
| | | clickFun: row => openInspectionForm("view", row), |
| | | show: row => row.status !== "待巡检" |
| | | clickFun: row => openInspectionDetail(row), |
| | | show: isCheckedInspection |
| | | }, |
| | | { |
| | | name: "整改", type: "text", |
| | | clickFun: row => openRectificationForm("add", row), |
| | | show: row => row.checkResult === "异常" |
| | | clickFun: row => openRectificationFromInspection(row), |
| | | show: row => isCheckedInspection(row) && isAbnormalInspection(row) |
| | | }, |
| | | { name: "删除", type: "text", style: { color: "#F56C6C" }, clickFun: row => handleDeleteInspection(row) } |
| | | { name: "删除", type: "text", clickFun: row => handleDeleteInspection(row), show: isPendingInspection } |
| | | ] |
| | | } |
| | | ]); |
| | | |
| | | // 整改跟踪表格列配置 |
| | | const rectificationTableColumn = ref([ |
| | | { label: "巡检编号", prop: "inspectionCode", showOverflowTooltip: true, minWidth: 150 }, |
| | | { label: "设施名称", prop: "facilityName", showOverflowTooltip: true, minWidth: 150 }, |
| | | { label: "问题描述", prop: "problemDesc", showOverflowTooltip: true, minWidth: 200 }, |
| | | { |
| | |
| | | return map[params] || "info"; |
| | | } |
| | | }, |
| | | { label: "验收人", prop: "verifyUserName", minWidth: 120 }, |
| | | { |
| | | dataType: "action", label: "操作", align: "center", fixed: "right", width: 200, |
| | | dataType: "action", label: "操作", align: "center", fixed: "right", width: 180, |
| | | operation: [ |
| | | { |
| | | name: "整改", type: "text", |
| | | clickFun: row => openRectificationForm("do", row), |
| | | show: row => row.status === "待整改" || row.status === "整改中" |
| | | show: isPendingRectification |
| | | }, |
| | | { |
| | | name: "验收", type: "text", |
| | | clickFun: row => openRectificationForm("verify", row), |
| | | show: row => row.status === "已整改" |
| | | show: isRectified, |
| | | disabled: isNotAssignedVerifier |
| | | }, |
| | | { name: "查看", type: "text", clickFun: row => openRectificationForm("view", row) } |
| | | { name: "查看", type: "text", clickFun: row => openRectificationDetail(row) } |
| | | ] |
| | | } |
| | | ]); |
| | |
| | | // 生命周期 |
| | | onMounted(() => { |
| | | getLedgerList(); |
| | | getTaskList(); |
| | | getInspectionList(); |
| | | getRectificationList(); |
| | | getFacilityOptionList(); |
| | | getUserList(); |
| | | }); |
| | | |
| | | // 标签页切换 |
| | | const handleTabClick = () => { |
| | | if (activeTab.value === "ledger") getLedgerList(); |
| | | else if (activeTab.value === "task") getTaskList(); |
| | | else if (activeTab.value === "inspection") getInspectionList(); |
| | | else if (activeTab.value === "rectification") getRectificationList(); |
| | | }; |
| | | |
| | | const getUserList = () => { |
| | | userListNoPage().then(res => { |
| | | userList.value = res.data || []; |
| | | }); |
| | | }; |
| | | |
| | | const getFacilityOptionList = () => { |
| | | getFacilityLedgerList({ current: 1, size: 1000 }).then(res => { |
| | | facilityOptions.value = (res.data?.records || []).filter(item => item.status !== "报废"); |
| | | }); |
| | | }; |
| | | |
| | | // ============ 设施台账方法 ============ |
| | |
| | | getLedgerList(); |
| | | }; |
| | | |
| | | const resetLedgerQuery = () => { |
| | | Object.assign(ledgerSearchForm.value, { |
| | | facilityCode: "", |
| | | facilityName: "", |
| | | facilityType: "", |
| | | status: "" |
| | | }); |
| | | handleLedgerQuery(); |
| | | }; |
| | | |
| | | const getLedgerList = () => { |
| | | ledgerTableLoading.value = true; |
| | | getFacilityLedgerList({ ...ledgerPage.value, ...ledgerSearchForm.value }) |
| | | .then(res => { |
| | | ledgerTableLoading.value = false; |
| | | ledgerTableData.value = res.data.records; |
| | | ledgerPage.value.total = res.data.total; |
| | | ledgerTableData.value = res.data?.records || []; |
| | | ledgerPage.value.total = res.data?.total || 0; |
| | | }) |
| | | .catch(() => { ledgerTableLoading.value = false; }); |
| | | }; |
| | |
| | | ledgerSelectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | const openLedgerDetail = row => { |
| | | ledgerDetail.value = { ...row }; |
| | | ledgerDetailVisible.value = true; |
| | | }; |
| | | |
| | | const openLedgerForm = (type, row = null) => { |
| | | ledgerDialogType.value = type; |
| | | if (type === "add") { |
| | | ledgerDialogTitle.value = "新增设施"; |
| | | Object.assign(ledgerForm.value, { |
| | | id: null, facilityCode: "", facilityName: "", facilityType: "", facilitySpec: "", |
| | | installLocation: "", installTime: "", productionDate: "", validPeriod: null, |
| | | installLocation: "", installTime: "", productionDate: "", |
| | | status: "正常", remark: "" |
| | | }); |
| | | } else { |
| | |
| | | ElMessage.success(ledgerDialogType.value === "add" ? "添加成功" : "更新成功"); |
| | | ledgerDialogVisible.value = false; |
| | | getLedgerList(); |
| | | getFacilityOptionList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "操作失败"); |
| | | } |
| | |
| | | if (res.code === 200) { |
| | | ElMessage.success("删除成功"); |
| | | getLedgerList(); |
| | | getFacilityOptionList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "删除失败"); |
| | | } |
| | | }).catch(() => {}); |
| | | }; |
| | | |
| | | const handleBatchDeleteLedger = () => { |
| | | if (ledgerSelectedIds.value.length === 0) { |
| | | ElMessage.warning("请选择要删除的设施"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("确认删除选中的设施吗?已产生巡检记录的设施不会被后端允许删除。", "批量删除", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }).then(async () => { |
| | | const res = await deleteFacilityLedger(ledgerSelectedIds.value); |
| | | if (res.code === 200) { |
| | | ElMessage.success("删除成功"); |
| | | ledgerSelectedIds.value = []; |
| | | getLedgerList(); |
| | | getFacilityOptionList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "删除失败"); |
| | | } |
| | | }).catch(() => {}); |
| | | }; |
| | | |
| | | // ============ 巡检任务方法 ============ |
| | | |
| | | const handleTaskQuery = () => { |
| | | taskPage.value.current = 1; |
| | | getTaskList(); |
| | | }; |
| | | |
| | | const resetTaskQuery = () => { |
| | | Object.assign(taskSearchForm.value, { |
| | | inspectionName: "", |
| | | facilityName: "", |
| | | isEnabled: "" |
| | | }); |
| | | handleTaskQuery(); |
| | | }; |
| | | |
| | | const getTaskList = () => { |
| | | taskTableLoading.value = true; |
| | | getFacilityInspectionTaskList({ ...taskPage.value, ...taskSearchForm.value }) |
| | | .then(res => { |
| | | taskTableLoading.value = false; |
| | | taskTableData.value = res.data?.records || []; |
| | | taskPage.value.total = res.data?.total || 0; |
| | | }) |
| | | .catch(() => { taskTableLoading.value = false; }); |
| | | }; |
| | | |
| | | const taskPagination = obj => { |
| | | taskPage.value.current = obj.page; |
| | | taskPage.value.size = obj.limit; |
| | | getTaskList(); |
| | | }; |
| | | |
| | | const handleTaskSelectionChange = selection => { |
| | | taskSelectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | const openTaskDetail = row => { |
| | | taskDetail.value = { ...row }; |
| | | taskDetailVisible.value = true; |
| | | }; |
| | | |
| | | const openTaskDialog = (type, row = null) => { |
| | | resetTaskForm(); |
| | | taskDialogTitle.value = type === "add" ? "新增巡检任务" : "编辑巡检任务"; |
| | | if (type === "edit" && row) { |
| | | Object.assign(taskForm.value, { |
| | | id: row.id, |
| | | inspectionName: row.inspectionName, |
| | | facilityId: row.facilityId, |
| | | facilityCode: row.facilityCode, |
| | | facilityName: row.facilityName, |
| | | inspectionProject: row.inspectionProject, |
| | | inspectorId: row.inspectorId, |
| | | frequencyType: row.frequencyType, |
| | | frequencyDetail: row.frequencyDetail, |
| | | isEnabled: row.isEnabled ?? ENABLED, |
| | | remark: row.remark |
| | | }); |
| | | parseFrequencyDetail(row.frequencyType, row.frequencyDetail); |
| | | } |
| | | taskDialogVisible.value = true; |
| | | }; |
| | | |
| | | const resetTaskForm = () => { |
| | | Object.assign(taskForm.value, createTaskForm()); |
| | | taskFormRef.value?.clearValidate?.(); |
| | | }; |
| | | |
| | | const handleTaskFacilityChange = facilityId => { |
| | | const facility = facilityOptions.value.find(item => Number(item.id) === Number(facilityId)); |
| | | taskForm.value.facilityCode = facility?.facilityCode || ""; |
| | | taskForm.value.facilityName = facility?.facilityName || ""; |
| | | }; |
| | | |
| | | const handleFrequencyTypeChange = () => { |
| | | Object.assign(taskForm.value, { frequencyDetail: "", week: "", day: "", time: "" }); |
| | | taskFormRef.value?.clearValidate?.("frequencyDetail"); |
| | | }; |
| | | |
| | | const parseFrequencyDetail = (frequencyType, frequencyDetail) => { |
| | | if (!frequencyDetail) return; |
| | | if (frequencyType === "DAILY") { |
| | | taskForm.value.frequencyDetail = frequencyDetail; |
| | | return; |
| | | } |
| | | const [firstPart, timePart] = frequencyDetail.split(","); |
| | | taskForm.value.frequencyDetail = ""; |
| | | taskForm.value.time = timePart || ""; |
| | | if (frequencyType === "WEEKLY") { |
| | | taskForm.value.week = firstPart || ""; |
| | | } |
| | | if (frequencyType === "MONTHLY") { |
| | | taskForm.value.day = String(firstPart || "").padStart(2, "0"); |
| | | } |
| | | }; |
| | | |
| | | const buildFrequencyDetail = () => { |
| | | if (taskForm.value.frequencyType === "DAILY") { |
| | | return taskForm.value.frequencyDetail; |
| | | } |
| | | if (taskForm.value.frequencyType === "WEEKLY") { |
| | | return `${taskForm.value.week},${taskForm.value.time}`; |
| | | } |
| | | if (taskForm.value.frequencyType === "MONTHLY") { |
| | | return `${taskForm.value.day},${taskForm.value.time}`; |
| | | } |
| | | return ""; |
| | | }; |
| | | |
| | | const submitTaskForm = async () => { |
| | | try { |
| | | await taskFormRef.value.validate(); |
| | | const payload = { |
| | | id: taskForm.value.id, |
| | | inspectionName: taskForm.value.inspectionName, |
| | | facilityId: taskForm.value.facilityId, |
| | | facilityCode: taskForm.value.facilityCode, |
| | | facilityName: taskForm.value.facilityName, |
| | | inspectionProject: taskForm.value.inspectionProject, |
| | | inspectorId: taskForm.value.inspectorId, |
| | | frequencyType: taskForm.value.frequencyType, |
| | | frequencyDetail: buildFrequencyDetail(), |
| | | isEnabled: taskForm.value.isEnabled, |
| | | remark: taskForm.value.remark |
| | | }; |
| | | const api = payload.id ? updateFacilityInspectionTask : addFacilityInspectionTask; |
| | | const res = await api(payload); |
| | | if (res.code === 200) { |
| | | ElMessage.success(payload.id ? "修改成功" : "新增成功"); |
| | | taskDialogVisible.value = false; |
| | | activeTab.value = "task"; |
| | | getTaskList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "操作失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("任务表单校验失败:", error); |
| | | } |
| | | }; |
| | | |
| | | const handleDeleteTask = row => { |
| | | ElMessageBox.confirm("确认删除该定时巡检任务吗?", "删除", { |
| | | confirmButtonText: "确认", cancelButtonText: "取消", type: "warning" |
| | | }).then(async () => { |
| | | const res = await deleteFacilityInspectionTask([row.id]); |
| | | if (res.code === 200) { |
| | | ElMessage.success("删除成功"); |
| | | getTaskList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "删除失败"); |
| | | } |
| | | }).catch(() => {}); |
| | | }; |
| | | |
| | | const handleBatchDeleteTask = () => { |
| | | if (taskSelectedIds.value.length === 0) { |
| | | ElMessage.warning("请选择要删除的巡检任务"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("确认删除选中的定时巡检任务吗?", "批量删除", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }).then(async () => { |
| | | const res = await deleteFacilityInspectionTask(taskSelectedIds.value); |
| | | if (res.code === 200) { |
| | | ElMessage.success("删除成功"); |
| | | taskSelectedIds.value = []; |
| | | getTaskList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "删除失败"); |
| | | } |
| | | }).catch(() => {}); |
| | | }; |
| | | |
| | | const openTaskHistory = row => { |
| | | taskHistoryTask.value = { ...row }; |
| | | taskHistoryPage.value.current = 1; |
| | | taskHistoryVisible.value = true; |
| | | getTaskHistoryList(); |
| | | }; |
| | | |
| | | const getTaskHistoryList = () => { |
| | | if (!taskHistoryTask.value?.id) { |
| | | taskHistoryTableData.value = []; |
| | | taskHistoryPage.value.total = 0; |
| | | return; |
| | | } |
| | | taskHistoryTableLoading.value = true; |
| | | getFacilityInspectionList({ |
| | | current: taskHistoryPage.value.current, |
| | | size: taskHistoryPage.value.size, |
| | | scheduleTaskId: taskHistoryTask.value.id |
| | | }) |
| | | .then(res => { |
| | | taskHistoryTableLoading.value = false; |
| | | taskHistoryTableData.value = res.data?.records || []; |
| | | taskHistoryPage.value.total = res.data?.total || 0; |
| | | }) |
| | | .catch(() => { taskHistoryTableLoading.value = false; }); |
| | | }; |
| | | |
| | | const taskHistoryPagination = obj => { |
| | | taskHistoryPage.value.current = obj.page; |
| | | taskHistoryPage.value.size = obj.limit; |
| | | getTaskHistoryList(); |
| | | }; |
| | | |
| | | // ============ 巡检记录方法 ============ |
| | |
| | | getInspectionList(); |
| | | }; |
| | | |
| | | const resetInspectionQuery = () => { |
| | | Object.assign(inspectionSearchForm.value, { |
| | | inspectionCode: "", |
| | | status: "" |
| | | }); |
| | | handleInspectionQuery(); |
| | | }; |
| | | |
| | | const getInspectionList = () => { |
| | | inspectionTableLoading.value = true; |
| | | getFacilityInspectionList({ ...inspectionPage.value, ...inspectionSearchForm.value }) |
| | | .then(res => { |
| | | inspectionTableLoading.value = false; |
| | | inspectionTableData.value = res.data.records; |
| | | inspectionPage.value.total = res.data.total; |
| | | inspectionTableData.value = res.data?.records || []; |
| | | inspectionPage.value.total = res.data?.total || 0; |
| | | }) |
| | | .catch(() => { inspectionTableLoading.value = false; }); |
| | | }; |
| | |
| | | getInspectionList(); |
| | | }; |
| | | |
| | | const openInspectionDetail = row => { |
| | | inspectionDetail.value = { |
| | | ...row, |
| | | storageBlobDTOs: row.storageBlobVOs || row.storageBlobDTOs || [] |
| | | }; |
| | | inspectionDetailVisible.value = true; |
| | | }; |
| | | |
| | | const openInspectionForm = (type, row = null) => { |
| | | if (type === "view") { |
| | | openInspectionDetail(row); |
| | | return; |
| | | } |
| | | inspectionDialogType.value = type; |
| | | if (type === "add") { |
| | | inspectionDialogTitle.value = "发起巡检"; |
| | | Object.assign(inspectionForm.value, { |
| | | id: null, facilityId: row.id, inspectionCode: "", inspectionType: "定期巡检", |
| | | planTime: "", checkResult: "", checkDesc: "" |
| | | }); |
| | | } else if (type === "do") { |
| | | if (type === "do") { |
| | | inspectionDialogTitle.value = "巡检"; |
| | | Object.assign(inspectionForm.value, { |
| | | id: row.id, facilityId: row.facilityId, inspectionCode: row.inspectionCode, |
| | | inspectionType: row.inspectionType, planTime: row.planTime, checkResult: "", checkDesc: "" |
| | | id: row.id, |
| | | scheduleTaskId: row.scheduleTaskId, |
| | | facilityId: row.facilityId, |
| | | facilityCode: row.facilityCode, |
| | | facilityName: row.facilityName, |
| | | inspectionCode: row.inspectionCode, |
| | | inspectionType: row.inspectionType, |
| | | inspectionProject: row.inspectionProject, |
| | | planTime: row.planTime, |
| | | checkResult: "", |
| | | checkDesc: "", |
| | | storageBlobDTOs: [] |
| | | }); |
| | | } else { |
| | | inspectionDialogTitle.value = "查看巡检"; |
| | | Object.assign(inspectionForm.value, { ...row }); |
| | | } |
| | | inspectionDialogVisible.value = true; |
| | | }; |
| | |
| | | const submitInspectionForm = async () => { |
| | | try { |
| | | await inspectionFormRef.value.validate(); |
| | | if (inspectionDialogTitle.value === "巡检") { |
| | | if (inspectionDialogType.value === "do") { |
| | | if (!inspectionForm.value.checkResult) { |
| | | ElMessage.warning("请选择检查结果"); |
| | | return; |
| | | } |
| | | if (inspectionForm.value.checkResult === "异常" && !inspectionForm.value.checkDesc) { |
| | | ElMessage.warning("检查结果异常时请填写检查说明"); |
| | | return; |
| | | } |
| | | if (inspectionForm.value.checkResult === "异常" && !hasAttachments(inspectionForm.value.storageBlobDTOs)) { |
| | | ElMessage.warning("检查结果异常时请上传现场照片"); |
| | | return; |
| | | } |
| | | inspectionForm.value.status = "已巡检"; |
| | | inspectionForm.value.actualTime = new Date().toISOString().replace("T", " ").substring(0, 19); |
| | | inspectionForm.value.actualTime = formatDateTime(); |
| | | } |
| | | const api = inspectionForm.value.id ? updateFacilityInspection : addFacilityInspection; |
| | | const res = await api({ ...inspectionForm.value }); |
| | | const res = await updateFacilityInspection({ ...inspectionForm.value }); |
| | | if (res.code === 200) { |
| | | ElMessage.success("操作成功"); |
| | | inspectionDialogVisible.value = false; |
| | | getInspectionList(); |
| | | if (inspectionDialogType.value === "do" && inspectionForm.value.checkResult === "异常") { |
| | | ElMessageBox.confirm("本次巡检结果为异常,是否立即创建整改跟踪?", "创建整改", { |
| | | confirmButtonText: "创建整改", |
| | | cancelButtonText: "稍后处理", |
| | | type: "warning" |
| | | }).then(() => { |
| | | openRectificationFromInspection({ ...inspectionForm.value }); |
| | | }).catch(() => {}); |
| | | } |
| | | } else { |
| | | ElMessage.error(res.msg || "操作失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("表单验证失败:", error); |
| | | } |
| | | }; |
| | | |
| | | const hasAttachments = attachments => Array.isArray(attachments) && attachments.length > 0; |
| | | |
| | | const handleDeleteInspection = row => { |
| | | ElMessageBox.confirm("确认删除该巡检记录吗?", "删除", { |
| | |
| | | if (res.code === 200) { |
| | | ElMessage.success("删除成功"); |
| | | getInspectionList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "删除失败"); |
| | | } |
| | | }).catch(() => {}); |
| | | }; |
| | |
| | | getRectificationList(); |
| | | }; |
| | | |
| | | const resetRectificationQuery = () => { |
| | | Object.assign(rectificationSearchForm.value, { |
| | | status: "" |
| | | }); |
| | | handleRectificationQuery(); |
| | | }; |
| | | |
| | | const getRectificationList = () => { |
| | | rectificationTableLoading.value = true; |
| | | getFacilityRectificationList({ ...rectificationPage.value, ...rectificationSearchForm.value }) |
| | | .then(res => { |
| | | rectificationTableLoading.value = false; |
| | | rectificationTableData.value = res.data.records; |
| | | rectificationPage.value.total = res.data.total; |
| | | rectificationTableData.value = res.data?.records || []; |
| | | rectificationPage.value.total = res.data?.total || 0; |
| | | }) |
| | | .catch(() => { rectificationTableLoading.value = false; }); |
| | | }; |
| | |
| | | getRectificationList(); |
| | | }; |
| | | |
| | | const getExistingRectification = async inspectionId => { |
| | | if (!inspectionId) return null; |
| | | const res = await getFacilityRectificationList({ current: 1, size: 1, inspectionId }); |
| | | return res.data?.records?.[0] || null; |
| | | }; |
| | | |
| | | const getRectificationDialogType = row => { |
| | | if (isPendingRectification(row)) return "do"; |
| | | if (isRectified(row)) return "verify"; |
| | | return "view"; |
| | | }; |
| | | |
| | | const openRectificationDetail = row => { |
| | | rectificationDetail.value = { |
| | | ...row, |
| | | storageBlobVOs: row.storageBlobVOs || row.storageBlobDTOs || [] |
| | | }; |
| | | rectificationDetailVisible.value = true; |
| | | }; |
| | | |
| | | const openRectificationFromInspection = async row => { |
| | | const existing = await getExistingRectification(row.id); |
| | | activeTab.value = "rectification"; |
| | | if (existing) { |
| | | ElMessage.info("该巡检已存在整改记录,已为你打开对应处理窗口"); |
| | | existing.inspectionCode = existing.inspectionCode || row.inspectionCode; |
| | | existing.facilityCode = existing.facilityCode || row.facilityCode; |
| | | existing.facilityName = existing.facilityName || row.facilityName; |
| | | openRectificationForm(getRectificationDialogType(existing), existing); |
| | | return; |
| | | } |
| | | openRectificationForm("add", row); |
| | | }; |
| | | |
| | | const openRectificationForm = (type, row = null) => { |
| | | if (type === "view") { |
| | | openRectificationDetail(row); |
| | | return; |
| | | } |
| | | rectificationDialogType.value = type; |
| | | if (type === "add") { |
| | | rectificationDialogTitle.value = "新增整改"; |
| | | Object.assign(rectificationForm.value, { |
| | | id: null, inspectionId: row.id, facilityId: row.facilityId, |
| | | problemDesc: "", problemLevel: "", rectifyDesc: "", verifyDesc: "" |
| | | id: null, |
| | | inspectionId: row.id, |
| | | facilityId: row.facilityId, |
| | | facilityName: row.facilityName || "", |
| | | facilityCode: row.facilityCode || "", |
| | | inspectionCode: row.inspectionCode || "", |
| | | problemDesc: row.checkDesc || "", |
| | | problemLevel: "一般", |
| | | rectifyUserId: currentUserId.value || "", |
| | | rectifyUserName: getUserName(currentUserId.value), |
| | | verifyUserId: "", |
| | | verifyUserName: "", |
| | | planTime: addDaysDateTime(1), |
| | | actualTime: "", |
| | | rectifyDesc: "", |
| | | verifyTime: "", |
| | | verifyDesc: "", |
| | | status: "待整改", |
| | | storageBlobVOs: row.storageBlobVOs || row.storageBlobDTOs || [] |
| | | }); |
| | | } else if (type === "do") { |
| | | rectificationDialogTitle.value = "整改"; |
| | | Object.assign(rectificationForm.value, { |
| | | id: row.id, inspectionId: row.inspectionId, facilityId: row.facilityId, |
| | | problemDesc: row.problemDesc, problemLevel: row.problemLevel, rectifyDesc: "", verifyDesc: "" |
| | | ...row, |
| | | storageBlobVOs: row.storageBlobVOs || row.storageBlobDTOs || [], |
| | | rectifyDesc: row.rectifyDesc || "", |
| | | verifyDesc: row.verifyDesc || "" |
| | | }); |
| | | } else if (type === "verify") { |
| | | rectificationDialogTitle.value = "验收"; |
| | | Object.assign(rectificationForm.value, { |
| | | id: row.id, inspectionId: row.inspectionId, facilityId: row.facilityId, |
| | | problemDesc: row.problemDesc, problemLevel: row.problemLevel, |
| | | rectifyDesc: row.rectifyDesc, verifyDesc: "" |
| | | ...row, |
| | | storageBlobVOs: row.storageBlobVOs || row.storageBlobDTOs || [], |
| | | verifyDesc: row.verifyDesc || "" |
| | | }); |
| | | } else { |
| | | rectificationDialogTitle.value = "查看整改"; |
| | | Object.assign(rectificationForm.value, { ...row }); |
| | | Object.assign(rectificationForm.value, { |
| | | ...row, |
| | | storageBlobVOs: row.storageBlobVOs || row.storageBlobDTOs || [] |
| | | }); |
| | | } |
| | | rectificationDialogVisible.value = true; |
| | | }; |
| | | |
| | | const buildRectificationPayload = () => { |
| | | const { |
| | | id, |
| | | inspectionId, |
| | | facilityId, |
| | | problemDesc, |
| | | problemLevel, |
| | | problemImage, |
| | | rectifyUserId, |
| | | planTime, |
| | | actualTime, |
| | | rectifyDesc, |
| | | rectifyImage, |
| | | status, |
| | | verifyUserId, |
| | | verifyTime, |
| | | verifyDesc |
| | | } = rectificationForm.value; |
| | | return { |
| | | id, |
| | | inspectionId, |
| | | facilityId, |
| | | problemDesc, |
| | | problemLevel, |
| | | problemImage, |
| | | rectifyUserId, |
| | | planTime, |
| | | actualTime, |
| | | rectifyDesc, |
| | | rectifyImage, |
| | | status, |
| | | verifyUserId, |
| | | verifyTime, |
| | | verifyDesc |
| | | }; |
| | | }; |
| | | |
| | | const submitRectificationForm = async () => { |
| | |
| | | rectificationDialogVisible.value = false; |
| | | return; |
| | | } |
| | | if (rectificationDialogTitle.value === "整改") { |
| | | try { |
| | | await rectificationFormRef.value.validate(); |
| | | } catch (error) { |
| | | console.error("表单验证失败:", error); |
| | | return; |
| | | } |
| | | if (rectificationDialogType.value === "do") { |
| | | rectificationForm.value.status = "已整改"; |
| | | rectificationForm.value.actualTime = new Date().toISOString().replace("T", " ").substring(0, 19); |
| | | } else if (rectificationDialogTitle.value === "验收") { |
| | | rectificationForm.value.actualTime = formatDateTime(); |
| | | } else if (rectificationDialogType.value === "verify") { |
| | | rectificationForm.value.status = "已验收"; |
| | | rectificationForm.value.verifyTime = new Date().toISOString().replace("T", " ").substring(0, 19); |
| | | rectificationForm.value.verifyTime = formatDateTime(); |
| | | } |
| | | const api = rectificationForm.value.id ? updateFacilityRectification : addFacilityRectification; |
| | | const res = await api({ ...rectificationForm.value }); |
| | | const res = await api(buildRectificationPayload()); |
| | | if (res.code === 200) { |
| | | ElMessage.success("操作成功"); |
| | | rectificationDialogVisible.value = false; |
| | | getRectificationList(); |
| | | getInspectionList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "操作失败"); |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .safety-facility-page { |
| | | padding-top: 4px; |
| | | } |
| | | |
| | | .facility-tabs { |
| | | width: 100%; |
| | | } |
| | | |
| | | .facility-tabs :deep(.el-tabs__header) { |
| | | margin-bottom: 18px; |
| | | } |
| | | |
| | | .facility-tabs :deep(.el-tabs__nav-wrap::after) { |
| | | height: 1px; |
| | | background-color: #d8e2ef; |
| | | } |
| | | |
| | | .facility-toolbar { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | gap: 14px 18px; |
| | | min-height: 44px; |
| | | margin-bottom: 18px; |
| | | } |
| | | |
| | | .toolbar-filters, |
| | | .toolbar-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 10px 12px; |
| | | } |
| | | |
| | | .toolbar-actions { |
| | | margin-left: auto; |
| | | } |
| | | |
| | | .table_list { |
| | | padding-top: 6px; |
| | | } |
| | | |
| | | .history-summary { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .table_list :deep(.link) { |
| | | color: var(--el-color-primary); |
| | | cursor: pointer; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .table_list :deep(.link:hover) { |
| | | text-decoration: underline; |
| | | } |
| | | |
| | | .search_title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #606266; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .mb20 { |
| | |
| | | .ml10 { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .toolbar-filters .ml10 { |
| | | margin-left: 0; |
| | | } |
| | | |
| | | .facility-form-dialog :deep(.el-dialog__body) { |
| | | padding: 24px 32px 10px; |
| | | } |
| | | |
| | | .facility-form-dialog :deep(.el-dialog__footer) { |
| | | padding: 8px 32px 26px; |
| | | } |
| | | |
| | | .dialog-summary { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, minmax(0, 1fr)); |
| | | gap: 12px; |
| | | margin-bottom: 20px; |
| | | padding: 14px 18px; |
| | | border: 1px solid #e4eaf3; |
| | | border-radius: 6px; |
| | | background: #f7faff; |
| | | } |
| | | |
| | | .summary-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .summary-item span { |
| | | flex: 0 0 auto; |
| | | color: #7a8599; |
| | | } |
| | | |
| | | .summary-item strong { |
| | | min-width: 0; |
| | | overflow: hidden; |
| | | color: #25324b; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .inspection-form-grid { |
| | | display: grid; |
| | | grid-template-columns: minmax(0, 1fr) minmax(220px, 0.8fr); |
| | | column-gap: 20px; |
| | | } |
| | | |
| | | .inspection-form-grid .form-grid-full { |
| | | grid-column: 1 / -1; |
| | | } |
| | | |
| | | .inspection-form :deep(.el-form-item) { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .inspection-form :deep(.el-form-item__label) { |
| | | margin-bottom: 8px; |
| | | padding: 0; |
| | | font-weight: 600; |
| | | color: #25324b; |
| | | line-height: 1.2; |
| | | } |
| | | |
| | | .rectification-image-list { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .rectification-image { |
| | | width: 96px; |
| | | height: 96px; |
| | | border: 1px solid #dbe4f0; |
| | | border-radius: 6px; |
| | | background: #f8fafc; |
| | | } |
| | | |
| | | .detail-dialog :deep(.el-dialog__body) { |
| | | padding: 24px 32px 8px; |
| | | } |
| | | |
| | | .detail-dialog :deep(.el-descriptions__label) { |
| | | width: 130px; |
| | | color: #4d5b73; |
| | | font-weight: 600; |
| | | background: #f4f7fb; |
| | | } |
| | | |
| | | .detail-dialog :deep(.el-descriptions__content) { |
| | | color: #25324b; |
| | | word-break: break-word; |
| | | } |
| | | |
| | | .detail-section { |
| | | margin-top: 18px; |
| | | } |
| | | |
| | | .detail-section-title { |
| | | margin-bottom: 10px; |
| | | color: #25324b; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .detail-image-list { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .detail-image { |
| | | width: 96px; |
| | | height: 96px; |
| | | border: 1px solid #dbe4f0; |
| | | border-radius: 6px; |
| | | background: #f8fafc; |
| | | } |
| | | |
| | | .frequency-row { |
| | | display: flex; |
| | | width: 100%; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .frequency-time-picker { |
| | | min-width: 0; |
| | | flex: 1; |
| | | } |
| | | |
| | | .frequency-day-select { |
| | | flex: 0 0 132px; |
| | | width: 132px; |
| | | } |
| | | |
| | | @media (max-width: 900px) { |
| | | .inspection-form-grid, |
| | | .dialog-summary { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | } |
| | | </style> |