uview-ultra 4.5.46 → 4.5.48
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/README.md +46 -0
- package/changelog.md +14 -0
- package/components/up-barcode/up-barcode.uvue +627 -626
- package/components/up-barcode/up-barcode.vue +2 -1
- package/components/up-navbar/navbar.js +2 -1
- package/components/up-navbar/navbar.uts +2 -1
- package/components/up-navbar/props.js +5 -0
- package/components/up-navbar/props.uts +5 -0
- package/components/up-navbar/up-navbar.uvue +21 -0
- package/components/up-navbar/up-navbar.vue +17 -1
- package/components/up-novel-reader/up-novel-reader.vue +1 -1
- package/components/up-tabs-pro/up-tabs-pro.vue +2 -3
- package/package.json +1 -1
- package/types/comps/navbar.d.ts +5 -0
- package/types/index.d.ts +8 -0
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
</view>
|
|
32
32
|
</template>
|
|
33
33
|
|
|
34
|
-
<script setup lang="uts">
|
|
35
|
-
import { computed, getCurrentInstance, nextTick, onMounted, ref, watch } from 'vue'
|
|
36
|
-
|
|
37
|
-
function stringValue(value: any | null): string {
|
|
38
|
-
return value == null ? '' : value.toString()
|
|
39
|
-
}
|
|
34
|
+
<script setup lang="uts">
|
|
35
|
+
import { computed, getCurrentInstance, nextTick, onMounted, ref, watch } from 'vue'
|
|
36
|
+
|
|
37
|
+
function stringValue(value: any | null): string {
|
|
38
|
+
return value == null ? '' : value.toString()
|
|
39
|
+
}
|
|
40
40
|
|
|
41
41
|
function normalizeNumber(value: any | null, defaultValue: number): number {
|
|
42
42
|
if (typeof value === 'number') {
|
|
@@ -155,626 +155,627 @@ function code39Map(): UTSJSONObject {
|
|
|
155
155
|
} as UTSJSONObject
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
defineOptions({
|
|
159
|
-
styleIsolation: 'app-and-page',
|
|
160
|
-
name: 'up-barcode'
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
const props = defineProps({
|
|
164
|
-
value: {
|
|
165
|
-
type: [String, Number],
|
|
166
|
-
default: ''
|
|
167
|
-
},
|
|
168
|
-
format: {
|
|
169
|
-
type: String,
|
|
170
|
-
default: 'auto'
|
|
171
|
-
},
|
|
172
|
-
width: {
|
|
173
|
-
type: Number,
|
|
174
|
-
default: 200
|
|
175
|
-
},
|
|
176
|
-
height: {
|
|
177
|
-
type: Number,
|
|
178
|
-
default: 80
|
|
179
|
-
},
|
|
180
|
-
displayValue: {
|
|
181
|
-
type: Boolean,
|
|
182
|
-
default: true
|
|
183
|
-
},
|
|
184
|
-
text: {
|
|
185
|
-
type: String,
|
|
186
|
-
default: ''
|
|
187
|
-
},
|
|
188
|
-
fontOptions: {
|
|
189
|
-
type: String,
|
|
190
|
-
default: ''
|
|
191
|
-
},
|
|
192
|
-
font: {
|
|
193
|
-
type: String,
|
|
194
|
-
default: 'monospace'
|
|
195
|
-
},
|
|
196
|
-
textAlign: {
|
|
197
|
-
type: String,
|
|
198
|
-
default: 'center'
|
|
199
|
-
},
|
|
200
|
-
textPosition: {
|
|
201
|
-
type: String,
|
|
202
|
-
default: 'bottom'
|
|
203
|
-
},
|
|
204
|
-
textMargin: {
|
|
205
|
-
type: Number,
|
|
206
|
-
default: 2
|
|
207
|
-
},
|
|
208
|
-
fontSize: {
|
|
209
|
-
type: Number,
|
|
210
|
-
default: 14
|
|
211
|
-
},
|
|
212
|
-
background: {
|
|
213
|
-
type: String,
|
|
214
|
-
default: '#ffffff'
|
|
215
|
-
},
|
|
216
|
-
lineColor: {
|
|
217
|
-
type: String,
|
|
218
|
-
default: '#000000'
|
|
219
|
-
},
|
|
220
|
-
margin: {
|
|
221
|
-
type: Number,
|
|
222
|
-
default: 10
|
|
223
|
-
},
|
|
224
|
-
marginTop: {
|
|
225
|
-
type: Number,
|
|
226
|
-
default: -1
|
|
227
|
-
},
|
|
228
|
-
marginBottom: {
|
|
229
|
-
type: Number,
|
|
230
|
-
default: -1
|
|
231
|
-
},
|
|
232
|
-
marginLeft: {
|
|
233
|
-
type: Number,
|
|
234
|
-
default: -1
|
|
235
|
-
},
|
|
236
|
-
marginRight: {
|
|
237
|
-
type: Number,
|
|
238
|
-
default: -1
|
|
239
|
-
},
|
|
240
|
-
useCanvas: {
|
|
241
|
-
type: Boolean,
|
|
242
|
-
default: true
|
|
243
|
-
}
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
const emit = defineEmits(['rendered', 'error'])
|
|
247
|
-
const instance = getCurrentInstance()!.proxy!
|
|
248
|
-
|
|
249
|
-
const canvasId = ref('up-barcode-' + Date.now().toString())
|
|
250
|
-
const barcodeImage = ref('')
|
|
251
|
-
const showCanvas = ref(false)
|
|
252
|
-
const canvasContext = ref<CanvasContext | null>(null)
|
|
253
|
-
const ctx = ref<CanvasRenderingContext2D | null>(null)
|
|
254
|
-
const bars = ref<Array<UTSJSONObject>>([] as Array<UTSJSONObject>)
|
|
255
|
-
const canvasWidth = ref(200)
|
|
256
|
-
const canvasHeight = ref(80)
|
|
257
|
-
const error = ref('')
|
|
258
|
-
|
|
259
|
-
const marginTopValue = computed((): number => {
|
|
260
|
-
return props.marginTop >= 0 ? props.marginTop : props.margin
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
const marginBottomValue = computed((): number => {
|
|
264
|
-
return props.marginBottom >= 0 ? props.marginBottom : props.margin
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
const marginLeftValue = computed((): number => {
|
|
268
|
-
return props.marginLeft >= 0 ? props.marginLeft : props.margin
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
const marginRightValue = computed((): number => {
|
|
272
|
-
return props.marginRight >= 0 ? props.marginRight : props.margin
|
|
273
|
-
})
|
|
274
|
-
|
|
275
|
-
const displayText = computed((): string => {
|
|
276
|
-
return props.text.length > 0 ? props.text : stringValue(props.value)
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
const showTopText = computed((): boolean => {
|
|
280
|
-
return props.displayValue && props.textPosition == 'top' && error.value.length == 0
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
const showBottomText = computed((): boolean => {
|
|
284
|
-
return props.displayValue && props.textPosition != 'top' && error.value.length == 0
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
const showImage = computed((): boolean => {
|
|
288
|
-
return props.useCanvas == false && barcodeImage.value.length > 0 && error.value.length == 0
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
const rootStyle = computed((): UTSJSONObject => {
|
|
292
|
-
return {
|
|
293
|
-
width: canvasWidth.value.toString() + 'px',
|
|
294
|
-
minHeight: canvasHeight.value.toString() + 'px',
|
|
295
|
-
paddingTop: marginTopValue.value.toString() + 'px',
|
|
296
|
-
paddingBottom: marginBottomValue.value.toString() + 'px',
|
|
297
|
-
paddingLeft: marginLeftValue.value.toString() + 'px',
|
|
298
|
-
paddingRight: marginRightValue.value.toString() + 'px',
|
|
299
|
-
backgroundColor: props.background
|
|
300
|
-
} as UTSJSONObject
|
|
301
|
-
})
|
|
302
|
-
|
|
303
|
-
const barcodeStyle = computed((): UTSJSONObject => {
|
|
304
|
-
return {
|
|
305
|
-
width: props.width.toString() + 'px',
|
|
306
|
-
height: props.height.toString() + 'px',
|
|
307
|
-
backgroundColor: props.background
|
|
308
|
-
} as UTSJSONObject
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
const canvasStyle = computed((): UTSJSONObject => {
|
|
312
|
-
return {
|
|
313
|
-
width: canvasWidth.value.toString() + 'px',
|
|
314
|
-
height: canvasHeight.value.toString() + 'px'
|
|
315
|
-
} as UTSJSONObject
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
const imageStyle = computed((): UTSJSONObject => {
|
|
319
|
-
return {
|
|
320
|
-
width: canvasWidth.value.toString() + 'px',
|
|
321
|
-
height: canvasHeight.value.toString() + 'px'
|
|
322
|
-
} as UTSJSONObject
|
|
323
|
-
})
|
|
324
|
-
|
|
325
|
-
const textStyle = computed((): UTSJSONObject => {
|
|
326
|
-
const style = {
|
|
327
|
-
fontSize: props.fontSize.toString() + 'px',
|
|
328
|
-
lineHeight: (props.fontSize + props.textMargin).toString() + 'px',
|
|
329
|
-
color: props.lineColor,
|
|
330
|
-
textAlign: props.textAlign
|
|
331
|
-
} as UTSJSONObject
|
|
332
|
-
return style
|
|
333
|
-
})
|
|
334
|
-
|
|
335
|
-
const getBarStyle = (bar: UTSJSONObject): UTSJSONObject => {
|
|
336
|
-
return {
|
|
337
|
-
width: normalizeNumber(bar['width'], 1).toString() + 'px',
|
|
338
|
-
height: props.height.toString() + 'px',
|
|
339
|
-
backgroundColor: stringValue(bar['color'])
|
|
340
|
-
} as UTSJSONObject
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const initCanvas = (): Promise<void> => {
|
|
344
|
-
return new Promise((resolve, reject) => {
|
|
345
|
-
uni.createCanvasContextAsync({
|
|
346
|
-
id: canvasId.value.toString() as string.IDString,
|
|
347
|
-
component: instance,
|
|
348
|
-
success: (context: CanvasContext) => {
|
|
349
|
-
canvasContext.value = context
|
|
350
|
-
ctx.value = context.getContext('2d')
|
|
351
|
-
resolve()
|
|
352
|
-
},
|
|
353
|
-
fail: (err: UniError) => {
|
|
354
|
-
reject(err)
|
|
355
|
-
}
|
|
356
|
-
})
|
|
357
|
-
})
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
const getErrorMessage = (err: any | null): string => {
|
|
361
|
-
if (err == null) {
|
|
362
|
-
return ''
|
|
363
|
-
}
|
|
364
|
-
const errObj = err as UTSJSONObject
|
|
365
|
-
const message = errObj['message']
|
|
366
|
-
return message == null ? err.toString() : message.toString()
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const createBars = (bits: string): Array<UTSJSONObject> => {
|
|
370
|
-
const list = [] as Array<UTSJSONObject>
|
|
371
|
-
if (bits.length == 0) {
|
|
372
|
-
return list
|
|
373
|
-
}
|
|
374
|
-
const moduleWidth = props.width / bits.length
|
|
375
|
-
let current = bits.substring(0, 1)
|
|
376
|
-
let count = 1
|
|
377
|
-
for (let i = 1; i < bits.length; i++) {
|
|
378
|
-
const bit = bits.substring(i, i + 1)
|
|
379
|
-
if (bit == current) {
|
|
380
|
-
count++
|
|
381
|
-
} else {
|
|
382
|
-
list.push({
|
|
383
|
-
color: current == '1' ? props.lineColor : props.background,
|
|
384
|
-
width: count * moduleWidth
|
|
385
|
-
} as UTSJSONObject)
|
|
386
|
-
current = bit
|
|
387
|
-
count = 1
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
list.push({
|
|
391
|
-
color: current == '1' ? props.lineColor : props.background,
|
|
392
|
-
width: count * moduleWidth
|
|
393
|
-
} as UTSJSONObject)
|
|
394
|
-
return list
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
const encodeCode128 = (data: string): string => {
|
|
398
|
-
const chars = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
|
399
|
-
const codes = [] as Array<number>
|
|
400
|
-
let checksum = 104
|
|
401
|
-
codes.push(104)
|
|
402
|
-
for (let i = 0; i < data.length; i++) {
|
|
403
|
-
const code = chars.indexOf(data.substring(i, i + 1))
|
|
404
|
-
if (code < 0) {
|
|
405
|
-
throw new Error('Invalid character in CODE128')
|
|
406
|
-
}
|
|
407
|
-
codes.push(code)
|
|
408
|
-
checksum += code * (i + 1)
|
|
409
|
-
}
|
|
410
|
-
codes.push(checksum % 103)
|
|
411
|
-
codes.push(106)
|
|
412
|
-
const patterns = code128Patterns()
|
|
413
|
-
let barcode = ''
|
|
414
|
-
for (let i = 0; i < codes.length; i++) {
|
|
415
|
-
barcode += patterns[codes[i]]
|
|
416
|
-
}
|
|
417
|
-
return barcode + '00000'
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const encodeCode39 = (data: string): string => {
|
|
421
|
-
const codes = code39Map()
|
|
422
|
-
const value = data.toUpperCase()
|
|
423
|
-
let barcode = stringValue(codes['*'])
|
|
424
|
-
for (let i = 0; i < value.length; i++) {
|
|
425
|
-
const char = value.substring(i, i + 1)
|
|
426
|
-
const code = codes[char]
|
|
427
|
-
if (code == null) {
|
|
428
|
-
throw new Error('Invalid character in CODE39')
|
|
429
|
-
}
|
|
430
|
-
barcode += '0' + code.toString()
|
|
431
|
-
}
|
|
432
|
-
return barcode + '0' + stringValue(codes['*'])
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
const encodeEAN13 = (data: string): string => {
|
|
436
|
-
if (!/^\d{13}$/.test(data)) {
|
|
437
|
-
throw new Error('EAN13 must be 13 digits')
|
|
438
|
-
}
|
|
439
|
-
let sum = 0
|
|
440
|
-
for (let i = 0; i < 12; i++) {
|
|
441
|
-
const digit = digitAt(data, i)
|
|
442
|
-
sum += i % 2 == 0 ? digit : digit * 3
|
|
443
|
-
}
|
|
444
|
-
const checkDigit = (10 - (sum % 10)) % 10
|
|
445
|
-
if (digitAt(data, 12) != checkDigit) {
|
|
446
|
-
throw new Error('Invalid EAN13 check digit')
|
|
447
|
-
}
|
|
448
|
-
const leftData = data.substring(1, 7)
|
|
449
|
-
const rightData = data.substring(7, 13)
|
|
450
|
-
const parity = [
|
|
451
|
-
'LLLLLL', 'LLGLGG', 'LLGGLG', 'LLGGGL', 'LGLLGG',
|
|
452
|
-
'LGGLLG', 'LGGGLL', 'LGLGLG', 'LGLGGL', 'LGGLGL'
|
|
453
|
-
] as Array<string>
|
|
454
|
-
const odd = leftOddCodes()
|
|
455
|
-
const even = leftEvenCodes()
|
|
456
|
-
const right = rightCodes()
|
|
457
|
-
const pattern = parity[digitAt(data, 0)]
|
|
458
|
-
let barcode = '101'
|
|
459
|
-
for (let i = 0; i < leftData.length; i++) {
|
|
460
|
-
const digit = digitAt(leftData, i)
|
|
461
|
-
barcode += pattern.substring(i, i + 1) == 'L' ? odd[digit] : even[digit]
|
|
462
|
-
}
|
|
463
|
-
barcode += '01010'
|
|
464
|
-
for (let i = 0; i < rightData.length; i++) {
|
|
465
|
-
barcode += right[digitAt(rightData, i)]
|
|
466
|
-
}
|
|
467
|
-
return barcode + '101'
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
const encodeEAN8 = (data: string): string => {
|
|
471
|
-
if (!/^\d{8}$/.test(data)) {
|
|
472
|
-
throw new Error('EAN8 must be 8 digits')
|
|
473
|
-
}
|
|
474
|
-
let sum = 0
|
|
475
|
-
for (let i = 0; i < 7; i++) {
|
|
476
|
-
const digit = digitAt(data, i)
|
|
477
|
-
sum += digit * (i % 2 == 0 ? 3 : 1)
|
|
478
|
-
}
|
|
479
|
-
const checkDigit = (10 - (sum % 10)) % 10
|
|
480
|
-
if (digitAt(data, 7) != checkDigit) {
|
|
481
|
-
throw new Error('Invalid EAN8 check digit')
|
|
482
|
-
}
|
|
483
|
-
const odd = leftOddCodes()
|
|
484
|
-
const right = rightCodes()
|
|
485
|
-
let barcode = '101'
|
|
486
|
-
for (let i = 0; i < 4; i++) {
|
|
487
|
-
barcode += odd[digitAt(data, i)]
|
|
488
|
-
}
|
|
489
|
-
barcode += '01010'
|
|
490
|
-
for (let i = 4; i < 8; i++) {
|
|
491
|
-
barcode += right[digitAt(data, i)]
|
|
492
|
-
}
|
|
493
|
-
return barcode + '101'
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
const encodeEAN52 = (data: string, format: string): string => {
|
|
497
|
-
const length = format == 'EAN5' ? 5 : 2
|
|
498
|
-
if (data.length != length || !/^\d+$/.test(data)) {
|
|
499
|
-
throw new Error(format + ' must be ' + length.toString() + ' digits')
|
|
500
|
-
}
|
|
501
|
-
const codes = leftOddCodes()
|
|
502
|
-
let barcode = '1011'
|
|
503
|
-
for (let i = 0; i < data.length; i++) {
|
|
504
|
-
if (i > 0) {
|
|
505
|
-
barcode += '01'
|
|
506
|
-
}
|
|
507
|
-
barcode += codes[digitAt(data, i)]
|
|
508
|
-
}
|
|
509
|
-
return barcode
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
const encodeUPCA = (data: string): string => {
|
|
513
|
-
let value = data
|
|
514
|
-
if (/^\d{11}$/.test(value)) {
|
|
515
|
-
let sum = 0
|
|
516
|
-
for (let i = 0; i < 11; i++) {
|
|
517
|
-
const digit = digitAt(value, i)
|
|
518
|
-
sum += i % 2 == 0 ? digit * 3 : digit
|
|
519
|
-
}
|
|
520
|
-
value += ((10 - (sum % 10)) % 10).toString()
|
|
521
|
-
}
|
|
522
|
-
if (!/^\d{12}$/.test(value)) {
|
|
523
|
-
throw new Error('UPC-A must be 11 or 12 digits')
|
|
524
|
-
}
|
|
525
|
-
return encodeEAN13('0' + value)
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
const encodeUPCE = (data: string): string => {
|
|
529
|
-
let value = data
|
|
530
|
-
if (/^\d{7}$/.test(value)) {
|
|
531
|
-
let sum = 0
|
|
532
|
-
for (let i = 0; i < 7; i++) {
|
|
533
|
-
const digit = digitAt(value, i)
|
|
534
|
-
sum += i % 2 == 0 ? digit * 3 : digit
|
|
535
|
-
}
|
|
536
|
-
value += ((10 - (sum % 10)) % 10).toString()
|
|
537
|
-
}
|
|
538
|
-
if (!/^\d{8}$/.test(value)) {
|
|
539
|
-
throw new Error('UPC-E must be 7 or 8 digits')
|
|
540
|
-
}
|
|
541
|
-
const odd = leftOddCodes()
|
|
542
|
-
const even = leftEvenCodes()
|
|
543
|
-
const middle = value.substring(1, 7)
|
|
544
|
-
const checkDigit = value.substring(7, 8)
|
|
545
|
-
let pattern = 'EEOOOO'
|
|
546
|
-
if (checkDigit == '0' || checkDigit == '1' || checkDigit == '2' || checkDigit == '3') {
|
|
547
|
-
pattern = 'EEEEOO'
|
|
548
|
-
} else if (checkDigit == '4') {
|
|
549
|
-
pattern = 'EEEOOO'
|
|
550
|
-
}
|
|
551
|
-
let barcode = '101'
|
|
552
|
-
for (let i = 0; i < middle.length; i++) {
|
|
553
|
-
const digit = digitAt(middle, i)
|
|
554
|
-
barcode += pattern.substring(i, i + 1) == 'E' ? even[digit] : odd[digit]
|
|
555
|
-
}
|
|
556
|
-
return barcode + '010101101'
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
const encodeBarcode = (value: string, format: string): string => {
|
|
560
|
-
switch (format) {
|
|
561
|
-
case 'CODE39':
|
|
562
|
-
return encodeCode39(value)
|
|
563
|
-
case 'EAN13':
|
|
564
|
-
return encodeEAN13(value)
|
|
565
|
-
case 'EAN8':
|
|
566
|
-
return encodeEAN8(value)
|
|
567
|
-
case 'EAN5':
|
|
568
|
-
case 'EAN2':
|
|
569
|
-
return encodeEAN52(value, format)
|
|
570
|
-
case 'UPC':
|
|
571
|
-
case 'UPCA':
|
|
572
|
-
return encodeUPCA(value)
|
|
573
|
-
case 'UPCE':
|
|
574
|
-
return encodeUPCE(value)
|
|
575
|
-
case 'CODE128':
|
|
576
|
-
case 'auto':
|
|
577
|
-
default:
|
|
578
|
-
return encodeCode128(value)
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
const drawCanvasText = (context: CanvasRenderingContext2D, barcodeY: number, textHeight: number): void => {
|
|
583
|
-
const text = displayText.value
|
|
584
|
-
const textX = props.textAlign == 'left'
|
|
585
|
-
? marginLeftValue.value
|
|
586
|
-
: (props.textAlign == 'right' ? canvasWidth.value - marginRightValue.value : canvasWidth.value / 2)
|
|
587
|
-
let textY = props.textPosition == 'top'
|
|
588
|
-
? marginTopValue.value + props.fontSize
|
|
589
|
-
: barcodeY + props.height + props.textMargin + props.fontSize
|
|
590
|
-
if (textY > canvasHeight.value - marginBottomValue.value) {
|
|
591
|
-
textY = canvasHeight.value - marginBottomValue.value - 2
|
|
592
|
-
}
|
|
593
|
-
context.fillStyle = props.lineColor
|
|
594
|
-
context.font = props.fontOptions.length > 0
|
|
595
|
-
? props.fontOptions + ' ' + props.fontSize.toString() + 'px ' + props.font
|
|
596
|
-
: props.fontSize.toString() + 'px ' + props.font
|
|
597
|
-
context.textAlign = props.textAlign == 'left' || props.textAlign == 'right' ? props.textAlign : 'center'
|
|
598
|
-
context.fillText(text, textX, textY)
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
const drawCanvasBarcode = (): Promise<void> => {
|
|
602
|
-
return new Promise((resolve, reject) => {
|
|
603
|
-
const context = ctx.value
|
|
604
|
-
if (context == null) {
|
|
605
|
-
reject(new Error('Canvas is not ready'))
|
|
606
|
-
return
|
|
607
|
-
}
|
|
608
|
-
try {
|
|
609
|
-
const bits = encodeBarcode(stringValue(props.value), props.format)
|
|
610
|
-
context.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
|
|
611
|
-
context.fillStyle = props.background
|
|
612
|
-
context.fillRect(0, 0, canvasWidth.value, canvasHeight.value)
|
|
613
|
-
let barcodeY = marginTopValue.value
|
|
614
|
-
const textHeight = props.displayValue ? props.fontSize + props.textMargin : 0
|
|
615
|
-
if (props.displayValue && props.textPosition == 'top') {
|
|
616
|
-
barcodeY += textHeight
|
|
617
|
-
}
|
|
618
|
-
const moduleWidth = props.width / Math.max(1, bits.length)
|
|
619
|
-
context.fillStyle = props.lineColor
|
|
620
|
-
let x = marginLeftValue.value
|
|
621
|
-
for (let i = 0; i < bits.length; i++) {
|
|
622
|
-
if (bits.substring(i, i + 1) == '1') {
|
|
623
|
-
context.fillRect(x, barcodeY, moduleWidth + 0.5, props.height)
|
|
624
|
-
}
|
|
625
|
-
x += moduleWidth
|
|
626
|
-
}
|
|
627
|
-
if (props.displayValue) {
|
|
628
|
-
drawCanvasText(context, barcodeY, textHeight)
|
|
629
|
-
}
|
|
630
|
-
context.draw()
|
|
631
|
-
resolve()
|
|
632
|
-
} catch (err) {
|
|
633
|
-
reject(err)
|
|
634
|
-
}
|
|
635
|
-
})
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
const exportImage = (): Promise<string> => {
|
|
639
|
-
return new Promise((resolve, reject) => {
|
|
640
|
-
showCanvas.value = true
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
const
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
watch(():
|
|
721
|
-
watch(():
|
|
722
|
-
watch((): number => props.
|
|
723
|
-
watch(():
|
|
724
|
-
watch(():
|
|
725
|
-
watch((): string => props.
|
|
726
|
-
watch(():
|
|
727
|
-
watch((): number => props.
|
|
728
|
-
watch(():
|
|
729
|
-
watch((): string => props.
|
|
730
|
-
watch(():
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
158
|
+
defineOptions({
|
|
159
|
+
styleIsolation: 'app-and-page',
|
|
160
|
+
name: 'up-barcode'
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const props = defineProps({
|
|
164
|
+
value: {
|
|
165
|
+
type: [String, Number],
|
|
166
|
+
default: ''
|
|
167
|
+
},
|
|
168
|
+
format: {
|
|
169
|
+
type: String,
|
|
170
|
+
default: 'auto'
|
|
171
|
+
},
|
|
172
|
+
width: {
|
|
173
|
+
type: Number,
|
|
174
|
+
default: 200
|
|
175
|
+
},
|
|
176
|
+
height: {
|
|
177
|
+
type: Number,
|
|
178
|
+
default: 80
|
|
179
|
+
},
|
|
180
|
+
displayValue: {
|
|
181
|
+
type: Boolean,
|
|
182
|
+
default: true
|
|
183
|
+
},
|
|
184
|
+
text: {
|
|
185
|
+
type: String,
|
|
186
|
+
default: ''
|
|
187
|
+
},
|
|
188
|
+
fontOptions: {
|
|
189
|
+
type: String,
|
|
190
|
+
default: ''
|
|
191
|
+
},
|
|
192
|
+
font: {
|
|
193
|
+
type: String,
|
|
194
|
+
default: 'monospace'
|
|
195
|
+
},
|
|
196
|
+
textAlign: {
|
|
197
|
+
type: String,
|
|
198
|
+
default: 'center'
|
|
199
|
+
},
|
|
200
|
+
textPosition: {
|
|
201
|
+
type: String,
|
|
202
|
+
default: 'bottom'
|
|
203
|
+
},
|
|
204
|
+
textMargin: {
|
|
205
|
+
type: Number,
|
|
206
|
+
default: 2
|
|
207
|
+
},
|
|
208
|
+
fontSize: {
|
|
209
|
+
type: Number,
|
|
210
|
+
default: 14
|
|
211
|
+
},
|
|
212
|
+
background: {
|
|
213
|
+
type: String,
|
|
214
|
+
default: '#ffffff'
|
|
215
|
+
},
|
|
216
|
+
lineColor: {
|
|
217
|
+
type: String,
|
|
218
|
+
default: '#000000'
|
|
219
|
+
},
|
|
220
|
+
margin: {
|
|
221
|
+
type: Number,
|
|
222
|
+
default: 10
|
|
223
|
+
},
|
|
224
|
+
marginTop: {
|
|
225
|
+
type: Number,
|
|
226
|
+
default: -1
|
|
227
|
+
},
|
|
228
|
+
marginBottom: {
|
|
229
|
+
type: Number,
|
|
230
|
+
default: -1
|
|
231
|
+
},
|
|
232
|
+
marginLeft: {
|
|
233
|
+
type: Number,
|
|
234
|
+
default: -1
|
|
235
|
+
},
|
|
236
|
+
marginRight: {
|
|
237
|
+
type: Number,
|
|
238
|
+
default: -1
|
|
239
|
+
},
|
|
240
|
+
useCanvas: {
|
|
241
|
+
type: Boolean,
|
|
242
|
+
default: true
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
const emit = defineEmits(['rendered', 'error'])
|
|
247
|
+
const instance = getCurrentInstance()!.proxy!
|
|
248
|
+
|
|
249
|
+
const canvasId = ref('up-barcode-' + Date.now().toString())
|
|
250
|
+
const barcodeImage = ref('')
|
|
251
|
+
const showCanvas = ref(false)
|
|
252
|
+
const canvasContext = ref<CanvasContext | null>(null)
|
|
253
|
+
const ctx = ref<CanvasRenderingContext2D | null>(null)
|
|
254
|
+
const bars = ref<Array<UTSJSONObject>>([] as Array<UTSJSONObject>)
|
|
255
|
+
const canvasWidth = ref(200)
|
|
256
|
+
const canvasHeight = ref(80)
|
|
257
|
+
const error = ref('')
|
|
258
|
+
|
|
259
|
+
const marginTopValue = computed((): number => {
|
|
260
|
+
return props.marginTop >= 0 ? props.marginTop : props.margin
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
const marginBottomValue = computed((): number => {
|
|
264
|
+
return props.marginBottom >= 0 ? props.marginBottom : props.margin
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
const marginLeftValue = computed((): number => {
|
|
268
|
+
return props.marginLeft >= 0 ? props.marginLeft : props.margin
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
const marginRightValue = computed((): number => {
|
|
272
|
+
return props.marginRight >= 0 ? props.marginRight : props.margin
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
const displayText = computed((): string => {
|
|
276
|
+
return props.text.length > 0 ? props.text : stringValue(props.value)
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
const showTopText = computed((): boolean => {
|
|
280
|
+
return props.displayValue && props.textPosition == 'top' && error.value.length == 0
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
const showBottomText = computed((): boolean => {
|
|
284
|
+
return props.displayValue && props.textPosition != 'top' && error.value.length == 0
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
const showImage = computed((): boolean => {
|
|
288
|
+
return props.useCanvas == false && barcodeImage.value.length > 0 && error.value.length == 0
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
const rootStyle = computed((): UTSJSONObject => {
|
|
292
|
+
return {
|
|
293
|
+
width: canvasWidth.value.toString() + 'px',
|
|
294
|
+
minHeight: canvasHeight.value.toString() + 'px',
|
|
295
|
+
paddingTop: marginTopValue.value.toString() + 'px',
|
|
296
|
+
paddingBottom: marginBottomValue.value.toString() + 'px',
|
|
297
|
+
paddingLeft: marginLeftValue.value.toString() + 'px',
|
|
298
|
+
paddingRight: marginRightValue.value.toString() + 'px',
|
|
299
|
+
backgroundColor: props.background
|
|
300
|
+
} as UTSJSONObject
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
const barcodeStyle = computed((): UTSJSONObject => {
|
|
304
|
+
return {
|
|
305
|
+
width: props.width.toString() + 'px',
|
|
306
|
+
height: props.height.toString() + 'px',
|
|
307
|
+
backgroundColor: props.background
|
|
308
|
+
} as UTSJSONObject
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
const canvasStyle = computed((): UTSJSONObject => {
|
|
312
|
+
return {
|
|
313
|
+
width: canvasWidth.value.toString() + 'px',
|
|
314
|
+
height: canvasHeight.value.toString() + 'px'
|
|
315
|
+
} as UTSJSONObject
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
const imageStyle = computed((): UTSJSONObject => {
|
|
319
|
+
return {
|
|
320
|
+
width: canvasWidth.value.toString() + 'px',
|
|
321
|
+
height: canvasHeight.value.toString() + 'px'
|
|
322
|
+
} as UTSJSONObject
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
const textStyle = computed((): UTSJSONObject => {
|
|
326
|
+
const style = {
|
|
327
|
+
fontSize: props.fontSize.toString() + 'px',
|
|
328
|
+
lineHeight: (props.fontSize + props.textMargin).toString() + 'px',
|
|
329
|
+
color: props.lineColor,
|
|
330
|
+
textAlign: props.textAlign
|
|
331
|
+
} as UTSJSONObject
|
|
332
|
+
return style
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
const getBarStyle = (bar: UTSJSONObject): UTSJSONObject => {
|
|
336
|
+
return {
|
|
337
|
+
width: normalizeNumber(bar['width'], 1).toString() + 'px',
|
|
338
|
+
height: props.height.toString() + 'px',
|
|
339
|
+
backgroundColor: stringValue(bar['color'])
|
|
340
|
+
} as UTSJSONObject
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const initCanvas = (): Promise<void> => {
|
|
344
|
+
return new Promise((resolve, reject) => {
|
|
345
|
+
uni.createCanvasContextAsync({
|
|
346
|
+
id: canvasId.value.toString() as string.IDString,
|
|
347
|
+
component: instance,
|
|
348
|
+
success: (context: CanvasContext) => {
|
|
349
|
+
canvasContext.value = context
|
|
350
|
+
ctx.value = context.getContext('2d')
|
|
351
|
+
resolve()
|
|
352
|
+
},
|
|
353
|
+
fail: (err: UniError) => {
|
|
354
|
+
reject(err)
|
|
355
|
+
}
|
|
356
|
+
})
|
|
357
|
+
})
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const getErrorMessage = (err: any | null): string => {
|
|
361
|
+
if (err == null) {
|
|
362
|
+
return ''
|
|
363
|
+
}
|
|
364
|
+
const errObj = err as UTSJSONObject
|
|
365
|
+
const message = errObj['message']
|
|
366
|
+
return message == null ? err.toString() : message.toString()
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const createBars = (bits: string): Array<UTSJSONObject> => {
|
|
370
|
+
const list = [] as Array<UTSJSONObject>
|
|
371
|
+
if (bits.length == 0) {
|
|
372
|
+
return list
|
|
373
|
+
}
|
|
374
|
+
const moduleWidth = props.width / bits.length
|
|
375
|
+
let current = bits.substring(0, 1)
|
|
376
|
+
let count = 1
|
|
377
|
+
for (let i = 1; i < bits.length; i++) {
|
|
378
|
+
const bit = bits.substring(i, i + 1)
|
|
379
|
+
if (bit == current) {
|
|
380
|
+
count++
|
|
381
|
+
} else {
|
|
382
|
+
list.push({
|
|
383
|
+
color: current == '1' ? props.lineColor : props.background,
|
|
384
|
+
width: count * moduleWidth
|
|
385
|
+
} as UTSJSONObject)
|
|
386
|
+
current = bit
|
|
387
|
+
count = 1
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
list.push({
|
|
391
|
+
color: current == '1' ? props.lineColor : props.background,
|
|
392
|
+
width: count * moduleWidth
|
|
393
|
+
} as UTSJSONObject)
|
|
394
|
+
return list
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const encodeCode128 = (data: string): string => {
|
|
398
|
+
const chars = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
|
399
|
+
const codes = [] as Array<number>
|
|
400
|
+
let checksum = 104
|
|
401
|
+
codes.push(104)
|
|
402
|
+
for (let i = 0; i < data.length; i++) {
|
|
403
|
+
const code = chars.indexOf(data.substring(i, i + 1))
|
|
404
|
+
if (code < 0) {
|
|
405
|
+
throw new Error('Invalid character in CODE128')
|
|
406
|
+
}
|
|
407
|
+
codes.push(code)
|
|
408
|
+
checksum += code * (i + 1)
|
|
409
|
+
}
|
|
410
|
+
codes.push(checksum % 103)
|
|
411
|
+
codes.push(106)
|
|
412
|
+
const patterns = code128Patterns()
|
|
413
|
+
let barcode = ''
|
|
414
|
+
for (let i = 0; i < codes.length; i++) {
|
|
415
|
+
barcode += patterns[codes[i]]
|
|
416
|
+
}
|
|
417
|
+
return barcode + '00000'
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const encodeCode39 = (data: string): string => {
|
|
421
|
+
const codes = code39Map()
|
|
422
|
+
const value = data.toUpperCase()
|
|
423
|
+
let barcode = stringValue(codes['*'])
|
|
424
|
+
for (let i = 0; i < value.length; i++) {
|
|
425
|
+
const char = value.substring(i, i + 1)
|
|
426
|
+
const code = codes[char]
|
|
427
|
+
if (code == null) {
|
|
428
|
+
throw new Error('Invalid character in CODE39')
|
|
429
|
+
}
|
|
430
|
+
barcode += '0' + code.toString()
|
|
431
|
+
}
|
|
432
|
+
return barcode + '0' + stringValue(codes['*'])
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const encodeEAN13 = (data: string): string => {
|
|
436
|
+
if (!/^\d{13}$/.test(data)) {
|
|
437
|
+
throw new Error('EAN13 must be 13 digits')
|
|
438
|
+
}
|
|
439
|
+
let sum = 0
|
|
440
|
+
for (let i = 0; i < 12; i++) {
|
|
441
|
+
const digit = digitAt(data, i)
|
|
442
|
+
sum += i % 2 == 0 ? digit : digit * 3
|
|
443
|
+
}
|
|
444
|
+
const checkDigit = (10 - (sum % 10)) % 10
|
|
445
|
+
if (digitAt(data, 12) != checkDigit) {
|
|
446
|
+
throw new Error('Invalid EAN13 check digit')
|
|
447
|
+
}
|
|
448
|
+
const leftData = data.substring(1, 7)
|
|
449
|
+
const rightData = data.substring(7, 13)
|
|
450
|
+
const parity = [
|
|
451
|
+
'LLLLLL', 'LLGLGG', 'LLGGLG', 'LLGGGL', 'LGLLGG',
|
|
452
|
+
'LGGLLG', 'LGGGLL', 'LGLGLG', 'LGLGGL', 'LGGLGL'
|
|
453
|
+
] as Array<string>
|
|
454
|
+
const odd = leftOddCodes()
|
|
455
|
+
const even = leftEvenCodes()
|
|
456
|
+
const right = rightCodes()
|
|
457
|
+
const pattern = parity[digitAt(data, 0)]
|
|
458
|
+
let barcode = '101'
|
|
459
|
+
for (let i = 0; i < leftData.length; i++) {
|
|
460
|
+
const digit = digitAt(leftData, i)
|
|
461
|
+
barcode += pattern.substring(i, i + 1) == 'L' ? odd[digit] : even[digit]
|
|
462
|
+
}
|
|
463
|
+
barcode += '01010'
|
|
464
|
+
for (let i = 0; i < rightData.length; i++) {
|
|
465
|
+
barcode += right[digitAt(rightData, i)]
|
|
466
|
+
}
|
|
467
|
+
return barcode + '101'
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const encodeEAN8 = (data: string): string => {
|
|
471
|
+
if (!/^\d{8}$/.test(data)) {
|
|
472
|
+
throw new Error('EAN8 must be 8 digits')
|
|
473
|
+
}
|
|
474
|
+
let sum = 0
|
|
475
|
+
for (let i = 0; i < 7; i++) {
|
|
476
|
+
const digit = digitAt(data, i)
|
|
477
|
+
sum += digit * (i % 2 == 0 ? 3 : 1)
|
|
478
|
+
}
|
|
479
|
+
const checkDigit = (10 - (sum % 10)) % 10
|
|
480
|
+
if (digitAt(data, 7) != checkDigit) {
|
|
481
|
+
throw new Error('Invalid EAN8 check digit')
|
|
482
|
+
}
|
|
483
|
+
const odd = leftOddCodes()
|
|
484
|
+
const right = rightCodes()
|
|
485
|
+
let barcode = '101'
|
|
486
|
+
for (let i = 0; i < 4; i++) {
|
|
487
|
+
barcode += odd[digitAt(data, i)]
|
|
488
|
+
}
|
|
489
|
+
barcode += '01010'
|
|
490
|
+
for (let i = 4; i < 8; i++) {
|
|
491
|
+
barcode += right[digitAt(data, i)]
|
|
492
|
+
}
|
|
493
|
+
return barcode + '101'
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const encodeEAN52 = (data: string, format: string): string => {
|
|
497
|
+
const length = format == 'EAN5' ? 5 : 2
|
|
498
|
+
if (data.length != length || !/^\d+$/.test(data)) {
|
|
499
|
+
throw new Error(format + ' must be ' + length.toString() + ' digits')
|
|
500
|
+
}
|
|
501
|
+
const codes = leftOddCodes()
|
|
502
|
+
let barcode = '1011'
|
|
503
|
+
for (let i = 0; i < data.length; i++) {
|
|
504
|
+
if (i > 0) {
|
|
505
|
+
barcode += '01'
|
|
506
|
+
}
|
|
507
|
+
barcode += codes[digitAt(data, i)]
|
|
508
|
+
}
|
|
509
|
+
return barcode
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const encodeUPCA = (data: string): string => {
|
|
513
|
+
let value = data
|
|
514
|
+
if (/^\d{11}$/.test(value)) {
|
|
515
|
+
let sum = 0
|
|
516
|
+
for (let i = 0; i < 11; i++) {
|
|
517
|
+
const digit = digitAt(value, i)
|
|
518
|
+
sum += i % 2 == 0 ? digit * 3 : digit
|
|
519
|
+
}
|
|
520
|
+
value += ((10 - (sum % 10)) % 10).toString()
|
|
521
|
+
}
|
|
522
|
+
if (!/^\d{12}$/.test(value)) {
|
|
523
|
+
throw new Error('UPC-A must be 11 or 12 digits')
|
|
524
|
+
}
|
|
525
|
+
return encodeEAN13('0' + value)
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const encodeUPCE = (data: string): string => {
|
|
529
|
+
let value = data
|
|
530
|
+
if (/^\d{7}$/.test(value)) {
|
|
531
|
+
let sum = 0
|
|
532
|
+
for (let i = 0; i < 7; i++) {
|
|
533
|
+
const digit = digitAt(value, i)
|
|
534
|
+
sum += i % 2 == 0 ? digit * 3 : digit
|
|
535
|
+
}
|
|
536
|
+
value += ((10 - (sum % 10)) % 10).toString()
|
|
537
|
+
}
|
|
538
|
+
if (!/^\d{8}$/.test(value)) {
|
|
539
|
+
throw new Error('UPC-E must be 7 or 8 digits')
|
|
540
|
+
}
|
|
541
|
+
const odd = leftOddCodes()
|
|
542
|
+
const even = leftEvenCodes()
|
|
543
|
+
const middle = value.substring(1, 7)
|
|
544
|
+
const checkDigit = value.substring(7, 8)
|
|
545
|
+
let pattern = 'EEOOOO'
|
|
546
|
+
if (checkDigit == '0' || checkDigit == '1' || checkDigit == '2' || checkDigit == '3') {
|
|
547
|
+
pattern = 'EEEEOO'
|
|
548
|
+
} else if (checkDigit == '4') {
|
|
549
|
+
pattern = 'EEEOOO'
|
|
550
|
+
}
|
|
551
|
+
let barcode = '101'
|
|
552
|
+
for (let i = 0; i < middle.length; i++) {
|
|
553
|
+
const digit = digitAt(middle, i)
|
|
554
|
+
barcode += pattern.substring(i, i + 1) == 'E' ? even[digit] : odd[digit]
|
|
555
|
+
}
|
|
556
|
+
return barcode + '010101101'
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const encodeBarcode = (value: string, format: string): string => {
|
|
560
|
+
switch (format) {
|
|
561
|
+
case 'CODE39':
|
|
562
|
+
return encodeCode39(value)
|
|
563
|
+
case 'EAN13':
|
|
564
|
+
return encodeEAN13(value)
|
|
565
|
+
case 'EAN8':
|
|
566
|
+
return encodeEAN8(value)
|
|
567
|
+
case 'EAN5':
|
|
568
|
+
case 'EAN2':
|
|
569
|
+
return encodeEAN52(value, format)
|
|
570
|
+
case 'UPC':
|
|
571
|
+
case 'UPCA':
|
|
572
|
+
return encodeUPCA(value)
|
|
573
|
+
case 'UPCE':
|
|
574
|
+
return encodeUPCE(value)
|
|
575
|
+
case 'CODE128':
|
|
576
|
+
case 'auto':
|
|
577
|
+
default:
|
|
578
|
+
return encodeCode128(value)
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
const drawCanvasText = (context: CanvasRenderingContext2D, barcodeY: number, textHeight: number): void => {
|
|
583
|
+
const text = displayText.value
|
|
584
|
+
const textX = props.textAlign == 'left'
|
|
585
|
+
? marginLeftValue.value
|
|
586
|
+
: (props.textAlign == 'right' ? canvasWidth.value - marginRightValue.value : canvasWidth.value / 2)
|
|
587
|
+
let textY = props.textPosition == 'top'
|
|
588
|
+
? marginTopValue.value + props.fontSize
|
|
589
|
+
: barcodeY + props.height + props.textMargin + props.fontSize
|
|
590
|
+
if (textY > canvasHeight.value - marginBottomValue.value) {
|
|
591
|
+
textY = canvasHeight.value - marginBottomValue.value - 2
|
|
592
|
+
}
|
|
593
|
+
context.fillStyle = props.lineColor
|
|
594
|
+
context.font = props.fontOptions.length > 0
|
|
595
|
+
? props.fontOptions + ' ' + props.fontSize.toString() + 'px ' + props.font
|
|
596
|
+
: props.fontSize.toString() + 'px ' + props.font
|
|
597
|
+
context.textAlign = props.textAlign == 'left' || props.textAlign == 'right' ? props.textAlign : 'center'
|
|
598
|
+
context.fillText(text, textX, textY)
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const drawCanvasBarcode = (): Promise<void> => {
|
|
602
|
+
return new Promise((resolve, reject) => {
|
|
603
|
+
const context = ctx.value
|
|
604
|
+
if (context == null) {
|
|
605
|
+
reject(new Error('Canvas is not ready'))
|
|
606
|
+
return
|
|
607
|
+
}
|
|
608
|
+
try {
|
|
609
|
+
const bits = encodeBarcode(stringValue(props.value), props.format)
|
|
610
|
+
context.clearRect(0, 0, canvasWidth.value, canvasHeight.value)
|
|
611
|
+
context.fillStyle = props.background
|
|
612
|
+
context.fillRect(0, 0, canvasWidth.value, canvasHeight.value)
|
|
613
|
+
let barcodeY = marginTopValue.value
|
|
614
|
+
const textHeight = props.displayValue ? props.fontSize + props.textMargin : 0
|
|
615
|
+
if (props.displayValue && props.textPosition == 'top') {
|
|
616
|
+
barcodeY += textHeight
|
|
617
|
+
}
|
|
618
|
+
const moduleWidth = props.width / Math.max(1, bits.length)
|
|
619
|
+
context.fillStyle = props.lineColor
|
|
620
|
+
let x = marginLeftValue.value
|
|
621
|
+
for (let i = 0; i < bits.length; i++) {
|
|
622
|
+
if (bits.substring(i, i + 1) == '1') {
|
|
623
|
+
context.fillRect(x, barcodeY, moduleWidth + 0.5, props.height)
|
|
624
|
+
}
|
|
625
|
+
x += moduleWidth
|
|
626
|
+
}
|
|
627
|
+
if (props.displayValue) {
|
|
628
|
+
drawCanvasText(context, barcodeY, textHeight)
|
|
629
|
+
}
|
|
630
|
+
context.draw()
|
|
631
|
+
resolve()
|
|
632
|
+
} catch (err) {
|
|
633
|
+
reject(err)
|
|
634
|
+
}
|
|
635
|
+
})
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const exportImage = (): Promise<string> => {
|
|
639
|
+
return new Promise((resolve, reject) => {
|
|
640
|
+
showCanvas.value = true
|
|
641
|
+
// 等待条件渲染的画布提交到组件宿主视图后再查询节点。
|
|
642
|
+
instance.$nextTick(() => {
|
|
643
|
+
initCanvas().then(() => {
|
|
644
|
+
drawCanvasBarcode().then(() => {
|
|
645
|
+
const canvas = canvasContext.value
|
|
646
|
+
if (canvas == null) {
|
|
647
|
+
showCanvas.value = false
|
|
648
|
+
reject(new Error('Canvas is not ready'))
|
|
649
|
+
return
|
|
650
|
+
}
|
|
651
|
+
const dataUrl = canvas.toDataURL('image/png', 1)
|
|
652
|
+
showCanvas.value = false
|
|
653
|
+
emit('rendered', { type: 'image', value: props.value, path: dataUrl } as UTSJSONObject)
|
|
654
|
+
resolve(dataUrl)
|
|
655
|
+
}).catch((err: any | null) => {
|
|
656
|
+
showCanvas.value = false
|
|
657
|
+
reject(err)
|
|
658
|
+
})
|
|
659
|
+
}).catch((err: any | null) => {
|
|
660
|
+
showCanvas.value = false
|
|
661
|
+
reject(err)
|
|
662
|
+
})
|
|
663
|
+
})
|
|
664
|
+
})
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const generateBarcode = (): void => {
|
|
668
|
+
try {
|
|
669
|
+
error.value = ''
|
|
670
|
+
const bits = encodeBarcode(stringValue(props.value), props.format)
|
|
671
|
+
bars.value = createBars(bits)
|
|
672
|
+
const textHeight = props.displayValue ? props.fontSize + props.textMargin : 0
|
|
673
|
+
canvasWidth.value = props.width + marginLeftValue.value + marginRightValue.value
|
|
674
|
+
canvasHeight.value = props.height + marginTopValue.value + marginBottomValue.value + textHeight
|
|
675
|
+
if (props.useCanvas == false) {
|
|
676
|
+
nextTick(() => {
|
|
677
|
+
exportImage().then((path: string) => {
|
|
678
|
+
barcodeImage.value = path
|
|
679
|
+
}).catch((err: any | null) => {
|
|
680
|
+
emit('error', err)
|
|
681
|
+
})
|
|
682
|
+
})
|
|
683
|
+
} else {
|
|
684
|
+
barcodeImage.value = ''
|
|
685
|
+
}
|
|
686
|
+
emit('rendered', {
|
|
687
|
+
type: props.useCanvas == false ? 'image' : 'view',
|
|
688
|
+
value: props.value,
|
|
689
|
+
format: props.format,
|
|
690
|
+
path: barcodeImage.value
|
|
691
|
+
} as UTSJSONObject)
|
|
692
|
+
} catch (err) {
|
|
693
|
+
const message = getErrorMessage(err)
|
|
694
|
+
error.value = message.length > 0 ? message : '生成条码失败'
|
|
695
|
+
bars.value = [] as Array<UTSJSONObject>
|
|
696
|
+
emit('error', {
|
|
697
|
+
message: error.value,
|
|
698
|
+
value: props.value,
|
|
699
|
+
format: props.format
|
|
700
|
+
} as UTSJSONObject)
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function toTempFilePath(options: UTSJSONObject = {} as UTSJSONObject): void {
|
|
705
|
+
const success = options['success'] as ((res: UTSJSONObject) => void) | null
|
|
706
|
+
const fail = options['fail'] as ((err: any | null) => void) | null
|
|
707
|
+
exportImage().then((path: string) => {
|
|
708
|
+
if (success != null) {
|
|
709
|
+
success({ tempFilePath: path, path } as UTSJSONObject)
|
|
710
|
+
}
|
|
711
|
+
}).catch((err: any | null) => {
|
|
712
|
+
if (fail != null) {
|
|
713
|
+
fail(err)
|
|
714
|
+
} else {
|
|
715
|
+
emit('error', err)
|
|
716
|
+
}
|
|
717
|
+
})
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
watch((): any => props.value, () => { generateBarcode() })
|
|
721
|
+
watch((): string => props.format, () => { generateBarcode() })
|
|
722
|
+
watch((): number => props.width, () => { generateBarcode() })
|
|
723
|
+
watch((): number => props.height, () => { generateBarcode() })
|
|
724
|
+
watch((): boolean => props.displayValue, () => { generateBarcode() })
|
|
725
|
+
watch((): string => props.text, () => { generateBarcode() })
|
|
726
|
+
watch((): string => props.textPosition, () => { generateBarcode() })
|
|
727
|
+
watch((): number => props.textMargin, () => { generateBarcode() })
|
|
728
|
+
watch((): number => props.fontSize, () => { generateBarcode() })
|
|
729
|
+
watch((): string => props.background, () => { generateBarcode() })
|
|
730
|
+
watch((): string => props.lineColor, () => { generateBarcode() })
|
|
731
|
+
watch((): number => props.margin, () => { generateBarcode() })
|
|
732
|
+
|
|
733
|
+
onMounted((): void => {
|
|
734
|
+
generateBarcode()
|
|
735
|
+
})
|
|
736
|
+
|
|
737
|
+
defineExpose({
|
|
738
|
+
canvasId,
|
|
739
|
+
barcodeImage,
|
|
740
|
+
showCanvas,
|
|
741
|
+
canvasContext,
|
|
742
|
+
ctx,
|
|
743
|
+
bars,
|
|
744
|
+
canvasWidth,
|
|
745
|
+
canvasHeight,
|
|
746
|
+
error,
|
|
747
|
+
marginTopValue,
|
|
748
|
+
marginBottomValue,
|
|
749
|
+
marginLeftValue,
|
|
750
|
+
marginRightValue,
|
|
751
|
+
displayText,
|
|
752
|
+
showTopText,
|
|
753
|
+
showBottomText,
|
|
754
|
+
showImage,
|
|
755
|
+
rootStyle,
|
|
756
|
+
barcodeStyle,
|
|
757
|
+
canvasStyle,
|
|
758
|
+
imageStyle,
|
|
759
|
+
textStyle,
|
|
760
|
+
getBarStyle,
|
|
761
|
+
generateBarcode,
|
|
762
|
+
toTempFilePath,
|
|
763
|
+
exportImage,
|
|
764
|
+
initCanvas,
|
|
765
|
+
drawCanvasBarcode,
|
|
766
|
+
drawCanvasText,
|
|
767
|
+
getErrorMessage,
|
|
768
|
+
createBars,
|
|
769
|
+
encodeBarcode,
|
|
770
|
+
encodeCode128,
|
|
771
|
+
encodeCode39,
|
|
772
|
+
encodeEAN13,
|
|
773
|
+
encodeEAN8,
|
|
774
|
+
encodeEAN52,
|
|
775
|
+
encodeUPCA,
|
|
776
|
+
encodeUPCE
|
|
777
|
+
})
|
|
778
|
+
</script>
|
|
778
779
|
|
|
779
780
|
<style scoped lang="scss">
|
|
780
781
|
.up-barcode {
|