拖拽元素动态简易使用
约 970 字大约 3 分钟
...
2026-09-14
自 sv-print@0.2.20 起,可通过 providerJson, providerRender 构建 provider.以实现数据源的动态拖拽元素.
providerJson 格式
providerJson[i]
├─ name ← "模块" 名,同 defaultModule / testModule
└─ list[]
├─ name ← 分组标题,如 "常规" / "测试"
└─ printElementTypes[]
└─ { tid, type, title, options, ... } ← 就是原来的元素对象后端JSON约定
1.打印元素类型请关注type和title 它是定义数据来源以及拖拽之前显示的描述。
2.跟业务挂钩的数据表重点关注field和表格的columnFields 它是定义数据来源,数据填充时,根据field来获取数据.
3.每种元素类型的options不好列全,可以在线demo中设计好后,右键->保存为自定义元素 查看。
温馨提示: 后端设计要点
key 建议一个业务模块一个,例如 orderModule、labelModule,避免和内置 defaultModule 冲突。
tid 必须全局唯一,推荐 {key}.{业务名},例如 testModule.text。
schema.js
{
"code": 0,
"msg": "ok",
"data": [
{
"name": "testModule", // 唯一标识,用于在前端渲染
"list": [
{
"name": "常规", // 分组名称,根据内容分类展示
"printElementTypes": [
{
"tid": "testModule.text",
"type": "text",
"title": "文本",
"options": { "title": "文本", "field": "text", "testData": "123" }
},
{
"tid": "testModule.image",
"type": "image",
"title": "图片",
"options": { "width": 100, "height": 100 }
},
{
"tid": "testModule.barcode",
"type": "text",
"title": "barcode",
"options": { "textType": "barcode", "width": 100, "height": 30 }
},
{
"tid": "testModule.qrcode",
"type": "text",
"title": "qrcode",
"options": { "textType": "qrcode", "width": 50, "height": 50 }
},
{ "tid": "testModule.longText", "type": "longText", "title": "长文" },
{
"tid": "testModule.table",
"type": "table",
"title": "表格",
"field": "table",
"columnFields": [
{
"text": "姓名",
"field": "name"
},
{
"text": "性别",
"field": "gender"
},
{
"text": "数量",
"field": "count"
},
{
"text": "金额",
"field": "amount"
}
],
"columns": [
[
{
"title": "姓名",
"align": "left",
"field": "name",
"width": 100
},
{
"title": "性别",
"field": "gender",
"width": 100
},
{
"title": "销售数量",
"field": "count",
"width": 100
},
{
"title": "销售金额",
"field": "amount",
"width": 100
}
]
]
},
{
"tid": "testModule.html",
"type": "html",
"title": "html",
"options": {
"formatter": "function(data, options) {\n return '<div style=\"height:50pt;width:50pt;background:red;border-radius:50%;\"></div>';\n}"
}
},
{
"tid": "testModule.pageBreak",
"type": "text",
"title": "分页符",
"options": {
"hideTitle": true,
"color": "#ff0000",
"textAlign": "center",
"pageBreak": true,
"showInPage": "none"
}
}
]
},
{
"name": "辅助",
"printElementTypes": [
{ "tid": "testModule.hline", "title": "横线", "type": "hline" },
{ "tid": "testModule.vline", "title": "竖线", "type": "vline" }
]
}
]
}
]
}前端加载调用
loadProviders.js
import { hiprint } from 'sv-print';
import { fetchProviderJson } from '@/api/print';
async function loadProviders() {
// 拉数据
const json = await fetchProviderJson();
// 追加(不清空已有)
hiprint.ElementTypes.addProviderJson(json);
// 若要「整体替换」,用 setProviderJson(内部先 clear)
// hiprint.ElementTypes.setProviderJson(json);
}导入导出与添加.js
// 导出
const json = hiprint.ElementTypes.getProviderJson();
// 清空
hiprint.ElementTypes.clearProvider();
// 导入(会先清空)
hiprint.ElementTypes.setProviderJson(json);
// 追加(不清空)
hiprint.ElementTypes.addProviderJson([
{
name: 'defaultModule',
list: [
{
name: '测试',
printElementTypes: [{ title: '横线1', tid: 'defaultModule.hline1', type: 'hline' }],
},
],
},
]);
// 往 defaultModule 下 "分组名称" 分组的第 1 个位置插入一个文本元素
hiprint.ElementTypes.insertPrintElementType(
{
title: '测试文本',
tid: 'defaultModule.ttt',
options: { title: '测试文本1' },
type: 'text',
},
'defaultModule',
'分组名称',
1,
);示例代码
demo.vue
<template>
<div style="width: 100vw; height: 100vh">
<Designer v-if="ready" :providerJson="providerJson" :providerRender="providerRender" />
<div v-else>加载中...</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { Designer } from '@sv-print/vue3';
import { fetchProviderJson } from '@/api/print';
const ready = ref(false);
const providerJson = ref([]);
// 可以把这个封装一下,方便换皮~
const providerRender = ref((list) => {
let container = globalThis.$('<div class="hiprint-printElement-type"></div>');
list.forEach(function (item) {
const box = globalThis.$(`
<div class="draggable-ele-group">
<span class="title">${item.name}</span>
<div class="list"></div>
</div>
`);
const typeList = box.find('.list');
item.printElementTypes.forEach(function (t) {
typeList.append(`
<div class="draggable-ele ep-draggable-item" tid=${t.tid}>
<i class="svicon sv-base sv-${t.type}"></i>
<p style="white-space:nowrap">${t.getText()}</p>
</div>
`);
});
container.append(box);
});
return container;
});
onMounted(async () => {
try {
providerJson.value = await fetchProviderJson();
} catch (e) {
console.error('[provider] 加载失败', e);
} finally {
ready.value = true;
}
});
</script>版权所有
版权归属:sv-print
