From 9e03b447fa15fa3fa0e468ca42a4bb7b4eac1e3b Mon Sep 17 00:00:00 2001 From: zhouwx <1175765986@qq.com> Date: 星期三, 08 一月 2025 11:07:42 +0800 Subject: [PATCH] 导出报告 --- src/views/analyse/applyReview/components/reportDialog.vue | 100 +++++++++++++++++++ src/views/analyse/assessApply/components/reportDialog.vue | 106 ++++++++++++++++++++- src/views/experiment/developing/components/exportWord.js | 55 +++++++++++ src/views/analyse/assessApply/index.ts | 6 + src/views/system/user/component/userDialog.vue | 5 public/static/exampleScience.docx | 0 6 files changed, 261 insertions(+), 11 deletions(-) diff --git a/public/static/exampleScience.docx b/public/static/exampleScience.docx new file mode 100644 index 0000000..7dbe241 --- /dev/null +++ b/public/static/exampleScience.docx Binary files differ diff --git a/src/views/analyse/applyReview/components/reportDialog.vue b/src/views/analyse/applyReview/components/reportDialog.vue index 985eca6..97a19d0 100644 --- a/src/views/analyse/applyReview/components/reportDialog.vue +++ b/src/views/analyse/applyReview/components/reportDialog.vue @@ -24,7 +24,8 @@ <!-- <el-radio :label="5">特种设备类</el-radio>--> <!-- <el-radio :label="6">其他类</el-radio>--> <!-- </el-radio-group>--> - {{reportDialogState.experimentTypeList.find(i=>i.id === reportDialogState.reportForm.experimentType)?.name}} +<!-- {{reportDialogState.experimentTypeList.find(i=>i.id === reportDialogState.reportForm.experimentType)?.name}}--> + {{typeValue}} </td> </tr> <tr> @@ -209,6 +210,7 @@ <span class="dialog-footer" style="padding-top:10px;text-align: center !important;"> <el-button @click="reportDialogState.reportDialogVisible = !reportDialogState.reportDialogVisible" size="default">取 消</el-button> <el-button type="primary" v-if="!reportDialogState.disabled" @click="onSubmitProject()" size="default">提交审批</el-button> + <el-button type="primary" v-if="reportDialogState.disabled" @click="startGeneration()" size="default">导出评估报告</el-button> </span> </template> </el-dialog> @@ -223,10 +225,11 @@ import {userApi} from "/@/api/systemManage/user"; import {roomApi} from "/@/api/basic/room"; import {assessApplyApi} from "/@/api/analyse/assessApply"; - +import {generateWordDocument} from "/@/views/experiment/developing/components/exportWord.js"; const SelectDanger = defineAsyncComponent(() => import('./selectDanger.vue')) const selectDangerRef = ref() const reportFormRef = ref() +const typeValue = ref([]) const reportDialogState = reactive<ReportDialogType>({ title: '', disabled: false, @@ -252,7 +255,9 @@ riskSourceType: [], description: '', person: [], - process:'' + process:'', + experimentAndType: [], + oldRiskAssess: [] }, reportFormRules: { assessPerson: [{ required: true, message: '请填写评估人员', trigger: 'blur' }], @@ -270,7 +275,23 @@ {id: 4, name: '机电类'}, {id: 5, name: '特种设备类'}, {id: 6, name: '其它类'} - ] + ], + riskSourceTypeList: [ + {id: 1, name: '化学安全'}, + {id: 2, name: '辐射安全'}, + {id: 3, name: '生物安全'}, + {id: 4, name: '机电安全'}, + {id: 5, name: '电气安全'}, + {id: 6, name: '激光安全'}, + {id: 7, name: '特种设备安全'}, + {id: 8, name: '其他安全'}, + ], + riskLevelList: [ + {id: 1, name: '重大风险(一级)'}, + {id: 2, name: '较大风险(二级)'}, + {id: 3, name: '一般风险(三级)'}, + {id: 4, name: '低风险(四级)'}, + ], }) const showReportDialog = (title: string, value: ProjectType, allRoomList: RoomType []) => { @@ -319,6 +340,8 @@ reportDialogState.reportForm[i] = res.data.data[0][i]; } } + const arr = reportDialogState.reportForm.experimentAndType.map(item => item.type.experimentType) + typeValue.value = arr.join(',') console.log(reportDialogState.reportForm,'reportDialogState.reportForm') }else{ ElMessage({ @@ -426,6 +449,75 @@ defineExpose({ showReportDialog, }); +const templatePath = '/static/exampleScience.docx' +const startGeneration = async () => { + const data = JSON.parse(JSON.stringify(reportDialogState.reportForm)) + const experimentTypeNameList = data.experimentAndType.map(item => { + return { + id: item.type.id, + experimentType: item.type.experimentType + } + }) + + const experimentTypeListExample = JSON.parse(JSON.stringify(reportDialogState.experimentTypeList)) + experimentTypeListExample.forEach(item => { + if(experimentTypeNameList.some(i => i.experimentType == item.name)){ + item.label = item.name + item.checked = false + }else { + item.label = item.name + item.checked = true + } + }) + data.typeList = experimentTypeListExample + data.depNameList = data.dep + const siteTest = data.experimentSite.map(item => item.siteName) + data.siteList = siteTest.join(',') + + const riskType = data.riskSourceType.filter(item => item.status == 1) + const riskListExample = reportDialogState.riskSourceTypeList + riskListExample.forEach(item => { + if(riskType.some(i => i.riskSourceType === item.name)){ + item.label = item.name + item.checked = false + }else { + item.label = item.name + item.checked = true + } + }) + data.riskList = riskListExample + + const level = data.assessLevel.toString().split(',') + const levelExample = JSON.parse(JSON.stringify(reportDialogState.riskLevelList)) + levelExample.forEach(item => { + if(level.some(i => i == item.id)){ + item.label = item.name + item.checked = false + }else { + item.label = item.name + item.checked = true + } + }) + data.riskLevel = levelExample + + data.tableData = data.oldRiskAssess + + data.riskSource = data.riskSource.map(item => { + return { + ...item, + description: item.description ? item.description: '' + } + }) + + try { + generateWordDocument(templatePath, data, `材料科学姑苏实验室安全风险评估表---${data.experimentName}.docx`); + } catch (error){ + ElMessage({ + type: 'warning', + message: '失败' + }); + } +}; onMounted(() => { getAllPersonList(); diff --git a/src/views/analyse/assessApply/components/reportDialog.vue b/src/views/analyse/assessApply/components/reportDialog.vue index 9623f1f..77b5845 100644 --- a/src/views/analyse/assessApply/components/reportDialog.vue +++ b/src/views/analyse/assessApply/components/reportDialog.vue @@ -24,7 +24,8 @@ <!-- <el-radio :label="5">特种设备类</el-radio>--> <!-- <el-radio :label="6">其他类</el-radio>--> <!-- </el-radio-group>--> - {{reportDialogState.experimentTypeList.find(i=>i.id === reportDialogState.reportForm.experimentType)?.name}} +<!-- {{reportDialogState.experimentTypeList.find(i=>i.id === reportDialogState.reportForm.experimentAndType)?.name}}--> + {{typeValue}} </td> </tr> <tr> @@ -215,6 +216,7 @@ <span class="dialog-footer" style="padding-top:10px;text-align: center !important;"> <el-button @click="reportDialogState.reportDialogVisible = !reportDialogState.reportDialogVisible" size="default">取 消</el-button> <el-button type="primary" v-if="!reportDialogState.disabled" @click="onSubmitProject()" size="default">提交审批</el-button> + <el-button type="primary" v-if="reportDialogState.disabled" @click="startGeneration()" size="default">导出评估报告</el-button> </span> </template> </el-dialog> @@ -223,13 +225,14 @@ <script setup lang="ts"> import {defineAsyncComponent, nextTick, onMounted, reactive, ref} from "vue"; +import {generateWordDocument} from "/@/views/experiment/developing/components/exportWord.js"; import {ElMessage} from "element-plus"; import {projectApi} from "/@/api/experiment/project"; import {personApi} from "/@/api/basic/person"; import {userApi} from "/@/api/systemManage/user"; import {roomApi} from "/@/api/basic/room"; import {assessApplyApi} from "/@/api/analyse/assessApply"; - +const typeValue = ref([]) const SelectDanger = defineAsyncComponent(() => import('./selectDanger.vue')) const selectDangerRef = ref() const reportFormRef = ref() @@ -258,7 +261,9 @@ riskSourceType: [], description: '', person:[], - process: '' + process: '', + experimentAndType: [], + oldRiskAssess: [] }, reportFormRules: { assessPerson: [{ required: true, message: '请填写评估人员', trigger: 'blur' }], @@ -276,7 +281,23 @@ {id: 4, name: '机电类'}, {id: 5, name: '特种设备类'}, {id: 6, name: '其它类'} - ] + ], + riskSourceTypeList: [ + {id: 1, name: '化学安全'}, + {id: 2, name: '辐射安全'}, + {id: 3, name: '生物安全'}, + {id: 4, name: '机电安全'}, + {id: 5, name: '电气安全'}, + {id: 6, name: '激光安全'}, + {id: 7, name: '特种设备安全'}, + {id: 8, name: '其他安全'}, + ], + riskLevelList: [ + {id: 1, name: '重大风险(一级)'}, + {id: 2, name: '较大风险(二级)'}, + {id: 3, name: '一般风险(三级)'}, + {id: 4, name: '低风险(四级)'}, + ], }) const showReportDialog = (title: string, value: ProjectType, allRoomList: RoomType []) => { @@ -346,7 +367,9 @@ riskSourceType: [], description: '', person:[], - process: '' + process: '', + experimentAndType: [], + oldRiskAssess: [] } if(res.data.data&&res.data.data.length==0){ ElMessage({ @@ -359,6 +382,8 @@ reportDialogState.reportForm[i] = res.data.data[0][i]; } } + const arr = reportDialogState.reportForm.experimentAndType.map(item => item.type.experimentType) + typeValue.value = arr.join(',') } }else{ ElMessage({ @@ -466,6 +491,77 @@ } }; +const templatePath = '/static/exampleScience.docx' +const startGeneration = async () => { + const data = JSON.parse(JSON.stringify(reportDialogState.reportForm)) + const experimentTypeNameList = data.experimentAndType.map(item => { + return { + id: item.type.id, + experimentType: item.type.experimentType + } + }) + + const experimentTypeListExample = JSON.parse(JSON.stringify(reportDialogState.experimentTypeList)) + experimentTypeListExample.forEach(item => { + if(experimentTypeNameList.some(i => i.experimentType == item.name)){ + item.label = item.name + item.checked = false + }else { + item.label = item.name + item.checked = true + } + }) + data.typeList = experimentTypeListExample + data.depNameList = data.dep + const siteTest = data.experimentSite.map(item => item.siteName) + data.siteList = siteTest.join(',') + + const riskType = data.riskSourceType.filter(item => item.status == 1) + const riskListExample = reportDialogState.riskSourceTypeList + riskListExample.forEach(item => { + if(riskType.some(i => i.riskSourceType === item.name)){ + item.label = item.name + item.checked = false + }else { + item.label = item.name + item.checked = true + } + }) + data.riskList = riskListExample + + const level = data.assessLevel.toString().split(',') + const levelExample = JSON.parse(JSON.stringify(reportDialogState.riskLevelList)) + levelExample.forEach(item => { + if(level.some(i => i == item.id)){ + item.label = item.name + item.checked = false + }else { + item.label = item.name + item.checked = true + } + }) + data.riskLevel = levelExample + + data.tableData = data.oldRiskAssess + + data.riskSource = data.riskSource.map(item => { + return { + ...item, + description: item.description ? item.description: '' + } + }) + + + try { + generateWordDocument(templatePath, data, `材料科学姑苏实验室安全风险评估表---${data.experimentName}.docx`); + } catch (error){ + ElMessage({ + type: 'warning', + message: '失败' + }); + } +}; + const emit = defineEmits(['refresh']); defineExpose({ diff --git a/src/views/analyse/assessApply/index.ts b/src/views/analyse/assessApply/index.ts index 85f9d64..ea7e1fb 100644 --- a/src/views/analyse/assessApply/index.ts +++ b/src/views/analyse/assessApply/index.ts @@ -27,13 +27,17 @@ riskSourceType: [], description: string, person: [], - process: string + process: string, + experimentAndType: [], + oldRiskAssess: [] } reportFormRules: object allPersonList: Array<AllPersonListType> systemPersonList: Array<AllPersonListType> allRoomList: Array<RoomType>, experimentTypeList: Array<Type> + riskSourceTypeList: Array<Type> + riskLevelList: Array<Type> } declare interface DangerSourceType { diff --git a/src/views/experiment/developing/components/exportWord.js b/src/views/experiment/developing/components/exportWord.js new file mode 100644 index 0000000..3ba3d7b --- /dev/null +++ b/src/views/experiment/developing/components/exportWord.js @@ -0,0 +1,55 @@ +//引入工具 +import PizZip from 'pizzip'; +import Docxtemplater from 'docxtemplater'; +import JSZipUtils from 'jszip-utils'; +import { saveAs } from 'file-saver'; + +// 加载 .docx 模板文件 +function loadFile(url, callback) { + JSZipUtils.getBinaryContent(url, callback); +} + +// 下载生成的文档 +export function download(file, name) { + +} + +// 生成并下载 Word 文档(templatePath是word文档模版地址,data是对应的数据) +export function generateWordDocument(templatePath, data, name) { + loadFile(templatePath, function (error, content) { + if (error) { + throw error + return; + } + + try { + // 加载模板文件内容到 PizZip + const zip = new PizZip(content); + const doc = new Docxtemplater(zip, { + paragraphLoop: true, + linebreaks: true, + }); + + // 设置模板中的占位符数据 + doc.setData(data); + + // 渲染文档 + doc.render(); + + // 生成最终的文档 Blob + const fileWord = doc.getZip().generate({ + type: 'blob', + mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + }); + + saveAs(fileWord, name); + + // // 返回生成的文档 Blob + // resolve(fileWord); + } catch (error) { + console.error('Error rendering document:', error); + throw error + } + }); + +} diff --git a/src/views/system/user/component/userDialog.vue b/src/views/system/user/component/userDialog.vue index b104036..3a839d0 100644 --- a/src/views/system/user/component/userDialog.vue +++ b/src/views/system/user/component/userDialog.vue @@ -237,6 +237,9 @@ } }; + const verifyPhoneTest = (phone) => { + return /^1[3-9]\d{9}$/.test(phone); + } // 新增修改 const onSubmit = async () => { userRef.value.validate(async (valid:Boolean) => { @@ -249,7 +252,7 @@ }); return } - if(verifyPhone(state.userForm.phone) == false){ + if(verifyPhoneTest(state.userForm.phone) == false){ ElMessage({ type: 'warning', message: '请输入正确的手机号', -- Gitblit v1.9.2