2026-06-14 03:16:39 +08:00
2026-06-12 19:34:27 +08:00
2026-06-14 03:16:39 +08:00
2026-06-12 19:34:27 +08:00
2026-06-12 19:34:27 +08:00
2026-06-12 22:09:49 +08:00
2026-06-12 19:34:27 +08:00
2026-06-12 19:34:27 +08:00
2026-06-12 19:34:27 +08:00
2026-06-13 13:51:02 +08:00
2026-06-12 19:34:27 +08:00
2026-06-12 19:34:27 +08:00

Label Designer

标签批量设计与排版工具:可视化编辑标签模板、导入 Excel 数据、预览整页排版并导出 PDF。

模板以 JSON 保存,导出文件扩展名为 .ladLabel Application Data


快速开始

npm install
npm run dev      # 开发服务器,默认 http://localhost:3000
npm run build    # 生产构建
npm run preview  # 预览构建结果

模板文件概览

一个模板描述单张标签的外观与排版参数。批量数据Excel 行)在导出阶段关联,不写入模板 JSON

最小合法结构

导入外部模板时JSON 至少包含:

字段 类型 说明
width number 标签宽度 (mm)
height number 标签高度 (mm)
elements array 元素列表

完整根对象 LabelTemplate

字段 类型 必填 说明
id string 模板唯一 ID应用内自动生成
name string 模板显示名称
width number 标签画布宽度 (mm)
height number 标签画布高度 (mm)
elements TemplateElement[] 标签上的所有元素
variableList string[] 声明的变量名列表(统一管理)
variableDefaults Record<string, string> 设计预览用默认值,变量名 → 文本
paper PaperConfig 纸张排版;缺省时使用 A4 默认配置
cutLine CutLineConfig PDF 裁切参考线;缺省时启用灰色虚线

坐标与单位

  • 所有尺寸、位置、边距、间距:毫米 (mm)
  • 字号:磅 (pt)
  • 元素坐标 (x, y) 为相对标签画布左上角的距离
  • 旋转 rotation:顺时针角度(度),默认 0

变量与占位符

语法

在元素的 content 中使用 {变量名} 引用数据。导出时由 Excel 列映射或默认值填充。

表格元素的变量写在各单元格的 tableCells["行,列"].content 中(见下文 表格 一节),同样参与变量汇总与数据映射。

占位符 说明
{变量名} 普通变量,如 {货位编号}{物料名称}
{#INDEX} 内置占位符:当前数据行在导入数据中的 1-based 序号(第 1 行 → 1

变量名规则:

  • 写在花括号内,不含 }
  • #INDEX reserved不要作为自定义变量名
  • 可在 variableList 中预先声明;也会从 content表格单元格 content 与显示条件中自动汇总

导出时的变量映射(非模板字段)

导出 Excel 时,每个变量需关联数据源,映射关系保存在浏览器本地,不在模板 JSON 内

映射值 含义
Excel 列名 取该列单元格值
__use_default__ 使用模板 variableDefaults 中的默认值
__use_row_index__ 使用数据序号(与 {#INDEX} 相同1-based

列名与变量名相同时会自动匹配。


元素 TemplateElement

每个元素是标签上的一个图层,按数组顺序从下到上绘制。

通用字段

字段 类型 说明
id string 元素唯一 ID
type 'text' | 'barcode' | 'qrcode' | 'image' | 'table' 元素类型
name string 图层名称(设计器显示用)
x, y number 位置 (mm)
width, height number 尺寸 (mm)
rotation number 旋转角度,默认 0
content string 静态文本或 {变量} 组合
fontFamily 'sans' | 'serif' | 'mono' 字体族
backgroundColor string 背景色,如 #fffffftransparent
backgroundOpacity number 背景不透明度 0100
padding number 内边距 (mm),四边统一
paddingTop/Right/Bottom/Left number 分边内边距,覆盖 padding
borderWidth number 边框线宽 (mm)0 为无边框
borderColor string 边框颜色
borderWidthTop/Right/Bottom/Left number 分边边框宽度
borderColorTop/Right/Bottom/Left string 分边边框颜色
borderRadius number 圆角半径 (mm)
borderRadiusTL/TR/BR/BL number 分角圆角
borderRadiusCorners object 指定哪些角圆角,如 { "tl": true, "tr": true }
locked boolean 锁定后设计器不可拖动

值提取(text / barcode / qrcode / image / 表格单元格 均有效)

变量替换完成后的完整 content 字符串 做提取(先替换 {变量},再提取)。

字段 类型 说明
textExtractMode 'none' | 'split' | 'prefix' | 'suffix' 提取方式;缺省且存在 textSplitDelimiter 时视为 split
textSplitDelimiter string 分隔符,如 -
textSplitIndex number 按分隔符拆分后取第 N 段(从 1 开始),段数不足则为空
textExtractLength number 前 N / 后 N 位时的位数

提取前会对完整内容 trim() 去除首尾空格。

示例content: "ABC-{货位编号}",货位编号 = A-1-2-3
→ 替换后 ABC-A-1-2-3 → 分隔符 -、第 3 段 → 显示 1

显示前后缀(仅 type: "text"

在值提取 之后 追加,仅影响显示,不参与「内容值」显示条件判断。

字段 类型 说明
textDisplayPrefix string 前缀字符,如 ¥
textDisplaySuffix string 后缀字符,如

显示控制

字段 类型 说明
visibilityMode 'always' | 'conditional' 始终显示 / 按条件显示
visibilityRules VisibilityRule[] 条件列表,全部满足才显示

VisibilityRule

字段 类型 说明
target 'variable' | 'content' 条件对象:变量值 或 本元素内容值(提取后、不含前后缀)
variable string target=variable 时的变量名
operator 见下表 比较运算符
value string gt / lt / eq / neq 时的比较目标
operator 含义
empty 为空
not_empty 不为空
gt 大于(数值优先比较,否则字符串)
lt 小于
eq 等于
neq 不等于

文本元素 type: "text"

字段 类型 默认值 说明
fontSize number 字号 (pt)
textAlign 'left' | 'center' | 'right' 水平对齐
verticalAlign 'top' | 'middle' | 'bottom' middle 垂直对齐
wordWrap boolean true 自动换行
textWritingMode 'horizontal' | 'vertical' horizontal 排列方向
fontWeight 'normal' | 'bold' 粗体
fontStyle 'normal' | 'italic' normal 斜体
textUnderline boolean 下划线
textLineThrough boolean 删除线
textScaleX, textScaleY number 1 水平/垂直拉伸
letterSpacing number 字间距 (mm)
textColor string 文字颜色
textFormat 'text' | 'number' | 'percent' | 'currency' text 显示格式
decimalPlaces number 2 数值/百分比/货币的小数位
numberPartDisplay 'full' | 'integer' | 'fraction' full 数值拆分显示(如价格拆成整数与小数两部分)

数值格式作用于每个 {变量} 替换值;提取与前后缀见上文顺序。


条形码 type: "barcode"

字段 类型 说明
barcodeFormat 'CODE128' | 'CODE39' | 'EAN13' | 'ITF' 码制
showText boolean 是否在条码下方显示可读文本
content string 条码数据,通常为 {变量}

输出模式下内容为空则不渲染该元素。


二维码 type: "qrcode"

字段 类型 说明
content string 二维码内容URL、文本等

二维码元素宽高相等(设计器约束)。内容为空时不渲染。


图片 type: "image"

字段 类型 说明
content string 图片 URL、data: URI{变量}
imageFit 'contain' | 'cover' | 'fill' 缩放方式,默认 contain

表格 type: "table"

表格由行数、列数及各行高、各列宽定义网格;单元格可单独设置内容与文本样式,支持合并。

元素级 content 对表格通常留空;单元格内容默认为空,在 tableCells 中按坐标单独设置。

表格结构字段

字段 类型 默认值 说明
tableRows number 3 行数 (150)
tableCols number 3 列数 (150)
tableRowHeights number[] 各行高度 (mm),长度须等于 tableRows
tableColWidths number[] 各列宽度 (mm),长度须等于 tableCols
tableBorderWidth number 0.2 单元格网格线宽 (mm)0 时不绘制网格线
tableBorderColor string #374151 网格线颜色
tableCells Record<string, TableCellData> 单元格数据,键为 "行,列"从 0 开始

尺寸关系

  • 内容区(网格区域)= 元素宽高减去 padding
  • sum(tableRowHeights) = 内容区高度
  • sum(tableColWidths) = 内容区宽度
  • 增大内边距时,元素宽高会自动增大以保持行高/列宽不变

拖拽缩放表格四角时,各行高、各列宽会 等比缩放

TableCellDatatableCells 的值)

字段 类型 说明
content string 单元格文本或 {变量};缺省为空
mergeAnchor { row, col } 被合并单元格指向主单元格坐标
rowSpan number 主单元格合并行数,默认 1
colSpan number 主单元格合并列数,默认 1
fontSize number 字号 (pt),缺省继承元素级
fontFamily 'sans' | 'serif' | 'mono' 字体
textAlign 'left' | 'center' | 'right' 水平对齐
verticalAlign 'top' | 'middle' | 'bottom' 垂直对齐
fontWeight 'normal' | 'bold' 粗体
fontStyle 'normal' | 'italic' 斜体
textUnderline boolean 下划线
textLineThrough boolean 删除线
textScaleX, textScaleY number 水平/垂直拉伸
letterSpacing number 字间距 (mm)
textWritingMode 'horizontal' | 'vertical' 排列方向
textColor string 文字颜色
backgroundColor string 单元格背景色
wordWrap boolean 自动换行
textFormat 同文本元素 显示格式
decimalPlaces number 小数位数
numberPartDisplay 同文本元素 数值拆分显示
textExtractMode 同值提取字段 对该单元格 content 生效
textDisplayPrefix / textDisplaySuffix string 显示前后缀

未在 tableCells 中声明的坐标视为空白单元格,使用元素级默认字体/对齐等绘制属性。

合并单元格

  • 主单元格(左上角)存 rowSpan / colSpan
  • 被合并的从属单元格存 mergeAnchor: { row, col } 指向主单元格
  • 合并区域内仅主单元格参与内容与样式;渲染时内部网格线自动省略

表格示例片段

{
  "id": "el_table",
  "type": "table",
  "name": "明细表",
  "x": 2,
  "y": 2,
  "width": 66,
  "height": 20,
  "content": "",
  "fontSize": 9,
  "textAlign": "center",
  "verticalAlign": "middle",
  "fontWeight": "normal",
  "fontFamily": "sans",
  "barcodeFormat": "CODE128",
  "showText": false,
  "tableRows": 2,
  "tableCols": 3,
  "tableRowHeights": [6, 6],
  "tableColWidths": [22, 22, 22],
  "tableBorderWidth": 0.2,
  "tableBorderColor": "#374151",
  "tableCells": {
    "0,0": { "content": "物料", "fontWeight": "bold" },
    "0,1": { "content": "数量", "fontWeight": "bold" },
    "0,2": { "content": "货位", "fontWeight": "bold" },
    "1,0": { "content": "{物料名称}" },
    "1,1": { "content": "{数量}" },
    "1,2": { "content": "{货位编号}" }
  }
}

合并 2×2 区域示例(主单元格 "0,0"rowSpan: 2colSpan: 2

"tableCells": {
  "0,0": { "content": "标题", "rowSpan": 2, "colSpan": 2 },
  "0,1": { "mergeAnchor": { "row": 0, "col": 0 } },
  "1,0": { "mergeAnchor": { "row": 0, "col": 0 } },
  "1,1": { "mergeAnchor": { "row": 0, "col": 0 } }
}

纸张排版 PaperConfig

控制标签如何排列到 PDF 页面上(每模板独立保存)。

字段 类型 说明
type 'A4' | 'A5' | 'A6' | 'custom' 纸张规格
width, height number 纸张尺寸 (mm);预设规格可省略自定义值
orientation 'portrait' | 'landscape' 纵向 / 横向
marginTop/Right/Bottom/Left number 页边距 (mm)
columnGap, rowGap number 标签横向 / 纵向间距 (mm)
flow 'left-right-top-bottom' | 'top-bottom-left-right' 标签填充顺序

默认 paper(未指定时)

{
  "type": "A4",
  "width": 210,
  "height": 297,
  "orientation": "portrait",
  "marginTop": 10,
  "marginRight": 10,
  "marginBottom": 10,
  "marginLeft": 10,
  "columnGap": 2,
  "rowGap": 2,
  "flow": "left-right-top-bottom"
}

裁切线 CutLineConfig

PDF 中标签之间的裁切参考线(预览与导出一致)。

字段 类型 说明
enabled boolean 是否显示
style 'dashed' | 'solid' 线型
width number 线宽 (mm),默认 0.1
color string 颜色,默认 #cccccc

完整示例

{
  "id": "demo_label_001",
  "name": "货位标签示例",
  "width": 70,
  "height": 40,
  "variableList": ["货位编号", "物料名称", "批次号"],
  "variableDefaults": {
    "货位编号": "A-01-05",
    "物料名称": "示例物料",
    "批次号": "2026061101"
  },
  "paper": {
    "type": "A4",
    "width": 210,
    "height": 297,
    "orientation": "portrait",
    "marginTop": 10,
    "marginRight": 10,
    "marginBottom": 10,
    "marginLeft": 10,
    "columnGap": 2,
    "rowGap": 2,
    "flow": "left-right-top-bottom"
  },
  "cutLine": {
    "enabled": true,
    "style": "dashed",
    "width": 0.1,
    "color": "#cccccc"
  },
  "elements": [
    {
      "id": "el_title",
      "type": "text",
      "name": "货位前缀",
      "x": 2,
      "y": 2,
      "width": 66,
      "height": 8,
      "content": "货位:",
      "fontSize": 9,
      "fontWeight": "bold",
      "textAlign": "left",
      "fontFamily": "sans",
      "barcodeFormat": "CODE128",
      "showText": false,
      "textColor": "#333333"
    },
    {
      "id": "el_location",
      "type": "text",
      "name": "货位段",
      "x": 18,
      "y": 2,
      "width": 20,
      "height": 8,
      "content": "{货位编号}",
      "fontSize": 10,
      "fontWeight": "bold",
      "textAlign": "left",
      "fontFamily": "mono",
      "barcodeFormat": "CODE128",
      "showText": false,
      "textExtractMode": "split",
      "textSplitDelimiter": "-",
      "textSplitIndex": 2,
      "visibilityMode": "conditional",
      "visibilityRules": [
        {
          "target": "content",
          "variable": "",
          "operator": "not_empty"
        }
      ]
    },
    {
      "id": "el_name",
      "type": "text",
      "name": "物料名称",
      "x": 2,
      "y": 12,
      "width": 66,
      "height": 10,
      "content": "{物料名称}",
      "fontSize": 8,
      "fontWeight": "normal",
      "textAlign": "left",
      "fontFamily": "sans",
      "barcodeFormat": "CODE128",
      "showText": false,
      "wordWrap": true
    },
    {
      "id": "el_barcode",
      "type": "barcode",
      "name": "条码",
      "x": 2,
      "y": 24,
      "width": 40,
      "height": 14,
      "content": "{货位编号}",
      "fontSize": 8,
      "textAlign": "center",
      "fontWeight": "normal",
      "fontFamily": "mono",
      "barcodeFormat": "CODE128",
      "showText": true,
      "textExtractMode": "suffix",
      "textExtractLength": 8
    },
    {
      "id": "el_qr",
      "type": "qrcode",
      "name": "二维码",
      "x": 48,
      "y": 22,
      "width": 18,
      "height": 18,
      "content": "https://example.com/{货位编号}",
      "fontSize": 8,
      "textAlign": "center",
      "fontWeight": "normal",
      "fontFamily": "sans",
      "barcodeFormat": "CODE128",
      "showText": false
    }
  ]
}

说明:barcodeFormatshowText 在所有元素类型上为历史 schema 要求字段,文本/二维码/图片元素也需填写(常用 CODE128 + showText: false)。


内容解析顺序(导出 / 预览)

对单个元素,最终显示值按以下顺序计算:

  1. content 中的 {变量} 替换为数据行值(文本元素可对每个变量做数值格式化;表格对每格 tableCells[*].content 同样处理)
  2. 对完整字符串做 值提取trim → 分隔符 / 前 N / 后 N
  3. 文本元素及 表格单元格 追加 显示前后缀textDisplayPrefix / textDisplaySuffix
  4. 根据 显示控制 决定是否绘制该元素

表格单元格 content 为空时不绘制该格文字;网格线仍按 tableBorderWidth 绘制(为 0 时不显示)。


导入 / 导出模板

操作 说明
应用内导出 生成 .lad JSON 文件
应用内导入 校验 widthheightelements 后追加到模板库
本地存储 浏览器 localStoragelabel_templates_list_v2

导入时会执行 normalizeTemplate:补全默认 papercutLine,并移除已废弃的数据源字段。


导出 PDF 流程(与模板的关系)

  1. 选择模板 → 设计标签(编辑 JSON 中的 elements 等)
  2. 导入 Excel → 配置 变量列映射(非模板部分)
  3. 设置纸张排版、数据范围、裁切线(排版参数来自模板 paper / cutLine
  4. 预览确认 → 导出 PDF

PDF 每页按 paper 网格排列标签,裁切线可选,标签图由 Canvas 渲染为 PNG/JPEG 嵌入 PDF。


类型定义源码

完整 TypeScript 类型见 src/types.ts(含 TableCellData)。
表格工具函数见 src/tableUtils.ts
模板规范化逻辑见 src/utils.ts 中的 normalizeTemplate

Description
No description provided
Readme 2.5 MiB
Languages
TypeScript 94.6%
CSS 5.3%