|
|
@@ -1,264 +1,638 @@
|
|
|
<template>
|
|
|
- <main class="safety-platform-container__main">
|
|
|
- <BasicForm
|
|
|
- ref="basicFormRef"
|
|
|
- :formData="ruleFormData"
|
|
|
- :formRules="isViewMode ? undefined : formRules"
|
|
|
- :formConfig="computedFormConfig"
|
|
|
- >
|
|
|
- <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"
|
|
|
- />
|
|
|
- <div v-else-if="ruleFormData.fileUrl" class="file-display">
|
|
|
- <a :href="ruleFormData.fileUrl" target="_blank" class="file-link">{{ getFileName(ruleFormData.fileUrl) }}</a>
|
|
|
+ <!-- 区域检查计划管理(部门)查看:与管理员查看样式一致 -->
|
|
|
+ <main class="safety-platform-container__main area-check-plan-view">
|
|
|
+ <section class="view-section view-summary">
|
|
|
+ <div class="view-summary__title">一级危险点:{{ viewDetail.checkVenue || '-' }}</div>
|
|
|
+ <div class="view-summary__meta">
|
|
|
+ <span>检查类别:{{ viewDetail.venueCategoryName || '-' }}</span>
|
|
|
+ <span>创建人:{{ viewDetail.createdBy || '李小红' }}</span>
|
|
|
+ <span>创建时间:{{ viewDetail.createdAt || '2026-01-06 12:20:30' }}</span>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="view-section audit-content">
|
|
|
+ <h4 class="section-title">
|
|
|
+ <el-icon class="section-title__icon"><Document /></el-icon>
|
|
|
+ <span>基本信息</span>
|
|
|
+ </h4>
|
|
|
+ <div class="detail-ct detail-ct--table">
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">区域计划名称:</div>
|
|
|
+ <div class="value">{{ viewDetail.planName || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">状态:</div>
|
|
|
+ <div class="value">{{ viewDetail.statusName || '进行中' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">主责部门:</div>
|
|
|
+ <div class="value">{{ viewDetail.mainDeptName || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">自查频率:</div>
|
|
|
+ <div class="value">{{ viewDetail.selfCheckFrequency || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">主责部门执行人所属分组名称:</div>
|
|
|
+ <div class="value">{{ viewDetail.mainDeptExecutorGroupName || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">主责部门责任人:</div>
|
|
|
+ <div class="value">{{ viewDetail.mainDeptResponsiblePerson || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">安全应急部部门名称:</div>
|
|
|
+ <div class="value">{{ viewDetail.safetyEmergencyDeptName || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">安全应急部检查频次:</div>
|
|
|
+ <div class="value">{{ viewDetail.safetyEmergencyCheckFrequency || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">安全应急部执行人所属分组名称:</div>
|
|
|
+ <div class="value">{{ viewDetail.safetyEmergencyExecutorGroupName || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">安全应急部责任人:</div>
|
|
|
+ <div class="value">{{ viewDetail.safetyEmergencyResponsiblePerson || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">院领导部门名称:</div>
|
|
|
+ <div class="value">{{ viewDetail.hospitalLeaderDeptName || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">院领导检查频次:</div>
|
|
|
+ <div class="value">{{ viewDetail.hospitalLeaderCheckFrequency || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">院领导执行人所属分组名称:</div>
|
|
|
+ <div class="value">{{ viewDetail.hospitalLeaderExecutorGroupName || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">院领导责任人:</div>
|
|
|
+ <div class="value">{{ viewDetail.hospitalLeaderResponsiblePerson || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">检查单所属类别名称:</div>
|
|
|
+ <div class="value">{{ viewDetail.checklistCategoryName || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">检查单模版名称:</div>
|
|
|
+ <div class="value">{{ viewDetail.checklistTemplateName || '-' }}</div>
|
|
|
+ </div>
|
|
|
</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"
|
|
|
- />
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">是否需要整体检查情况描述:</div>
|
|
|
+ <div class="value">{{ viewDetail.needOverallDesc === true ? '是' : viewDetail.needOverallDesc === false ? '否' : '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">是否需要被检查人签字:</div>
|
|
|
+ <div class="value">{{ viewDetail.needInspectedSign === true ? '是' : viewDetail.needInspectedSign === false ? '否' : '-' }}</div>
|
|
|
+ </div>
|
|
|
</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>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">计划开始日期:</div>
|
|
|
+ <div class="value">{{ viewDetail.planStartTime || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">计划完成日期:</div>
|
|
|
+ <div class="value">{{ viewDetail.planEndTime || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">检查内容:</div>
|
|
|
+ <div class="value value--list">
|
|
|
+ <ol class="inspection-content-list">
|
|
|
+ <li v-for="(item, i) in inspectionContentList" :key="i">{{ item }}</li>
|
|
|
+ </ol>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="col">
|
|
|
+ <div class="label">业务工作:</div>
|
|
|
+ <div class="value">{{ viewDetail.businessWork || '动火作业' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="view-section">
|
|
|
+ <div class="view-section__title">
|
|
|
+ <span class="view-section__icon" />
|
|
|
+ 检查记录
|
|
|
+ </div>
|
|
|
+ <div class="view-record-toolbar">
|
|
|
+ <el-input
|
|
|
+ v-model="recordSearchKeyword"
|
|
|
+ placeholder="检查场所类别/检查场所/检查人员"
|
|
|
+ clearable
|
|
|
+ style="width: 280px; margin-right: 12px"
|
|
|
+ />
|
|
|
+ <el-date-picker
|
|
|
+ v-model="recordDateRange"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="-"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ style="margin-right: 12px"
|
|
|
+ />
|
|
|
+ <el-button type="primary" @click="onRecordSearch">查询</el-button>
|
|
|
+ <el-button @click="onRecordExport">导出</el-button>
|
|
|
+ <el-button type="primary" @click="onAddRecord">新增检查日志</el-button>
|
|
|
+ </div>
|
|
|
+ <BasicTable
|
|
|
+ :tableData="paginatedRecordList"
|
|
|
+ :tableConfig="recordTableConfig"
|
|
|
+ class="view-record-table"
|
|
|
+ @update:pageSize="handleRecordSizeChange"
|
|
|
+ @update:pageNumber="handleRecordPageChange"
|
|
|
+ >
|
|
|
+ <template #sign="scope">
|
|
|
+ <template v-if="parseSignFiles(scope.row.signFile).length">
|
|
|
+ <div
|
|
|
+ class="file-container--div"
|
|
|
+ v-for="item in parseSignFiles(scope.row.signFile)"
|
|
|
+ :key="item.fileUrl || item.fileName"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="file-container--div__icon"
|
|
|
+ :src="FILE_TYPE_ICON[item.fileType as keyof typeof FILE_TYPE_ICON]"
|
|
|
+ @click="previewOnline(item.fileUrl, item.fileType as keyof typeof FILE_TYPE_ICON)"
|
|
|
+ />
|
|
|
+ <span
|
|
|
+ class="file-container--div__name"
|
|
|
+ @click="previewOnline(item.fileUrl, item.fileType as keyof typeof FILE_TYPE_ICON)"
|
|
|
+ >{{ item.fileName }}</span
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="file-container--div__download"
|
|
|
+ :src="DownloadIcon"
|
|
|
+ @click="downloadFile(item.fileUrl, item.fileName)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <span v-else>-</span>
|
|
|
+ </template>
|
|
|
+ <template #action="scope">
|
|
|
+ <el-button type="primary" link size="small" @click="onViewRecord(scope.row)">检查记录查看</el-button>
|
|
|
+ </template>
|
|
|
+ </BasicTable>
|
|
|
+ </section>
|
|
|
</main>
|
|
|
- <footer class="safety-platform-container__footer">
|
|
|
- <el-button @click="router.back()">返回</el-button>
|
|
|
- <el-button v-if="!isViewMode" type="primary" @click="handleSubmit">
|
|
|
- {{ isCreateMode ? '提交' : '保存' }}
|
|
|
- </el-button>
|
|
|
- </footer>
|
|
|
+ <PreviewOnline ref="previewOnlineRef" />
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
- import { computed, onMounted, ref, shallowRef, onBeforeUnmount } from 'vue';
|
|
|
+ import { computed, onMounted, ref, watch } 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 {
|
|
|
- queryAcademyFileById,
|
|
|
- saveAcademyFile,
|
|
|
- updateAcademyFile,
|
|
|
- type ProductionSafetyFile,
|
|
|
- } from '@/api/production-safety-system';
|
|
|
- import type { FileItem } from '@/components/UploadFiles/types';
|
|
|
+ import { Document } from '@element-plus/icons-vue';
|
|
|
+ import BasicTable from '@/components/BasicTable.vue';
|
|
|
+ import { FILE_TYPE_ICON } from '@/components/UploadFiles/constants';
|
|
|
+ import DownloadIcon from '@/views/disaster/disaster-control/src/svg/download.svg';
|
|
|
+ import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
|
|
|
+ import { downloadFile } from '@/views/disaster/utils';
|
|
|
+ import useTableConfig from '@/hooks/useTableConfigHook';
|
|
|
+ import type { TableColumnProps } from '@/types/basic-table';
|
|
|
+ import type { AreaCheckPlanRecord } from '../../areaCheckPlanManagement/configs/types';
|
|
|
+ import { AREA_CHECK_PLAN_STATUS_LABEL } from '../../areaCheckPlanManagement/configs/status';
|
|
|
|
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
|
|
|
|
- const operate = computed(() => (route.query.operate as string) || 'area-check-plan-dept-create');
|
|
|
const currentId = computed(() => Number(route.query.id));
|
|
|
|
|
|
- const isCreateMode = computed(() => operate.value === 'area-check-plan-dept-create');
|
|
|
- const isEditMode = computed(() => operate.value === 'area-check-plan-dept-edit');
|
|
|
- const isViewMode = computed(() => operate.value === 'area-check-plan-dept-view');
|
|
|
+ const viewDetailData = ref<Record<string, unknown>>({});
|
|
|
+ const viewDetail = computed(() => {
|
|
|
+ const d = viewDetailData.value;
|
|
|
+ const status = d?.status as number | undefined;
|
|
|
+ return {
|
|
|
+ ...d,
|
|
|
+ statusName: status != null ? AREA_CHECK_PLAN_STATUS_LABEL[String(status)] ?? '-' : '-',
|
|
|
+ planName: d?.planName ?? '-',
|
|
|
+ venueCategoryName: d?.venueCategoryName ?? '-',
|
|
|
+ checkVenue: d?.checkVenue ?? '-',
|
|
|
+ mainDeptName: d?.mainDeptName ?? '-',
|
|
|
+ selfCheckFrequency: d?.selfCheckFrequency ?? '-',
|
|
|
+ mainDeptExecutorGroupName: d?.mainDeptExecutorGroupName ?? '-',
|
|
|
+ mainDeptResponsiblePerson: d?.mainDeptResponsiblePerson ?? '-',
|
|
|
+ safetyEmergencyDeptName: d?.safetyEmergencyDeptName ?? '-',
|
|
|
+ safetyEmergencyCheckFrequency: d?.safetyEmergencyCheckFrequency ?? '-',
|
|
|
+ safetyEmergencyExecutorGroupName: d?.safetyEmergencyExecutorGroupName ?? '-',
|
|
|
+ safetyEmergencyResponsiblePerson: d?.safetyEmergencyResponsiblePerson ?? '-',
|
|
|
+ hospitalLeaderDeptName: d?.hospitalLeaderDeptName ?? '-',
|
|
|
+ hospitalLeaderCheckFrequency: d?.hospitalLeaderCheckFrequency ?? '-',
|
|
|
+ hospitalLeaderExecutorGroupName: d?.hospitalLeaderExecutorGroupName ?? '-',
|
|
|
+ hospitalLeaderResponsiblePerson: d?.hospitalLeaderResponsiblePerson ?? '-',
|
|
|
+ checklistCategoryName: d?.checklistCategoryName ?? '-',
|
|
|
+ checklistTemplateName: d?.checklistTemplateName ?? '-',
|
|
|
+ needOverallDesc: d?.needOverallDesc,
|
|
|
+ needInspectedSign: d?.needInspectedSign,
|
|
|
+ planStartTime: d?.planStartTime ?? '-',
|
|
|
+ planEndTime: d?.planEndTime ?? '-',
|
|
|
+ createdBy: d?.createdBy ?? '李小红',
|
|
|
+ createdAt: d?.createdAt ?? '2026-01-06 12:20:30',
|
|
|
+ businessWork: d?.businessWork ?? '动火作业',
|
|
|
+ };
|
|
|
+ });
|
|
|
|
|
|
- const { ruleFormData, formRules, ruleFormConfig, cloneRuleFormData, beforeRouteLeave } =
|
|
|
- useFormConfigHook(ACADEMY_FILE_FORM_CONFIG, ACADEMY_FILE_FORM_DATA, ACADEMY_FILE_FORM_RULES);
|
|
|
+ const inspectionContentList = computed(() => {
|
|
|
+ const content = (viewDetailData.value?.checkKeyContent ?? '') as string;
|
|
|
+ if (!content || typeof content !== 'string') {
|
|
|
+ return [
|
|
|
+ '工作场所布局是否合理,通道是否畅通;',
|
|
|
+ '各种机械、电力、电气等设备的安装和使用是否符合安全技术要求;',
|
|
|
+ '安全防护装置是否齐全、灵敏、有效;',
|
|
|
+ '易燃易爆、有限空间和高处作业等作业场所是否符合安全条件;',
|
|
|
+ '有较大危险因素和职业危害因素的科研试验场所和有关;',
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ return content.split(/[;;]/).map((s) => s.trim()).filter(Boolean);
|
|
|
+ });
|
|
|
|
|
|
- // 查看模式下,所有字段设为只读
|
|
|
- const viewFormConfig = ref(
|
|
|
- ACADEMY_FILE_FORM_CONFIG.map((item) => ({
|
|
|
- ...item,
|
|
|
- componentProps: {
|
|
|
- ...item.componentProps,
|
|
|
- disabled: true,
|
|
|
- },
|
|
|
- })),
|
|
|
+ const RECORD_TABLE_COLUMNS: TableColumnProps[] = [
|
|
|
+ { label: '编号', type: 'index', align: 'center', width: '60px' },
|
|
|
+ { label: '检查时间', prop: 'inspectionTime', minWidth: '160px' },
|
|
|
+ { label: '检查人员', prop: 'inspector', minWidth: '100px' },
|
|
|
+ { label: '检查场所类别', prop: 'venueCategory', minWidth: '120px' },
|
|
|
+ { label: '检查场所', prop: 'venue', minWidth: '120px' },
|
|
|
+ { label: '检查项总数', prop: 'totalItems', align: 'center', width: '100px' },
|
|
|
+ { label: '合格项数', prop: 'qualifiedItems', align: 'center', width: '90px' },
|
|
|
+ { label: '不合格项数', prop: 'unqualifiedItems', align: 'center', width: '100px' },
|
|
|
+ { label: '整体检查情况描述', prop: 'overallDesc', minWidth: '180px', showOverflowTooltip: true },
|
|
|
+ { label: '被检查人签字', slot: 'sign', align: 'center', width: '140px' },
|
|
|
+ { label: '操作', slot: 'action', align: 'center', width: '160px', 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 computedFormConfig = computed(() => {
|
|
|
- if (isViewMode.value) {
|
|
|
- return viewFormConfig.value;
|
|
|
- }
|
|
|
- return ruleFormConfig.value;
|
|
|
+ const recordSearchKeyword = ref('');
|
|
|
+ const recordDateRange = ref<[string, string] | null>(null);
|
|
|
+ const inspectionRecordList = ref([
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ inspectionTime: '2025-03-28 10:00:00',
|
|
|
+ inspector: '孙菲',
|
|
|
+ venueCategory: '各级风险点',
|
|
|
+ venue: '18号楼',
|
|
|
+ totalItems: '25项',
|
|
|
+ qualifiedItems: '20项',
|
|
|
+ unqualifiedItems: '5项',
|
|
|
+ overallDesc: '学习宣传贯彻习近平…',
|
|
|
+ signFile: '领导签字文件.pdf',
|
|
|
+ },
|
|
|
+ ]);
|
|
|
+
|
|
|
+ const paginatedRecordList = computed(() => {
|
|
|
+ const list = inspectionRecordList.value;
|
|
|
+ const start = (recordPagination.pageNumber - 1) * recordPagination.pageSize;
|
|
|
+ return list.slice(start, start + recordPagination.pageSize);
|
|
|
});
|
|
|
|
|
|
- const basicFormRef = ref<InstanceType<typeof BasicForm>>();
|
|
|
-
|
|
|
- // 富文本编辑器
|
|
|
- const editorRef = shallowRef();
|
|
|
- const editorConfig = {
|
|
|
- placeholder: '请输入文档内容',
|
|
|
- MENU_CONF: {},
|
|
|
- };
|
|
|
+ watch(
|
|
|
+ () => inspectionRecordList.value.length,
|
|
|
+ (len) => {
|
|
|
+ recordPagination.total = len;
|
|
|
+ },
|
|
|
+ { immediate: true },
|
|
|
+ );
|
|
|
|
|
|
- const handleEditorCreated = (editor: any) => {
|
|
|
- editorRef.value = editor;
|
|
|
+ const handleRecordSizeChange = (value: number) => {
|
|
|
+ recordPagination.pageSize = value;
|
|
|
+ recordPagination.pageNumber = 1;
|
|
|
};
|
|
|
-
|
|
|
- const handleEditorChange = () => {
|
|
|
- // 编辑器内容变化时的处理
|
|
|
+ const handleRecordPageChange = (value: number) => {
|
|
|
+ recordPagination.pageNumber = value;
|
|
|
};
|
|
|
|
|
|
- // 文件上传
|
|
|
- const uploadFileList = ref<FileItem[]>([]);
|
|
|
+ const onRecordSearch = () => {
|
|
|
+ ElMessage.info('查询检查记录');
|
|
|
+ };
|
|
|
+ const onRecordExport = () => {
|
|
|
+ ElMessage.success('导出功能开发中');
|
|
|
+ };
|
|
|
|
|
|
- const handleUploadSuccess = (files: FileItem[]) => {
|
|
|
- uploadFileList.value = files;
|
|
|
- if (files.length > 0 && files[0].file) {
|
|
|
- // 这里需要实际上传文件到服务器,获取 fileUrl
|
|
|
- // 暂时使用文件对象,实际应该调用上传接口
|
|
|
- ruleFormData.fileUrl = files[0].file.name; // 临时处理,需要替换为实际上传后的URL
|
|
|
- }
|
|
|
+ const onAddRecord = () => {
|
|
|
+ router.push({
|
|
|
+ name: 'areaCheckPlanManagementDeptItem',
|
|
|
+ query: {
|
|
|
+ operate: 'area-check-plan-record-add',
|
|
|
+ planId: currentId.value,
|
|
|
+ planName: viewDetail.value.planName,
|
|
|
+ checkVenue: viewDetail.value.checkVenue,
|
|
|
+ },
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
- const getFileName = (url: string) => {
|
|
|
- if (!url) return '';
|
|
|
- const parts = url.split('/');
|
|
|
- return parts[parts.length - 1];
|
|
|
+ const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
|
|
|
+ const previewOnline = (url: string | undefined, type: keyof typeof FILE_TYPE_ICON) => {
|
|
|
+ if (url) previewOnlineRef.value?.open(url, type);
|
|
|
};
|
|
|
|
|
|
- const handleValidate = async () => {
|
|
|
- if (!basicFormRef.value) return;
|
|
|
- const res = await basicFormRef.value.validateForm();
|
|
|
- return res;
|
|
|
+ const parseSignFiles = (signFile: string | undefined): Array<{ fileUrl: string; fileName: string; fileType: string }> => {
|
|
|
+ if (!signFile || !String(signFile).trim()) return [];
|
|
|
+ const parts = String(signFile)
|
|
|
+ .split(',')
|
|
|
+ .map((s) => s.trim())
|
|
|
+ .filter(Boolean);
|
|
|
+ return parts.map((part) => {
|
|
|
+ const urlParts = part.split('/');
|
|
|
+ const fileName = urlParts[urlParts.length - 1] || part || '未知文件';
|
|
|
+ const extension = fileName.split('.').pop()?.toLowerCase() || '';
|
|
|
+ let fileType = 'pdf';
|
|
|
+ if (extension === 'doc' || extension === 'docx') fileType = 'word';
|
|
|
+ else if (extension === 'xls' || extension === 'xlsx') fileType = 'excel';
|
|
|
+ else if (extension === 'ppt' || extension === 'pptx') fileType = 'ppt';
|
|
|
+ return { fileUrl: part, fileName, fileType };
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
- const getDetail = async () => {
|
|
|
- if (!currentId.value) 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',
|
|
|
- },
|
|
|
- ];
|
|
|
- }
|
|
|
- }
|
|
|
- cloneRuleFormData();
|
|
|
- } catch (e) {
|
|
|
- console.error('获取院级文件详情失败:', e);
|
|
|
- ElMessage.error('获取详情失败');
|
|
|
- }
|
|
|
+ const onViewRecord = (row: { id?: number; inspector?: string; inspectionTime?: string; venue?: string; overallDesc?: string; signFile?: string }) => {
|
|
|
+ router.push({
|
|
|
+ name: 'areaCheckPlanManagementDeptItem',
|
|
|
+ query: {
|
|
|
+ operate: 'area-check-plan-record-view',
|
|
|
+ id: row.id,
|
|
|
+ inspectedUnit: viewDetail.value.mainDeptName || viewDetail.value.checkVenue || '',
|
|
|
+ inspector: row.inspector || '',
|
|
|
+ checkTime: row.inspectionTime || '',
|
|
|
+ checkPlace: row.venue || '',
|
|
|
+ overallDesc: row.overallDesc || '',
|
|
|
+ signFile: row.signFile || '',
|
|
|
+ },
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
- const handleSubmit = async () => {
|
|
|
- const res = await handleValidate();
|
|
|
- if (!res) 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,
|
|
|
- };
|
|
|
-
|
|
|
- if (isCreateMode.value) {
|
|
|
- await saveAcademyFile(basePayload);
|
|
|
- ElMessage.success('创建成功');
|
|
|
- } else if (isEditMode.value && currentId.value) {
|
|
|
- await updateAcademyFile({
|
|
|
- id: currentId.value,
|
|
|
- ...basePayload,
|
|
|
- });
|
|
|
- ElMessage.success('保存成功');
|
|
|
- }
|
|
|
+ /** 详情 mock 数据(与列表 MOCK_LIST 对应) */
|
|
|
+ const MOCK_DETAIL_MAP: Record<number, AreaCheckPlanRecord> = {
|
|
|
+ 1: {
|
|
|
+ id: 1,
|
|
|
+ planName: '2025年度生产安全检查计划',
|
|
|
+ status: 1,
|
|
|
+ checkVenue: '18号楼、油库、液氮罐',
|
|
|
+ venueCategoryName: '各级风险点',
|
|
|
+ mainDeptName: '试验验证中心、质量管理部',
|
|
|
+ selfCheckFrequency: '每日',
|
|
|
+ mainDeptExecutorGroupName: '自查小分队分组',
|
|
|
+ mainDeptResponsiblePerson: '孙菲、周萍',
|
|
|
+ safetyEmergencyDeptName: '安全应急部',
|
|
|
+ safetyEmergencyCheckFrequency: '每周',
|
|
|
+ safetyEmergencyExecutorGroupName: '安全应急部小分队分组',
|
|
|
+ safetyEmergencyResponsiblePerson: '李雪峰',
|
|
|
+ hospitalLeaderDeptName: '院领导',
|
|
|
+ hospitalLeaderCheckFrequency: '每季度',
|
|
|
+ hospitalLeaderExecutorGroupName: '领导小分队执行组',
|
|
|
+ hospitalLeaderResponsiblePerson: '孙菲亚',
|
|
|
+ checklistCategoryName: '安全管理检查单',
|
|
|
+ checklistTemplateName: '上飞院安全检查表',
|
|
|
+ needOverallDesc: true,
|
|
|
+ needInspectedSign: true,
|
|
|
+ planStartTime: '2019-03-28',
|
|
|
+ planEndTime: '2019-03-28',
|
|
|
+ createdBy: '李小红',
|
|
|
+ createdAt: '2026-01-06 12:20:30',
|
|
|
+ businessWork: '动火作业',
|
|
|
+ checkKeyContent: '工作场所布局是否合理,通道是否畅通;各种机械、电力、电气等设备的安装和使用是否符合安全技术要求;安全防护装置是否齐全、灵敏、有效;易燃易爆、有限空间和高处作业等作业场所是否符合安全条件',
|
|
|
+ },
|
|
|
+ 2: {
|
|
|
+ id: 2,
|
|
|
+ planName: '2025年一季度专项检查计划',
|
|
|
+ status: 0,
|
|
|
+ checkVenue: '试验车间、配电间',
|
|
|
+ venueCategoryName: '关键业务活动',
|
|
|
+ mainDeptName: '生产保障部',
|
|
|
+ selfCheckFrequency: '每周',
|
|
|
+ mainDeptExecutorGroupName: '安全员分组',
|
|
|
+ mainDeptResponsiblePerson: '张三',
|
|
|
+ safetyEmergencyDeptName: '安全应急部',
|
|
|
+ safetyEmergencyCheckFrequency: '每月',
|
|
|
+ safetyEmergencyExecutorGroupName: '应急值班组',
|
|
|
+ safetyEmergencyResponsiblePerson: '李四',
|
|
|
+ hospitalLeaderDeptName: '院领导',
|
|
|
+ hospitalLeaderCheckFrequency: '每半年',
|
|
|
+ hospitalLeaderExecutorGroupName: '领导检查组',
|
|
|
+ hospitalLeaderResponsiblePerson: '王五',
|
|
|
+ checklistCategoryName: '关键业务活动专项检查单',
|
|
|
+ checklistTemplateName: '关键业务活动专项检查单',
|
|
|
+ needOverallDesc: false,
|
|
|
+ needInspectedSign: true,
|
|
|
+ planStartTime: '2025-01-01',
|
|
|
+ planEndTime: '2025-03-31',
|
|
|
+ createdBy: '李小红',
|
|
|
+ createdAt: '2026-01-06 12:20:30',
|
|
|
+ businessWork: '动火作业',
|
|
|
+ checkKeyContent: '设备安全;电气安全',
|
|
|
+ },
|
|
|
+ };
|
|
|
|
|
|
- router.back();
|
|
|
- } catch (e) {
|
|
|
- console.error('保存院级文件失败:', e);
|
|
|
- ElMessage.error('保存失败,请重试');
|
|
|
- }
|
|
|
+ const getDetail = () => {
|
|
|
+ if (!currentId.value) return;
|
|
|
+ const res = MOCK_DETAIL_MAP[currentId.value] ?? {
|
|
|
+ id: currentId.value,
|
|
|
+ planName: '2025年度生产安全检查计划',
|
|
|
+ status: 1,
|
|
|
+ checkVenue: '18号楼、油库、液氮罐',
|
|
|
+ venueCategoryName: '各级风险点',
|
|
|
+ mainDeptName: '试验验证中心、质量管理部',
|
|
|
+ selfCheckFrequency: '每日',
|
|
|
+ mainDeptExecutorGroupName: '自查小分队分组',
|
|
|
+ mainDeptResponsiblePerson: '孙菲、周萍',
|
|
|
+ safetyEmergencyDeptName: '安全应急部',
|
|
|
+ safetyEmergencyCheckFrequency: '每周',
|
|
|
+ safetyEmergencyExecutorGroupName: '安全应急部小分队分组',
|
|
|
+ safetyEmergencyResponsiblePerson: '李雪峰',
|
|
|
+ hospitalLeaderDeptName: '院领导',
|
|
|
+ hospitalLeaderCheckFrequency: '每季度',
|
|
|
+ hospitalLeaderExecutorGroupName: '领导小分队执行组',
|
|
|
+ hospitalLeaderResponsiblePerson: '孙菲亚',
|
|
|
+ checklistCategoryName: '安全管理检查单',
|
|
|
+ checklistTemplateName: '上飞院安全检查表',
|
|
|
+ needOverallDesc: true,
|
|
|
+ needInspectedSign: true,
|
|
|
+ planStartTime: '2019-03-28',
|
|
|
+ planEndTime: '2019-03-28',
|
|
|
+ createdBy: '李小红',
|
|
|
+ createdAt: '2026-01-06 12:20:30',
|
|
|
+ businessWork: '动火作业',
|
|
|
+ checkKeyContent: '',
|
|
|
+ };
|
|
|
+ viewDetailData.value = { ...res };
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
- cloneRuleFormData();
|
|
|
- beforeRouteLeave();
|
|
|
- if (isEditMode.value || isViewMode.value) {
|
|
|
- getDetail();
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- onBeforeUnmount(() => {
|
|
|
- const editor = editorRef.value;
|
|
|
- if (editor == null) return;
|
|
|
- editor.destroy();
|
|
|
+ getDetail();
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
@use '@/styles/page-details-layout.scss' as *;
|
|
|
+ @use '@/styles/basic-table-file.scss' as *;
|
|
|
|
|
|
- .editor-container {
|
|
|
- width: 100%;
|
|
|
- border: 1px solid #dcdfe6;
|
|
|
- border-radius: 4px;
|
|
|
- overflow: hidden;
|
|
|
+ .area-check-plan-view {
|
|
|
+ padding: 16px 24px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 24px;
|
|
|
}
|
|
|
|
|
|
- .content-display {
|
|
|
- min-height: 200px;
|
|
|
- padding: 12px;
|
|
|
- border: 1px solid #dcdfe6;
|
|
|
- border-radius: 4px;
|
|
|
- background-color: #f5f7fa;
|
|
|
+ .view-section {
|
|
|
+ .view-section__title {
|
|
|
+ font-weight: 600;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+ &--small {
|
|
|
+ font-size: 13px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .view-section__icon {
|
|
|
+ width: 4px;
|
|
|
+ height: 14px;
|
|
|
+ background: var(--el-color-primary);
|
|
|
+ border-radius: 2px;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .file-display {
|
|
|
- .file-link {
|
|
|
- color: #409eff;
|
|
|
- text-decoration: none;
|
|
|
- &:hover {
|
|
|
- text-decoration: underline;
|
|
|
+ .view-summary {
|
|
|
+ .view-summary__title {
|
|
|
+ font-weight: 600;
|
|
|
+ font-size: 15px;
|
|
|
+ margin-bottom: 4px;
|
|
|
+ }
|
|
|
+ .view-summary__venue {
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+ .view-summary__meta {
|
|
|
+ font-size: 13px;
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
+ span + span {
|
|
|
+ margin-left: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .audit-content {
|
|
|
+ .section-title {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ margin: 20px 0 12px 0;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+
|
|
|
+ .section-title__icon {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-title:first-child {
|
|
|
+ margin-top: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-ct {
|
|
|
+ font-size: 14px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+
|
|
|
+ &--table {
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ .row {
|
|
|
+ display: flex;
|
|
|
+ border-bottom: 1px solid #dcdfe6;
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .col {
|
|
|
+ display: flex;
|
|
|
+ flex: 1;
|
|
|
+ min-height: 40px;
|
|
|
+ align-items: stretch;
|
|
|
+
|
|
|
+ .label {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-end;
|
|
|
+ flex-shrink: 0;
|
|
|
+ width: 200px;
|
|
|
+ padding: 0 12px;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ border-right: 1px solid #dcdfe6;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ .value {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 10px 20px;
|
|
|
+ background-color: #fff;
|
|
|
+ border-right: 1px solid #dcdfe6;
|
|
|
+ color: #333;
|
|
|
+
|
|
|
+ &--list {
|
|
|
+ align-items: flex-start;
|
|
|
+ .inspection-content-list {
|
|
|
+ margin: 0;
|
|
|
+ padding-left: 20px;
|
|
|
+ line-height: 1.8;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .row .col:last-child .value {
|
|
|
+ border-right: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .row .col:nth-child(2) .label {
|
|
|
+ border-left: 1px solid #dcdfe6;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .no-file {
|
|
|
- color: rgba(0, 0, 0, 0.65);
|
|
|
+ .view-record-toolbar {
|
|
|
+ margin-bottom: 12px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
}
|
|
|
-</style>
|
|
|
|
|
|
+ .view-record-table {
|
|
|
+ margin-bottom: 16px;
|
|
|
+ }
|
|
|
+</style>
|