npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

template-designer

v0.11.8

Published

模板拖拽设计器组件库

Readme

模板设计器组件库

一个基于Vue 3的可视化模板设计器组件库,支持拖拽、缩放、旋转等操作。

功能特性

  • 🎨 可视化模板设计
  • 📝 文本组件
  • 📊 条形码组件
  • 🔲 二维码组件
  • 🖼️ 图片组件(支持上传)
  • 📐 矩形框组件
  • ➖ 线段组件
  • 🎯 组件拖拽、缩放、旋转
  • 📋 属性面板配置
  • 🖼️ 模板预览导出
  • 🔧 双重组件控制

安装和使用

npm install template-designer
<template>
  <TemplateDesigner 
    :templateData="templateData"
    :config="config"
    :options="{ fields }"
    template-type="lodop"
  />
</template>

<script setup>
import { TemplateDesigner } from 'template-designer'

// templateData必须包含width,height字段且值均大于0
const templateData = ref({
  width: 100,
  height: 30,
  printWidth: 103,
  printHeight: 40,
  items: []
})

const config = ref({
  // 组件显示配置
})

const fields = ref([
  { label: '商品条码', value: 'goodsSn' },
  { label: '商品名称', value: 'goodsName', {
    // 配置动态联动属性  同 /props/(lodop或rfid).js中的propertyPanel配置  可多级
    // 例如
    propertyPanel: {
      // 必选
      prop: 'xxx',
      // 必选
      label: 'xxx',
      // 必选
      type: 'select',
      // 必选
      default: '',
      // 必选 属性布局 full-独占一行 half-半行
      layout: 'full',
      // 可选 是否多选
      multiple: false,
      // 可选 属性描述(label后显示问好图标,hover显示)
      desc: '',
      // 可选 是否隐藏
      hide: false,
      // type为select必选
      options: [
        {
          label: 'xxx',
          value: 'xxx',
          propertyPanel: {
            prop: 'xxx',
            label: 'xxx',
            type: 'select',
            default: '',
            layout: 'full',
            options: [
              ...
            ]
          }
        },
        ...
      ]
    }
  }, ...}
])
</script>

配置说明

双重组件控制功能

功能说明

组件库现在支持双重控制来隐藏/显示组件:

  1. 通过config参数控制
  2. 通过配置文件控制 如果配置文件中没有某个组件的配置,则不展示该组件

属性面板布局控制功能

功能说明

组件库现在支持通过配置文件控制属性面板的布局:

  1. 独占一行layout: 'full')- 属性项占满整行宽度
  2. 占半行layout: 'half')- 属性项占半行宽度,可以并排显示,自动换行
  3. 默认布局 - 根据属性类型自动判断布局方式

使用方法

1. 通过config参数控制

const config = {
  // 隐藏特定组件
  text: { hidden: true },     // 隐藏文本组件
  barcode: { hidden: true },  // 隐藏一维码组件
  image: { hidden: true },    // 隐藏图片组件
  rectangle: { hidden: true }, // 隐藏矩形框组件
  // 设计区域背景 默认rgba(0, 0, 0, .05)  须为css支持的字符
  designBackground: ''
}

// 使用组件
<TemplateDesigner :config="config" />

2. 通过配置文件控制

src/js/config/props/ 目录下创建配置文件,只包含需要显示的组件:

// src/js/config/props/xxx.js
export default {
  text: {
    // 文本组件配置
  },
  barcode: {
    // 一维码组件配置
  }
  ...
}

系统会自动根据 template-type 动态加载对应的配置文件:

// src/js/config/index.js
export async function getPropsConfig(type) {
  try {
    // 直接通过type对应文件名动态导入
    const config = await import(`./props/${type}.js`)
    return config.default
  } catch (error) {
    // 如果指定的配置文件不存在,返回lodop配置作为默认值
    const defaultConfig = await import('./props/lodop.js')
    return defaultConfig.default
  }
}

3. 双重控制示例

<template>
  <TemplateDesigner 
    :template-type="currentTemplateType"
    :config="componentConfig"
  />
</template>

<script setup>
import { ref } from 'vue'

const currentTemplateType = ref('rfid') // 使用rfid配置文件

const componentConfig = ref({
  text: { hidden: false },    // 显示文本组件
  barcode: { hidden: true },  // 隐藏一维码组件
  // 注意:即使config中设置了显示,如果配置文件中没有该组件,仍然不会显示
})

// 切换模板类型
const changeTemplateType = (type) => {
  currentTemplateType.value = type
}
</script>

实际效果

  • LODOP配置:显示所有组件(text, barcode, qrcode, image, rectangle, line)
  • RFID配置:显示所有组件(text, barcode, qrcode, image)

支持的模板类型

  • lodop - 默认配置,包含所有组件(对应 lodop.js
  • rfid - RFID标签配置,包含所有组件(对应 rfid.js
  • 其他任何类型 - 系统会尝试加载 ./props/{type}.js 文件,如果不存在则使用lodop配置作为默认值

组件类型

  • text - 文本组件
  • barcode - 一维码组件
  • qrcode - 二维码组件
  • image - 图片组件
  • rectangle - 矩形框组件
  • line - 线段组件

属性面板布局控制功能

功能说明

组件库现在支持通过配置文件控制属性面板的布局:

  1. 独占一行layout: 'full')- 属性项占满整行宽度
  2. 占半行layout: 'half')- 属性项占半行宽度,可以并排显示,自动换行
  3. 默认布局 - 根据属性类型自动判断布局方式

使用方法

1. 在配置文件中设置布局

// src/js/config/props/rfid.js
export default {
  text: {
    propertyPanel: [
      {
        prop: 'Title',
        label: '标题',
        default: '',
        layout: 'full' // 独占一行
      },
      {
        prop: 'FontName',
        label: '字体名称',
        type: 'select',
        options: [...],
        default: '黑体',
        layout: 'half' // 占半行
      },
      {
        prop: 'FontSize',
        label: '字体大小',
        type: 'number',
        min: 1,
        max: 100,
        default: 10,
        layout: 'half' // 占半行
      }
    ]
  }
}

2. 布局类型说明

  • layout: 'full' - 属性项独占一行,适合文本输入、文件上传等需要更多空间的属性
  • layout: 'half' - 属性项占半行,适合下拉选择、数字输入等紧凑型属性
  • 不设置layout - 系统根据属性类型自动判断:
    • textfiletextarea 类型默认独占一行
    • 其他类型默认占半行

3. 布局效果

  • 独占一行:属性项占满整行宽度,垂直排列
  • 占半行:两个属性项并排显示,自动换行,形成网格布局
  • 响应式:在不同屏幕尺寸下自动调整布局

图片上传

在配置中添加图片上传

// 隐藏特定组件
const config = {
  ...
  image: { request: file => {
    // 上传
    ....
    return url // 上传完的url
  }}
  ...
}

// 使用组件
<TemplateDesigner :config="config" />

注意事项

1、控件中的字段(FieldName)只选中一个值为字符串,如果选中多个则为字符串数组,使用时注意兼容

2、当前模板中控件的旋转中心为控件的中心,每个组件的数据都包含x1,y1,为左上角旋转之后的实时坐标,旋转角度为顺时针

字段替换规则

  • 适用组件:text、barcode、qrcode。
  • FieldName 支持 string 或数组:
    • string:从 printData[key] 取值
    • array:从 printData 逐个取值,使用组件 FieldConnector 连接(默认空格)
  • 覆盖策略:导出前始终用打印数据覆盖组件测试值:
    • text → 覆盖 Text
    • barcode → 覆盖 BarcodeValue
    • qrcode → 覆盖 QRCodeValue

渲染导出工具:renderTemplateToPdfBase64

提供一个独立工具,将“模板数据 + 打印数据”渲染为 PDF 或 PNG,并返回 base64 或 dataURL

导入

import { renderTemplateToPdfBase64 } from 'template-designer'

函数签名

async function renderTemplateToPdfBase64(
  template: object,            // 模板数据(同设计器使用的数据结构)
  printData: Record<string, any>, // 打印数据(key -> value)
  options?: {
    page?: { widthMm?: number; heightMm?: number; marginMm?: number } // (可选)默认打印宽高
    returnType?: 'base64' | 'dataUrl' // (可选)默认 'base64'
    format?: 'pdf' | 'png'            // (可选)默认 'pdf';png 可保留透明背景
    pdf?: {
      orientation?: 'portrait' | 'landscape' // (可选)默认自动
      transparent?: boolean                  // (可选)是否保留透明背景(仅对 pdf 内嵌图像生效)
      quality?: number                       // (可选)0~1(jpeg质量,透明=false 时生效,默认 0.85)
      scale?: number                         // (可选)html2canvas 放大倍数,建议 1.5~2.5
      compress?: boolean                     // (可选)jsPDF 压缩,默认 true
    }
  }
): Promise<string>

基础用法(导出 PDF,返回 base64)

const pdfBase64 = await renderTemplateToPdfBase64(template, printData, {
  page: { widthMm: 103, heightMm: 40 },
  returnType: 'base64',
  pdf: {
    orientation: 'landscape',
    transparent: false, // 若不需要透明,可关闭以减小体积
    quality: 0.8,       // 仅非透明时生效(jpeg质量)
    scale: 2,           // 1.5~2.5 间调节清晰度与体积
    compress: true
  }
})

体积优化建议

  • 不需要透明背景时,transparent=false + quality≈0.8 + scale≈2,可显著减小体积仍保持清晰。
  • 需要极致清晰时提高 scale;若体积过大,适当降低 quality

条形码和二维码生成工具

提供独立的条形码和二维码生成函数,可在组件外部使用。

generateBarcode - 条形码生成

导入

import { generateBarcode } from 'template-designer'

函数签名

async function generateBarcode(
  text: string,                    // 要编码的文本内容
  options?: {
    CodeType?: string              // 条形码格式,可选'CODE128'|'CODE39'|'EAN13'|'EAN8'|'UPC'|'ITF14'|'MSI'|'pharmacode'|'codabar',默认'CODE128'
    width?: number                 // 条形码宽度(毫米),默认50
    height?: number                // 条形码高度(毫米),默认15
    LineColor?: string             // 条形码颜色,默认'#000000'
    background?: string            // 背景色,默认'#ffffff'
    displayValue?: boolean         // 是否显示文本,默认false
    textAlign?: string             // 文本对齐,可选'left'|'center'|'right',默认'center'
    textPosition?: string          // 文本位置,可选'bottom'|'top',默认'bottom'
    textMargin?: number            // 文本边距(毫米),默认2
    font?: string                  // 字体,默认'monospace'
    fontSize?: number              // 字体大小(毫米),默认5
    outputFormat?: string          // 输出格式,可选'png'|'jpeg'|'svg',默认'png'
    quality?: number               // 图片质量(0-1),仅对jpeg有效,默认0.95
    returnDataUrl?: boolean        // 是否返回完整dataUrl,默认true
    dpi?: number                   // DPI值,默认300
  }
): Promise<string>                 // 返回base64格式的图片数据或dataUrl

使用示例

// 基础用法
const barcodeDataUrl = await generateBarcode('1234567890', {
  CodeType: 'CODE128',
  width: 50,
  height: 15,
  displayValue: true
})

// 使用返回的dataUrl
const img = document.createElement('img')
img.src = barcodeDataUrl
document.body.appendChild(img)

// 自定义样式
const customBarcode = await generateBarcode('ABC123', {
  CodeType: 'CODE39',
  width: 60,
  height: 20,
  LineColor: '#FF0000',
  background: '#FFFF00',
  displayValue: true,
  textAlign: 'center',
  fontSize: 6,
  outputFormat: 'png',
  dpi: 300
})

支持的条形码格式

  • CODE128 - 支持ASCII字符,最大80个字符(默认)
  • CODE39 - 支持大写字母、数字、特殊字符,最大43个字符
  • EAN13 - 13位数字,商品条码
  • EAN8 - 8位数字,商品条码
  • UPC - 12位数字,商品条码
  • ITF14 - 14位数字,物流条码
  • MSI - 数字,最大20位
  • pharmacode - 数字,最大6位,药品条码
  • codabar - 支持数字、字母、特殊字符,最大20个字符

generateQRCode - 二维码生成

导入

import { generateQRCode } from 'template-designer'

函数签名

async function generateQRCode(
  text: string,                    // 要编码的文本内容
  options?: {
    width?: number                 // 二维码宽度(毫米),默认50
    height?: number                // 二维码高度(毫米),默认50
    QRCodeForeground?: string      // 前景色(二维码颜色),默认'#000000'
    QRCodeBackground?: string      // 背景色,默认'#ffffff'
    QRCodeErrorLevel?: string      // 错误纠正级别,可选'L'|'M'|'Q'|'H',默认'M'
    margin?: number                // 边距(毫米),默认0
    format?: string                // 输出格式,可选'png'|'jpeg'|'svg',默认'png'
    quality?: number               // 图片质量(0-1),仅对jpeg有效,默认0.9
    returnDataUrl?: boolean        // 是否返回完整dataUrl,默认true
    dpi?: number                   // DPI值,默认96
  }
): Promise<string>                 // 返回base64格式的图片数据或dataUrl

使用示例

// 基础用法
const qrcodeDataUrl = await generateQRCode('https://example.com', {
  width: 50,
  height: 50,
  QRCodeErrorLevel: 'M'
})

// 使用返回的dataUrl
const img = document.createElement('img')
img.src = qrcodeDataUrl
document.body.appendChild(img)

// 自定义样式
const customQRCode = await generateQRCode('Hello World', {
  width: 60,
  height: 60,
  QRCodeForeground: '#0000FF',
  QRCodeBackground: '#FFFFFF',
  QRCodeErrorLevel: 'H',  // 高错误纠正级别
  margin: 2,
  format: 'png',
  dpi: 300
})

// 生成SVG格式
const svgQRCode = await generateQRCode('SVG格式二维码', {
  width: 50,
  height: 50,
  format: 'svg',
  returnDataUrl: true
})

错误纠正级别说明

  • L - 低(约7%的错误可被纠正)
  • M - 中(约15%的错误可被纠正,默认)
  • Q - 四分之一(约25%的错误可被纠正)
  • H - 高(约30%的错误可被纠正)

开发

npm run dev
npm run build

许可证

MIT