DirectSurface UIDirectSurface UI
开始使用
组件/可视化和文档组件

可视化和文档组件 / COMPONENT

Barcode / QRCode

RenderBarcode 用于在 DirectSurface UI 中绘制一维条码和二维码。它不依赖 DOM 组件,编辑模式可直接绘制到 Canvas;打印或 SVG 输出可使用同一套编码逻辑生成 SVG vnode。

文档 READY示例 1
PUBLIC APIRenderBarcode

FUNCTION EXPLORER

可运行示例与完整源码。

这里始终保留组件的主运行入口;文档中的示例用于补充具体功能说明。

LIVE EXAMPLE BARCODE
全屏
正在启动 DirectSurface UI 运行时…

Barcode / QRCode 条码二维码

通用布局能力RenderBarcode 实例统一支持 widthheight、min/max、margin 和槽位对齐;条码绘制使用布局后的实际 size,不要直接修改该结果。详见组件通用布局属性

RenderBarcode 用于在 DirectSurface UI 中绘制一维条码和二维码。它不依赖 DOM 组件,编辑模式可直接绘制到 Canvas;打印或 SVG 输出可使用同一套编码逻辑生成 SVG vnode。

当前支持:

  • code128
  • code39
  • ean13
  • qrcode

历史拼写 ena13 会被兼容归一化为 ean13

LIVE CANVAS可运行组件示例
ON-DEMAND RUNTIME交互式示例将在进入视区时启动避免文档首屏同时初始化多个 Canvas Runtime

API 总览

import {  RenderBarcode,  barcodeToSvgVNode,  measureBarcode,  normalizeBarcodeType,  paintBarcode,  type BarcodeMetrics,  type BarcodeOptions,  type BarcodeType,} from 'ds-ui'
API 类型 用途
RenderBarcode class 在 DirectSurface UI 中绘制一维条码或二维码的 render object。
BarcodeOptions type 条码/二维码配置。
BarcodeType type 支持的编码类型:code128、code39、ean13、ena13、qrcode。
BarcodeMetrics type 测量和有效性结果。
measureBarcode() function 不绘制,仅测量尺寸和校验有效性。
paintBarcode() function 直接向 CanvasRenderingContext2D 绘制。
barcodeToSvgVNode() function 生成打印/SVG 场景可用的 vnode。
normalizeBarcodeType() function 归一化编码类型,未知值回退到 code128。

最小装配顺序是:创建 RenderBarcode({ type, text, width, height })。医疗文档、标签和表单中应明确宽高,避免条码内容变化引起排版跳动。

何时使用

使用 Barcode / QRCode:

  • 医疗腕带、标本标签、申请单号、病历号等一维条码。
  • 移动端扫码、URL、文档定位、患者标识等二维码。
  • 需要在 Canvas 编辑模式和 SVG/打印模式保持一致编码结果。

不要使用:

  • 大量富图形、Logo 二维码、渐变彩色码。当前只支持基础黑白编码绘制。
  • 需要交互识别的扫码器组件。RenderBarcode 只负责显示。
  • 不稳定宽高的表单行内内容。医疗文档中条码区域应给定明确宽高,避免排版跳动。

最小示例

const barcode = new RenderBarcode({  type: 'code128',  text: 'MR202605130001',  width: 180,  height: 56,  showText: true,})

二维码:

const qrcode = new RenderBarcode({  type: 'qrcode',  text: 'https://example.com/patient/123',  width: 96,  height: 96,})

更新值:

const barcode = new RenderBarcode({ type: 'code39', text: 'ABC123' })barcode.setValue('XYZ789')

setValue() 会请求布局,因为不同内容可能改变编码有效性和推荐尺寸。

BarcodeType

type BarcodeType = 'ean13' | 'ena13' | 'code39' | 'code128' | 'qrcode'
类型 说明 内容限制
code128 默认类型。当前实现是 Code 128-B。 ASCII 32-127。中文等非 ASCII 内容无效。
code39 Code 39。 0-9A-Z、空格、- . $ / + %。输入会转大写。
ean13 EAN-13 商品码。 12 或 13 位数字;13 位时校验位必须正确。
ena13 兼容历史拼写。 等同 ean13
qrcode 二维码。 使用内置 qrcodegen 编码,纠错等级固定为 MEDIUM

未知 type 会归一化为 code128

const type = normalizeBarcodeType('unknown')

BarcodeOptions

interface BarcodeOptions {  type?: BarcodeType | string  text?: string  width?: number  height?: number  foreground?: string  background?: string  showText?: boolean  quietZone?: number}
参数 类型 默认值 说明
type BarcodeType | string 'code128' 编码类型。未知值按 code128 处理。
text string '' 待编码文本。
width number 一维 120,二维码 48 绘制宽度。最小归一化为 1。
height number 一维 48,二维码跟随宽度 绘制高度。最小归一化为 1。
foreground string '#000' 条/模块颜色。
background string '#fff' 背景颜色。
showText boolean true 一维码是否在底部绘制可读文本。二维码忽略该项。
quietZone number 10 一维码左右静区模块数。二维码固定内部 border 为 2 个模块。

foregroundbackground 当前是 Canvas/SVG 可接受的颜色字符串,不做主题 token 解析。

RenderBarcode 属性和方法

API 类型 说明
type BarcodeOptions['type'] 当前类型。
text string 当前编码文本。
barcodeWidth number | undefined 显式宽度。来自 options.width
barcodeHeight number | undefined 显式高度。来自 options.height
foreground string | undefined 前景色。
background string | undefined 背景色。
showText boolean | undefined 是否显示一维码文本。
quietZone number | undefined 一维码静区。
setValue(text) void 更新文本并请求布局。
debugState() BarcodeMetrics 返回当前测量和有效性信息。

如果运行时直接改 typebarcodeWidthbarcodeHeight 等属性,应由调用方请求布局或重绘;只有 setValue() 内置了布局请求。

BarcodeMetrics

interface BarcodeMetrics {  width: number  height: number  valid: boolean  type: 'ean13' | 'code39' | 'code128' | 'qrcode'  message?: string}

measureBarcode(options) 会返回同样结构,适合在排版前预估尺寸和有效性:

const metrics = measureBarcode({  type: 'ean13',  text: '690123456789',  width: 120,  height: 48,}) if (!metrics.valid) {  console.warn(metrics.message)}

注意:BarcodeMetrics 不暴露内部 modules,避免业务依赖编码内部结构。

Canvas 绘制

底层绘制函数:

const canvas = document.createElement('canvas')const ctx = canvas.getContext('2d')! const metrics = paintBarcode(ctx, 10, 20, {  type: 'code128',  text: 'MR-001',  width: 180,  height: 48,})

行为:

  • 返回 BarcodeMetrics
  • 有效内容绘制背景和条/模块。
  • 无效内容绘制占位框:一维码显示 CODE,二维码显示 QR
  • 不抛出编码异常;错误信息放在 metrics.message

RenderBarcode.performPaint() 会把当前布局尺寸作为 width/height 传给 paintBarcode(),因此 Canvas 绘制结果和实际布局尺寸一致。

SVG / 打印输出

打印或 SVG 场景使用:

const vnode = barcodeToSvgVNode({  type: 'qrcode',  text: 'MR-001',  width: 40,  height: 40,})

barcodeToSvgVNode() 返回 snabbdom 风格 vnode:

  • 有效一维码生成 path,可选 text
  • 有效二维码生成 path
  • 无效内容生成占位 svg
  • viewBoxwidthheight 与测量结果一致。

医疗编辑器的 Canvas 模式使用 paintBarcode(),打印/SVG 模式使用 barcodeToSvgVNode(),两者共享编码和测量逻辑。

尺寸和排版

默认尺寸:

类型 默认宽度 默认高度
一维码 120 48
二维码 48 widthheight 推导

尺寸规则:

  • widthheight 最小归一化为 1。
  • 一维码 showText !== false 时,底部预留约 14px 绘制可读文本。
  • 二维码使用 min(width, height) 计算方形模块区域,并在剩余空间中居中。
  • 二维码内部 border 固定为 2 个模块。
  • RenderBarcode.performLayout() 会先 measureBarcode(),再通过父约束 constrainSize() 得到最终尺寸。

医疗文档中建议显式设置条码/二维码宽高。二维码在病历数据元中通常应采用等比 resize;一维码可以允许宽高分别调整。

错误处理

常见无效情况:

类型 无效原因
ean13 不是 12/13 位数字,或 13 位校验位不正确。
code39 包含 Code 39 不支持的字符。
code128 包含 ASCII 32-127 以外字符,例如中文。
qrcode 文本无法由内置 qrcodegen 编码。

示例:

const canvas = document.createElement('canvas')const ctx = canvas.getContext('2d')! const metrics = paintBarcode(ctx, 0, 0, {  type: 'code128',  text: '中文',  width: 90,  height: 32,}) if (!metrics.valid) {  state.error = metrics.message}

无效内容会绘制占位,不会抛异常。这能保证病历编辑器和打印流程不中断,但业务层仍应提前校验关键码值。

缓存策略

编码计划内部使用 LRU 缓存:

  • 最大缓存 256 个 plan。
  • 缓存 key 包含类型、文本、宽高、showTextquietZone
  • 命中后会更新最近使用顺序。
  • 超过上限会删除最旧项。

这个缓存属于组件内部优化,不提供公开清理 API。它不缓存 Canvas、图片或 DOM 资源。

医疗编辑器集成

病历数据元 data-ele-barcode 使用同一套能力:

  • 布局阶段通过 measureBarcode() 得到非零 render 尺寸。
  • Canvas 编辑模式通过 paintBarcode() 绘制。
  • SVG/打印模式通过 barcodeToSvgVNode() 输出。
  • props.type 支持 ean13ena13code128code39qrcode
  • props.text 是编码文本。
  • props.widthprops.height 是文档内占位尺寸。

因此,编辑显示和打印输出不会走两套编码规则。

性能边界

  • 一维码编码和绘制复杂度与文本长度、模块数相关。
  • 二维码编码复杂度由 qrcodegen 决定,绘制复杂度与二维码模块数相关。
  • 大量重复码值会受益于内部 plan 缓存。
  • 高频更新 text 会触发布局,应避免在动画或输入过程中不断重建条码。
  • 大批量打印建议复用测量结果或让文档布局缓存承担重复计算。

常见问题

为什么 code128 不能显示中文?

当前实现是 Code 128-B,只支持 ASCII 32-127。中文文本应使用二维码,或先由业务编码成 ASCII 标识。

为什么 ean13 输入 12 位也有效?

12 位输入会自动计算第 13 位校验码;13 位输入会校验最后一位。

二维码纠错等级能配置吗?

当前固定使用 qrcodegen.QrCode.Ecc.MEDIUM,没有公开配置项。

quietZone 对二维码有效吗?

quietZone 只影响一维码左右静区。二维码使用固定 2 模块 border。

无效内容会不会抛异常?

不会。测量和绘制都会返回 valid: false,并绘制占位提示。业务可以读取 message 做校验提示。

Canvas 和 SVG 会不会不一致?

不会刻意走两套规则。paintBarcode()barcodeToSvgVNode() 都基于同一个 createBarcodePlan() 结果。

相关文档