DesignerUtils工具类
约 2318 字大约 8 分钟
...
2026-09-22
温馨提示
一般在 Designer设计器组件 中使用 DesignerUtils 工具类. 通过 onDesigned 回调可拿到。
通过插件机制扩展 DesignerUtils 工具类.
内置一些 UI api 方便插件中使用
模板相关
// 内置菜单:新建: 弹窗提示用户输入模板名称
designerUtils.newTemplate();
// 内置菜单:本地模板: 打开本地模板列表弹窗
designerUtils.openTemplateList();
// 内置菜单:保存: 保存当前模板
designerUtils.save();
// 内置菜单:保存->导入 导入模板json;
designerUtils.import();
// 内置菜单:保存->导出 导出模板json;
designerUtils.export();
// 获取模板对象
designerUtils.printTemplate;
// 获取模板json
designerUtils.printTemplate.getJson();
// 获取打印数据
designerUtils.printData;
// 设置打印数据
designerUtils.printData = { name: 'sv-print' };
designerUtils.setPrintData({ name: 'sv-print' });编辑相关
// 需要引入插件 @sv-print/plugin-view-code-edit
// 内置菜单:保存->编辑模板数据: 编辑当前模板json
designerUtils.edit();
// 内置菜单:保存->编辑打印数据: 编辑打印/预览数据json
designerUtils.editData();
// 内置菜单:保存->拖拽元素: 编辑provider元素json
designerUtils.editPrintElementJson();
// 内置菜单:保存->编辑模板数据: 编辑当前模板json
designerUtils.edit();
// 显示 编辑弹窗
designerUtils.editor.show({
value: 'let a = "sv-print"', // 字符串内容
lang: 'javascript', // 语言类型:javascript, typescript, json, css, html
title: '编辑器标题', // 标题
submitText: '确定', // 确定按钮文字
codeMirror: {}, // codeMirror 配置项
submit: (value) => {
console.log('确认事件', value);
},
cancelText: '取消', // 取消按钮文字
cancel: (value) => {
console.log('取消事件', value);
},
});UI相关
提示弹窗.ts
// 吐司弹窗
designerUtils.showToast('提示信息', {
type: 'warning', // "info" | "success" | "warning" | "error";
time: 2, // 显示时间 单位秒
});
// 提示弹窗
interface TipsOptions {
title: string; // 标题
/** 主要内容(支持纯文本或 HTML 字符串) */
content?: string; // 主要内容
desc?: string; // 描述
showFooter?: boolean; // 是否显示 底部操作按钮
modalStyle?: string; // 弹窗样式
submitText?: string; // 确定按钮文字 默认 "确定"
submit?: (close: () => void) => void; // 确定按钮点击事件
autoClose?: boolean; // 是否自动关闭弹窗 默认 true
showCancel?: boolean; // 是否显示 取消按钮 默认 true
cancelText?: string; // 取消按钮文字 默认 "取消"
cancel?: () => void; // 取消按钮点击事件
onClose?: () => void; // 弹窗关闭事件
drag?: boolean; // 是否可拖动
}
designerUtils.showModal({
title: '提示',
content: '提示信息',
});表单弹窗.ts
const randomKey = Math.random().toString(36).substring(2, 8).toUpperCase();
const randomTitle = `默认模板-${randomKey.substring(0, 4)}`;
// 支持的类型 看下方 ts 定义
designerUtils.showFormModal({
title: '新建模板',
desc: '用于保存到本地,导出名称',
schema: [
{
key: 'templateKey',
label: '模板key',
defaultValue: randomKey || 'default-template',
type: 'text',
required: true,
minLength: 2,
},
{
key: 'title',
label: '模板名称',
defaultValue: randomTitle || '默认模板',
type: 'text',
required: true,
minLength: 2,
},
],
autoClose: false, // 点击确认 是否自动关闭弹窗 默认 true
submit: (data, close) => {
console.log('提交数据', data);
designerUtils.showModal({
title: '温馨提示',
content: '当前设计内容将清空,是否继续新建',
submitText: '确认新建',
submit: () => {
close();
// xxx
},
}); // ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ 点 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ 展开查看代码
},
cancel: () => {
console.log('取消');
},
onClose: () => {
console.log('弹窗关闭');
},
});
// 支持的输入类型
export type FieldType = 'text' | 'number' | 'email' | 'password' | 'textarea' | 'select' | 'custom'; // 新增自定义类型
// 下拉选项
export interface SelectOption {
value: string | number;
label: string;
}
// 校验结果:返回 false 或非空字符串表示失败,返回 true/null/undefined 表示通过
export type ValidationResult = string | boolean | null | undefined;
// 自定义校验函数类型
export type CustomValidator = (value: any, formData?: Record<string, any>) => ValidationResult;
// 自定义字段的渲染函数
export type CustomRender = (params: {
value: any;
container: HTMLElement;
onUpdate: (newValue: any) => void;
refresh: (result: HTMLElement | string) => void;
error?: string;
isRequired?: boolean;
}) => HTMLElement | string;
// 字段校验规则(根据类型自动关联部分属性)
export interface FieldSchema {
/** 字段唯一标识,用于数据收集 */
key: string;
/** 显示标签 */
label: string;
/** 输入控件类型 */
type: FieldType;
/** 是否必填 */
required?: boolean;
/** 占位提示文本 */
placeholder?: string;
/** 默认值 */
defaultValue?: string | number;
// 字符串类型校验规则(适用于 text, email, password, textarea)
/** 最小长度 */
minLength?: number;
/** 最大长度 */
maxLength?: number;
/** 正则表达式字符串 */
pattern?: string;
// 数字类型校验规则(仅 number 类型)
/** 最小值 */
min?: number;
/** 最大值 */
max?: number;
// 下拉选项(仅 select 类型)
/** 选项列表 */
options?: SelectOption[];
/** 自定义校验函数(优先级高于内置规则) */
validator?: CustomValidator;
// 自定义渲染(仅当 type === 'custom' 时使用)
render?: CustomRender;
renderPlaceholder?: string;
// 自定义字段的额外提示
helpText?: string;
}
export interface FormOptions {
title: string; // 标题
desc?: string; // 描述
modalStyle?: string; // 弹窗样式
schema: FieldSchema[]; // 字段校验规则
submitText?: string; // 确定按钮文字 默认 "确定"
submit: (data: any, close: () => void) => void; // 提交表单数据
autoClose?: boolean; // 是否自动关闭弹窗 默认 true
showCancel?: boolean; // 是否显示 取消按钮 默认 true
cancelText?: string; // 取消按钮文字 默认 "取消"
cancel?: () => void; // 取消按钮点击事件
onClose?: () => void; // 弹窗关闭事件
drag?: boolean; // 是否可拖动
}自定义UI弹窗.ts
// 支持的类型 看下方 ts 定义
// 没那么复杂,如果不是前端,那可能是有点头大.但是有 AI 啊 😁
designerUtils.showCustomModal({
title: '本地模板列表',
desc: '本地缓存的模板,你完全可自定义这个功能',
modalStyle: 'max-width:60vw;',
render: function (target: HTMLElement, close: () => void): void {
const style = `<style>
.svp-template-list{
display: flex;
flex-wrap: wrap;
}
.svp-template-item{
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-bottom: 10px;
margin-right: 16px;
width: 200px;
border: 2px solid #e5e5e5;
transition: all 0.3s ease-in-out;
border-radius: 6px;
}
.svp-template-item .image{
width: 100%;
height: 120px;
border-radius: 6px 6px 0 0;
object-fit: contain;
object-position: top;
}
.svp-template-item .key{
margin-top: 6px;
font-size: 14px;
color: color-mix(in oklch, var(--color-primary), white 20%);
font-weight: bold;
}
.svp-template-item .title{
font-size: 14px;
}
.svp-template-item .del{
position: absolute;
right: 6px;
top: 6px;
border-radius: 50%;
width: 16px;
height: 16px;
z-index: 3;
line-height: 16px;
text-align: center;
color: var(--color-neutral);
font-size: 12px;
}
.svp-template-item:hover{
color: var(--color-primary-content);
background: color-mix(in oklch, var(--color-primary), white 10%);
}
.svp-template-item:hover .del{
color: var(--color-primary-content);
background: var(--color-neutral);
}
.svp-template-item:hover .key{
color: var(--color-primary-content);
}
.svp-template-item.active{
border: 2px solid var(--color-primary);
}
</style>`;
const box = $("<div class='svp-template-list'>");
const templates = {};
box.on('click', '.svp-template-item', function () {
const key = $(this).data('key');
if (!key) return;
if (key == util.options.templateKey) return;
designerUtils.showModal({
title: '温馨提示',
content: '切换模板当前设计内容将清空,是否继续',
submitText: '清空并切换',
submit: () => {
const template = templates[key];
designerUtils.options.templateKey = key;
designerUtils.options.title = template.title;
designerUtils.printData = template.data;
designerUtils.newPrintTemplate(template.json);
close();
},
});
});
box.on('click', '.svp-template-item .del', function (event) {
event.stopPropagation();
const key = $(this).parent().data('key');
const title = $(this).parent().data('title');
if (!key) return;
designerUtils.showModal({
title: '温馨提示',
content: `是否确认删除模板【${title}】`,
submitText: '确认删除',
submit: () => {
delete templates[key];
$(this).parent().remove();
},
cancel: () => {
console.log('取消');
},
onClose: () => {
console.log('弹窗关闭');
},
});
});
for (const key in templates) {
const template = templates[key];
const active = designerUtils.options.templateKey === key;
box.append(`<div class="svp-template-item ${
active ? 'active' : ''
}" data-key="${key}" data-title="${template.title}">
${active ? '' : `<div class="del"><i class="svicon sv-close"></i></div>`}
<img class="image" src="${template.image || './favicon.ico'}"></img>
<div class="key">${key}</div>
<div class="title">${template.title}</div>
</div>`);
}
$(target).append(style);
$(target).append(box);
},
showFooter: false,
});
export interface CustomModalOptions {
title: string; // 弹窗标题
desc?: string; // 弹窗描述
modalStyle?: string; // 弹窗样式
render: (target: HTMLElement, close: () => void) => void; // 自定义渲染函数
autoClose?: boolean; // 是否自动关闭
showFooter?: boolean; // 是否显示底部按钮
showCancel?: boolean; // 是否显示取消按钮
submitText?: string; // 提交按钮文本
cancelText?: string; // 取消按钮文本
submit?: (target: HTMLElement, close: () => void) => void; // 提交按钮点击事件
cancel?: () => void; // 取消按钮点击事件
onClose?: () => void; // 弹窗关闭事件
drag?: boolean; // 是否可拖动
}预览组件.js
// 设计器内 预览弹窗
designerUtils.preview?.show(); // 使用默认的 预览/打印数据 designerUtils.printData
designerUtils.preview?.show(
{ name: 'sv-print' }, // 预览/打印数据
{
showPdf: true, // 是否显示 pdf导出
showImg: true, // 是否显示 图片导出
showPrint2: true, // 是否显示 静默打印
showPrint: true, // 是否显示 浏览器打印
// selectedPrinter: "默认打印机名称", // 选中的打印机
// 传递给 导出pdf,图片的参数
// 参数类型参考: node_modules/sv-print/dist/types.d.ts PreviewShowOptions
// 融合了 导出pdf,图片,静默打印的参数
options: {
name: '传递导出名称',
// 模糊,不清晰调整这个
pixelRatio: 2, // 提高清晰度 默认 window.devicePixelRatio.
onProgress: (cur, total) => {
console.log(cur, total);
},
},
// 一些事件回调
onClick: (type) => {
console.log(type);
},
onClose: () => {
console.log('onClose');
},
onRender: () => {
console.log('onRender');
},
callBackOptions: {
statusCallback: (status) => {
console.log(status);
},
},
},
); // 使用自定义的 打印数据高级用法
// 通过插件机制 扩展 api
import type { PluginOptions } from 'sv-print';
interface PluginConfig {}
const onDesignedHook = (pluginConfig: PluginConfig): HookOptions => ({
hook: 'onDesigned',
name: 'xxx OnDesigned',
description: 'xx插件 添加 xxx api 到 designerUtils',
priority: 1,
run: ({ designerUtils }) => {
designerUtils.xxx = {
a: () => {
console.log('a');
},
b: () => {
console.log('b');
},
};
},
});
const plugin = (pluginConfig: PluginConfig): PluginOptions => ({
name: 'designerUtils Plugin',
description: 'xx插件 添加 xxx api 到 designerUtils',
hooks: [onDesignedHook(pluginConfig)],
leastHiprintVersion: '0.3.0',
});版权所有
版权归属:sv-print
