gongchunyi
2 天以前 e01f84ba06a75b2f2e77b2f59923b8f0cf10a46e
fix: 线路巡检调整
已修改2个文件
2624 ■■■■ 文件已修改
src/api/safeProduction/lineInspection.js 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safeProduction/lineInspection/index.vue 2574 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/safeProduction/lineInspection.js
@@ -4,6 +4,49 @@
 * 线路巡检API接口
 */
// 获取线路定时巡检任务列表
export function getLineInspectionTaskList(params) {
  return request({
    url: "/safeLineInspectionTask/page",
    method: "get",
    params,
  });
}
// 根据ID获取线路定时巡检任务详情
export function getLineInspectionTaskById(id) {
  return request({
    url: `/safeLineInspectionTask/${id}`,
    method: "get",
  });
}
// 新增线路定时巡检任务
export function addLineInspectionTask(data) {
  return request({
    url: "/safeLineInspectionTask",
    method: "post",
    data,
  });
}
// 修改线路定时巡检任务
export function updateLineInspectionTask(data) {
  return request({
    url: "/safeLineInspectionTask",
    method: "put",
    data,
  });
}
// 删除线路定时巡检任务
export function deleteLineInspectionTask(ids) {
  return request({
    url: "/safeLineInspectionTask/" + ids.join(","),
    method: "delete",
  });
}
// 获取线路巡检列表
export function getLineInspectionList(params) {
  return request({
@@ -47,11 +90,12 @@
  });
}
// 完成巡检
export function completeLineInspection(id) {
// 执行巡检
export function executeLineInspection(data) {
  return request({
    url: `/safeLineInspection/complete/${id}`,
    url: "/safeLineInspection/execute",
    method: "put",
    data,
  });
}
src/views/safeProduction/lineInspection/index.vue
@@ -1,100 +1,774 @@
<template>
  <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 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">
      <PIMTable rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :isSelection="true"
                @selection-change="handleSelectionChange"
                :tableLoading="tableLoading"
                @pagination="pagination"
                :total="page.total"></PIMTable>
      <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="dialogVisible"
               :title="dialogTitle"
               width="800px"
               :close-on-click-modal="false">
      <el-form ref="formRef"
               :model="form"
               :rules="rules"
               label-width="120px">
    <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="inspectionCode">
              <el-input v-model="form.inspectionCode"
                        placeholder="请输入巡检编号" />
            <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="inspectionName">
              <el-input v-model="form.inspectionName"
                        placeholder="请输入巡检名称" />
            <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="lineName">
              <el-input v-model="form.lineName"
                        placeholder="请输入线路名称" />
            <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="inspectionType">
              <el-select v-model="form.inspectionType"
                         placeholder="请选择巡检类型"
                         style="width: 100%">
            <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>
@@ -103,70 +777,80 @@
        </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 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="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-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="备注"
                      prop="remark">
          <el-input v-model="form.remark"
                    type="textarea"
                    :rows="3"
                    placeholder="请输入备注" />
        <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="submitForm">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
          <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">
    <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>
        <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="检查点" width="150" show-overflow-tooltip />
        <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 }">
@@ -175,16 +859,16 @@
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="checkDesc" label="检查说明" width="200" show-overflow-tooltip />
          <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) ? '已上传' : '未上传' }}
                {{ hasAttachments(row.storageBlobVOs) ? "已上传" : "未上传" }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="checkTime" label="检查时间" width="180" />
          <el-table-column label="操作" width="120" fixed="right">
          <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>
@@ -193,27 +877,22 @@
        </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-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 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-form-item label="检查结果" prop="checkResult">
                <el-radio-group v-model="recordForm.checkResult">
                  <el-radio label="正常">正常</el-radio>
                  <el-radio label="异常">异常</el-radio>
@@ -221,61 +900,56 @@
              </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 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-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="上传照片" />
            <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-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 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">
    <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>
        <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="隐患编号" width="120" show-overflow-tooltip />
        <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 }">
@@ -284,7 +958,7 @@
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="hazardLocation" label="隐患位置" width="150" show-overflow-tooltip />
          <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)">
@@ -292,120 +966,334 @@
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="rectifyUserName" label="整改责任人" width="120" />
          <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 type="success" link :disabled="currentInspectionStatus === '已完成'" @click="handleRectify(row)" v-if="row.status !== '已整改'">整改</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-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-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 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 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>
    <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 { Search } from "@element-plus/icons-vue";
import { onMounted, ref, reactive, toRefs } from "vue";
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,
  addLineInspection,
  getLineInspectionById,
  updateLineInspection,
  deleteLineInspection,
  completeLineInspection,
  executeLineInspection,
  getInspectionRecords,
  addInspectionRecord,
  updateInspectionRecord,
  deleteInspectionRecord,
  getInspectionHazards,
  getHazardsByInspectionId,
  addInspectionHazard,
  updateInspectionHazard
} from "@/api/safeProduction/lineInspection";
// 表单验证规则
const rules = {
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: [{ required: true, message: "请选择巡检人", trigger: "change" }]
  inspectorIds: [{ type: "array", required: true, message: "请选择巡检人", trigger: "change" }]
};
const recordRules = {
@@ -420,388 +1308,570 @@
  hazardLocation: [{ required: true, message: "请输入隐患位置", trigger: "blur" }]
};
// 响应式数据
const data = reactive({
  searchForm: {
    inspectionCode: "",
    inspectionName: "",
    lineName: "",
    status: ""
  },
  tableLoading: false,
  page: {
    current: 1,
    size: 20,
    total: 0
  },
  tableData: [],
  selectedIds: [],
  form: {
    id: null,
    inspectionCode: "",
    inspectionName: "",
    lineName: "",
    inspectionType: "",
    planTime: "",
    inspectorId: "",
    inspectorIds: [],
    remark: ""
  },
  dialogVisible: false,
  dialogTitle: "",
  dialogType: "add",
  // 巡检记录
  currentInspectionId: null,
  currentInspectionStatus: "",
  recordDialogVisible: false,
  recordFormVisible: false,
  recordList: [],
  recordForm: {
    id: null,
    inspectionId: null,
    checkPoint: "",
    checkContent: "",
    checkResult: "正常",
    checkDesc: "",
    checkTime: "",
    storageBlobDTOs: []
  },
  // 隐患管理
  hazardDialogVisible: false,
  hazardFormVisible: false,
  hazardDialogTitle: "上报隐患",
  hazardList: [],
  hazardForm: {
    id: null,
    inspectionId: null,
    hazardDesc: "",
    hazardLevel: "",
    hazardLocation: ""
  },
  rectifyFormVisible: false,
  rectifyForm: {
    id: null,
    rectifyDesc: ""
  }
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 {
  searchForm,
  tableLoading,
  page,
  tableData,
  selectedIds,
  form,
  dialogVisible,
  dialogTitle,
  dialogType,
  currentInspectionId,
  currentInspectionStatus,
  recordDialogVisible,
  recordFormVisible,
  recordList,
  recordForm,
  hazardDialogVisible,
  hazardFormVisible,
  hazardDialogTitle,
  hazardList,
  hazardForm,
  rectifyFormVisible,
  rectifyForm
} = toRefs(data);
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 formRef = ref();
const recordFormRef = ref();
const hazardFormRef = ref();
const rectifyFormRef = ref();
const userList = ref([]);
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 tableColumn = ref([
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: "inspectionCode",
    showOverflowTooltip: true,
    minWidth: 150
    label: "频次",
    prop: "frequencyType",
    minWidth: 85,
    align: "center",
    formatData: value => frequencyTypeMap[value] || value || "--"
  },
  {
    label: "巡检名称",
    prop: "inspectionName",
    showOverflowTooltip: true,
    minWidth: 180
    label: "开始日期与时间",
    prop: "frequencyDetail",
    minWidth: 150,
    align: "center",
    formatData: value => formatFrequencyDetail(value)
  },
  {
    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";
    }
  },
  { label: "下次执行时间", prop: "nextExecutionTime", minWidth: 170, showOverflowTooltip: true, align: "center" },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: "right",
    width: 350,
    width: 220,
    operation: [
      {
        name: "历史巡检",
        type: "text",
        clickFun: row => openTaskHistory(row)
      },
      {
        name: "编辑",
        type: "text",
        clickFun: row => {
          openForm("edit", row);
        },
        disabled: 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 === "巡检中"
        clickFun: row => openTaskDialog("edit", row)
      },
      {
        name: "删除",
        type: "text",
        style: { color: "#F56C6C" },
        clickFun: row => {
          handleDelete(row);
        },
        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;
    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 = () => {
const getList = async () => {
  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;
  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 pagination = obj => {
  page.value.current = obj.page;
  page.value.size = obj.limit;
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 getHazardStatusType = status => {
  const map = {
    待整改: "danger",
    整改中: "warning",
    已整改: "success"
  };
  return map[status] || "info";
const openTaskDetail = row => {
  taskDetail.value = { ...row };
  taskDetailVisible.value = true;
};
const getAttachments = row => row?.storageBlobDTOs || row?.storageBlobVOs || [];
const hasAttachments = attachments => Array.isArray(attachments) && attachments.length > 0;
const openTaskHistory = row => {
  taskHistoryTask.value = { ...row };
  taskHistoryPage.current = 1;
  taskHistoryVisible.value = true;
  fetchTaskHistory();
};
// 打开表单
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, {
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,
      inspectionCode: row.inspectionCode,
      inspectionName: row.inspectionName,
      lineName: row.lineName,
      inspectionType: row.inspectionType,
      planTime: row.planTime,
      inspectionProject: row.inspectionProject,
      inspectorId: row.inspectorId,
      inspectorIds: inspectorIds,
      inspectorIds: parseInspectorIds(row.inspectorId),
      frequencyType: row.frequencyType,
      frequencyDetail: row.frequencyDetail,
      isEnabled: row.isEnabled ?? ENABLED,
      remark: row.remark
    });
    parseFrequencyDetail(row.frequencyType, row.frequencyDetail);
  }
  dialogVisible.value = true;
  taskDialogVisible.value = true;
};
// 提交表单
const submitForm = async () => {
  try {
    await formRef.value.validate();
    // 将数组转换为逗号分隔的字符串
    const submitData = {
      ...form.value,
      inspectorId: form.value.inspectorIds ? form.value.inspectorIds.join(",") : ""
    };
    delete submitData.inspectorIds;
const resetTaskForm = () => {
  Object.assign(taskForm, createTaskForm());
  taskFormRef.value?.clearValidate?.();
};
    const api = dialogType.value === "add" ? addLineInspection : updateLineInspection;
    const res = await api(submitData);
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(dialogType.value === "add" ? "添加成功" : "更新成功");
      dialogVisible.value = false;
      ElMessage.success(taskForm.id ? "修改成功" : "新增成功");
      taskDialogVisible.value = false;
      getList();
    } else {
      ElMessage.error(res.msg || "操作失败");
    }
  } catch (error) {
    console.error("表单验证失败:", error);
    console.error("任务表单校验失败:", error);
  }
};
// 删除
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 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 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 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;
@@ -809,7 +1879,6 @@
  recordDialogVisible.value = true;
};
// 获取巡检记录
const fetchRecords = async inspectionId => {
  const res = await getInspectionRecords(inspectionId);
  if (res.code === 200) {
@@ -817,9 +1886,8 @@
  }
};
// 打开记录表单
const openRecordForm = () => {
  Object.assign(recordForm.value, {
  Object.assign(recordForm, {
    id: null,
    inspectionId: currentInspectionId.value,
    checkPoint: "",
@@ -832,9 +1900,8 @@
  recordFormVisible.value = true;
};
// 打开编辑记录表单
const openEditRecordForm = (row) => {
  Object.assign(recordForm.value, {
const openEditRecordForm = row => {
  Object.assign(recordForm, {
    id: row.id,
    inspectionId: row.inspectionId,
    checkPoint: row.checkPoint,
@@ -847,13 +1914,8 @@
  recordFormVisible.value = true;
};
// 删除巡检记录
const handleDeleteRecord = (row) => {
  ElMessageBox.confirm("确认删除该巡检记录吗?", "删除", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning"
  }).then(async () => {
const handleDeleteRecord = row => {
  confirmDelete("确认删除该巡检记录明细吗?", async () => {
    const res = await deleteInspectionRecord([row.id]);
    if (res.code === 200) {
      ElMessage.success("删除成功");
@@ -861,32 +1923,31 @@
    } else {
      ElMessage.error(res.msg || "删除失败");
    }
  }).catch(() => {});
  });
};
// 提交记录表单
const submitRecordForm = async () => {
  try {
    await recordFormRef.value.validate();
    if (recordForm.value.checkResult === "异常" && !hasAttachments(recordForm.value.storageBlobDTOs)) {
    if (recordForm.checkResult === "异常" && !hasAttachments(recordForm.storageBlobDTOs)) {
      ElMessage.warning("巡检结果异常时请上传现场照片");
      return;
    }
    const api = recordForm.value.id ? updateInspectionRecord : addInspectionRecord;
    const res = await api({ ...recordForm.value });
    const api = recordForm.id ? updateInspectionRecord : addInspectionRecord;
    const res = await api({ ...recordForm });
    if (res.code === 200) {
      ElMessage.success(recordForm.value.id ? "修改成功" : "添加成功");
      ElMessage.success(recordForm.id ? "修改成功" : "添加成功");
      recordFormVisible.value = false;
      fetchRecords(currentInspectionId.value);
      getList();
    } else {
      ElMessage.error(res.msg || "操作失败");
    }
  } catch (error) {
    console.error("表单验证失败:", error);
    console.error("巡检记录明细表单校验失败:", error);
  }
};
// 打开隐患管理弹窗
const openHazardDialog = row => {
  currentInspectionId.value = row.id;
  currentInspectionStatus.value = row.status;
@@ -894,7 +1955,6 @@
  hazardDialogVisible.value = true;
};
// 获取隐患列表
const fetchHazards = async inspectionId => {
  const res = await getHazardsByInspectionId(inspectionId);
  if (res.code === 200) {
@@ -902,11 +1962,10 @@
  }
};
// 打开隐患表单
const openHazardForm = (type, row = null) => {
  if (type === "add") {
    hazardDialogTitle.value = "上报隐患";
    Object.assign(hazardForm.value, {
    Object.assign(hazardForm, {
      id: null,
      inspectionId: currentInspectionId.value,
      hazardDesc: "",
@@ -915,7 +1974,7 @@
    });
  } else {
    hazardDialogTitle.value = "编辑隐患";
    Object.assign(hazardForm.value, {
    Object.assign(hazardForm, {
      id: row.id,
      inspectionId: row.inspectionId,
      hazardDesc: row.hazardDesc,
@@ -926,12 +1985,11 @@
  hazardFormVisible.value = true;
};
// 提交隐患表单
const submitHazardForm = async () => {
  try {
    await hazardFormRef.value.validate();
    const api = hazardForm.value.id ? updateInspectionHazard : addInspectionHazard;
    const res = await api({ ...hazardForm.value });
    const api = hazardForm.id ? updateInspectionHazard : addInspectionHazard;
    const res = await api({ ...hazardForm });
    if (res.code === 200) {
      ElMessage.success("操作成功");
      hazardFormVisible.value = false;
@@ -940,40 +1998,370 @@
      ElMessage.error(res.msg || "操作失败");
    }
  } catch (error) {
    console.error("表单验证失败:", error);
    console.error("隐患表单校验失败:", error);
  }
};
// 整改
const handleRectify = row => {
  Object.assign(rectifyForm.value, {
  if (!canRectify(row)) {
    ElMessage.warning("只有整改责任人可以进行整改");
    return;
  }
  currentInspectionId.value = row.inspectionId || currentInspectionId.value;
  Object.assign(rectifyForm, {
    id: row.id,
    rectifyDesc: ""
    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.value.id,
    id: rectifyForm.id,
    status: "已整改",
    rectifyDesc: rectifyForm.value.rectifyDesc
    rectifyDesc: rectifyForm.rectifyDesc,
    storageBlobDTOs: rectifyForm.storageBlobDTOs
  });
  if (res.code === 200) {
    ElMessage.success("整改成功");
    rectifyFormVisible.value = false;
    fetchHazards(currentInspectionId.value);
    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 {
@@ -987,4 +2375,14 @@
.ml10 {
  margin-left: 10px;
}
@media (max-width: 1500px) {
  .line-search-panel {
    align-items: flex-start;
  }
  .search-left {
    flex-wrap: wrap;
  }
}
</style>