简单介绍一下前端打印的做法和一些问题
一、简介
前端打印即浏览器打印,是通过浏览器的打印功能来实现打印效果的做法。
通过前端打印,可以实现的功能。
二、基本打印
首先用最普通的方式实现一些前端打印。
print.vue:
<template>
<div class="print-box" style="margin-left: 20px; margin-right: 20px">
<h2 class="print-header" style="margin-top: 0px">预分拣单</h2>
<div class="top-info-box">
<div class="flex-box">
<div class="flex-2">预分拣单:{{printData.crossDockingNo}}</div>
<div class="flex-1">总SKU数:{{printData.skuQty}}</div>
<div class="flex-1">总PCS数:{{printData.pcsQty}}</div>
</div>
<div class="flex-box">
<div class="flex-1">生单时间:{{printData.createTime}}</div>
<div class="flex-1">打印时间:{{printData.printTime}}</div>
</div>
</div>
<hr class="top-line" style="margin-top: 2px;margin-bottom: 2px;"/>
<ul class="printTable">
<li v-for="item in printData.commodityList" :key="item.commodityCode">
<div class="table-top-box">
<div class="flex-box">
<div class="flex-1">商品编码:{{item.commodityCode}}</div>
<div class="flex-1">越库数量:{{item.crossQty}}</div>
</div>
<div class="flex-box">
<div class="flex-2">品名:{{item.commodityName}}</div>
<div class="flex-1">规格:{{item.spec}}</div>
<div class="flex-1">单位:{{item.unit}}</div>
</div>
</div>
<table>
<thead>
<tr>
<th>门店编码</th>
<th>门店名称</th>
<th>门店库位</th>
<th>播种数量</th>
</tr>
</thead>
<tbody>
<tr v-for="subItem in item.distributionDetail" :key="subItem.storeCode">
<td>{{ subItem.storeCode }}</td>
<td>{{ subItem.storeName }}</td>
<td>{{ subItem.collectionLocation}}</td>
<td>{{ subItem.matchQty }}</td>
</tr>
</tbody>
</table>
</li>
</ul>
<hr class="bottom-line" style="margin-top: 2px;margin-bottom: 2px;"/>
<div class="footer-center">
<el-button @click="startPrint" type="primary">打印</el-button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
printData: {}
}
},
mounted() {
this.init();
},
methods: {
init() {
const data = {
'crossDockingNo': 'PSTSHW000218314-9999',
'skuCount': 3,
'pcsCount': 2452,
'createTime': '2018-03-14 17:40:01',
'printTime': '2018-03-14 17:40:01',
'commodityList': [
{
'commodityCode': 200004960001,
'commodityName': '薯片',
'spec': '32.4g',
'unit': '袋',
'crossQty': 150,
'distributionDetail': [
{
'storeCode': 0,
'storeName': '人广店',
'collectionLocation': 'MENDIAN1',
'matchQty': 21,
}
]
}
],
};
for (let i = 0; i < 10; i++) {
const item = Object.assign({}, data.commodityList[0].distributionDetail[0]);
item.storeCode = i + 1;
data.commodityList[0].distributionDetail.push(item);
}
for (let i = 0; i < 10; i++) {
const item = Object.assign({}, data.commodityList[0]);
item.commodityCode = i + 1;
data.commodityList.push(data.commodityList[0]);
}
this.printData = data || {};
},
startPrint() {
// 打开一个新窗口
const myWindow = window.open('', '标题');
// 获取id为app内的html
const bodyHtml = window.document.getElementById('app').innerHTML;
// 获取head标签内的html
let headHtml = document.head.innerHTML;
// 头中的screen换成打印样式print
headHtml = headHtml.replace('screen', 'screen, print');
//重新写入文档流
myWindow.document.write('<html>');
myWindow.document.write(headHtml);
myWindow.document.write('<body >');
myWindow.document.write(bodyHtml);
myWindow.document.write('<script>setTimeout(function() {window.print(); window.close();}, 500)</');
myWindow.document.write('script>');
myWindow.document.write('</body></html>');
}
}
};
</script>
<style lang="less" scoped>
@import url("./print.less");
</style>
print.less:
.print-box {
font-size: 12px;
padding: 2px;
@media print {
font-family: "PingFang SC", "Hiragino Sans GB", "Helvetica Neue", Roboto, Noto, sans-serif;
}
.print-header {
text-align: center;
margin-top: 15px;
font-weight: bold;
}
.top-line {
height: 10px;
border: none;
border-top: 10px groove;
margin-top: 12px;
margin-bottom: 12px;
}
.table-top-box {
font-size: 18px;
}
.flex-box {
display: flex;
.flex-2 {
flex: 2;
}
.flex-1 {
flex: 1;
}
}
.printTable li {
margin-top: 20px;
.table-top-box {
margin-bottom: 10px;
}
}
.bottom-line {
height: 1px;
border: none;
border-top: 3px groove; /* solid */
margin-top: 12px;
margin-bottom: 12px;
}
@border-color: #e1e1e1;
.printTable {
table {
text-align: center;
font-size: 12px;
border: 1px solid @border-color;
width: 100%;
th, td {
padding: 1px;
border-bottom: 1px solid @border-color;
border-right: 1px solid @border-color;
}
th {
text-align: center;
&:last-child {
border-right: none;
}
}
tr {
td:last-child {
border-right: none;
}
&:last-child {
td {
border-bottom: none;
}
}
}
}
}
.footer-center {
@media print {
display: none;
}
margin-top: 12px;
text-align: center;
}
}
打印预览:
三、功能设置
3.1 页面设置
@page 规则用于指定打印页面的一些属性,包括纸张尺寸、方向、页边距、分页等特性。
@page :pseudo-class {
size: A4 landscape;
margin:2cm;
}
3.2 分页
page-break-before用于设置元素前面的分页行为,可取值:
- auto默认值。如果必要则在元素前插入分页符。
- always在元素前插入分页符。
- avoid避免在元素前插入分页符。
- left在元素之前足够的分页符,一直到一张空白的左页为止。
- right在元素之前足够的分页符,一直到一张空白的右页为止。
- inherit规定应该从父元素继承 page-break-before 属性的设置。
page-break-after设置元素后的分页行为。取值与page-break-before一样。
page-break-inside设置元素内部的分页行为。取值如下:
- auto默认。如果必要则在元素内部插入分页符。
- avoid避免在元素内部插入分页符。
- inherit规定应该从父元素继承 page-break-inside 属性的设置。
@media print {
section {page-break-before: always;}
h1 {page-break-after: always;}
p {page-break-inside: avoid;}
}
3.3 分页保留行数
orphans设置当元素内部发生分页时必须在页面底部保留的最少行数。
widows设置当元素内部发生分页时必须在页面顶部保留的最少行数。
@media print {
p {orphans:3; widows:2;}
}
3.4 显示背景色
打印默认不显示背景色,在 screen 下的设置是不起效果的。
可以通过设置改变。
@media print {
* {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}
四、其他
- 对于页面上有显示而不想打印的内容,可以将其display设置为none来避免打印。
- 需要打印的内容尽量避免float,有些浏览器不会正确的打印浮动的内容。
- 可以调用window.print()函数来打印当前页面。
- 分页打印或换页打印:page- break-before 和 page-break-after CSS属性并不会修改网页在屏幕上的显示,这两个属性是用来控制文件的打印方式。