优化预览与导出排版

This commit is contained in:
iqudoo
2026-06-12 20:07:49 +08:00
parent 7ad1f59ae1
commit c9a187bf9b
7 changed files with 291 additions and 116 deletions

View File

@@ -1,6 +1,6 @@
import { jsPDF } from 'jspdf';
import type { PaperConfig, LabelTemplate, CutLineConfig } from './types';
import type { PrintableLabel } from './utils';
import { collectGridCutLinePositions, getCutLineChannel, type PrintableLabel } from './utils';
export interface PdfExportProgress {
done: number;
@@ -48,24 +48,61 @@ function parseColorToRgb(color: string): [number, number, number] {
return [204, 204, 204];
}
function drawCutLineRect(
pdf: jsPDF,
x: number,
y: number,
w: number,
h: number,
cutLine: CutLineConfig
) {
function setupCutLinePen(pdf: jsPDF, cutLine: CutLineConfig) {
const [r, g, b] = parseColorToRgb(cutLine.color);
pdf.setDrawColor(r, g, b);
pdf.setLineWidth(Math.max(0.02, cutLine.width));
pdf.setLineWidth(cutLine.width);
if (cutLine.style === 'dashed') {
const dash = Math.max(0.5, cutLine.width * 4);
pdf.setLineDashPattern([dash, dash], 0);
} else {
pdf.setLineDashPattern([], 0);
}
pdf.rect(x, y, w, h, 'S');
}
function drawPageGridCutLines(
pdf: jsPDF,
paper: PaperConfig,
labelW: number,
labelH: number,
gridCols: number,
gridRows: number,
cutLine: CutLineConfig
) {
const originX = paper.marginLeft;
const originY = paper.marginTop;
const lineW = Math.max(0.02, cutLine.width);
const { xs, ys, gridW, gridH } = collectGridCutLinePositions(
originX,
originY,
labelW,
labelH,
gridCols,
gridRows,
paper.columnGap,
paper.rowGap
);
const [r, g, b] = parseColorToRgb(cutLine.color);
pdf.setFillColor(r, g, b);
if (cutLine.style === 'solid') {
for (const y of ys) {
pdf.rect(originX, y - lineW / 2, gridW, lineW, 'F');
}
for (const x of xs) {
pdf.rect(x - lineW / 2, originY, lineW, gridH, 'F');
}
return;
}
setupCutLinePen(pdf, cutLine);
for (const y of ys) {
pdf.line(originX, y, originX + gridW, y);
}
for (const x of xs) {
pdf.line(x, originY, x, originY + gridH);
}
pdf.setLineDashPattern([], 0);
}
@@ -115,6 +152,8 @@ export async function exportLabelsPdfAsync(options: AsyncExportLabelsPdfOptions)
}
const pageRows = printablePages[pIdx];
const gridRows = Math.ceil(pageRows.length / gridCols);
const cutChannel = getCutLineChannel(paper.columnGap, paper.rowGap, cutLine);
report(pIdx + 1, 'render');
const pageJobs: { cellIdx: number; label: PrintableLabel }[] = [];
@@ -136,14 +175,12 @@ export async function exportLabelsPdfAsync(options: AsyncExportLabelsPdfOptions)
for (const { cellIdx, dataUrl } of rendered) {
const col = cellIdx % gridCols;
const row = Math.floor(cellIdx / gridCols);
const x = paper.marginLeft + col * (labelW + paper.columnGap);
const y = paper.marginTop + row * (labelH + paper.rowGap);
const x = paper.marginLeft + col * (labelW + paper.columnGap) + cutChannel.x;
const y = paper.marginTop + row * (labelH + paper.rowGap) + cutChannel.y;
const drawW = labelW - 2 * cutChannel.x;
const drawH = labelH - 2 * cutChannel.y;
pdf.addImage(dataUrl, imageFormat, x, y, labelW, labelH, undefined, 'FAST');
if (cutLine.enabled) {
drawCutLineRect(pdf, x, y, labelW, labelH, cutLine);
}
pdf.addImage(dataUrl, imageFormat, x, y, drawW, drawH, undefined, 'FAST');
done++;
}
@@ -156,6 +193,10 @@ export async function exportLabelsPdfAsync(options: AsyncExportLabelsPdfOptions)
}
}
if (cutLine.enabled && pageRows.length > 0) {
drawPageGridCutLines(pdf, paper, labelW, labelH, gridCols, gridRows, cutLine);
}
report(pIdx + 1, 'render');
await yieldToMain();
}