<template>
|
<div class="app-container line-inspection-page">
|
<div class="module-tabs">
|
<button
|
v-for="tab in moduleTabs"
|
:key="tab.value"
|
class="module-tab"
|
:class="{ active: activeTab === tab.value }"
|
type="button"
|
@click="handleModuleTabChange(tab.value)"
|
>
|
{{ tab.label }}
|
</button>
|
</div>
|
|
<div class="search_form line-search-panel mb20">
|
<div class="search-left">
|
<template v-if="activeTab === 'task'">
|
<div class="filter-item">
|
<span class="search_title">巡检任务名称:</span>
|
<el-input
|
v-model="taskSearchForm.inspectionName"
|
class="filter-control is-wide"
|
placeholder="请输入巡检任务名称"
|
clearable
|
:prefix-icon="Search"
|
@change="handleQuery"
|
/>
|
</div>
|
<div class="filter-item">
|
<span class="search_title">线路名称:</span>
|
<el-input
|
v-model="taskSearchForm.lineName"
|
class="filter-control"
|
placeholder="请输入线路名称"
|
clearable
|
:prefix-icon="Search"
|
@change="handleQuery"
|
/>
|
</div>
|
<div class="filter-item">
|
<span class="search_title">是否启用:</span>
|
<el-select
|
v-model="taskSearchForm.isEnabled"
|
class="filter-control is-short"
|
clearable
|
placeholder="请选择"
|
@change="handleQuery"
|
>
|
<el-option label="是" :value="1" />
|
<el-option label="否" :value="0" />
|
</el-select>
|
</div>
|
</template>
|
<template v-else-if="activeTab === 'record'">
|
<div class="filter-item">
|
<span class="search_title">巡检编号:</span>
|
<el-input
|
v-model="recordSearchForm.inspectionCode"
|
class="filter-control"
|
placeholder="请输入巡检编号"
|
clearable
|
:prefix-icon="Search"
|
@change="handleQuery"
|
/>
|
</div>
|
<div class="filter-item">
|
<span class="search_title">巡检名称:</span>
|
<el-input
|
v-model="recordSearchForm.inspectionName"
|
class="filter-control"
|
placeholder="请输入巡检名称"
|
clearable
|
:prefix-icon="Search"
|
@change="handleQuery"
|
/>
|
</div>
|
<div class="filter-item">
|
<span class="search_title">线路名称:</span>
|
<el-input
|
v-model="recordSearchForm.lineName"
|
class="filter-control"
|
placeholder="请输入线路名称"
|
clearable
|
:prefix-icon="Search"
|
@change="handleQuery"
|
/>
|
</div>
|
</template>
|
<template v-else>
|
<div class="filter-item">
|
<span class="search_title">隐患编号:</span>
|
<el-input
|
v-model="rectifySearchForm.hazardCode"
|
class="filter-control"
|
placeholder="请输入隐患编号"
|
clearable
|
:prefix-icon="Search"
|
@change="handleQuery"
|
/>
|
</div>
|
<div class="filter-item">
|
<span class="search_title">隐患描述:</span>
|
<el-input
|
v-model="rectifySearchForm.hazardDesc"
|
class="filter-control"
|
placeholder="请输入隐患描述"
|
clearable
|
:prefix-icon="Search"
|
@change="handleQuery"
|
/>
|
</div>
|
<div class="filter-item">
|
<span class="search_title">整改状态:</span>
|
<el-select
|
v-model="rectifySearchForm.status"
|
class="filter-control is-short"
|
clearable
|
placeholder="请选择"
|
@change="handleQuery"
|
>
|
<el-option label="待整改" value="待整改" />
|
<el-option label="整改中" value="整改中" />
|
<el-option label="已整改" value="已整改" />
|
</el-select>
|
</div>
|
</template>
|
<div class="filter-buttons">
|
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
</div>
|
</div>
|
</div>
|
|
<div class="table_list">
|
<div class="table-toolbar" v-if="activeTab === 'task'">
|
<div></div>
|
<div class="toolbar-actions">
|
<el-button type="primary" :icon="Plus" @click="openTaskDialog('add')">新增巡检任务</el-button>
|
<el-button type="danger" :icon="Delete" :disabled="selectedIds.length === 0" @click="handleBatchDeleteTask">删除</el-button>
|
</div>
|
</div>
|
<PIMTable
|
rowKey="id"
|
:column="tableColumns"
|
:tableData="tableData"
|
:page="page"
|
:isSelection="true"
|
:tableLoading="tableLoading"
|
:total="page.total"
|
:height="'calc(100vh - 25em)'"
|
:table-style="{ width: '100%' }"
|
@selection-change="handleSelectionChange"
|
@pagination="pagination"
|
>
|
<template #taskName="{ row }">
|
<el-button class="task-name-link" type="primary" link @click="openTaskDetail(row)">
|
{{ row.inspectionName || "--" }}
|
</el-button>
|
</template>
|
<template #inspectionCode="{ row }">
|
<el-button class="code-link" type="primary" link @click="openInspectionDetailEntry(row)">
|
{{ row.inspectionCode || "--" }}
|
</el-button>
|
</template>
|
<template #inspectionResult="{ row }">
|
<el-tag :type="getInspectionResultType(row.inspectionResult)" size="small">
|
{{ row.inspectionResult || "未巡检" }}
|
</el-tag>
|
</template>
|
<template #inspectorName="{ row }">
|
<div class="person-tags">
|
<template v-if="getInspectorNames(row).length">
|
<el-tag
|
v-for="name in getInspectorNames(row)"
|
:key="name"
|
size="small"
|
type="primary"
|
class="person-tag"
|
>
|
{{ name }}
|
</el-tag>
|
</template>
|
<span v-else class="no-data">--</span>
|
</div>
|
</template>
|
<template #isEnabled="{ row }">
|
<el-tag :type="row.isEnabled === 1 ? 'success' : 'info'" size="small">
|
{{ row.isEnabled === 1 ? "是" : "否" }}
|
</el-tag>
|
</template>
|
<template #status="{ row }">
|
<el-tag :type="getInspectionStatusType(row.status)" size="small">
|
{{ row.status || "--" }}
|
</el-tag>
|
</template>
|
<template #hazardLevel="{ row }">
|
<el-tag :type="getRiskLevelType(row.hazardLevel)" size="small">
|
{{ row.hazardLevel || "--" }}
|
</el-tag>
|
</template>
|
<template #hazardStatus="{ row }">
|
<el-tag :type="getHazardStatusType(row.status)" size="small">
|
{{ row.status || "--" }}
|
</el-tag>
|
</template>
|
<template #rectifyPhotos="{ row }">
|
<el-tag :type="hasAttachments(getAttachments(row)) ? 'success' : 'info'" size="small">
|
{{ hasAttachments(getAttachments(row)) ? "已上传" : "未上传" }}
|
</el-tag>
|
</template>
|
</PIMTable>
|
</div>
|
|
<el-dialog
|
v-model="taskDetailVisible"
|
title="巡检任务详情"
|
width="780px"
|
:close-on-click-modal="false"
|
>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="巡检任务名称">
|
{{ taskDetail.inspectionName || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="线路名称">
|
{{ taskDetail.lineName || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="执行巡检人">
|
{{ getInspectorNames(taskDetail).join("、") || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="是否启用">
|
<el-tag :type="taskDetail.isEnabled === 1 ? 'success' : 'info'" size="small">
|
{{ taskDetail.isEnabled === 1 ? "是" : "否" }}
|
</el-tag>
|
</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="最后执行时间">
|
{{ taskDetail.lastExecutionTime || "--" }}
|
</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="1280px"
|
:close-on-click-modal="false"
|
>
|
<el-descriptions class="history-summary" :column="3" border>
|
<el-descriptions-item label="巡检任务名称">
|
{{ taskHistoryTask.inspectionName || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="线路名称">
|
{{ taskHistoryTask.lineName || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="频次">
|
{{ frequencyTypeMap[taskHistoryTask.frequencyType] || taskHistoryTask.frequencyType || "--" }}
|
</el-descriptions-item>
|
</el-descriptions>
|
<PIMTable
|
rowKey="id"
|
:column="taskHistoryColumns"
|
:tableData="taskHistoryData"
|
:page="taskHistoryPage"
|
:tableLoading="taskHistoryLoading"
|
:total="taskHistoryPage.total"
|
:height="420"
|
:table-style="{ width: '100%' }"
|
@pagination="taskHistoryPagination"
|
>
|
<template #inspectionCode="{ row }">
|
<el-button class="code-link" type="primary" link @click="openInspectionDetail(row)">
|
{{ row.inspectionCode || "--" }}
|
</el-button>
|
</template>
|
<template #inspectionResult="{ row }">
|
<el-tag :type="getInspectionResultType(row.inspectionResult)" size="small">
|
{{ row.inspectionResult || "未巡检" }}
|
</el-tag>
|
</template>
|
<template #inspectorName="{ row }">
|
<div class="person-tags">
|
<template v-if="getInspectorNames(row).length">
|
<el-tag
|
v-for="name in getInspectorNames(row)"
|
:key="name"
|
size="small"
|
type="primary"
|
class="person-tag"
|
>
|
{{ name }}
|
</el-tag>
|
</template>
|
<span v-else class="no-data">--</span>
|
</div>
|
</template>
|
<template #status="{ row }">
|
<el-tag :type="getInspectionStatusType(row.status)" size="small">
|
{{ row.status || "--" }}
|
</el-tag>
|
</template>
|
</PIMTable>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary" @click="taskHistoryVisible = false">关闭</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
|
<el-dialog
|
v-model="inspectionDetailVisible"
|
title="巡检详情"
|
width="960px"
|
:close-on-click-modal="false"
|
>
|
<el-descriptions :column="3" border>
|
<el-descriptions-item label="巡检编号">
|
{{ inspectionDetail.inspectionCode || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="巡检名称">
|
{{ inspectionDetail.inspectionName || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="线路名称">
|
{{ inspectionDetail.lineName || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="计划巡检时间">
|
{{ inspectionDetail.planTime || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="实际巡检时间">
|
{{ inspectionDetail.actualInspectionTime || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="巡检结果">
|
<el-tag :type="getInspectionResultType(inspectionDetail.inspectionResult)" size="small">
|
{{ inspectionDetail.inspectionResult || "未巡检" }}
|
</el-tag>
|
</el-descriptions-item>
|
<el-descriptions-item label="巡检人">
|
{{ getInspectorNames(inspectionDetail).join("、") || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="状态">
|
<el-tag :type="getInspectionStatusType(inspectionDetail.status)" size="small">
|
{{ inspectionDetail.status || "--" }}
|
</el-tag>
|
</el-descriptions-item>
|
<el-descriptions-item label="巡检类型">
|
{{ inspectionDetail.inspectionType || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="巡检项目" :span="3">
|
{{ inspectionDetail.inspectionProject || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="备注" :span="3">
|
{{ inspectionDetail.remark || "--" }}
|
</el-descriptions-item>
|
</el-descriptions>
|
|
<div class="detail-section-title">巡检执行记录</div>
|
<el-table v-loading="inspectionDetailLoading" :data="inspectionDetailRecords" border>
|
<el-table-column prop="checkResult" label="结果" width="90" align="center">
|
<template #default="{ row }">
|
<el-tag :type="row.checkResult === '正常' ? 'success' : 'danger'" size="small">
|
{{ row.checkResult || "--" }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="checkContent" label="巡检项目" min-width="180" show-overflow-tooltip />
|
<el-table-column prop="checkDesc" label="巡检说明" min-width="180" show-overflow-tooltip />
|
<el-table-column prop="checkTime" label="巡检时间" width="170" align="center" />
|
<el-table-column label="现场照片" min-width="180" align="center">
|
<template #default="{ row }">
|
<div v-if="getAttachments(row).length" class="photo-list">
|
<el-image
|
v-for="(item, index) in getAttachments(row)"
|
:key="item.storageAttachmentId || item.id || index"
|
class="record-photo"
|
:src="getAttachmentPreviewUrl(item)"
|
:preview-src-list="getAttachmentPreviewUrls(row)"
|
fit="cover"
|
preview-teleported
|
/>
|
</div>
|
<span v-else class="no-data">--</span>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<div class="detail-section-title">整改跟踪</div>
|
<el-table v-loading="inspectionDetailLoading" :data="inspectionDetailHazards" border>
|
<el-table-column prop="hazardCode" label="隐患编号" width="145" align="center" show-overflow-tooltip />
|
<el-table-column prop="hazardDesc" label="异常描述" min-width="170" show-overflow-tooltip />
|
<el-table-column prop="hazardLocation" label="异常位置" min-width="130" show-overflow-tooltip />
|
<el-table-column prop="hazardLevel" label="风险等级" width="105" align="center">
|
<template #default="{ row }">
|
<el-tag :type="getRiskLevelType(row.hazardLevel)" size="small">
|
{{ row.hazardLevel || "--" }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="rectifyUserName" label="整改责任人" width="120" align="center" show-overflow-tooltip />
|
<el-table-column prop="rectifyDeadline" label="整改期限" width="120" align="center" />
|
<el-table-column prop="rectifyDesc" label="整改说明" min-width="170" show-overflow-tooltip>
|
<template #default="{ row }">
|
{{ row.rectifyDesc || "--" }}
|
</template>
|
</el-table-column>
|
<el-table-column prop="rectifyTime" label="整改时间" width="165" align="center">
|
<template #default="{ row }">
|
{{ row.rectifyTime || "--" }}
|
</template>
|
</el-table-column>
|
<el-table-column label="整改照片" min-width="150" align="center">
|
<template #default="{ row }">
|
<div v-if="getAttachments(row).length" class="photo-list">
|
<el-image
|
v-for="(item, index) in getAttachments(row)"
|
:key="item.storageAttachmentId || item.id || index"
|
class="record-photo"
|
:src="getAttachmentPreviewUrl(item)"
|
:preview-src-list="getAttachmentPreviewUrls(row)"
|
fit="cover"
|
preview-teleported
|
/>
|
</div>
|
<span v-else class="no-data">--</span>
|
</template>
|
</el-table-column>
|
<el-table-column prop="status" label="整改状态" width="100" align="center">
|
<template #default="{ row }">
|
<el-tag :type="getHazardStatusType(row.status)" size="small">
|
{{ row.status || "--" }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary" @click="inspectionDetailVisible = false">关闭</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
|
<el-dialog
|
v-model="executeDialogVisible"
|
title="执行巡检"
|
width="820px"
|
:close-on-click-modal="false"
|
@closed="resetExecuteForm"
|
>
|
<el-descriptions :column="2" border class="execute-summary">
|
<el-descriptions-item label="巡检编号">
|
{{ currentInspection.inspectionCode || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="巡检名称">
|
{{ currentInspection.inspectionName || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="线路名称">
|
{{ currentInspection.lineName || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="计划时间">
|
{{ currentInspection.planTime || "--" }}
|
</el-descriptions-item>
|
<el-descriptions-item label="巡检项目" :span="2">
|
{{ currentInspection.inspectionProject || "--" }}
|
</el-descriptions-item>
|
</el-descriptions>
|
|
<el-form ref="executeFormRef" :model="executeForm" :rules="executeRules" label-width="120px">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="巡检结果" prop="checkResult">
|
<el-radio-group v-model="executeForm.checkResult" @change="handleExecuteResultChange">
|
<el-radio label="正常">正常</el-radio>
|
<el-radio label="异常">异常</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="巡检时间" prop="checkTime">
|
<el-date-picker
|
v-model="executeForm.checkTime"
|
type="datetime"
|
placeholder="请选择巡检时间"
|
format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-form-item v-if="executeForm.checkResult === '正常'" label="巡检说明" prop="checkDesc">
|
<el-input
|
v-model="executeForm.checkDesc"
|
type="textarea"
|
:rows="3"
|
placeholder="请输入正常巡检情况说明"
|
/>
|
</el-form-item>
|
|
<template v-if="executeForm.checkResult === '异常'">
|
<el-form-item label="异常照片" prop="storageBlobDTOs">
|
<ImageUpload v-model:file-list="executeForm.storageBlobDTOs" :limit="6" button-text="上传照片" />
|
</el-form-item>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="隐患类型" prop="hiddenType">
|
<el-select v-model="executeForm.hiddenType" placeholder="请选择隐患类型" clearable style="width: 100%">
|
<el-option
|
v-for="item in hiddenTypeOptions"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value"
|
/>
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="风险等级" prop="riskLevel">
|
<el-select v-model="executeForm.riskLevel" placeholder="请选择风险等级" clearable style="width: 100%">
|
<el-option v-for="item in riskLevelList" :key="item.value" :label="item.label" :value="item.value" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="隐患位置" prop="hazardLocation">
|
<el-input v-model="executeForm.hazardLocation" placeholder="请输入隐患位置" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="整改责任人" prop="rectifyUserId">
|
<el-select
|
v-model="executeForm.rectifyUserId"
|
placeholder="请选择整改责任人"
|
filterable
|
clearable
|
style="width: 100%"
|
@change="handleRectifyUserChange"
|
>
|
<el-option
|
v-for="item in userList"
|
:key="item.userId"
|
:label="item.nickName"
|
:value="item.userId"
|
/>
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="整改期限" prop="rectifyTime">
|
<el-date-picker
|
v-model="executeForm.rectifyTime"
|
type="date"
|
placeholder="请选择整改期限"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-form-item label="异常描述/整改要求" prop="hazardDesc">
|
<el-input
|
v-model="executeForm.hazardDesc"
|
type="textarea"
|
:rows="3"
|
placeholder="请描述异常情况和整改要求"
|
/>
|
</el-form-item>
|
</template>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary" @click="submitExecuteForm">提交</el-button>
|
<el-button @click="executeDialogVisible = false">取消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
|
<el-dialog
|
v-model="taskDialogVisible"
|
:title="taskDialogTitle"
|
width="960px"
|
: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="inspectionName">
|
<el-input v-model="taskForm.inspectionName" placeholder="请输入巡检任务名称" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="线路名称" prop="lineName">
|
<el-input v-model="taskForm.lineName" placeholder="请输入线路名称" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="巡检人" prop="inspectorIds">
|
<el-select
|
v-model="taskForm.inspectorIds"
|
placeholder="请选择巡检人"
|
filterable
|
multiple
|
collapse-tags
|
collapse-tags-tooltip
|
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="inspectionDialogVisible"
|
title="编辑巡检记录"
|
width="800px"
|
:close-on-click-modal="false"
|
@closed="resetInspectionForm"
|
>
|
<el-form ref="inspectionFormRef" :model="inspectionForm" :rules="inspectionRules" 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>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="巡检名称" prop="inspectionName">
|
<el-input v-model="inspectionForm.inspectionName" placeholder="请输入巡检名称" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="线路名称" prop="lineName">
|
<el-input v-model="inspectionForm.lineName" 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-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<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>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="巡检人" prop="inspectorIds">
|
<el-select
|
v-model="inspectionForm.inspectorIds"
|
placeholder="请选择巡检人"
|
filterable
|
multiple
|
collapse-tags
|
collapse-tags-tooltip
|
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-row>
|
<el-form-item label="巡检项目">
|
<el-input
|
v-model="inspectionForm.inspectionProject"
|
type="textarea"
|
:rows="3"
|
placeholder="请输入巡检项目"
|
/>
|
</el-form-item>
|
<el-form-item label="备注">
|
<el-input v-model="inspectionForm.remark" type="textarea" :rows="3" placeholder="请输入备注" />
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary" @click="submitInspectionForm">确定</el-button>
|
<el-button @click="inspectionDialogVisible = false">取消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
|
<el-dialog
|
ref="recordDialogRef"
|
v-model="recordDialogVisible"
|
title="巡检记录"
|
width="70vw"
|
:close-on-click-modal="false"
|
@open="onRecordDialogOpen"
|
>
|
<div class="mb10">
|
<el-button
|
type="primary"
|
size="small"
|
:disabled="currentInspectionStatus === '已完成'"
|
@click="openRecordForm"
|
>
|
新增记录
|
</el-button>
|
</div>
|
<div class="dialog-table-wrapper">
|
<el-table :data="recordList" border style="width: 100%">
|
<el-table-column prop="checkPoint" label="检查点" min-width="140" show-overflow-tooltip />
|
<el-table-column prop="checkContent" label="检查内容" min-width="200" show-overflow-tooltip />
|
<el-table-column prop="checkResult" label="检查结果" width="100">
|
<template #default="{ row }">
|
<el-tag :type="row.checkResult === '正常' ? 'success' : 'danger'">
|
{{ row.checkResult }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="checkDesc" label="检查说明" min-width="180" show-overflow-tooltip />
|
<el-table-column label="现场照片" width="100">
|
<template #default="{ row }">
|
<el-tag :type="hasAttachments(row.storageBlobVOs) ? 'success' : 'info'">
|
{{ hasAttachments(row.storageBlobVOs) ? "已上传" : "未上传" }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="checkTime" label="检查时间" width="180" />
|
<el-table-column label="操作" width="130" fixed="right">
|
<template #default="{ row }">
|
<el-button type="primary" link :disabled="currentInspectionStatus === '已完成'" @click="openEditRecordForm(row)">编辑</el-button>
|
<el-button type="danger" link :disabled="currentInspectionStatus === '已完成'" @click="handleDeleteRecord(row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
|
<el-dialog
|
v-model="recordFormVisible"
|
:title="recordForm.id ? '编辑巡检记录' : '新增巡检记录'"
|
width="600px"
|
append-to-body
|
:close-on-click-modal="false"
|
>
|
<el-form ref="recordFormRef" :model="recordForm" :rules="recordRules" label-width="100px">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="检查点" prop="checkPoint">
|
<el-input v-model="recordForm.checkPoint" placeholder="请输入检查点" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="检查结果" prop="checkResult">
|
<el-radio-group v-model="recordForm.checkResult">
|
<el-radio label="正常">正常</el-radio>
|
<el-radio label="异常">异常</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-form-item label="检查内容" prop="checkContent">
|
<el-input v-model="recordForm.checkContent" type="textarea" :rows="3" placeholder="请输入检查内容" />
|
</el-form-item>
|
<el-form-item label="检查说明">
|
<el-input v-model="recordForm.checkDesc" type="textarea" :rows="2" placeholder="请输入检查说明" />
|
</el-form-item>
|
<el-form-item v-if="recordForm.checkResult === '异常'" label="现场照片">
|
<ImageUpload v-model:file-list="recordForm.storageBlobDTOs" :limit="6" button-text="上传照片" />
|
</el-form-item>
|
<el-form-item label="检查时间">
|
<el-date-picker
|
v-model="recordForm.checkTime"
|
type="datetime"
|
placeholder="请选择检查时间"
|
format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary" @click="submitRecordForm">确定</el-button>
|
<el-button @click="recordFormVisible = false">取消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</el-dialog>
|
|
<el-dialog
|
ref="hazardDialogRef"
|
v-model="hazardDialogVisible"
|
title="隐患管理"
|
width="75vw"
|
:close-on-click-modal="false"
|
@open="onHazardDialogOpen"
|
>
|
<div class="mb10">
|
<el-button
|
type="primary"
|
size="small"
|
:disabled="currentInspectionStatus === '已完成'"
|
@click="openHazardForm('add')"
|
>
|
上报隐患
|
</el-button>
|
</div>
|
<div class="dialog-table-wrapper">
|
<el-table :data="hazardList" border style="width: 100%">
|
<el-table-column prop="hazardCode" label="隐患编号" min-width="120" show-overflow-tooltip />
|
<el-table-column prop="hazardDesc" label="隐患描述" min-width="200" show-overflow-tooltip />
|
<el-table-column prop="hazardLevel" label="隐患等级" width="100">
|
<template #default="{ row }">
|
<el-tag :type="row.hazardLevel === '重大' ? 'danger' : 'warning'">
|
{{ row.hazardLevel }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="hazardLocation" label="隐患位置" min-width="150" show-overflow-tooltip />
|
<el-table-column prop="status" label="状态" width="100">
|
<template #default="{ row }">
|
<el-tag :type="getHazardStatusType(row.status)">
|
{{ row.status }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="rectifyUserName" label="整改责任人" min-width="120" />
|
<el-table-column label="操作" width="150" fixed="right">
|
<template #default="{ row }">
|
<el-button type="primary" link :disabled="currentInspectionStatus === '已完成'" @click="openHazardForm('edit', row)">编辑</el-button>
|
<el-button
|
v-if="row.status !== '已整改'"
|
type="success"
|
link
|
:disabled="currentInspectionStatus === '已完成'"
|
@click="handleRectify(row)"
|
>
|
整改
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
|
<el-dialog
|
v-model="hazardFormVisible"
|
:title="hazardDialogTitle"
|
width="600px"
|
append-to-body
|
:close-on-click-modal="false"
|
>
|
<el-form ref="hazardFormRef" :model="hazardForm" :rules="hazardRules" label-width="100px">
|
<el-form-item label="隐患描述" prop="hazardDesc">
|
<el-input v-model="hazardForm.hazardDesc" type="textarea" :rows="3" placeholder="请输入隐患描述" />
|
</el-form-item>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="隐患等级" prop="hazardLevel">
|
<el-select v-model="hazardForm.hazardLevel" placeholder="请选择隐患等级" style="width: 100%">
|
<el-option label="一般" value="一般" />
|
<el-option label="重大" value="重大" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="隐患位置" prop="hazardLocation">
|
<el-input v-model="hazardForm.hazardLocation" placeholder="请输入隐患位置" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary" @click="submitHazardForm">确定</el-button>
|
<el-button @click="hazardFormVisible = false">取消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
|
</el-dialog>
|
|
<el-dialog
|
v-model="rectifyFormVisible"
|
title="整改"
|
width="620px"
|
append-to-body
|
:close-on-click-modal="false"
|
@closed="resetRectifyForm"
|
>
|
<el-form ref="rectifyFormRef" :model="rectifyForm" :rules="rectifyRules" label-width="100px">
|
<el-form-item label="整改说明" prop="rectifyDesc">
|
<el-input v-model="rectifyForm.rectifyDesc" type="textarea" :rows="4" placeholder="请输入整改说明" />
|
</el-form-item>
|
<el-form-item label="整改后照片" prop="storageBlobDTOs">
|
<ImageUpload v-model:file-list="rectifyForm.storageBlobDTOs" :limit="6" button-text="上传照片" />
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary" @click="submitRectifyForm">确定</el-button>
|
<el-button @click="rectifyFormVisible = false">取消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { computed, getCurrentInstance, onMounted, reactive, ref } from "vue";
|
import { Delete, Plus, Search } from "@element-plus/icons-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 {
|
getLineInspectionTaskList,
|
addLineInspectionTask,
|
updateLineInspectionTask,
|
deleteLineInspectionTask,
|
getLineInspectionList,
|
getLineInspectionById,
|
updateLineInspection,
|
deleteLineInspection,
|
executeLineInspection,
|
getInspectionRecords,
|
addInspectionRecord,
|
updateInspectionRecord,
|
deleteInspectionRecord,
|
getInspectionHazards,
|
getHazardsByInspectionId,
|
addInspectionHazard,
|
updateInspectionHazard
|
} from "@/api/safeProduction/lineInspection";
|
|
const ENABLED = 1;
|
const { proxy } = getCurrentInstance();
|
const { hidden_danger_type } = proxy.useDict("hidden_danger_type");
|
const userStore = useUserStore();
|
const currentUserId = computed(() => Number(userStore.id));
|
|
const activeTab = ref("task");
|
const tableLoading = ref(false);
|
const tableData = ref([]);
|
const selectedIds = ref([]);
|
const userList = ref([]);
|
const taskDialogVisible = ref(false);
|
const taskDetailVisible = ref(false);
|
const taskHistoryVisible = ref(false);
|
const taskHistoryLoading = ref(false);
|
const inspectionDetailVisible = ref(false);
|
const inspectionDetailLoading = ref(false);
|
const executeDialogVisible = ref(false);
|
const inspectionDialogVisible = ref(false);
|
const recordDialogVisible = ref(false);
|
const recordFormVisible = ref(false);
|
const hazardDialogVisible = ref(false);
|
const hazardFormVisible = ref(false);
|
const rectifyFormVisible = ref(false);
|
const taskDialogTitle = ref("新增巡检任务");
|
const hazardDialogTitle = ref("上报隐患");
|
const currentInspectionId = ref(null);
|
const currentInspectionStatus = ref("");
|
const currentInspection = ref({});
|
const inspectionDetail = ref({});
|
const taskHistoryTask = ref({});
|
const taskHistoryData = ref([]);
|
const inspectionDetailRecords = ref([]);
|
const inspectionDetailHazards = ref([]);
|
const recordList = ref([]);
|
const hazardList = ref([]);
|
|
const taskFormRef = ref();
|
const inspectionFormRef = ref();
|
const recordFormRef = ref();
|
const hazardFormRef = ref();
|
const executeFormRef = ref();
|
const rectifyFormRef = ref();
|
|
const moduleTabs = [
|
{ label: "巡检任务", value: "task" },
|
{ label: "巡检记录", value: "record" },
|
{ label: "整改跟踪", value: "rectify" }
|
];
|
|
const page = reactive({
|
current: 1,
|
size: 20,
|
total: 0,
|
layout: "total, sizes, prev, pager, next, jumper"
|
});
|
|
const taskHistoryPage = reactive({
|
current: 1,
|
size: 10,
|
total: 0,
|
layout: "total, sizes, prev, pager, next, jumper"
|
});
|
|
const taskSearchForm = reactive({
|
inspectionName: "",
|
lineName: "",
|
isEnabled: ""
|
});
|
|
const recordSearchForm = reactive({
|
inspectionCode: "",
|
inspectionName: "",
|
lineName: ""
|
});
|
|
const rectifySearchForm = reactive({
|
hazardCode: "",
|
hazardDesc: "",
|
status: ""
|
});
|
|
const createTaskForm = () => ({
|
id: null,
|
inspectionName: "",
|
lineName: "",
|
inspectionProject: "",
|
inspectorId: "",
|
inspectorIds: [],
|
frequencyType: "",
|
frequencyDetail: "",
|
week: "",
|
day: "",
|
time: "",
|
isEnabled: ENABLED,
|
remark: ""
|
});
|
|
const createInspectionForm = () => ({
|
id: null,
|
scheduleTaskId: null,
|
inspectionCode: "",
|
inspectionName: "",
|
lineName: "",
|
inspectionType: "定期巡检",
|
inspectionProject: "",
|
planTime: "",
|
inspectorId: "",
|
inspectorIds: [],
|
status: "",
|
remark: ""
|
});
|
|
const taskForm = reactive(createTaskForm());
|
const taskDetail = ref({});
|
const inspectionForm = reactive(createInspectionForm());
|
|
const recordForm = reactive({
|
id: null,
|
inspectionId: null,
|
checkPoint: "",
|
checkContent: "",
|
checkResult: "正常",
|
checkDesc: "",
|
checkTime: "",
|
storageBlobDTOs: []
|
});
|
|
const hazardForm = reactive({
|
id: null,
|
inspectionId: null,
|
hazardDesc: "",
|
hazardLevel: "",
|
hazardLocation: ""
|
});
|
|
const rectifyForm = reactive({
|
id: null,
|
rectifyDesc: "",
|
storageBlobDTOs: []
|
});
|
|
const createExecuteForm = () => ({
|
inspectionId: null,
|
checkResult: "正常",
|
checkDesc: "",
|
checkTime: "",
|
storageBlobDTOs: [],
|
hiddenType: "",
|
riskLevel: "",
|
hazardLocation: "",
|
hazardDesc: "",
|
rectifyUserId: "",
|
rectifyUserMobile: "",
|
rectifyTime: ""
|
});
|
|
const executeForm = reactive(createExecuteForm());
|
|
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 validateFrequencyDetail = (rule, value, callback) => {
|
if (!taskForm.frequencyType) {
|
callback(new Error("请选择任务频率"));
|
return;
|
}
|
if (taskForm.frequencyType === "DAILY" && !taskForm.frequencyDetail) {
|
callback(new Error("请选择时间"));
|
return;
|
}
|
if (taskForm.frequencyType === "WEEKLY" && (!taskForm.week || !taskForm.time)) {
|
callback(new Error("请选择星期和时间"));
|
return;
|
}
|
if (taskForm.frequencyType === "MONTHLY" && (!taskForm.day || !taskForm.time)) {
|
callback(new Error("请选择日期和时间"));
|
return;
|
}
|
callback();
|
};
|
|
const taskRules = {
|
inspectionName: [{ required: true, message: "请输入巡检任务名称", trigger: "blur" }],
|
lineName: [{ required: true, message: "请输入线路名称", trigger: "blur" }],
|
inspectionProject: [{ required: true, message: "请输入巡检项目", trigger: "blur" }],
|
inspectorIds: [{ type: "array", 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" }],
|
inspectionName: [{ required: true, message: "请输入巡检名称", trigger: "blur" }],
|
lineName: [{ required: true, message: "请输入线路名称", trigger: "blur" }],
|
inspectorIds: [{ type: "array", required: true, message: "请选择巡检人", trigger: "change" }]
|
};
|
|
const recordRules = {
|
checkPoint: [{ required: true, message: "请输入检查点", trigger: "blur" }],
|
checkContent: [{ required: true, message: "请输入检查内容", trigger: "blur" }],
|
checkResult: [{ required: true, message: "请选择检查结果", trigger: "change" }]
|
};
|
|
const hazardRules = {
|
hazardDesc: [{ required: true, message: "请输入隐患描述", trigger: "blur" }],
|
hazardLevel: [{ required: true, message: "请选择隐患等级", trigger: "change" }],
|
hazardLocation: [{ required: true, message: "请输入隐患位置", trigger: "blur" }]
|
};
|
|
const rectifyRules = {
|
rectifyDesc: [{ required: true, message: "请输入整改说明", trigger: "blur" }],
|
storageBlobDTOs: [{ required: true, message: "请上传整改后照片", trigger: "change" }]
|
};
|
|
const riskLevelList = [
|
{ value: "重大风险", label: "重大风险" },
|
{ value: "较大风险", label: "较大风险" },
|
{ value: "一般风险", label: "一般风险" },
|
{ value: "低风险", label: "低风险" }
|
];
|
|
const hiddenTypeOptions = computed(() => {
|
const list = hidden_danger_type?.value || [];
|
return list.length ? list : [{ label: "线路巡检", value: "线路巡检" }];
|
});
|
|
const validateAbnormalRequired = message => (rule, value, callback) => {
|
if (executeForm.checkResult !== "异常") {
|
callback();
|
return;
|
}
|
if (Array.isArray(value) ? value.length === 0 : value === "" || value === null || value === undefined) {
|
callback(new Error(message));
|
return;
|
}
|
callback();
|
};
|
|
const executeRules = {
|
checkResult: [{ required: true, message: "请选择巡检结果", trigger: "change" }],
|
checkTime: [{ required: true, message: "请选择巡检时间", trigger: "change" }],
|
storageBlobDTOs: [{ validator: validateAbnormalRequired("巡检异常时请上传异常照片"), trigger: "change" }],
|
hiddenType: [{ validator: validateAbnormalRequired("请选择隐患类型"), trigger: "change" }],
|
riskLevel: [{ validator: validateAbnormalRequired("请选择风险等级"), trigger: "change" }],
|
hazardLocation: [{ validator: validateAbnormalRequired("请输入隐患位置"), trigger: "blur" }],
|
hazardDesc: [{ validator: validateAbnormalRequired("请输入异常描述/整改要求"), trigger: "blur" }],
|
rectifyUserId: [{ validator: validateAbnormalRequired("请选择整改责任人"), trigger: "change" }],
|
rectifyTime: [{ validator: validateAbnormalRequired("请选择整改期限"), trigger: "change" }]
|
};
|
|
const taskColumns = [
|
{ label: "巡检任务名称", prop: "inspectionName", minWidth: 165, dataType: "slot", slot: "taskName", align: "left" },
|
{ label: "线路名称", prop: "lineName", minWidth: 150, showOverflowTooltip: true, align: "left" },
|
{ label: "巡检项目", prop: "inspectionProject", minWidth: 175, showOverflowTooltip: true, align: "left" },
|
{ label: "执行巡检人", prop: "inspectorName", minWidth: 145, dataType: "slot", slot: "inspectorName", align: "center" },
|
{ label: "是否启用", prop: "isEnabled", minWidth: 90, dataType: "slot", slot: "isEnabled", align: "center" },
|
{
|
label: "频次",
|
prop: "frequencyType",
|
minWidth: 85,
|
align: "center",
|
formatData: value => frequencyTypeMap[value] || value || "--"
|
},
|
{
|
label: "开始日期与时间",
|
prop: "frequencyDetail",
|
minWidth: 150,
|
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",
|
style: { color: "#F56C6C" },
|
clickFun: row => handleDeleteTask(row)
|
}
|
]
|
}
|
];
|
|
const taskHistoryColumns = [
|
{ label: "巡检编号", prop: "inspectionCode", width: 190, dataType: "slot", slot: "inspectionCode", align: "center" },
|
{ label: "巡检名称", prop: "inspectionName", minWidth: 135, showOverflowTooltip: true, align: "left" },
|
{ label: "线路名称", prop: "lineName", minWidth: 130, showOverflowTooltip: true, align: "left" },
|
{ label: "巡检项目", prop: "inspectionProject", minWidth: 150, showOverflowTooltip: true, align: "left" },
|
{ label: "计划巡检时间", prop: "planTime", width: 165, showOverflowTooltip: true, align: "center" },
|
{ label: "巡检结果", prop: "inspectionResult", width: 90, dataType: "slot", slot: "inspectionResult", align: "center" },
|
{ label: "实际巡检时间", prop: "actualInspectionTime", width: 165, showOverflowTooltip: true, align: "center" },
|
{ label: "巡检人", prop: "inspectorName", minWidth: 105, dataType: "slot", slot: "inspectorName", align: "center" },
|
{ label: "状态", prop: "status", width: 90, dataType: "slot", slot: "status", align: "center" }
|
];
|
|
const recordColumns = [
|
{ label: "巡检编号", prop: "inspectionCode", width: 190, dataType: "slot", slot: "inspectionCode", align: "center" },
|
{ label: "巡检名称", prop: "inspectionName", minWidth: 135, showOverflowTooltip: true, align: "left" },
|
{ label: "线路名称", prop: "lineName", minWidth: 130, showOverflowTooltip: true, align: "left" },
|
{ label: "巡检项目", prop: "inspectionProject", minWidth: 145, showOverflowTooltip: true, align: "left" },
|
{ label: "计划巡检时间", prop: "planTime", width: 165, showOverflowTooltip: true, align: "center" },
|
{ label: "巡检结果", prop: "inspectionResult", width: 90, dataType: "slot", slot: "inspectionResult", align: "center" },
|
{ label: "实际巡检时间", prop: "actualInspectionTime", width: 165, showOverflowTooltip: true, align: "center" },
|
{ label: "巡检人", prop: "inspectorName", minWidth: 105, dataType: "slot", slot: "inspectorName", align: "center" },
|
{ label: "状态", prop: "status", width: 90, dataType: "slot", slot: "status", align: "center" },
|
{
|
dataType: "action",
|
label: "操作",
|
align: "center",
|
fixed: "right",
|
width: 125,
|
operation: [
|
{
|
name: "执行巡检",
|
type: "text",
|
clickFun: row => openExecuteDialog(row),
|
show: row => row.status !== "已完成" && row.status !== "待整改"
|
},
|
{
|
name: "删除",
|
type: "text",
|
style: { color: "#F56C6C" },
|
clickFun: row => handleDeleteInspection(row),
|
disabled: row => row.status !== "待巡检"
|
}
|
]
|
}
|
];
|
|
const rectifyColumns = [
|
{ label: "隐患编号", prop: "hazardCode", width: 135, showOverflowTooltip: true, align: "center" },
|
{ label: "巡检编号", prop: "inspectionCode", width: 190, dataType: "slot", slot: "inspectionCode", align: "center" },
|
{ label: "巡检名称", prop: "inspectionName", minWidth: 120, showOverflowTooltip: true, align: "left" },
|
{ label: "线路名称", prop: "lineName", minWidth: 120, showOverflowTooltip: true, align: "left" },
|
{ label: "异常描述", prop: "hazardDesc", minWidth: 160, showOverflowTooltip: true, align: "left" },
|
{ label: "异常位置", prop: "hazardLocation", minWidth: 130, showOverflowTooltip: true, align: "left" },
|
{ label: "风险等级", prop: "hazardLevel", width: 95, dataType: "slot", slot: "hazardLevel", align: "center" },
|
{ label: "整改责任人", prop: "rectifyUserName", minWidth: 110, showOverflowTooltip: true, align: "center" },
|
{ label: "整改期限", prop: "rectifyDeadline", width: 110, showOverflowTooltip: true, align: "center" },
|
{ label: "整改状态", prop: "status", width: 95, dataType: "slot", slot: "hazardStatus", align: "center" },
|
{
|
dataType: "action",
|
label: "操作",
|
align: "center",
|
fixed: "right",
|
width: 85,
|
operation: [
|
{
|
name: "整改",
|
type: "text",
|
color: "#67C23A",
|
clickFun: row => handleRectify(row),
|
show: row => row.status !== "已整改" && canRectify(row)
|
}
|
]
|
}
|
];
|
|
const tableColumns = computed(() => {
|
if (activeTab.value === "task") {
|
return taskColumns;
|
}
|
if (activeTab.value === "record") {
|
return recordColumns;
|
}
|
return rectifyColumns;
|
});
|
|
onMounted(() => {
|
getList();
|
userListNoPage().then(res => {
|
userList.value = res.data || [];
|
});
|
});
|
|
const getList = async () => {
|
tableLoading.value = true;
|
try {
|
const params = cleanParams({
|
current: page.current,
|
size: page.size,
|
...getActiveSearchForm()
|
});
|
const api = getActiveListApi();
|
const res = await api(params);
|
tableData.value = res.data?.records || [];
|
page.total = res.data?.total || 0;
|
} finally {
|
tableLoading.value = false;
|
}
|
};
|
|
const getActiveSearchForm = () => {
|
if (activeTab.value === "task") {
|
return taskSearchForm;
|
}
|
if (activeTab.value === "record") {
|
return recordSearchForm;
|
}
|
return rectifySearchForm;
|
};
|
|
const getActiveListApi = () => {
|
if (activeTab.value === "task") {
|
return getLineInspectionTaskList;
|
}
|
if (activeTab.value === "record") {
|
return getLineInspectionList;
|
}
|
return getInspectionHazards;
|
};
|
|
const handleQuery = () => {
|
page.current = 1;
|
getList();
|
};
|
|
const resetQuery = () => {
|
page.current = 1;
|
if (activeTab.value === "task") {
|
Object.assign(taskSearchForm, { inspectionName: "", lineName: "", isEnabled: "" });
|
} else if (activeTab.value === "record") {
|
Object.assign(recordSearchForm, { inspectionCode: "", inspectionName: "", lineName: "" });
|
} else {
|
Object.assign(rectifySearchForm, { hazardCode: "", hazardDesc: "", status: "" });
|
}
|
getList();
|
};
|
|
const handleTabChange = () => {
|
selectedIds.value = [];
|
page.current = 1;
|
getList();
|
};
|
|
const handleModuleTabChange = tab => {
|
if (activeTab.value === tab) {
|
return;
|
}
|
activeTab.value = tab;
|
handleTabChange();
|
};
|
|
const pagination = obj => {
|
page.current = obj.page;
|
page.size = obj.limit;
|
getList();
|
};
|
|
const handleSelectionChange = selection => {
|
selectedIds.value = selection.map(item => item.id);
|
};
|
|
const openTaskDetail = row => {
|
taskDetail.value = { ...row };
|
taskDetailVisible.value = true;
|
};
|
|
const openTaskHistory = row => {
|
taskHistoryTask.value = { ...row };
|
taskHistoryPage.current = 1;
|
taskHistoryVisible.value = true;
|
fetchTaskHistory();
|
};
|
|
const fetchTaskHistory = async () => {
|
if (!taskHistoryTask.value?.id) {
|
taskHistoryData.value = [];
|
taskHistoryPage.total = 0;
|
return;
|
}
|
taskHistoryLoading.value = true;
|
try {
|
const res = await getLineInspectionList(
|
cleanParams({
|
current: taskHistoryPage.current,
|
size: taskHistoryPage.size,
|
scheduleTaskId: taskHistoryTask.value.id
|
})
|
);
|
taskHistoryData.value = res.data?.records || [];
|
taskHistoryPage.total = res.data?.total || 0;
|
} finally {
|
taskHistoryLoading.value = false;
|
}
|
};
|
|
const taskHistoryPagination = obj => {
|
taskHistoryPage.current = obj.page;
|
taskHistoryPage.size = obj.limit;
|
fetchTaskHistory();
|
};
|
|
const openInspectionDetailEntry = row => {
|
if (activeTab.value === "rectify") {
|
openInspectionDetailById(row.inspectionId, row);
|
return;
|
}
|
openInspectionDetail(row);
|
};
|
|
const openInspectionDetailById = async (inspectionId, fallback = {}) => {
|
let row = {
|
id: inspectionId,
|
inspectionCode: fallback.inspectionCode,
|
inspectionName: fallback.inspectionName,
|
lineName: fallback.lineName
|
};
|
if (inspectionId) {
|
const res = await getLineInspectionById(inspectionId);
|
if (res.code === 200 && res.data) {
|
row = { ...row, ...res.data };
|
}
|
}
|
openInspectionDetail(row);
|
};
|
|
const openInspectionDetail = async row => {
|
if (!row?.id) {
|
ElMessage.warning("巡检记录不存在");
|
return;
|
}
|
inspectionDetail.value = { ...row };
|
inspectionDetailVisible.value = true;
|
inspectionDetailLoading.value = true;
|
try {
|
const [recordsRes, hazardsRes] = await Promise.all([
|
getInspectionRecords(row.id),
|
getHazardsByInspectionId(row.id)
|
]);
|
inspectionDetailRecords.value = recordsRes.code === 200 ? recordsRes.data || [] : [];
|
inspectionDetailHazards.value = hazardsRes.code === 200 ? hazardsRes.data || [] : [];
|
} finally {
|
inspectionDetailLoading.value = false;
|
}
|
};
|
|
const openExecuteDialog = row => {
|
currentInspection.value = { ...row };
|
Object.assign(executeForm, createExecuteForm(), {
|
inspectionId: row.id,
|
checkTime: formatDateTime(new Date()),
|
hazardLocation: row.lineName || ""
|
});
|
executeDialogVisible.value = true;
|
};
|
|
const resetExecuteForm = () => {
|
Object.assign(executeForm, createExecuteForm());
|
currentInspection.value = {};
|
executeFormRef.value?.clearValidate?.();
|
};
|
|
const handleExecuteResultChange = () => {
|
if (executeForm.checkResult === "异常") {
|
executeForm.hazardLocation = executeForm.hazardLocation || currentInspection.value.lineName || "";
|
executeForm.checkDesc = "";
|
}
|
executeFormRef.value?.clearValidate?.();
|
};
|
|
const handleRectifyUserChange = userId => {
|
const selectedUser = userList.value.find(user => Number(user.userId) === Number(userId));
|
executeForm.rectifyUserMobile = selectedUser?.phonenumber || "";
|
};
|
|
const submitExecuteForm = async () => {
|
try {
|
await executeFormRef.value.validate();
|
const payload = { ...executeForm };
|
if (payload.checkResult === "正常") {
|
Object.assign(payload, {
|
storageBlobDTOs: [],
|
hiddenType: "",
|
riskLevel: "",
|
hazardLocation: "",
|
hazardDesc: "",
|
rectifyUserId: "",
|
rectifyUserMobile: "",
|
rectifyTime: ""
|
});
|
} else {
|
payload.checkDesc = "";
|
}
|
const res = await executeLineInspection(payload);
|
if (res.code === 200) {
|
ElMessage.success(payload.checkResult === "异常" ? "异常已上报整改" : "巡检已完成");
|
executeDialogVisible.value = false;
|
getList();
|
} else {
|
ElMessage.error(res.msg || "巡检提交失败");
|
}
|
} catch (error) {
|
console.error("执行巡检表单校验失败:", error);
|
}
|
};
|
|
const openTaskDialog = (type, row = null) => {
|
resetTaskForm();
|
taskDialogTitle.value = type === "add" ? "新增巡检任务" : "编辑巡检任务";
|
if (type === "edit" && row) {
|
Object.assign(taskForm, {
|
id: row.id,
|
inspectionName: row.inspectionName,
|
lineName: row.lineName,
|
inspectionProject: row.inspectionProject,
|
inspectorId: row.inspectorId,
|
inspectorIds: parseInspectorIds(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, createTaskForm());
|
taskFormRef.value?.clearValidate?.();
|
};
|
|
const handleFrequencyTypeChange = () => {
|
Object.assign(taskForm, { frequencyDetail: "", week: "", day: "", time: "" });
|
taskFormRef.value?.clearValidate?.("frequencyDetail");
|
};
|
|
const parseFrequencyDetail = (frequencyType, frequencyDetail) => {
|
if (!frequencyDetail) {
|
return;
|
}
|
if (frequencyType === "DAILY") {
|
taskForm.frequencyDetail = frequencyDetail;
|
return;
|
}
|
const [firstPart, timePart] = frequencyDetail.split(",");
|
taskForm.frequencyDetail = "";
|
taskForm.time = timePart || "";
|
if (frequencyType === "WEEKLY") {
|
taskForm.week = firstPart || "";
|
}
|
if (frequencyType === "MONTHLY") {
|
taskForm.day = String(firstPart || "").padStart(2, "0");
|
}
|
};
|
|
const submitTaskForm = async () => {
|
try {
|
await taskFormRef.value.validate();
|
const payload = {
|
id: taskForm.id,
|
inspectionName: taskForm.inspectionName,
|
lineName: taskForm.lineName,
|
inspectionProject: taskForm.inspectionProject,
|
inspectorId: taskForm.inspectorIds.join(","),
|
frequencyType: taskForm.frequencyType,
|
frequencyDetail: buildFrequencyDetail(),
|
isEnabled: taskForm.isEnabled,
|
remark: taskForm.remark
|
};
|
const api = taskForm.id ? updateLineInspectionTask : addLineInspectionTask;
|
const res = await api(payload);
|
if (res.code === 200) {
|
ElMessage.success(taskForm.id ? "修改成功" : "新增成功");
|
taskDialogVisible.value = false;
|
getList();
|
} else {
|
ElMessage.error(res.msg || "操作失败");
|
}
|
} catch (error) {
|
console.error("任务表单校验失败:", error);
|
}
|
};
|
|
const buildFrequencyDetail = () => {
|
if (taskForm.frequencyType === "DAILY") {
|
return taskForm.frequencyDetail;
|
}
|
if (taskForm.frequencyType === "WEEKLY") {
|
return `${taskForm.week},${taskForm.time}`;
|
}
|
if (taskForm.frequencyType === "MONTHLY") {
|
return `${taskForm.day},${taskForm.time}`;
|
}
|
return "";
|
};
|
|
const handleDeleteTask = row => {
|
confirmDelete("确认删除该定时巡检任务吗?", async () => {
|
const res = await deleteLineInspectionTask([row.id]);
|
handleDeleteResult(res);
|
});
|
};
|
|
const handleBatchDeleteTask = () => {
|
if (selectedIds.value.length === 0) {
|
ElMessage.warning("请选择要删除的巡检任务");
|
return;
|
}
|
confirmDelete("确认删除选中的定时巡检任务吗?", async () => {
|
const res = await deleteLineInspectionTask(selectedIds.value);
|
handleDeleteResult(res);
|
});
|
};
|
|
const openInspectionDialog = row => {
|
resetInspectionForm();
|
Object.assign(inspectionForm, {
|
id: row.id,
|
scheduleTaskId: row.scheduleTaskId,
|
inspectionCode: row.inspectionCode,
|
inspectionName: row.inspectionName,
|
lineName: row.lineName,
|
inspectionType: row.inspectionType,
|
inspectionProject: row.inspectionProject,
|
planTime: row.planTime,
|
inspectorId: row.inspectorId,
|
inspectorIds: parseInspectorIds(row.inspectorId),
|
status: row.status,
|
remark: row.remark
|
});
|
inspectionDialogVisible.value = true;
|
};
|
|
const resetInspectionForm = () => {
|
Object.assign(inspectionForm, createInspectionForm());
|
inspectionFormRef.value?.clearValidate?.();
|
};
|
|
const submitInspectionForm = async () => {
|
try {
|
await inspectionFormRef.value.validate();
|
const payload = {
|
...inspectionForm,
|
inspectorId: inspectionForm.inspectorIds.join(",")
|
};
|
delete payload.inspectorIds;
|
const res = await updateLineInspection(payload);
|
if (res.code === 200) {
|
ElMessage.success("修改成功");
|
inspectionDialogVisible.value = false;
|
getList();
|
} else {
|
ElMessage.error(res.msg || "操作失败");
|
}
|
} catch (error) {
|
console.error("巡检记录表单校验失败:", error);
|
}
|
};
|
|
const handleDeleteInspection = row => {
|
confirmDelete("确认删除该巡检记录吗?", async () => {
|
const res = await deleteLineInspection([row.id]);
|
handleDeleteResult(res);
|
});
|
};
|
|
const openRecordDialog = row => {
|
currentInspectionId.value = row.id;
|
currentInspectionStatus.value = row.status;
|
fetchRecords(row.id);
|
recordDialogVisible.value = true;
|
};
|
|
const fetchRecords = async inspectionId => {
|
const res = await getInspectionRecords(inspectionId);
|
if (res.code === 200) {
|
recordList.value = res.data || [];
|
}
|
};
|
|
const openRecordForm = () => {
|
Object.assign(recordForm, {
|
id: null,
|
inspectionId: currentInspectionId.value,
|
checkPoint: "",
|
checkContent: "",
|
checkResult: "正常",
|
checkDesc: "",
|
checkTime: "",
|
storageBlobDTOs: []
|
});
|
recordFormVisible.value = true;
|
};
|
|
const openEditRecordForm = row => {
|
Object.assign(recordForm, {
|
id: row.id,
|
inspectionId: row.inspectionId,
|
checkPoint: row.checkPoint,
|
checkContent: row.checkContent,
|
checkResult: row.checkResult,
|
checkDesc: row.checkDesc,
|
checkTime: row.checkTime,
|
storageBlobDTOs: getAttachments(row)
|
});
|
recordFormVisible.value = true;
|
};
|
|
const handleDeleteRecord = row => {
|
confirmDelete("确认删除该巡检记录明细吗?", async () => {
|
const res = await deleteInspectionRecord([row.id]);
|
if (res.code === 200) {
|
ElMessage.success("删除成功");
|
fetchRecords(currentInspectionId.value);
|
} else {
|
ElMessage.error(res.msg || "删除失败");
|
}
|
});
|
};
|
|
const submitRecordForm = async () => {
|
try {
|
await recordFormRef.value.validate();
|
if (recordForm.checkResult === "异常" && !hasAttachments(recordForm.storageBlobDTOs)) {
|
ElMessage.warning("巡检结果异常时请上传现场照片");
|
return;
|
}
|
const api = recordForm.id ? updateInspectionRecord : addInspectionRecord;
|
const res = await api({ ...recordForm });
|
if (res.code === 200) {
|
ElMessage.success(recordForm.id ? "修改成功" : "添加成功");
|
recordFormVisible.value = false;
|
fetchRecords(currentInspectionId.value);
|
getList();
|
} else {
|
ElMessage.error(res.msg || "操作失败");
|
}
|
} catch (error) {
|
console.error("巡检记录明细表单校验失败:", error);
|
}
|
};
|
|
const openHazardDialog = row => {
|
currentInspectionId.value = row.id;
|
currentInspectionStatus.value = row.status;
|
fetchHazards(row.id);
|
hazardDialogVisible.value = true;
|
};
|
|
const fetchHazards = async inspectionId => {
|
const res = await getHazardsByInspectionId(inspectionId);
|
if (res.code === 200) {
|
hazardList.value = res.data || [];
|
}
|
};
|
|
const openHazardForm = (type, row = null) => {
|
if (type === "add") {
|
hazardDialogTitle.value = "上报隐患";
|
Object.assign(hazardForm, {
|
id: null,
|
inspectionId: currentInspectionId.value,
|
hazardDesc: "",
|
hazardLevel: "",
|
hazardLocation: ""
|
});
|
} else {
|
hazardDialogTitle.value = "编辑隐患";
|
Object.assign(hazardForm, {
|
id: row.id,
|
inspectionId: row.inspectionId,
|
hazardDesc: row.hazardDesc,
|
hazardLevel: row.hazardLevel,
|
hazardLocation: row.hazardLocation
|
});
|
}
|
hazardFormVisible.value = true;
|
};
|
|
const submitHazardForm = async () => {
|
try {
|
await hazardFormRef.value.validate();
|
const api = hazardForm.id ? updateInspectionHazard : addInspectionHazard;
|
const res = await api({ ...hazardForm });
|
if (res.code === 200) {
|
ElMessage.success("操作成功");
|
hazardFormVisible.value = false;
|
fetchHazards(currentInspectionId.value);
|
} else {
|
ElMessage.error(res.msg || "操作失败");
|
}
|
} catch (error) {
|
console.error("隐患表单校验失败:", error);
|
}
|
};
|
|
const handleRectify = row => {
|
if (!canRectify(row)) {
|
ElMessage.warning("只有整改责任人可以进行整改");
|
return;
|
}
|
currentInspectionId.value = row.inspectionId || currentInspectionId.value;
|
Object.assign(rectifyForm, {
|
id: row.id,
|
rectifyDesc: "",
|
storageBlobDTOs: []
|
});
|
rectifyFormVisible.value = true;
|
};
|
|
const resetRectifyForm = () => {
|
Object.assign(rectifyForm, {
|
id: null,
|
rectifyDesc: "",
|
storageBlobDTOs: []
|
});
|
rectifyFormRef.value?.clearValidate?.();
|
};
|
|
const submitRectifyForm = async () => {
|
await rectifyFormRef.value.validate();
|
if (!hasAttachments(rectifyForm.storageBlobDTOs)) {
|
ElMessage.warning("请上传整改后照片");
|
return;
|
}
|
const res = await updateInspectionHazard({
|
id: rectifyForm.id,
|
status: "已整改",
|
rectifyDesc: rectifyForm.rectifyDesc,
|
storageBlobDTOs: rectifyForm.storageBlobDTOs
|
});
|
if (res.code === 200) {
|
ElMessage.success("整改成功");
|
rectifyFormVisible.value = false;
|
if (currentInspectionId.value) {
|
fetchHazards(currentInspectionId.value);
|
}
|
getList();
|
} else {
|
ElMessage.error(res.msg || "整改失败");
|
}
|
};
|
|
const canRectify = row => {
|
return Number(row?.rectifyUserId) === currentUserId.value;
|
};
|
|
const confirmDelete = (message, onConfirm) => {
|
ElMessageBox.confirm(message, "删除", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning"
|
})
|
.then(onConfirm)
|
.catch(() => {});
|
};
|
|
const handleDeleteResult = res => {
|
if (res.code === 200) {
|
ElMessage.success("删除成功");
|
selectedIds.value = [];
|
getList();
|
} else {
|
ElMessage.error(res.msg || "删除失败");
|
}
|
};
|
|
const cleanParams = params => {
|
return Object.fromEntries(
|
Object.entries(params).filter(([, value]) => value !== "" && value !== null && value !== undefined)
|
);
|
};
|
|
const getInspectionStatusType = status => {
|
const map = {
|
待巡检: "info",
|
巡检中: "warning",
|
待整改: "danger",
|
已完成: "success"
|
};
|
return map[status] || "info";
|
};
|
|
const getInspectionResultType = result => {
|
const map = {
|
正常: "success",
|
异常: "danger"
|
};
|
return map[result] || "info";
|
};
|
|
const getHazardStatusType = status => {
|
const map = {
|
待整改: "danger",
|
整改中: "warning",
|
已整改: "success"
|
};
|
return map[status] || "info";
|
};
|
|
const getRiskLevelType = level => {
|
const map = {
|
重大风险: "danger",
|
较大风险: "warning",
|
一般风险: "primary",
|
低风险: "info",
|
重大: "danger",
|
一般: "warning"
|
};
|
return map[level] || "info";
|
};
|
|
const getInspectorNames = row => {
|
if (Array.isArray(row.inspector)) {
|
return row.inspector.filter(Boolean);
|
}
|
if (!row.inspectorName && row.inspectorId) {
|
return parseInspectorIds(row.inspectorId)
|
.map(id => userList.value.find(user => Number(user.userId) === Number(id))?.nickName)
|
.filter(Boolean);
|
}
|
return String(row.inspectorName || "")
|
.split(",")
|
.map(item => item.trim())
|
.filter(Boolean);
|
};
|
|
const parseInspectorIds = inspectorId => {
|
return String(inspectorId || "")
|
.split(",")
|
.map(item => Number(item.trim()))
|
.filter(item => !Number.isNaN(item));
|
};
|
|
const formatFrequencyDetail = value => {
|
if (!value) {
|
return "--";
|
}
|
return String(value).replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => weekLabelMap[match] || match);
|
};
|
|
const getAttachments = row => row?.storageBlobDTOs || row?.storageBlobVOs || [];
|
const hasAttachments = attachments => Array.isArray(attachments) && attachments.length > 0;
|
const getAttachmentPreviewUrl = row => row?.previewURL || row?.previewUrl || row?.url || row?.downloadURL || row?.downloadUrl || "";
|
const getAttachmentPreviewUrls = row => getAttachments(row).map(getAttachmentPreviewUrl).filter(Boolean);
|
|
const formatDateTime = date => {
|
const pad = value => String(value).padStart(2, "0");
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
};
|
|
const setDialogFixedHeight = () => {
|
setTimeout(() => {
|
const dialogs = document.body.querySelectorAll(".el-dialog");
|
const dialog = dialogs[dialogs.length - 1];
|
if (!dialog) return;
|
Object.assign(dialog.style, {
|
height: "70vh",
|
maxHeight: "70vh",
|
overflow: "hidden",
|
display: "flex",
|
flexDirection: "column"
|
});
|
const body = dialog.querySelector(".el-dialog__body");
|
if (body) {
|
Object.assign(body.style, { flex: "1", overflow: "hidden" });
|
}
|
const wrapper = dialog.querySelector(".dialog-table-wrapper");
|
if (wrapper) {
|
Object.assign(wrapper.style, { flex: "1", overflowY: "auto" });
|
}
|
}, 100);
|
};
|
|
const onRecordDialogOpen = () => setDialogFixedHeight();
|
const onHazardDialogOpen = () => setDialogFixedHeight();
|
</script>
|
|
<style scoped>
|
.line-inspection-page :deep(.table_list) {
|
width: 100%;
|
}
|
|
.module-tabs {
|
display: flex;
|
align-items: center;
|
gap: 42px;
|
min-height: 58px;
|
margin-bottom: 16px;
|
padding: 0 28px;
|
border-bottom: 1px solid #d7e2f1;
|
}
|
|
.module-tab {
|
position: relative;
|
border: 0;
|
background: transparent;
|
color: #1f2d3d;
|
font-size: 16px;
|
line-height: 58px;
|
cursor: pointer;
|
padding: 0;
|
}
|
|
.module-tab.active {
|
color: #003bb3;
|
font-weight: 600;
|
}
|
|
.module-tab.active::after {
|
position: absolute;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
height: 2px;
|
background: #003bb3;
|
content: "";
|
}
|
|
.line-search-panel {
|
justify-content: flex-start;
|
align-items: center;
|
gap: 16px;
|
min-height: 44px;
|
overflow: hidden;
|
}
|
|
.search-left {
|
display: flex;
|
flex: 1 1 auto;
|
flex-wrap: nowrap;
|
align-items: center;
|
gap: 14px;
|
min-width: 0;
|
padding-right: 12px;
|
}
|
|
.filter-item,
|
.filter-buttons,
|
.toolbar-actions {
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
flex: 0 0 auto;
|
}
|
|
.filter-control {
|
width: 210px;
|
}
|
|
.filter-control.is-wide {
|
width: 240px;
|
}
|
|
.filter-control.is-short {
|
width: 150px;
|
}
|
|
.table-toolbar {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
gap: 16px;
|
margin-bottom: 12px;
|
min-height: 40px;
|
}
|
|
.search_title {
|
font-size: 14px;
|
color: #606266;
|
white-space: nowrap;
|
}
|
|
.person-tags {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 4px;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.person-tag {
|
margin: 0;
|
}
|
|
.task-name-link {
|
max-width: 100%;
|
padding: 0;
|
font-weight: 600;
|
vertical-align: middle;
|
}
|
|
.task-name-link :deep(span),
|
.code-link :deep(span) {
|
display: inline-block;
|
max-width: 100%;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.code-link {
|
max-width: 100%;
|
padding: 0;
|
font-weight: 600;
|
vertical-align: middle;
|
}
|
|
.detail-section-title {
|
margin: 18px 0 10px;
|
color: #1f2d3d;
|
font-size: 15px;
|
font-weight: 600;
|
}
|
|
.history-summary {
|
margin-bottom: 14px;
|
}
|
|
.execute-summary {
|
margin-bottom: 18px;
|
}
|
|
.photo-list {
|
display: flex;
|
justify-content: center;
|
gap: 6px;
|
flex-wrap: wrap;
|
}
|
|
.record-photo {
|
width: 46px;
|
height: 46px;
|
border-radius: 4px;
|
border: 1px solid #dcdfe6;
|
}
|
|
.frequency-row {
|
display: grid;
|
grid-template-columns: 132px minmax(170px, 1fr);
|
gap: 10px;
|
width: 100%;
|
}
|
|
.frequency-day-select,
|
.frequency-time-picker {
|
width: 100%;
|
}
|
|
:deep(.frequency-detail-item .el-form-item__label) {
|
width: 72px !important;
|
flex: 0 0 72px;
|
}
|
|
.no-data {
|
color: #909399;
|
}
|
|
.mb10 {
|
margin-bottom: 10px;
|
}
|
|
.mb20 {
|
margin-bottom: 20px;
|
}
|
|
.ml10 {
|
margin-left: 10px;
|
}
|
|
@media (max-width: 1500px) {
|
.line-search-panel {
|
align-items: flex-start;
|
}
|
|
.search-left {
|
flex-wrap: wrap;
|
}
|
}
|
</style>
|