vue打印前台⽤户⾃⼰设计模版打印报表实现记录
⼀需求
公司产品由cs转向bs,我前端使⽤vue技术栈,具体的难点
1.在vue的基础上让⽤户⾃⼰设计模版
2.设计的模版与后台请求的数据相结合
3.打印
⼆功能实现
2.1 先说打印
问百度 web打印出来的基本是两种⽅案,⼀是 js插件⼆是lodop 控件实现web打印功能
注: lodop 控件需要下载⼀个程序。对于我们客户来说或许有些⿇烦那就选js插件吧    lodop 官⽹:实现⽅式百度好多略过!!!
问百度 vue 项⽬实现打印也是两种⽅式
⼀是:通过npm 安装插件
⼆是:⼿动下载插件到本地
扩展:详细说下 npm安装⽅式
//1.安装
npm install vue-print-nb --save
//2 main.js⽂件中引⼊
import Print from 'vue-print-nb'
Vue.use(Print); //注册
//3.使⽤
<div id="printTest" >
     <p>锄⽲⽇当午</p>
     <p>汗滴⽲下⼟ </p>
     <p>谁知盘中餐</p>
     <p>粒粒皆⾟苦</p>
   </div>
   <button v-print="'#printTest'">打印</button>
//⽬前看不到⼿动调的⽅法
//
2.2 接下来如何设计模版
做这个模版设计,百度了⼀顿的就看见⼀个注册组件⽅式,写的不详细,⾃⼰没有实现出来,(┬_┬)先回到jq的思维!!
让⽤户或者实施⼈员⾃⼰设计模版,这听起来有点之前的拖拽建站的感觉呀,拖拽元素⽣成对应的html代码(不想做个这东西!!),想想有啥可以借⽤的东西呢?⼀下⼦想到之前⽤过的富⽂本编译
器o(∩_∩)o 哈哈!!那就百度下-----确实到⼀篇类似的⽂章⽂章中很多数据看不到,没法具体的尝试!!只能借鉴思路了,既然提到了ueditor那就也⽤这个吧!!
ueditor 的官⽹有不少例⼦
初试的时候⽤的jq版本(这个插件就是jq版的)vue的盛⾏到⽬前已经好久不更新了,试验完 jq版本⼜尝试往 vue项⽬上转移。
拓展:Vue 中使⽤UEditor富⽂本编辑器
参考
//1.安装
cnpm i vue-ueditor-wrap
//2.下载处理后的UEditor,下载地址
github/HaoChuan9421/vue-ueditor-wrap/tree/master/assets/downloads
//解压,重命名⽂件夹为UEditor,放⼊public⽂件夹下(如果是旧项⽬对应static⽂件夹)。
//3.引⽤组件、注册组件
import VueUeditorWrap from 'vue-ueditor-wrap'// ES6 Module
// 或者
const VueUeditorWrap = require('vue-ueditor-wrap') // CommonJS
//4. v-model绑定数据
<vue-ueditor-wrap v-model="msg"></vue-ueditor-wrap>
data () {
return {
msg: '<h2><img src="img.baidu/hi/jx2/j_0003.gif"/>Vue + UEditor + v-model双向绑定</h2>'
}
}
//5. 修改配置具体参考如下详细代码
//详细代码
<template>
<div>
<div id="app">
<vue-ueditor-wrap v-model="msg" :config="myConfig"></vue-ueditor-wrap>
<div class="tembtn">
<!-- <el-button type="primary" @click="showOne();">获取编辑器内容</el-button> -->
<el-button type="primary" @click="saveTemplate();">保存编辑模版</el-button>
</div>
</div>
</div>
</template>
<script>
import VueUeditorWrap from 'vue-ueditor-wrap'
export default {
name: "setPrintTemplate",
components: {
VueUeditorWrap
},
data() {
msg:'',
myConfig:{
// 编辑器不⾃动被内容撑⾼
autoHeightEnabled: false,
// 初始容器⾼度
initialFrameHeight: 480,
// 初始容器宽度
initialFrameWidth: '100%',
// 上传⽂件接⼝(这个地址是我为了⽅便各位体验⽂件上传功能搭建的临时接⼝,请勿在⽣产环境使⽤!!!)
serverUrl: '',
// UEditor 资源⽂件的存放路径,如果你使⽤的是 vue-cli ⽣成的项⽬,通常不需要设置该选项,vue-ueditor-wrap 会⾃动处理常见的情况,如果需要特殊配置,参考下⽅的常见问题2                UEDITOR
_HOME_URL: '/static/UEditor/'
}
}
},
mounted() {
this.msg = localStorage.setPrintTemplate || ''
},
methods: {
showOne(){
alert(this.msg);
},
saveTemplate(){
alert('初步计划:此处需要将保存的模版保存到数据库中,可以设置多个,先本地模拟⼀个保存');
localStorage.setPrintTemplate = this.msg;
alert('模版保存成功')
}
},
}
</script>
注意:这⾥的msg 就是我需要的html代码
附件:显⽰⼀下测试中设计的模版与模拟的json数据(模版字段与json字段相同)
2.3 重点来了-----将上⾯的 html内容与 json想结合需要⼀个函数,两个参数分别是模版代码与 json内容
这个功能算是核⼼功能吧费了点尽!~~~(由于不确定哪些⽤循环?哪些是简单的单独的字段替换?表格的位置都在最后么??等等可扩展功能)
补充:在做这个功能的时候先百度了下 js模版引擎原理来提⾼点思路
⽂章⼀:
⽂章⼆:
⽂章三:
确实提供⼀些思路但我需要的功能也不近相同,他们都知道循环体是哪~~我这个没法具体的,写出来循环体只能去判断!!
上来给⾃⼰定了个难点的模版 (⊙﹏⊙) 如图⽰:
第⼀部分是单纯的 p标签内容替换
第⼆四部分是⼀个 table 带有循环体(这个循环体的table我加了个 class="for"做标记)
第三部分是⼀个不带循环的table形式(其实他的性质和单纯的p标签⼀样算是⼀类)
第五部分是结尾没啥!!!!
js 正则替换
⼤体思路:
1.将模版分段(依据循环的表格),显⽰顺序不能变,放⼊到⼀个⼤的数组arr中
2.将arr中的每个模版进⾏处理
2.1 如是⾮循环部分直接正则替换后形成 html内容
2.2 若是循环部分再次正则出循环体,循环替换后与该table的其他部分组成新的html内容
设计模版的时候要注意:
如果是循环展⽰列表数据那么这个列表应该加class="for",(编译器切换到html模式),模版字段必须与接⼝返回的数据字段⼀样
对于接⼝:
返回的数据格式要参照上⾯形式
直接代码
<script>
var html = '<p>商品快递单</p><p>时间:{{time}}</p><p>地点:{{address}}</p><p>内容:</p><p><br/></p><table class="for"><tbody><tr class="firstRow"><td width="105" valign="top" > 
var json = {
time: '2018-15-15',
address: '⼭东青岛',
data: [{
name: '苹果',
color: '红⾊',
size: '3存',
num: '4',
tj: '5',
price: '6',
aoutprice: '1',
cname: '刘⼀',
}, {
name: '桃⼦',
color: '绿⾊',
size: '6',
num: '4',
tj: '5',
price: '6',
aoutprice: '1',
cname: '刘⼆',
}],
country: '中国',
province: '⼭东',
}
var efg = /<table class="for">.*?<\/table>/g;
var regtr = /<tr>.*?<\/tr>/g;
attachTemplateToData = function(template, data) {
var i = 0,
len = data.length,
fragment = '',
tmeparr = [], //总的模版
tempforarr = [], //⽤ replace 处理得到字段中需要循环的模版------最多就⼀个哈哈哈哈哈
tempsplit = []; //⽤ split 处理得到的不需要循环的模版
function strReplace(temps, obj) {
var t, key, reg;       //遍历该数据项下所有的属性,将该属性作为key值来查标签,然后替换
for (key in obj) {
reg = new RegExp('{{' + key + '}}', 'ig');
if (typeof(obj[key]) === 'string') {
t = (t || temps).replace(reg, obj[key]);
}
}
return t;
}
function forReplace(temps, obj) {
var t, key, reg;       //遍历该数据项下所有的属性,将该属性作为key值来查标签,然后替换
for (key in obj) {
reg = new RegExp('{{' + key + '}}', 'ig');
t = (t || temps).replace(reg, obj[key]);
}
console.log(t)
return t;
}
tempsplit = template.split(efg);
tempforarr.push(str)
})
for (var i = 0; i < tempsplit.length - 1; i++) {
//for 循环把 tempforarr 和 tempsplit 的模版组成⼀个完整的组数(按照原先显⽰顺序的,其实就是在 tempsplit 中元素之间依次插⼊ tempforarr)
//鉴于就⼀个 for循环的表格的直接中间插⼊就好
tmeparr.push(tempsplit[i]);
tmeparr.push(tempforarr[i])
}
tmeparr.push(tempsplit[tempsplit.length - 1]);
console.log(tmeparr)
//处理模版
var forTempHtml = '',
forTempCont = '';
for (var m = 0; m < tmeparr.length; m++) {
if (st(tmeparr[m]) && (tmeparr[m].search('table class="for"') != -1)) {
//for for循环数据
/
/得到循环体的模版
tmeparr[m].replace(regtr, function(str) {
forTempHtml = str;
})
// 将循环体的模版与数据结合得到相应的 html结构
for (var n = 0; n < json.data.length; n++) {
forTempCont += forReplace(forTempHtml, json.data[n]);
}
//得到循环后的html结构将此结构替换原先的模版
fragment += tmeparr[m].replace(regtr, forTempCont)
} else {
/
/普通的字段替换
fragment += strReplace(tmeparr[m], json);
}
}
return fragment;
};
$('#cont').html(attachTemplateToData(html, json))
</script>
拓展补充:正则与字符串处理
a.*?b就是a开始b结束的匹配
//利⽤正则分割,str.split(/reg/);
js同时使⽤多个分隔符分割字符串.
var mystring = "jb51,google,baidu_weibo_haotu";
var myarray = mystring.split(/[,_]/);
//代码中常⽤的⼏个正则
var re = /<%([^%>]+)?%>/g,
正则全局匹配以<%开头,中间不是%或>并以%>结尾的配配项
var efg = /<table class="for">.*?<\/table>/g;
//⽬前还不知道有啥函数可以⼀次性的将模版分成5段!!
//split 函数得到的结果不带有分隔符
//replace 函数可以到对应的分隔符
//两者相结合,你来⼀个元素我来⼀个元素最终巧妙的按照顺序得到了完整的分段模版6666

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。