SpringBoot+Vue3 固定资产条码闭环:短链二维码 + CODE39 + 扫码建档 + 盘点枪全流程拆解
🌐 演示地址:https://ruoyioffice.com | 📦 源码1·GitHub:ruoyi-office | 📦 源码2·GitCode:ruoyi-office | 📦 源码3·Gitee:ruoyi-office | 💬 微信:17156169080(备注「RuoYi Office」)
领用、调拨、折旧解决的是「账上怎么流转」;真正卡住现场的,往往是另一件事——实物上那张标签,能不能一扫就对上台账。RuoYi Office 资产管理把这条「实物 ↔ 台账」闭环做成了产品能力:短链二维码只做 302、标签双码制(QR 走短链 / CODE39 走编号)、编号预分配支持先贴后建档、移动端扫码四态分流、盘点枪扫码核对。本文不重复全生命周期大段,只拆「条码怎么绑死实物」。

▲ 全景图:配置拼短链 → 预分配/建档生码 → 标签双码打印 → 外部扫码 302 落地 → 登录后四态分流 → 盘点枪扫码核对,实物与台账同一条编号主线
引言:标签贴了,为什么还对不上账?
很多企业上了资产系统,标签也打印了,盘点时仍满场找人:手机扫出来是一串看不懂的 URL,盘点枪扫出来编码失败,仓库先贴了空白标签却没法在系统里「认领」。问题不在「会不会画二维码」,而在码的内容、跳转安全、码制兼容、未建档编号四件事没闭环。
短链乱配域名:二维码写死演示环境域名,本地/客户现场扫码全跳外网;或者把资产明细塞进免登接口,安全与多租户立刻穿帮。
一维码塞 URL:工业盘点枪认 CODE39/CODE128,塞一整段 https://... 直接失败;手机扫二维码又需要可打开的 H5。
先贴后建档断层:批量采购常「先贴标签再录系统」,若系统只支持先建卡再打码,现场只能手写编号再人工对账。
扫码结果只有「有/无」:已建档、预分配未建档、无效、作废四类结果混在一起,前端无法分流到详情或建档页。
| 现状做法 | 直接后果 |
|---|---|
| 二维码里写资产 JSON / 明细接口 | 微信一扫就泄密,租户边界被绕过 |
| 标签只打一维码或只打二维码 | 手机与盘点枪总有一端用不了 |
| 编号与标签分两套体系 | 盘点靠「肉眼读编号再手输」 |
| 扫码只查卡片表 | 空白预分配标签全部报「无效」 |
一句话方案:编号是唯一主键;二维码内容是「可 302 的短链」;一维码内容是「纯编号」;扫码先解析编号,再按四态分流。 全生命周期(领用/折旧等)见系列文 企业资产管理系统设计,本文只讲条码闭环。
一、业务设计:双码制 + 短链只跳转
1.1 核心原则:编号唯一,码只是载体
资产编号(assetCode)是实物与台账的唯一粘合剂。 二维码、一维码、短链路径末段、盘点枪回传内容,最终都要收敛到同一个 assetCode。卡片主键 id 给内部关联用;贴在机器上的永远是编号,不是数据库自增 ID。
因此:
- 生成码时先有编号,再拼短链、再出图;
- 扫码时先
extractAssetCode,再查卡片 / 预分配; - 打印时 QR 与 CODE39 可以内容不同,但指向同一编号。
1.2 双码制:手机看 QR,枪扫 CODE39
标签模板字典 asset_barcode_format:1=二维码,3=CODE39。打印服务按码制分流内容:
| 码制 | 编码内容 | 典型设备 | 设计理由 |
|---|---|---|---|
| 二维码(QR) | {base}/admin-api/asset/s/{assetCode} | 手机微信/相机、APP 扫一扫 | 可打开落地页,便于现场看详情或建档 |
| CODE39 | 纯 assetCode | 工业盘点枪、手持 PDA | 一维码容错与长度受限,禁止塞 URL |
同一张标签可以「上 QR、下 CODE39、中间印编号文字」——三种呈现,一条编号主线。
1.3 短链原则:免登只 302,明细必须登录后取
外部扫码工具(微信、系统相机)不带 Token、不带租户 Header。若短链接口直接返回资产名称、使用人、原值,等于把台账对全世界公开。
正确切分:
外部扫码 → GET /admin-api/asset/s/{assetCode}(@PermitAll + @TenantIgnore)
→ 仅 302 到 H5 落地页(带 assetCode 查询参数)
→ 落地页判断登录 → 调 /asset/barcode/scan(需鉴权)
→ 按 scanResult 跳详情 / 建档 / 提示无效或作废短链控制器故意不返回明细:302 成功则 return null;只有基址解析失败时才退回 JSON,仍是扫描解析结果,不是完整台账导出。
1.4 预分配:空白标签先贴后建档
「围绕条码建档」是仓储现场刚需:先批量占用编号(asset_code_reserve),打印空白标签贴到实物,入库/巡检时再扫码补录名称、分类、原值。预分配与正式建档共用同一套 Redis 序号规则,避免撞号。
预分配状态:
| 状态 | 含义 | 扫码后行为 |
|---|---|---|
| 未建档 | 号已占用,卡未建 | 跳扫码建档页,可带出预设分类/位置/部门 |
| 已建档 | 已关联 cardId | 视同正式资产(通常以卡片为准) |
| 已作废 | 标签作废 | 提示更换标签,禁止建档 |
1.5 扫码四态:前端分流的契约
后端 AssetScanRespVO / 移动端常量约定:
| scanResult | 含义 | 前端动作 |
|---|---|---|
| 1 | 已建档 | 跳资产卡片详情 |
| 2 | 已预分配未建档 | 跳扫码建档,带预设字段 |
| 3 | 无效(未知编号) | 提示「不属于本系统」 |
| 4 | 已作废 | 提示更换标签 |
这套枚举同时服务:微信短链落地、APP 内扫一扫、入库明细扫预分配号、盘点 scanCheck 前的编号提取。
二、系统设计:模块组成与决策表
2.1 条码闭环涉及的子模块
| 子模块 | 关键能力 | 面向角色 |
|---|---|---|
模块配置 asset_config | qr_base_url(含 {auto})、默认标签模板、扫码建档开关、建卡自动生码 | 资产管理员 |
条码服务 AssetBarcodeService | 拼短链、生图、解析扫码、提取编号 | 全模块复用 |
| 短链 Controller | 免登 302 | 外部扫码入口 |
编号预分配 asset_code_reserve | 批量生号、作废、打印计数 | 仓管 / 资产岗 |
| 标签模板 / 打印 | 字段布局、双码内容、ZPL/TSPL 裸指令 | 资产岗 |
| 资产卡片 | 建卡自动/补生成 QR,台账展示码图 | 全员只读 / 管理员维护 |
盘点 scanCheck | 扫码核对明细行、离线同步 | 盘点员 |
| UniApp 扫码页 / 落地页 | 四态分流、登录回跳 | 现场人员 |
2.2 核心设计决策
| 决策点 | 方案 | 理由 |
|---|---|---|
| 短链是否免登 | @PermitAll + @TenantIgnore,只 302 | 外部扫码无 Token;明细仍走登录态接口 |
| 短链是否返回 JSON 明细 | 默认不返回,成功即 redirect | 防止「扫一下泄一台账」 |
| QR 内容 | {origin}/admin-api/asset/s/{code} | 部署无需额外 nginx rewrite(可选用更短 rewrite) |
| 基址配置 | 支持固定域名或 {auto} | 本地扫本地、线上扫线上,避免写死演示域 |
| CODE39 内容 | 只用资产编号 | 盘点枪兼容,避免 URL 超长/非法字符 |
| 未建档标签 | asset_code_reserve 预占号 | 支持先贴后建档 |
| 编号提取 | 无 :// 当纯编号;有 URL 取 path 末段 | 兼容旧标签与短链新标签 |
| 盘点扫码 | extractAssetCode + 范围校验 | 枪扫 CODE39、手机扫 QR 同一套 |
三、PC 端:配置、台账、标签与预分配
3.1 模块配置:短链基址与开关
路径:资产管理 → 模块配置。与条码强相关的字段:
| 配置项 | 作用 |
|---|---|
二维码短链基址 qr_base_url | 拼 QR 内容;{auto} / 空 = 按当前请求访问源动态生成 |
| 默认标签模板 | 打印时默认版式 |
| 允许扫码建档 | 未建档编号是否允许移动端直接建卡 |
| 建档自动生成二维码 | 新建卡片后是否自动 generateCardQrCode |
部署时建议把历史演示域名批量改为 {auto},避免新环境继续扫到旧演示站:
-- 短链基址改为 {auto}:按当前访问域名生成
-- 正式环境若需固定公网域名,可在「资产管理 → 模块配置」改回 https://xxx
UPDATE `asset_config`
SET `qr_base_url` = '{auto}'
WHERE `deleted` = b'0'
AND (`qr_base_url` IS NULL
OR `qr_base_url` = ''
OR `qr_base_url` LIKE '%demo.ruoyioffice.com%');
▲ 模块配置:qr_base_url 填 {auto} 或固定公网域名;扫码建档与自动生码开关同页
3.2 资产台账:身份区展示双码
卡片详情「身份区」展示资产编号、QR 图、一维码内容。历史数据若 qr_code 为空,列表支持批量补生成;单卡也可点「生成二维码」。

▲ 台账详情身份区:编号 + QR 预览;打印标签时再按模板决定 CODE39 内容
3.3 标签模板与打印
标签模板维护尺寸、字段(编号/名称/分类/位置等)、码制、可选 ZPL/TSPL 裸指令。打印接口返回每张标签的:
qrContent:短链(保证出码)barcodeContent:按码制解析后的实际编码串fieldValues:模板字段取值rawCommand:热敏打印机指令(可选)
正式卡打印与预分配空白标签共用同一套 resolveBarcodeContent:CODE39 → 编号,否则 → 短链。

▲ 标签打印预览:上方二维码(短链)、下方 CODE39(纯编号),中间可读编号文字
3.4 编号预分配批次
路径:资产管理 → 编号预分配。一次生成一批号(批次号如 B20260728143000),可选同步生成 QR 图片;支持按批次打印空白标签、作废未建档号、查看打印次数。
典型现场节奏:
- PC 批量预分配 50 个号并打印空白标签;
- 仓管把标签贴到到货设备;
- 入库或巡检时手机扫码 → 状态 2 → 补录建档;
- 或入库单明细扫预分配号,转固时沿用该编号(避免生成第二张卡)。

▲ 预分配列表:批次号、编号、状态(未建档/已建档/已作废)、打印次数
四、移动端扫码链路:从微信一扫到四态分流
4.1 两条入口,同一解析契约
| 入口 | 是否已登录 | 路径 |
|---|---|---|
| 微信/相机扫标签 QR | 通常未登录 | 短链 302 → /app/#/pages-asset/scan/landing/index?assetCode= |
| APP 内「扫码」页 | 已登录 | 摄像头/相册得到内容 → GET /asset/barcode/scan |
落地页 excludeLoginPath: true,避免路由守卫把 redirect 吞掉;页面内自行判断 Token:无登录则 toLoginPage 并带回跳,有登录再调解析接口。
4.2 落地页分流逻辑
落地页根据 scanResult:
- 已建档 → 资产详情;
- 预分配 → 建档页,并带上
categoryId/locationId等预设; - 作废 / 无效 → 状态提示 +「去扫码页」。

▲ H5 落地页(竖屏):识别中 → 登录回跳 → 详情或建档
4.3 入库场景:只接受「预分配未建档」
入库明细扫码时有额外约束:已建档号不能再扫进入库行(否则审批通过会造第二张卡);只有 scanResult === 2 才自动建行并绑定预分配编号。这是「条码闭环」与「入库建卡」的衔接点,避免编号漂移。
4.4 盘点场景:枪与手机同一 extract
盘点执行页调用 scanCheck:后端先 extractAssetCode,再校验该编号是否在本盘点单明细范围内,写入实盘位置/状态/照片。离线包同步时同样按编号幂等合并,冲突则记入 conflictCodes。

▲ 盘点扫码:识别编号后命中明细行,回写实盘结果与进度
五、后端核心实现
5.1 短链 Controller:免登 + 免租户 + 只跳转
短链是外部世界进入系统的唯一「裸入口」。注释写得很清楚:不携带 token / tenant-id 时,这里只做编号到移动端页面的 302。
// AssetShortLinkController.java — GET /asset/s/{assetCode}
@GetMapping("/{assetCode}")
@PermitAll
@TenantIgnore
@Operation(summary = "扫码短链跳转", description = "302 跳转到移动端资产详情或建档页")
public CommonResult<AssetScanRespVO> redirect(@PathVariable("assetCode") String assetCode,
HttpServletRequest request,
HttpServletResponse response) throws IOException {
AssetScanRespVO scanRespVO = barcodeService.resolveScan(assetCode);
// 用当前短链请求的访问源拼落地页,避免配置成演示域名后本地仍跳外网
String targetUrl = barcodeService.buildMobileDetailUrl(
assetCode, scanRespVO.getScanResult(), request);
if (StrUtil.isBlank(targetUrl)) {
log.warn("[redirect][编号({}) 无法解析短链基址,返回 JSON]", assetCode);
return success(scanRespVO);
}
response.sendRedirect(targetUrl);
return null;
}要点:resolveScan 在 302 前就会调用——用于决定落地后的业务语义;但响应体在成功 redirect 时为空,浏览器只看到 Location。
5.2 拼短链、拼落地页、{auto} 基址
QR 内容与落地页 URL 是两条地址:QR 指向 API 短链;302 目标指向 UniApp H5 hash 路由。
// AssetBarcodeServiceImpl.java — 拼 QR 内容与 H5 落地页
public static final String SHORT_LINK_PATH = "/admin-api/asset/s/";
@Override
public String buildQrContent(String assetCode) {
if (StrUtil.isBlank(assetCode)) {
return null;
}
String baseUrl = resolveQrBaseUrl(null);
if (StrUtil.isBlank(baseUrl)) {
// 未配置基址且无请求上下文时退化为纯编号:APP 内扫码仍可用
return assetCode;
}
return StrUtil.removeSuffix(baseUrl, "/") + SHORT_LINK_PATH + assetCode;
}
@Override
public String buildMobileDetailUrl(String assetCode, Integer scanResult,
HttpServletRequest request) {
String baseUrl = resolveRequestOrigin(request);
if (StrUtil.isBlank(baseUrl)) {
baseUrl = resolveQrBaseUrl(null);
}
if (StrUtil.isBlank(baseUrl)) {
return null;
}
// UniApp H5 是 hash 模式,深链必须带 #/
return StrUtil.format("{}/app/#/pages-asset/scan/landing/index?assetCode={}",
StrUtil.removeSuffix(baseUrl, "/"), assetCode);
}resolveQrBaseUrl:配置了固定域名则用配置;空或 {auto} 则取 X-Forwarded-Proto/Host 或当前请求 origin。这样同一套二维码生成逻辑在本地与生产都不会「扫错站」。
5.3 生图与卡片回写
建卡或批量补码时:buildQrContent → Hutool 生成 300px PNG → 文件服务落盘 → 回写 asset_card.qr_code / qr_content。
// AssetBarcodeServiceImpl.java — 生成图片并回写卡片
@Override
public String generateQrImage(String qrContent) {
if (StrUtil.isBlank(qrContent)) {
return null;
}
try {
QrConfig qrConfig = QrConfig.create().setWidth(QR_SIZE).setHeight(QR_SIZE).setMargin(1);
byte[] png = QrCodeUtil.generatePng(qrContent, qrConfig);
return fileApi.createFile(png, buildQrFileName(qrContent), "asset/qr", "image/png");
} catch (Exception ex) {
log.error("[generateQrImage][内容({}) 生成二维码失败]", qrContent, ex);
throw exception(ASSET_CARD_QR_GENERATE_FAIL);
}
}
@Override
public String generateCardQrCode(Long cardId) {
AssetCardDO card = cardMapper.selectById(cardId);
if (card == null) {
throw exception(ASSET_CARD_NOT_EXISTS);
}
String qrContent = buildQrContent(card.getAssetCode());
String qrCode = generateQrImage(qrContent);
AssetCardDO updateObj = new AssetCardDO();
updateObj.setId(cardId);
updateObj.setQrCode(qrCode);
updateObj.setQrContent(qrContent);
cardMapper.updateById(updateObj);
return qrCode;
}5.4 标签双码:resolveBarcodeContent
打印时明确「避免把 URL 塞进一维码导致扫枪失败」:
// AssetLabelTemplateServiceImpl.java — 按码制决定编码内容
// 字典 asset_barcode_format:1=二维码 3=CODE39
private String resolveBarcodeContent(AssetLabelTemplateDO template,
String assetCode,
String qrContent) {
if (Objects.equals(template.getBarcodeFormat(), 3)) {
return assetCode;
}
return qrContent;
}
// 正式卡打印片段(同文件 buildCardLabels)
item.setQrContent(StrUtil.blankToDefault(card.getQrContent(),
barcodeService.buildQrContent(card.getAssetCode())));
item.setQrCode(card.getQrCode());
// CODE39 编码资产编号;二维码仍用短链
item.setBarcodeContent(resolveBarcodeContent(template, item.getAssetCode(), item.getQrContent()));预分配空白标签走同一逻辑,只是 blank=true,字段除编号外留空占位,保证与正式标签排版一致。
5.5 扫码解析四态 + 编号提取
// AssetBarcodeServiceImpl.java — resolveScan + extractAssetCode
@Override
public AssetScanRespVO resolveScan(String scanContent) {
AssetScanRespVO respVO = new AssetScanRespVO();
String assetCode = extractAssetCode(scanContent);
respVO.setAssetCode(assetCode);
if (StrUtil.isBlank(assetCode)) {
respVO.setScanResult(AssetScanRespVO.RESULT_UNKNOWN);
respVO.setMessage("无法从条码中识别资产编号");
return respVO;
}
AssetCardDO card = cardMapper.selectByAssetCode(assetCode);
if (card != null) {
respVO.setScanResult(AssetScanRespVO.RESULT_FILED);
respVO.setCard(BeanUtils.toBean(card, AssetCardRespVO.class));
return respVO;
}
AssetCodeReserveDO reserve = reserveMapper.selectByAssetCode(assetCode);
if (reserve == null) {
respVO.setScanResult(AssetScanRespVO.RESULT_UNKNOWN);
respVO.setMessage(StrUtil.format("编号 {} 不存在,请确认标签是否属于本系统", assetCode));
return respVO;
}
if (ReserveStatusEnum.CANCELED.getStatus().equals(reserve.getReserveStatus())) {
respVO.setScanResult(AssetScanRespVO.RESULT_CANCELED);
respVO.setMessage(StrUtil.format("编号 {} 已作废,请更换标签", assetCode));
return respVO;
}
respVO.setScanResult(AssetScanRespVO.RESULT_RESERVED);
// ... 回填 reserveId / 预设分类位置部门
return respVO;
}extractAssetCode:无 :// 直接当编号;有 URL 则去掉 query/hash,取 path 最后一段——因此短链改写为 /a/{code} 或保持 /admin-api/asset/s/{code} 都能解析。
5.6 盘点扫码核对
// AssetStocktakeServiceImpl.java — 扫码盘点
@Override
@Transactional(rollbackFor = Exception.class)
public AssetStocktakeItemRespVO scanCheck(AssetStocktakeScanCheckReqVO reqVO) {
AssetStocktakeDO head = validateStocktakeCheckable(reqVO.getStocktakeId());
String assetCode = barcodeService.extractAssetCode(reqVO.getScanContent());
if (StrUtil.isBlank(assetCode)) {
throw exception(ASSET_STOCKTAKE_ITEM_NOT_IN_SCOPE);
}
AssetStocktakeItemDO item =
stocktakeItemMapper.selectByStocktakeIdAndAssetCode(head.getId(), assetCode);
if (item == null) {
throw exception(ASSET_STOCKTAKE_ITEM_NOT_IN_SCOPE);
}
writeCheckResult(head, item, reqVO.getActualLocationId(), reqVO.getActualStatus(),
reqVO.getPhotoUrls(), reqVO.getRemark(), SCAN_SOURCE_QR, null, false);
refreshProgress(head.getId(), item.getUseUserId());
return BeanUtils.toBean(stocktakeItemMapper.selectById(item.getId()),
AssetStocktakeItemRespVO.class);
}枪扫 CODE39 得到纯编号、手机扫 QR 得到短链 URL——进入 scanCheck 后都被还原为 assetCode,再做范围校验。不在盘点范围内的标签直接报错,避免「扫到别的仓库资产却记成本单盘盈」。
预分配批量生号(AssetCodeReserveServiceImpl.createReserveBatch)与正式建档共用 cardService.generateAssetCode()(Redis 序列),写 asset_code_reserve 时可同步 buildQrContent / generateQrImage;图片失败不阻断生号,前端仍可用 qrContent 即时渲染打印。
六、RuoYi Office 创新设计
6.1 「短链只跳转」而不是「短链即接口」
| 传统做法 | 本方案 |
|---|---|
| 免登 GET 直接返回资产 JSON | 免登只 302,明细必须登录后 /barcode/scan |
| 二维码写死业务域名 | {auto} + 302 时跟请求 origin 走 |
| 多租户靠短链里塞 tenantId | 租户在登录会话中解析,短链不加租户明文 |
标签会贴在会议室、走廊等可见区域,扫码工具是不可信客户端——跳转与读数分离,是最低成本的安全边界。
6.2 双码制一张标签打穿「手机 + 枪」
不是两套资产体系,而是同一编号两种编码内容:手机走短链,盘点枪走 CODE39。一套标签模板覆盖两类硬件。
6.3 预分配把「贴标」前移到「建账」之前
传统系统强迫「先有卡再有码」。预分配把编号生命周期拆成:占用 → 打印 → 粘贴 → 扫码建档 / 入库沿用 →(可选)作废。空白标签与正式标签版式一致,避免二次换标。
6.4 四态契约 + 统一编号提取
移动端常量与后端 RESULT_*(1/2/3/4)对齐,落地页 / 扫码页 / 入库扫码复用同一 API。盘点与业务解析共用 extractAssetCode,避免各模块各自 parse URL 导致规则漂移;短链若缩短为 /a/{code},只改生成与提取两侧约定即可。
七、数据结构
| 表 / 对象 | 关键字段 | 说明 |
|---|---|---|
asset_config | qr_base_url、scan_create_enabled、qr_auto_generate、default_label_template_id | 短链基址(含 {auto})、扫码建档与自动生码开关 |
asset_card | asset_code、qr_content、qr_code | 对外编号 + 短链内容 + 码图 URL |
asset_code_reserve | asset_code、batch_no、reserve_status、card_id、预设分类/位置/部门、print_count | 预占号;状态 1 未建档 / 2 已建档 / 3 已作废 |
| 标签模板 | barcode_format、field_config、raw_command_template | 1=QR / 3=CODE39;ZPL/TSPL 用 ${qrContent} 等占位 |
设计要点:编号在卡片与预分配表防重且共用序列;qr_content 与图片分离便于换域重生;短链不含租户明文;盘点明细仍按编号关联,扫码只加速定位行。
八、技术亮点总结
| 设计要点 | 实现方式 | 价值 |
|---|---|---|
| 短链免登 | @PermitAll + @TenantIgnore + 302 | 微信可扫,且不泄台账 |
| 动态基址 | qr_base_url={auto} + Forwarded 头 | 本地/生产一套配置 |
| QR / 落地页 | /admin-api/asset/s/{code} → /app/#/pages-asset/scan/landing/... | 深链稳定,可选 nginx 再缩短 |
| 双码制 | resolveBarcodeContent | 手机 + 盘点枪兼容 |
| 编号提取 | extractAssetCode | 纯号与短链统一 |
| 四态分流 | scanResult 1/2/3/4 | 详情/建档/无效/作废 |
| 预分配 | asset_code_reserve + 共用生号 | 先贴后建档 |
| 建卡生码 | generateCardQrCode | 台账即可见码 |
| 盘点扫码 | scanCheck + 范围校验 | 枪扫即核对 |
| 离线盘点 | syncOfflineItems 幂等/冲突 | 弱网现场可用 |
| 标签指令 | ZPL/TSPL ${} 替换 | 热敏机房可落地 |
九、快速体验
9.1 在线演示
- Web:https://ruoyioffice.com/web/(账号
admin/admin123) - APP / H5:https://ruoyioffice.com/app/
9.2 推荐体验路径(8 步)
- 登录 PC → 资产管理 → 模块配置,确认
qr_base_url为{auto}或你的公网域名; - 打开 编号预分配,生成一小批号并勾选生成二维码;
- 按批次 打印空白标签(预览 QR 短链与 CODE39 编号);
- 用手机扫其中一张 QR:应 302 到 H5 落地页,登录后进入 扫码建档;
- 补全名称等字段完成建档,再扫同一标签:应进入 资产详情;
- 在台账打开该卡,查看身份区二维码;必要时用正式模板再打一张「有名称」标签;
- 创建盘点单纳入该资产,移动端或扫码枪执行 扫码核对;
- 故意扫一张已作废预分配号,确认提示「已作废」而非误建档。
9.3 源码仓库
| 端 | 仓库 |
|---|---|
| 后端 / 前端 / 文档等 | GitHub · GitCode · Gitee |
本地联调提示:短链与落地页都依赖「浏览器能访问到的 origin」。后端与网关、H5 静态资源需在同一对外域名下可访问,否则 302 会跳到打不开的地址。
9.4 系列阅读
- SpringBoot+Vue3 企业资产管理系统设计:建账·领用·调拨·盘点·折旧·处置全生命周期拆解 —— 单据驱动状态与折旧引擎
- 本文 —— 实物标签与台账绑定的条码闭环
常见问题(FAQ)
固定资产二维码短链为什么不直接返回资产详情?
因为微信/系统相机扫码时没有登录态。短链接口若直接吐明细,等于公开台账。RuoYi Office 的做法是短链只 302 到 H5,登录后再调 /asset/barcode/scan 取数并分流。
CODE39 和二维码可以印在同一张资产标签上吗?
可以。模板按码制决定编码内容:二维码用短链,CODE39 用纯资产编号。手机与工业盘点枪可以共用同一套标签。
还没建档能不能先打印标签贴到设备上?
可以。使用 编号预分配:批量占号并打印空白标签,扫码后再建档,或在入库明细扫预分配号沿用该编号转固。
扫码结果 1/2/3/4 分别是什么意思?
1 已建档(去详情),2 已预分配未建档(去建档),3 无效编号,4 已作废。移动端与后端常量保持一致,避免各页面各自解释。
{auto} 会导致本地和演示环境二维码乱跳吗?
不会。生成码时按请求访问源拼基址;短链打开时落地页再跟当前请求 origin。本地扫本地、线上扫线上。若「内网打印、外网扫码」,在模块配置改为固定 https://你的域名。完整部署与现场盘点方案可微信 17156169080(备注「RuoYi Office」)咨询商业版支持。
结语
固定资产条码闭环的本质不是「把二维码图画漂亮」,而是:编号唯一、码制分工、短链不泄密、未建档可预占、扫码结果可分流、盘点枪与手机同解析。 把这六件事焊在同一条 assetCode 主线上,实物上的标签才真正成为台账的延伸,而不是另一本对不上的账。
这种「载体与权限分离、先占号后建档、双码兼容现场硬件」的模式,同样适用于仪器计量标签、工具室借还、门禁资产巡检等「先有物、后补档」的场景。
你们团队现在贴的资产标签,手机和盘点枪是同一套码,还是两套互相翻译?欢迎在评论区交流踩坑经验。
💡 想要体验 RuoYi Office 的强大功能?
🌐 在线演示:https://ruoyioffice.com/web/(账号 admin / admin123)
📦 源码仓库:GitHub | GitCode | Gitee
💬 技术咨询:添加微信 17156169080,备注「RuoYi Office」
⭐ 如果觉得不错,请给个 Star 支持一下!
