Token导航 LogoToken导航

Agent Skill · 前端设计

sv-print(SV print 命令行)

sv-print 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

sv-print 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描有未通过项,按安装量在前端设计类的 10,216 个 Skill 里排第 7,779。

总安装 343周安装 14GitHub Stars 公开资料未说明下载 111核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:sv-print(SV print 命令行)
来源仓库:https://github.com/ccsimple/skill-sv-print
仓库路径:skills/sv-print
安装命令:
npx skills add https://github.com/ccsimple/skill-sv-print --skill sv-print
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/ccsimple/skill-sv-print --skill sv-print

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

SV print 命令行技能提供打印功能支持。适合前端开发中的调试输出需求。可结合项目构建流程使用。sv-print 属于前端设计类 Skill,可作为该场景下的辅助能力补充。安装前需确认命令行环境配置。注意生产环境日志级别控制。

适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/sv-print

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/ccsimple/skill-sv-print --skill sv-print;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

sv-print 怎么安装?

在终端执行 npx skills add https://github.com/ccsimple/skill-sv-print --skill sv-print。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

sv-print 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

sv-print 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

sv-print 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

sv-print 用的人多吗?

公开数据是累计安装 343 次,近一周安装 14 次,下载 111 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

sv-print 安全吗?

第三方扫描有未通过项,风险较高。除非你确认过源码,否则不建议直接安装到常用环境。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
sv-print

SV print 命令行 · 本页

343—需要联网未明确未通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

sv-print

可视化打印设计器组件。基于 Svelte 构建,支持 Vue、React、Angular、jQuery 等框架引入。

快速开始

安装

# Svelte/Vanilla JS
npm i sv-print

# React
npm i @sv-print/react

# Vue2
npm i @sv-print/vue

# Vue3
npm i @sv-print/vue3

# 核心库
npm i @sv-print/hiprint

引入样式

在 main.ts 或 main.js 文件中引入组件样式

import 'sv-print/dist/style.css';

引入打印样式

需要复制 node_modules/@sv-print/hiprint/dist/print-lock.css 到开发资源目录。 例如: Vue 项目的 public 目录。 假如你部署的网站是: https://www.abcd.com/index.html 那么确保 https://www.abcd.com/print-lock.css 能够正常访问。

在 index.html 中添加打印样式:

<link rel="stylesheet" type="text/css" media="print" href="/print-lock.css" />

基本使用

<template>
  <div style="width:100vw; height:100vh">
    <Designer :template="template" @onDesigned="onDesigned" />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { Designer } from '@sv-print/vue3';

const template = ref({});
const onDesigned = (e) => {
  const { hiprint, designerUtils } = e.detail;
  console.log(designerUtils.printTemplate);
};
</script>

核心概念

模板 JSON

模板数据格式包含 panels 数组,每个面板支持:

  • width/height: 面板尺寸(单位 mm)
  • printElements: 打印元素列表
  • paperHeader/paperFooter: 页眉/页脚线
  • paperNumberLeft/paperNumberTop: 页码位置
  • backgroundColor: 背景颜色
  • watermarkOptions: 水印配置

See template.md for details.

全局对象

对象用途
hiprint创建模板、打印预览、provider 管理
hiwebSocket连接打印客户端
hinnn工具类(单位转换、事件等)
HIPRINT_CONFIG全局配置对象

See api.md for details.

设计器组件

Designer 组件支持丰富的参数:

  • template: 模板 JSON 数据
  • printData: 打印预览数据
  • config: 配置参数
  • plugins: 插件列表
  • events: 事件回调
  • theme: 主题配置

See designer.md for details.

插件系统

官方插件:

  • @sv-print/plugin-ele-bwip-js - 二维码/条形码
  • @sv-print/plugin-ele-echarts - ECharts 图表
  • @sv-print/plugin-ele-fabric - Fabric 绘制
  • @sv-print/plugin-ele-e2table - Excel 表格
  • @sv-print/plugin-text-auto - 文本自适应
  • @sv-print/plugin-formatter - 数据格式化

See plugins.md for details.

常见场景

浏览器打印

const printTemplate = new hiprint.PrintTemplate({ template: json });
const printData = { name: 'i不简' };
await printTemplate.print(printData);
// 批量打印
await printTemplate.print([printData, printData, printData]);

静默打印(需要打印客户端)

const res = await printTemplate.print2(printData, {
  printer: '打印机名称',
  pageSize: { width: 210 * 1000, height: 297 * 1000 },
  copies: 2,
  landscape: false,
  color: true,
});

获取预览 HTML

const html = (await printTemplate.getHtml(printData)).html();

导出

导出 PDF(需插件)

import pluginApiPdf from '@sv-print/plugin-api-pdf3';
import { hiprint } from 'sv-print';

// 注册插件
hiprint.register({
  plugins: [pluginApiPdf({})],
});

// 导出 PDF
const printTemplate = new hiprint.PrintTemplate({ template: json });
const printData = { name: '测试数据' };

// 方式一:直接下载
await printTemplate.toPdf(printData, '文件名称');

// 方式二:获取 Blob 对象
const res = await printTemplate.toPdf(printData, {
  name: 'pdf名称',
  isDownload: false, // 不自动下载,返回结果对象
  type: 'blob', // 输出类型: blob | bloburl | dataurl | pdfobjectnewwindow
  onProgress: (cur, total) => {
    console.log('进度', Math.floor((cur / total) * 100) + '%');
  },
});
console.log('PDF Blob:', res);

// 方式三:小模板填充到指定纸张大小
// 适用于:模板中 panelLayoutOptions.layoutRowGap > 0 或 layoutColumnGap > 0
// 且 printData 为数组时,小模板会自动填充到指定纸张大小
await printTemplate.toPdf(printDataArray, '发货单', {
  paperWidth: 210, // 纸张宽度 (mm)
  paperHeight: 297, // 纸张高度 (mm)
});

toPdf 参数说明:

参数类型默认值说明
namestring'print'下载文件名
isDownloadbooleantrue是否自动下载
typestring'blob'输出类型: blob, bloburl, dataurl, pdfobjectnewwindow
paperWidthnumber-纸张宽度 (mm),小模板填充时有效
paperHeightnumber-纸张高度 (mm),小模板填充时有效
onProgressfunction-进度回调 (cur, total)

导出图片(需插件)

import pluginApiImage from '@sv-print/plugin-api-image';
import { hiprint } from 'sv-print';

// 注册插件
hiprint.register({
  plugins: [pluginApiImage({})],
});

// 导出图片
const printTemplate = new hiprint.PrintTemplate({ template: json });
const printData = { name: '测试数据' };

// 方式一:直接下载
await printTemplate.toImage(printData, '图片名称');

// 方式二:获取 URL 或 Blob
const res = await printTemplate.toImage(printData, {
  name: '图片名称',
  isDownload: false, // 不自动下载
  type: 'image/jpeg', // 图片类型: image/jpeg | image/png
  quality: 0.92, // 图片质量 0-1
  toType: 'url', // 返回类型: url | blob
  limit: 10, // 多少页为一个图片文件
  onProgress: (cur, total) => {
    console.log('进度', Math.floor((cur / total) * 100) + '%');
  },
});
console.log('图片URL:', res);

// 方式三:小模板填充到指定纸张大小
await printTemplate.toImage(printDataArray, '发货单', {
  paperWidth: 210, // 纸张宽度 (mm)
  paperHeight: 297, // 纸张高度 (mm)
});

toImage 参数说明:

参数类型默认值说明
namestring'print'下载文件名
isDownloadbooleantrue是否自动下载
typestring'image/jpeg'图片类型: image/jpeg, image/png
qualitynumber0.92图片质量 0-1
toTypestring'url'返回类型: url, blob
limitnumber10多少页为一个图片文件
paperWidthnumber-纸张宽度 (mm),小模板填充时有效
paperHeightnumber-纸张高度 (mm),小模板填充时有效
onProgressfunction-进度回调 (cur, total)

小模板填充说明

当需要将多个小模板(如名片、标签等)填充到一张大纸(如 A4)时使用:

// 模板 JSON:配置行列间距
const templateJson = {
  panels: [
    {
      index: 0,
      name: '小模板',
      height: 50, // 小模板高度 (mm)
      width: 90, // 小模板宽度 (mm)
      panelLayoutOptions: {
        layoutType: 'row', // 行列布局类型: row, column
        layoutRowGap: 10, // 行间距 (mm)
        layoutColumnGap: 8, // 列间距 (mm)
      },
      printElements: [
        // 元素配置
      ],
    },
  ],
};

// 打印数据:数组格式
const printDataArray = [
  { name: '张三', phone: '13800138000' },
  { name: '李四', phone: '13900139000' },
  { name: '王五', phone: '13700137000' },
  // 更多数据...
];

// 导出到 A4 纸
await printTemplate.toPdf(printDataArray, '批量名片', {
  paperWidth: 210, // A4 宽度 (mm)
  paperHeight: 297, // A4 高度 (mm)
});

完整导出示例

<template>
  <div class="designer-container">
    <Designer :template="template" @onDesigned="onDesigned" />
    <div class="export-buttons">
      <button @click="exportPdf">导出 PDF</button>
      <button @click="exportImage">导出 图片</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Designer } from '@sv-print/vue3';
import pluginApiPdf from '@sv-print/plugin-api-pdf3';
import pluginApiImage from '@sv-print/plugin-api-image';
import { hiprint } from 'sv-print';

const printTemplate = ref(null);

// 注册导出插件
hiprint.register({
  plugins: [pluginApiPdf({}), pluginApiImage({})],
});

const onDesigned = (e) => {
  printTemplate.value = e.detail.designerUtils.printTemplate;
};

// 导出 PDF
const exportPdf = async () => {
  if (!printTemplate.value) return;

  const printData = { name: '测试数据' };

  try {
    // 显示下载进度
    await printTemplate.value.toPdf(printData, '发货单', {
      isDownload: true,
      paperWidth: 210,
      paperHeight: 297,
      onProgress: (cur, total) => {
        console.log('PDF 导出进度:', Math.floor((cur / total) * 100) + '%');
      },
    });
    console.log('PDF 导出完成');
  } catch (error) {
    console.error('PDF 导出失败', error);
  }
};

// 导出图片
const exportImage = async () => {
  if (!printTemplate.value) return;

  const printData = { name: '测试数据' };

  try {
    const res = await printTemplate.value.toImage(printData, '发货单', {
      isDownload: false,
      type: 'image/jpeg',
      quality: 0.92,
      toType: 'url',
      onProgress: (cur, total) => {
        console.log('图片导出进度:', Math.floor((cur / total) * 100) + '%');
      },
    });

    // 获取到 URL 后可以自定义处理
    console.log('图片 URL:', res);

    // 打开新窗口查看
    window.open(res, '_blank');
  } catch (error) {
    console.error('图片导出失败', error);
  }
};
</script>

<style>
.export-buttons {
  position: fixed;
  right: 20px;
  top: 20px;
  z-index: 1000;
}

.export-buttons button {
  margin-left: 10px;
  padding: 8px 16px;
  background: #409eff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.export-buttons button:hover {
  background: #66b1ff;
}
</style>

实际业务场景示例

场景一:自定义 Header 标题和菜单(保存到服务器)

<template>
  <div class="designer-container">
    <Designer
      headerTitle="发货单模板设计"
      :headerNewMenu="true"
      :headerMenuList="headerMenuList"
      :events="events"
      @onDesigned="onDesigned"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Designer } from '@sv-print/vue3';
import axios from 'axios';

const designerUtils = ref(null);

// 1. 自定义菜单列表
const headerMenuList = ref([
  {
    icon: 'sv-save',
    title: '保存模板',
    desc: 'Ctrl + S',
    click: (util) => util.save(), // 调用内置保存,会触发 events.onSave
  },
  {
    icon: 'sv-preview',
    title: '预览',
    desc: '',
    click: async (util) => {
      util.preview.show();
    },
  },
]);

// 2. 事件处理
const events = ref({
  // 保存模板 - 发送到服务器
  onSave: async (key, data) => {
    try {
      await axios.post('/api/template/save', {
        key: key || 'default-template',
        template: data,
        templateName: '发货单模板',
      });
      console.log('保存成功');
      return true; // 返回 true 阻止冒泡(不弹出内置保存提示)
    } catch (error) {
      console.error('保存失败', error);
      return false;
    }
  },
  // 编辑模板数据
  onEdit: (data) => {
    console.log('模板已编辑');
    return true;
  },
  // 编辑打印数据
  onEditData: (data) => {
    console.log('打印数据已编辑', data);
    return true;
  },
  // 快捷键
  onKeyDownEvent: (e, util) => {
    if (e.ctrlKey && e.key === 's') {
      e.preventDefault();
      util.save();
      return true;
    }
    return false;
  },
});

// 3. 初始化完成回调
const onDesigned = (e) => {
  const { designerUtils: utils } = e.detail;
  designerUtils.value = utils;

  // 可在此处加载已有模板
  loadTemplate();
};

// 加载模板
const loadTemplate = async () => {
  const res = await axios.get('/api/template/get?id=1');
  if (res.data.template) {
    designerUtils.value.printTemplate.update(res.data.template);
  }
};
</script>

<style>
.designer-container {
  width: 100vw;
  height: 90vh;
  overflow: hidden;
}
</style>

场景二:隐藏默认菜单,只保留自定义保存按钮

<template>
  <div class="designer-container">
    <Designer
      headerTitle="入库单设计"
      :headerNewMenu="true"
      :headerMenuList="headerMenuList"
      :showOption="{ showToolbar: true }"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Designer } from '@sv-print/vue3';

const headerMenuList = ref([
  {
    icon: 'sv-save',
    title: '保存',
    desc: 'Ctrl+S',
    click: async (util) => {
      const templateData = util.printTemplate.getJson();
      console.log('保存模板:', templateData);
      // 保存逻辑
    },
  },
  {
    icon: 'sv-preview',
    title: '预览',
    click: (util) => {
      util.preview.show();
    },
  },
  {
    gap: true, // 分割线
  },
  {
    icon: 'sv-print',
    title: '直接打印',
    click: async (util) => {
      await util.printTemplate.print2({ name: '测试数据' });
    },
  },
]);
</script>

场景三:根据 ID 从服务端加载模板并预览

<template>
  <!-- 设计器外层容器需要设置宽高 -->
  <div v-if="showDesigner" class="designer-container">
    <Designer
      :template="template"
      :printData="printData"
      :events="events"
      :onPreviewClick="onPreviewClick"
      @onDesigned="onDesigned"
    />
  </div>
  <!-- 加载中状态 -->
  <div v-else class="loading">
    <span>加载中...</span>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Designer } from '@sv-print/vue3';
import axios from 'axios';

const route = useRoute();
const router = useRouter();

const showDesigner = ref(false); // 控制设计器显示
const template = ref({}); // 模板数据
const printData = ref({}); // 打印数据
const designerUtils = ref(null);

// 从路由获取模板 ID
const templateId = route.query.id as string;

// 事件处理
const events = ref({
  onSave: async (key, data) => {
    try {
      // 保存到服务器
      await axios.post('/api/template/save', {
        id: templateId,
        template: data,
      });
      console.log('保存成功');
      return true;
    } catch (error) {
      console.error('保存失败', error);
      return false;
    }
  },
});

// 预览点击事件
const onPreviewClick = () => {
  // 可自定义预览逻辑
  console.log('点击预览');
};

// 初始化完成回调
const onDesigned = (e) => {
  const { designerUtils: utils } = e.detail;
  designerUtils.value = utils;
};

// 从服务器加载模板和打印数据
const loadTemplate = async () => {
  try {
    if (!templateId) {
      // 没有 ID,跳转到新建页面或使用默认空模板
      template.value = {};
      showDesigner.value = true;
      return;
    }

    // 并行请求模板和打印数据
    const [templateRes, printDataRes] = await Promise.all([
      axios.get(`/api/template/${templateId}`),
      axios.get(`/api/template/${templateId}/printData`),
    ]);

    // 设置模板数据
    if (templateRes.data.template) {
      template.value = templateRes.data.template;
    }

    // 设置打印数据
    if (printDataRes.data.printData) {
      printData.value = printDataRes.data.printData;
    }

    // 数据加载完成后显示设计器
    showDesigner.value = true;
  } catch (error) {
    console.error('加载模板失败', error);
    showDesigner.value = true;
  }
};

onMounted(() => {
  loadTemplate();
});
</script>

<style scoped>
.designer-container {
  width: 100vw;
  height: 90vh;
  overflow: hidden;
}

.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  height: 90vh;
  font-size: 16px;
  color: #666;
}
</style>

场景四:切换主题和语言

<template>
  <div class="designer-container">
    <Designer :theme="theme" :themeList="themeList" headerTitle="多主题模板设计" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Designer } from '@sv-print/vue3';

// 主题
const theme = ref('light');

// 可选主题列表
const themeList = ref([
  'light',
  'dark',
  'cupcake',
  'bumblebee',
  'emerald',
  'corporate',
  'synthwave',
  'retro',
  'cyberpunk',
  'dracula',
  'business',
  'winter',
]);

// 切换主题
const changeTheme = (newTheme: string) => {
  theme.value = newTheme;
};
</script>

<style>
.designer-container {
  width: 100vw;
  height: 90vh;
  overflow: hidden;
}
</style>

场景五:自定义可拖拽元素

<template>
  <div class="designer-container">
    <Designer :providers="providers" :providerMap="providerMap" :clearProviderContainer="true" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Designer } from '@sv-print/vue3';
import { hiprint } from 'sv-print';

// 定义 provider
const customProvider = (options) => {
  var addElementTypes = function (context) {
    context.removePrintElementTypes('customModule');

    context.addPrintElementTypes('customModule', [
      // 常规分组
      new hiprint.PrintElementTypeGroup('业务字段', [
        {
          tid: 'customModule.companyName',
          type: 'text',
          title: '公司名称',
          options: {
            title: '公司名称',
            field: 'companyName',
            testData: '不简科技',
            fontSize: 16,
            fontWeight: 'bolder',
          },
        },
        {
          tid: 'customModule.orderNo',
          type: 'text',
          title: '订单号',
          options: {
            title: '订单号',
            field: 'orderNo',
            testData: 'DD20240129001',
          },
        },
      ]),
      // 辅助分组
      new hiprint.PrintElementTypeGroup('辅助', [
        {
          tid: 'customModule.hline',
          type: 'hline',
          title: '横线',
        },
        {
          tid: 'customModule.rect',
          type: 'rect',
          title: '矩形',
        },
      ]),
    ]);
  };
  return { addElementTypes };
};

const providers = ref([customProvider({})]);

const providerMap = ref({
  container: '.hiprintEpContainer',
  value: 'customModule',
});
</script>

<style>
.designer-container {
  width: 100vw;
  height: 90vh;
  overflow: hidden;
}
</style>

场景六:表格元素使用

// 表格元素模板
const tableTemplate = {
  panels: [
    {
      index: 0,
      name: '面板0',
      height: 297,
      width: 210,
      printElements: [
        {
          options: {
            left: 60,
            top: 60,
            height: 100,
            width: 500,
            field: 'table',
            columnFields: [
              { text: 'ID', field: 'id' },
              { text: '姓名', field: 'name' },
              { text: '数量', field: 'count' },
            ],
            columns: [
              [
                { width: 100, title: 'ID', field: 'id', checked: true },
                { width: 150, title: '姓名', field: 'name', checked: true },
                { width: 100, title: '数量', field: 'count', checked: true },
              ],
            ],
          },
          printElementType: {
            title: '表格',
            type: 'table',
            editable: true,
            columnResizable: true,
            isEnableInsertRow: true,
            isEnableDeleteRow: true,
          },
        },
      ],
    },
  ],
};

// 打印数据
const printData = {
  table: [
    { id: 1, name: '商品A', count: 100 },
    { id: 2, name: '商品B', count: 200 },
    { id: 3, name: '商品C', count: 300 },
  ],
};

场景七:二维码/条形码元素

方式一:使用文本元素(无需插件)

通过 text 元素设置 textType 属性实现二维码或条形码:

// 二维码模板
const qrcodeTemplate = {
  panels: [
    {
      index: 0,
      name: '面板0',
      height: 297,
      width: 210,
      printElements: [
        {
          options: {
            left: 100,
            top: 60,
            height: 50,
            width: 50,
            title: '123456789', // 显示内容
            textType: 'qrcode', // 设置为二维码
            color: '#000000',
          },
          printElementType: {
            title: '文本',
            type: 'text',
          },
        },
      ],
    },
  ],
};

// 条形码模板
const barcodeTemplate = {
  panels: [
    {
      index: 0,
      name: '面板0',
      height: 297,
      width: 210,
      printElements: [
        {
          options: {
            left: 100,
            top: 60,
            height: 40,
            width: 150,
            title: '123456789',
            textType: 'barcode', // 设置为条形码
            color: '#000000',
          },
          printElementType: {
            title: '文本',
            type: 'text',
          },
        },
      ],
    },
  ],
};

方式二:使用插件扩展的新元素类型(推荐)

引入 @sv-print/plugin-ele-bwip-js 插件后,会新增 barcode 和 qrcode 元素类型:

<template>
  <div class="designer-container">
    <Designer :plugins="plugins" :template="template" headerTitle="发货单(含条码)" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Designer } from '@sv-print/vue3';
import pluginBwip from '@sv-print/plugin-ele-bwip-js';

const plugins = ref([
  pluginBwip({}), // 插件无配置参数,直接引入即可
]);

// 使用插件新增的 qrcode 元素类型
const template = ref({
  panels: [
    {
      index: 0,
      name: '面板0',
      height: 297,
      width: 210,
      printElements: [
        {
          options: {
            left: 100,
            top: 60,
            height: 60,
            width: 60,
            title: '二维码内容', // 显示内容
          },
          printElementType: {
            title: '二维码', // 插件新增的元素类型
            type: 'qrcode',
          },
        },
        {
          options: {
            left: 200,
            top: 60,
            height: 50,
            width: 150,
            title: '条形码内容',
          },
          printElementType: {
            title: '条形码', // 插件新增的元素类型
            type: 'barcode',
          },
        },
      ],
    },
  ],
});

// 打印数据
const printData = {
  name: '张三',
};
</script>

<style>
.designer-container {
  width: 100vw;
  height: 90vh;
  overflow: hidden;
}
</style>

场景八:接收外部保存信号触发设计器保存

<template>
  <div class="page-container">
    <div class="toolbar">
      <button @click="saveTemplate">外部保存按钮</button>
    </div>
    <div class="designer-container">
      <Designer :events="events" @onDesigned="onDesigned" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import { Designer } from '@sv-print/vue3';
import { hinnn } from 'sv-print';

const designerUtils = ref(null);
const saveTrigger = ref(0); // 保存触发器

// 事件
const events = ref({
  onSave: (key, data) => {
    console.log('保存模板', key);
    // 发送到服务器或 localStorage
    return true;
  },
});

const onDesigned = (e) => {
  const { designerUtils: utils } = e.detail;
  designerUtils.value = utils;
};

// 外部保存
const saveTemplate = () => {
  if (designerUtils.value) {
    designerUtils.value.save();
  }
};

// 监听外部保存信号(可通过 pinia/vuex 或事件总线触发)
watch(saveTrigger, () => {
  saveTemplate();
});

// 模拟外部触发
// hinnn.event.trigger('saveTemplate');
</script>

<style>
.page-container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.toolbar {
  height: 50px;
  padding: 0 20px;
  display: flex;
  align-items: center;
  background: #f5f5f5;
}

.designer-container {
  flex: 1;
  overflow: hidden;
}
</style>

场景九:设置默认纸张和尺寸

<template>
  <div class="designer-container">
    <Designer :paperList="paperList" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Designer } from '@sv-print/vue3';

const paperList = ref([
  { type: 'A4', width: 210, height: 297 },
  { type: 'A5', width: 148, height: 210 },
  { type: 'Custom', width: 100, height: 150 }, // 自定义尺寸
]);
</script>

<style>
.designer-container {
  width: 100vw;
  height: 90vh;
  overflow: hidden;
}
</style>

场景十:禁用/调整 UI 组件

通过 styleOption、showOption、rulerStyle 可以隐藏或调整各个小组件的位置:

<template>
  <div class="designer-container">
    <Designer
      :styleOption="styleOption"
      :showOption="showOption"
      :rulerStyle="rulerStyle"
      :showPanels="false"
      headerTitle="简化版设计器"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Designer } from '@sv-print/vue3';

// 控制各小组件的显示和位置
const styleOption = ref({
  draggableEls: {
    // 可拖拽元素区域
    mode: 'left', // 固定在左侧
    show: true, // 是否显示
    style: 'left:0;top:95px;width:200px;height:calc(100% - 340px);',
  },
  options: {
    // 属性面板 - 隐藏
    show: false,
  },
  pageStructure: {
    // 页面结构 - 隐藏
    show: false,
  },
  locationExchange: {
    // 位置交换 - 隐藏
    show: false,
  },
  miniMap: {
    // 小地图 - 隐藏
    show: false,
  },
  editableTools: {
    // 编辑工具 - 隐藏
    show: false,
  },
  zIndexTools: {
    // 层级工具 - 隐藏
    show: false,
  },
  fontTools: {
    // 字体工具 - 隐藏
    show: false,
  },
  zoomTools: {
    // 缩放工具 - 显示并调整位置
    mode: 'right',
    style: 'right:10px;top:100px;',
  },
  rotateTools: {
    // 旋转工具 - 隐藏
    show: false,
  },
});

// 控制主区域显示
const showOption = ref({
  showHeader: true, // 显示顶部 Header
  showToolbar: true, // 显示工具栏 Toolbar
  showFooter: true, // 显示底部 Footer
  showPower: false, // 隐藏 "powered by sv-print"
});

// 控制标尺
const rulerStyle = ref({
  show: false, // 隐藏标尺
});
</script>

<style>
.designer-container {
  width: 100vw;
  height: 90vh;
  overflow: hidden;
}
</style>

styleOption 可配置项说明:

组件说明可配置项
panels多面板区域mode
draggableEls可拖拽元素show, mode, style, html
options属性面板show, mode, style, html
pageStructure页面结构show, mode, style, html
locationExchange位置交换show, mode, style, html
miniMap小地图show, mode, style, html
history历史记录show, mode, style, html
editableTools编辑工具show, mode, style
zIndexTools层级工具show, mode, style
fontTools字体工具show, mode, style
zoomTools缩放工具show, mode, style
rotateTools旋转工具show, mode, style

mode 取值说明:

  • default - 默认位置
  • top - 固定在顶部
  • bottom - 固定在底部
  • left - 固定在左侧
  • right - 固定在右侧
  • fixed - 自由拖拽(需配合 style 设置初始位置)

平台分布

Codex

36.46%
按下载量换算40

Claude

30.77%
按下载量换算34

Cursor

17.33%
按下载量换算19

Gemini CLI

9.77%
按下载量换算11

安全审计

Gen Agent Trust Hub

未通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills