From 591736f11f481e30722d38102b84f41cd19338e1 Mon Sep 17 00:00:00 2001 From: zlwu Date: Sat, 5 Sep 2026 14:50:00 +0800 Subject: [PATCH] feat(web-admin): add Generate Word on contract detail print dialog Co-authored-by: Cursor --- web-admin/src/views/crm/contract/detail.vue | 54 +++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/web-admin/src/views/crm/contract/detail.vue b/web-admin/src/views/crm/contract/detail.vue index e6f6b2752..b8bdd6594 100644 --- a/web-admin/src/views/crm/contract/detail.vue +++ b/web-admin/src/views/crm/contract/detail.vue @@ -1111,6 +1111,9 @@ {{ showRedSeal ? '隐藏红章' : '显示红章' }} 打印 + + 生成 Word + 生成PDF @@ -1126,6 +1129,12 @@ import { list as listOperLog } from '@/api/monitor/operlog'; import type { OperLogVO, OperLogQuery } from '@/api/monitor/operlog/types'; import { parseTime } from '@/utils/format'; import { $modal } from '@/utils/modal' +import FileSaver from 'file-saver' +import { + buildContractDocxFileName, + generateContractDocxBlob, + prepareContractHtmlForDocx +} from '@/utils/crm/contract-html-to-docx' import { formatBrandForPrint } from '@/utils/crm-product-brand'; import { useDictStore } from '@/store/modules/dict'; import DictTag from '@/components/DictTag/index.vue'; @@ -1216,6 +1225,7 @@ const isPreviewMode = ref(false); /** 打印弹窗内红章显隐(仅本次弹窗有效,打开时默认显示) */ const showRedSeal = ref(true); const pdfGenerating = ref(false); +const wordGenerating = ref(false); /** 加载合同详情 */ const loadContractDetail = async () => { @@ -2833,6 +2843,50 @@ const togglePreviewMode = () => { isPreviewMode.value = !isPreviewMode.value; }; +/** 从打印弹窗生成 Word */ +const handleGenerateWordFile = async () => { + if (!contract.value?.id) { + $modal.msgError('合同信息不存在'); + return; + } + + wordGenerating.value = true; + try { + $modal.loading('正在生成 Word...'); + + let htmlContent = contractContent.value; + const res = await getContract(contract.value.id); + if (res?.data) { + htmlContent = replacePlaceholders(htmlContent, res.data); + contractContent.value = htmlContent; + } + + const prepared = prepareContractHtmlForDocx({ + html: htmlContent, + contractNo: contract.value.contractNo, + origin: window.location.origin + }); + + const blob = await generateContractDocxBlob( + prepared, + contract.value.contractName || contract.value.contractNo + ); + FileSaver.saveAs( + blob, + buildContractDocxFileName(contract.value.contractName, contract.value.contractNo) + ); + + $modal.closeLoading(); + $modal.msgSuccess('Word 生成成功'); + } catch (error) { + console.error('生成 Word 失败:', error); + $modal.closeLoading(); + $modal.msgError('生成 Word 失败,请重试'); + } finally { + wordGenerating.value = false; + } +}; + /** 生成PDF文件 */ const handleGeneratePdfFile = async () => { try {