feat
This commit is contained in:
@@ -42,61 +42,70 @@ const QuotationPreview = () => {
|
|||||||
// PDF导出函数
|
// PDF导出函数
|
||||||
const exportPDF = async () => {
|
const exportPDF = async () => {
|
||||||
try {
|
try {
|
||||||
// 显示加载中
|
|
||||||
message.loading('正在生成PDF...', 0);
|
message.loading('正在生成PDF...', 0);
|
||||||
|
|
||||||
// 获取要导出的DOM元素
|
|
||||||
const element = document.getElementById('quotation-content');
|
const element = document.getElementById('quotation-content');
|
||||||
|
|
||||||
// 使用html2canvas将DOM转换为canvas
|
// A4 尺寸(单位:pt,1mm ≈ 2.83pt)
|
||||||
const canvas = await html2canvas(element, {
|
const a4Width = 595.28;
|
||||||
scale: 2, // 提高清晰度
|
const a4Height = 841.89;
|
||||||
useCORS: true, // 允许加载跨域图片
|
const margin = 40; // 页边距(pt)
|
||||||
logging: false, // 关闭日志
|
|
||||||
backgroundColor: '#ffffff' // 设置背景色
|
// 初始化 PDF
|
||||||
|
const pdf = new jsPDF({
|
||||||
|
unit: 'pt',
|
||||||
|
format: 'a4',
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取canvas的宽高
|
// 获取内容的总高度
|
||||||
const imgWidth = 210; // A4纸的宽度(mm)
|
let remainingContent = element.cloneNode(true);
|
||||||
const pageHeight = 297; // A4纸的高度(mm)
|
document.body.appendChild(remainingContent);
|
||||||
const imgHeight = canvas.height * imgWidth / canvas.width;
|
remainingContent.style.width = `${a4Width - 2 * margin}pt`;
|
||||||
const pdfWidth = imgWidth;
|
const totalHeight = remainingContent.offsetHeight;
|
||||||
const pdfHeight = imgHeight;
|
|
||||||
|
|
||||||
// 将canvas转为图片
|
// 计算需要的页数
|
||||||
const imgData = canvas.toDataURL('image/jpeg', 1.0);
|
const contentHeight = a4Height - 2 * margin;
|
||||||
|
const pageCount = Math.ceil(totalHeight / contentHeight);
|
||||||
|
|
||||||
// 初始化jsPDF
|
// 逐页处理内容
|
||||||
const pdf = new jsPDF('p', 'mm', 'a4');
|
for (let i = 0; i < pageCount; i++) {
|
||||||
|
if (i > 0) {
|
||||||
// 计算分页
|
|
||||||
let position = 0;
|
|
||||||
let currentPage = 1;
|
|
||||||
|
|
||||||
while (position < pdfHeight) {
|
|
||||||
// 添加图片到PDF
|
|
||||||
pdf.addImage(
|
|
||||||
imgData,
|
|
||||||
'JPEG',
|
|
||||||
0, // x坐标
|
|
||||||
position === 0 ? 0 : -position, // y坐标
|
|
||||||
pdfWidth, // 图片宽度
|
|
||||||
pdfHeight // 图片高度
|
|
||||||
);
|
|
||||||
|
|
||||||
position += pageHeight;
|
|
||||||
|
|
||||||
// 如果还有内容,添加新页面
|
|
||||||
if (position < pdfHeight) {
|
|
||||||
pdf.addPage();
|
pdf.addPage();
|
||||||
currentPage++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建当前页的容器
|
||||||
|
const pageDiv = document.createElement('div');
|
||||||
|
pageDiv.style.width = `${a4Width - 2 * margin}pt`;
|
||||||
|
pageDiv.style.height = `${contentHeight}pt`;
|
||||||
|
pageDiv.style.position = 'absolute';
|
||||||
|
pageDiv.style.top = '0';
|
||||||
|
pageDiv.style.left = '0';
|
||||||
|
pageDiv.style.overflow = 'hidden';
|
||||||
|
|
||||||
|
// 克隆原始内容
|
||||||
|
const contentClone = element.cloneNode(true);
|
||||||
|
contentClone.style.transform = `translateY(-${i * contentHeight}pt)`;
|
||||||
|
pageDiv.appendChild(contentClone);
|
||||||
|
document.body.appendChild(pageDiv);
|
||||||
|
|
||||||
|
// 转换为图片并添加到 PDF
|
||||||
|
const canvas = await html2canvas(pageDiv, {
|
||||||
|
scale: 2,
|
||||||
|
useCORS: true,
|
||||||
|
logging: false,
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
});
|
||||||
|
|
||||||
|
const imgData = canvas.toDataURL('image/jpeg', 1.0);
|
||||||
|
pdf.addImage(imgData, 'JPEG', margin, margin, a4Width - 2 * margin, contentHeight);
|
||||||
|
|
||||||
|
// 清理临时元素
|
||||||
|
document.body.removeChild(pageDiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存PDF
|
// 清理克隆的元素
|
||||||
pdf.save(`${quotation.attributes.quataName || '报价单'}.pdf`);
|
document.body.removeChild(remainingContent);
|
||||||
|
|
||||||
// 关闭加载提示
|
pdf.save(`${quotation.attributes.quataName || '报价单'}.pdf`);
|
||||||
message.destroy();
|
message.destroy();
|
||||||
message.success('PDF导出成功!');
|
message.success('PDF导出成功!');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -81,6 +81,15 @@ export const allRoutes = [
|
|||||||
hidden: true,
|
hidden: true,
|
||||||
key: "company/quotaInfo",
|
key: "company/quotaInfo",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "quotaInfo/preview/:id?",
|
||||||
|
hidden: true,
|
||||||
|
component: lazy(() => import("@/pages/company/quotation/view")),
|
||||||
|
name: "报价单预览",
|
||||||
|
icon: "file",
|
||||||
|
key: "company/quotaInfo/preview",
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: "project",
|
path: "project",
|
||||||
component: lazy(() => import("@/pages/company/project")),
|
component: lazy(() => import("@/pages/company/project")),
|
||||||
@@ -140,7 +149,14 @@ export const allRoutes = [
|
|||||||
icon: "appstore",
|
icon: "appstore",
|
||||||
hidden: true,
|
hidden: true,
|
||||||
key: "company/projectView",
|
key: "company/projectView",
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
path: "templateItemManage",
|
||||||
|
component: lazy(() => import("@/pages/company/service/itemsManange")),
|
||||||
|
name: "资源类型",
|
||||||
|
icon: "container",
|
||||||
|
key: "company/templateItem",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user