diff --git a/jeecgboot-vue3/src/views/print/template/native/core/printRenderer.ts b/jeecgboot-vue3/src/views/print/template/native/core/printRenderer.ts index 6374ff3..837109c 100644 --- a/jeecgboot-vue3/src/views/print/template/native/core/printRenderer.ts +++ b/jeecgboot-vue3/src/views/print/template/native/core/printRenderer.ts @@ -157,7 +157,8 @@ async function renderTablePage( }), ) ).join(''); - return `${cells}`; + // 使用 min-height:长文本/二维码撑高行时以内容为准,避免固定 height 与实高不一致导致分页估算偶发偏差 + return `${cells}`; }), ) ).join(''); @@ -673,6 +674,46 @@ function resolveDetailTableChunkTopMm( const MM_TO_CSS_PX = 96 / 25.4; const CSS_PX_PER_MM = MM_TO_CSS_PX; +/** 版心底部保留的防裁切余量(mm)。过大则本页明明还能放 1~2 行却提前换页导致大块留白;过小易压分页缝 */ +const AUTO_PAGE_CHUNK_INSET_MM = 1.4; +/** 累计行高微调:略大于 1 防亚像素/线宽误差,不宜过大以免总行高膨胀、底部空白 */ +const AUTO_PAGE_ROW_HEIGHT_FIT_FACTOR = 1.03; + +/** 判断是否视为「全角级」占宽,用于换行行数估算(拉丁字母约 0.62em,汉字约 1em) */ +function isFullWidthWrapCodePoint(cp: number): boolean { + return ( + (cp >= 0x2e80 && cp <= 0x9fff) || // CJK/CJK 部首等 + (cp >= 0x3040 && cp <= 0x30ff) || // 假名 + (cp >= 0xac00 && cp <= 0xd7af) || // 谚文音节 + (cp >= 0xf900 && cp <= 0xfaff) || // 兼容汉字 + (cp >= 0xff00 && cp <= 0xffef) + ); // 全角ASCII +} + +/** + * 按列宽与字体估算换行宽度单位(拉丁≈0.62、CJK≈1),避免纯用字符数/拉丁 charWidth 低估中文行数导致偶发跨页裁切。 + */ +function estimateTextWrapLines(text: string, innerWpx: number, fontSize: number): number { + if (!text.length) { + return 1; + } + let units = 0; + for (const ch of text) { + const cp = ch.codePointAt(0)!; + if (isFullWidthWrapCodePoint(cp)) { + units += 1; + } else if (/\s/.test(ch)) { + units += 0.22; + } else { + units += 0.62; + } + } + units = Math.max(0.01, units); + // 每行可容纳的等效「全角」数:0.97 在防中文低估与避免行数虚高之间折中 + const unitsPerLine = Math.max(1.8, (innerWpx / Math.max(1, fontSize)) * 0.97); + return Math.max(1, Math.ceil(units / unitsPerLine)); +} + /** * 估算表格数据行在纸面上的高度(mm)。换行/二维码等会使实际行高远大于设计 rowHeight, * 若仍按固定 rowHeight 分页会导致整表落在同一 chunk、页数为 1 且预览溢出灰底。 @@ -681,6 +722,8 @@ function estimateTableBodyRowHeightMm(element: NativeTableElement, row: Record