sv-print
npx skills add https://github.com/ccsimple/skill-sv-print --skill sv-print
Agent 安装分布
Skill 文档
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 åæ°è¯´æï¼
| åæ° | ç±»å | é»è®¤å¼ | 说æ |
|---|---|---|---|
| name | string | ‘print’ | ä¸è½½æä»¶å |
| isDownload | boolean | true | æ¯å¦èªå¨ä¸è½½ |
| type | string | ‘blob’ | è¾åºç±»å: blob, bloburl, dataurl, pdfobjectnewwindow |
| paperWidth | number | – | çº¸å¼ å®½åº¦ (mm)ï¼å°æ¨¡æ¿å¡«å æ¶ææ |
| paperHeight | number | – | çº¸å¼ é«åº¦ (mm)ï¼å°æ¨¡æ¿å¡«å æ¶ææ |
| onProgress | function | – | è¿åº¦åè° (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 åæ°è¯´æï¼
| åæ° | ç±»å | é»è®¤å¼ | 说æ |
|---|---|---|---|
| name | string | ‘print’ | ä¸è½½æä»¶å |
| isDownload | boolean | true | æ¯å¦èªå¨ä¸è½½ |
| type | string | ‘image/jpeg’ | å¾çç±»å: image/jpeg, image/png |
| quality | number | 0.92 | å¾çè´¨é 0-1 |
| toType | string | ‘url’ | è¿åç±»å: url, blob |
| limit | number | 10 | å¤å°é¡µä¸ºä¸ä¸ªå¾çæä»¶ |
| paperWidth | number | – | çº¸å¼ å®½åº¦ (mm)ï¼å°æ¨¡æ¿å¡«å æ¶ææ |
| paperHeight | number | – | çº¸å¼ é«åº¦ (mm)ï¼å°æ¨¡æ¿å¡«å æ¶ææ |
| onProgress | function | – | è¿åº¦åè° (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 设置åå§ä½ç½®ï¼