xiaweibo 3 miesięcy temu
rodzic
commit
467bd6fd17

+ 1 - 1
src/api/evaluationSystem/index.ts

@@ -604,7 +604,7 @@ export function saveSecurityExamineAdvUserAdmin(data: SaveSecurityExamineAdvUser
  * 管理员端更新先进个人
  */
 export interface UpdateSecurityExamineAdvUserAdminRequest extends EvaluationDeptAdvancedUserItem {
-  psemId?: number; // 考核表ID(可选)
+  psemId: number; // 考核表ID
 }
 
 export function updateSecurityExamineAdvUserAdmin(data: UpdateSecurityExamineAdvUserAdminRequest) {

+ 132 - 1
src/api/production-safety-system/index.ts

@@ -1,5 +1,5 @@
 import { http } from '@/utils/http/axios';
-import type { QueryPageResponse } from '@/types/basic-query';
+import type { QueryPageRequest, QueryPageResponse } from '@/types/basic-query';
 
 /**
  * 生产安全体系文件基础接口
@@ -599,3 +599,134 @@ export function importSafetyStandardization(file: File) {
     },
   });
 }
+
+// ==================== 检查单模版管理 (checklistTemplate) 接口基础路径: /api/checklistTemplate ====================
+
+/** 检查单模板明细子表 */
+export interface ChecklistTemplateItem {
+  id?: number;
+  templateId?: number;
+  checkContent?: string; // 检查内容
+  checkStandard?: string; // 检查标准
+  checkResult?: string; // 检查结果:合格/不合格/待检
+  checkProblem?: string; // 检查发现问题
+  isDeleted?: number; // 删除标识(0-未删除,>0-已删除)
+  createdAt?: string;
+  updatedAt?: string;
+}
+
+/** 检查单模版列表项 (ChecklistTemplatePageRes) */
+export interface ChecklistTemplatePageItem {
+  id?: number;
+  templateName?: string;
+  moduleName?: string;
+  status?: number; // 0-禁用,1-启用,2-草稿
+  categoryName?: string;
+  categoryCode?: string;
+  useCount?: number;
+  remark?: string;
+  updateUserName?: string;
+  businessWork?: string;
+  fillInstruction?: string;
+}
+
+/** 检查单模版查询条件 */
+export interface ChecklistTemplateQuery {
+  templateName?: string; // 搜索检查单模版名称
+  status?: boolean; // true=启用,false=禁用(接口文档为Boolean,实际可传number兼容)
+  startDate?: string; // 上传日期范围-开始
+  endDate?: string; // 上传日期范围-结束
+}
+
+/** 检查单模版保存/编辑请求 (SaveChecklistTemplateReq) */
+export interface SaveChecklistTemplateReq {
+  id?: number;
+  templateName: string;
+  categoryName?: string;
+  categoryCode?: string;
+  businessWork: string;
+  fillInstruction: string;
+  ChecklistTemplateItem?: ChecklistTemplateItem[];
+}
+
+/** 分页查询请求 - 响应含 pageNumber/pageSize/total/totalPage/records */
+interface ChecklistTemplatePageQuery {
+  pageNumber?: number;
+  pageSize?: number;
+  queryParam?: ChecklistTemplateQuery;
+}
+
+interface ChecklistTemplatePageRes {
+  pageNumber: number;
+  pageSize: number;
+  total: number;
+  totalPage: number;
+  records: ChecklistTemplatePageItem[];
+}
+
+/** 一、查询检查单模版管理列表 */
+export function queryChecklistTemplateList(query: ChecklistTemplatePageQuery) {
+  return http.request<ChecklistTemplatePageRes>({
+    url: '/checklistTemplate/queryChecklistTemplateList',
+    method: 'post',
+    data: query,
+  });
+}
+
+/** 二、删除检查单模版管理 */
+export function deleteChecklistTemplateList(id: number) {
+  return http.request({
+    url: `/checklistTemplate/deleteChecklistTemplateList?id=${id}`,
+    method: 'delete',
+  });
+}
+
+/** 三、删除检查单模版明细 */
+export function deleteChecklistTemplateItem(id: number) {
+  return http.request({
+    url: `/checklistTemplate/deleteChecklistTemplateItem?id=${id}`,
+    method: 'delete',
+  });
+}
+
+/** 四、编辑检查单模版管理 */
+export function updateChecklistTemplate(data: SaveChecklistTemplateReq) {
+  return http.request<number>({
+    url: '/checklistTemplate/updateChecklistTemplate',
+    method: 'put',
+    data,
+  });
+}
+
+/** 五、新增检查单模版管理 */
+export function saveChecklistTemplateList(data: Omit<SaveChecklistTemplateReq, 'id'>) {
+  return http.request({
+    url: '/checklistTemplate/saveChecklistTemplateList',
+    method: 'post',
+    data,
+  });
+}
+
+/** 六、查询检查单模版管理详情 */
+export function queryChecklistTemplateDetail(id: number) {
+  return http.request<SaveChecklistTemplateReq>({
+    url: `/checklistTemplate/queryChecklistTemplateDetail?id=${id}`,
+    method: 'post',
+  });
+}
+
+/** 七、批量导入检查单模板明细子表 */
+export function importChecklistTemplateItem(file: File, id: string | number) {
+  const formData = new FormData();
+  formData.append('file', file);
+  formData.append('id', String(id));
+  return http.request({
+    url: '/checklistTemplate/importChecklistTemplateItem',
+    method: 'post',
+    data: formData,
+    headers: {
+      'Content-Type': 'multipart/form-data',
+    },
+  });
+}
+

+ 60 - 106
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/checkTemplateManagement/checkTemplateManagement.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="safety-platform-container">
     <header class="safety-platform-container__header">
-      <div class="breadcrumb-title"> 院级文件管理 </div>
+      <div class="breadcrumb-title">检查单模版管理</div>
     </header>
     <main class="safety-platform-container__main">
       <div class="search-table-container">
@@ -10,35 +10,18 @@
             <el-button type="primary" class="search-table-container--button" @click="handleCreate">
               添加
             </el-button>
-            <el-button plain class="search-table-container--button" @click="handleImport">
-              导入
-            </el-button>
-            <el-button plain class="search-table-container--button" @click="handleDownload">
-              导出
-            </el-button>
           </div>
 
           <div class="act-search">
             <section class="select-box">
               <div class="select-box--item">
-                <span>文件名称/编号:</span>
+                <span>模版条件:</span>
                 <el-input
-                  v-model="tableQuery.queryParam.keyword"
-                  placeholder="搜索文件名称或编号"
+                  v-model="tableQuery.queryParam.templateName"
+                  placeholder="搜索检查单模版名称"
                   class="act-search-input"
                 />
               </div>
-              <div class="select-box--item">
-                <span>分类:</span>
-                <el-select
-                  v-model="tableQuery.queryParam.classifyName"
-                  placeholder="请选择分类"
-                  clearable
-                >
-                  <el-option label="外部院级文件" value="外部院级文件" />
-                  <el-option label="内部院级文件" value="内部院级文件" />
-                </el-select>
-              </div>
               <div class="select-box--item">
                 <span>状态:</span>
                 <el-select
@@ -46,10 +29,22 @@
                   placeholder="请选择状态"
                   clearable
                 >
-                  <el-option label="启用" :value="1" />
-                  <el-option label="禁用" :value="0" />
+                  <el-option label="启用" :value="true" />
+                  <el-option label="禁用" :value="false" />
                 </el-select>
               </div>
+              <div class="select-box--item">
+                <span>日期范围:</span>
+                <el-date-picker
+                  v-model="dateRange"
+                  type="daterange"
+                  range-separator="-"
+                  start-placeholder="开始日期"
+                  end-placeholder="结束日期"
+                  value-format="YYYY-MM-DD"
+                  format="YYYY-MM-DD"
+                />
+              </div>
             </section>
             <section class="search-btn">
               <el-button type="primary" @click="handleSearch">查询</el-button>
@@ -68,7 +63,7 @@
           >
             <template #status="scope">
               <span>
-                {{ scope.row.status === 1 ? '启用' : scope.row.status === 0 ? '禁用' : '-' }}
+                {{ scope.row.status === 1 ? '启用' : scope.row.status === 0 ? '禁用' : scope.row.status === 2 ? '草稿' : '-' }}
               </span>
             </template>
             <template #action="scope">
@@ -88,16 +83,6 @@
         </div>
       </div>
     </main>
-    <BatchImport
-      v-if="batchImportVisible"
-      :visible="batchImportVisible"
-      :import-api-url="importApiUrl"
-      :template-url="templateUrl"
-      template-name="下载模板"
-      :show-template="false"
-      @close="batchImportVisible = false"
-      @update="handleUpdate"
-    />
   </div>
 </template>
 
@@ -107,41 +92,41 @@
   import BasicTable from '@/components/BasicTable.vue';
   import useTableConfig from '@/hooks/useTableConfigHook';
   import ActionButton from '@/components/ActionButton.vue';
-  import { TABLE_OPTIONS, INVENTORY_TABLE_COLUMNS } from './configs/tables';
+  import { TABLE_OPTIONS, CHECK_TEMPLATE_TABLE_COLUMNS } from './configs/tables';
   import { useRouter } from 'vue-router';
-  import type { QueryPageRequest } from '@/types/basic-query';
   import {
-    queryAcademyFilePage,
-    deleteAcademyFile,
-    exportAcademyFile,
-    type ProductionSafetyFileQuery,
+    queryChecklistTemplateList,
+    deleteChecklistTemplateList,
+    type ChecklistTemplateQuery,
   } from '@/api/production-safety-system';
-  import { downloadByData } from '@/utils/file/download';
-  import BatchImport from '@/components/batch-import/BatchImport.vue';
-  import { useGlobSetting } from '@/hooks/setting';
-  import urlJoin from 'url-join';
 
   const router = useRouter();
 
   // 表格
   const basicTableRef = ref<InstanceType<typeof BasicTable>>();
 
-  const { tableConfig, pagination } = useTableConfig(INVENTORY_TABLE_COLUMNS, TABLE_OPTIONS);
+  const { tableConfig, pagination } = useTableConfig(CHECK_TEMPLATE_TABLE_COLUMNS, TABLE_OPTIONS);
 
   const tableData = ref<any[]>([]);
 
-  const tableQuery = reactive<QueryPageRequest<ProductionSafetyFileQuery>>({
+  const tableQuery = reactive<{
+    pageNumber: number;
+    pageSize: number;
+    queryParam: ChecklistTemplateQuery;
+  }>({
     pageNumber: pagination.pageNumber,
     pageSize: pagination.pageSize,
     queryParam: {
-      keyword: '', // 文件名称/编号(模糊查询)
-      status: 1, // 状态:1-启用,0-禁用
-      classifyName: '', // 分类名称:外部院级文件/内部院级文件
-      startDate: '', // 上传日期范围-开始日期
-      endDate: '', // 上传日期范围-结束日期
+      templateName: '',
+      status: undefined,
+      startDate: '',
+      endDate: '',
     },
   });
 
+  // 日期范围(用于日期选择器)
+  const dateRange = ref<[string, string] | null>(null);
+
   const handleSizeChange = (value: number) => {
     pagination.pageSize = value;
     tableQuery.pageSize = value;
@@ -154,28 +139,25 @@
     getTableData();
   };
 
-
   async function getTableData() {
     tableConfig.loading = true;
     try {
-      const res = await queryAcademyFilePage(tableQuery);
+      const res = await queryChecklistTemplateList(tableQuery);
       if (res) {
-        // 映射返回数据字段到表格字段
-        tableData.value = res.records.map((item) => ({
+        tableData.value = (res.records || []).map((item) => ({
           id: item.id,
-          fileName: item.fileName, // 文件名称
-          fileCode: item.fileCode, // 文件编号
-          classifyName: item.classifyName, // 分类名称
-          fileVersion: item.fileVersion, // 文件版本号
-          fileFormat: item.fileFormat, // 文件格式
-          releaseDate: item.releaseDate, // 发布日期
-          status: item.status, // 状态:1-启用,0-禁用
-          uploadTime: item.uploadTime || item.createdAt, // 上传时间
+          templateName: item.templateName,
+          status: item.status,
+          categoryName: item.categoryName,
+          useCount: item.useCount ?? 0,
+          remark: item.remark,
+          updateUserName: item.updateUserName,
+          updatedAt: (item as any).updatedAt,
         }));
-        pagination.total = res.total || 0;
+        pagination.total = res.total ?? 0;
       }
     } catch (e) {
-      console.error('获取院级文件列表失败:', e);
+      console.error('获取检查单模版列表失败:', e);
       tableData.value = [];
       pagination.total = 0;
     } finally {
@@ -184,56 +166,28 @@
   }
 
   const handleSearch = () => {
+    // 处理日期范围
+    if (dateRange.value && dateRange.value.length === 2) {
+      tableQuery.queryParam.startDate = dateRange.value[0];
+      tableQuery.queryParam.endDate = dateRange.value[1];
+    } else {
+      tableQuery.queryParam.startDate = '';
+      tableQuery.queryParam.endDate = '';
+    }
     pagination.pageNumber = 1;
     tableQuery.pageNumber = 1;
     getTableData();
   };
 
   const handleReset = () => {
-    tableQuery.queryParam.keyword = '';
+    tableQuery.queryParam.templateName = '';
     tableQuery.queryParam.status = undefined;
-    tableQuery.queryParam.classifyName = '';
     tableQuery.queryParam.startDate = '';
     tableQuery.queryParam.endDate = '';
+    dateRange.value = null;
     handleSearch();
   };
 
-  // 批量导入
-  const batchImportVisible = ref(false);
-  const { urlPrefix } = useGlobSetting();
-  const importApiUrl = ref(urlJoin(urlPrefix, '/productionSafety/academyFile/import'));
-  const templateUrl = ref('./skyeye-file-upload/sfysecurity/TEMPLATE/import-academy-file-template.xlsx');
-
-  const handleImport = () => {
-    batchImportVisible.value = true;
-  };
-
-  const handleUpdate = () => {
-    batchImportVisible.value = false;
-    getTableData();
-  };
-
-  const handleDownload = async () => {
-    try {
-      const exportParams: ProductionSafetyFileQuery = {
-        keyword: tableQuery.queryParam.keyword || undefined,
-        status: tableQuery.queryParam.status,
-        classifyName: tableQuery.queryParam.classifyName || undefined,
-        startDate: tableQuery.queryParam.startDate || undefined,
-        endDate: tableQuery.queryParam.endDate || undefined,
-      };
-      const response = await exportAcademyFile(exportParams);
-      if (response) {
-        const fileName = `院级文件管理_${new Date().toISOString().split('T')[0]}.xlsx`;
-        downloadByData(response, fileName);
-        ElMessage.success('导出成功');
-      }
-    } catch (e) {
-      console.error('导出院级文件失败:', e);
-      ElMessage.error('导出失败,请重试');
-    }
-  };
-
   const handleCreate = () => {
     router.push({
       name: 'checkTemplateManagementItem',
@@ -255,11 +209,11 @@
 
   const handleDelete = async (id: number) => {
     try {
-      await deleteAcademyFile(id);
+      await deleteChecklistTemplateList(id);
       ElMessage.success('删除成功');
       getTableData();
     } catch (e) {
-      console.error('删除院级文件失败:', e);
+      console.error('删除检查单模版失败:', e);
       ElMessage.error('删除失败,请重试');
     }
   };
@@ -284,4 +238,4 @@
   @use '@/styles/page-main-layout.scss' as *;
   @use '@/styles/basic-table-action.scss' as *;
   @use '@/views/traffic/violation/style/act-search-table.scss' as *;
-</style>
+</style>

+ 2 - 1
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/checkTemplateManagement/checkTemplateManagementItem.vue

@@ -4,7 +4,7 @@
       <BreadcrumbBack />
       <span class="breadcrumb-title">{{ headerTitle }}</span>
     </header>
-    <CheckTemplateManagementDetail />
+    <CheckTemplateManagementDetail :id="id" />
   </div>
 </template>
 
@@ -16,6 +16,7 @@
 
   const route = useRoute();
   const operate = route.query.operate as string;
+  const id = computed(() => Number(route.query.id));
 
   const headerTitle = computed(() => {
     switch (operate) {

+ 273 - 187
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/checkTemplateManagement/components/checkTemplateManagementDetail.vue

@@ -1,51 +1,119 @@
 <template>
   <main class="safety-platform-container__main">
-    <BasicForm
-      ref="basicFormRef"
-      :formData="ruleFormData"
-      :formRules="isViewMode ? undefined : formRules"
-      :formConfig="computedFormConfig"
+    <el-form
+      ref="formRef"
+      :model="ruleFormData"
+      :rules="formRules"
+      label-width="auto"
+      class="check-template-form"
     >
-      <template #fileFormat>
-        <el-radio-group v-model="ruleFormData.fileFormat" :disabled="isViewMode">
-          <el-radio value="PDF">PDF</el-radio>
-          <el-radio value="WORD">WORD</el-radio>
-        </el-radio-group>
-      </template>
-      <template #fileUrl>
-        <UploadFiles
-          v-if="!isViewMode"
-          label="上传文件"
-          :maxCount="1"
-          :fileList="uploadFileList"
-          @uploadSuccess="handleUploadSuccess"
+      <el-form-item label="检查单模版名称:" prop="templateName">
+        <el-input
+          v-model="ruleFormData.templateName"
+          placeholder="请输入检查单模版名称"
+          :disabled="isViewMode"
         />
-        <div v-else-if="ruleFormData.fileUrl" class="file-display">
-          <a :href="ruleFormData.fileUrl" target="_blank" class="file-link">{{ getFileName(ruleFormData.fileUrl) }}</a>
-        </div>
-        <span v-else class="no-file">暂无文件</span>
-      </template>
-      <template #content>
-        <div v-if="!isViewMode" class="editor-container">
-          <Toolbar style="border-bottom: 1px solid #dcdfe6" :editor="editorRef" />
-          <Editor
-            style="height: 400px; overflow-y: auto"
-            v-model="ruleFormData.content"
-            mode="default"
-            :defaultConfig="editorConfig"
-            @on-created="handleEditorCreated"
-            @on-change="handleEditorChange"
+      </el-form-item>
+      <el-form-item label="类别名称:" prop="categoryName">
+        <el-select
+          v-model="ruleFormData.categoryCode"
+          placeholder="请选择类别名称"
+          :disabled="isViewMode"
+          style="width: 100%"
+          @change="onCategoryChange"
+        >
+          <el-option
+            v-for="item in CHECK_TEMPLATE_CATEGORY_OPTIONS"
+            :key="item.categoryCode"
+            :label="item.label"
+            :value="item.categoryCode"
           />
-        </div>
-        <div v-else class="content-display" v-html="ruleFormData.content || '暂无内容'"></div>
-      </template>
-      <template #status>
-        <el-radio-group v-model="ruleFormData.status" :disabled="isViewMode">
-          <el-radio :value="1">启用</el-radio>
-          <el-radio :value="0">禁用</el-radio>
-        </el-radio-group>
-      </template>
-    </BasicForm>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="业务工作:" prop="businessWork">
+        <el-input
+          v-model="ruleFormData.businessWork"
+          placeholder="请输入业务工作"
+          :disabled="isViewMode"
+        />
+      </el-form-item>
+      <el-form-item label="填写说明:" prop="fillInstruction">
+        <el-input
+          v-model="ruleFormData.fillInstruction"
+          type="textarea"
+          :rows="5"
+          placeholder="请输入填写说明(限300字)"
+          :disabled="isViewMode"
+          maxlength="300"
+          show-word-limit
+        />
+      </el-form-item>
+    </el-form>
+
+    <div class="check-items-section">
+      <div class="section-header">
+        <el-upload
+          v-if="isEditMode && props.id"
+          :show-file-list="false"
+          :http-request="handleImportItem"
+          accept=".xlsx,.xls"
+        >
+          <el-button type="primary" size="small">批量导入明细</el-button>
+        </el-upload>
+      </div>
+      <div class="check-items-table">
+        <el-table :data="checkItems" border>
+          <el-table-column label="编号" type="index" width="80" align="center" />
+          <el-table-column label="检查内容" min-width="180">
+            <template #header>
+              <span>检查内容<span style="color: red">*</span></span>
+            </template>
+            <template #default="scope">
+              <el-input
+                v-model="scope.row.checkContent"
+                placeholder="请输入检查内容"
+                :disabled="isViewMode"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="检查标准" min-width="180">
+            <template #default="scope">
+              <el-input
+                v-model="scope.row.checkStandard"
+                placeholder="请输入检查标准"
+                :disabled="isViewMode"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="检查结果" min-width="150" align="center">
+            <template #default="scope">
+              <el-radio-group v-model="scope.row.checkResult" :disabled="isViewMode">
+                <el-radio value="合格">合格</el-radio>
+                <el-radio value="不合格">不合格</el-radio>
+                <el-radio value="待检">待检</el-radio>
+              </el-radio-group>
+            </template>
+          </el-table-column>
+          <el-table-column label="检查发现问题" min-width="200">
+            <template #default="scope">
+              <el-input
+                v-model="scope.row.checkProblem"
+                placeholder="请输入检查发现问题"
+                :disabled="isViewMode"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column v-if="!isViewMode" label="操作" fixed="right" width="350" align="center">
+            <template #default="scope">
+              <el-button type="primary" link @click="handleAddItem(scope.$index)">新增</el-button>
+              <el-button type="primary" link @click="handleMoveUp(scope.$index)">向上插入分类</el-button>
+              <el-button type="primary" link @click="handleMoveDown(scope.$index)">向下插入分类</el-button>
+              <el-button type="danger" link @click="handleDeleteItem(scope.$index)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
   </main>
   <footer class="safety-platform-container__footer">
     <el-button @click="router.back()">返回</el-button>
@@ -56,209 +124,227 @@
 </template>
 
 <script setup lang="ts">
-  import { computed, onMounted, ref, shallowRef, onBeforeUnmount } from 'vue';
+  import { computed, onMounted, ref } from 'vue';
   import { useRoute, useRouter } from 'vue-router';
   import { ElMessage } from 'element-plus';
-  import BasicForm from '@/components/BasicForm.vue';
-  import UploadFiles from '@/components/UploadFiles/UploadFiles.vue';
-  import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
-  import '@wangeditor/editor/dist/css/style.css';
-  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
-  import { ACADEMY_FILE_FORM_CONFIG, ACADEMY_FILE_FORM_DATA, ACADEMY_FILE_FORM_RULES } from '../configs/form';
+  import type { FormInstance } from 'element-plus';
   import {
-    queryAcademyFileById,
-    saveAcademyFile,
-    updateAcademyFile,
-    type ProductionSafetyFile,
+    CHECK_TEMPLATE_CATEGORY_OPTIONS,
+    CHECK_TEMPLATE_FORM_DATA,
+    CHECK_TEMPLATE_FORM_RULES,
+  } from '../configs/form';
+  import {
+    queryChecklistTemplateDetail,
+    saveChecklistTemplateList,
+    updateChecklistTemplate,
+    importChecklistTemplateItem,
+    type ChecklistTemplateItem,
   } from '@/api/production-safety-system';
-  import type { FileItem } from '@/components/UploadFiles/types';
+
+  const props = defineProps<{
+    id?: number;
+  }>();
 
   const router = useRouter();
   const route = useRoute();
 
   const operate = computed(() => (route.query.operate as string) || 'check-template-create');
-  const currentId = computed(() => Number(route.query.id));
-
   const isCreateMode = computed(() => operate.value === 'check-template-create');
   const isEditMode = computed(() => operate.value === 'check-template-edit');
   const isViewMode = computed(() => operate.value === 'check-template-view');
 
-  const { ruleFormData, formRules, ruleFormConfig, cloneRuleFormData, beforeRouteLeave } =
-    useFormConfigHook(ACADEMY_FILE_FORM_CONFIG, ACADEMY_FILE_FORM_DATA, ACADEMY_FILE_FORM_RULES);
-
-  // 查看模式下,所有字段设为只读
-  const viewFormConfig = ref(
-    ACADEMY_FILE_FORM_CONFIG.map((item) => ({
-      ...item,
-      componentProps: {
-        ...item.componentProps,
-        disabled: true,
-      },
-    })),
-  );
-
-  const computedFormConfig = computed(() => {
-    if (isViewMode.value) {
-      return viewFormConfig.value;
-    }
-    return ruleFormConfig.value;
-  });
+  const formRef = ref<FormInstance>();
+  const ruleFormData = ref({ ...CHECK_TEMPLATE_FORM_DATA });
+  const formRules = CHECK_TEMPLATE_FORM_RULES;
+
+  const checkItems = ref<CheckItemRow[]>([]);
 
-  const basicFormRef = ref<InstanceType<typeof BasicForm>>();
-  
-  // 富文本编辑器
-  const editorRef = shallowRef();
-  const editorConfig = {
-    placeholder: '请输入文档内容',
-    MENU_CONF: {},
+  const onCategoryChange = (categoryCode: string) => {
+    const opt = CHECK_TEMPLATE_CATEGORY_OPTIONS.find((c) => c.categoryCode === categoryCode);
+    if (opt) ruleFormData.value.categoryName = opt.categoryName;
   };
 
-  const handleEditorCreated = (editor: any) => {
-    editorRef.value = editor;
+  interface CheckItemRow {
+    id?: number;
+    templateId?: number;
+    checkContent: string;
+    checkStandard: string;
+    checkResult: string; // 合格/不合格/待检
+    checkProblem: string;
+  }
+
+  const handleValidate = async () => {
+    if (!formRef.value) return;
+    return new Promise((resolve) => {
+      formRef.value?.validate((valid: boolean) => {
+        resolve(valid);
+      });
+    });
   };
 
-  const handleEditorChange = () => {
-    // 编辑器内容变化时的处理
+  const handleAddItem = (index: number) => {
+    checkItems.value.splice(index + 1, 0, createEmptyCheckItem());
   };
 
-  // 文件上传
-  const uploadFileList = ref<FileItem[]>([]);
+  /** 向上插入分类:在当前行之前插入一条空白数据 */
+  const handleMoveUp = (index: number) => {
+    checkItems.value.splice(index, 0, createEmptyCheckItem());
+  };
 
-  const handleUploadSuccess = (files: FileItem[]) => {
-    uploadFileList.value = files;
-    if (files.length > 0 && files[0].file) {
-      // 这里需要实际上传文件到服务器,获取 fileUrl
-      // 暂时使用文件对象,实际应该调用上传接口
-      ruleFormData.fileUrl = files[0].file.name; // 临时处理,需要替换为实际上传后的URL
-    }
+  /** 向下插入分类:在当前行之后插入一条空白数据 */
+  const handleMoveDown = (index: number) => {
+    checkItems.value.splice(index + 1, 0, createEmptyCheckItem());
   };
 
-  const getFileName = (url: string) => {
-    if (!url) return '';
-    const parts = url.split('/');
-    return parts[parts.length - 1];
+  const handleDeleteItem = (index: number) => {
+    if (checkItems.value.length <= 1) {
+      ElMessage.warning('至少需要保留一条数据');
+      return;
+    }
+    checkItems.value.splice(index, 1);
   };
 
-  const handleValidate = async () => {
-    if (!basicFormRef.value) return;
-    const res = await basicFormRef.value.validateForm();
-    return res;
+  const handleImportItem = async (options: { file: File }) => {
+    if (!props.id) return;
+    try {
+      await importChecklistTemplateItem(options.file, props.id);
+      ElMessage.success('导入成功');
+      await getDetail();
+    } catch (e: any) {
+      ElMessage.error(e?.message || '导入失败');
+    }
   };
 
   const getDetail = async () => {
-    if (!currentId.value) return;
+    if (!props.id) return;
+
     try {
-      const res = await queryAcademyFileById(currentId.value);
-      if (res) {
-        // 映射接口字段到表单字段
-        ruleFormData.fileName = res.fileName || '';
-        ruleFormData.classifyName = res.classifyName || '';
-        ruleFormData.fileCode = res.fileCode || '';
-        ruleFormData.fileVersion = res.fileVersion || '';
-        ruleFormData.fileFormat = res.fileFormat || '';
-        ruleFormData.releaseDate = res.releaseDate || '';
-        ruleFormData.fileUrl = res.fileUrl || '';
-        ruleFormData.content = res.content || '';
-        ruleFormData.status = res.status ?? 1;
-        
-        // 如果有文件URL,转换为FileItem格式
-        if (res.fileUrl) {
-          uploadFileList.value = [
-            {
-              fileId: Date.now(),
-              fileName: getFileName(res.fileUrl),
-              fileType: res.fileFormat?.toLowerCase() === 'pdf' ? 'pdf' : 'word',
-              fileSize: '0KB',
-            },
-          ];
-        }
+      const detail = await queryChecklistTemplateDetail(props.id);
+      if (!detail) return;
+
+      ruleFormData.value.templateName = detail.templateName || '';
+      ruleFormData.value.categoryName = detail.categoryName || '';
+      ruleFormData.value.categoryCode = detail.categoryCode || '';
+      ruleFormData.value.businessWork = detail.businessWork || '';
+      ruleFormData.value.fillInstruction = detail.fillInstruction || '';
+
+      const items = detail.ChecklistTemplateItem;
+      if (items && items.length > 0) {
+        checkItems.value = items
+          .filter((it) => !it.isDeleted || it.isDeleted === 0)
+          .map((item) => ({
+            id: item.id,
+            templateId: item.templateId,
+            checkContent: item.checkContent || '',
+            checkStandard: item.checkStandard || '',
+            checkResult: item.checkResult || '待检',
+            checkProblem: item.checkProblem || '',
+          }));
       }
-      cloneRuleFormData();
-    } catch (e) {
-      console.error('获取院级文件详情失败:', e);
-      ElMessage.error('获取详情失败');
+      if (checkItems.value.length === 0) checkItems.value = [createEmptyCheckItem()];
+    } catch (e: any) {
+      console.error('获取检查单模版详情失败:', e);
+      ElMessage.error(e?.message || '获取详情失败,请重试');
     }
   };
 
+  const createEmptyCheckItem = (): CheckItemRow => ({
+    checkContent: '',
+    checkStandard: '',
+    checkResult: '待检',
+    checkProblem: '',
+  });
+
+  const validateCheckItems = (): boolean => {
+    for (let i = 0; i < checkItems.value.length; i++) {
+      const item = checkItems.value[i];
+      if (!item.checkContent || !item.checkContent.trim()) {
+        ElMessage.warning(`第 ${i + 1} 行的检查内容不能为空`);
+        return false;
+      }
+    }
+    return true;
+  };
+
   const handleSubmit = async () => {
-    const res = await handleValidate();
-    if (!res) return;
+    const valid = await handleValidate();
+    if (!valid) return;
+
+    if (!validateCheckItems()) return;
+
     try {
-      const basePayload: ProductionSafetyFile = {
-        fileName: ruleFormData.fileName,
-        classifyName: ruleFormData.classifyName,
-        fileCode: ruleFormData.fileCode,
-        fileVersion: ruleFormData.fileVersion,
-        fileFormat: ruleFormData.fileFormat,
-        releaseDate: ruleFormData.releaseDate,
-        fileUrl: ruleFormData.fileUrl || undefined,
-        content: ruleFormData.content || undefined,
-        status: ruleFormData.status ?? 1,
+      const items: ChecklistTemplateItem[] = checkItems.value.map((item) => ({
+        id: item.id,
+        templateId: props.id ?? item.templateId,
+        checkContent: item.checkContent || '',
+        checkStandard: item.checkStandard || '',
+        checkResult: item.checkResult || '待检',
+        checkProblem: item.checkProblem || '',
+        isDeleted: 0,
+      }));
+
+      const payload = {
+        templateName: ruleFormData.value.templateName || '',
+        categoryName: ruleFormData.value.categoryName || '',
+        categoryCode: ruleFormData.value.categoryCode || '',
+        businessWork: ruleFormData.value.businessWork || '',
+        fillInstruction: ruleFormData.value.fillInstruction || '',
+        ChecklistTemplateItem: items,
       };
 
-      if (isCreateMode.value) {
-        await saveAcademyFile(basePayload);
-        ElMessage.success('创建成功');
-      } else if (isEditMode.value && currentId.value) {
-        await updateAcademyFile({
-          id: currentId.value,
-          ...basePayload,
-        });
+      if (isEditMode.value && props.id) {
+        await updateChecklistTemplate({ id: props.id, ...payload });
         ElMessage.success('保存成功');
+      } else {
+        await saveChecklistTemplateList(payload);
+        ElMessage.success('创建成功');
       }
 
       router.back();
-    } catch (e) {
-      console.error('保存院级文件失败:', e);
-      ElMessage.error('保存失败,请重试');
+    } catch (e: any) {
+      console.error('保存检查单模版失败:', e);
+      ElMessage.error(e?.message || '保存失败,请重试');
     }
   };
 
   onMounted(() => {
-    cloneRuleFormData();
-    beforeRouteLeave();
     if (isEditMode.value || isViewMode.value) {
       getDetail();
+    } else {
+      checkItems.value = [createEmptyCheckItem()];
     }
   });
-
-  onBeforeUnmount(() => {
-    const editor = editorRef.value;
-    if (editor == null) return;
-    editor.destroy();
-  });
 </script>
 
 <style scoped lang="scss">
   @use '@/styles/page-details-layout.scss' as *;
 
-  .editor-container {
-    width: 100%;
-    border: 1px solid #dcdfe6;
-    border-radius: 4px;
-    overflow: hidden;
+  .check-template-form {
+    display: flex;
+    flex-direction: column;
+    width: 600px;
+    gap: 32px;
+
+    :deep(.el-form-item) {
+      margin-bottom: 0;
+    }
+
+    :deep(.el-form-item__label) {
+      padding: 0;
+    }
   }
 
-  .content-display {
-    min-height: 200px;
-    padding: 12px;
-    border: 1px solid #dcdfe6;
-    border-radius: 4px;
-    background-color: #f5f7fa;
+  .check-items-section {
+    margin-top: 32px;
   }
 
-  .file-display {
-    .file-link {
-      color: #409eff;
-      text-decoration: none;
-      &:hover {
-        text-decoration: underline;
-      }
-    }
+  .section-header {
+    display: flex;
+    gap: 10px;
+    margin-bottom: 20px;
   }
 
-  .no-file {
-    color: rgba(0, 0, 0, 0.65);
+  .check-items-table {
+    width: 100%;
   }
 </style>
-

+ 17 - 86
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/checkTemplateManagement/configs/form.ts

@@ -1,91 +1,22 @@
-import { FormConfig } from '@/types/basic-form';
-
-export const ACADEMY_FILE_FORM_CONFIG: FormConfig[] = [
-  {
-    prop: 'fileName',
-    label: '文件名称:',
-    component: 'ElInput',
-    componentProps: {
-      placeholder: '请输入文件名称',
-    },
-  },
-  {
-    prop: 'classifyName',
-    label: '分类名称:',
-    component: 'ElSelect',
-    componentProps: {
-      placeholder: '请选择分类名称',
-    },
-    selectOptions: [
-      { label: '外部院级文件', value: '外部院级文件' },
-      { label: '内部院级文件', value: '内部院级文件' },
-    ],
-  },
-  {
-    prop: 'fileCode',
-    label: '文件编号:',
-    component: 'ElInput',
-    componentProps: {
-      placeholder: '请输入文件编号',
-    },
-  },
-  {
-    prop: 'fileVersion',
-    label: '文件版本号:',
-    component: 'ElInput',
-    componentProps: {
-      placeholder: '请输入文件版本号,如:V1.0',
-    },
-  },
-  {
-    prop: 'fileFormat',
-    label: '文件格式:',
-    slot: 'fileFormat',
-  },
-  {
-    prop: 'releaseDate',
-    label: '发布日期:',
-    component: 'ElDatePicker',
-    componentProps: {
-      type: 'date',
-      placeholder: '请选择发布日期',
-      valueFormat: 'YYYY-MM-DD',
-    },
-  },
-  {
-    prop: 'fileUrl',
-    label: '文件上传:',
-    slot: 'fileUrl',
-  },
-  {
-    prop: 'content',
-    label: '文档内容:',
-    slot: 'content',
-  },
-  {
-    prop: 'status',
-    label: '状态:',
-    slot: 'status',
-  },
+/** 检查单模版类别:对应接口 categoryName / categoryCode */
+export const CHECK_TEMPLATE_CATEGORY_OPTIONS = [
+  { label: '安全管理检查单', categoryName: '安全管理检查单', categoryCode: 'SAFETY_MANAGEMENT' },
+  { label: '关键业务活动专项检查单', categoryName: '关键业务活动专项检查单', categoryCode: 'KEY_BUSINESS' },
+  { label: '日常安全检查单', categoryName: '日常安全检查单', categoryCode: 'DAILY_SAFETY' },
 ];
 
-export const ACADEMY_FILE_FORM_DATA = {
-  fileName: '',
-  classifyName: '',
-  fileCode: '',
-  fileVersion: '',
-  fileFormat: '',
-  releaseDate: '',
-  fileUrl: '',
-  content: '',
-  status: 1, // 默认启用
+export const CHECK_TEMPLATE_FORM_DATA = {
+  templateName: '',
+  categoryName: '' as string,
+  categoryCode: '' as string,
+  businessWork: '',
+  fillInstruction: '',
+  status: 1,
 };
 
-export const ACADEMY_FILE_FORM_RULES = {
-  fileName: [{ required: true, message: '请输入文件名称', trigger: 'blur' }],
-  classifyName: [{ required: true, message: '请选择分类名称', trigger: 'change' }],
-  fileCode: [{ required: true, message: '请输入文件编号', trigger: 'blur' }],
-  fileVersion: [{ required: true, message: '请输入文件版本号', trigger: 'blur' }],
-  fileFormat: [{ required: true, message: '请选择文件格式', trigger: 'change' }],
-  releaseDate: [{ required: true, message: '请选择发布日期', trigger: 'change' }],
+export const CHECK_TEMPLATE_FORM_RULES = {
+  templateName: [{ required: true, message: '请输入检查单模版名称', trigger: 'blur' }],
+  categoryName: [{ required: true, message: '请选择类别名称', trigger: 'change' }],
+  businessWork: [{ required: true, message: '请输入业务工作', trigger: 'blur' }],
+  fillInstruction: [{ required: true, message: '请输入填写说明', trigger: 'blur' }],
 };

+ 27 - 20
src/views/production-safety/hiddenTroubleInvestigationAndGovernance/checkTemplateManagement/configs/tables.ts

@@ -7,7 +7,8 @@ export const TABLE_OPTIONS = {
   maxHeight: 'calc(70vh - 150px)',
 };
 
-export const INVENTORY_TABLE_COLUMNS: TableColumnProps[] = [
+// 检查单模版列表字段:编号,模版名称,状态,类别名称,使用次数,备注,修改用户名称,修改时间,操作
+export const CHECK_TEMPLATE_TABLE_COLUMNS: TableColumnProps[] = [
   {
     label: '编号',
     type: 'index',
@@ -15,41 +16,47 @@ export const INVENTORY_TABLE_COLUMNS: TableColumnProps[] = [
     width: '80px',
   },
   {
-    label: '物品名称',
-    prop: 'itemName',
+    label: '模版名称',
+    prop: 'templateName',
     align: 'left',
-    minWidth: '120px',
+    minWidth: '150px',
+  },
+  {
+    label: '状态',
+    prop: 'status',
+    slot: 'status',
+    align: 'center',
+    minWidth: '100px',
   },
   {
-    label: '入库日期',
-    prop: 'warehouseDate',
+    label: '类别名称',
+    prop: 'categoryName',
     align: 'left',
     minWidth: '120px',
   },
   {
-    label: '物品数量',
-    prop: 'itemQuantity',
+    label: '使用次数',
+    prop: 'useCount',
     align: 'center',
-    minWidth: '120px',
+    minWidth: '100px',
   },
   {
-    label: '经办人',
-    prop: 'handler',
+    label: '备注',
+    prop: 'remark',
     align: 'left',
-    minWidth: '120px',
+    minWidth: '150px',
   },
   {
-    label: '备注',
-    prop: 'remarks',
+    label: '修改用户名称',
+    prop: 'updateUserName',
     align: 'left',
-    minWidth: '150px',
+    minWidth: '120px',
   },
   {
-    label: '状态',
-    prop: 'status',
-    slot: 'status',
-    align: 'center',
-    minWidth: '100px',
+    label: '修改时间',
+    prop: 'updatedAt',
+    align: 'left',
+    minWidth: '160px',
   },
   {
     label: '操作',

+ 5 - 0
src/views/production-safety/safetyAssessment/evaluationSystem/components/EvaluationSystemAdvancedPerson.vue

@@ -584,9 +584,14 @@
           ElMessage.error('缺少编辑记录数据,无法保存');
           return;
         }
+        if (!evaluationId.value) {
+          ElMessage.error('缺少考核表ID,无法保存');
+          return;
+        }
 
         const updatePayload: UpdateSecurityExamineAdvUserAdminRequest = {
           ...editDetailData.value,
+          psemId: evaluationId.value,
           advUserStaffNo: normalForm.employeeCode,
           advUserName: normalForm.employeeName,
           advUserLink: normalForm.employeeContact,