From 16a2e4ff09fc3d67be542b3247447655fbc7a4a2 Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Wed, 11 Mar 2026 14:13:57 +0800 Subject: [PATCH] f --- resources/qiye.html | 274 ++++++++++++++++++++++++++++++++------------ 1 file changed, 198 insertions(+), 76 deletions(-) diff --git a/resources/qiye.html b/resources/qiye.html index 3f3c71b..f9b0d01 100644 --- a/resources/qiye.html +++ b/resources/qiye.html @@ -127,6 +127,78 @@ color: var(--primary-dark); transform: translateY(-1px); } + /* 保存 PDF 按钮:固定悬浮,不随页面滚动,且不会进入截图中 */ + .pdf-actions-fixed { + position: fixed; + top: 20px; + right: 24px; + z-index: 1000; + } + .pdf-fixed-btn { + display: inline-flex; + align-items: center; + padding: 10px 18px; + border-radius: 999px; + border: 1px solid var(--primary); + background: var(--bg-card); + color: var(--primary); + font-size: 14px; + font-weight: 500; + cursor: pointer; + box-shadow: 0 2px 8px rgba(37, 99, 235, 0.2); + transition: + background 0.15s ease, + color 0.15s ease, + box-shadow 0.15s ease; + } + .pdf-fixed-btn:hover { + background: var(--primary); + color: #fff; + box-shadow: 0 4px 12px rgba(37, 99, 235, 0.35); + } + .pdf-fixed-btn:disabled { + opacity: 0.7; + cursor: not-allowed; + } + /* 生成 PDF 时的全屏加载层 */ + .pdf-loading-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.35); + z-index: 2000; + display: flex; + align-items: center; + justify-content: center; + } + .pdf-loading-overlay[aria-hidden="true"] { + display: none; + } + .pdf-loading-content { + background: var(--bg-card); + padding: 28px 36px; + border-radius: 16px; + text-align: center; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); + } + .pdf-loading-spinner { + width: 44px; + height: 44px; + border: 3px solid var(--border); + border-top-color: var(--primary); + border-radius: 50%; + margin: 0 auto 16px; + animation: pdf-spin 0.75s linear infinite; + } + .pdf-loading-content p { + margin: 0; + font-size: 15px; + color: var(--text); + } + @keyframes pdf-spin { + to { + transform: rotate(360deg); + } + } .header-score .score { font-size: 32px; font-weight: 700; @@ -382,6 +454,10 @@ .print-btn { display: none !important; } + .pdf-actions-fixed, + .pdf-loading-overlay { + display: none !important; + } /* 抬头简化为白底、去圆角和阴影 */ .header { background: #ffffff !important; @@ -452,13 +528,21 @@ 综合评分 风险:- -
- -
+ +
+ +
+ + @@ -2101,83 +2185,121 @@ } loadReport(); - // 绑定「保存为 PDF」按钮,使用 html2canvas + jsPDF 截图生成 PDF,避免依赖浏览器打印对话框 + // 绑定「保存为 PDF」按钮:html2canvas 截取 .page → 转 JPEG → jsPDF 分页生成 PDF(按钮在 .page 外固定悬浮,不会进 PDF) var saveBtn = document.getElementById("btnSavePdf"); + var loadingOverlay = document.getElementById("pdfLoadingOverlay"); if (saveBtn && window.html2canvas && window.jspdf && window.jspdf.jsPDF) { saveBtn.addEventListener("click", function () { - try { - var pageEl = document.querySelector(".page"); - if (!pageEl) { - console.error("未找到 .page 容器"); - return; - } - - html2canvas(pageEl, { - scale: 1.5, - useCORS: true, - scrollX: 0, - scrollY: -window.scrollY, - }) - .then(function (canvas) { - // 使用 JPEG 可以避免部分环境下 PNG 解析问题(Incomplete or corrupt PNG file) - var imgData = canvas.toDataURL( - "image/jpeg", - 0.95, - ); - - var pdf = new jspdf.jsPDF("p", "mm", "a4"); - var pageWidth = pdf.internal.pageSize.getWidth(); - var pageHeight = pdf.internal.pageSize.getHeight(); - - var imgWidth = pageWidth; - var imgHeight = - (canvas.height * imgWidth) / canvas.width; - - var position = 0; - var heightLeft = imgHeight; - - pdf.addImage( - imgData, - "JPEG", - 0, - position, - imgWidth, - imgHeight, - ); - heightLeft -= pageHeight; - - while (heightLeft > 0) { - position = heightLeft - imgHeight; - pdf.addPage(); - pdf.addImage( - imgData, - "JPEG", - 0, - position, - imgWidth, - imgHeight, - ); - heightLeft -= pageHeight; - } - - var fileName = "企业全景报告.pdf"; - if ( - reportData && - reportData.entName && - typeof reportData.entName === "string" - ) { - fileName = - reportData.entName + - "_企业全景报告.pdf"; - } - pdf.save(fileName); - }) - .catch(function (e) { - console.error("生成 PDF 失败", e); - }); - } catch (e) { - console.error("触发生成 PDF 失败", e); + var pageEl = document.querySelector(".page"); + if (!pageEl) { + console.error("未找到 .page 容器"); + return; } + var btnText = saveBtn.textContent; + saveBtn.disabled = true; + saveBtn.textContent = "生成中..."; + if (loadingOverlay) { + loadingOverlay.setAttribute("aria-hidden", "false"); + } + function restoreBtn() { + saveBtn.disabled = false; + saveBtn.textContent = btnText; + if (loadingOverlay) { + loadingOverlay.setAttribute("aria-hidden", "true"); + } + } + // 等待浏览器完成布局与绘制,再截取,避免截到白屏 + function doCapture() { + requestAnimationFrame(function () { + requestAnimationFrame(function () { + try { + html2canvas(pageEl, { + scale: 1.5, + useCORS: true, + allowTaint: false, + backgroundColor: "#ffffff", + scrollX: 0, + scrollY: 0, + windowWidth: pageEl.scrollWidth, + windowHeight: pageEl.scrollHeight, + onclone: function (clonedDoc, node) { + var body = clonedDoc.body; + if (body) { + body.style.backgroundColor = "#ffffff"; + body.style.overflow = "visible"; + } + var clonePage = clonedDoc.querySelector(".page"); + if (clonePage) { + clonePage.style.overflow = "visible"; + clonePage.style.backgroundColor = "#ffffff"; + } + }, + }) + .then(function (canvas) { + if (!canvas.width || !canvas.height) { + console.error("截图为空,宽或高为 0"); + restoreBtn(); + return; + } + var imgData = canvas.toDataURL( + "image/jpeg", + 0.95, + ); + var pdf = new jspdf.jsPDF("p", "mm", "a4"); + var pageWidth = pdf.internal.pageSize.getWidth(); + var pageHeight = pdf.internal.pageSize.getHeight(); + var imgWidth = pageWidth; + var imgHeight = + (canvas.height * imgWidth) / canvas.width; + var position = 0; + var heightLeft = imgHeight; + pdf.addImage( + imgData, + "JPEG", + 0, + position, + imgWidth, + imgHeight, + ); + heightLeft -= pageHeight; + while (heightLeft > 0) { + position = heightLeft - imgHeight; + pdf.addPage(); + pdf.addImage( + imgData, + "JPEG", + 0, + position, + imgWidth, + imgHeight, + ); + heightLeft -= pageHeight; + } + var fileName = "企业全景报告.pdf"; + if ( + reportData && + reportData.entName && + typeof reportData.entName === "string" + ) { + fileName = + reportData.entName + + "_企业全景报告.pdf"; + } + pdf.save(fileName); + restoreBtn(); + }) + .catch(function (e) { + console.error("生成 PDF 失败", e); + restoreBtn(); + }); + } catch (e) { + console.error("触发生成 PDF 失败", e); + restoreBtn(); + } + }); + }); + } + doCapture(); }); } })();