fix(intake): refine second-template barcode layout

This commit is contained in:
WuYongJie 2026-07-01 10:28:44 +08:00
parent 354a154fee
commit 8510049293
4 changed files with 96 additions and 14 deletions

View File

@ -21,6 +21,7 @@ export function BarcodePrintTemplateDialog({
isOpen,
mode,
templates,
defaultTemplateTitle,
rowSummary,
onClose,
onSubmit,
@ -28,15 +29,19 @@ export function BarcodePrintTemplateDialog({
isOpen: boolean;
mode: BarcodePrintTemplateDialogMode;
templates: PrintTemplateOption[];
defaultTemplateTitle?: string;
rowSummary: string;
onClose: () => void;
onSubmit: (value: BarcodePrintTemplateDialogSubmit) => void;
}) {
const defaultTemplateTitle = useMemo(
() => templates[0]?.title ?? "",
[templates],
const resolvedDefaultTemplateTitle = useMemo(
() =>
templates.some((template) => template.title === defaultTemplateTitle)
? defaultTemplateTitle ?? ""
: (templates[0]?.title ?? ""),
[defaultTemplateTitle, templates],
);
const [templateTitle, setTemplateTitle] = useState(defaultTemplateTitle);
const [templateTitle, setTemplateTitle] = useState(resolvedDefaultTemplateTitle);
const [batchNumber, setBatchNumber] = useState("");
const [errorMessage, setErrorMessage] = useState("");
const title = mode === "barcode" ? "请选择打印模板" : "请选择合格证模板";
@ -46,13 +51,17 @@ export function BarcodePrintTemplateDialog({
useEffect(() => {
if (!isOpen) return;
setTemplateTitle(resolvedDefaultTemplateTitle);
setBatchNumber("");
setErrorMessage("");
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Escape") onClose();
};
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, [isOpen, onClose]);
}, [isOpen, onClose, resolvedDefaultTemplateTitle]);
if (!isOpen) return null;

View File

@ -61,6 +61,7 @@ import {
} from "./barcodePrintProgressState";
import {
BARCODE_PRINT_TEMPLATE_OPTIONS,
getDefaultBarcodePrintTemplateTitle,
printBarcodeRow,
} from "./barcodePrintLodop";
import type {
@ -624,6 +625,11 @@ export function BarcodePrintWorkspace({
? CERTIFICATE_PRINT_TEMPLATE_OPTIONS
: BARCODE_PRINT_TEMPLATE_OPTIONS
}
defaultTemplateTitle={
pendingPrintJob.mode === "barcode"
? getDefaultBarcodePrintTemplateTitle(pendingPrintRow)
: undefined
}
rowSummary={buildPrintRowSummary(pendingPrintRow)}
onClose={() => setPendingPrintJob(null)}
onSubmit={(value) => void handleTemplatePrint(value)}

View File

@ -24,4 +24,12 @@ describe("splitBarcodeParts", () => {
bar3: "Z396V01",
});
});
it("keeps the full first segment for GBSFY-LRSF style prefixes", () => {
expect(__barcodePrintTestUtils.splitBarcodeParts("GBSFY-LRSF009001N1280V01")).toEqual({
catcode: "GBSFY-LRSF",
bar2: "009001",
bar3: "N1280V01",
});
});
});

View File

@ -185,6 +185,35 @@ export const __barcodePrintTestUtils = {
splitBarcodeParts,
};
function getDefaultBarcodeTemplateVariant(row: BarcodePrintRow) {
if (row.supplierName.includes("顾家")) {
return "gujia" as const;
}
const barcode = trimText(row.barcode);
if (!barcode) {
return "first" as const;
}
return splitBarcodeParts(barcode).catcode ? "second" as const : "first" as const;
}
export function getDefaultBarcodePrintTemplateTitle(row: BarcodePrintRow) {
const variant = getDefaultBarcodeTemplateVariant(row);
if (variant === "gujia") {
return BARCODE_PRINT_TEMPLATES.find((template) => template.title === "椤惧")?.title
?? BARCODE_PRINT_TEMPLATES[0]?.title
?? "";
}
if (variant === "second") {
return BARCODE_PRINT_TEMPLATES[1]?.title ?? BARCODE_PRINT_TEMPLATES[0]?.title ?? "";
}
return BARCODE_PRINT_TEMPLATES[0]?.title ?? "";
}
function buildLodopRecord(row: BarcodePrintRow): BarcodeLodopRecord {
const barcode = trimText(row.barcode);
if (!barcode) {
@ -295,6 +324,15 @@ function setFont(lodop: Lodop, size: number, bold = false) {
if (bold) lodop.SET_PRINT_STYLEA(0, "Bold", 1);
}
function getAdaptiveCenterFontSize(value: string, baseSize: number) {
const digitCount = value.trim().length;
if (digitCount <= 6) return baseSize;
if (digitCount === 7) return Math.max(20, baseSize - 4);
return Math.max(18, baseSize - 6);
}
function printCommonLayout(
record: BarcodeLodopRecord,
lodop: Lodop,
@ -307,8 +345,11 @@ function printCommonLayout(
productionBatchLeft?: number;
splitCodePrefixLeft?: number;
splitCodePrefixWidth?: number;
splitCodeCenterTop?: number;
splitCodeCenterLeft?: number;
splitCodeCenterWidth?: number;
splitCodeCenterHeight?: number;
splitCodeCenterFontSize?: number;
splitCodeSuffixLeft?: number;
splitCodeSuffixWidth?: number;
splitCodeSuffixFontSize?: number;
@ -334,8 +375,11 @@ function printCommonLayout(
if (options?.splitCode) {
const splitCodePrefixLeft = options?.splitCodePrefixLeft ?? 191;
const splitCodePrefixWidth = options?.splitCodePrefixWidth ?? 150;
const splitCodeCenterTop = options?.splitCodeCenterTop ?? 190;
const splitCodeCenterLeft = options?.splitCodeCenterLeft ?? 274;
const splitCodeCenterWidth = options?.splitCodeCenterWidth ?? 230;
const splitCodeCenterHeight = options?.splitCodeCenterHeight ?? 38;
const splitCodeCenterFontSize = options?.splitCodeCenterFontSize ?? 28;
const splitCodeSuffixLeft = options?.splitCodeSuffixLeft ?? 474;
const splitCodeSuffixWidth = options?.splitCodeSuffixWidth ?? 141;
const splitCodeSuffixFontSize = options?.splitCodeSuffixFontSize ?? 15;
@ -346,15 +390,25 @@ function printCommonLayout(
lodop.SET_PRINT_STYLEA(0, "TextNeatRow", 1);
lodop.SET_PRINT_STYLEA(0, "WordWrap", 0);
lodop.SET_PRINT_STYLEA(0, "TextFit", 1);
lodop.ADD_PRINT_TEXT(186, splitCodeCenterLeft, splitCodeCenterWidth, 52, record.bar2);
setFont(lodop, 28, true);
lodop.ADD_PRINT_TEXT(
splitCodeCenterTop,
splitCodeCenterLeft,
splitCodeCenterWidth,
splitCodeCenterHeight,
record.bar2,
);
setFont(
lodop,
getAdaptiveCenterFontSize(record.bar2, splitCodeCenterFontSize),
true,
);
lodop.SET_PRINT_STYLEA(0, "Alignment", 2);
lodop.SET_PRINT_STYLEA(0, "TextNeatRow", 1);
lodop.SET_PRINT_STYLEA(0, "WordWrap", 0);
lodop.SET_PRINT_STYLEA(0, "TextFit", 1);
lodop.ADD_PRINT_TEXT(203, splitCodeSuffixLeft, splitCodeSuffixWidth, 25, record.bar3);
setFont(lodop, splitCodeSuffixFontSize);
lodop.SET_PRINT_STYLEA(0, "Alignment", 2);
lodop.SET_PRINT_STYLEA(0, "Alignment", 1);
lodop.SET_PRINT_STYLEA(0, "TextNeatRow", 1);
lodop.SET_PRINT_STYLEA(0, "WordWrap", 0);
lodop.SET_PRINT_STYLEA(0, "TextFit", 1);
@ -391,11 +445,15 @@ const BARCODE_PRINT_TEMPLATES: BarcodePrintTemplate[] = [
splitCode: true,
labelPrefix: "编码:",
productionBatchLeft: 458,
splitCodePrefixWidth: 124,
splitCodeCenterLeft: 302,
splitCodeCenterWidth: 190,
splitCodeSuffixLeft: 468,
splitCodeSuffixWidth: 132,
splitCodePrefixLeft: 191,
splitCodePrefixWidth: 142,
splitCodeCenterTop: 192,
splitCodeCenterLeft: 341,
splitCodeCenterWidth: 140,
splitCodeCenterHeight: 34,
splitCodeCenterFontSize: 24,
splitCodeSuffixLeft: 489,
splitCodeSuffixWidth: 116,
splitCodeSuffixFontSize: 13,
});
},
@ -536,9 +594,10 @@ export async function printBarcodeRow(
) {
const lodop = await getLodop();
const record = buildLodopRecord(row);
const defaultTemplateTitle = getDefaultBarcodePrintTemplateTitle(row);
const template = options.templateTitle
? BARCODE_PRINT_TEMPLATES.find((item) => item.title === options.templateTitle)
: chooseBarcodeTemplate(row);
: BARCODE_PRINT_TEMPLATES.find((item) => item.title === defaultTemplateTitle) ?? chooseBarcodeTemplate(row);
if (!template) {
throw new Error("请选择有效的条码打印模板。");