更新记录
1.0.0(2026-10-27)
首个版本:内置 70+ 条常用 AI(GTIN/SSCC/批号/效期/生产包装日期/序列号/数量/GLN/净重毛重/金额/GRAI/GIAI/GSRN 等),支持带 FNC1、无分隔符、括号三种输入形态并自动清理 AIM 前缀;校验模 10 校验位(含 GTIN-8/12/13/14、SSCC-18、GLN-13)、GS1 日期世纪推断与闰年、数值型、长度越界、重复 AI,逐条产出具名 issue 并给出正确校验位;UDI-DI/UDI-PI 拆分;反向由字段生成元素串(变长自动补 GS、日期自动转、校验位自动补);效期判断与剩余天数自算序日不受时区影响;UTS→Kotlin 编译通过,126 项核心逻辑测试通过。
平台兼容性
uni-app
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | √ | - | - | √ | × | √ | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
szhzy-gs1-barcode
把 GS1 条码内容(GS1-128 / GS1 DataMatrix / GS1 QR / DataBar 解出来的文本)按应用标识符(AI) 拆成结构化字段,并把 GTIN/SSCC/GLN 的校验位、日期合法性、长度、重复项一并校验。
给谁用:用 PDA 或扫码枪做仓库收货、产线追溯、医疗器械 UDI 的 uni-app(Vue3)Android 项目。
验证状态
| 项目 | 结果 | 说明 |
|---|---|---|
| UTS → Kotlin 编译 | 通过 | Project demo-gs1 compiled successfully.(HBuilderX 5.33,kotlin 级编译,非仅语法转写) |
| 纯逻辑回归测试 | 通过 | 126 项,失败 0 项 |
| 真机运行验证 | 未执行 | cli launch 编译通过后 Stopped running...,标准基座未切换到本工程,设备未能操作 |
| 真机截图 | 未取得 | 市场图来自 H5 渲染,非真机截图 |
| iOS / 鸿蒙 | 未实现 | 平台声明已标不支持 |
编译期真实修掉的问题(每条都是 Kotlin 编译器报的,不是猜的):
String.substring在 Kotlin 侧只接受Int,而.length与算术结果是Number→ 统一走内部substr2/substr1(内部.toInt());let valueEnd = s.length被推断成Int,后面赋Number报Assignment type mismatch→ 显式声明let valueEnd: number = s.length;charCodeAt(i)同样要Int→s.charCodeAt(i.toInt())。
它不做什么
本插件不做图像识别。条码怎么扫出来的(系统扫码、uni.scanCode、HMS Scan Kit、PDA 广播)
不归它管,它只处理已经解出来的那串文本。这样定位的好处是:不占相机、不要权限、不吃安装包体积。
快速开始
import { parseBarcode, parseUdiCode, buildBarcode } from '@/uni_modules/szhzy-gs1-barcode'
// 1) 解析(传扫码拿到的字符串)
const r = parseBarcode({ code: scanText })
if (r.ok) {
r.fields.gtin // '06901234567892'
r.fields.lot // 'L2026A'
r.fields.expiry // '2026-12-31'
r.fields.quantity // '120'
r.readable // '(01)06901234567892 (17)2026-12-31 (10)L2026A (30)120'
} else {
r.code // 'CHECK_DIGIT' / 'AI_UNKNOWN' / 'DATE_INVALID' ...
r.issues // ['(01) 校验位应为 2,实际是末位 3']
}
// 2) 医疗器械 UDI
const udi = parseUdiCode({ code: scanText })
udi.di // UDI-DI
udi.diType // 'GTIN' | 'GIAI'
udi.pi // [{ ai: '17', title: '有效期', text: '2027-03-15' }, ...]
// 3) 反向生成(做标签、写二维码)
const b = buildBarcode({
items: [
{ ai: '01', value: '0690123456789' }, // 少一位校验位会自动补,并记一条说明
{ ai: '17', value: '2026-12-31' }, // 日期自动转 YYMMDD
{ ai: '10', value: 'L2026A' } // 变长字段后自动补 FNC1(0x1D)
]
})
b.elementString // '01069012345678921726123110L2026A'(末尾变长字段不补分隔符)
API
| 函数 | 说明 |
|---|---|
parseBarcode({ code }) |
解析。返回 { ok, code, message, source, hasFnc1, readable, elements[], fields{}, issues[] } |
parseUdiCode({ code }) |
UDI 拆分。返回 { ok, code, message, diType, di, pi[], readable, fields, issues } |
buildBarcode({ items }) |
由字段生成。返回 { ok, code, message, elementString, readable, issues } |
checkCode({ value }) |
校验位计算/校验。返回 { ok, length, checkDigit, valid, fixed } |
convertDate({ value, to }) |
yyyy-MM-dd ↔ YYMMDD(to 取 gs1 或 text) |
checkExpiry({ expiry, today, warnDays }) |
{ expired, days, level: expired/warning/ok/unknown } |
listAiTable() |
内置 AI 表全集,用于做"支持字段"页 |
getSeparator() / getCodeText(code) / getVersion() |
分隔符常量 / 错误码中文 / 版本 |
所有函数返回统一信封 { ok, code, message, ... },不抛异常;code 取值见下表。
支持的输入形态
| 形态 | 例子 | 说明 |
|---|---|---|
| 带 FNC1 | 0106901234567892 + 17 + 261231 + 10 + L2026A + \x1D + 30 + 120 |
原生扫描串,变长字段以 GS 结尾 |
| 无分隔符 | 01069012345678921726123110L2026A |
部分解码器会吃掉 GS,靠 AI 定长规则推算 |
| 括号格式 | (01)06901234567892(17)261231(10)L2026A |
人眼可见的标签文本 |
| 带 AIM 前缀 | ]C10106901234567892… |
自动清掉 ]C1 / ]Q3 |
错误码
| code | 含义 | 建议处理 |
|---|---|---|
OK |
成功 | — |
EMPTY |
输入为空 | 检查扫码回调是否拿到内容 |
AI_UNKNOWN |
含未收录的 AI | 核对码制;需要时联系作者补 AI 表 |
VALUE_LENGTH |
值长度不符 | 通常是码被截断或拼接口径不对 |
CHECK_DIGIT |
校验位不通过 | 码磨损、重复拼接,或根本不是 GS1 码 |
DATE_INVALID |
日期不是合法年月日 | 拒绝入库,让人工核对 |
NOT_NUMERIC |
该是数字的位置有字母 | 码制选错(例如把普通 Code128 当 GS1-128 扫) |
DUPLICATE_AI |
同一 AI 出现两次 | 常见于扫码枪双触发,去重即可 |
PAREN_UNBALANCED |
括号格式不闭合 | 标签文本被破坏了 |
NO_DEVICE_ID |
不是 UDI 载体 | 缺少 (01) 或 (8004),按普通条码处理 |
内置 AI(节选)
标识类:00 SSCC、01 GTIN、02 内含 GTIN、10 批号、11 生产日期、12 到期日期、
13 包装日期、15 最佳食用日期、16 销售截止、17 有效期、20 产品变体、21 序列号、22 HIBCC。
追溯与单据:240 附加产品标识、241 客户物料号、242 定制加工号、250 二级序列号、400 客户订单号。
位置类:410–417 各类 GLN、420 邮编、421 行政区划、422 原产国、423–426 加工国。
资产类:7001 NSN、8003 GRAI、8004 GIAI、8006 ITIP、8010 CPID、8013 GMN、8017/8018 GSRN。
计量类(族,第 4 位是小数位数):310x 净重 kg、320x 净重 lb、330x 毛重 kg、340x 毛重 lb、
350x 面积、360x 体积、390x/392x/393x 金额。
90–99 为厂商内部 AI;完整清单用 listAiTable() 取。
几个容易踩的坑(本插件已处理)
- FNC1 会被吃掉:不少 PDA 广播或
uni.scanCode返回的串里 0x1D 丢了,靠"变长 AI 一直取到结尾"猜会错位。 插件按 AI 定长表推算,只有最后一个变长字段才吃到结尾。 - GS1 日期的世纪:
YY不是直接 20YY。按规范00–49→ 20xx,50–99→ 19xx,否则 1999 年的效期会被算成 2099。 - 校验位权重:从最右位起 3/1 交替,不是从最左位。
- 同一串里 GTIN 和 SSCC 都带校验位,但 GLN 是 13 位、GTIN 是 14 位、SSCC 是 18 位,长度不能混用。
310x的值没有小数点,3103+001250是 1.250 kg;直接当整数会错 1000 倍。
演示工程
demo-gs1/ 是"仓库收货 + UDI 追溯"演示页面:三个示例码(整箱收货 / UDI 器械 / 校验位错),
点一下就出字段、问题和 UDI 拆分。真机运行需自定义基座(标准基座不含第三方 UTS 插件)。
授权
普通授权 / 源码授权双档,见 license.md。插件不包含任何第三方库。

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 13
赞赏 0
下载 12720552
赞赏 1958
赞赏
京公网安备:11010802035340号