nv-img-barcode-cmmn 1.0.1 → 1.0.2
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/TEST/tst0.js +71 -0
- package/gs1.js +454 -0
- package/index.js +2 -85
- package/package.json +1 -1
- package/ptrn.js +0 -161
package/TEST/tst0.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const validate_and_fmt_int = (info,value)=>{
|
|
2
|
+
//整数
|
|
3
|
+
let num = Number(value);
|
|
4
|
+
if(!Object.is(num,NaN)) {
|
|
5
|
+
if(num<0) {return [false,`不可为负数`]}
|
|
6
|
+
if(num <=Number.MAX_SAFE_INTEGER){
|
|
7
|
+
if(parseInt(num) === num) {
|
|
8
|
+
value =String(num);
|
|
9
|
+
if(value.length<= info.length) {
|
|
10
|
+
value = '0'.repeat(info.length - value.length) + value;
|
|
11
|
+
return [true,value];
|
|
12
|
+
} else {
|
|
13
|
+
return [false,`${info.desc} 长度最多 ${info.length}`];
|
|
14
|
+
}
|
|
15
|
+
} else {
|
|
16
|
+
return [false,`${info.desc} 必须是整数数字`];
|
|
17
|
+
}
|
|
18
|
+
} else {
|
|
19
|
+
// num > Number.MAX_SAFE_INTEGER
|
|
20
|
+
num = BigInt(value);
|
|
21
|
+
value =String(num);
|
|
22
|
+
if(value.length<= info.length) {
|
|
23
|
+
value = '0'.repeat(info.length - value.length) + value;
|
|
24
|
+
return [true,value];
|
|
25
|
+
} else {
|
|
26
|
+
return [false,`${info.desc} 长度最多 ${info.length}`];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
return [false,`${info.desc} 必须是整数数字`];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function test_logic() {
|
|
35
|
+
const info = { length: 6, desc: "测试字段" };
|
|
36
|
+
|
|
37
|
+
console.log('MAX_SAFE_INTEGER:', Number.MAX_SAFE_INTEGER);
|
|
38
|
+
console.log('2**53:', 2**53);
|
|
39
|
+
console.log('2**53 === Number.MAX_SAFE_INTEGER?', 2**53 === Number.MAX_SAFE_INTEGER);
|
|
40
|
+
console.log('');
|
|
41
|
+
|
|
42
|
+
const testCases = [
|
|
43
|
+
// 在安全范围内的数
|
|
44
|
+
{ value: 9007199254740991, desc: "MAX_SAFE_INTEGER" }, // 应该成功
|
|
45
|
+
{ value: 9007199254740992, desc: "刚好超出安全" }, // 应该进入BigInt分支
|
|
46
|
+
{ value: 9999999999999999, desc: "9999万亿" }, // 1e16-1
|
|
47
|
+
|
|
48
|
+
// 明确超出安全范围的数
|
|
49
|
+
{ value: 10000000000000000, desc: "1e16" }, // 1e16
|
|
50
|
+
{ value: 99999999999999999, desc: "9.9e16" }, // 你提到的数
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
testCases.forEach(test => {
|
|
54
|
+
const num = Number(test.value);
|
|
55
|
+
const isSafe = num <= Number.MAX_SAFE_INTEGER;
|
|
56
|
+
|
|
57
|
+
console.log(`${test.desc.padEnd(20)}: ${test.value}`);
|
|
58
|
+
console.log(` Number() = ${num}`);
|
|
59
|
+
console.log(` <= MAX_SAFE_INTEGER? ${isSafe}`);
|
|
60
|
+
console.log(` 会进入哪个分支? ${isSafe ? '安全分支' : 'BigInt分支'}`);
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const [success, result] = validate_and_fmt_int(info, test.value);
|
|
64
|
+
console.log(` 结果: ${success ? '成功' : '失败'} ${result || ''}`);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.log(` 异常: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
console.log('');
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
test_logic();
|
package/gs1.js
ADDED
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
const GS1_AI_SPECS = {
|
|
2
|
+
'00': { name: 'SSCC', length: 18, format: 'numeric', desc: '物流单元标识符' },
|
|
3
|
+
'01': { name: 'GTIN', length: 14, format: 'numeric', desc: '全球贸易项目代码' },
|
|
4
|
+
'02': { name: 'CONTENT_GTIN', length: 14, format: 'numeric', desc: '物流单元内贸易项目GTIN' },
|
|
5
|
+
'10': { name: 'BATCH', length: 20, format: 'alphanumeric', desc: '批号' },
|
|
6
|
+
'11': { name: 'PROD_DATE', length: 6, format: 'date', desc: '生产日期(YYMMDD)' },
|
|
7
|
+
'12': { name: 'DUE_DATE', length: 6, format: 'date', desc: '付款截止日期(YYMMDD)' },
|
|
8
|
+
'13': { name: 'PACK_DATE', length: 6, format: 'date', desc: '包装日期(YYMMDD)' },
|
|
9
|
+
'15': { name: 'BEST_BEFORE', length: 6, format: 'date', desc: '保质期(YYMMDD)' },
|
|
10
|
+
'16': { name: 'SELL_BY', length: 6, format: 'date', desc: '销售日期(YYMMDD)' },
|
|
11
|
+
'17': { name: 'EXPIRY', length: 6, format: 'date', desc: '有效期(YYMMDD)' },
|
|
12
|
+
'19': { name: 'EXPIRY_ALT', length: 6, format: 'date', desc: '过期日期(YYMMDD)' },
|
|
13
|
+
'20': { name: 'VARIANT', length: 2, format: 'numeric', desc: '包装内部标识' },
|
|
14
|
+
'21': { name: 'SERIAL', length: 20, format: 'alphanumeric', desc: '序列号' },
|
|
15
|
+
'22': { name: 'MEDICAL_DATA', length: 20, format: 'alphanumeric', desc: '医疗产品附加数据' },
|
|
16
|
+
'23': { name: 'LOT_GROUP', length: 20, format: 'alphanumeric', desc: '组号' },
|
|
17
|
+
'30': { name: 'VAR_COUNT', length: 8, format: 'numeric', desc: '可变数量' },
|
|
18
|
+
'3100': { name: 'NET_WEIGHT_0', length: 6, format: 'numeric', decimal: 0, unit: 'kg', desc: '净重(kg)整数' },
|
|
19
|
+
'3101': { name: 'NET_WEIGHT_1', length: 6, format: 'numeric', decimal: 1, unit: 'kg', desc: '净重(kg)1位小数' },
|
|
20
|
+
'3102': { name: 'NET_WEIGHT_2', length: 6, format: 'numeric', decimal: 2, unit: 'kg', desc: '净重(kg)2位小数' },
|
|
21
|
+
'3103': { name: 'NET_WEIGHT_3', length: 6, format: 'numeric', decimal: 3, unit: 'kg', desc: '净重(kg)3位小数' },
|
|
22
|
+
'3104': { name: 'NET_WEIGHT_4', length: 6, format: 'numeric', decimal: 4, unit: 'kg', desc: '净重(kg)4位小数' },
|
|
23
|
+
'3105': { name: 'NET_WEIGHT_5', length: 6, format: 'numeric', decimal: 5, unit: 'kg', desc: '净重(kg)5位小数' },
|
|
24
|
+
'3110': { name: 'LENGTH_0', length: 6, format: 'numeric', decimal: 0, unit: 'm', desc: '长度(m)整数' },
|
|
25
|
+
'3111': { name: 'LENGTH_1', length: 6, format: 'numeric', decimal: 1, unit: 'm', desc: '长度(m)1位小数' },
|
|
26
|
+
'3112': { name: 'LENGTH_2', length: 6, format: 'numeric', decimal: 2, unit: 'm', desc: '长度(m)2位小数' },
|
|
27
|
+
'3113': { name: 'LENGTH_3', length: 6, format: 'numeric', decimal: 3, unit: 'm', desc: '长度(m)3位小数' },
|
|
28
|
+
'3114': { name: 'LENGTH_4', length: 6, format: 'numeric', decimal: 4, unit: 'm', desc: '长度(m)4位小数' },
|
|
29
|
+
'3115': { name: 'LENGTH_5', length: 6, format: 'numeric', decimal: 5, unit: 'm', desc: '长度(m)5位小数' },
|
|
30
|
+
'3120': { name: 'WIDTH_0', length: 6, format: 'numeric', decimal: 0, unit: 'm', desc: '宽度(m)整数' },
|
|
31
|
+
'3121': { name: 'WIDTH_1', length: 6, format: 'numeric', decimal: 1, unit: 'm', desc: '宽度(m)1位小数' },
|
|
32
|
+
'3122': { name: 'WIDTH_2', length: 6, format: 'numeric', decimal: 2, unit: 'm', desc: '宽度(m)2位小数' },
|
|
33
|
+
'3123': { name: 'WIDTH_3', length: 6, format: 'numeric', decimal: 3, unit: 'm', desc: '宽度(m)3位小数' },
|
|
34
|
+
'3124': { name: 'WIDTH_4', length: 6, format: 'numeric', decimal: 4, unit: 'm', desc: '宽度(m)4位小数' },
|
|
35
|
+
'3125': { name: 'WIDTH_5', length: 6, format: 'numeric', decimal: 5, unit: 'm', desc: '宽度(m)5位小数' },
|
|
36
|
+
'3130': { name: 'HEIGHT_0', length: 6, format: 'numeric', decimal: 0, unit: 'm', desc: '高度(m)整数' },
|
|
37
|
+
'3131': { name: 'HEIGHT_1', length: 6, format: 'numeric', decimal: 1, unit: 'm', desc: '高度(m)1位小数' },
|
|
38
|
+
'3132': { name: 'HEIGHT_2', length: 6, format: 'numeric', decimal: 2, unit: 'm', desc: '高度(m)2位小数' },
|
|
39
|
+
'3133': { name: 'HEIGHT_3', length: 6, format: 'numeric', decimal: 3, unit: 'm', desc: '高度(m)3位小数' },
|
|
40
|
+
'3134': { name: 'HEIGHT_4', length: 6, format: 'numeric', decimal: 4, unit: 'm', desc: '高度(m)4位小数' },
|
|
41
|
+
'3135': { name: 'HEIGHT_5', length: 6, format: 'numeric', decimal: 5, unit: 'm', desc: '高度(m)5位小数' },
|
|
42
|
+
'3140': { name: 'AREA_0', length: 6, format: 'numeric', decimal: 0, unit: 'm²', desc: '面积(m²)整数' },
|
|
43
|
+
'3141': { name: 'AREA_1', length: 6, format: 'numeric', decimal: 1, unit: 'm²', desc: '面积(m²)1位小数' },
|
|
44
|
+
'3142': { name: 'AREA_2', length: 6, format: 'numeric', decimal: 2, unit: 'm²', desc: '面积(m²)2位小数' },
|
|
45
|
+
'3143': { name: 'AREA_3', length: 6, format: 'numeric', decimal: 3, unit: 'm²', desc: '面积(m²)3位小数' },
|
|
46
|
+
'3144': { name: 'AREA_4', length: 6, format: 'numeric', decimal: 4, unit: 'm²', desc: '面积(m²)4位小数' },
|
|
47
|
+
'3145': { name: 'AREA_5', length: 6, format: 'numeric', decimal: 5, unit: 'm²', desc: '面积(m²)5位小数' },
|
|
48
|
+
'3150': { name: 'NET_VOLUME_L_0', length: 6, format: 'numeric', decimal: 0, unit: 'l', desc: '净容积(l)整数' },
|
|
49
|
+
'3151': { name: 'NET_VOLUME_L_1', length: 6, format: 'numeric', decimal: 1, unit: 'l', desc: '净容积(l)1位小数' },
|
|
50
|
+
'3152': { name: 'NET_VOLUME_L_2', length: 6, format: 'numeric', decimal: 2, unit: 'l', desc: '净容积(l)2位小数' },
|
|
51
|
+
'3153': { name: 'NET_VOLUME_L_3', length: 6, format: 'numeric', decimal: 3, unit: 'l', desc: '净容积(l)3位小数' },
|
|
52
|
+
'3154': { name: 'NET_VOLUME_L_4', length: 6, format: 'numeric', decimal: 4, unit: 'l', desc: '净容积(l)4位小数' },
|
|
53
|
+
'3155': { name: 'NET_VOLUME_L_5', length: 6, format: 'numeric', decimal: 5, unit: 'l', desc: '净容积(l)5位小数' },
|
|
54
|
+
'3160': { name: 'NET_VOLUME_M3_0', length: 6, format: 'numeric', decimal: 0, unit: 'm³', desc: '净体积(m³)整数' },
|
|
55
|
+
'3161': { name: 'NET_VOLUME_M3_1', length: 6, format: 'numeric', decimal: 1, unit: 'm³', desc: '净体积(m³)1位小数' },
|
|
56
|
+
'3162': { name: 'NET_VOLUME_M3_2', length: 6, format: 'numeric', decimal: 2, unit: 'm³', desc: '净体积(m³)2位小数' },
|
|
57
|
+
'3163': { name: 'NET_VOLUME_M3_3', length: 6, format: 'numeric', decimal: 3, unit: 'm³', desc: '净体积(m³)3位小数' },
|
|
58
|
+
'3164': { name: 'NET_VOLUME_M3_4', length: 6, format: 'numeric', decimal: 4, unit: 'm³', desc: '净体积(m³)4位小数' },
|
|
59
|
+
'3165': { name: 'NET_VOLUME_M3_5', length: 6, format: 'numeric', decimal: 5, unit: 'm³', desc: '净体积(m³)5位小数' },
|
|
60
|
+
'3200': { name: 'NET_WEIGHT_LB_0', length: 6, format: 'numeric', decimal: 0, unit: 'lb', desc: '净重(lb)整数' },
|
|
61
|
+
'3201': { name: 'NET_WEIGHT_LB_1', length: 6, format: 'numeric', decimal: 1, unit: 'lb', desc: '净重(lb)1位小数' },
|
|
62
|
+
'3202': { name: 'NET_WEIGHT_LB_2', length: 6, format: 'numeric', decimal: 2, unit: 'lb', desc: '净重(lb)2位小数' },
|
|
63
|
+
'3203': { name: 'NET_WEIGHT_LB_3', length: 6, format: 'numeric', decimal: 3, unit: 'lb', desc: '净重(lb)3位小数' },
|
|
64
|
+
'3204': { name: 'NET_WEIGHT_LB_4', length: 6, format: 'numeric', decimal: 4, unit: 'lb', desc: '净重(lb)4位小数' },
|
|
65
|
+
'3205': { name: 'NET_WEIGHT_LB_5', length: 6, format: 'numeric', decimal: 5, unit: 'lb', desc: '净重(lb)5位小数' },
|
|
66
|
+
'3300': { name: 'GROSS_WEIGHT_0', length: 6, format: 'numeric', decimal: 0, unit: 'kg', desc: '毛重(kg)整数' },
|
|
67
|
+
'3301': { name: 'GROSS_WEIGHT_1', length: 6, format: 'numeric', decimal: 1, unit: 'kg', desc: '毛重(kg)1位小数' },
|
|
68
|
+
'3302': { name: 'GROSS_WEIGHT_2', length: 6, format: 'numeric', decimal: 2, unit: 'kg', desc: '毛重(kg)2位小数' },
|
|
69
|
+
'3303': { name: 'GROSS_WEIGHT_3', length: 6, format: 'numeric', decimal: 3, unit: 'kg', desc: '毛重(kg)3位小数' },
|
|
70
|
+
'3304': { name: 'GROSS_WEIGHT_4', length: 6, format: 'numeric', decimal: 4, unit: 'kg', desc: '毛重(kg)4位小数' },
|
|
71
|
+
'3305': { name: 'GROSS_WEIGHT_5', length: 6, format: 'numeric', decimal: 5, unit: 'kg', desc: '毛重(kg)5位小数' },
|
|
72
|
+
'37': { name: 'COUNT', length: 8, format: 'numeric', desc: '物流单元内商品数量' },
|
|
73
|
+
'90': { name: 'INTERNAL_1', length: 30, format: 'alphanumeric', desc: '自定义0' },
|
|
74
|
+
'91': { name: 'INTERNAL_2', length: 90, format: 'alphanumeric', desc: '自定义1' },
|
|
75
|
+
'92': { name: 'INTERNAL_3', length: 90, format: 'alphanumeric', desc: '自定义2' },
|
|
76
|
+
'93': { name: 'INTERNAL_4', length: 90, format: 'alphanumeric', desc: '自定义3' },
|
|
77
|
+
'94': { name: 'INTERNAL_5', length: 90, format: 'alphanumeric', desc: '自定义4' },
|
|
78
|
+
'95': { name: 'INTERNAL_6', length: 90, format: 'alphanumeric', desc: '自定义5' },
|
|
79
|
+
'96': { name: 'INTERNAL_7', length: 90, format: 'alphanumeric', desc: '自定义6' },
|
|
80
|
+
'97': { name: 'INTERNAL_8', length: 90, format: 'alphanumeric', desc: '自定义7' },
|
|
81
|
+
'98': { name: 'INTERNAL_9', length: 90, format: 'alphanumeric', desc: '自定义8' },
|
|
82
|
+
'99': { name: 'INTERNAL_10', length: 90, format: 'alphanumeric', desc: '自定义9' }
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const GS1_ALPHANUMERIC_REGEX = /^[A-Za-z0-9 !"*+,\-.\/:;=?_\x23\x24]+$/;
|
|
86
|
+
// ^
|
|
87
|
+
// [ # 字符集开始
|
|
88
|
+
// A-Za-z0-9 # 字母和数字
|
|
89
|
+
// \x20 # 空格(ASCII 32)
|
|
90
|
+
// !"*+,\-.\/:;=?_ # 允许的特殊字符
|
|
91
|
+
// \x23 # #(ASCII 35)
|
|
92
|
+
// \x24 # $(ASCII 36)
|
|
93
|
+
// ] # 字符集结束
|
|
94
|
+
// + # 至少一个字符
|
|
95
|
+
// $ # 字符串结束
|
|
96
|
+
const YYMMDD_REGEX = /^(\d{2})(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])$/;
|
|
97
|
+
const mts_to_yymmdd = (mts)=>{
|
|
98
|
+
////时间戳转换为YYMMDD
|
|
99
|
+
const date = new Date(mts);
|
|
100
|
+
const year = date.getFullYear() % 100; // 取年份后两位
|
|
101
|
+
const month = date.getMonth() + 1; // 月份从0开始
|
|
102
|
+
const day = date.getDate(); // 获取日期
|
|
103
|
+
|
|
104
|
+
return [
|
|
105
|
+
year.toString().padStart(2, '0'), // YY
|
|
106
|
+
month.toString().padStart(2, '0'), // MM
|
|
107
|
+
day.toString().padStart(2, '0') // DD
|
|
108
|
+
].join('');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const splitIntegerDecimal = (num) => {
|
|
112
|
+
// 转换为字符串
|
|
113
|
+
const str = String(num);
|
|
114
|
+
|
|
115
|
+
// 分割整数和小数部分
|
|
116
|
+
const parts = str.split('.');
|
|
117
|
+
|
|
118
|
+
// 处理整数部分
|
|
119
|
+
let integerPart = null;
|
|
120
|
+
const integerNum = parseInt(parts[0] || '0', 10);
|
|
121
|
+
if (integerNum !== 0) {
|
|
122
|
+
integerPart = integerNum;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 处理小数部分
|
|
126
|
+
let decimalPart = null;
|
|
127
|
+
if (parts[1] && parts[1] !== '0') {
|
|
128
|
+
// 移除末尾的0
|
|
129
|
+
const decimalStr = parts[1].replace(/0+$/, '');
|
|
130
|
+
if (decimalStr && decimalStr !== '0') {
|
|
131
|
+
decimalPart = parseInt(decimalStr, 10);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return [integerPart, decimalPart];
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
const validate_and_fmt_int = (info,value)=>{
|
|
140
|
+
//整数
|
|
141
|
+
let num = Number(value);
|
|
142
|
+
if(!Object.is(num,NaN)) {
|
|
143
|
+
if(num<0) {return [false,`不可为负数`]}
|
|
144
|
+
if(num <=Number.MAX_SAFE_INTEGER){
|
|
145
|
+
if(parseInt(num) === num) {
|
|
146
|
+
value =String(num);
|
|
147
|
+
if(value.length<= info.length) {
|
|
148
|
+
value = '0'.repeat(info.length - value.length) + value;
|
|
149
|
+
return [true,value];
|
|
150
|
+
} else {
|
|
151
|
+
return [false,`${info.desc} 长度最多 ${info.length}`];
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
return [false,`${info.desc} 必须是整数数字`];
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
// num > Number.MAX_SAFE_INTEGER
|
|
158
|
+
num = BigInt(value);
|
|
159
|
+
value =String(num);
|
|
160
|
+
if(value.length<= info.length) {
|
|
161
|
+
value = '0'.repeat(info.length - value.length) + value;
|
|
162
|
+
return [true,value];
|
|
163
|
+
} else {
|
|
164
|
+
return [false,`${info.desc} 长度最多 ${info.length}`];
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
return [false,`${info.desc} 必须是整数数字`];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const validate_and_fmt_ai_value = (ai, value)=>{
|
|
173
|
+
ai = String(ai);
|
|
174
|
+
let info = GS1_AI_SPECS[ai];
|
|
175
|
+
if(info===undefined) {
|
|
176
|
+
return [false,"非法AI"]
|
|
177
|
+
} else {
|
|
178
|
+
if(info.format === "numeric") {
|
|
179
|
+
if(info.decimal === undefined|| info.decimal ===0) {
|
|
180
|
+
//整数
|
|
181
|
+
return validate_and_fmt_int(info,value);
|
|
182
|
+
} else {
|
|
183
|
+
//浮点
|
|
184
|
+
let num = Number(value);
|
|
185
|
+
let [ii,dd] = splitIntegerDecimal(num);
|
|
186
|
+
if(ii === null) {
|
|
187
|
+
if(dd === null) {
|
|
188
|
+
return [true,'0'.repeat(info.length)]
|
|
189
|
+
} else {
|
|
190
|
+
dd = "0." + String(dd);
|
|
191
|
+
dd = Number(dd);
|
|
192
|
+
dd = dd *(10**info.decimal);
|
|
193
|
+
dd = String(dd);
|
|
194
|
+
dd = '0'.repeat(info.length - dd.length)+dd;
|
|
195
|
+
return [true,dd]
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
if(dd === null) {
|
|
199
|
+
return validate_and_fmt_int(info,ii);
|
|
200
|
+
} else {
|
|
201
|
+
let ilen = String(ii).length;
|
|
202
|
+
let int_max_length = info.length - info.decimal;
|
|
203
|
+
if(ilen> int_max_length) {
|
|
204
|
+
return [false,`${info.desc} 长度最多 ${info.length}`]
|
|
205
|
+
} else {
|
|
206
|
+
const intPart = String(ii).padStart(int_max_length, '0');
|
|
207
|
+
let decStr = String(dd).padEnd(info.decimal, '0').substring(0, info.decimal);
|
|
208
|
+
const result = intPart + decStr;
|
|
209
|
+
return [true, result];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
} else if(info.format === "date") {
|
|
215
|
+
if(typeof(value)==="number") {
|
|
216
|
+
////视作时间戳
|
|
217
|
+
return [true,mts_to_yymmdd(value)]
|
|
218
|
+
} else {
|
|
219
|
+
value = String(value);
|
|
220
|
+
}
|
|
221
|
+
if(YYMMDD_REGEX.test(value)) {
|
|
222
|
+
return [true,value];
|
|
223
|
+
} else {
|
|
224
|
+
return [false,`${info.desc} 必需匹配 YYMMDD`];
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
//(info.format === "alphanumeric")
|
|
228
|
+
value = String(value);
|
|
229
|
+
if(GS1_ALPHANUMERIC_REGEX.test(value)) {
|
|
230
|
+
if(info.length>=value.length) {
|
|
231
|
+
return [true,value]
|
|
232
|
+
} else {
|
|
233
|
+
return [false,`${info.desc} 长度必需 <= ${info.length}`];
|
|
234
|
+
}
|
|
235
|
+
} else {
|
|
236
|
+
return [false,`${info.desc} 必需匹配 /^[A-Za-z0-9 !"%&'()*+,\-.\/:;<=>?_]+$/`];
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
let ALIAS = {
|
|
243
|
+
// 物流单元
|
|
244
|
+
'物流单元标识符': '00',
|
|
245
|
+
'物流单元': '00',
|
|
246
|
+
'运输包装代码': '00',
|
|
247
|
+
'托盘代码': '00',
|
|
248
|
+
// 商品代码
|
|
249
|
+
'商品条码': '01',
|
|
250
|
+
'商品代码': '01',
|
|
251
|
+
'产品代码': '01',
|
|
252
|
+
// 批次
|
|
253
|
+
'批次': '10',
|
|
254
|
+
'批号': '10',
|
|
255
|
+
'lot': '10',
|
|
256
|
+
'batch': '10',
|
|
257
|
+
// 日期相关
|
|
258
|
+
'生产日期': '11',
|
|
259
|
+
'制造日期': '11',
|
|
260
|
+
'保质期': '15',
|
|
261
|
+
'保鲜期': '15',
|
|
262
|
+
'有效期': '17',
|
|
263
|
+
'到期日': '17',
|
|
264
|
+
// 数量
|
|
265
|
+
'数量': '30',
|
|
266
|
+
'件数': '30',
|
|
267
|
+
'quantity': '30',
|
|
268
|
+
'物流单元内商品数量': '37',
|
|
269
|
+
'整箱数量': '37',
|
|
270
|
+
// 序列号
|
|
271
|
+
'序列号': '21',
|
|
272
|
+
'流水号': '21',
|
|
273
|
+
'serial': '21',
|
|
274
|
+
// 重量体积
|
|
275
|
+
'净重': '3100',
|
|
276
|
+
'重量': '3100',
|
|
277
|
+
'毛重': '3300',
|
|
278
|
+
'总重': '3300',
|
|
279
|
+
'长度': '3110',
|
|
280
|
+
'长': '3110',
|
|
281
|
+
'宽度': '3120',
|
|
282
|
+
'宽': '3120',
|
|
283
|
+
'高度': '3130',
|
|
284
|
+
'高': '3130',
|
|
285
|
+
'面积': '3140',
|
|
286
|
+
'体积': '3160',
|
|
287
|
+
'容积': '3150',
|
|
288
|
+
'容量': '3150',
|
|
289
|
+
|
|
290
|
+
// 包装
|
|
291
|
+
'包装内部标识': '20',
|
|
292
|
+
'包装标识': '20',
|
|
293
|
+
|
|
294
|
+
// 医疗
|
|
295
|
+
'医疗': '22',
|
|
296
|
+
'药品': '22',
|
|
297
|
+
|
|
298
|
+
// 组
|
|
299
|
+
'组号': '23',
|
|
300
|
+
'分组': '23',
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
let AI_TO_NAMES = {};
|
|
304
|
+
let NAME_TO_AI = {};
|
|
305
|
+
const reset_map = ()=> {
|
|
306
|
+
AI_TO_NAMES = {};
|
|
307
|
+
NAME_TO_AI = {};
|
|
308
|
+
for(let ai in GS1_AI_SPECS) {
|
|
309
|
+
NAME_TO_AI[ai] = ai; // 直接使用ai
|
|
310
|
+
AI_TO_NAMES[ai] = [ai];
|
|
311
|
+
let detail = GS1_AI_SPECS[ai];
|
|
312
|
+
let v = GS1_AI_SPECS[ai];
|
|
313
|
+
let name = v.name.toLowerCase(); NAME_TO_AI[name] = ai; // 使用英文名
|
|
314
|
+
////使用中文名
|
|
315
|
+
{
|
|
316
|
+
let desc = v.desc.replace('(m)', '米')
|
|
317
|
+
.replace('(m²)', '平')
|
|
318
|
+
.replace('(m³)', '方')
|
|
319
|
+
.replace('(lb)', '磅')
|
|
320
|
+
.replace('(kg)', '公斤')
|
|
321
|
+
.replace('(l)', '升')
|
|
322
|
+
.replace(/[\(\)]/g, '') // 再清理一次可能的残留括号
|
|
323
|
+
.trim()
|
|
324
|
+
.toLowerCase()
|
|
325
|
+
;
|
|
326
|
+
NAME_TO_AI[desc] = ai;
|
|
327
|
+
AI_TO_NAMES[ai].push(desc);
|
|
328
|
+
////
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
reset_map();
|
|
333
|
+
let FIXED_NAMES ;
|
|
334
|
+
const update_map = ()=> {
|
|
335
|
+
reset_map();
|
|
336
|
+
////使用ALIAS
|
|
337
|
+
{
|
|
338
|
+
for(let alias in ALIAS) {
|
|
339
|
+
let ai = ALIAS[alias];
|
|
340
|
+
if(GS1_AI_SPECS[ai]){
|
|
341
|
+
NAME_TO_AI[alias.toLowerCase()] = ai;
|
|
342
|
+
AI_TO_NAMES[ai].push(alias.toLowerCase());
|
|
343
|
+
} else {
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
FIXED_NAMES = Object.keys(NAME_TO_AI);
|
|
349
|
+
}
|
|
350
|
+
update_map();
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
const name_to_ai = (name)=>{
|
|
354
|
+
name = String(name).toLowerCase();
|
|
355
|
+
let ai = NAME_TO_AI[name];
|
|
356
|
+
return ai;
|
|
357
|
+
}
|
|
358
|
+
const ai_to_names = (ai)=>AI_TO_NAMES[ai];
|
|
359
|
+
const encd_one =(name_or_ai,value)=>{
|
|
360
|
+
let ai = name_to_ai(name_or_ai);
|
|
361
|
+
if (!ai) {
|
|
362
|
+
//无效的字段名或AI代码: "${name_or_ai} 请尝试使用 未使用的自定义ai 90-99"
|
|
363
|
+
return [null,name_to_ai];
|
|
364
|
+
}
|
|
365
|
+
let [cond,v] = validate_and_fmt_ai_value(ai,value);
|
|
366
|
+
if(cond) {
|
|
367
|
+
return [true,`(${ai})${v}`];
|
|
368
|
+
} else {
|
|
369
|
+
return [false,v];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
////
|
|
375
|
+
const _encd = (arr) => {
|
|
376
|
+
let succs = [];let fails = [];
|
|
377
|
+
const aloc_next_unused_dyn_slot = ()=>{
|
|
378
|
+
for(let ai=90;ai<=99;++ai) {if(st.has(ai)) {} else {st.add(ai);return ai;}}
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
let len = arr.length;let st = new Set();
|
|
382
|
+
if(len === 0) { fails.push("参数不能为空");
|
|
383
|
+
} else {
|
|
384
|
+
if(len %2 === 0) {} else {arr.push(undefined);}
|
|
385
|
+
for(let i=0;i<arr.length;i+=2) {
|
|
386
|
+
let name_or_ai = arr[i];
|
|
387
|
+
let value = arr[i+1];
|
|
388
|
+
if(value !== undefined) {
|
|
389
|
+
let [cond,vstr] = encd_one(name_or_ai,value);
|
|
390
|
+
if(cond === null) {
|
|
391
|
+
let ai = aloc_next_unused_dyn_slot();
|
|
392
|
+
if(ai!== null) {
|
|
393
|
+
let [cond1,vstr1] = encd_one(ai,value);
|
|
394
|
+
if (cond1) {
|
|
395
|
+
succs.push(vstr1);ALIAS[String(name_or_ai).toLowerCase()] = ai;update_map();
|
|
396
|
+
} else {
|
|
397
|
+
fails.push(`${name_or_ai} : ${vstr}`)
|
|
398
|
+
}
|
|
399
|
+
} else {
|
|
400
|
+
fails.push(`${name_or_ai} 不是合法AI 并且 90-99 动态ai 都已占用`)
|
|
401
|
+
}
|
|
402
|
+
} else if(cond === true) {
|
|
403
|
+
succs.push(vstr);
|
|
404
|
+
let ai = Number(name_to_ai(name_or_ai));
|
|
405
|
+
if(ai>=90 && ai<=99 ) {
|
|
406
|
+
st.add(ai); //已经被占用
|
|
407
|
+
} else {}
|
|
408
|
+
} else {
|
|
409
|
+
fails.push(`${name_or_ai} : ${vstr}`)
|
|
410
|
+
}
|
|
411
|
+
} else {
|
|
412
|
+
fails.push(`${name_or_ai} : "值不能为空"`)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return [succs,fails]
|
|
417
|
+
}
|
|
418
|
+
const encd = (...args)=>{
|
|
419
|
+
if(args.length === 0) {
|
|
420
|
+
return null;
|
|
421
|
+
} else if(args.length === 1) {
|
|
422
|
+
let arr = args[0];
|
|
423
|
+
if(Array.isArray(args[0])) {
|
|
424
|
+
} else {
|
|
425
|
+
arr = Object.entries(args[0]).flat();
|
|
426
|
+
}
|
|
427
|
+
let [succs,fails] = _encd(arr);
|
|
428
|
+
let succ_str = succs.join("");
|
|
429
|
+
return succ_str===""?null:succ_str;
|
|
430
|
+
} else {
|
|
431
|
+
let [succs,fails] = _encd(args);
|
|
432
|
+
let succ_str = succs.join("");
|
|
433
|
+
return succ_str===""?null:succ_str;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
module.exports = {
|
|
438
|
+
get GS1_AI_SPECS() {return GS1_AI_SPECS;},
|
|
439
|
+
get ALIAS() {return ALIAS;},
|
|
440
|
+
set ALIAS(d) {
|
|
441
|
+
ALIAS = d;
|
|
442
|
+
update_map();
|
|
443
|
+
},
|
|
444
|
+
get NAME_TO_AI() {return NAME_TO_AI;},
|
|
445
|
+
get AI_TO_NAMES() {return AI_TO_NAMES;},
|
|
446
|
+
get FIXED_NAMES() {return FIXED_NAMES;},
|
|
447
|
+
validate_and_fmt_ai_value,
|
|
448
|
+
name_to_ai,ai_to_names,
|
|
449
|
+
encd_one,
|
|
450
|
+
_encd,
|
|
451
|
+
encd,
|
|
452
|
+
list_names: ()=>FIXED_NAMES,
|
|
453
|
+
look_requirements: (name)=>GS1_AI_SPECS[name_to_ai(name)]
|
|
454
|
+
}
|
package/index.js
CHANGED
|
@@ -1,88 +1,5 @@
|
|
|
1
|
-
const
|
|
2
|
-
code128_code_to_ptrn,
|
|
3
|
-
code128_ptrn_to_code,
|
|
4
|
-
CODE128_CODE_TO_PTRN
|
|
5
|
-
} = require("./ptrn")
|
|
6
|
-
|
|
7
|
-
const bytes_to_code128 = (bytes) => {
|
|
8
|
-
const codes = [];
|
|
9
|
-
const START_B = 104;
|
|
10
|
-
codes.push(START_B);
|
|
11
|
-
|
|
12
|
-
for (const b of bytes) {
|
|
13
|
-
codes.push(b & 0x7f); // 与 decoder 对称
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// checksum
|
|
17
|
-
let sum = START_B;
|
|
18
|
-
codes.slice(1).forEach((c, i) => {
|
|
19
|
-
sum += c * (i + 1);
|
|
20
|
-
});
|
|
21
|
-
codes.push(sum % 103);
|
|
22
|
-
|
|
23
|
-
// STOP
|
|
24
|
-
codes.push(106);
|
|
25
|
-
|
|
26
|
-
// codes -> modules
|
|
27
|
-
return codes.flatMap(c => CODE128_CODE_TO_PTRN[c]);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const code128_to_bytes = (modules) => {
|
|
31
|
-
const codes = [];
|
|
32
|
-
let i = 0;
|
|
33
|
-
|
|
34
|
-
while (i < modules.length) {
|
|
35
|
-
let code = code128_ptrn_to_code(modules.slice(i, i + 6));
|
|
36
|
-
if (code >= 0) {
|
|
37
|
-
codes.push(code);
|
|
38
|
-
i += 6;
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// 尝试 STOP
|
|
43
|
-
if (i + 7 <= modules.length) {
|
|
44
|
-
code = code128_ptrn_to_code(modules.slice(i, i + 7));
|
|
45
|
-
if (code === 106) {
|
|
46
|
-
codes.push(106);
|
|
47
|
-
i += 7;
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// 不匹配也安全跳过:+1 移动
|
|
53
|
-
i += 1;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 安全处理 START / STOP
|
|
57
|
-
if (codes.length === 0 || codes[0] !== 104) {
|
|
58
|
-
// 没有 START_B,用空 payload
|
|
59
|
-
return new Uint8Array(0);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// 去掉 START / checksum / STOP
|
|
63
|
-
const payload = codes.slice(1, -2);
|
|
64
|
-
|
|
65
|
-
// checksum 校验可选
|
|
66
|
-
let sum = 104;
|
|
67
|
-
payload.forEach((c, i) => sum += c * (i + 1));
|
|
68
|
-
const checksum = codes[codes.length - 2] ?? 0;
|
|
69
|
-
if (sum % 103 !== checksum) {
|
|
70
|
-
// 可以返回 null 或空数组表示校验失败
|
|
71
|
-
return new Uint8Array(0);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return Uint8Array.from(payload);
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const normalize_runs_to_modules = (runs) => {
|
|
78
|
-
const min = Math.min(...runs);
|
|
79
|
-
return runs.map(r => Math.max(1, Math.round(r / min)));
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
|
|
1
|
+
const gs1 = require("./gs1");
|
|
83
2
|
|
|
84
3
|
module.exports = {
|
|
85
|
-
|
|
86
|
-
code128_to_bytes,
|
|
87
|
-
normalize_runs_to_modules,
|
|
4
|
+
gs1
|
|
88
5
|
}
|
package/package.json
CHANGED
package/ptrn.js
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
// Code 128 patterns (ISO/IEC 15417)
|
|
2
|
-
const CODE128_CODE_TO_PTRN = [
|
|
3
|
-
[2,1,2,2,2,2], // 0
|
|
4
|
-
[2,2,2,1,2,2], // 1
|
|
5
|
-
[2,2,2,2,2,1], // 2
|
|
6
|
-
[1,2,1,2,2,3], // 3
|
|
7
|
-
[1,2,1,3,2,2], // 4
|
|
8
|
-
[1,3,1,2,2,2], // 5
|
|
9
|
-
[1,2,2,2,1,3], // 6
|
|
10
|
-
[1,2,2,3,1,2], // 7
|
|
11
|
-
[1,3,2,2,1,2], // 8
|
|
12
|
-
[2,2,1,2,1,3], // 9
|
|
13
|
-
[2,2,1,3,1,2], // 10
|
|
14
|
-
[2,3,1,2,1,2], // 11
|
|
15
|
-
[1,1,2,2,3,2], // 12
|
|
16
|
-
[1,2,2,1,3,2], // 13
|
|
17
|
-
[1,2,2,2,3,1], // 14
|
|
18
|
-
[1,1,3,2,2,2], // 15
|
|
19
|
-
[1,2,3,1,2,2], // 16
|
|
20
|
-
[1,2,3,2,2,1], // 17
|
|
21
|
-
[2,2,3,2,1,1], // 18
|
|
22
|
-
[2,2,1,1,3,2], // 19
|
|
23
|
-
[2,2,1,2,3,1], // 20
|
|
24
|
-
[2,1,3,2,1,2], // 21
|
|
25
|
-
[2,2,3,1,1,2], // 22
|
|
26
|
-
[3,1,2,1,3,1], // 23
|
|
27
|
-
[3,1,1,2,2,2], // 24
|
|
28
|
-
[3,2,1,1,2,2], // 25
|
|
29
|
-
[3,2,1,2,2,1], // 26
|
|
30
|
-
[3,1,2,2,1,2], // 27
|
|
31
|
-
[3,2,2,1,1,2], // 28
|
|
32
|
-
[3,2,2,2,1,1], // 29
|
|
33
|
-
[2,1,2,1,2,3], // 30
|
|
34
|
-
[2,1,2,3,2,1], // 31
|
|
35
|
-
[2,3,2,1,2,1], // 32
|
|
36
|
-
[1,1,1,3,2,3], // 33
|
|
37
|
-
[1,3,1,1,2,3], // 34
|
|
38
|
-
[1,3,1,3,2,1], // 35
|
|
39
|
-
[1,1,2,3,1,3], // 36
|
|
40
|
-
[1,3,2,1,1,3], // 37
|
|
41
|
-
[1,3,2,3,1,1], // 38
|
|
42
|
-
[2,1,1,3,1,3], // 39
|
|
43
|
-
[2,3,1,1,1,3], // 40
|
|
44
|
-
[2,3,1,3,1,1], // 41
|
|
45
|
-
[1,1,2,1,3,3], // 42
|
|
46
|
-
[1,1,2,3,3,1], // 43
|
|
47
|
-
[1,3,2,1,3,1], // 44
|
|
48
|
-
[1,1,3,1,2,3], // 45
|
|
49
|
-
[1,1,3,3,2,1], // 46
|
|
50
|
-
[1,3,3,1,2,1], // 47
|
|
51
|
-
[3,1,3,1,2,1], // 48
|
|
52
|
-
[2,1,1,3,3,1], // 49
|
|
53
|
-
[2,3,1,1,3,1], // 50
|
|
54
|
-
[2,1,3,1,1,3], // 51
|
|
55
|
-
[2,1,3,3,1,1], // 52
|
|
56
|
-
[2,1,3,1,3,1], // 53
|
|
57
|
-
[3,1,1,1,2,3], // 54
|
|
58
|
-
[3,1,1,3,2,1], // 55
|
|
59
|
-
[3,3,1,1,2,1], // 56
|
|
60
|
-
[3,1,2,1,1,3], // 57
|
|
61
|
-
[3,1,2,3,1,1], // 58
|
|
62
|
-
[3,3,2,1,1,1], // 59
|
|
63
|
-
[3,1,4,1,1,1], // 60
|
|
64
|
-
[2,2,1,4,1,1], // 61
|
|
65
|
-
[4,3,1,1,1,1], // 62
|
|
66
|
-
[1,1,1,2,2,4], // 63
|
|
67
|
-
[1,1,1,4,2,2], // 64
|
|
68
|
-
[1,2,1,1,2,4], // 65
|
|
69
|
-
[1,2,1,4,2,1], // 66
|
|
70
|
-
[1,4,1,1,2,2], // 67
|
|
71
|
-
[1,4,1,2,2,1], // 68
|
|
72
|
-
[1,1,2,2,1,4], // 69
|
|
73
|
-
[1,1,2,4,1,2], // 70
|
|
74
|
-
[1,2,2,1,1,4], // 71
|
|
75
|
-
[1,2,2,4,1,1], // 72
|
|
76
|
-
[1,4,2,1,1,2], // 73
|
|
77
|
-
[1,4,2,2,1,1], // 74
|
|
78
|
-
[2,4,1,2,1,1], // 75
|
|
79
|
-
[2,2,1,1,1,4], // 76
|
|
80
|
-
[4,1,3,1,1,1], // 77
|
|
81
|
-
[2,4,1,1,1,2], // 78
|
|
82
|
-
[1,3,4,1,1,1], // 79
|
|
83
|
-
[1,1,1,2,4,2], // 80
|
|
84
|
-
[1,2,1,1,4,2], // 81
|
|
85
|
-
[1,2,1,2,4,1], // 82
|
|
86
|
-
[1,1,4,2,1,2], // 83
|
|
87
|
-
[1,2,4,1,1,2], // 84
|
|
88
|
-
[1,2,4,2,1,1], // 85
|
|
89
|
-
[4,1,1,2,1,2], // 86
|
|
90
|
-
[4,2,1,1,1,2], // 87
|
|
91
|
-
[4,2,1,2,1,1], // 88
|
|
92
|
-
[2,1,2,1,4,1], // 89
|
|
93
|
-
[2,1,4,1,2,1], // 90
|
|
94
|
-
[4,1,2,1,2,1], // 91
|
|
95
|
-
[1,1,1,1,4,3], // 92
|
|
96
|
-
[1,1,1,3,4,1], // 93
|
|
97
|
-
[1,3,1,1,4,1], // 94
|
|
98
|
-
[1,1,4,1,1,3], // 95
|
|
99
|
-
[1,1,4,3,1,1], // 96
|
|
100
|
-
[4,1,1,1,1,3], // 97
|
|
101
|
-
[4,1,1,3,1,1], // 98
|
|
102
|
-
[1,1,3,1,4,1], // 99
|
|
103
|
-
[1,1,4,1,3,1], // 100
|
|
104
|
-
[3,1,1,1,4,1], // 101
|
|
105
|
-
[4,1,1,1,3,1], // 102
|
|
106
|
-
[2,1,1,4,1,2], // 103 START A
|
|
107
|
-
[2,1,1,2,1,4], // 104 START B
|
|
108
|
-
[2,1,1,2,3,2], // 105 START C
|
|
109
|
-
[2,3,3,1,1,1,2], // 106 STOP (7 modules!)
|
|
110
|
-
];
|
|
111
|
-
|
|
112
|
-
const arr_to_intkey = (arr)=> parseInt(arr.join(""),5);
|
|
113
|
-
|
|
114
|
-
const [MIN_KEY,CODE128_PTRN_TO_CODE] = JSON.parse(JSON.stringify(
|
|
115
|
-
(() => {
|
|
116
|
-
const mp = {};
|
|
117
|
-
for (let i = 0; i < CODE128_CODE_TO_PTRN.length; i++) {
|
|
118
|
-
const arr = CODE128_CODE_TO_PTRN[i];
|
|
119
|
-
mp[arr_to_intkey(arr)]=i;
|
|
120
|
-
}
|
|
121
|
-
let ks = Object.keys(mp);
|
|
122
|
-
ks = ks.map(r=>Number(r));
|
|
123
|
-
ks.sort((a,b)=>a-b);
|
|
124
|
-
let MIN = ks[0];
|
|
125
|
-
let MAX = ks[ks.length-1];
|
|
126
|
-
let arr = [];
|
|
127
|
-
for(let i=0;i<=MAX;++i) {arr[i] = 0;}
|
|
128
|
-
for(let k of ks) { arr[k-MIN] = mp[k];}
|
|
129
|
-
return [MIN,arr];
|
|
130
|
-
})()
|
|
131
|
-
));
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const code128_code_to_ptrn = (cd) => CODE128_CODE_TO_PTRN[cd]; //->Array<>
|
|
135
|
-
const code128_ptrn_to_code = (arr)=> {
|
|
136
|
-
const key = arr_to_intkey(arr);
|
|
137
|
-
const idx = key - MIN_KEY;
|
|
138
|
-
return CODE128_PTRN_TO_CODE[idx];
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
module.exports = {
|
|
143
|
-
CODE128_CODE_TO_PTRN,
|
|
144
|
-
MIN_KEY,
|
|
145
|
-
CODE128_PTRN_TO_CODE,
|
|
146
|
-
////
|
|
147
|
-
arr_to_intkey,
|
|
148
|
-
code128_code_to_ptrn,
|
|
149
|
-
code128_ptrn_to_code
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if(module.id===".") {
|
|
153
|
-
for(let i=0;i<CODE128_CODE_TO_PTRN.length;++i) {
|
|
154
|
-
let expected = CODE128_CODE_TO_PTRN[i];
|
|
155
|
-
let actual = code128_ptrn_to_code(CODE128_CODE_TO_PTRN[i]);
|
|
156
|
-
if(actual!== i) {
|
|
157
|
-
throw({expected,actual})
|
|
158
|
-
} else {
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
} else {}
|