Prechádzať zdrojové kódy

feat:区域检查计划任务-管理员

sunqijun 3 týždňov pred
rodič
commit
988c9896fd

+ 627 - 44
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/areaCheckPlanTask/areaCheckPlanTask.vue

@@ -6,10 +6,6 @@
     <main class="safety-platform-container__main">
       <div class="search-table-container">
         <header>
-          <!-- <div style="position: relative">
-            <el-button plain class="search-table-container--button" @click="handleImport"> 导入 </el-button>
-          </div> -->
-
           <div class="act-search">
             <section class="select-box">
               <div class="select-box--item">
@@ -65,10 +61,8 @@
             <template #status="scope">
               <span>{{ AREA_CHECK_PLAN_STATUS_LABEL[String(scope.row.status)] ?? '-' }}</span>
             </template>
-            <template #needOverallDesc="scope">
-              <span>{{
-               scope.row.status === 0 ? '-' : scope.row.needOverallDesc === true ? '是' : scope.row.needOverallDesc === false ? '否' : '-'
-              }}</span>
+            <template #frequency="scope">
+              <span>{{ FREQUENCY_TO_LABEL[scope.row.frequency] ?? '-' }}</span>
             </template>
             <template #sign="scope">
             <div class="file-list">
@@ -85,21 +79,22 @@
                   </div>
                 </div>
             </template>
-            <template #needSigneeSign="scope">
+            <template #checkItemTotal="scope">
               <span>{{
-                scope.row.status === 0 ? '-' : scope.row.needSigneeSign === true ? '是' : scope.row.needSigneeSign === false ? '否' : '-'
+                scope.row.checkItemTotal ? scope.row.checkItemTotal+'项' : '-'
               }}</span>
             </template>
-            <template #startDate="scope">
-              <span>{{ scope.row.startDate ?? '-' }}</span>
+            <template #qualifiedItemNum="scope">
+              <span>{{ scope.row.qualifiedItemNum ? scope.row.qualifiedItemNum+'项' : '-' }}</span>
             </template>
-            <template #endDate="scope">
-              <span>{{ scope.row.endDate ?? '-' }}</span>
+            <template #unqualifiedItemNum="scope">
+              <span style="color:#1777ff;" v-if="scope.row.unqualifiedItemNum" @click="openUnqualifiedDialog(scope.row)">{{ scope.row.unqualifiedItemNum+'项'}}</span>
+              <span v-else>-</span>
             </template>
             <template #action="scope">
               <div class="action-container--div" style="justify-content: left">
-                <template v-if="Number(scope.row.status) === 0">
-                  <ActionButton text="查看" @click="handleView(scope.row.id)" />
+                <template >
+                  <ActionButton text="查看" @click="handleView(scope.row)" />
                 </template>
               </div>
             </template>
@@ -107,12 +102,231 @@
         </div>
       </div>
     </main>
-
+      <PreviewOnline ref="previewOnlineRef" />
+
+
+  <!-- 检查不合格数据弹窗(部门) -->
+  <el-dialog
+    v-model="showUnqualifiedDialog"
+    title="检查不合格数据"
+    width="800px"
+    destroy-on-close
+  >
+    <BasicTable
+      :tableData="unqualifiedList"
+      :tableConfig="unqualifiedTableConfig"
+      @update:pageSize="handleUnqualifiedSizeChange"
+      @update:pageNumber="handleUnqualifiedPageChange"
+    >
+      <template #action="scope">
+        <el-button
+          v-if="Number(scope.row.IsSand) == 0"
+          type="primary"
+          link
+          size="small"
+          @click="handleSandToHiddenDangerDept(scope.row)"
+        >
+          入账
+        </el-button>
+        <span v-else-if="Number(scope.row.IsSand) == 1" style="color: #999999">已入账</span>
+        <span v-else>-</span>
+      </template>
+    </BasicTable>
+  </el-dialog>
+
+  <!-- 部门端:检查记录入账隐患台账确认弹窗(仅查看提示,不真正入账) -->
+  <el-dialog
+    v-model="showSandConfirmDialogDept"
+    title="检查记录入账隐患台账"
+    width="900px"
+    destroy-on-close
+  >
+    <el-form ref="sandHiddenDangerFormRefDept" label-width="150px" :model="sandHiddenDangerFormDataDept" :rules="sandHiddenDangerFormRulesDept">
+        <el-form-item prop="typeId" label="隐患问题类别:" style="width: 70%;">
+          <el-select
+            v-model="sandHiddenDangerFormDataDept.typeId"
+            placeholder="请选择隐患问题类别"
+            filterable
+            clearable
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in dangerTypeList"
+              :key="item.id"
+              :label="item.categoryName"
+              :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="隐患问题:" prop="dangerProblem">
+            <el-input
+            v-model="sandHiddenDangerFormDataDept.dangerProblem"
+            placeholder="请输入隐患问题描述"
+            style="width: 450px"
+            />
+      </el-form-item>
+
+      <el-form-item label="问题主要原因:" prop="reasonId">
+        <el-select
+          v-model="sandHiddenDangerFormDataDept.reasonId"
+          placeholder="请选择问题主要原因"
+          clearable
+          filterable
+          style="width: 450px"
+        >
+          <el-option
+            v-for="option in REASON_OPTIONS"
+            :key="option.value"
+            :label="option.label"
+            :value="option.value"
+          />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="任务来源:" prop="taskSource">
+        <el-input
+          v-model="sandHiddenDangerFormDataDept.taskSource"
+          placeholder="如:上级检查、院内自查"
+          style="width: 450px"
+        />
+      </el-form-item>
+
+      <el-form-item label="整改要求:" prop="rectificationRequirement">
+        <el-input
+          v-model="sandHiddenDangerFormDataDept.rectificationRequirement"
+          placeholder="请输入整改要求"
+          style="width: 450px"
+        />
+      </el-form-item>
+
+      <el-form-item prop="rectificationDepartmentIds" label="整改责任部门:">
+          <el-cascader
+            ref="cascaderDeptRef"
+            v-model="sandHiddenDangerFormDataDept.rectificationDepartmentIds"
+            :options="issueDeptTree"
+            :props="cascaderDeptProp"
+            :show-all-levels="false"
+            placeholder="请选择整改责任部门"
+            filterable
+            clearable
+            style="width: 450px"
+            @change="onIssueDeptChange"
+          />
+        </el-form-item>
+
+        <el-form-item prop="rectificationResponsibleIds" label="整改负责人">
+          <el-select
+            v-model="sandHiddenDangerFormDataDept.rectificationResponsibleIds"
+            placeholder="选择整改负责人"
+            filterable
+            clearable
+            style="width: 450px"
+          >
+            <el-option
+              v-for="user in issueUserList"
+              :key="user.id"
+              :label="user.realname ?? user.username"
+              :value="user.id"
+            />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="整改日期:" prop="rectificationDeadline">
+            <el-date-picker
+            v-model="sandHiddenDangerFormDataDept.rectificationDeadline"
+            type="date"
+            value-format="YYYY-MM-DD"
+            placeholder="请选择整改日期"
+            style="width: 450px"
+            />
+      </el-form-item>
+
+      <el-form-item prop="reviewDepartmentId" label="复查人员所属部门:">
+          <el-cascader
+            ref="reviewDeptRef"
+            v-model="sandHiddenDangerFormDataDept.reviewDepartmentId"
+            :options="deptTree"
+            :props="cascaderDeptProp"
+            :show-all-levels="false"
+            placeholder="请选择复查人员所属部门"
+            filterable
+            clearable
+            style="width: 450px"
+            @change="onReviewDeptChange"
+        />
+      </el-form-item>
+
+      <el-form-item label="复查人员:" prop="reviewPersonId">
+        <el-select
+          v-model="sandHiddenDangerFormDataDept.reviewPersonId"
+          placeholder="请选择复查人员"
+          clearable
+          filterable
+          style="width: 450px"
+        >
+          <el-option
+            v-for="u in reviewUserListDept"
+            :key="u.id"
+            :label="u.realname || u.username"
+            :value="u.id"
+          />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="举一反三是否推送:" prop="isDrawLessonsPush">
+        <el-radio-group v-model="sandHiddenDangerFormDataDept.isDrawLessonsPush" >
+          <el-radio :value="0">否</el-radio>
+          <el-radio :value="1">是</el-radio>
+        </el-radio-group>
+      </el-form-item>
+
+        <el-form-item label-width="150px" v-if="sandHiddenDangerFormDataDept.isDrawLessonsPush === 1">
+            <el-input placeholder="如:上级检查、院内自查" style="width: 450px"  v-model="sandHiddenDangerFormDataDept.drawLessonsContent" />
+        </el-form-item>
+        <el-form-item prop="drawLessonsDepartmentIds" v-if="sandHiddenDangerFormDataDept.isDrawLessonsPush === 1" label="举一反三责任部门:">
+            <el-select
+                v-model="drawLessonsDeptIdsArrayDept"
+                placeholder="请选择举一反三责任部门,可多选"
+                clearable
+                filterable
+                multiple
+                collapse-tags
+                collapse-tags-tooltip
+                style="width: 450px"
+                @change="() => { sandHiddenDangerFormDataDept.drawLessonsDepartmentIds = drawLessonsDeptIdsArrayDept.join(','); }"
+                >
+                <el-option
+                    v-for="d in deptOptions"
+                    :key="d.id"
+                    :label="d.deptName"
+                    :value="d.id"
+                />
+                </el-select>
+        </el-form-item>
+        
+        <el-form-item prop="drawLessonsDeadline" label="举一反三时限:" v-if="sandHiddenDangerFormDataDept.isDrawLessonsPush === 1">
+          <el-date-picker
+            v-model="sandHiddenDangerFormDataDept.drawLessonsDeadline"
+            type="date"
+            style="width: 450px"
+            value-format="YYYY-MM-DD"
+            placeholder="请选择举一反三截止日期(选填)"
+          />
+        </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="showSandConfirmDialogDept = false">取消</el-button>
+      <el-button type="primary" :loading="sandConfirmLoadingDept" @click="confirmSandToHiddenDangerDept">
+        提交
+      </el-button>
+    </template>
+  </el-dialog>
   </div>
 </template>
 
 <script setup lang="ts">
-  import { onMounted, reactive, ref } from 'vue';
+  import { onMounted, reactive, ref, computed } from 'vue';
   import { ElMessage } from 'element-plus';
   import BasicTable from '@/components/BasicTable.vue';
   import useTableConfig from '@/hooks/useTableConfigHook';
@@ -124,13 +338,22 @@
     AREA_CHECK_PLAN_STATUS_OPTIONS,
     AREA_CHECK_PLAN_STATUS_LABEL,
   } from './configs/tables';
+  import { FREQUENCY_TO_LABEL } from './configs/form';
   import { useRouter } from 'vue-router';
   import type { QueryPageRequest } from '@/types/basic-query';
+  import type { TableColumnProps } from '@/types/basic-table';
   import type { AreaCheckPlanQuery, AreaCheckPlanRecord } from './configs/types';
   import {
     queryAreaCheckPlanDetailPage,
+    queryAreaInspectionPlanTask,
+    queryAreaCheckPlanDetailDeptPage,
+    queryUnqualifiedItemNumDeptPage,
     mapAreaCheckPlanApiRecordToUi,
     exportAreaCheckPlanAdministration,
+    sandAreaCheckRecordToProductionHiddenDanger,
+    exportRegionalInspectionPlanTaskDepartmentData,
+    type UnqualifiedItemNumRecord,
+    type SandAreaCheckRecordToHiddenDangerReq,
   } from '@/api/production-safety-system';
   import { getAllDepartments } from '@/api/auth/dept';
   import type { DeptTree } from '@/types/dept/type';
@@ -141,8 +364,16 @@
   import urlJoin from 'url-join';
   import { downloadByData } from '@/utils/file/download';
   import { downloadFile } from '@/views/disaster/utils';
+  import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
+  import {
+    queryDangerTypePage,
+  } from '@/api/production-safety';
+  import { queryAvailableUserList } from '@/api/production-safety/responsibility-implementation';
+  import BasicForm from '@/components/BasicForm.vue';
+  import type { CascaderInstance } from 'element-plus'
+  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
+  import { HIDDEN_DANGER_FORM_CONFIG, HIDDEN_DANGER_FORM_RULES, REASON_OPTIONS, HIDDEN_DANGER_FORM_DATA } from "./configs/form"
   const router = useRouter();
-
   const basicTableRef = ref<InstanceType<typeof BasicTable>>();
   const { tableConfig, pagination } = useTableConfig(AREA_CHECK_PLAN_TABLE_COLUMNS, TABLE_OPTIONS);
   const tableData = ref<AreaCheckPlanRecord[]>([]);
@@ -151,10 +382,8 @@
   // 场所所属类别选项(示例数据,本页面不调用接口)
   const venueCategoryOptions = ref<Array<{ label: string; value: string }>>([]);
 
-
-
-
-
+    // 预览
+  const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
   const previewOnline = (url: string | undefined, type) => {
     if (url) {
       previewOnlineRef.value?.open(url, type);
@@ -162,20 +391,14 @@
   };
 
 
-
-
-
-
-
   const tableQuery = reactive<QueryPageRequest<AreaCheckPlanQuery>>({
     pageNumber: pagination.pageNumber,
     pageSize: pagination.pageSize,
     queryParam: {
       searchKey: '',
-      status: '' as AreaCheckPlanQuery['status'],
-      venueCategory: '',
       startDate: '',
       endDate: '',
+      status: '' as AreaCheckPlanQuery['status'],
     },
   });
 
@@ -190,19 +413,32 @@
     tableQuery.pageNumber = value;
     getTableData();
   };
+  // 判断是否有值, 如果有值就转换成JSON.parse
+  const safeJsonParse = (str) => {
+  // 判断是否有有效值
+  if (str === null || str === undefined || str.trim() === '') {
+    return [];
+  }
+
+  try {
+    return JSON.parse(str);
+  } catch (e) {
+    console.warn('JSON 解析失败:', e);
+    return [];
+  }
+}
 
   async function getTableData() {
     tableConfig.loading = true;
     try {
-      const res = await queryAreaCheckPlanDetailPage({
-        pageNumber: tableQuery.pageNumber,
-        pageSize: tableQuery.pageSize,
-        queryParam: tableQuery.queryParam,
-      });
-      const raw = (res as { data?: { records?: unknown[]; totalRow?: number } })?.data ?? res;
-      const list = raw?.records ?? [];
-      tableData.value = list.map((r: unknown) => mapAreaCheckPlanApiRecordToUi(r));
-      pagination.total = raw?.totalRow ?? 0;
+      const res = await queryAreaInspectionPlanTask(tableQuery);
+      const list = res?.records ?? [];
+      tableData.value = list.map(item=>{
+        // 附件转换格式
+          item.checkedPersonSign = safeJsonParse(item.checkedPersonSign);
+          return item;
+      })
+      pagination.total = res?.totalRow ?? 0;
     } catch (e) {
       console.error('查询区域检查计划列表失败:', e);
       tableData.value = [];
@@ -228,7 +464,6 @@
   const handleReset = () => {
     tableQuery.queryParam.searchKey = '';
     tableQuery.queryParam.status = '';
-    tableQuery.queryParam.venueCategory = '';
     tableQuery.queryParam.startDate = '';
     tableQuery.queryParam.endDate = '';
     dateRange.value = null;
@@ -237,19 +472,34 @@
 
 
 
-  const handleView = (id: number) => {
+  const handleView = (row) => {
     router.push({
-      name: 'areaCheckPlanTaskItem',
-      query: { id, operate: 'area-check-plan-view' },
+      name: 'areaCheckPlanTaskDeptItem',
+      query: { 
+        recordId: row.id, 
+        planId: row.areaPlanId,
+        checkType: row.checkType, 
+        operate: 'area-check-plan-view' 
+      },
     });
   };
 
+  const handleCheck = (row: any) => {
+    router.push({
+      name: 'areaCheckPlanTaskDeptItem',
+      query: { 
+        recordId: row.id,
+        planId: row.areaPlanId,
+        checkType: row.checkType, // 传递检查类型,后续根据检查类型区分检查项来源
+        operate: 'area-check-plan-create' },
+    });
+  };
 
 
 
   const handleDownload = async () => {
     try {
-      const response = await exportAreaCheckPlanAdministration(tableQuery.queryParam);
+      const response = await exportRegionalInspectionPlanTaskDepartmentData(tableQuery.queryParam);
       if (response) {
         const fileName = `区域检查计划任务_${new Date().toISOString().split('T')[0]}.xlsx`;
         downloadByData(response, fileName);
@@ -296,7 +546,334 @@
       { label: '室内外停车场', value: '室内外停车场' },
     ];
     getTableData();
+    onIssueDialogOpen();
   });
+
+
+
+  // 检查不合格数据弹窗
+  const showUnqualifiedDialog = ref(false);
+  const currentRecordIdForUnqualified = ref<number | null>(null);
+  const currentRowForUnqualified = ref<Record<string, unknown> | null>(null);
+  const unqualifiedList = ref<UnqualifiedItemNumRecord[]>([]);
+  const UNQUALIFIED_TABLE_COLUMNS: TableColumnProps[] = [
+    { label: '编号', type: 'index', align: 'center', width: '80px' },
+    { label: '检查场所', prop: 'checkPlace', minWidth: '200px' },
+    { label: '发现问题', prop: 'checkProblem', minWidth: '220px' },
+    { label: '检查时间', prop: 'checkTime', minWidth: '180px' },
+    { label: '操作', slot: 'action', align: 'center', width: '100px' },
+  ];
+  const UNQUALIFIED_TABLE_OPTIONS = {
+    emptyText: '暂无不合格数据',
+    loading: false,
+    maxHeight: '400px',
+    stripe: true,
+  };
+  
+  const { tableConfig: unqualifiedTableConfig, pagination: unqualifiedPagination } = useTableConfig(
+    UNQUALIFIED_TABLE_COLUMNS,
+    UNQUALIFIED_TABLE_OPTIONS,
+    true,
+  );
+
+  const RECORD_TABLE_COLUMNS: TableColumnProps[] = [
+    { label: '编号', type: 'index', align: 'center', width: '80px' },
+    { label: '完成(检查)时间', prop: 'checkTime', minWidth: '180px' },
+    { label: '状态', prop: 'status', slot: 'status', minWidth: '120px' },
+    { label: '检查人员', prop: 'checkPerson', minWidth: '140px' },
+    { label: '检查场所类别', prop: 'checkPlaceCategory', minWidth: '160px' },
+    { label: '检查场所', prop: 'checkPlace', minWidth: '180px' },
+    { label: '检查项总数', prop: 'checkItemTotal', align: 'center', width: '160px' },
+    { label: '合格项数', prop: 'qualifiedItemNum', align: 'center', width: '140px' },
+    { label: '不合格项数', prop: 'unqualifiedItemNum', slot: 'unqualifiedItemNum', align: 'center', width: '160px' },
+    { label: '整体检查情况描述', prop: 'overallCheckDesc', minWidth: '190px', showOverflowTooltip: true },
+    { label: '被检查人签字', slot: 'sign', align: 'center', width: '180px' },
+    { label: '操作', slot: 'action', align: 'center', width: '220px', fixed: 'right' },
+  ];
+  const RECORD_TABLE_OPTIONS = {
+    emptyText: '暂无检查记录',
+    loading: false,
+    maxHeight: '400px',
+    stripe: true,
+  };
+  const { tableConfig: recordTableConfig, pagination: recordPagination } = useTableConfig(
+    RECORD_TABLE_COLUMNS,
+    RECORD_TABLE_OPTIONS,
+    true,
+  );
+    // 部门端入账弹窗数据(复用隐患台账新增表单字段与样式)
+  const showSandConfirmDialogDept = ref(false);
+  const sandConfirmLoadingDept = ref(false);
+  const sandHiddenDangerFormRefDept = ref<InstanceType<typeof BasicForm>>();
+  const {
+    ruleFormData: sandHiddenDangerFormDataDept,
+    formRules: sandHiddenDangerFormRulesDept,
+    ruleFormConfig: sandHiddenDangerFormConfigDept,
+  } = useFormConfigHook(
+    HIDDEN_DANGER_FORM_CONFIG,
+    HIDDEN_DANGER_FORM_DATA as Record<string, unknown>,
+    HIDDEN_DANGER_FORM_RULES,
+  );
+  const issueDeptTree = ref<DeptTree[]>([]);
+  const issueUserList = ref<Array<{ id: number; realname?: string; username?: string }>>([]);
+  // 复用部门树与用户下拉,用于复查部门/人员 & 举一反三责任部门
+  const deptTree = ref<DeptTree[]>([]);
+  const cascaderDeptProp = {
+    checkStrictly: true,
+    expandTrigger: 'hover' as const,
+    value: 'id',
+    label: 'deptName',
+    emitPath: false,
+  };
+  const drawLessonsDeptIdsArrayDept = ref<number[]>([]);
+  const reviewUserListDept = ref<Array<{ id: number; realname?: string; username?: string }>>([]);
+
+  const deptOptions = computed(() => flattenDeptTree(deptTree.value));
+  const flattenDeptTree = (nodes: DeptTree[] | undefined): Array<{ id: number; deptName: string }> => {
+    if (!nodes?.length) return [];
+    const list: Array<{ id: number; deptName: string }> = [];
+    const walk = (items: DeptTree[]) => {
+      items.forEach((n) => {
+        if (n.id != null) list.push({ id: n.id, deptName: n.deptName });
+        if (n.children?.length) walk(n.children);
+      });
+    };
+    walk(nodes);
+    return list;
+  }
+  const openUnqualifiedDialog = (row: { id?: number } & Record<string, unknown>) => {
+    if (!row.id) return;
+    currentRecordIdForUnqualified.value = Number(row.id);
+    currentRowForUnqualified.value = row;
+    unqualifiedPagination.pageNumber = 1;
+    showUnqualifiedDialog.value = true;
+    loadUnqualifiedList();
+  };
+
+
+  const loadUnqualifiedList = async () => {
+    if (!currentRecordIdForUnqualified.value) return;
+    unqualifiedTableConfig.loading = true;
+    try {
+      const res = await queryUnqualifiedItemNumDeptPage({
+        pageNumber: unqualifiedPagination.pageNumber,
+        pageSize: unqualifiedPagination.pageSize,
+        queryParam: {
+          id: currentRecordIdForUnqualified.value,
+          checkPlace: String(currentRowForUnqualified.value?.checkPlace ?? ''),
+          checkProblem: String(currentRowForUnqualified.value?.checkProblem ?? ''),
+          checkTime: String(currentRowForUnqualified.value?.checkTime ?? ''),
+        },
+      });
+      const raw = (res as { data?: { records?: UnqualifiedItemNumRecord[]; totalRow?: number } })?.data ?? res;
+      unqualifiedList.value = raw?.records ?? [];
+      unqualifiedPagination.total = raw?.totalRow ?? 0;
+    } catch (e) {
+      console.error('查询不合格数据失败:', e);
+      unqualifiedList.value = [];
+      unqualifiedPagination.total = 0;
+    } finally {
+      unqualifiedTableConfig.loading = false;
+    }
+  };
+
+  const handleUnqualifiedSizeChange = (value: number) => {
+    unqualifiedPagination.pageSize = value;
+    unqualifiedPagination.pageNumber = 1;
+    loadUnqualifiedList();
+  };
+
+  const handleUnqualifiedPageChange = (value: number) => {
+    unqualifiedPagination.pageNumber = value;
+    loadUnqualifiedList();
+  };
+
+  // 隐患类别数据
+  const dangerTypeList = ref<any[]>([])
+  const dangerTypeData = async ()=> {
+    try {
+      // 将日期范围同步到查询参数
+     let params = {
+        pageNumber: 1,
+        pageSize: 1000,
+        queryParam: {
+            status: 1,
+        },
+     }
+      const res = await queryDangerTypePage(params);
+      if (res) {
+        dangerTypeList.value = res.records || [];
+      }
+    } catch (e) {
+      console.error('获取隐患类别列表失败:', e);
+      dangerTypeList.value = [];
+    }
+  }
+
+  const handleSandToHiddenDangerDept = (row: { id?: number } & Record<string, unknown>) => {
+    if (!row.id) return;
+    dangerTypeData()
+    currentRecordIdForUnqualified.value = Number(row.id);
+    // 部门端入账同样不带入检查记录旧数据,每次打开还原为隐患台账初始表单
+    Object.assign(sandHiddenDangerFormDataDept, HIDDEN_DANGER_FORM_DATA);
+    showSandConfirmDialogDept.value = true;
+  };
+
+  const validateSandHiddenDangerFormDept = async () => {
+    if (!sandHiddenDangerFormRefDept.value) return false;
+    return await sandHiddenDangerFormRefDept.value.validate();
+  };
+
+  const confirmSandToHiddenDangerDept = async () => {
+    if (!currentRecordIdForUnqualified.value) return;
+    const valid = await validateSandHiddenDangerFormDept();
+    if (!valid) return;
+    sandConfirmLoadingDept.value = true;
+    try {
+      const d = sandHiddenDangerFormDataDept;
+      const payload: SandAreaCheckRecordToHiddenDangerReq = {
+        areaCheckRecordId: currentRecordIdForUnqualified.value,
+        sourceType: 4,
+        sourceRefId: currentRecordIdForUnqualified.value,
+        dangerProblem: d.dangerProblem || '',
+        typeId: d.typeId,
+        reasonId: d.reasonId,
+        taskSource: d.taskSource || '',
+        rectificationRequirement: d.rectificationRequirement || '',
+        rectificationDeadline: d.rectificationDeadline || '',
+        rectificationDepartmentIds: d.rectificationDepartmentIds || '',
+        rectificationResponsiblePerson: d.rectificationResponsiblePerson || '',
+        reviewDepartmentId: d.reviewDepartmentId,
+        reviewPersonId: d.reviewPersonId,
+        reviewPersonName: d.reviewPersonName || '',
+        isDrawLessonsPush: d.isDrawLessonsPush ?? 0,
+        drawLessonsContent: d.drawLessonsContent || '',
+        drawLessonsDepartmentIds: d.drawLessonsDepartmentIds || '',
+        drawLessonsDeadline: d.drawLessonsDeadline || '',
+        attachments: d.attachments || '',
+        confirmSandToHiddenDangerDept: d.confirmSandToHiddenDangerDept ?? 0,
+        rectificationResponsibleIds: d.rectificationResponsibleIds || '',
+        drawLessonsContent: d.drawLessonsContent || '',
+        drawLessonsDepartmentIds: d.drawLessonsDepartmentIds || '',
+        drawLessonsDeadline: d.drawLessonsDeadline || '',
+      };
+      await sandAreaCheckRecordToProductionHiddenDanger(payload);
+      ElMessage.success('入账成功');
+      // 关闭入账表单弹窗和“不合格数据”弹窗
+      showSandConfirmDialogDept.value = false;
+      showUnqualifiedDialog.value = false;
+      await loadRecordList();
+    } catch (e:any) {
+      console.error('部门端下入账失败:', e);
+      ElMessage.error(e?.message || e?.data || '下入账失败,请稍后重试');
+    } finally {
+      sandConfirmLoadingDept.value = false;
+    }
+  };
+
+
+  const onIssueDialogOpen = async () => {
+    try {
+      const [deptRes, userRes] = await Promise.all([
+        getAllDepartments(),
+        queryAvailableUserList({ pageNumber: 1, pageSize: 9999, queryParam: {} }),
+      ]);
+      const fullTree = (deptRes as DeptTree[]) ?? [];
+      issueDeptTree.value = Array.isArray(fullTree) && fullTree[0]?.children ? fullTree[0].children : [];
+      issueUserList.value = (userRes as any)?.records ?? [];
+    } catch (e:any) {
+      console.error('获取部门/用户列表失败:', e);
+      ElMessage.error(e?.message || e?.data || '加载部门或负责人列表失败');
+      issueDeptTree.value = [];
+      issueUserList.value = [];
+    }
+  };
+  const cascaderDeptRef = ref<CascaderInstance | null>(null)
+  const onIssueDeptChange = async () => {
+    const nodes = cascaderDeptRef.value?.getCheckedNodes()
+  
+    if (!nodes || nodes.length === 0) return
+    const currentDept = nodes[0]
+    sandHiddenDangerFormDataDept.rectificationResponsibleIds = undefined;
+    try {
+      const userRes = await queryAvailableUserList({ pageNumber: 1, pageSize: 9999, queryParam: {deptName: currentDept.data.deptName||undefined} });
+      issueUserList.value = (userRes as any)?.records ?? [];
+    } catch (e:any) {
+      ElMessage.error(e?.message || e?.data || '加载部门或负责人列表失败');
+      issueUserList.value = [];
+    }
+  };
+   // 复查人员所属部门
+  const reviewDeptRef = ref<CascaderInstance | null>(null)
+  const onReviewDeptChange = async () => {
+    const nodes = reviewDeptRef.value?.getCheckedNodes()
+  
+    if (!nodes || nodes.length === 0) return
+    const currentDept = nodes[0]
+    sandHiddenDangerFormDataDept.reviewPersonId = undefined;
+    try {
+      const userRes = await queryAvailableUserList({ pageNumber: 1, pageSize: 9999, queryParam: {deptName: currentDept.data.deptName||undefined} });
+       reviewUserListDept.value = (userRes as any)?.records ?? [];
+    } catch (e:any) {
+      ElMessage.error(e?.message || e?.data || '加载部门或负责人列表失败');
+       reviewUserListDept.value = [];
+    }
+  };
+  const currentId = ref<number | null>(null);
+  const recordSearchKeyword = ref('');
+  const recordDateRange = ref<[string, string] | null>(null);
+  const statusValue = ref<number | null>(null);
+  const inspectionRecordList = ref<Array<Record<string, unknown>>>([]);
+
+  const paginatedRecordList = computed(() => inspectionRecordList.value);
+  const loadRecordList = async () => {
+    if (!currentRecordIdForUnqualified.value) return;
+    recordTableConfig.loading = true;
+    try {
+      const [start, end] = recordDateRange.value && recordDateRange.value.length === 2
+        ? recordDateRange.value
+        : ['', ''];
+      const res = await queryAreaCheckPlanDetailDeptPage(currentRecordIdForUnqualified.value, {
+        pageNumber: recordPagination.pageNumber,
+        pageSize: recordPagination.pageSize,
+        queryParam: {
+          searchKey: recordSearchKeyword.value || undefined,
+          startDate: start || undefined,
+          endDate: end || undefined,
+          id: currentRecordIdForUnqualified.value,
+        },
+      });
+      const raw = (res as { data?: { records?: Array<Record<string, unknown>>; totalRow?: number } })?.data ?? res;
+      const records = raw?.records ?? [];
+
+      inspectionRecordList.value = records.map((r: Record<string, unknown>) => {
+            let checkedPersonSign: unknown[] = [];
+            const signValue = r.checkedPersonSign;
+            // 兼容所有脏数据
+            if (signValue) {
+                try {
+                    const parsed = JSON.parse(signValue as string);
+                    checkedPersonSign = Array.isArray(parsed) ? parsed : [];
+                } catch {
+                    checkedPersonSign = [signValue];
+                }
+            }
+            return {
+                ...r,
+                checkedPersonSign,
+                checkPerson: r.checkPerson ?? r.checkPersonName,
+                checkedCompany: r.checkedCompany ?? r.checkedCompanyName,
+            };
+      });
+      recordPagination.total = raw?.totalRow ?? 0;
+    } catch (e) {
+      console.error('查询检查记录失败:', e);
+      inspectionRecordList.value = [];
+      recordPagination.total = 0;
+    } finally {
+      recordTableConfig.loading = false;
+    }
+  };
 </script>
 
 <style scoped lang="scss">
@@ -304,4 +881,10 @@
   @use '@/styles/page-main-layout.scss' as *;
   @use '@/styles/basic-table-action.scss' as *;
   @use '@/views/traffic/violation/style/act-search-table.scss' as *;
+  :deep(.preview-img){
+    img{
+        max-width: 100%;
+        max-height: 80vh;
+    }
+  }
 </style>

+ 342 - 85
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/areaCheckPlanTask/components/areaCheckPlanRecordDetail.vue

@@ -1,68 +1,138 @@
 <template>
-  <div class="area-check-plan-record-detail">
-    <main class="safety-platform-container__main">
-      <el-form :model="formData" label-width="auto" class="check-record-form">
-        <el-form-item label="被检查单位:">
-          <el-input v-model="formData.inspectedUnit" disabled />
-        </el-form-item>
-        <el-form-item label="检查人员:">
-          <el-input v-model="formData.inspector" disabled />
-        </el-form-item>
-        <el-form-item label="检查时间:">
-          <el-input v-model="formData.checkTime" disabled />
-        </el-form-item>
-        <el-form-item label="检查地点:">
-          <el-input v-model="formData.checkPlace" disabled />
-        </el-form-item>
-        <el-form-item label="整体检查情况描述:">
-          <el-input
-            v-model="formData.overallDesc"
-            type="textarea"
-            :rows="5"
-            maxlength="300"
-            show-word-limit
-            disabled
-            placeholder="整体检查情况描述(限300字)"
-          />
-        </el-form-item>
-        <el-form-item label="被检查人签字文件:">
-          <div class="upload-files-disabled">
-            <UploadFiles
-              label="上传附件"
-              :file-list="signFileList"
-            />
+  <main class="safety-platform-container__main">
+    <el-form ref="formRef" :model="formData" :rules="isViewMode ? undefined : formRules" label-width="180px" class="check-record-form">
+      <el-form-item label="被检查单位:" prop="inspectedUnit">
+        <el-input v-model="formData.inspectedUnit" :disabled="!isAddMode || checkType===1" placeholder="请输入被检查单位" clearable />
+      </el-form-item>
+      <el-form-item label="检查人员:" prop="inspector">
+        <el-input v-model="formData.inspector" :disabled="!isAddMode" placeholder="请输入检查人员" clearable />
+      </el-form-item>
+      <el-form-item label="检查时间:" prop="checkTime">
+        <el-date-picker
+          v-if="isAddMode"
+          v-model="formData.checkTime"
+          type="datetime"
+          placeholder="选择检查日期"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          format="YYYY-MM-DD HH:mm:ss"
+          style="width: 100%"
+        />
+        <el-input v-else v-model="formData.checkTime" disabled />
+      </el-form-item>
+      <el-form-item label="检查地点:" prop="checkPlace">
+        <el-input v-model="formData.checkPlace" :disabled="!isAddMode" placeholder="请输入检查地点" clearable />
+      </el-form-item>
+      <el-form-item v-if="viewDetailData.needOverallDesc === 1" label="整体检查情况描述:" prop="overallDesc" :required="viewDetailData.needOverallDesc === 1 && isAddMode">
+        <el-input
+          v-model="formData.overallDesc"
+          type="textarea"
+          :rows="5"
+          maxlength="300"
+          show-word-limit
+          :disabled="!isAddMode"
+          :placeholder="isAddMode ? '请输入整体检查情况描述(限300字)' : '整体检查情况描述(限300字)'"
+        />
+      </el-form-item>
+      <el-form-item v-if="viewDetailData.needSigneeSign === 1" label="被检查人签字文件:" prop="signFile" :required="viewDetailData.needSigneeSign === 1 && isAddMode">
+        <UploadFiles
+          v-if="!isViewMode"
+          label="上传文件"
+          :file-list="signFileList"
+          :disabled="isViewMode"
+          :allow-all-file-types="true"
+          :accept="'.jpg,.jpeg,.png'"
+          :desc="'支持.jpg,.jpeg,.png'"
+          @uploadSuccess="(list: FileItem[]) => handleUploadSuccess(list)"
+        />
+        <div class="file-list" v-else>
+          <div class="file-item" v-for="file in signFileList" :key="file.fileId">
+            <span class="file-item--name">{{ file.fileName }}</span>
+            <div class="file-item--footer">
+              <el-button link type="primary" @click="previewOnline(file.fileUrl, file.fileType)"
+                >预览</el-button
+              >
+              <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
+                >下载</el-button
+              >
+            </div>
           </div>
-        </el-form-item>
-      </el-form>
-
-      <div class="check-items-section">
-        <div class="section-header">
-          <span class="section-title">检查明细</span>
-        </div>
-        <div class="check-items-table">
-          <el-table :data="checkItems" border>
-            <el-table-column type="index" label="编号" width="80" align="center" />
-            <el-table-column prop="checkContent" label="检查内容" min-width="180" />
-            <el-table-column prop="checkStandard" label="检查标准" min-width="180" />
-            <el-table-column prop="checkResult" label="检查结果" min-width="120" align="center" />
-            <el-table-column prop="checkProblem" label="检查发现问题" min-width="200" />
-          </el-table>
         </div>
+      </el-form-item>
+    </el-form>
+
+    <div class="check-items-section">
+      <div class="section-header">
+        <span class="section-title">检查明细</span>
       </div>
-    </main>
-  </div>
+      <el-table :data="checkItems" border class="check-items-table">
+        <el-table-column type="index" label="编号" width="80" align="center" />
+        <el-table-column prop="checkContent" label="检查内容" min-width="200" />
+        <el-table-column prop="checkStandard" label="检查标准" min-width="200" />
+        <el-table-column label="检查结果" width="160" align="center">
+          <template #default="{ row }">
+            <el-radio-group v-if="isAddMode" v-model="row.checkResult" size="small">
+              <el-radio value="合格">合格</el-radio>
+              <el-radio value="不合格">不合格</el-radio>
+              <!-- <el-radio value="待检">待检</el-radio> -->
+            </el-radio-group>
+            <span v-else>{{ row.checkResult || '-' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="检查发现问题" min-width="200">
+          <template #default="{ row }">
+            <el-input v-if="isAddMode" v-model="row.checkProblem" placeholder="请输入检查发现问题" clearable  :disabled="row.checkResult === '不合格' ? false : true"/>
+            <span v-else>{{ row.checkProblem || '-' }}</span>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <footer v-if="isAddMode" class="safety-platform-container__footer">
+      <el-button @click="handleBack">返回</el-button>
+      <el-button type="primary" @click="handleSubmit">提交</el-button>
+    </footer>
+
+    <PreviewOnline ref="previewOnlineRef" />
+
+  </main>
 </template>
 
 <script setup lang="ts">
-  import { computed, onMounted, ref } from 'vue';
-  import { useRoute } from 'vue-router';
+  import { computed, onMounted, reactive, ref } from 'vue';
+  import { useRoute, useRouter } from 'vue-router';
+  import { ElMessage } from 'element-plus';
   import UploadFiles from '@/components/UploadFiles/UploadFiles.vue';
   import type { FileItem } from '@/components/UploadFiles/types';
-  import { queryAreaCheckRecord } from '@/api/production-safety-system';
+  import {
+    queryAreaCheckPlanManageDeptDetail,
+    queryAreaCheckRecordDept,
+    fetchDeptAreaCheckRecord,
+    mapAreaCheckPlanApiRecordToUi,
+    queryAreaCheckRecordTemplateDept,
+    saveAreaCheckPlanDetailDept,
+    type AreaCheckRecordTemplateItem,
+  } from '@/api/production-safety-system';
+  import { formatAttachmentList } from '@/components/UploadFiles/utils';
+  import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
+  import { downloadFile } from '@/views/disaster/utils';
+  import { useUserInfoHook } from '@/views/disaster/hooks';
 
+  const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
+  const router = useRouter();
   const route = useRoute();
-  const recordId = computed(() => Number(route.query.recordId));
+  const { id } = useUserInfoHook()
 
+  const operate = computed(() => (route.query.operate as string) || '');
+  const isAddMode = computed(() => operate.value === 'area-check-plan-create');
+  const isViewMode = computed(() => operate.value === 'area-check-plan-view');
+  const recordId = computed(() => Number(route.query.recordId));
+  const planId = computed(() => Number(route.query.planId));
+  const checkType = computed(() => Number(route.query.checkType));
+  const areaPlanId = computed(() => Number(route.query.areaPlanId));
+//   const needOverallDesc = computed(() => route.query.needOverallDesc);
+//   const needSigneeSign = computed(() => route.query.needSigneeSign);
+  const viewDetailData = ref<Record<string, unknown>>({});
+  const formRef = ref();
   const formData = ref({
     inspectedUnit: '',
     inspector: '',
@@ -72,7 +142,33 @@
     signFile: '',
   });
 
-  /** 将签字文件(逗号分隔URL或文件名)转换为 UploadFiles 使用的 FileItem 列表,复用新增安全考核上传附件文档字段样式 */
+  const formRules = {
+    inspectedUnit: [{ required: true, message: '请输入被检查单位', trigger: 'blur' }],
+    inspector: [{ required: true, message: '请输入检查人员', trigger: 'blur' }],
+    checkTime: [{ required: true, message: '请选择检查时间', trigger: 'change' }],
+    checkPlace: [{ required: true, message: '请输入检查地点', trigger: 'blur' }],
+    overallDesc: [{ 
+      required: viewDetailData.value.needOverallDesc === 1, 
+      message: '请输入整体检查情况描述', 
+      trigger: 'blur' 
+    }],
+    signFile: [{ 
+      required: viewDetailData.value.needSigneeSign === 1, 
+      message: '请上传被检查人签字文件', 
+      trigger: 'change' 
+    }],
+  };
+
+  interface CheckItem {
+    checkContent: string;
+    checkStandard: string;
+    checkResult: string;
+    checkProblem: string;
+    id: number;
+  }
+
+  const checkItems = ref<CheckItem[]>([]);
+
   function convertSignFileToFileItems(attachmentsStr: string): FileItem[] {
     if (!attachmentsStr || !String(attachmentsStr).trim()) return [];
     const urls = String(attachmentsStr)
@@ -91,18 +187,100 @@
     });
   }
 
-  const signFileList = computed<FileItem[]>(() => convertSignFileToFileItems(formData.value.signFile || ''));
+  const signFileList = ref<FileItem[]>([]);
+  const displayFileList = computed(() => {
+    if (isAddMode.value) return signFileList.value;
+    return convertSignFileToFileItems(formData.value.signFile || '');
+  });
 
-  const checkItems = ref<Array<{
-    checkContent?: string;
-    checkStandard?: string;
-    checkResult?: string;
-    checkProblem?: string;
-  }>>([]);
+  const handleUploadSuccess = (files: FileItem[]) => {
+    signFileList.value = files;
+    formData.value.signFile = JSON.stringify(files);
+  };
 
+  const handleBack = () => {
+    router.back();
+  };
+
+  const handleSubmit = async () => {
+    if (!formRef.value) return;
+    const valid = await formRef.value.validate().catch(() => false);
+    if (!valid) return;
+    if (!planId.value) {
+      ElMessage.error('缺少关联的区域检查计划ID,无法提交');
+      return;
+    }
+    try {
+
+      const uploadedFileList = await formatAttachmentList(signFileList.value);
+
+      await saveAreaCheckPlanDetailDept({
+          areaPlanId: checkItemData.areaPlanId || planId.value,
+          id: checkItemData.id, // 编辑时传记录ID,新增时后端自动生成无需传
+          checkedCompanyName: formData.value.inspectedUnit,
+          checkTime: formData.value.checkTime,
+          checkPersonName: formData.value.inspector,
+          // 暂无人员 code 来源,前端先不传或由后端根据名称解析
+          checkAddress: formData.value.checkPlace,
+          overallCheckDesc: formData.value.overallDesc,
+          checkedPersonSign: JSON.stringify(uploadedFileList),
+          areaCheckRecords: checkItems.value.map((item) => ({
+          checkContent: item.checkContent || '',
+          checkStandard: item.checkStandard || '',
+          id: item.id,
+          // 新增检查日志时,检查结果和问题直接使用接口返回的数据
+          checkResult: item.checkResult || '',
+          checkProblem: item.checkProblem || '',
+        })),
+      });
+      ElMessage.success('提交成功');
+      router.back();
+    } catch (e:any) {
+      console.error('新增检查日志提交失败:', e);
+      ElMessage.error(e?.message || e?.data || '提交失败,请稍后重试');
+    }
+  };
+  // 判断是否有值, 如果有值就转换成JSON.parse
+  const safeJsonParse = (str) => {
+  // 判断是否有有效值
+  if (str === null || str === undefined || str.trim() === '') {
+    return [];
+  }
+
+  try {
+    return JSON.parse(str);
+  } catch (e) {
+    console.warn('JSON 解析失败:', e);
+    return [];
+  }
+}
   const loadRecordDetail = async () => {
-    if (!recordId.value) {
-      // 新增检查日志:全部为空数据
+    if (recordId.value) {
+      try {
+        const res = await queryAreaCheckRecordDept(recordId.value);
+        const raw = (res as { data?: Record<string, unknown> })?.data ?? res;
+        const r = raw as Record<string, unknown>;
+        formData.value = {
+          inspectedUnit: String(r?.checkedCompanyName ?? r?.checkedCompany ?? ''),
+          inspector: String(r?.checkPersonName ?? r?.checkPerson ?? ''),
+          checkTime: String(r?.checkTime ?? ''),
+          checkPlace: String(r?.checkAddress ?? r?.checkPlace ?? ''),
+          overallDesc: String(r?.overallCheckDesc ?? ''),
+          signFile: JSON.stringify(convertSignFileToFileItems(String(r?.checkedPersonSign ?? ''))),
+        };
+        signFileList.value = safeJsonParse(r?.checkedPersonSign);
+        const records = (r?.areaCheckRecords ?? []) as Array<Record<string, unknown>>;
+        checkItems.value = records.map((item) => ({
+          checkContent: (item.checkContent ?? '') as string,
+          checkStandard: (item.checkStandard ?? '') as string,
+          checkResult: (item.checkResult ?? '') as string,
+          checkProblem: (item.checkProblem ?? '') as string,
+        }));
+      } catch (e) {
+        console.error('获取检查记录详情失败:', e);
+      }
+    } else {
+      // 无 recordId 的查看场景,只保留空表单和空检查明细(不依赖路由传递数据)
       formData.value = {
         inspectedUnit: '',
         inspector: '',
@@ -112,33 +290,92 @@
         signFile: '',
       };
       checkItems.value = [];
+    }
+  };
+  interface CheckItemData {
+  areaPlanId: number;
+  id?: number;
+  [key: string]: unknown;
+  // 其他可能的字段...
+}
+  let checkItemData = reactive<CheckItemData>({
+    areaPlanId: 0
+})
+// 开始任务检查的检查明细列表
+  const loadCheckItems = async () => {
+    if (!planId.value) {
+      // 没有计划ID时,不展示任何检查明细
+      checkItems.value = [];
       return;
     }
     try {
-      const res = await queryAreaCheckRecord(recordId.value);
-      const raw = (res as { data?: Record<string, unknown> })?.data ?? res;
-      const r = raw as Record<string, unknown>;
+      const res = await fetchDeptAreaCheckRecord(planId.value);
+      const list = res.areaCheckRecords || [];
+      checkItemData = res
+      if (Array.isArray(list) && list.length > 0) {
+        checkItems.value = list;
+      } else {
+        // 模板为空时,不展示任何检查明细
+        checkItems.value = [];
+      }
+    } catch (e) {
+      console.error('获取检查明细模板失败:', e);
+      // 接口异常时不影响表单填写,但不展示任何假数据
+      checkItems.value = [];
+    }
+  };
+
+  const initFormData = async () => {
+    if (isAddMode.value) {
+      const { planName, checkVenue } = route.query;
       formData.value = {
-        inspectedUnit: String(r?.checkedCompanyName ?? r?.checkedCompany ?? ''),
-        inspector: String(r?.checkPersonName ?? r?.checkPerson ?? ''),
-        checkTime: String(r?.checkTime ?? ''),
-        checkPlace: String(r?.checkAddress ?? r?.checkPlace ?? ''),
-        overallDesc: String(r?.overallCheckDesc ?? ''),
-        signFile: String(r?.checkedPersonSign ?? ''),
+        inspectedUnit: planName ? String(planName) : '',
+        inspector: '',
+        checkTime: '',
+        checkPlace: checkVenue ? String(checkVenue) : '',
+        overallDesc: '',
+        signFile: '',
       };
-      const records = (r?.areaCheckRecords ?? []) as Array<Record<string, unknown>>;
-      checkItems.value = records.map((r) => ({
-        checkContent: r.checkContent as string,
-        checkStandard: r.checkStandard as string,
-        checkResult: r.checkResult as string,
-        checkProblem: r.checkProblem as string,
-      }));
-    } catch (e) {
-      console.error('获取检查记录详情失败:', e);
+      signFileList.value = [];
+      await loadCheckItems();
+    } else {
+      await loadRecordDetail();
     }
   };
 
-  onMounted(() => loadRecordDetail());
+  const previewOnline = (url: string | undefined, type) => {
+    if (url) {
+      previewOnlineRef.value?.open(url, type);
+    }
+  };
+
+  const authority = ref(false)
+  const currentId = computed(() => Number(route.query.planId));
+  const getDetail = async () => {
+    if (!currentId.value) return;
+    try {
+      const res = await queryAreaCheckPlanManageDeptDetail(currentId.value);
+      viewDetailData.value = { ...res };
+      // 若是自查,则被检查单位默认就是本单位,不需要手动输入。
+      if(checkType.value === 1){
+        authority.value = true
+        formData.value.inspectedUnit = res.responsibleDeptName || ''
+      }
+      // 如果主责部门责任人ID包含当前登录人ID,则直接回填(被检查单位、 检查人员、检查时间、检查地点),且不可更改
+    //   let primaryResponsibleDeptPersonCode = res.primaryResponsibleDeptPersonCode?.split(',').map(Number)
+    //   if(primaryResponsibleDeptPersonCode?.includes(id)){
+    //     authority.value = true
+    //     formData.value.inspectedUnit = res.responsibleDeptName || ''
+    //     formData.value.inspector = String(res.primaryResponsibleDeptPersonName) || ''
+    //   }
+    } catch (e) {
+      console.error('获取详情失败:', e);
+    }
+  };
+  onMounted(() => {
+    getDetail()
+    initFormData();
+  });
 </script>
 
 <style scoped lang="scss">
@@ -146,20 +383,35 @@
   @use '@/styles/page-main-layout.scss' as *;
 
   .check-record-form {
-    max-width: 800px;
+    max-width: 900px;
+    margin-bottom: 24px;
   }
 
   .check-items-section {
     margin-top: 16px;
+    margin-bottom: 24px;
 
     .section-header {
-      margin-bottom: 8px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin-bottom: 12px;
+
       .section-title {
         font-weight: 600;
+        font-size: 15px;
       }
     }
   }
 
+  .check-items-table {
+    :deep(.el-textarea__inner) {
+      border: none;
+      box-shadow: none;
+      padding: 4px 0;
+    }
+  }
+
   .upload-files-disabled {
     pointer-events: none;
     opacity: 0.6;
@@ -174,5 +426,10 @@
       display: none;
     }
   }
+  :deep(.preview-img){
+    img{
+        max-width: 100%;
+        max-height: 80vh;
+    }
+  }
 </style>
-

+ 9 - 0
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/areaCheckPlanTask/configs/form.ts

@@ -10,6 +10,15 @@ export const CHECK_FREQUENCY_OPTIONS = [
   { label: '每年', value: '每年' },
 ];
 
+/** 检查频次映射:0=每日 1=每周 2=每月 3=每季度 4=每半年 5=每年 */
+export const FREQUENCY_TO_LABEL: Record<number, string> = {
+  0: '每日',
+  1: '每周',
+  2: '每月',
+  3: '每季度',
+  4: '每半年',
+  5: '每年',
+};
 /** 检查单模版类别选项(单选):1-安全管理检查单 2-关键业务活动专项检查单 3-日常安全检查单 */
 export const CHECKLIST_CATEGORY_OPTIONS = [
   { label: '安全管理检查单', value: '安全管理检查单' },

+ 2 - 5
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/areaCheckPlanTask/configs/status.ts

@@ -1,15 +1,12 @@
-// 区域检查计划状态配置(管理员与部门一致):0=未下发 1=进行中 2=已完成 3=已作废
 export const AREA_CHECK_PLAN_STATUS_OPTIONS = [
   { label: '全部', value: '' as const },
-//   { label: '未下发', value: 0 },
-  { label: '进行中', value: 1 },
+  { label: '待检查', value: 1 },
   { label: '已完成', value: 2 },
   { label: '已作废', value: 3 },
 ];
 
 export const AREA_CHECK_PLAN_STATUS_LABEL: Record<string, string> = {
-  '0': '未下发',
-  '1': '进行中',
+  '1': '待检查',
   '2': '已完成',
   '3': '已作废',
 };

+ 28 - 23
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/areaCheckPlanTask/configs/tables.ts

@@ -20,85 +20,90 @@ export const AREA_CHECK_PLAN_TABLE_COLUMNS: TableColumnProps[] = [
   {
     label: '完成(检查)时间',
     prop: 'checkTime',
-    align: 'left',
+    align: 'center',
     minWidth: '180px',
     showOverflowTooltip: true,
   },
   {
     label: '状态',
-    prop: 'checkVenue',
-    align: 'left',
+    prop: 'status',
+    slot: 'status',
+    align: 'center',
     minWidth: '120px',
     showOverflowTooltip: true,
   },
   {
     label: '检查人员',
-    prop: 'checkPerson',
-    align: 'left',
+    prop: 'checkPersonName',
+    align: 'center',
     minWidth: '120px',
     showOverflowTooltip: true,
   },
-  {
-    label: '检查场所类别',
-    prop: 'checkPlaceCategory',
-    align: 'left',
-    minWidth: '160px',
-    showOverflowTooltip: true,
-  },
+//   {
+//     label: '检查场所类别',
+//     prop: 'checkPlaceCategory',
+//     align: 'center',
+//     minWidth: '160px',
+//     showOverflowTooltip: true,
+//   },
   {
     label: '检查场所',
     prop: 'checkPlace',
-    align: 'left',
+    align: 'center',
     minWidth: '120px',
     showOverflowTooltip: true,
   },
   {
     label: '检查频次',
-    prop: 'planName',
-    align: 'left',
+    prop: 'frequency',
+    slot: 'frequency',
+    align: 'center',
     minWidth: '120px',
     showOverflowTooltip: true,
   },
   {
     label: '检查重点内容',
-    prop: 'primaryResponsibleDeptName',
-    slot: 'primaryResponsibleDeptName',
-    align: 'left',
+    prop: 'checkKeyContent',
+    align: 'center',
     width: '200px',
     showOverflowTooltip: true,
   },
   {
     label: '整体检查情况描述',
     prop: 'overallCheckDesc',
-    align: 'left',
+    align: 'center',
     minWidth: '200px',
     showOverflowTooltip: true,
   },
   {
     label: '被检查人签字',
     prop: 'sign',
-    align: 'left',
+    slot:'sign',
+    align: 'center',
     minWidth: '140px',
     showOverflowTooltip: true,
   },
   {
     label: '检查项总数',
     prop: 'checkItemTotal',
-    align: 'left',
+    slot: 'checkItemTotal',
+    align: 'center',
     minWidth: '160px',
     showOverflowTooltip: true,
   },
   {
     label: '合格项数',
     prop: 'qualifiedItemNum',
-    align: 'left',
+    slot: 'qualifiedItemNum',
+    align: 'center',
     minWidth: '160px',
     showOverflowTooltip: true,
   },
   {
     label: '不合格项数',
     prop: 'unqualifiedItemNum',
-    align: 'left',
+    slot: 'unqualifiedItemNum',
+    align: 'center',
     minWidth: '160px',
     showOverflowTooltip: true,
   },

+ 6 - 5
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/areaCheckPlanTask/configs/types.ts

@@ -43,9 +43,10 @@ export interface AreaCheckPlanRecord {
 }
 
 export interface AreaCheckPlanQuery {
-  keyword?: string;
+  searchKey?: string;
   status?: AreaCheckPlanStatus | '';
-  venueCategory?: string;
-  planStartTime?: string;
-  planEndTime?: string;
-}
+  startDate?: string;
+  endDate?: string;
+  userId?: number; // 当前登录人ID
+  [key: string]: unknown;
+}