<!doctype html>
|
<html>
|
<head>
|
<meta charset="UTF-8" />
|
<style>
|
/* 页面基础设置 */
|
* {
|
margin: 0;
|
padding: 0;
|
box-sizing: border-box;
|
}
|
|
body {
|
font-family:
|
'SimSun',
|
'Microsoft YaHei',
|
-apple-system,
|
BlinkMacSystemFont,
|
sans-serif;
|
font-size: 3mm;
|
line-height: 1.6;
|
}
|
|
/* 主表格 */
|
.main-table {
|
width: 100%;
|
border-collapse: collapse;
|
table-layout: fixed;
|
}
|
|
.main-table th,
|
.main-table td {
|
border: 1px solid #333;
|
padding: 1.5mm 2mm;
|
text-align: center;
|
vertical-align: middle;
|
}
|
|
/* Logo 单元格 */
|
.logo-cell {
|
width: 25mm;
|
padding: 0.5mm;
|
text-align: center;
|
vertical-align: middle;
|
}
|
|
.logo-placeholder {
|
width: 22mm;
|
height: 22mm;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin: 0 auto;
|
}
|
|
.logo-placeholder img {
|
width: 100%;
|
height: 100%;
|
object-fit: contain;
|
}
|
|
/* 公司名称 */
|
.company-name {
|
font-size: 4.5mm;
|
font-weight: bold;
|
padding: 1.5mm 2mm;
|
}
|
|
/* 报告名称 */
|
.report-name {
|
font-size: 3.75mm;
|
font-weight: bold;
|
padding: 1.5mm 2mm;
|
}
|
|
/* 编号 */
|
.doc-number {
|
font-size: 3.25mm;
|
font-weight: bold;
|
padding: 1.5mm 2mm;
|
}
|
|
/* 报告书编号 */
|
.report-book-number {
|
font-size: 3mm;
|
text-align: right !important;
|
padding: 1mm 2mm;
|
border: none !important;
|
}
|
|
/* 依据说明 */
|
.basis-row td {
|
text-align: left !important;
|
padding: 1.5mm 2mm;
|
font-size: 3mm;
|
border: none !important;
|
}
|
|
/* 页码标签 */
|
.page-code-label {
|
font-size: 3.25mm;
|
width: 20mm;
|
padding: 1.5mm 2mm;
|
}
|
|
/* 页码值 */
|
.page-code-value {
|
font-size: 3.25mm;
|
font-weight: bold;
|
text-decoration: underline;
|
width: 20mm;
|
padding: 1.5mm 2mm;
|
}
|
|
/* 依据说明 */
|
.basis-row td {
|
text-align: left !important;
|
padding: 1.5mm 2mm;
|
font-size: 3mm;
|
}
|
|
/* 打印样式中确保依据行左对齐 */
|
@media print {
|
.basis-row td {
|
text-align: left !important;
|
}
|
}
|
|
/* 数据表头 */
|
.data-header {
|
font-weight: bold;
|
}
|
|
/* 内容单元格 */
|
.content-cell {
|
text-align: left !important;
|
font-size: 2.75mm;
|
}
|
|
/* 合并单元格的样式 */
|
.category-cell {
|
font-weight: bold;
|
}
|
|
/* 样品信息行 */
|
.sample-info-row {
|
font-size: 3mm;
|
}
|
|
/* 数据表头行 */
|
.data-header-row {
|
font-weight: bold;
|
}
|
|
/* 隐藏测量容器 - 使用打印样式确保测量准确 */
|
.measure-container {
|
position: absolute;
|
visibility: hidden;
|
left: -9999px;
|
top: 0;
|
}
|
|
.measure-container .main-table {
|
width: 210mm;
|
border-collapse: collapse;
|
table-layout: fixed;
|
}
|
|
.measure-container .main-table th,
|
.measure-container .main-table td {
|
border: 1px solid #333;
|
padding: 1mm 1.5mm; /* 使用打印时的 padding */
|
font-size: 2.75mm; /* 使用打印时的 font-size */
|
text-align: center;
|
vertical-align: middle;
|
}
|
|
.measure-container .main-table td.category-cell {
|
font-weight: bold;
|
}
|
|
.measure-container .main-table td.content-cell {
|
text-align: left;
|
word-wrap: break-word;
|
}
|
|
/* 屏幕预览样式 */
|
@media screen {
|
body {
|
background: #f0f0f0;
|
padding: 10mm;
|
}
|
|
.screen-view {
|
display: block;
|
max-width: 210mm;
|
min-height: 297mm;
|
margin: 0 auto;
|
background: white;
|
padding: 5mm;
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
}
|
|
.print-pages {
|
display: none !important;
|
}
|
}
|
|
/* 打印样式 */
|
@media print {
|
/* 打印机页面设置 - 清除浏览器的默认边距 */
|
@page {
|
size: A4;
|
margin: 0; /* 清除所有边距,让代码完全控制 */
|
}
|
|
body {
|
background: white;
|
padding: 0;
|
margin: 0;
|
}
|
|
.no-print,
|
.screen-view {
|
display: none !important;
|
}
|
|
.print-pages {
|
display: block !important;
|
}
|
|
/* 确保依据行在打印时也是左对齐 */
|
.basis-row td {
|
text-align: left !important;
|
}
|
|
.page-section {
|
break-after: page;
|
page-break-after: always;
|
height: 297mm; /* 使用完整 A4 高度 */
|
width: 210mm; /* 使用完整 A4 宽度 */
|
overflow: hidden;
|
position: relative;
|
padding: 10mm 10mm 10mm 10mm; /* 统一边距 10mm */
|
box-sizing: border-box;
|
margin: 0;
|
}
|
|
.page-section:last-child {
|
break-after: auto;
|
page-break-after: auto;
|
}
|
|
.page-section .main-table {
|
border-collapse: collapse;
|
width: 100%;
|
table-layout: fixed;
|
}
|
|
.page-section .main-table th,
|
.page-section .main-table td {
|
border: 1px solid #333;
|
padding: 1mm 1.5mm;
|
text-align: center;
|
vertical-align: middle;
|
font-size: 2.75mm;
|
overflow: visible;
|
word-wrap: break-word; /* 允许内容换行 */
|
word-break: break-all;
|
}
|
|
/* 确保表格底部有边框 */
|
.page-section .main-table tbody tr:last-child td,
|
.page-section .main-table tbody tr:last-child th {
|
border-bottom: 1px solid #333 !important;
|
}
|
|
/* 表格行不被截断 */
|
.page-section .main-table tbody tr {
|
break-inside: avoid !important;
|
page-break-inside: avoid !important;
|
}
|
}
|
</style>
|
</head>
|
<body>
|
<!-- 屏幕预览:连续表格 -->
|
<div class="screen-view">
|
<table class="main-table" id="source-table"></table>
|
</div>
|
|
<!-- 打印预览:分页容器 -->
|
<div class="print-pages no-screen" id="print-container"></div>
|
|
<script>
|
// ==================== 数据层 ====================
|
// 从 window.templateData 读取外部传入的数据
|
const templateData = window.templateData || {};
|
|
// 页面配置常量 - 全部使用毫米单位
|
const PAGE_CONFIG = {
|
width: 210, // A4 宽度 mm
|
height: 297, // A4 高度 mm
|
paddingTop: 10, // 上边距 mm
|
paddingBottom: 10, // 下边距 mm
|
sampleInfoHeight: 12, // 样品信息 + 报告书编号行的高度 mm
|
safetyMargin: 20, // 安全边距 mm(增大以防止截断)
|
|
// 毫米转像素(96 DPI)
|
mmToPx(mm) {
|
return mm * 3.779527559;
|
},
|
|
// 可用高度 = A4高度 - 上下边距 - 安全边距
|
get availableHeightPx() {
|
const availableMm = this.height - this.paddingTop - this.paddingBottom - this.safetyMargin;
|
return this.mmToPx(availableMm);
|
},
|
|
// 第一页额外减去样品信息高度
|
get firstPageExtraHeight() {
|
return this.mmToPx(this.sampleInfoHeight);
|
},
|
};
|
|
// API 响应字段(结构见 jianyan_baogao.md)
|
const header = templateData.header || {};
|
const groups = templateData.groups || [];
|
const yiju = templateData.yiju || '';
|
const jielun = templateData.jielun || '';
|
const signatures = templateData.signatures || {};
|
const beizhu = templateData.beizhu || '';
|
const templateName = templateData.template_name || '';
|
|
// 模板静态显示信息(非 API 字段,由渲染页面设置)
|
const companyName = templateData.companyName || '';
|
const docNumber = templateData.docNumber || '';
|
const reportBookNumber = templateData.reportBookNumber || '';
|
const tableColgroupHTML =
|
'<colgroup>' +
|
'<col style="width: 16%;">' +
|
'<col style="width: 20%;">' +
|
'<col style="width: 13%;">' +
|
'<col style="width: 19%;">' +
|
'<col style="width: 13%;">' +
|
'<col style="width: 19%;">' +
|
'</colgroup>';
|
|
function formatSignature(sig) {
|
if (!sig) return '';
|
return (sig.name || '') + (sig.date ? ' ' + sig.date : '');
|
}
|
|
function buildSignatureItems() {
|
return [
|
{
|
role: (signatures.baogaoren && signatures.baogaoren.label) || '报告人/日期',
|
value: formatSignature(signatures.baogaoren),
|
},
|
{
|
role: (signatures.fuheren && signatures.fuheren.label) || '复核人/日期',
|
value: formatSignature(signatures.fuheren),
|
},
|
{
|
role: (signatures.pizhunren && signatures.pizhunren.label) || 'QC经理/日期',
|
value: formatSignature(signatures.pizhunren),
|
},
|
];
|
}
|
|
function hasSignature() {
|
return !!(signatures.baogaoren || signatures.fuheren || signatures.pizhunren);
|
}
|
|
function generateSignatureMainRowHTML(items) {
|
return (
|
'<tr>' +
|
'<td class="category-cell">' +
|
escapeHtml(items[0].role) +
|
'</td>' +
|
'<td>' +
|
escapeHtml(items[0].value) +
|
'</td>' +
|
'<td class="category-cell">' +
|
escapeHtml(items[1].role) +
|
'</td>' +
|
'<td>' +
|
escapeHtml(items[1].value) +
|
'</td>' +
|
'<td class="category-cell">' +
|
escapeHtml(items[2].role) +
|
'</td>' +
|
'<td>' +
|
escapeHtml(items[2].value) +
|
'</td>' +
|
'</tr>'
|
);
|
}
|
|
// HTML 转义函数(防止特殊字符破坏 HTML 结构)
|
function escapeHtml(text) {
|
if (text === null || text === undefined) return '';
|
return String(text).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
}
|
|
// ==================== HTML 生成函数 ====================
|
|
// 生成表头 HTML(每页都需要)
|
function generateHeaderHTML(pageNum, totalPages) {
|
return (
|
'<tr>' +
|
'<td rowspan="3" class="logo-cell">' +
|
'<div class="logo-placeholder"><img src="/logo.png" alt="Logo"></div>' +
|
'</td>' +
|
'<td colspan="5" class="company-name">' +
|
companyName +
|
'</td>' +
|
'</tr>' +
|
'<tr>' +
|
'<td colspan="3" class="report-name">' +
|
templateName +
|
'</td>' +
|
'<td colspan="2" class="page-code-label">页码</td>' +
|
'</tr>' +
|
'<tr>' +
|
'<td colspan="3" class="doc-number">' +
|
docNumber +
|
'</td>' +
|
'<td colspan="2" class="page-code-value">' +
|
pageNum +
|
' / ' +
|
totalPages +
|
'</td>' +
|
'</tr>' +
|
'<tr>' +
|
'<td colspan="6" class="report-book-number">报告书编号:' +
|
reportBookNumber +
|
'</td>' +
|
'</tr>'
|
);
|
}
|
|
// 生成样品信息 HTML(字段来自 API header)
|
function generateSampleInfoHTML() {
|
const rows = [
|
['产品名称', header.chanpin_mingcheng, '批号', header.pihao],
|
['来源编码', header.laiyuan_bianma, '产品编码', header.chanpin_bianma],
|
['规格', header.guige, '生产日期', header.shengchan_riqi],
|
['批量', (header.piliang || '') + ' ' + (header.piliang_danwei || ''), '有效期至', header.youxiaoqi],
|
];
|
let html = '';
|
rows.forEach(function (r) {
|
html +=
|
'<tr class="sample-info-row data-header">' +
|
'<td class="category-cell">' +
|
escapeHtml(r[0]) +
|
'</td>' +
|
'<td>' +
|
escapeHtml(r[1]) +
|
'</td>' +
|
'<td colspan="2" class="category-cell">' +
|
escapeHtml(r[2]) +
|
'</td>' +
|
'<td colspan="2">' +
|
escapeHtml(r[3]) +
|
'</td>' +
|
'</tr>';
|
});
|
html += '<tr class="basis-row">' + '<td colspan="6"><strong>依据:</strong>' + escapeHtml(yiju) + '</td>' + '</tr>';
|
return html;
|
}
|
|
// 生成列标题 HTML
|
function generateColumnHeadersHTML() {
|
return (
|
'<tr class="data-header-row">' + '<td>质量属性</td>' + '<td colspan="2">检验项目</td>' + '<td>放行标准</td>' + '<td colspan="2">结果</td>' + '</tr>'
|
);
|
}
|
|
// 按分类对行进行分组(用于计算 rowspan)
|
function groupRowsByCategory(rows) {
|
const groups = [];
|
let currentGroup = null;
|
|
rows.forEach((row) => {
|
if (row.type !== 'test') {
|
// 非检测项目行(结论、签名、备注)单独成组
|
if (currentGroup) {
|
groups.push(currentGroup);
|
currentGroup = null;
|
}
|
groups.push({ category: row.category, rows: [row] });
|
} else {
|
// 检测项目行按分类分组
|
if (!currentGroup || currentGroup.category !== row.category) {
|
if (currentGroup) {
|
groups.push(currentGroup);
|
}
|
currentGroup = { category: row.category, rows: [] };
|
}
|
currentGroup.rows.push(row);
|
}
|
});
|
|
if (currentGroup) {
|
groups.push(currentGroup);
|
}
|
|
return groups;
|
}
|
|
// 将 groups 数据和结论/签名/备注扁平化为行数组
|
function flattenTestItems() {
|
const rows = [];
|
|
groups.forEach(function (group) {
|
group.items.forEach(function (item, index) {
|
rows.push({
|
category: group.fenxi_leixing,
|
isFirstRow: index === 0,
|
totalRows: group.items.length,
|
rowIndex: index,
|
type: 'test',
|
name: item.jianyan_xiangmu_mingcheng,
|
standard: item.biaozhun_guiding,
|
result: item.jianyan_jieguo,
|
});
|
});
|
});
|
|
if (jielun) {
|
rows.push({
|
category: '结论',
|
isFirstRow: true,
|
totalRows: 1,
|
rowIndex: 0,
|
type: 'conclusion',
|
label: '结论',
|
content: jielun,
|
});
|
}
|
|
if (hasSignature()) {
|
rows.push({
|
category: '签名',
|
isFirstRow: true,
|
totalRows: 1,
|
rowIndex: 0,
|
type: 'signature',
|
items: buildSignatureItems(),
|
});
|
}
|
|
if (beizhu) {
|
rows.push({
|
category: '备注',
|
isFirstRow: true,
|
totalRows: 1,
|
rowIndex: 0,
|
type: 'remarks',
|
label: '备注',
|
content: Array.isArray(beizhu) ? beizhu : [beizhu],
|
});
|
}
|
|
return rows;
|
}
|
|
// 生成单行 HTML - 每页独立渲染
|
// showCategory: 是否显示分类单元格(第一行或新页面的第一行需要显示)
|
// rowspan: 分类单元格需要跨的行数(仅在 showCategory 为 true 时有效)
|
function generateDataRowHTML(row, showCategory = false, rowspan = 1) {
|
// 处理结论行 - 结论单独一行,第一列显示"结论"
|
if (row.type === 'conclusion') {
|
return (
|
'<tr>' +
|
'<td class="category-cell">' +
|
row.label +
|
'</td>' +
|
'<td colspan="5" class="content-cell">' +
|
'<span style="font-size: 3.25mm;">' +
|
escapeHtml(row.content) +
|
'</span>' +
|
'</td>' +
|
'</tr>'
|
);
|
}
|
|
// 处理签名行 - 三组签名同一行显示
|
if (row.type === 'signature') {
|
return generateSignatureMainRowHTML(row.items);
|
}
|
|
// 处理备注行 - 单独一行
|
if (row.type === 'remarks') {
|
const content = row.content.map((r) => escapeHtml(r)).join('<br>');
|
return '<tr>' + '<td class="category-cell">' + row.label + '</td>' + '<td colspan="5" class="content-cell">' + content + '</td>' + '</tr>';
|
}
|
|
// 处理检测项目行(默认类型)
|
// 只有分类的第一行显示分类单元格(使用 rowspan 合并)
|
if (showCategory) {
|
// 显示分类单元格(使用 rowspan 合并)
|
const rowspanAttr = rowspan > 1 ? ' rowspan="' + rowspan + '"' : '';
|
return (
|
'<tr>' +
|
'<td class="category-cell"' +
|
rowspanAttr +
|
'>' +
|
row.category +
|
'</td>' +
|
'<td colspan="2" class="content-cell">' +
|
row.name +
|
'</td>' +
|
'<td class="content-cell">' +
|
row.standard +
|
'</td>' +
|
'<td colspan="2">' +
|
row.result +
|
'</td>' +
|
'</tr>'
|
);
|
} else {
|
// 非第一行,不显示分类单元格(已被 rowspan 合并)
|
return (
|
'<tr>' +
|
'<td colspan="2" class="content-cell">' +
|
row.name +
|
'</td>' +
|
'<td class="content-cell">' +
|
row.standard +
|
'</td>' +
|
'<td colspan="2">' +
|
row.result +
|
'</td>' +
|
'</tr>'
|
);
|
}
|
}
|
|
// 生成结论和签名 HTML(仅用于测量高度)
|
function generateConclusionHTML() {
|
let html = '';
|
|
if (jielun) {
|
html +=
|
'<tr class="sample-info-row data-header">' +
|
'<td class="category-cell">结论</td>' +
|
'<td colspan="5" class="content-cell">' +
|
'<span style="font-size: 3.25mm;">' +
|
escapeHtml(jielun) +
|
'</span>' +
|
'</td>' +
|
'</tr>';
|
}
|
|
if (hasSignature()) {
|
html += generateSignatureMainRowHTML(buildSignatureItems());
|
}
|
|
if (beizhu) {
|
var content = Array.isArray(beizhu)
|
? beizhu
|
.map(function (r) {
|
return escapeHtml(r);
|
})
|
.join('<br>')
|
: escapeHtml(beizhu);
|
html +=
|
'<tr class="sample-info-row data-header">' +
|
'<td class="category-cell">备注</td>' +
|
'<td colspan="5" class="content-cell">' +
|
content +
|
'</td>' +
|
'</tr>';
|
}
|
|
return html;
|
}
|
|
// ==================== 测量层 ====================
|
|
// 测量表头高度和每行高度
|
function measureHeights() {
|
// 创建测量容器
|
const measureDiv = document.createElement('div');
|
measureDiv.className = 'measure-container';
|
document.body.appendChild(measureDiv);
|
|
// 创建测量表格 - 包含完整表头(第一页表头)
|
const measureTable = document.createElement('table');
|
measureTable.className = 'main-table';
|
measureTable.innerHTML = `
|
${tableColgroupHTML}
|
<thead>${generateHeaderHTML(1, 1)}${generateSampleInfoHTML()}${generateColumnHeadersHTML()}</thead>
|
<tbody id="measure-tbody"></tbody>
|
`;
|
measureDiv.appendChild(measureTable);
|
|
// 测量第一页表头高度(包含样品信息)
|
const theadRows = measureTable.querySelectorAll('thead tr');
|
let firstPageHeaderHeight = 0;
|
theadRows.forEach((tr) => {
|
firstPageHeaderHeight += tr.offsetHeight;
|
});
|
|
// 测量后续页表头高度(不包含样品信息)- 样品信息约4行
|
let otherPageHeaderHeight = firstPageHeaderHeight;
|
const sampleInfoRows = Array.from(theadRows).filter((tr) => tr.classList.contains('sample-info-row'));
|
const sampleInfoHeight = sampleInfoRows.reduce((sum, tr) => sum + tr.offsetHeight, 0);
|
otherPageHeaderHeight = firstPageHeaderHeight - sampleInfoHeight;
|
|
// 测量每行高度
|
const tbody = measureTable.querySelector('#measure-tbody');
|
const rows = flattenTestItems();
|
const rowHeights = [];
|
|
rows.forEach((row) => {
|
const tr = document.createElement('tr');
|
tr.innerHTML = generateDataRowHTML(row, row.isFirstRow).replace('<tr>', '').replace('</tr>', '');
|
tbody.appendChild(tr);
|
rowHeights.push(tr.offsetHeight);
|
tbody.innerHTML = '';
|
});
|
|
// 清理测量容器
|
document.body.removeChild(measureDiv);
|
|
return {
|
firstPageHeaderHeight,
|
otherPageHeaderHeight,
|
rowHeights,
|
rows,
|
};
|
}
|
|
// ==================== 分页引擎 ====================
|
|
// 计算分页 - 简单逐行分页,不需要考虑 rowspan
|
function calculatePages(rowHeights, rows, availableHeight) {
|
const pages = [];
|
let currentPage = [];
|
let currentHeight = 0;
|
let isFirstPage = true; // 标记是否是第一页
|
|
function getCurrentLimit() {
|
// 第一页需要减去样品信息的高度
|
if (isFirstPage) {
|
return availableHeight - PAGE_CONFIG.firstPageExtraHeight;
|
}
|
// 后续页使用全部可用高度
|
return availableHeight;
|
}
|
|
rows.forEach((row, index) => {
|
const height = rowHeights[index];
|
const limit = getCurrentLimit();
|
|
// 检查当前页是否能容纳
|
if (currentHeight + height > limit && currentPage.length > 0) {
|
// 当前页放不下,新建一页
|
pages.push(currentPage);
|
currentPage = [index];
|
currentHeight = height;
|
isFirstPage = false; // 不再是第一页
|
} else {
|
// 当前页能容纳
|
currentPage.push(index);
|
currentHeight += height;
|
}
|
});
|
|
if (currentPage.length > 0) {
|
pages.push(currentPage);
|
}
|
|
return pages;
|
}
|
|
// ==================== 渲染层 ====================
|
|
// 渲染屏幕预览(连续表格)
|
function renderScreenView() {
|
const table = document.getElementById('source-table');
|
const rows = flattenTestItems();
|
|
// 按分类分组,计算每个分类的 rowspan
|
const categoryGroups = groupRowsByCategory(rows);
|
|
let tbodyContent = '';
|
categoryGroups.forEach((group) => {
|
group.rows.forEach((row, index) => {
|
// 分类内第一行显示分类单元格(使用 rowspan)
|
const showCategory = index === 0 && row.type === 'test';
|
const rowspan = showCategory ? group.rows.length : 1;
|
tbodyContent += generateDataRowHTML(row, showCategory, rowspan);
|
});
|
});
|
|
table.innerHTML =
|
tableColgroupHTML +
|
'<thead>' +
|
generateHeaderHTML(1, 1) +
|
generateSampleInfoHTML() +
|
generateColumnHeadersHTML() +
|
'</thead>' +
|
'<tbody>' +
|
tbodyContent +
|
'</tbody>';
|
}
|
|
// 渲染分页打印内容
|
function renderPrintPages() {
|
const container = document.getElementById('print-container');
|
container.innerHTML = '';
|
|
// 测量
|
const { firstPageHeaderHeight, otherPageHeaderHeight, rowHeights, rows } = measureHeights();
|
|
// 使用统一的可用高度(已包含安全边距)
|
const availableHeight = PAGE_CONFIG.availableHeightPx;
|
|
// 计算分页(逐行)
|
const pages = calculatePages(rowHeights, rows, availableHeight);
|
const totalPages = pages.length;
|
|
// 渲染每页
|
pages.forEach((pageRowIndices, pageIndex) => {
|
const pageNum = pageIndex + 1;
|
const pageSection = document.createElement('div');
|
pageSection.className = 'page-section';
|
|
// 创建表格
|
const table = document.createElement('table');
|
table.className = 'main-table';
|
|
// 第一页包含样品信息,后续页只有列标题
|
const theadContent =
|
pageIndex === 0
|
? generateHeaderHTML(pageNum, totalPages) + generateSampleInfoHTML() + generateColumnHeadersHTML()
|
: generateHeaderHTML(pageNum, totalPages) + generateColumnHeadersHTML();
|
|
// 生成 tbody 内容
|
let tbodyContent = '';
|
|
pageRowIndices.forEach((rowIdx) => {
|
const row = rows[rowIdx];
|
// 只有分类的第一行显示分类名称
|
tbodyContent += generateDataRowHTML(row, row.isFirstRow);
|
});
|
|
table.innerHTML = tableColgroupHTML + '<thead>' + theadContent + '</thead>' + '<tbody>' + tbodyContent + '</tbody>';
|
|
pageSection.appendChild(table);
|
container.appendChild(pageSection);
|
});
|
}
|
|
// ==================== 初始化 ====================
|
|
// 页面加载时初始化
|
window.addEventListener('load', function () {
|
renderScreenView();
|
// 延迟执行分页渲染,确保字体等资源加载完成
|
setTimeout(renderPrintPages, 100);
|
});
|
|
// 打印前重新计算分页
|
window.addEventListener('beforeprint', function () {
|
renderPrintPages();
|
});
|
|
// 窗口大小变化时重新计算(用于调试)
|
let resizeTimer;
|
window.addEventListener('resize', function () {
|
clearTimeout(resizeTimer);
|
resizeTimer = setTimeout(renderPrintPages, 250);
|
});
|
</script>
|
</body>
|
</html>
|