| package.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| public/innerReviewExport.docx | 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/components/Tinymce/Tinymce.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/utils/exportWord.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/system/clauseManage/components/editDialog.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/system/clauseManage/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/work/selfProblems/internalAudit/innerReviewSheet/components/editDialog.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/work/selfProblems/internalAudit/innerReviewSheet/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
package.json
@@ -25,6 +25,7 @@ "angular-expressions": "^1.5.0", "axios": "0.27.2", "buffer": "^6.0.3", "cssom": "^0.5.0", "docx": "^9.5.1", "docx-preview": "^0.3.5", "docx-templates": "^4.14.1", @@ -37,6 +38,7 @@ "fuse.js": "6.6.2", "html-docx-js": "^0.3.1", "html2canvas": "^1.4.1", "htmlparser2": "^10.0.0", "js-base64": "^3.7.5", "js-cookie": "3.0.1", "jsdom": "^27.0.0", public/innerReviewExport.docxBinary files differ
src/components/Tinymce/Tinymce.vue
@@ -85,7 +85,7 @@ fontsize_formats: "8pt 10pt 12pt 13pt 14pt 18pt 24pt 36pt", // 字体样式应用到文本时使用 <span> 而非 <font> inline_styles: true, // inline_styles: true, images_upload_handler: async (blobInfo, success, failure) => { const formData = new FormData(); // 和后端协商后用formData格式进行传参 formData.append("file", blobInfo.blob());// 传递的参数 src/utils/exportWord.js
@@ -1,22 +1,22 @@ //引入工具 // 引入工具(已修正 htmlparser2 导入) import PizZip from 'pizzip'; import Docxtemplater from 'docxtemplater'; import JSZipUtils from 'jszip-utils'; import { saveAs } from 'file-saver'; import ImageModule from 'docxtemplater-image-module-free'; // 新增:图片处理模 import ImageModule from 'docxtemplater-image-module-free'; import { Parser } from 'htmlparser2'; import CSSOM from 'cssom'; // 加载 .docx 模板文件 // 加载 .docx 模板文件(不变) function loadFile(url, callback) { JSZipUtils.getBinaryContent(url, callback); } // 下载生成的文档 export function download(file, name) { // 下载生成的文档(不变) export function download(file, name) { } } // 辅助函数:将 base64 图片转为 Uint8Array(图片模块需要此格式) // 辅助函数:base64 转 Uint8Array(不变) function base64ToUint8Array(base64) { // 去掉 base64 前缀(如 "data:image/png;base64,") const base64WithoutPrefix = base64.replace(/^data:image\/\w+;base64,/, ''); const binaryString = atob(base64WithoutPrefix); const length = binaryString.length; @@ -27,24 +27,147 @@ return uint8Array; } // -------------------------- 富文本处理核心函数(不变) -------------------------- function getFontSizeFromStyle(styleStr) { if (!styleStr) return 12; try { const style = CSSOM.parse(`.temp { ${styleStr} }`).cssRules[0].style; const fontSize = style.getPropertyValue('font-size'); if (!fontSize) return 12; const sizeNum = parseInt(fontSize.replace(/[^\d]/g, ''), 10); return isNaN(sizeNum) ? 12 : sizeNum; } catch (e) { return 12; } } // 生成并下载 Word 文档(templatePath是word文档模版地址,data是对应的数据) export function generateWordDocument(templatePath, data, name) { loadFile(templatePath, function (error, content) { if (error) { throw error return; function htmlToDocxXml(html) { let xml = ''; let currentFontSize = 12; const entityMap = { ' ': ' ', '<': '<', '>': '>', '&': '&', '"': '"', ''': "'" }; const parser = new Parser({ onopentag: (name, attributes) => { switch (name) { case 'p': xml += '<w:p><w:r>'; break; case 'span': const fontSize = getFontSizeFromStyle(attributes.style); currentFontSize = fontSize; const szVal = currentFontSize * 2; xml += `<w:rPr><w:sz w:val="${szVal}"/><w:szCs w:val="${szVal}"/></w:rPr>`; break; case 'b': case 'strong': xml += '<w:rPr><w:b/></w:rPr>'; break; case 'br': xml += '<w:br/>'; break; } }, ontext: (text) => { const processedText = text .replace(/ |<|>|&|"|'/g, match => entityMap[match]) .replace(/\n/g, '<w:br/>'); xml += `<w:t>${processedText}</w:t>`; }, onclosetag: (name) => { switch (name) { case 'p': xml += '</w:r></w:p>'; currentFontSize = 12; break; case 'span': case 'b': case 'strong': xml += '</w:rPr>'; break; } } }, { decodeEntities: true }); try { // 新版创建解析器的正确方式(无需 import AngularParser) const parser = (tag, _variable) => { parser.write(html); parser.end(); return xml; } function processRichTextData(data, richTextFields = []) { const process = (obj) => { if (typeof obj !== 'object' || obj === null) return obj; if (Array.isArray(obj)) { return obj.map(item => process(item)); } const processedObj = { ...obj }; for (const key in processedObj) { if (processedObj.hasOwnProperty(key)) { if (richTextFields.includes(key) && typeof processedObj[key] === 'string') { const filteredHtml = processedObj[key].replace(/<p>\s*( )?\s*<\/p>/g, ''); processedObj[key] = htmlToDocxXml(filteredHtml); } else { processedObj[key] = process(processedObj[key]); } } } return processedObj; }; return process(data); } // -------------------------- 核心:生成 Word 文档(修正构造函数配置) -------------------------- export function generateWordDocument(templatePath, data, name, richTextFields = []) { loadFile(templatePath, function (error, content) { if (error) { console.error('加载模板失败:', error); return; } try { const processedData = processRichTextData(data, richTextFields); // 图片处理模块(不变) const imageModule = new ImageModule({ getImage: function (tagValue, tagName) { return base64ToUint8Array(tagValue); }, getSize: function (tagValue, tagName) { switch (tagName) { case 'avatar': return [200, 200]; case 'coverImg': return [600, 300]; default: return [80, 130]; } } }); // 关键修正:将 parser 直接传入构造函数 options,删除 setOptions() const zip = new PizZip(content); const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, raw: true, // 富文本核心:允许插入原始 XML modules: [imageModule], // 图片模块 nullGetter: () => '', // 空值处理 // 直接在这里传入 parser 配置(无需 setOptions()) parser: (tag, _variable) => { return { get(scope) { if (scope[tag] !== undefined) { return scope[tag] || ''; } // 处理特殊变量(如 $first) if (tag.startsWith('$')) { const varName = tag.slice(1); return scope[varName] || ''; @@ -52,61 +175,26 @@ return ''; } }; }; // 1. 配置图片处理规则(核心) const imageModule = new ImageModule({ // 获取图片:根据传入的图片数据(base64)转为模块需要的格式 getImage: function (tagValue, tagName) { // tagValue:data 中对应图片键的值(必须是 base64 字符串) // tagName:图片占位符的键名(如 "avatar") return base64ToUint8Array(tagValue); }, // 设置图片尺寸:返回 [宽度, 高度](单位:px),可动态调整 getSize: function (tagValue, tagName) { } }); // 示例:根据不同的图片键,返回不同尺寸 switch (tagName) { case 'avatar': // 头像:200x200 return [200, 200]; case 'coverImg': // 封面图:600x300 return [600, 300]; default: // 默认尺寸:400x300 return [80, 130]; } } }); // 加载模板文件内容到 PizZip const zip = new PizZip(content); const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, modules: [imageModule] // 关键:注入图片模块 }); // 删除这一行!!!v4 构造函数已包含 parser,无需手动 setOptions // doc.setOptions({ parser }); // const parser = new AngularParser(); // doc.setOptions({ parser }); // 注入数据并渲染(不变) doc.setData(processedData); doc.render(); const fileWord = doc.getZip().generate({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', }); // 设置模板中的占位符数据 doc.setData(data); saveAs(fileWord, name); console.log('导出成功!'); // 渲染文档 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 } }); } catch (error) { console.error('生成文档失败:', error); } }); } src/views/system/clauseManage/components/editDialog.vue
@@ -15,9 +15,20 @@ <el-form-item label="条款内容:" prop="name"> <el-input v-model.trim="state.form.name" :disabled="state.title =='查看'" placeholder="条款内容"></el-input> </el-form-item> <el-form-item label="审核要点:" prop="points"> <el-input v-model.trim="state.form.points" :disabled="state.title =='查看'" placeholder="审核要点"></el-input> <el-form-item label="审核要点:" v-if="showEditor" > <t-editor style="width: 500px" ref="myEditor" :toolbar="toolbar" :value="state.form.points"></t-editor> </el-form-item> <el-form-item label="审核要点:" v-else> <div class="ql-container ql-snow" style="height: 500px;width: 100%;margin-top: 10px;"> <div class="ql-editor"> <div class="reviewTable" v-html="state.form.points" ></div> </div> </div> </el-form-item> <!-- <el-form-item label="审核要点:" prop="points">--> <!-- <el-input v-model.trim="state.form.points" :disabled="state.title =='查看'" placeholder="审核要点"></el-input>--> <!-- </el-form-item>--> </el-form> <template #footer v-if="state.title !='查看'"> <span class="dialog-footer"> @@ -35,10 +46,13 @@ import {Base64} from "js-base64" import {getCompany} from "@/api/onlineEducation/company"; import {updateInfoPlatforms, updateSysClause} from "@/api/staffManage/staff"; import TEditor from "@/components/Tinymce/Tinymce.vue"; const emit = defineEmits(["getList"]); const dialogVisible = ref(false) const superRef = ref() const toolbar = ref('fontsizeselect | undo redo') const showEditor = ref(true); const state = reactive({ title: '', form: { @@ -51,7 +65,7 @@ formRules:{ clauseNum: [{ required: true, message: '请输入条款编码', trigger: 'blur' }], name: [{ required: true, message: '请输入条款内容', trigger: 'blur' }], points: [{ required: true, message: '请输入审核要点', trigger: 'blur' }], // points: [{ required: true, message: '请输入审核要点', trigger: 'blur' }], } }) onMounted(() => { @@ -61,6 +75,7 @@ const openDialog = async (type, value,companyId) => { state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' state.form.companyId = companyId showEditor.value = false if(state.title == '编辑'||state.title == '查看'){ Object.keys(state.form).forEach(key => { if (key in value) { @@ -68,11 +83,19 @@ } }) } if (state.title === '查看') { showEditor.value = false } if (type === 'edit' || type === 'add') { showEditor.value = true; } dialogVisible.value = true } const onSubmit = async () => { state.form.points = tinyMCE.activeEditor.getContent(); const valid = await superRef.value.validate(); if(valid){ let data = {} @@ -80,7 +103,8 @@ data = { clauseNum: state.form.clauseNum, name: state.form.name, companyId: state.form.companyId companyId: state.form.companyId, points:state.form.points } }else{ data = state.form @@ -89,6 +113,7 @@ if(res.code == 200){ ElMessage.success(res.message) emit('getList') showEditor.value = false handleClose() dialogVisible.value = false; }else{ @@ -106,6 +131,7 @@ companyId: null, points:'' } showEditor.value = false superRef.value.clearValidate(); superRef.value.resetFields() dialogVisible.value = false; src/views/system/clauseManage/index.vue
@@ -30,10 +30,15 @@ <!-- 表格数据 --> <el-table v-loading="loading" :data="dataList" :border="true"> <el-table-column label="序号" type="index" align="center" width="80"/> <el-table-column label="条款编号" prop="clauseNum" align="center"/> <el-table-column label="条款内容" prop="name" align="center"/> <el-table-column label="审核要点" prop="points" align="center"/> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" > <el-table-column label="条款编号" prop="clauseNum" align="center" width="90"/> <el-table-column label="条款内容" prop="name" align="center" width="150"/> <!-- <el-table-column label="审核要点" prop="points" align="center"/>--> <el-table-column label="审核要点" prop="points" align="center" > <template #default="scope"> <div v-html="scope.row.points" ></div> </template> </el-table-column> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180"> <template #default="scope"> <el-button link type="primary" @click="openDialog('view',scope.row)">查看</el-button> <el-button link type="primary" @click="openDialog('edit',scope.row)" v-hasPermi="['clauseManage:edit']">编辑</el-button> src/views/work/selfProblems/internalAudit/innerReviewSheet/components/editDialog.vue
@@ -3,7 +3,7 @@ <el-dialog v-model="dialogVisible" :title="state.title" width="950px" width="1200px" :before-close="handleClose" :close-on-press-escape="false" :close-on-click-modal="false" @@ -85,54 +85,67 @@ </div> <el-table style="margin-top: 15px;margin-bottom: 20px" :data="state.form.checkCatalogues" :border="true"> <el-table-column label="适用条款" align="center"> <el-table-column label="体系标准款项" prop="number" align="center"></el-table-column> <el-table-column label="标题" prop="mess" align="center"></el-table-column> <el-table-column label="体系标准款项" prop="number" align="center" width="110"></el-table-column> <el-table-column label="标题" prop="mess" align="center" width="150"></el-table-column> </el-table-column> <el-table-column label="审核要点" prop="pointKey" align="center" width="180"> <el-table-column label="审核要点" prop="pointKey" align="left" header-align="center"> <template #default="{row,$index}"> <div v-for="(i,index) in row.checkContents" :key="index"> <el-form-item :prop="'checkCatalogues.' + '[' + $index + '].' +'checkContents.' + '[' + index + ']' + '.pointKey'" :rules="state.formRules.pointKey"> <el-input style="margin-top: 10px" :disabled="state.title === '查看'" type="textarea" :rows="4" v-model="i.pointKey" placeholder="请输入"></el-input> </el-form-item> </div> <el-form-item :prop="'checkCatalogues.' + '[' + $index + ']' + '.pointKey'" :rules="state.formRules.pointKey"> <div v-if="showEditor" > <t-editor style="width: 380px;" :height="250" ref="myEditor" :toolbar="toolbar" :value="row.pointKey" @input="inputPonit($event,$index)"></t-editor> </div> <div v-else > <div class="reviewTable" v-html="row.pointKey" ></div> </div> </el-form-item> </template> </el-table-column> <el-table-column label="审核发现" prop="find" align="center" width="300"> <el-table-column label="审核发现" prop="find" align="left" header-align="center"> <template #default="{row,$index}"> <div v-for="(i,index) in row.checkContents" :key="index"> <el-form-item :prop="'checkCatalogues.' + '[' + $index + '].' +'checkContents.' + '[' + index + ']' + '.find'" :rules="state.formRules.find"> <el-input style="margin-top: 10px" :disabled="state.title === '查看'" type="textarea" :rows="4" v-model="i.find" placeholder="请输入"></el-input> </el-form-item> </div> <el-form-item :prop="'checkCatalogues.' + '[' + $index + ']' + '.find'" :rules="state.formRules.find"> <div v-if="showEditor" > <t-editor style="width: 380px;" :height="250" ref="myEditor" :toolbar="toolbar" :value="row.find" @input="inputFind($event,$index)"></t-editor> </div> <div v-else > <div class="reviewTable" v-html="row.find" ></div> </div> </el-form-item> </template> </el-table-column> <el-table-column label="审核结果" align="center" > <el-table-column label="符合" prop="conform" align="center" width="70"> <template #default="{row,$index}"> <div v-for="(i,index) in row.checkContents" :key="index"> <el-form-item :prop="'checkCatalogues.' + '[' + $index + '].' +'checkContents.' + '[' + index + ']' + '.result'" :rules="state.formRules.result"> <el-radio style="height: 100px" v-model="i.result" :label="1" :disabled="state.title === '查看'" > </el-radio> </el-form-item> </div> </template> </el-table-column> <!-- <el-table-column label="符合" prop="conform" align="center" width="70">--> <!-- <template #default="{row,$index}">--> <!-- <div v-for="(i,index) in row.checkContents" :key="index">--> <!-- <el-form-item :prop="'checkCatalogues.' + '[' + $index + '].' +'checkContents.' + '[' + index + ']' + '.result'" :rules="state.formRules.result">--> <!-- <el-radio--> <!-- style="height: 100px"--> <!-- v-model="i.result"--> <!-- :label="1"--> <!-- :disabled="state.title === '查看'"--> <!-- > </el-radio>--> <!-- </el-form-item>--> <!-- </div>--> <!-- </template>--> <!-- </el-table-column>--> <el-table-column label="不符合" prop="minor" align="center" width="90"> <template #default="{row,$index}"> <div v-for="(i,index) in row.checkContents" :key="index"> <el-form-item :prop="'checkCatalogues.' + '[' + $index + '].' +'checkContents.' + '[' + index + ']' + '.result'" :rules="state.formRules.result"> <el-radio <!-- <div v-for="(i,index) in row.checkContents" :key="index">--> <el-form-item :prop="'checkCatalogues.' + '[' + $index + ']' + '.result'" :rules="state.formRules.result"> <el-checkbox style="height: 100px" v-model="i.result" :label="2" v-model="row.result" :disabled="state.title === '查看'" ></el-radio> /> <!-- <el-radio--> <!-- style="height: 100px"--> <!-- v-model="row.result"--> <!-- :label="2"--> <!-- :disabled="state.title === '查看'"--> <!-- ></el-radio>--> </el-form-item> </div> <!-- </div>--> </template> </el-table-column> <!-- <el-table-column label="严重不符合" prop="serious" align="center" width="90">--> @@ -150,12 +163,12 @@ <!-- </template>--> <!-- </el-table-column>--> </el-table-column> <el-table-column label="操作" align="center" width="120" v-if="state.title !== '查看'" > <template #default="scope"> <el-button link type="primary" @click="addObject(scope.row,scope.$index)" >添加</el-button> <el-button link type="danger" @click="delObject(scope.row,scope.$index)" >删除</el-button> </template> </el-table-column> <!-- <el-table-column label="操作" align="center" width="120" v-if="state.title !== '查看'" >--> <!-- <template #default="scope">--> <!-- <el-button link type="primary" @click="addObject(scope.row,scope.$index)" >添加</el-button>--> <!-- <el-button link type="danger" @click="delObject(scope.row,scope.$index)" >删除</el-button>--> <!-- </template>--> <!-- </el-table-column>--> </el-table> </el-col> @@ -221,11 +234,16 @@ import {getCatalogue} from "@/api/qualityManage/catalog"; import Cookies from "js-cookie"; import {getUser} from "@/api/onlineEducation/user"; import TEditor from "@/components/Tinymce/Tinymce.vue"; const emit = defineEmits(["getList"]); const dialogVisible = ref(false) const superRef = ref() const termRef = ref() const myEditor = ref(); const isReview = ref(false); const showEditor = ref(true); const toolbar = ref('fontsizeselect | undo redo') const checkTime = ref([]) const validateFieldsReview = (rule, value, callback) =>{ if (checkTime.value && checkTime.value.length >0 ) { @@ -259,8 +277,8 @@ // checkTime: [{ required: true, message: '请选择内审时间', trigger: 'blur' }], startTime: [{ required: true,validator: validateFieldsReview, trigger: 'blur' }],//审核时间 checkRecord: [{ required: true, message: '请填写检查记录', trigger: 'blur' }], pointKey: [{ required: true, message: '', trigger: 'blur' }], find: [{ required: true, message: '', trigger: 'blur' }], pointKey: [{ required: true, message: '请输入审核要点', trigger: 'blur' }], find: [{ required: true, message: '请输入审核发现', trigger: 'blur' }], result: [{ required: true, message: '', trigger: 'blur' }], @@ -293,6 +311,7 @@ state.form.companyId = value.companyId state.companyList = companyList } showEditor.value = false state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' if(state.title == '编辑'||state.title == '查看'){ Object.keys(state.form).forEach(key => { @@ -301,12 +320,20 @@ } }) checkTime.value = [state.form.startTime,state.form.endTime] console.log('1',state.form) state.form.checkCatalogues.forEach(item => { if(item.checkContents && item.checkContents.length == 0){ item.checkContents.push({}) state.form.checkCatalogues = state.form.checkCatalogues.map(item => { return { ...item, result: item.result == 2 ? true:false } }) console.log('1',state.form) } if (state.title == '查看') { showEditor.value = false } if (type === 'edit' || type === 'add') { showEditor.value = true; } await getUserList() await getDepartList(state.form.companyId) @@ -355,6 +382,13 @@ } const onSubmit = async () => { console.log('f',state.form) state.form.checkCatalogues = state.form.checkCatalogues.map(item => { return { ...item, result: item.result ? 2:1 } }) state.form.startTime = checkTime.value[0] state.form.endTime = checkTime.value[1] const valid = await superRef.value.validate(); @@ -478,24 +512,24 @@ state.showDialog = true // state.form.checkCatalogues.push({checkContents: [{}]}) } const addObject = (val,itemIndex) => { state.form.checkCatalogues.forEach((item,index) => { if(index == itemIndex){ item.checkContents.push({}) } }) } const delObject = (val,itemIndex) => { state.form.checkCatalogues.forEach((item,index) => { if(index == itemIndex){ if(item.checkContents.length == 1){ state.form.checkCatalogues.splice(index,1) }else { item.checkContents.pop() } } }) } // const addObject = (val,itemIndex) => { // state.form.checkCatalogues.forEach((item,index) => { // if(index == itemIndex){ // item.checkContents.push({}) // } // }) // } // const delObject = (val,itemIndex) => { // state.form.checkCatalogues.forEach((item,index) => { // if(index == itemIndex){ // if(item.checkContents.length == 1){ // state.form.checkCatalogues.splice(index,1) // }else { // item.checkContents.pop() // } // } // }) // } const handleCloseDialog = () => { state.termForm = { id: null, @@ -507,9 +541,7 @@ const onSubmitTerm = async () =>{ const valid = await termRef.value.validate(); if(valid){ state.form.checkCatalogues.push({ checkContents: [{}], catalogueId:state.termForm.id, number: state.termForm.number, mess: state.termForm.mess}) @@ -528,6 +560,14 @@ }; const inputFind = (val,index)=> { state.form.checkCatalogues[index].find = val } const inputPonit = (val,index)=> { state.form.checkCatalogues[index].pointKey = val } defineExpose({ openDialog }); src/views/work/selfProblems/internalAudit/innerReviewSheet/index.vue
@@ -45,6 +45,7 @@ <el-table-column label="受审核部门" prop="deptName" align="center"></el-table-column> <el-table-column label="操作" align="center"> <template #default="scope"> <el-button link type="primary" @click="openDialog('review',scope.row)">查看</el-button> <el-button link type="primary" @click="openDialog('edit',scope.row)" v-hasPermi="['innerReviewSheet:list:edit']">编辑</el-button> <el-button link type="danger" @click="handleDelete(scope.row)" v-hasPermi="['innerReviewSheet:list:del']">删除</el-button> </template> @@ -195,20 +196,16 @@ item.tableData = item.checkCatalogues.map((i,index) => { return{ ...i, checkContents: i.checkContents.map((q,qindex) => { return{ ...q, first: qindex == 0, well: q.result == 1, fine: q.result == 2, bad: q.result == 3, } }) well: i.result == 1, fine: i.result == 2, bad: i.result == 3, } }) console.log('11',item.tableData) item.checkTime = item.startTime +'-'+item.endTime.slice(11) try { generateWordDocument(templatePath.value, item, item.year+'年'+item.deptName+'_内审检查表.docx'); generateWordDocument(templatePath.value, item, item.year+'年'+item.deptName+'_内审检查表.docx',['pointKey', 'find']); } catch (error){ ElMessage({ type: 'warning',