/** * TSC 标签指令构建(纯 TypeScript,无 require/import 外部 CJS 模块) * 使用 UTF-8 编码。对于纯英文/ASCII 内容,UTF-8 与 GB18030 字节一致,佳博打印机可正常打印。 * 若需中文等非 ASCII,可考虑运行时动态加载 tsc.js(仅 APP 端)。 */ /** 将字符串转为 UTF-8 字节数组(不依赖 TextEncoder) */ function stringToUtf8Bytes (str: string): number[] { const out: number[] = [] for (let i = 0; i < str.length; i++) { let c = str.charCodeAt(i) if (c < 0x80) { out.push(c) } else if (c < 0x800) { out.push(0xc0 | (c >> 6), 0x80 | (c & 0x3f)) } else if (c < 0xd800 || c >= 0xe000) { out.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f)) } else { i++ const c2 = str.charCodeAt(i) const u = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000 out.push( 0xf0 | (u >> 18), 0x80 | ((u >> 12) & 0x3f), 0x80 | ((u >> 6) & 0x3f), 0x80 | (u & 0x3f) ) } } return out } function addCommandBytes (out: number[], str: string) { const bytes = stringToUtf8Bytes(str) for (let i = 0; i < bytes.length; i++) out.push(bytes[i]) } function escapeTscString (s: string): string { return String(s).replace(/\\/g, '\\\\').replace(/"/g, '\\"') } /** * 构建标签打印指令字节数组(TSC) * 与官方 Demo createLabel 格式一致(SIZE 100x30, GAP 0) */ export function buildTscLabel (options: { productName: string labelId: string printQty?: number widthMm?: number heightMm?: number category?: string extraLine?: string }): number[] { const { productName, labelId, printQty = 1, widthMm = 100, heightMm = 30, category = '', extraLine = '', } = options const out: number[] = [] const add = (s: string) => addCommandBytes(out, s + '\r\n') let y = 10 add(`SIZE ${widthMm} mm,${heightMm} mm`) add('GAP 0 mm,0 mm') add('CLS') add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"${escapeTscString(productName)}"`) y += 35 if (category) { add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Category: ${escapeTscString(category)}"`) y += 35 } add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"ID: ${escapeTscString(labelId)}"`) y += 35 if (extraLine) { add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"${escapeTscString(extraLine)}"`) y += 35 } add(`QRCODE 50,${y},L,5,A,0,"${escapeTscString(labelId)}"`) add(`PRINT 1,${printQty}`) add('FEED 1') return out } /** * 食品营养成分标签测试打印(Nutrition Facts 格式) */ export function buildTestTscLabel (): number[] { const out: number[] = [] const add = (s: string) => addCommandBytes(out, s + '\r\n') let y = 10 add('SIZE 100 mm,70 mm') add('GAP 0 mm,0 mm') add('CLS') add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"NUTRITION FACTS"`) y += 28 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Grilled Chicken Breast"`) y += 28 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Serving Size 1 piece (100g)"`) y += 32 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Calories 165"`) y += 28 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Total Fat 4g"`) y += 24 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Saturated Fat 1g"`) y += 24 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Cholesterol 85mg"`) y += 24 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Sodium 75mg"`) y += 24 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Total Carb 0g"`) y += 24 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Protein 31g"`) y += 28 add(`TEXT 50,${y},"TSS24.BF2",0,1,1,"Exp: 01/17/25 ID: TEST-251227"`) y += 35 add(`QRCODE 50,${y},L,4,A,0,"TEST-251227-001"`) add('PRINT 1,1') add('FEED 1') return out }