修复200mm打印

This commit is contained in:
2026-07-23 20:10:49 +08:00
parent ed099e0f4f
commit 9e94385dfc
2 changed files with 90 additions and 39 deletions
+88 -37
View File
@@ -46,6 +46,8 @@ const PAPER_PRESETS = {
fontSize: 28,
lineHeight: 45,
cpcl: {
pageWidth: 800, // 100mm @200dpi = 800 点
gapSense: true, // 自动检测标签间隙,避免固定 GAP 值不匹配
fields: [
{ x: 192, y: 100 }, // 名称
{ x: 192, y: 150 }, // 类别
@@ -78,23 +80,26 @@ const PAPER_PRESETS = {
fontSize: 36,
lineHeight: 60,
cpcl: {
pageWidth: 1200, // PAGE-WIDTH150mm @200dpi = 1200 点),防止右半边被截断
gapSense: true, // 自动检测标签间隙,避免固定 GAP 值不匹配
// 字体大小沿用 200x200mag/bold),位置用 150 原坐标,整体下移 3mm24 点 @200dpi
fields: [
{ x: 288, y: 150 }, // 名称
{ x: 288, y: 225 }, // 类别
{ x: 288, y: 300 }, // 代码
{ x: 720, y: 300 }, // 形态
{ x: 288, y: 375 }, // 主要成分
{ x: 288, y: 525 }, // 有害成分
{ x: 288, y: 672 }, // 注意
{ x: 324, y: 804 }, // 识别码
{ x: 384, y: 876 }, // 单位
{ x: 432, y: 948 }, // 联系
{ x: 288, y: 1020 }, // 日期
{ x: 720, y: 1020 }, // 重量
{ x: 225, y: 1092 }, // 备注
{ x: 720, y: 525 } // 标识
{ x: 288, y: 174, mag: [2, 2], bold: 0.0, font: 1 }, // 名称(150:150+24
{ x: 288, y: 249, mag: [2, 2], bold: 0.0, font: 1 }, // 类别(150:225+24
{ x: 288, y: 324, mag: [2, 2], bold: 0.5, font: 0 }, // 代码(150:300+24,加粗)
{ x: 720, y: 324, mag: [2, 2], bold: 0.0, font: 1 }, // 形态(150:300+24
{ x: 288, y: 399, mag: [2, 2], bold: 0.5, font: 0 }, // 主要成分(150:375+24,加粗)
{ x: 288, y: 549, mag: [2, 2], bold: 0.5, font: 0 }, // 有害成分(150:525+24,加粗)
{ x: 288, y: 696, mag: [2, 2], bold: 0.0, font: 1 }, // 注意(150:672+24
{ x: 308, y: 836, mag: [2, 2], bold: 0.0, font: 1 }, // 识别码(注意以下:x-16 左2mm, y+8 下1mm
{ x: 368, y: 908, mag: [2, 2], bold: 0.0, font: 1 }, // 单位(注意以下)
{ x: 416, y: 980, mag: [2, 2], bold: 0.0, font: 1 }, // 联系(注意以下)
{ x: 272, y: 1052, mag: [2, 2], bold: 0.5, font: 0 }, // 日期(注意以下,加粗)
{ x: 704, y: 1052, mag: [2, 2], bold: 0.0, font: 1 }, // 重量(注意以下)
{ x: 209, y: 1124, mag: [2, 2], bold: 0.0, font: 1 }, // 备注(注意以下)
{ x: 720, y: 549, mag: [4, 4], bold: 0.0, font: 1 } // 标识(150:525+244 倍放大)
],
qrCode: { x: 936, y: 876, size: 4 }
qrCode: { x: 936, y: 900, size: 4 } // 位置用 150 原坐标(876+24),size 4 不越界
},
tspl: {
startX: 30,
@@ -512,7 +517,7 @@ class BluetoothPrinterService {
console.log(`[打印] 共 ${lines.length} 行, ${dataSize} bytes`);
// 行数少时一次发送(更快),行数多时按行发送(防止指令被拆包)
const LINE_THRESHOLD = 22;
const LINE_THRESHOLD = 10;
if (lines.length <= LINE_THRESHOLD) {
console.log('[打印] 行数较少,一次发送');
await this._writeData(buffer);
@@ -533,25 +538,67 @@ class BluetoothPrinterService {
const lines = content.split('\n');
console.log(`[打印] 按行发送,共 ${lines.length}`);
for (let i = 0; i < lines.length; i++) {
const line = lines[i] + '\n';
const buffer = this._stringToBuffer(line);
let i = 0;
while (i < lines.length) {
const line = lines[i];
const trimmed = line.trim();
try {
await this._writeData(buffer);
// 每行之间延迟 80ms,给打印机处理时间
if (i < lines.length - 1) {
await this._delay(80);
// CPCL QR 码块:从 B QR / BARCODE QR 到 ENDQR,必须作为整体一次发送
// 否则行间 80ms 延迟会导致打印机无法将数据与 QR 命令关联,二维码无法生成
const isQRStart = /^(B\s+QR|BARCODE\s+QR)\b/i.test(trimmed);
if (isQRStart) {
// 收集完整 QR 块(含结束标记 ENDQR)
const qrBlockLines = [];
while (i < lines.length) {
qrBlockLines.push(lines[i]);
if (lines[i].trim() === 'ENDQR') {
i++;
break;
}
i++;
}
} catch (err) {
const isLastLine = i === lines.length - 1;
if (isLastLine) {
// 尾行容错:与 _writeData 保持一致,最后一行写入失败不抛异常
console.warn(`[打印] ${i + 1} 行(最后一行)发送失败,视为尾包处理:`, err);
return;
// 整体发送 QR 块,中间不加延迟
const blockStr = qrBlockLines.join('\n') + '\n';
const blockBuffer = this._stringToBuffer(blockStr);
console.log(`[打印] 发送 QR 块(${qrBlockLines.length} 行, ${blockBuffer.byteLength}B`);
try {
await this._writeData(blockBuffer);
} catch (err) {
const isLastBlock = i >= lines.length;
if (isLastBlock) {
// 尾块容错:与 _writeData 保持一致,最后一个块写入失败不抛异常
console.warn(`[打印] QR 块(最后一个块)发送失败,视为尾包处理:`, err);
return;
}
console.error(`[打印] QR 块发送失败:`, err);
throw err;
}
console.error(`[打印] 第 ${i + 1} 行发送失败:`, err);
throw err;
} else {
// 普通行,逐行发送
const lineStr = line + '\n';
const buffer = this._stringToBuffer(lineStr);
try {
await this._writeData(buffer);
} catch (err) {
const isLastLine = i === lines.length - 1;
if (isLastLine) {
// 尾行容错:与 _writeData 保持一致,最后一行写入失败不抛异常
console.warn(`[打印] 第 ${i + 1} 行(最后一行)发送失败,视为尾包处理:`, err);
return;
}
console.error(`[打印] 第 ${i + 1} 行发送失败:`, err);
throw err;
}
i++;
}
// 行间/块间延迟 80ms,给打印机处理时间
if (i < lines.length) {
await this._delay(80);
}
}
@@ -665,11 +712,15 @@ class BluetoothPrinterService {
fieldOrder.forEach((field, index) => {
if (data[field]) {
const f = conf[index] || {};
const mag = f.mag || [1, 1]; // 默认 1 倍(兼容 100x100
const bold = (f.bold != null) ? f.bold : 0.0;
const font = f.font || 1;
commands.push(`SETMAG ${mag[0]} ${mag[1]}`);
commands.push(`SETBOLD ${bold}`);
// 仅当字段显式配置了 mag / bold 时才输出,否则走打印机默认值
// (100x100 标签字段无这些配置,避免输出多余的 SETMAG/SETBOLD
if (f.mag) {
commands.push(`SETMAG ${f.mag[0]} ${f.mag[1]}`);
}
if (f.bold != null) {
commands.push(`SETBOLD ${f.bold}`);
}
const font = (f.font != null) ? f.font : 1;
commands.push(`T ${font} 0 ${f.x} ${f.y} ${data[field]}`);
}
});