做了三四天的浏览器打印....有点想吐血的感觉...不过总体来说还是有点收获的.
先看一下最终一些打印的预览图:
注意点:
背景色打印
.bg {
-webkit-print-color-adjust: exact; /* 这一行必须要 */
print-color-adjust: exact;
background-color: green;
}
@page {
size: landscape;
}
横竖打印,以及打印边距
portrait为竖着打 landscape为横着打
Vue.prototype.GlobalPrint = function(title = '打印', printHtml, pageSet = {}) {
// 打开一个新窗口
const myWindow = window.open('', title);
// 获取id为app内的html
const bodyHtml = printHtml || window.document.getElementById('app').innerHTML;
// 获取head标签内的html
let headHtml = document.head.innerHTML;
const pageStr = `
<style media="print">
@page {
size: ${pageSet.size || 'landscape'}; // portrait
margin: ${pageSet.margin || '18mm 18mm 18mm 18mm'};
}
</style>
`;
headHtml += pageStr;
// 头中的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();}, 50)</');
myWindow.document.write('script>');
myWindow.document.write('</body></html>');
return true;
}
调用方式
this.GlobalPrint(null, null, {
size: 'portrait',
margin: '1cm'
});
分页
@media print {
.next-page {
page-break-before: always;
}
}
print.less
.so-list-print {
position: relative;
font-size: 12px;
@media print {
.next-page {
page-break-before: always;
}
}
.next-page {
position: relative;
.right-top {
position: absolute;
right: 0;
top: 0;
}
.right-top-2 {
position: absolute;
right: 0;
top: 12px;
}
}
.header-first {
display: flex;
flex-wrap: wrap;
span {
width: 50%
}
span:nth-child(even) {
text-align: right;
}
}
.header-second {
display: flex;
flex-wrap: wrap;
span {
width: 33.33%
}
span:nth-child(2) {
text-align: center;
}
span:nth-child(3) {
text-align: right;
}
}
.print-header {
text-align: center;
margin-top: 15px;
font-weight: bold;
}
.top-line {
height: 10px;
border: none;
border-top: 10px groove;
margin-top: 2px;
margin-bottom: 2px;
}
.bottom-line {
height: 1px;
border: none;
border-top: 3px groove;
margin-top: 12px;
margin-bottom: 12px;
}
.count {
text-align: right;
span {
width: 10%;
text-align: center;
display: inline-block;
}
}
.sign {
display: flex;
justify-content: flex-end;
margin-top: 12px;
div {
text-align: center;
margin-right: 20px;
border: 1px solid grey;
width: 80px;
height: 70px;
span {
font-size: 12px;
padding: 8px;
display: block;
border-bottom: 1px groove;
}
}
}
@border-color: #e1e1e1;
.table-container {
table {
text-align: center;
font-size: 12px;
width: 100%;
th, td {
border-bottom: 1px solid @border-color;
padding: 6px;
}
}
}
.footer-left {
position: absolute;
bottom: -30px;
left: 0px;
span {
font-size: 20px;
font-weight: bold;
}
}
.footer-center {
@media print {
display: none;
}
position: fixed;
bottom: 30px;
left: 50%;
}
}
print.vue
<template>
<div class="so-list-print">
<div v-for="(item, index) in printData" :key="index" class="next-page">
<div v-for="(detail, key) in item.sort" :key="key" :class="key == item.totalPage ? null : 'next-page'">
<h2 class="print-header">仓库出货单</h2>
<div class="right-top">
<span>第 {{item.header.printCount}} 回打印</span>
</div>
<div class="right-top-2">
<span class="align-left;">打印时间: {{ item.header.timeCur }}</span>
</div>
<div class="header-first">
<span>发运单号: {{ item.header.soNo }}</span>
<span>发货时间: {{ item.header.sendTime }}</span>
<span>仓库编号: {{ item.header.warehouseCode }}</span>
<span>客户编号: {{ item.header.customerCode }}</span>
</div>
<div class="header-second">
<span>仓库名称: {{ item.header.warehouseName }}</span>
<span>物流名称: {{ item.header.logistics }}</span>
<span>客户名称: {{ item.header.customerName }}</span>
</div>
<hr class="top-line" />
<div class="table-container">
<table>
<thead>
<tr>
<th>序号</th>
<th>商品编码</th>
<th>商品名称</th>
<th>分类</th>
<th width="10%">计划数量</th>
<th width="10%">成交数量</th>
</tr>
</thead>
<tbody>
<tr v-for="(item2, index) in detail">
<td>{{ item2.index }}</td>
<td>{{ item2.skuCode }}</td>
<td>{{ item2.skuName }}</td>
<td>{{ item2.divName}}</td>
<td width="10%">{{ item2.planQty }}</td>
<td width="10%">{{ item2.shipQty }}</td>
</tr>
</tbody>
</table>
</div>
<span class="footer-left">当前第 <span>{{parseInt(key) + 1}}</span> 页, 共 <span>{{ item.totalPage }}</span> 页</span>
</div>
<div class="count">
总计: <span>{{ item.header.totalPlanQty }}</span><span>{{ item.header.totalShipQty }}</span>
</div>
<hr class="bottom-line" />
<div class="sign">
<div><span>物流</span></div>
<div><span>驾驶员</span></div>
<div><span>店铺</span></div>
<div><span>验收印</span></div>
</div>
</div>
<div class="footer-center">
<el-button @click="GlobalPrint(null, null, printOptions)" type="primary">打印</el-button>
</div>
</div>
</template>
<script>
import moment from 'moment';
import {DeliveryFindAll} from './service/service';
export default {
data() {
const url = this.$route.path;
const soIds = url.substring(url.lastIndexOf('/') + 1, url.length);
const soIdArr = soIds.split(',');
return {
soIds: soIdArr,
printData: [],
printOptions: {
size: 'portrait',
margin: '1cm'
},
catData: {
pageName: 'so-list-print',
msg: 'Failed',
},
loading: false,
}
},
mounted() {
this.init();
},
methods: {
init() {
const soIds = this.soIds;
if (soIds.length === 0) {
this.$alert('无发运单id,无法打印!', '提示', {confirmButtonText: '确定', type: 'info'});
return;
}
const catData = {...this.catData, msg: 'DeliveryFindAll'};
this.loading = true;
DeliveryFindAll(soIds, catData).then((res = []) => {
this.loading = false;
res.forEach(item => {
item.header.timeCur = moment().format('YYYY-MM-DD HH:mm:ss');
item.details.forEach((item2, index) => {
item2.index = index + 1;
});
item.sort = {};
const count = parseInt(item.details.length / 25) + 1;
for (let i = 0; i < count; i++) {
item.sort[i] = item.details.slice(i * 25, (i + 1) * 25);
}
item.totalPage = count;
});
this.printData = res;
this.$confirm('确认打印', '提示').then(() => {
this.GlobalPrint(null, null, this.printOptions);
}).catch(() => {})
}).catch((err) => {
this.loading = false;
this.printData = [];
this.$alert(err.msg || '服务器错误!', '提示', {type: 'error'});
});
},
}
};
</script>
<style lang="less">
@import url("../../less/print/so-list-print");
</style>
另外页眉页脚是没法通过浏览器自定义设置的,需要自己写div和样式。