taro-bluetooth-print 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +73 -195
- package/README.md +134 -386
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/types/config/PrinterConfigManager.d.ts +206 -0
- package/dist/types/config/index.d.ts +8 -0
- package/dist/types/core/BluetoothPrinter.d.ts +1 -1
- package/dist/types/core/EventEmitter.d.ts +6 -26
- package/dist/types/core/index.d.ts +6 -0
- package/dist/types/device/MultiPrinterManager.d.ts +164 -0
- package/dist/types/device/index.d.ts +2 -0
- package/dist/types/drivers/CpclDriver.d.ts +304 -0
- package/dist/types/drivers/GPrinterDriver.d.ts +63 -0
- package/dist/types/drivers/ZplDriver.d.ts +325 -0
- package/dist/types/drivers/index.d.ts +9 -0
- package/dist/types/encoding/gbk-lite.d.ts +8 -0
- package/dist/types/encoding/gbk-table.d.ts +8 -30
- package/dist/types/index.d.ts +12 -8
- package/dist/types/services/BatchPrintManager.d.ts +205 -0
- package/dist/types/services/ConnectionManager.d.ts +1 -1
- package/dist/types/services/PrintHistory.d.ts +142 -0
- package/dist/types/services/PrintJobManager.d.ts +28 -4
- package/dist/types/services/PrinterStatus.d.ts +97 -0
- package/dist/types/services/index.d.ts +11 -0
- package/package.json +25 -7
- package/src/adapters/AlipayAdapter.ts +1 -0
- package/src/adapters/BaiduAdapter.ts +1 -0
- package/src/adapters/BaseAdapter.ts +6 -8
- package/src/adapters/ByteDanceAdapter.ts +1 -0
- package/src/adapters/TaroAdapter.ts +1 -0
- package/src/adapters/WebBluetoothAdapter.ts +1 -1
- package/src/config/PrinterConfigManager.ts +519 -0
- package/src/config/index.ts +15 -0
- package/src/core/BluetoothPrinter.ts +15 -15
- package/src/core/EventEmitter.ts +15 -15
- package/src/core/index.ts +7 -0
- package/src/device/MultiPrinterManager.ts +470 -0
- package/src/device/index.ts +8 -0
- package/src/drivers/CpclDriver.ts +549 -0
- package/src/drivers/GPrinterDriver.ts +115 -0
- package/src/drivers/TsplDriver.ts +9 -21
- package/src/drivers/ZplDriver.ts +543 -0
- package/src/drivers/index.ts +37 -0
- package/src/encoding/gbk-lite.ts +113 -0
- package/src/encoding/gbk-table.ts +80 -58
- package/src/index.ts +40 -35
- package/src/plugins/PluginManager.ts +3 -1
- package/src/plugins/builtin/LoggingPlugin.ts +4 -2
- package/src/plugins/builtin/RetryPlugin.ts +8 -14
- package/src/services/BatchPrintManager.ts +500 -0
- package/src/services/ConnectionManager.ts +25 -22
- package/src/services/PrintHistory.ts +336 -0
- package/src/services/PrintJobManager.ts +69 -9
- package/src/services/PrinterStatus.ts +267 -0
- package/src/services/index.ts +22 -0
- package/src/template/TemplateEngine.ts +4 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TSPL Driver
|
|
3
3
|
* TSC Printer Language driver for label/barcode printers
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* TSPL is commonly used in thermal transfer label printers (TSC, Zebra, etc.)
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -112,11 +112,11 @@ export interface LineOptions {
|
|
|
112
112
|
|
|
113
113
|
/**
|
|
114
114
|
* TSPL Driver for label printers
|
|
115
|
-
*
|
|
115
|
+
*
|
|
116
116
|
* @example
|
|
117
117
|
* ```typescript
|
|
118
118
|
* const tspl = new TsplDriver();
|
|
119
|
-
*
|
|
119
|
+
*
|
|
120
120
|
* const commands = tspl
|
|
121
121
|
* .size(60, 40)
|
|
122
122
|
* .gap(3)
|
|
@@ -216,14 +216,7 @@ export class TsplDriver {
|
|
|
216
216
|
* @param options - Text options
|
|
217
217
|
*/
|
|
218
218
|
text(content: string, options: TextOptions): this {
|
|
219
|
-
const {
|
|
220
|
-
x,
|
|
221
|
-
y,
|
|
222
|
-
font = 2,
|
|
223
|
-
rotation = 0,
|
|
224
|
-
xMultiplier = 1,
|
|
225
|
-
yMultiplier = 1,
|
|
226
|
-
} = options;
|
|
219
|
+
const { x, y, font = 2, rotation = 0, xMultiplier = 1, yMultiplier = 1 } = options;
|
|
227
220
|
|
|
228
221
|
// TEXT x, y, "font", rotation, x-mul, y-mul, "content"
|
|
229
222
|
this.commands.push(
|
|
@@ -269,14 +262,7 @@ export class TsplDriver {
|
|
|
269
262
|
* @param options - QR code options
|
|
270
263
|
*/
|
|
271
264
|
qrcode(content: string, options: QRCodeOptions): this {
|
|
272
|
-
const {
|
|
273
|
-
x,
|
|
274
|
-
y,
|
|
275
|
-
eccLevel = 'M',
|
|
276
|
-
cellWidth = 6,
|
|
277
|
-
mode = 'A',
|
|
278
|
-
rotation = 0,
|
|
279
|
-
} = options;
|
|
265
|
+
const { x, y, eccLevel = 'M', cellWidth = 6, mode = 'A', rotation = 0 } = options;
|
|
280
266
|
|
|
281
267
|
// QRCODE x, y, ECC level, cell width, mode, rotation, "content"
|
|
282
268
|
this.commands.push(
|
|
@@ -301,7 +287,7 @@ export class TsplDriver {
|
|
|
301
287
|
*/
|
|
302
288
|
line(options: LineOptions): this {
|
|
303
289
|
const { x1, y1, x2, y2, thickness = 2 } = options;
|
|
304
|
-
|
|
290
|
+
|
|
305
291
|
if (x1 === x2 || y1 === y2) {
|
|
306
292
|
// Horizontal or vertical line - use BAR command
|
|
307
293
|
const width = Math.abs(x2 - x1) || thickness;
|
|
@@ -309,7 +295,9 @@ export class TsplDriver {
|
|
|
309
295
|
this.commands.push(`BAR ${Math.min(x1, x2)},${Math.min(y1, y2)},${width},${height}`);
|
|
310
296
|
} else {
|
|
311
297
|
// Diagonal line - use DIAGONAL command if supported
|
|
312
|
-
this.commands.push(
|
|
298
|
+
this.commands.push(
|
|
299
|
+
`DIAGONAL ${x1},${y1},${thickness},${Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)},${(Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI}`
|
|
300
|
+
);
|
|
313
301
|
}
|
|
314
302
|
return this;
|
|
315
303
|
}
|
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZPL Driver
|
|
3
|
+
* Zebra Printer Language driver for Zebra label printers
|
|
4
|
+
*
|
|
5
|
+
* ZPL is the industry standard for industrial label printing
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Logger } from '@/utils/logger';
|
|
9
|
+
import { Encoding } from '@/utils/encoding';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* ZPL Label size configuration
|
|
13
|
+
*/
|
|
14
|
+
export interface ZplLabelSize {
|
|
15
|
+
/** Label width in dots */
|
|
16
|
+
width: number;
|
|
17
|
+
/** Label height in dots */
|
|
18
|
+
height: number;
|
|
19
|
+
/** Label gap in dots (default: 0) */
|
|
20
|
+
gap?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Text format options
|
|
25
|
+
*/
|
|
26
|
+
export interface ZplTextOptions {
|
|
27
|
+
/** X position in dots */
|
|
28
|
+
x: number;
|
|
29
|
+
/** Y position in dots */
|
|
30
|
+
y: number;
|
|
31
|
+
/** Font name (default: 0 for built-in) */
|
|
32
|
+
font?: string;
|
|
33
|
+
/** Font rotation: N=0, R=90, I=270, B=180 (default: N) */
|
|
34
|
+
rotation?: 'N' | 'R' | 'I' | 'B';
|
|
35
|
+
/** Horizontal magnification (1-10, default: 1) */
|
|
36
|
+
xMultiplier?: number;
|
|
37
|
+
/** Vertical magnification (1-10, default: 1) */
|
|
38
|
+
yMultiplier?: number;
|
|
39
|
+
/** Field orientation: N=normal, R=rotated, I=inverted, B=bottom-up */
|
|
40
|
+
orientation?: 'N' | 'R' | 'I' | 'B';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Barcode options
|
|
45
|
+
*/
|
|
46
|
+
export interface ZplBarcodeOptions {
|
|
47
|
+
/** X position in dots */
|
|
48
|
+
x: number;
|
|
49
|
+
/** Y position in dots */
|
|
50
|
+
y: number;
|
|
51
|
+
/** Barcode type: 128, 39, 93, EAN13, EAN8, UPCE, CODE51, etc. */
|
|
52
|
+
type: '128' | '39' | '93' | 'EAN13' | 'EAN8' | 'UPCA' | 'UPCE' | 'CODE51' | 'MSI' | 'PLESSEY';
|
|
53
|
+
/** Barcode height in dots (default: 50) */
|
|
54
|
+
height?: number;
|
|
55
|
+
/** Show human-readable text (default: Y) */
|
|
56
|
+
showText?: 'Y' | 'N';
|
|
57
|
+
/** Check digit: Y=validate, N=no check (default: Y) */
|
|
58
|
+
checkDigit?: 'Y' | 'N';
|
|
59
|
+
/** Interpretation line: Y=print, N=omit (default: Y) */
|
|
60
|
+
interpretLine?: 'Y' | 'N';
|
|
61
|
+
/** Interpretation line above: Y=above, N=below (default: N) */
|
|
62
|
+
interpretLineAbove?: 'Y' | 'N';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* QR Code options
|
|
67
|
+
*/
|
|
68
|
+
export interface ZplQRCodeOptions {
|
|
69
|
+
/** X position in dots */
|
|
70
|
+
x: number;
|
|
71
|
+
/** Y position in dots */
|
|
72
|
+
y: number;
|
|
73
|
+
/** Model: 2 (default) or 1 */
|
|
74
|
+
model?: 1 | 2;
|
|
75
|
+
/** Magnification factor 1-10 (default: 4) */
|
|
76
|
+
magnification?: number;
|
|
77
|
+
/** Error correction level: L(~7%), M(~15%), Q(~25%), H(~30%) */
|
|
78
|
+
errorCorrection?: 'L' | 'M' | 'Q' | 'H';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Box/Rectangle options
|
|
83
|
+
*/
|
|
84
|
+
export interface ZplBoxOptions {
|
|
85
|
+
/** X position in dots */
|
|
86
|
+
x: number;
|
|
87
|
+
/** Y position in dots */
|
|
88
|
+
y: number;
|
|
89
|
+
/** Width in dots */
|
|
90
|
+
width: number;
|
|
91
|
+
/** Height in dots */
|
|
92
|
+
height: number;
|
|
93
|
+
/** Border thickness (default: 2) */
|
|
94
|
+
borderThickness?: number;
|
|
95
|
+
/** Corner rounding (0-10, default: 0) */
|
|
96
|
+
cornerRounding?: number;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* ZPL Driver for Zebra label printers
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const zpl = new ZplDriver();
|
|
105
|
+
*
|
|
106
|
+
* const commands = zpl
|
|
107
|
+
* .startFormat()
|
|
108
|
+
* .labelHome(10, 10)
|
|
109
|
+
* .text('Product Name', { x: 50, y: 50 })
|
|
110
|
+
* .barcode('1234567890', { x: 50, y: 150, type: '128' })
|
|
111
|
+
* .qrcode('https://example.com', { x: 300, y: 50 })
|
|
112
|
+
* .print()
|
|
113
|
+
* .getCommands();
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export class ZplDriver {
|
|
117
|
+
private commands: string[] = [];
|
|
118
|
+
private readonly logger = Logger.scope('ZplDriver');
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Initialize ZPL driver with default settings
|
|
122
|
+
*/
|
|
123
|
+
constructor() {
|
|
124
|
+
// Start with format start
|
|
125
|
+
this.startFormat();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Start label format (^XA)
|
|
130
|
+
*/
|
|
131
|
+
startFormat(): this {
|
|
132
|
+
this.commands.push('^XA');
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* End label format (^XZ)
|
|
138
|
+
*/
|
|
139
|
+
endFormat(): this {
|
|
140
|
+
this.commands.push('^XZ');
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Set label home position
|
|
146
|
+
* @param x - X position in dots
|
|
147
|
+
* @param y - Y position in dots
|
|
148
|
+
*/
|
|
149
|
+
labelHome(x: number, y: number): this {
|
|
150
|
+
this.commands.push(`^FO${x},${y}`);
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Set field data (^FD)
|
|
156
|
+
* @param content - Field content
|
|
157
|
+
*/
|
|
158
|
+
fieldData(content: string): this {
|
|
159
|
+
this.commands.push(`^FD${this.escapeField(content)}`);
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Set field origin
|
|
165
|
+
* @param x - X position in dots
|
|
166
|
+
* @param y - Y position in dots
|
|
167
|
+
*/
|
|
168
|
+
fieldOrigin(x: number, y: number): this {
|
|
169
|
+
this.commands.push(`^FO${x},${y}`);
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Set print width
|
|
175
|
+
* @param width - Width in dots
|
|
176
|
+
*/
|
|
177
|
+
printWidth(width: number): this {
|
|
178
|
+
this.commands.push(`^PW${width}`);
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Set label length
|
|
184
|
+
* @param length - Length in dots
|
|
185
|
+
*/
|
|
186
|
+
labelLength(length: number): this {
|
|
187
|
+
this.commands.push(`^LL${length}`);
|
|
188
|
+
return this;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Set label gap
|
|
193
|
+
* @param gap - Gap in dots
|
|
194
|
+
*/
|
|
195
|
+
labelGap(gap: number): this {
|
|
196
|
+
this.commands.push(`^LS${gap}`);
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Set print quantity
|
|
202
|
+
* @param quantity - Number of labels
|
|
203
|
+
*/
|
|
204
|
+
quantity(quantity: number): this {
|
|
205
|
+
this.commands.push(`^PQ${quantity},0,1,Y`);
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Add text to label
|
|
211
|
+
* @param content - Text content
|
|
212
|
+
* @param options - Text options
|
|
213
|
+
*/
|
|
214
|
+
text(content: string, options?: ZplTextOptions): this {
|
|
215
|
+
if (options) {
|
|
216
|
+
const {
|
|
217
|
+
x = 0,
|
|
218
|
+
y = 0,
|
|
219
|
+
font = '0',
|
|
220
|
+
rotation = 'N',
|
|
221
|
+
xMultiplier = 1,
|
|
222
|
+
yMultiplier = 1,
|
|
223
|
+
} = options;
|
|
224
|
+
|
|
225
|
+
this.commands.push(
|
|
226
|
+
`^FO${x},${y}^A${font}${rotation},${yMultiplier},${xMultiplier}^FD${this.escapeField(content)}^FS`
|
|
227
|
+
);
|
|
228
|
+
} else {
|
|
229
|
+
// Simple text at current position
|
|
230
|
+
this.commands.push(`^FD${this.escapeField(content)}^FS`);
|
|
231
|
+
}
|
|
232
|
+
return this;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Add text with explicit field origin
|
|
237
|
+
* @param content - Text content
|
|
238
|
+
* @param x - X position
|
|
239
|
+
* @param y - Y position
|
|
240
|
+
* @param font - Font name (default: 0)
|
|
241
|
+
* @param rotation - Rotation
|
|
242
|
+
*/
|
|
243
|
+
textAt(
|
|
244
|
+
content: string,
|
|
245
|
+
x: number,
|
|
246
|
+
y: number,
|
|
247
|
+
font = '0',
|
|
248
|
+
rotation: 'N' | 'R' | 'I' | 'B' = 'N'
|
|
249
|
+
): this {
|
|
250
|
+
this.commands.push(`^FO${x},${y}^A${font}${rotation}^FD${this.escapeField(content)}^FS`);
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Use built-in font
|
|
256
|
+
* @param content - Text content
|
|
257
|
+
* @param x - X position
|
|
258
|
+
* @param y - Y position
|
|
259
|
+
* @param height - Character height (40-400)
|
|
260
|
+
* @param width - Character width (30-300)
|
|
261
|
+
*/
|
|
262
|
+
font(content: string, x: number, y: number, height = 30, width = 20): this {
|
|
263
|
+
this.commands.push(`^FO${x},${y}^A${height},${width}^FD${this.escapeField(content)}^FS`);
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Add scalable font
|
|
269
|
+
* @param content - Text content
|
|
270
|
+
* @param x - X position
|
|
271
|
+
* @param y - Y position
|
|
272
|
+
* @param fontName - Font name (e.g., "0" for built-in, or loaded font name)
|
|
273
|
+
* @param fontHeight - Height multiplier
|
|
274
|
+
* @param fontWidth - Width multiplier
|
|
275
|
+
*/
|
|
276
|
+
scalableText(
|
|
277
|
+
content: string,
|
|
278
|
+
x: number,
|
|
279
|
+
y: number,
|
|
280
|
+
fontName = '0',
|
|
281
|
+
fontHeight = 30,
|
|
282
|
+
fontWidth = 20
|
|
283
|
+
): this {
|
|
284
|
+
this.commands.push(
|
|
285
|
+
`^FO${x},${y}^A${fontName}N,${fontHeight},${fontWidth}^FD${this.escapeField(content)}^FS`
|
|
286
|
+
);
|
|
287
|
+
return this;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Add barcode
|
|
292
|
+
* @param content - Barcode content
|
|
293
|
+
* @param options - Barcode options
|
|
294
|
+
*/
|
|
295
|
+
barcode(content: string, options: ZplBarcodeOptions): this {
|
|
296
|
+
const {
|
|
297
|
+
x = 0,
|
|
298
|
+
y = 0,
|
|
299
|
+
type = '128',
|
|
300
|
+
height = 50,
|
|
301
|
+
showText = 'Y',
|
|
302
|
+
checkDigit = 'N',
|
|
303
|
+
interpretLine = 'Y',
|
|
304
|
+
interpretLineAbove = 'N',
|
|
305
|
+
} = options;
|
|
306
|
+
|
|
307
|
+
this.commands.push(
|
|
308
|
+
`^FO${x},${y}^B${type}${showText},${height},${interpretLine},${interpretLineAbove},${checkDigit}^FD${this.escapeField(content)}^FS`
|
|
309
|
+
);
|
|
310
|
+
return this;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Add Code 128 barcode
|
|
315
|
+
* @param content - Barcode content
|
|
316
|
+
* @param x - X position
|
|
317
|
+
* @param y - Y position
|
|
318
|
+
* @param height - Barcode height
|
|
319
|
+
*/
|
|
320
|
+
code128(content: string, x = 0, y = 0, height = 50): this {
|
|
321
|
+
return this.barcode(content, { x, y, type: '128', height });
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Add Code 39 barcode
|
|
326
|
+
* @param content - Barcode content
|
|
327
|
+
* @param x - X position
|
|
328
|
+
* @param y - Y position
|
|
329
|
+
* @param height - Barcode height
|
|
330
|
+
*/
|
|
331
|
+
code39(content: string, x = 0, y = 0, height = 50): this {
|
|
332
|
+
return this.barcode(content, { x, y, type: '39', height, checkDigit: 'Y' });
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Add EAN-13 barcode
|
|
337
|
+
* @param content - Barcode content (12 or 13 digits)
|
|
338
|
+
* @param x - X position
|
|
339
|
+
* @param y - Y position
|
|
340
|
+
* @param height - Barcode height
|
|
341
|
+
*/
|
|
342
|
+
ean13(content: string, x = 0, y = 0, height = 50): this {
|
|
343
|
+
return this.barcode(content, { x, y, type: 'EAN13', height });
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Add QR code
|
|
348
|
+
* @param content - QR code content
|
|
349
|
+
* @param options - QR code options
|
|
350
|
+
*/
|
|
351
|
+
qrcode(content: string, options?: ZplQRCodeOptions): this {
|
|
352
|
+
const { x = 0, y = 0, model = 2, magnification = 4, errorCorrection = 'M' } = options || {};
|
|
353
|
+
|
|
354
|
+
// Model 2 is the default
|
|
355
|
+
// ZPL QR code uses fixed model 2 for better compatibility
|
|
356
|
+
const qrModel = model === 1 ? '1' : '2';
|
|
357
|
+
this.commands.push(
|
|
358
|
+
`^FO${x},${y}^BQN,${qrModel},${magnification}^FD${errorCorrection},${this.escapeField(content)}^FS`
|
|
359
|
+
);
|
|
360
|
+
return this;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Add rectangle/border
|
|
365
|
+
* @param options - Box options
|
|
366
|
+
*/
|
|
367
|
+
box(options: ZplBoxOptions): this {
|
|
368
|
+
const { x = 0, y = 0, width, height, borderThickness = 2, cornerRounding = 0 } = options;
|
|
369
|
+
|
|
370
|
+
this.commands.push(`^FO${x},${y}^GB${width},${height},${borderThickness},${cornerRounding}^FS`);
|
|
371
|
+
return this;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Add line
|
|
376
|
+
* @param x1 - Start X
|
|
377
|
+
* @param y1 - Start Y
|
|
378
|
+
* @param x2 - End X
|
|
379
|
+
* @param y2 - End Y
|
|
380
|
+
* @param thickness - Line thickness
|
|
381
|
+
*/
|
|
382
|
+
line(x1: number, y1: number, x2: number, y2: number, thickness = 2): this {
|
|
383
|
+
const width = Math.abs(x2 - x1) || thickness;
|
|
384
|
+
const height = Math.abs(y2 - y1) || thickness;
|
|
385
|
+
const x = Math.min(x1, x2);
|
|
386
|
+
const y = Math.min(y1, y2);
|
|
387
|
+
|
|
388
|
+
this.commands.push(`^FO${x},${y}^GB${width},${height},${thickness}^FS`);
|
|
389
|
+
return this;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Add circle
|
|
394
|
+
* @param x - Center X
|
|
395
|
+
* @param y - Center Y
|
|
396
|
+
* @param diameter - Diameter in dots
|
|
397
|
+
* @param borderThickness - Border thickness
|
|
398
|
+
*/
|
|
399
|
+
circle(x: number, y: number, diameter: number, borderThickness = 2): this {
|
|
400
|
+
this.commands.push(`^FO${x},${y}^GC${diameter},${borderThickness}^FS`);
|
|
401
|
+
return this;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Add diagonal line
|
|
406
|
+
* @param x - Start X
|
|
407
|
+
* @param y - Start Y
|
|
408
|
+
* @param width - Width
|
|
409
|
+
* @param height - Height
|
|
410
|
+
* @param thickness - Line thickness
|
|
411
|
+
*/
|
|
412
|
+
diagonal(x: number, y: number, width: number, height: number, thickness = 2): this {
|
|
413
|
+
this.commands.push(`^FO${x},${y}^GD${width},${height},${thickness}^FS`);
|
|
414
|
+
return this;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Add ellipse
|
|
419
|
+
* @param x - Center X
|
|
420
|
+
* @param y - Center Y
|
|
421
|
+
* @param width - Width
|
|
422
|
+
* @param height - Height
|
|
423
|
+
* @param borderThickness - Border thickness
|
|
424
|
+
*/
|
|
425
|
+
ellipse(x: number, y: number, width: number, height: number, borderThickness = 2): this {
|
|
426
|
+
this.commands.push(`^FO${x},${y}^GE${width},${height},${borderThickness}^FS`);
|
|
427
|
+
return this;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Add image from raw bitmap
|
|
432
|
+
* Note: For best results, use pre-processed images. This is a placeholder for future implementation.
|
|
433
|
+
* @param _x - X position (placeholder)
|
|
434
|
+
* @param _y - Y position (placeholder)
|
|
435
|
+
* @param _width - Image width (placeholder)
|
|
436
|
+
* @param _height - Image height (placeholder)
|
|
437
|
+
* @param _bitmap - Binary bitmap data (placeholder)
|
|
438
|
+
*/
|
|
439
|
+
image(_x: number, _y: number, _width: number, _height: number, _bitmap: Uint8Array): this {
|
|
440
|
+
// TODO: Implement proper ZPL image encoding using ^GFA or ^XG commands
|
|
441
|
+
// For now, this is a placeholder
|
|
442
|
+
this.logger.debug('ZPL image encoding not fully implemented');
|
|
443
|
+
return this;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Set darkness/print density
|
|
448
|
+
* @param value - Darkness value (0-30, default: 15)
|
|
449
|
+
*/
|
|
450
|
+
setDarkness(value = 15): this {
|
|
451
|
+
this.commands.push(`~SD${Math.min(30, Math.max(0, Math.floor(value)))}`);
|
|
452
|
+
return this;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Set print speed
|
|
457
|
+
* @param speed - Speed: 1=slowest, 2-5=medium, 6-13=fast, 14=max
|
|
458
|
+
*/
|
|
459
|
+
setSpeed(speed: number): this {
|
|
460
|
+
const safeSpeed = Math.min(14, Math.max(1, Math.floor(speed)));
|
|
461
|
+
this.commands.push(`^PR${safeSpeed}`);
|
|
462
|
+
return this;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Print configuration label (useful for testing)
|
|
467
|
+
*/
|
|
468
|
+
printConfigLabel(): this {
|
|
469
|
+
this.commands.push('~WC');
|
|
470
|
+
return this;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Calibrate sensors
|
|
475
|
+
*/
|
|
476
|
+
calibrate(): this {
|
|
477
|
+
this.commands.push('~JC');
|
|
478
|
+
return this;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Reset printer
|
|
483
|
+
*/
|
|
484
|
+
reset(): this {
|
|
485
|
+
this.commands.push('^JUS');
|
|
486
|
+
return this;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Get all commands as string
|
|
491
|
+
*/
|
|
492
|
+
getCommands(): string {
|
|
493
|
+
// Ensure format is properly closed
|
|
494
|
+
if (!this.commands[0]?.startsWith('^XA')) {
|
|
495
|
+
this.startFormat();
|
|
496
|
+
}
|
|
497
|
+
if (!this.commands[this.commands.length - 1]?.startsWith('^XZ')) {
|
|
498
|
+
this.endFormat();
|
|
499
|
+
}
|
|
500
|
+
return this.commands.join('\n');
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Get commands as buffer for sending to printer
|
|
505
|
+
*/
|
|
506
|
+
getBuffer(): Uint8Array {
|
|
507
|
+
const commandString = this.getCommands();
|
|
508
|
+
this.logger.debug(`ZPL commands:\n${commandString}`);
|
|
509
|
+
return Encoding.encode(commandString, 'UTF-8');
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Get raw command list
|
|
514
|
+
*/
|
|
515
|
+
getCommandList(): string[] {
|
|
516
|
+
return [...this.commands];
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Clear all commands
|
|
521
|
+
*/
|
|
522
|
+
resetCommands(): this {
|
|
523
|
+
this.commands = [];
|
|
524
|
+
this.startFormat();
|
|
525
|
+
return this;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Print label (end format)
|
|
530
|
+
*/
|
|
531
|
+
print(quantity = 1): this {
|
|
532
|
+
this.quantity(quantity);
|
|
533
|
+
this.endFormat();
|
|
534
|
+
return this;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Escape special characters in field data
|
|
539
|
+
*/
|
|
540
|
+
private escapeField(str: string): string {
|
|
541
|
+
return str.replace(/\\/g, '\\\\').replace(/\^/g, '\\^').replace(/~/g, '\\~');
|
|
542
|
+
}
|
|
543
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Printer Drivers Module
|
|
3
|
+
* 打印机驱动模块 - 支持多种打印机协议
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { EscPos, type EscPosOptions } from './EscPos';
|
|
7
|
+
|
|
8
|
+
export { GPrinterDriver, type GPrinterOptions } from './GPrinterDriver';
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
TsplDriver,
|
|
12
|
+
type LabelSize,
|
|
13
|
+
type TextOptions,
|
|
14
|
+
type BarcodeOptions,
|
|
15
|
+
type QRCodeOptions,
|
|
16
|
+
type BoxOptions,
|
|
17
|
+
type LineOptions,
|
|
18
|
+
} from './TsplDriver';
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
ZplDriver,
|
|
22
|
+
type ZplLabelSize,
|
|
23
|
+
type ZplTextOptions,
|
|
24
|
+
type ZplBarcodeOptions,
|
|
25
|
+
type ZplQRCodeOptions,
|
|
26
|
+
type ZplBoxOptions,
|
|
27
|
+
} from './ZplDriver';
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
CpclDriver,
|
|
31
|
+
type CPCLPageSize,
|
|
32
|
+
type CpclTextOptions,
|
|
33
|
+
type CpclBarcodeOptions,
|
|
34
|
+
type CpclQRCodeOptions,
|
|
35
|
+
type CpclLineOptions,
|
|
36
|
+
type CpclBoxOptions,
|
|
37
|
+
} from './CpclDriver';
|