❝相信你看了 【vue-plugin-hiprint】使用-入门篇 已经知道了如何引入及构建设计器了。本
❞进阶篇
教大家如何进一步的构建设计器,包括第二种构建可拖拽元素(provider)
、vue3组合式函数
、常用API及如何查看可用API
等。
源码链接: https://github.com/CcSimple/vue-plugin-hiprint-start
这里将创建两个provider
文件,用于演示如何在两个不同容器
中去构建可拖拽元素。
首先创建provider
,直接上代码:
// provider1.js
import { hiprint } from "vue-plugin-hiprint";
export const provider1 = function (options) {
console.log(options);
var addElementTypes = function (context) {
context.removePrintElementTypes("providerModule1");
context.addPrintElementTypes("providerModule1", [
new hiprint.PrintElementTypeGroup("常规", [
// 注意这里,使用了传入的 options.config
options.config,
{
tid: "providerModule1.header",
title: "单据表头",
data: "单据表头",
type: "text",
options: {
testData: "单据表头",
height: 17,
fontSize: 16.5,
fontWeight: "700",
textAlign: "center",
hideTitle: true,
},
},
// 此处省略....
])
};
return {
addElementTypes: addElementTypes,
};
};
代码过长,各位看源码吧~ 😄
❝如果你不清楚怎么编写
❞provider
,请看 【vue-plugin-hiprint】如何自定义可拖拽元素provider
html 相对简单,只需注意容器id
及样式
即可。
<div class="flex-2 left flex-col">
<div class="title">provider1 默认样式</div>
<!-- provider1 的容器; 加上 class "rect-printElement-types" 使用默认样式 -->
<!-- 当然可以 重写 或者 自定义样式 -->
<div id="provider-container1" class="container rect-printElement-types"></div>
<div class="title">provider2 自定义样式</div>
<!-- provider2 的容器; -->
<!-- 这里自定义显示样式 custom-style-types -->
<div id="provider-container2" class="container custom-style-types"></div>
<div class=""></div>
</div>
准备工作已完成,现在即可开始真正的构建可拖拽元素
。
import { onMounted } from "vue";
import { hiprint } from "vue-plugin-hiprint";
import { provider1 } from "./provider1";
import { provider2 } from "./provider2";
// 自定义传入 provider 的参数
let options = {
config: {
tid: "providerModule1.header",
title: "参数provider示例",
type: "text",
options: {
testData: "单据表头",
height: 30,
fontSize: 16,
},
},
};
// 初始化 provider
hiprint.init({
providers: [provider1(options), provider2(options)],
});
// 为什么要在 onMounted 中执行? (你应该清楚了吧)
onMounted(()=>{
buildLeftElement();
})
/**
* 构建左侧可拖拽元素
* 注意: 可拖拽元素必须在 hiprint.init() 之后调用
* 调用之前 可以先 console.log($("#provider-container1")) 看看是否有该 dom
*/
const buildLeftElement = () => {
// ----- providerModule1 -----
$("#provider-container1").empty(); // 先清空, 避免重复构建
// 使用 providerModule1 去填充到 $("#provider-container1") 容器中
hiprint.PrintElementTypeManager.build($("#provider-container1"), "providerModule1");
// ----- providerModule2 -----
$("#provider-container2").empty(); // 先清空, 避免重复构建
// 使用 providerModule2 去填充到 $("#provider-container2") 容器中
hiprint.PrintElementTypeManager.build($("#provider-container2"), "providerModule2");
};
OK,到这里,构建可拖拽元素
成功,我们将得到如下效果图:
这个打印模板json
就是设计器的默认元素。首先先了解一下它的格式:
const template =
// 包含一个 “panels” 及 hiprint中的 “面板”
{
// “面板” 是一个数组,(支持多面板)
panels: [
// 面板 0 , 包含 宽、高、打印元素、页眉、页脚等重要信息。
{
index: 0, // 面板下标
height: 297, // 纸张 高 (mm)
width: 210, // 纸张 宽 (mm)
paperHeader: 49.5, // 页眉 (pt)
paperFooter: 780, // 页脚 (pt)
printElements: [ // 打印元素, 数组
// 打印元素
{
// 打印元素 参数
options: { left: 60, top: 27, height: 13, width: 52, title: "页眉线" },
// 打印元素 类型
printElementType: { title: "自定义文本", type: "text" },
},
],
paperNumberLeft: 565.5, // 页码位置 left (pt)
paperNumberTop: 819, // 页码位置 top (pt)
},
],
};
export default template;
正常情况,我们不会手动去创建模板json
,而是通过拖拽设计
,然后调用hiprintTemplate
对象的 getJson
Api 来获取该模板json
。
注意: 这个模板json
实际应是一个 JSON Object
,确保内部能够使用 object.key
拿到对应数据。
如何构建设计器
呢,这里我们再累述
一下。
首先插入一段 html 如下:
<div class="flex-5 center">
<!-- 设计器的 容器 -->
<div id="hiprint-printTemplate"></div>
</div>
然后在对应时机去构建(design)
<script setup>
import { onMounted } from "vue";
import { hiprint } from "vue-plugin-hiprint";
import template from "./template"; // 引入默认模板json
// 为什么要在 onMounted 中执行? (你应该清楚了吧)
onMounted(() => {
buildDesigner();
});
let hiprintTemplate;
// ref 创建的模板json (很多小伙伴的踩坑记录)
const templateRef = ref(template);
console.log("templateRef 数据格式:");
console.log("templateRef", templateRef);
console.log("templateRef.value", templateRef.value);
// 注意事项: 模板json(object)
// 如果使用 vue ref 创建的模板json, 需要使用 .value 获取 (确保内部能够使用 object.key 拿到对应数据就行)
/**
* 构建设计器
* 调用之前 可以先 console.log($("#hiprint-printTemplate")) 看看是否有该 dom
*/
const buildDesigner = () => {
$("#hiprint-printTemplate").empty(); // 先清空, 避免重复构建
hiprintTemplate = new hiprint.PrintTemplate({
// 如果使用 vue ref 创建的模板json, 需要使用 .value 获取 (确保内部能够使用 object.key 拿到对应数据就行)
template: templateRef.value, // 模板json(object)
settingContainer: "#PrintElementOptionSetting", // 元素参数容器
});
// 构建 并填充到 容器中
hiprintTemplate.design("#hiprint-printTemplate");
};
</script>
注意: 如果使用 vue ref
创建的模板json
, 需要使用 .value
获取 (确保内部能够使用 object.key 拿到对应数据就行)
当执行完design
后,我们将看到如下:
这里使用了 vue3 组合式函数
,封装了一下如何创建及获取对应模板对象
。方便再组合式函数
调用相关的 API,代码如下:
import { hiprint } from "vue-plugin-hiprint";
// 存放`模板对象`
const templateMap = {};
// 创建
export function newHiprintPrintTemplate(key, options) {
let template = new hiprint.PrintTemplate(options);
templateMap[key] = template;
return template;
}
// 获取
export function getHiprintPrintTemplate(key) {
return templateMap[key];
}
将上一步(2.1 通过模板json构建设计器)中的 buildDesigner
调整成:
// 一个唯一名称而已
const TEMPLATE_KEY = "start-02"
const buildDesigner = () => {
// ** 省略部分 **
hiprintTemplate = newHiprintPrintTemplate(TEMPLATE_KEY, {
template: templateRef.value, // 模板json(object)
settingContainer: "#PrintElementOptionSetting", // 元素参数容器
});
// ** 省略部分 **
};
在hooks
目录创建use-paper.js
(调整纸张大小)和use-zoom.js
(缩放面板)。
use-paper.js
示例:
import { reactive, computed, toRefs } from "vue";
import { getHiprintPrintTemplate } from "../utils/template-helper";
/**
* vue3 组合式函数
* 把一些逻辑抽离出来,方便复用
* 返回 使用方 可用的方法和数据
*/
export function usePaper(key) {
// ** 省略部分 **
// 获取创建的 "模板对象"
const tp = () => {
return getHiprintPrintTemplate(key);
};
// ** 省略部分 **
const setPaper = (type, value) => {
try {
if (Object.keys(state.paperTypes).includes(type)) {
state.curPaper = { type: type, width: value.width, height: value.height };
tp().setPaper(value.width, value.height);
} else {
state.curPaper = { type: "other", width: value.width, height: value.height };
tp().setPaper(value.width, value.height);
}
} catch (error) {
alert(`操作失败: ${error}`);
}
};
// ** 省略部分 **
// 暴露给使用方
return {
...toRefs(state),
curPaperType,
showPaperPop,
hidePaperPop,
setPaper,
setPaperOther,
};
}
组合式函数
处理完了,我们只需要在使用的第一,引入对应的方法即可
首先编写 html
:
<div class="paper">
<!-- 纸张大小 A3、A4 等 -->
<template v-for="(value, type) in paperTypes" :key="type">
<button :class="curPaperType === type ? 'api' : 'info'" @click="setPaper(type, value)">
{{ type }}
</button>
</template>
<!-- 自定义纸张 -->
<button :class="'other' == curPaperType ? 'api' : 'info'" class="auto" @click="showPaperPop">自定义纸张</button>
<!-- 自定义纸张 popover -->
<div class="popover">
<div class="popover-content flex-col" v-show="paperPopVisible">
<div style="font-size: 16px; font-weight: bold">设置纸张宽高(mm)</div>
<div class="flex-row mt-10">
<input class="input" :value="paperWidth" type="number" placeholder="宽(mm)" />
<span class="ml-10 mr-10">x</span>
<input class="input" :value="paperHeight" type="number" placeholder="高(mm)" />
</div>
<button class="primary circle-10" style="margin-top: 6px" @click.stop="setPaperOther">确定</button>
</div>
</div>
</div>
<!-- 缩放 此处省略 -->
如上方html,我们需要数据:paperTypes
,curPaperType
等,需要函数:setPaper
,setPaperOther
等。 我们已经在use-paper.js
中处理了,所以现在只需要引入即可:
// 组合式函数 hooks
import { usePaper } from "../hooks/use-paper";
import { useZoom } from "../hooks/use-zoom";
const TEMPLATE_KEY = "start-02"; // 存储模板对象的 key
// 引入需要的 数据 和 函数
const { paperTypes, curPaperType, paperPopVisible, paperWidth, paperHeight, showPaperPop, setPaper, setPaperOther } = usePaper(TEMPLATE_KEY);
// 缩放的 组合式函数
const { scaleValue, changeScale } = useZoom(TEMPLATE_KEY);
引入过后,就可以正常调用相关功能了。这样把部分业务代码
抽离出来,单文件不那么臃肿
,我们后续再写相关功能
的时候,直接引入即可。
旋转纸张
就是把现有纸张的宽高对调
;清空元素
就是清空现有设计器中的元素;代码如下:
/**
* 旋转纸张
*/
const rotatePaper = () => {
hiprintTemplate.rotatePaper();
};
/**
* 清空所有元素
*/
const clearPaper = () => {
hiprintTemplate.clear();
};
其中getJsonTid()
就是仅导出 options
, 不导出 printElementType
,一些其他数据需要再 provider
中获取,所以一点要先 init
对应的 provider
。
代码如下:
/**
* 导出模板 json
* 必须确保 hiprintTemplate 已成功创建
*/
const exportJson = () => {
let json = hiprintTemplate.getJson();
console.log(json);
alert("导出成功! 请查看控制台输出");
};
/**
* 导出模板 json tid
* 仅导出 options, 不导出 printElementType
* 必须确保 hiprintTemplate 已成功创建
*/
const exportJsonTid = () => {
let json = hiprintTemplate.getJsonTid();
console.log(json);
alert("导出成功! 请查看控制台输出");
};
篇幅有限,不可能把所有常用的 API 都一一讲解。俗话说:授人以鱼,不如授之以渔
。
首先你得了解对象的结构
和什么是原型链
。这里肯定不会讲滴~ 要学会自己去查阅资料
😄
提示: 接下来步骤将在开发人员工具/JavaScript控制台
中操作。笔者使用的是 Microsoft Edge
。操作路径:点击工具
菜单,然后选中开发人员
中的开发人员工具/JavaScript控制台
。如下图:
OK,废话不多说。先看模板对象
hiprintTemplate的结构。
let hiprintTemplate = new hiprint.PrintTemplate();
console.log(hiprintTemplate);
我们先来尝试一下,传上图看到的一些参数:
let hiprintTemplate = new hiprint.PrintTemplate({
dataMode: 2, // 1:getJson 其他:getJsonTid 默认1
history: false, // 是否需要 撤销重做功能
onDataChanged: (type, json) => {
console.log(type); // 新增、移动、删除、修改(参数调整)、大小、旋转
console.log(json); // 返回 template
},
});
console.log(hiprintTemplate);
嘿嘿,很明显,这几个参数是有作用的呢。
我们再试试,传入一个模板json
:
let template = { panels:[] }; // 这里代码省略,记得自己试一试哟~
let hiprintTemplate = new hiprint.PrintTemplate({
template: template
});
console.log(hiprintTemplate);
好了,相信看到这里,对于模板对象
的结构
你一定已经有所了解了。接下来就是 API 了。
看了几张图,我们还没有看到常用 API,如setPaper
,zomm
,getJson
等等,那它应该在哪里呢?管它呢,没找到就先东点西点看看看呗 😄, 当我们点开最后一个[[Prototype]]
时,你将发现新大陆
:
如上图,我们常用的API好像都在这里了呢。
新大陆已发现,不探索一下,怎么行呢?
就好比在新大陆
看到了很多树
,那树
上有些什么怎么看
呢?
我们以setPaper
API为例,带大家来一探究竟
:
我们可以清楚看到这个setPaper
需要传两个参数,然后后面又一个[[FunctionLocation]]
它后是个链接
的形式,是可以点击。FunctionLocation
翻译过来就是函数位置
,那么很明显了吧,我们就要从这里开始~
不要慌,想想我们主要的目
的是看什么
? 清楚了目的是vue-plugin-hiprint
,我们找一找呗~
皇天不负有心人
,可算在这里找到你了:
当我们格式化代码
后,哈哈,好看多了嘛。我们再回到先前的[[FunctionLocation]]
,再次点击这个链接
欧克欧克,终于看到了 API 源码
啦~
好了,关于如何查看有什么API
就到这里了。至于源码做了些什么,就需要各位自行探索了
。
此处可以说是网页调试
相关的一些内容,如果你不会浏览器调试技巧
,那么赶紧科普科普去吧~
赘述
了 provider
和 设计器
的构建,希望大家能够很清楚的去构建渲染
组合式函数
使用场景模板对象
的结构
手把手
的教大家如何去探索
更多的 模板对象
API进阶篇
到此结束,有些不清楚的知识点,大家一定要学会自己查阅相关资料
。
欢迎各位码友转发
及留言反馈
,觉得不错就点个赞
再走咯~