/** * 运输计划单据(入库单 / 送货单 / 分装单)PDF 截图共用渲染策略。 * html2canvas 对 0.3px 边框与 border-collapse 在 Windows DPI 缩放下易画成粗线。 */ /** 固定像素倍率,不跟 devicePixelRatio,保证 Mac / Windows 栅格化尺度一致 */ export function getPlSlipPdfCanvasScale(): number { return 3 } /** * 将表格单元格边框改为「仅右+底」的 1px 背景线(首行补顶、首列补左)。 * 相邻格只画一条共享边,避免全边框叠成双线。 */ export function applyPdfStableTableCellBorders(cells: Iterable): void { const cellList = Array.from(cells) as HTMLElement[] if (!cellList.length) return const rows = new Map() for (const cell of cellList) { const tr = cell.closest('tr') if (!tr) continue const list = rows.get(tr) if (list) list.push(cell) else rows.set(tr, [cell]) } let rowIndex = 0 for (const [, rowCells] of rows) { rowCells.forEach((cell, colIndex) => { const gradients = ['linear-gradient(#000,#000)', 'linear-gradient(#000,#000)'] const sizes = ['100% 1px', '1px 100%'] const positions = ['left bottom', 'right top'] if (rowIndex === 0) { gradients.push('linear-gradient(#000,#000)') sizes.push('100% 1px') positions.push('left top') } if (colIndex === 0) { gradients.push('linear-gradient(#000,#000)') sizes.push('1px 100%') positions.push('left top') } cell.style.setProperty('border', 'none', 'important') cell.style.setProperty('border-width', '0', 'important') cell.style.setProperty('background-color', '#ffffff', 'important') cell.style.setProperty('background-image', gradients.join(','), 'important') cell.style.setProperty('background-size', sizes.join(','), 'important') cell.style.setProperty('background-position', positions.join(','), 'important') cell.style.setProperty('background-repeat', 'no-repeat', 'important') }) rowIndex += 1 } }