打印页面优化

This commit is contained in:
geht
2026-04-08 17:13:57 +08:00
parent 30ceadc832
commit adc0631569
2 changed files with 77 additions and 39 deletions

View File

@@ -344,7 +344,8 @@ function(t,e,printData){
for (var h=0;h<columns.length;h++){
var hc = columns[h];
var hw = hc.width ? ('width:'+hc.width+'pt;') : '';
var hbg = headerBg ? ('background:'+headerBg+';') : '';
var colBg = hc.headerBg || '';
var hbg = (colBg || headerBg) ? ('background:'+(colBg || headerBg)+';') : '';
html += '<th style="border:'+borderWidth+'px solid '+borderColor+';padding:'+cellPadding+';text-align:center;'+hbg+hw+'">'+esc(hc.title || hc.field || '')+'</th>';
}
html += '</tr></thead><tbody>';
@@ -653,6 +654,41 @@ function(t,e,printData){
align: c.align,
}));
const mergedGroups = groupEnabled.value ? [...groupFields.value] : [];
const readCanvasTableStyle = () => {
try {
const tables = Array.from(document.querySelectorAll('#hiprint-printTemplate table'));
if (!tables.length) return null;
const tb = tables[0] as HTMLTableElement;
const ths = Array.from(tb.querySelectorAll('thead th')) as HTMLElement[];
const th = ths.length > 0 ? ths[0] : null;
const td = tb.querySelector('tbody td') as HTMLElement | null;
const ref = th || td;
if (!ref) return null;
const cs = window.getComputedStyle(ref);
const tbcs = window.getComputedStyle(tb);
const validColor = (c: string) => !!c && c !== 'rgba(0, 0, 0, 0)' && c !== 'transparent';
const headerColors = ths.map((cell) => window.getComputedStyle(cell).backgroundColor || '');
const firstValidHeaderBg = headerColors.find((c) => validColor(c)) || '';
const bg = firstValidHeaderBg || (th ? window.getComputedStyle(th).backgroundColor : '');
const headerTitles = ths.map((cell) => (cell.textContent || '').trim());
const borderWidth = parseFloat(cs.borderTopWidth || '1') || 1;
const tableWidth = tb.style.width || (tbcs.width && tbcs.width !== 'auto' ? tbcs.width : '100%');
return {
fontSize: parseFloat(cs.fontSize || '10') || 10,
borderColor: cs.borderTopColor || '#000',
borderWidth: borderWidth,
cellPadding: `${cs.paddingTop || '2px'} ${cs.paddingRight || '4px'}`,
headerBg: bg && bg !== 'rgba(0, 0, 0, 0)' ? bg : '',
headerTitles,
headerColors,
tableWidth,
};
} catch (e) {
console.warn(e);
return null;
}
};
const domStyle = readCanvasTableStyle();
const extractColumnsFromElement = (el: any) => {
// 1) 新结构options.columns
@@ -715,6 +751,44 @@ function(t,e,printData){
headerBg: originOptions.headerBg,
tableWidth: originOptions.tableWidth,
};
// 保真模式:优先用画布真实样式兜底(含表头填充色)
if (preserveDesignStyle.value && domStyle) {
// 保真模式:列顺序与表头标题优先按画布 DOM 对齐
if (Array.isArray(domStyle.headerTitles) && domStyle.headerTitles.length > 0) {
const srcCols = Array.isArray(node.options.columns) ? [...node.options.columns] : [];
const unused = [...srcCols];
const ordered = domStyle.headerTitles.map((title: string, idx: number) => {
let hitIdx = -1;
if (title) {
hitIdx = unused.findIndex((c: any) => (c?.title || '').trim() === title);
}
let base: any;
if (hitIdx >= 0) {
base = unused.splice(hitIdx, 1)[0];
} else if (unused.length > 0) {
base = unused.shift();
} else {
base = srcCols[idx] || mergedCols[idx] || { title: title || `${idx + 1}`, field: '' };
}
return {
...base,
title: title || base?.title || base?.field || `${idx + 1}`,
headerBg: Array.isArray(domStyle.headerColors) ? domStyle.headerColors[idx] || '' : '',
};
});
if (ordered.length > 0) {
node.options.columns = ordered;
}
}
node.options.__qhmesStyle = {
fontSize: node.options.__qhmesStyle.fontSize || domStyle.fontSize,
borderColor: node.options.__qhmesStyle.borderColor || domStyle.borderColor,
borderWidth: node.options.__qhmesStyle.borderWidth || domStyle.borderWidth,
cellPadding: node.options.__qhmesStyle.cellPadding || domStyle.cellPadding,
headerBg: node.options.__qhmesStyle.headerBg || domStyle.headerBg,
tableWidth: node.options.__qhmesStyle.tableWidth || domStyle.tableWidth,
};
}
node.options.formatter = getTableSimpleFormatter();
}
@@ -963,35 +1037,6 @@ function(t,e,printData){
createMessage.success('已根据 table[0] 推导列配置');
}
function buildGroupedRowsVisualMerge(rows: any[], groups: string[]) {
if (!Array.isArray(rows) || rows.length === 0 || !Array.isArray(groups) || groups.length === 0) {
return rows;
}
const out = rows.map((r) => ({ ...r }));
for (let i = 1; i < out.length; i++) {
for (let level = 0; level < groups.length; level++) {
const field = groups[level];
// 上层一致才比较当前层
let upperSame = true;
for (let up = 0; up < level; up++) {
const upField = groups[up];
if ((out[i][upField] ?? '') !== (out[i - 1][upField] ?? '')) {
upperSame = false;
break;
}
}
if (!upperSame) break;
if ((out[i][field] ?? '') === (out[i - 1][field] ?? '')) {
// 保真模式下只清空重复值,保持原组件样式不变
out[i][field] = '';
} else {
break;
}
}
}
return out;
}
function parseTemplatePayload(str: string | undefined) {
if (!str || str === '{}') {
return { template: {}, ext: null as any };
@@ -1111,14 +1156,6 @@ function(t,e,printData){
return;
}
const data = parsePrintData();
if (preserveDesignStyle.value) {
// 样式优先:不改模板结构,只改分组字段的显示数据
if (groupEnabled.value && Array.isArray(data.table) && groupFields.value.length > 0) {
data.table = buildGroupedRowsVisualMerge(data.table, groupFields.value);
}
hiprintTemplate.print(data, {}, { callback: () => {} });
return;
}
// 兜底:即使元素 options 未同步,预览时也从全局参数读取列和分组配置
let parsedCols: any[] = [];
try {

View File

@@ -144,7 +144,8 @@ function(t,e,printData){
for (var h=0;h<columns.length;h++){
var hc = columns[h];
var hw = hc.width ? ('width:'+hc.width+'pt;') : '';
var hbg = headerBg ? ('background:'+headerBg+';') : '';
var colBg = hc.headerBg || '';
var hbg = (colBg || headerBg) ? ('background:'+(colBg || headerBg)+';') : '';
html += '<th style="border:'+borderWidth+'px solid '+borderColor+';padding:'+cellPadding+';text-align:center;'+hbg+hw+'">'+esc(hc.title || hc.field || '')+'</th>';
}
html += '</tr></thead><tbody>';