| | |
| | | <template> |
| | | <div class="line-inspection"> |
| | | <!-- 搜索区域 --> |
| | | <div class="search-area"> |
| | | <el-form :inline="true" :model="searchForm"> |
| | | <el-form-item label="任务名称"> |
| | | <el-input v-model="searchForm.taskName" placeholder="请输入任务名称" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="线路名称"> |
| | | <el-input v-model="searchForm.routeName" placeholder="请输入线路名称" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="巡检人"> |
| | | <el-input v-model="searchForm.inspector" placeholder="请输入巡检人" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="状态"> |
| | | <el-select v-model="searchForm.status" placeholder="请选择状态" clearable> |
| | | <el-option label="待巡检" value="待巡检" /> |
| | | <el-option label="进行中" value="进行中" /> |
| | | <el-option label="已完成" value="已完成" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch">搜索</el-button> |
| | | <el-button @click="resetSearch">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">巡检编号:</span> |
| | | <el-input v-model="searchForm.inspectionCode" |
| | | style="width: 200px" |
| | | placeholder="请输入巡检编号" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">巡检名称:</span> |
| | | <el-input v-model="searchForm.inspectionName" |
| | | style="width: 200px" |
| | | placeholder="请输入巡检名称" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">线路名称:</span> |
| | | <el-input v-model="searchForm.lineName" |
| | | style="width: 200px" |
| | | placeholder="请输入线路名称" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">状态:</span> |
| | | <el-select v-model="searchForm.status" |
| | | clearable |
| | | @change="handleQuery" |
| | | style="width: 150px"> |
| | | <el-option label="待巡检" value="待巡检" /> |
| | | <el-option label="巡检中" value="巡检中" /> |
| | | <el-option label="已完成" value="已完成" /> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px"> |
| | | 搜索 |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">新增巡检任务</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <div class="actions"> |
| | | <el-button type="primary" @click="handleAdd">新增巡检</el-button> |
| | | <el-button type="success" @click="handleExport">导出</el-button> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | |
| | | <!-- 巡检列表 --> |
| | | <el-table :data="inspectionList" style="width: 100%; margin-top: 10px;" border> |
| | | <el-table-column prop="taskName" label="任务名称" width="180" /> |
| | | <el-table-column prop="routeName" label="线路名称" width="180" /> |
| | | <el-table-column prop="deviceName" label="关联设备" width="150" /> |
| | | <el-table-column prop="inspector" label="巡检人" width="120" /> |
| | | <el-table-column prop="inspectionTime" label="巡检时间" width="180" /> |
| | | <el-table-column prop="inspectionResult" label="巡检结果" width="120"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="row.inspectionResult === '正常' ? 'success' : 'danger'"> |
| | | {{ row.inspectionResult || '未巡检' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="状态" width="120"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getStatusType(row.status)"> |
| | | {{ row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="200" fixed="right"> |
| | | <template #default="{ row }"> |
| | | <el-button type="primary" link @click="handleEdit(row)">编辑</el-button> |
| | | <el-button type="danger" link @click="handleDelete(row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- 分页 --> |
| | | <div class="pagination"> |
| | | <el-pagination |
| | | v-model:current-page="pagination.currentPage" |
| | | v-model:page-size="pagination.pageSize" |
| | | :page-sizes="[10, 20, 50, 100]" |
| | | :total="pagination.total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- 新增/编辑对话框 --> |
| | | <el-dialog :title="dialogTitle" v-model="showDialog" width="600px"> |
| | | <el-form :model="form" :rules="formRules" ref="formRef" label-width="100px"> |
| | | <el-form-item label="任务名称" prop="taskName"> |
| | | <el-input v-model="form.taskName" placeholder="请输入任务名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="线路名称" prop="routeName"> |
| | | <el-input v-model="form.routeName" placeholder="请输入线路名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="关联设备"> |
| | | <el-select v-model="form.deviceId" placeholder="请选择设备" clearable> |
| | | <el-option |
| | | v-for="item in deviceOptions" |
| | | :key="item.id" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="巡检人" prop="inspector"> |
| | | <el-input v-model="form.inspector" placeholder="请输入巡检人" /> |
| | | </el-form-item> |
| | | <el-form-item label="巡检时间"> |
| | | <el-date-picker |
| | | v-model="form.inspectionTime" |
| | | type="datetime" |
| | | placeholder="请选择巡检时间" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="巡检结果"> |
| | | <el-radio-group v-model="form.inspectionResult"> |
| | | <el-radio label="正常">正常</el-radio> |
| | | <el-radio label="异常">异常</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="隐患描述" v-if="form.inspectionResult === '异常'"> |
| | | <el-input type="textarea" v-model="form.hazardDescription" placeholder="请输入隐患描述" /> |
| | | </el-form-item> |
| | | <el-form-item label="备注"> |
| | | <el-input type="textarea" v-model="form.remarks" placeholder="请输入备注" /> |
| | | <!-- 新增/编辑巡检任务弹窗 --> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="800px" |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="巡检编号" |
| | | prop="inspectionCode"> |
| | | <el-input v-model="form.inspectionCode" |
| | | placeholder="请输入巡检编号" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="巡检名称" |
| | | prop="inspectionName"> |
| | | <el-input v-model="form.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="form.lineName" |
| | | placeholder="请输入线路名称" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="巡检类型" |
| | | prop="inspectionType"> |
| | | <el-select v-model="form.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="form.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="inspectorId"> |
| | | <el-select v-model="form.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="备注" |
| | | prop="remark"> |
| | | <el-input v-model="form.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入备注" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确定</el-button> |
| | | <el-button @click="showDialog = false">取消</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm">确定</el-button> |
| | | <el-button @click="dialogVisible = 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" |
| | | @click="openRecordForm">新增记录</el-button> |
| | | </div> |
| | | <div class="dialog-table-wrapper"> |
| | | <el-table :data="recordList" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column prop="checkPoint" label="检查点" width="150" 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="检查说明" width="200" show-overflow-tooltip /> |
| | | <el-table-column prop="checkTime" label="检查时间" width="180" /> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- 新增记录表单 --> |
| | | <el-dialog v-model="recordFormVisible" |
| | | title="新增巡检记录" |
| | | 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 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" |
| | | @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="隐患编号" 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="隐患位置" 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="整改责任人" width="120" /> |
| | | <el-table-column label="操作" width="150" fixed="right"> |
| | | <template #default="{ row }"> |
| | | <el-button type="primary" link @click="openHazardForm('edit', row)">编辑</el-button> |
| | | <el-button type="success" link @click="handleRectify(row)" v-if="row.status !== '已整改'">整改</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 v-model="rectifyFormVisible" |
| | | title="整改" |
| | | width="500px" |
| | | append-to-body |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="rectifyFormRef" |
| | | :model="rectifyForm" |
| | | 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> |
| | | <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> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { nextTick, onMounted, ref, reactive, toRefs } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { |
| | | getLineInspectionList, |
| | | addOrEditLineInspection, |
| | | addLineInspection, |
| | | updateLineInspection, |
| | | deleteLineInspection, |
| | | exportLineInspection |
| | | } from '@/api/safeProduction/lineInspection' |
| | | import { getDeviceLedger } from '@/api/equipmentManagement/ledger' |
| | | |
| | | // 搜索表单 |
| | | const searchForm = reactive({ |
| | | taskName: '', |
| | | routeName: '', |
| | | inspector: '', |
| | | status: '' |
| | | }) |
| | | |
| | | // 分页数据 |
| | | const pagination = reactive({ |
| | | currentPage: 1, |
| | | pageSize: 10, |
| | | total: 0 |
| | | }) |
| | | |
| | | // 列表数据 |
| | | const inspectionList = ref([]) |
| | | |
| | | // 设备选项 |
| | | const deviceOptions = ref([]) |
| | | |
| | | // 对话框状态 |
| | | const showDialog = ref(false) |
| | | const dialogTitle = ref('新增巡检') |
| | | |
| | | // 表单数据 |
| | | const form = reactive({ |
| | | id: null, |
| | | taskName: '', |
| | | routeName: '', |
| | | deviceId: null, |
| | | inspector: '', |
| | | inspectionTime: '', |
| | | inspectionResult: '', |
| | | hazardDescription: '', |
| | | remarks: '' |
| | | }) |
| | | completeLineInspection, |
| | | getInspectionRecords, |
| | | addInspectionRecord, |
| | | getHazardsByInspectionId, |
| | | addInspectionHazard, |
| | | updateInspectionHazard |
| | | } from "@/api/safeProduction/lineInspection"; |
| | | |
| | | // 表单验证规则 |
| | | const formRules = reactive({ |
| | | taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }], |
| | | routeName: [{ required: true, message: '请输入线路名称', trigger: 'blur' }], |
| | | inspector: [{ required: true, message: '请输入巡检人', trigger: 'blur' }] |
| | | }) |
| | | const rules = { |
| | | inspectionCode: [{ required: true, message: "请输入巡检编号", trigger: "blur" }], |
| | | inspectionName: [{ required: true, message: "请输入巡检名称", trigger: "blur" }], |
| | | lineName: [{ required: true, message: "请输入线路名称", trigger: "blur" }] |
| | | }; |
| | | |
| | | const formRef = ref(null) |
| | | const recordRules = { |
| | | checkPoint: [{ required: true, message: "请输入检查点", trigger: "blur" }], |
| | | checkContent: [{ required: true, message: "请输入检查内容", trigger: "blur" }], |
| | | checkResult: [{ required: true, message: "请选择检查结果", trigger: "change" }] |
| | | }; |
| | | |
| | | // 获取状态标签类型 |
| | | const getStatusType = (status) => { |
| | | const map = { |
| | | '待巡检': 'info', |
| | | '进行中': 'warning', |
| | | '已完成': 'success' |
| | | } |
| | | return map[status] || 'info' |
| | | } |
| | | const hazardRules = { |
| | | hazardDesc: [{ required: true, message: "请输入隐患描述", trigger: "blur" }], |
| | | hazardLevel: [{ required: true, message: "请选择隐患等级", trigger: "change" }], |
| | | hazardLocation: [{ required: true, message: "请输入隐患位置", trigger: "blur" }] |
| | | }; |
| | | |
| | | // 获取巡检列表 |
| | | const fetchList = async () => { |
| | | try { |
| | | const params = { |
| | | ...searchForm, |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize |
| | | } |
| | | const res = await getLineInspectionList(params) |
| | | if (res.code === 200) { |
| | | inspectionList.value = res.data.records || [] |
| | | pagination.total = res.data.total || 0 |
| | | } else { |
| | | ElMessage.error(res.message || '获取列表失败') |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('获取列表失败') |
| | | } |
| | | } |
| | | |
| | | // 获取设备列表 |
| | | const fetchDeviceOptions = async () => { |
| | | try { |
| | | const res = await getDeviceLedger() |
| | | if (res.code === 200) { |
| | | deviceOptions.value = res.data || [] |
| | | } |
| | | } catch (error) { |
| | | console.error('获取设备列表失败') |
| | | } |
| | | } |
| | | |
| | | // 搜索 |
| | | const handleSearch = () => { |
| | | pagination.currentPage = 1 |
| | | fetchList() |
| | | } |
| | | |
| | | // 重置搜索 |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | taskName: '', |
| | | routeName: '', |
| | | inspector: '', |
| | | status: '' |
| | | }) |
| | | handleSearch() |
| | | } |
| | | |
| | | // 新增 |
| | | const handleAdd = () => { |
| | | dialogTitle.value = '新增巡检' |
| | | Object.assign(form, { |
| | | // 响应式数据 |
| | | const data = reactive({ |
| | | searchForm: { |
| | | inspectionCode: "", |
| | | inspectionName: "", |
| | | lineName: "", |
| | | status: "" |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0 |
| | | }, |
| | | tableData: [], |
| | | selectedIds: [], |
| | | form: { |
| | | id: null, |
| | | taskName: '', |
| | | routeName: '', |
| | | deviceId: null, |
| | | inspector: '', |
| | | inspectionTime: '', |
| | | inspectionResult: '', |
| | | hazardDescription: '', |
| | | remarks: '' |
| | | }) |
| | | showDialog.value = true |
| | | } |
| | | |
| | | // 编辑 |
| | | const handleEdit = (row) => { |
| | | dialogTitle.value = '编辑巡检' |
| | | Object.assign(form, { |
| | | id: row.id, |
| | | taskName: row.taskName, |
| | | routeName: row.routeName, |
| | | deviceId: row.deviceId, |
| | | inspector: row.inspector, |
| | | inspectionTime: row.inspectionTime, |
| | | inspectionResult: row.inspectionResult, |
| | | hazardDescription: row.hazardDescription, |
| | | remarks: row.remarks |
| | | }) |
| | | showDialog.value = true |
| | | } |
| | | |
| | | // 删除 |
| | | const handleDelete = async (row) => { |
| | | try { |
| | | await ElMessageBox.confirm('确认删除该巡检记录吗?', '提示', { |
| | | type: 'warning' |
| | | }) |
| | | const res = await deleteLineInspection([row.id]) |
| | | if (res.code === 200) { |
| | | ElMessage.success('删除成功') |
| | | fetchList() |
| | | } else { |
| | | ElMessage.error(res.message || '删除失败') |
| | | } |
| | | } catch (error) { |
| | | // 取消删除 |
| | | inspectionCode: "", |
| | | inspectionName: "", |
| | | lineName: "", |
| | | inspectionType: "", |
| | | planTime: "", |
| | | inspectorId: "", |
| | | inspectorIds: [], |
| | | remark: "" |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | // 巡检记录 |
| | | currentInspectionId: null, |
| | | recordDialogVisible: false, |
| | | recordFormVisible: false, |
| | | recordList: [], |
| | | recordForm: { |
| | | inspectionId: null, |
| | | checkPoint: "", |
| | | checkContent: "", |
| | | checkResult: "正常", |
| | | checkDesc: "", |
| | | checkTime: "" |
| | | }, |
| | | // 隐患管理 |
| | | hazardDialogVisible: false, |
| | | hazardFormVisible: false, |
| | | hazardDialogTitle: "上报隐患", |
| | | hazardList: [], |
| | | hazardForm: { |
| | | id: null, |
| | | inspectionId: null, |
| | | hazardDesc: "", |
| | | hazardLevel: "", |
| | | hazardLocation: "" |
| | | }, |
| | | rectifyFormVisible: false, |
| | | rectifyForm: { |
| | | id: null, |
| | | rectifyDesc: "" |
| | | } |
| | | } |
| | | }); |
| | | |
| | | const { |
| | | searchForm, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | selectedIds, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | currentInspectionId, |
| | | recordDialogVisible, |
| | | recordFormVisible, |
| | | recordList, |
| | | recordForm, |
| | | hazardDialogVisible, |
| | | hazardFormVisible, |
| | | hazardDialogTitle, |
| | | hazardList, |
| | | hazardForm, |
| | | rectifyFormVisible, |
| | | rectifyForm |
| | | } = toRefs(data); |
| | | |
| | | // 表单引用 |
| | | const formRef = ref(); |
| | | const recordFormRef = ref(); |
| | | const hazardFormRef = ref(); |
| | | const rectifyFormRef = ref(); |
| | | const userList = ref([]); |
| | | |
| | | // 表格列配置 |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "巡检编号", |
| | | prop: "inspectionCode", |
| | | showOverflowTooltip: true, |
| | | minWidth: 150 |
| | | }, |
| | | { |
| | | label: "巡检名称", |
| | | prop: "inspectionName", |
| | | showOverflowTooltip: true, |
| | | minWidth: 180 |
| | | }, |
| | | { |
| | | label: "线路名称", |
| | | prop: "lineName", |
| | | showOverflowTooltip: true, |
| | | minWidth: 150 |
| | | }, |
| | | { |
| | | label: "巡检类型", |
| | | prop: "inspectionType", |
| | | showOverflowTooltip: true, |
| | | minWidth: 100 |
| | | }, |
| | | { |
| | | label: "计划巡检时间", |
| | | prop: "planTime", |
| | | showOverflowTooltip: true, |
| | | minWidth: 180 |
| | | }, |
| | | { |
| | | label: "巡检人", |
| | | prop: "inspectorName", |
| | | showOverflowTooltip: true, |
| | | minWidth: 100 |
| | | }, |
| | | { |
| | | label: "状态", |
| | | prop: "status", |
| | | minWidth: 100, |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | const typeMap = { |
| | | 待巡检: "info", |
| | | 巡检中: "warning", |
| | | 已完成: "success" |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 350, |
| | | operation: [ |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | show: row => row.status === "待巡检" |
| | | }, |
| | | { |
| | | name: "巡检记录", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openRecordDialog(row); |
| | | } |
| | | }, |
| | | { |
| | | name: "隐患管理", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openHazardDialog(row); |
| | | } |
| | | }, |
| | | { |
| | | name: "完成巡检", |
| | | type: "text", |
| | | style: { color: "#67C23A" }, |
| | | clickFun: row => { |
| | | handleComplete(row); |
| | | }, |
| | | show: row => row.status === "巡检中" |
| | | }, |
| | | { |
| | | name: "删除", |
| | | type: "text", |
| | | style: { color: "#F56C6C" }, |
| | | clickFun: row => { |
| | | handleDelete(row); |
| | | }, |
| | | show: row => row.status === "待巡检" |
| | | } |
| | | ] |
| | | } |
| | | ]); |
| | | |
| | | // 生命周期 |
| | | onMounted(() => { |
| | | getList(); |
| | | userListNoPage().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | }); |
| | | |
| | | // 弹窗固定高度处理 |
| | | const setDialogFixedHeight = () => { |
| | | setTimeout(() => { |
| | | // 直接在 body 上找所有 el-dialog(teleport 渲染到 body) |
| | | 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 recordDialogRef = ref(null); |
| | | const hazardDialogRef = ref(null); |
| | | |
| | | const onRecordDialogOpen = () => setDialogFixedHeight(); |
| | | const onHazardDialogOpen = () => setDialogFixedHeight(); |
| | | const handleQuery = () => { |
| | | page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | getLineInspectionList({ ...page.value, ...searchForm.value }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.value.total = res.data.total; |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // 分页处理 |
| | | const pagination = obj => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | // 选择变化处理 |
| | | const handleSelectionChange = selection => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | // 获取隐患状态类型 |
| | | const getHazardStatusType = status => { |
| | | const map = { |
| | | 待整改: "danger", |
| | | 整改中: "warning", |
| | | 已整改: "success" |
| | | }; |
| | | return map[status] || "info"; |
| | | }; |
| | | |
| | | // 打开表单 |
| | | const openForm = (type, row = null) => { |
| | | dialogType.value = type; |
| | | if (type === "add") { |
| | | dialogTitle.value = "新增巡检任务"; |
| | | Object.assign(form.value, { |
| | | id: null, |
| | | inspectionCode: "", |
| | | inspectionName: "", |
| | | lineName: "", |
| | | inspectionType: "", |
| | | planTime: "", |
| | | inspectorId: "", |
| | | inspectorIds: [], |
| | | remark: "" |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "编辑巡检任务"; |
| | | // 将逗号分隔的ID字符串转换为数组 |
| | | const inspectorIds = row.inspectorId |
| | | ? row.inspectorId.split(",").map(id => parseInt(id.trim())).filter(id => !isNaN(id)) |
| | | : []; |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | inspectionCode: row.inspectionCode, |
| | | inspectionName: row.inspectionName, |
| | | lineName: row.lineName, |
| | | inspectionType: row.inspectionType, |
| | | planTime: row.planTime, |
| | | inspectorId: row.inspectorId, |
| | | inspectorIds: inspectorIds, |
| | | remark: row.remark |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // 提交表单 |
| | | const submitForm = async () => { |
| | | if (!formRef.value) return |
| | | try { |
| | | await formRef.value.validate() |
| | | const res = await addOrEditLineInspection(form) |
| | | await formRef.value.validate(); |
| | | // 将数组转换为逗号分隔的字符串 |
| | | const submitData = { |
| | | ...form.value, |
| | | inspectorId: form.value.inspectorIds ? form.value.inspectorIds.join(",") : "" |
| | | }; |
| | | delete submitData.inspectorIds; |
| | | |
| | | const api = dialogType.value === "add" ? addLineInspection : updateLineInspection; |
| | | const res = await api(submitData); |
| | | if (res.code === 200) { |
| | | ElMessage.success('操作成功') |
| | | showDialog.value = false |
| | | fetchList() |
| | | ElMessage.success(dialogType.value === "add" ? "添加成功" : "更新成功"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } else { |
| | | ElMessage.error(res.message || '操作失败') |
| | | ElMessage.error(res.msg || "操作失败"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('请填写完整表单信息') |
| | | console.error("表单验证失败:", error); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 导出 |
| | | const handleExport = async () => { |
| | | // 删除 |
| | | const handleDelete = row => { |
| | | ElMessageBox.confirm("确认删除该巡检任务吗?", "删除", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }) |
| | | .then(async () => { |
| | | const res = await deleteLineInspection([row.id]); |
| | | if (res.code === 200) { |
| | | ElMessage.success("删除成功"); |
| | | getList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "删除失败"); |
| | | } |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // 完成巡检 |
| | | const handleComplete = row => { |
| | | ElMessageBox.confirm("确认完成该巡检任务吗?", "完成巡检", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }) |
| | | .then(async () => { |
| | | const res = await completeLineInspection(row.id); |
| | | if (res.code === 200) { |
| | | ElMessage.success("巡检已完成"); |
| | | getList(); |
| | | } else { |
| | | ElMessage.error(res.msg || "操作失败"); |
| | | } |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // 打开巡检记录弹窗 |
| | | const openRecordDialog = row => { |
| | | currentInspectionId.value = row.id; |
| | | 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.value, { |
| | | inspectionId: currentInspectionId.value, |
| | | checkPoint: "", |
| | | checkContent: "", |
| | | checkResult: "正常", |
| | | checkDesc: "", |
| | | checkTime: "" |
| | | }); |
| | | recordFormVisible.value = true; |
| | | }; |
| | | |
| | | // 提交记录表单 |
| | | const submitRecordForm = async () => { |
| | | try { |
| | | const res = await exportLineInspection(searchForm) |
| | | const blob = new Blob([res]) |
| | | const url = window.URL.createObjectURL(blob) |
| | | const link = document.createElement('a') |
| | | link.href = url |
| | | link.download = '线路巡检记录.xlsx' |
| | | link.click() |
| | | window.URL.revokeObjectURL(url) |
| | | ElMessage.success('导出成功') |
| | | await recordFormRef.value.validate(); |
| | | const res = await addInspectionRecord({ ...recordForm.value }); |
| | | if (res.code === 200) { |
| | | ElMessage.success("添加成功"); |
| | | recordFormVisible.value = false; |
| | | fetchRecords(currentInspectionId.value); |
| | | } else { |
| | | ElMessage.error(res.msg || "添加失败"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('导出失败') |
| | | console.error("表单验证失败:", error); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 分页大小改变 |
| | | const handleSizeChange = (val) => { |
| | | pagination.pageSize = val |
| | | fetchList() |
| | | } |
| | | // 打开隐患管理弹窗 |
| | | const openHazardDialog = row => { |
| | | currentInspectionId.value = row.id; |
| | | fetchHazards(row.id); |
| | | hazardDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 当前页改变 |
| | | const handleCurrentChange = (val) => { |
| | | pagination.currentPage = val |
| | | fetchList() |
| | | } |
| | | // 获取隐患列表 |
| | | const fetchHazards = async inspectionId => { |
| | | const res = await getHazardsByInspectionId(inspectionId); |
| | | if (res.code === 200) { |
| | | hazardList.value = res.data || []; |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | fetchList() |
| | | fetchDeviceOptions() |
| | | }) |
| | | // 打开隐患表单 |
| | | const openHazardForm = (type, row = null) => { |
| | | if (type === "add") { |
| | | hazardDialogTitle.value = "上报隐患"; |
| | | Object.assign(hazardForm.value, { |
| | | id: null, |
| | | inspectionId: currentInspectionId.value, |
| | | hazardDesc: "", |
| | | hazardLevel: "", |
| | | hazardLocation: "" |
| | | }); |
| | | } else { |
| | | hazardDialogTitle.value = "编辑隐患"; |
| | | Object.assign(hazardForm.value, { |
| | | 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.value.id ? updateInspectionHazard : addInspectionHazard; |
| | | const res = await api({ ...hazardForm.value }); |
| | | 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 => { |
| | | Object.assign(rectifyForm.value, { |
| | | id: row.id, |
| | | rectifyDesc: "" |
| | | }); |
| | | rectifyFormVisible.value = true; |
| | | }; |
| | | |
| | | // 提交整改表单 |
| | | const submitRectifyForm = async () => { |
| | | const res = await updateInspectionHazard({ |
| | | id: rectifyForm.value.id, |
| | | status: "已整改", |
| | | rectifyDesc: rectifyForm.value.rectifyDesc |
| | | }); |
| | | if (res.code === 200) { |
| | | ElMessage.success("整改成功"); |
| | | rectifyFormVisible.value = false; |
| | | fetchHazards(currentInspectionId.value); |
| | | } else { |
| | | ElMessage.error(res.msg || "整改失败"); |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .line-inspection { |
| | | padding: 20px; |
| | | .search_title { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | |
| | | .search-area { |
| | | background: #f5f7fa; |
| | | padding: 20px; |
| | | border-radius: 4px; |
| | | margin-bottom: 15px; |
| | | .mb10 { |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .actions { |
| | | margin-bottom: 15px; |
| | | .mb20 { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .pagination { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | .ml10 { |
| | | margin-left: 10px; |
| | | } |
| | | </style> |