一、安装vue3-print-nb
npm install vue3-print-nb --save
yarn add vue3-print-nb
二、引入Vue项目
// 1. 全局挂载
import { createApp } from 'vue'
import App from './App.vue'
import print from 'vue3-print-nb'
const app = createApp(App)
app.use(print)
app.mount('#app')
// 2. 自定义指令
import print from 'vue3-print-nb'
directives: {
print
}
三、简单使用案例
1、在components目录下新建penaltyRequestForm.vue
<script setup>
import { reactive, ref } from "vue";
let penaltyRequestForm = reactive({
// id
id: '',
// 罚款单编号
number: "20241025001",
// 被扣款单位和个人
deductionPerson : "代雄伟",
// 扣款事项
deductionMatters: "就是想扣你钱",
// 扣款金额
deductionAmount: "64800.00",
// 扣款方式
deductionMethod: "运费/工资中扣除",
// 备注
remark: "备注备注备注备注备注",
// 分管领导审批
departmentHeadApproval: "孙总",
// 财务审核
financialReview: "祝总",
// 部门审核
departmentReview: "李总",
// 创建时间
createTime: "2024年12月13日",
});
</script>
<template>
<div>
<div class="bottom-list">
<div class="line-center">
<span style="text-align: center;font-size: 28px;font-weight: bold;">重庆XXXXXXXX有限公司</span>
</div>
<div class="line-center">
<span style="text-align: center; font-size: 24px;font-weight: bold;">扣(罚)款通知单</span>
</div>
<div class="line-right">
<span style="text-align: right; font-weight: bold;">编号:<span style="padding: 0 2px">{{ penaltyRequestForm.number }} </span></span>
</div>
<div class="g-grid-box">
<div class="g-grid6">
<div class="g-item center">被扣款单位/个人</div>
<div class="g-item center">扣款事项</div>
<div class="g-item center">扣款金额(单位:元)</div>
<div class="g-item center">扣款方式</div>
<div class="g-item center">备注</div>
</div>
<div class="g-grid6">
<div class="g-item">{{ penaltyRequestForm.deductionPerson }}</div>
<div class="g-item">{{ penaltyRequestForm.deductionMatters }}</div>
<div class="g-item">{{ penaltyRequestForm.deductionAmount }}</div>
<div class="g-item">{{ penaltyRequestForm.deductionMethod }}</div>
<div class="g-item">{{ penaltyRequestForm.remark }}</div>
</div>
</div>
<div class="g-grid5">
<div><span style="text-align: center; font-size: 14px;">注:本通知单一式三联,当事单位(人)、制表部门、财务部门各执一份。</span></div>
</div>
<div class="g-grid4">
<div>
分管领导审批:
<span>{{ penaltyRequestForm.departmentHeadApproval }}</span>
</div>
<div>
财务审核:
<span>{{ penaltyRequestForm.financialReview }}</span>
</div>
<div>
部门审核:
<span>{{ penaltyRequestForm.departmentReview }}</span>
</div>
</div>
<div class="g-grid5">
<div style="display:flex;justify-content: flex-end;"><span>制表日期: {{ penaltyRequestForm.createTime }} </span></div>
</div>
</div>
<div sytle="height: 50px;"> </div>
<div sytle="height: 50px;"> </div>
<div class="xuxian"></div>
<div sytle="height: 50px;"> </div>
<div sytle="height: 50px;"> </div>
<div class="bottom-list">
<div class="line-center">
<span style="text-align: center;font-size: 28px;font-weight: bold;">重庆XXXXXXXX有限公司</span>
</div>
<div class="line-center">
<span style="text-align: center; font-size: 24px;font-weight: bold;">扣(罚)款通知单</span>
</div>
<div class="line-right">
<span style="text-align: right; font-weight: bold;">编号:<span style="padding: 0 2px">{{ penaltyRequestForm.number }} </span></span>
</div>
<div class="g-grid-box">
<div class="g-grid6">
<div class="g-item center">被扣款单位/个人</div>
<div class="g-item center">扣款事项</div>
<div class="g-item center">扣款金额(单位:元)</div>
<div class="g-item center">扣款方式</div>
<div class="g-item center">备注</div>
</div>
<div class="g-grid6">
<div class="g-item">{{ penaltyRequestForm.deductionPerson }}</div>
<div class="g-item">{{ penaltyRequestForm.deductionMatters }}</div>
<div class="g-item">{{ penaltyRequestForm.deductionAmount }}</div>
<div class="g-item">{{ penaltyRequestForm.deductionMethod }}</div>
<div class="g-item">{{ penaltyRequestForm.remark }}</div>
</div>
</div>
<div class="g-grid5">
<div><span style="text-align: center; font-size: 14px;">注:本通知单一式三联,当事单位(人)、制表部门、财务部门各执一份。</span></div>
</div>
<div class="g-grid4">
<div>
分管领导审批:
<span>{{ penaltyRequestForm.departmentHeadApproval }}</span>
</div>
<div>
财务审核:
<span>{{ penaltyRequestForm.financialReview }}</span>
</div>
<div>
部门审核:
<span>{{ penaltyRequestForm.departmentReview }}</span>
</div>
</div>
<div class="g-grid5">
<div style="display:flex;justify-content: flex-end;"><span>制表日期: {{ penaltyRequestForm.createTime }} </span></div>
</div>
</div>
<div sytle="height: 50px;"> </div>
<div sytle="height: 50px;"> </div>
<div class="xuxian"></div>
<div sytle="height: 50px;"> </div>
<div sytle="height: 50px;"> </div>
<div class="bottom-list">
<div class="line-center">
<span style="text-align: center;font-size: 28px;font-weight: bold;">重庆XXXXXXXX有限公司</span>
</div>
<div class="line-center">
<span style="text-align: center; font-size: 24px;font-weight: bold;">扣(罚)款通知单</span>
</div>
<div class="line-right">
<span style="text-align: right; font-weight: bold;">编号:<span style="padding: 0 2px">{{ penaltyRequestForm.number }} </span></span>
</div>
<div class="g-grid-box">
<div class="g-grid6">
<div class="g-item center">被扣款单位/个人</div>
<div class="g-item center">扣款事项</div>
<div class="g-item center">扣款金额(单位:元)</div>
<div class="g-item center">扣款方式</div>
<div class="g-item center">备注</div>
</div>
<div class="g-grid6">
<div class="g-item">{{ penaltyRequestForm.deductionPerson }}</div>
<div class="g-item">{{ penaltyRequestForm.deductionMatters }}</div>
<div class="g-item">{{ penaltyRequestForm.deductionAmount }}</div>
<div class="g-item">{{ penaltyRequestForm.deductionMethod }}</div>
<div class="g-item">{{ penaltyRequestForm.remark }}</div>
</div>
</div>
<div class="g-grid5">
<div><span style="text-align: center; font-size: 14px;">注:本通知单一式三联,当事单位(人)、制表部门、财务部门各执一份。</span></div>
</div>
<div class="g-grid4">
<div>
分管领导审批:
<span>{{ penaltyRequestForm.departmentHeadApproval }}</span>
</div>
<div>
财务审核:
<span>{{ penaltyRequestForm.financialReview }}</span>
</div>
<div>
部门审核:
<span>{{ penaltyRequestForm.departmentReview }}</span>
</div>
</div>
<div class="g-grid5">
<div style="display:flex;justify-content: flex-end;"><span>制表日期: {{ penaltyRequestForm.createTime }} </span></div>
</div>
</div>
</div>
</template>
<style scoped>
.g-grid-box {
border: 1px solid #666666;
}
.g-item {
line-height: 30px;
border: 1px solid #666666;
padding: 4px;
}
.center {
text-align: center;
}
.g-grid {
display: grid;
grid-template-columns: 130px 1fr 130px 1fr;
}
.g-grid1 {
display: grid;
grid-template-columns: 130px 1fr;
}
.g-grid2 {
display: grid;
grid-template-columns: 130px 1fr 130px 1fr;
}
.grid3 {
display: grid;
grid-template-columns: 1fr 1fr;
}
.g-grid4 {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.g-grid4 div {
padding: 2px;
}
.g-grid4 div span {
padding: 0 2px;
}
.checkbox-custom {
width: 18px; /* 调整多选框宽度 */
height: 18px; /* 调整多选框高度 */
background-color: #fff;
border: 2px solid #666666;
border-radius: 4px;
position: relative;
cursor: pointer;
display: inline-block;
margin-left: 10px;
}
.checkbox-custom::after {
content: "";
width: 6px; /* 调整勾选标记的宽度 */
height: 12px; /* 调整勾选标记的高度 */
border: solid #666666;
border-width: 0 2px 2px 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(45deg);
opacity: 0; /* 默认隐藏 */
}
.checkbox-custom.checked::after {
opacity: 1; /* 显示勾选标记 */
}
.method-box {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding: 0 20px;
}
.method-box div {
display: flex;
align-items: center;
}
.g-grid5 {
display: grid;
grid-template-columns: 1fr;
}
.g-grid5 div {
padding: 2px;
}
.g-grid5 div span {
padding: 0 2px;
}
.g-grid6 {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
}
.line-center {
display: flex;
flex-direction:row;
justify-content: center;
align-items: center;
}
.line-right {
display: flex;
flex-direction:row;
justify-content: flex-end;
align-items: center;
}
.xuxian {
height: 0;
width: 100%;
border-bottom: 1px dashed #ccc;
}
</style>
2、在components目录下新建paymentRequestForm.vue
<script setup>
import { reactive, ref } from "vue";
let paymentRequestForm = reactive({
// id
id: '',
// 申请日期
requestDate: "2024年12月12日",
// 收款单位
payee: "重庆收费有限公司",
// 收款地址
payeeAddress: "重庆市江北区观音桥街道建新北路1号",
// 开户银行
bankName: "中国建设银行重庆分行沙坪坝支行",
// 账号
account: "62220231234567890",
// 付款金额¥
paymentAmount: "678860.00",
// 款项用途
paymentPurpose: "你该付钱那!!!",
// 付款金额(大写)
paymentAmountInWords: "陆拾柒万捌千捌佰陆拾元",
// 申请部门
applyingDepartment: "重庆办事处",
// 申请人
applicant: "代某某",
// 对账确认
reconciliationConfirmation: "付某",
// 开票确认
invoicingConfirmation: "李某",
// 付款方式
paymentMethod: {
// 银行转账
bankTransfer: false,
// 汇款
remittance: false,
// 现金
cash: true,
},
// 备注
remark: "备注备注备注备注备注备注",
// 分管领导审批
departmentHeadApproval: "孙总",
// 财务审核
financialReview: "祝总",
// 部门审核
departmentReview: "李总",
});
</script>
<template>
<div>
<div class="bottom-list">
<h1 style="text-align: center">重庆XXXXXXXX有限公司</h1>
<h2 style="text-align: center">付款申请单</h2>
<h3 style="text-align: right">
申请日期:
<span style="padding: 0 10px">{{ paymentRequestForm.requestDate }}</span>
</h3>
<div class="g-grid-box">
<div class="g-grid">
<div class="g-item center">收款单位</div>
<div class="g-item">{{ paymentRequestForm.payee }}</div>
<div class="g-item center">收款地址</div>
<div class="g-item">{{ paymentRequestForm.payeeAddress }}</div>
</div>
<div class="g-grid">
<div class="g-item center">开户银行</div>
<div class="g-item">
{{ paymentRequestForm.bankName }}
</div>
<div class="g-item center">账号</div>
<div class="g-item">{{ paymentRequestForm.account }}</div>
</div>
<div class="g-grid">
<div class="g-item center">付款金额¥</div>
<div class="g-item">{{ paymentRequestForm.paymentAmount }}</div>
<div class="g-item center">款项用途</div>
<div class="g-item">{{ paymentRequestForm.paymentPurpose }}</div>
</div>
<div class="g-grid1">
<div class="g-item center">付款金额(大写)</div>
<div class="g-item" colspan="6">
{{ paymentRequestForm.paymentAmountInWords }}
</div>
</div>
<div class="g-grid">
<div class="g-item center">申请部门</div>
<div class="g-item">{{ paymentRequestForm.applyingDepartment }}</div>
<div class="g-item center">申请人</div>
<div class="g-item">{{ paymentRequestForm.applicant }}</div>
</div>
<div class="grid3">
<div class="g-grid">
<div class="g-item center">对账确认</div>
<div class="g-item">
{{ paymentRequestForm.reconciliationConfirmation }}
</div>
<div class="g-item center">开票确认</div>
<div class="g-item">
{{ paymentRequestForm.invoicingConfirmation }}
</div>
</div>
<div class="g-grid1">
<div class="g-item center">付款方式</div>
<div class="g-item method-box">
<div>
转账
<span
:class="{ 'checkbox-custom': true, checked: paymentRequestForm.paymentMethod.bankTransfer }"
></span>
</div>
<div>
汇款
<span
:class="{ 'checkbox-custom': true, checked: paymentRequestForm.paymentMethod.remittance }"
></span>
</div>
<div>
现金
<span
:class="{ 'checkbox-custom': true, checked: paymentRequestForm.paymentMethod.cash }"
></span>
</div>
</div>
</div>
</div>
<div class="g-grid1">
<div class="g-item center" style="line-height: 80px">备注</div>
<div class="g-item" colspan="6">{{ paymentRequestForm.remark }}</div>
</div>
</div>
<div class="g-grid4">
<div>
分管领导审批:
<span>{{ paymentRequestForm.departmentHeadApproval }}</span>
</div>
<div>
财务审核:
<span>{{ paymentRequestForm.financialReview }}</span>
</div>
<div>
部门审核:
<span>
{{ paymentRequestForm.departmentReview }}
</span>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.g-grid-box {
border: 1px solid #666666;
}
.g-item {
line-height: 40px;
border: 1px solid #666666;
padding: 8px;
}
.center {
text-align: center;
}
.g-grid {
display: grid;
grid-template-columns: 130px 1fr 130px 1fr;
}
.g-grid1 {
display: grid;
grid-template-columns: 130px 1fr;
}
.g-grid2 {
display: grid;
grid-template-columns: 130px 1fr 130px 1fr;
}
.grid3 {
display: grid;
grid-template-columns: 1fr 1fr;
}
.g-grid4 {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.g-grid4 div {
padding: 10px;
}
.g-grid4 div span {
padding: 0 10px;
}
.checkbox-custom {
width: 18px; /* 调整多选框宽度 */
height: 18px; /* 调整多选框高度 */
background-color: #fff;
border: 2px solid #666666;
border-radius: 4px;
position: relative;
cursor: pointer;
display: inline-block;
margin-left: 10px;
}
.checkbox-custom::after {
content: "";
width: 6px; /* 调整勾选标记的宽度 */
height: 12px; /* 调整勾选标记的高度 */
border: solid #666666;
border-width: 0 2px 2px 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(45deg);
opacity: 0; /* 默认隐藏 */
}
.checkbox-custom.checked::after {
opacity: 1; /* 显示勾选标记 */
}
.method-box {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding: 0 20px;
}
.method-box div {
display: flex;
align-items: center;
}
</style>
3、App.vue修改内容如下
<script setup>
import PenaltyRequisition from "./components/PenaltyRequisition.vue";
import PaymentRequisition from "./components/PaymentRequisition.vue";
</script>
<template>
<div id="PenaltyRequisition">
<PenaltyRequisition />
</div>
<button v-print="'PenaltyRequisition'">Print1</button>
<div id="PaymentRequisition">
<PaymentRequisition />
</div>
<button v-print="'PaymentRequisition'">Print2</button>
</template>
<style>
@media print {
}
</style>
4、打开页面出现的效果
5、点击打印1出现的效果
6、点击打印2出现的效果
四、通过添加border来测试解决问题
在一次使用vue的print.js打印简历的时候,会多出一个空白页,百度了一些博客,大致方法就是设置margin:0;但是我的项目依然是没有用。
突然想到了把边框打印出来,使用border:1px solid red;点击打印,发现空白页消失了,由于打印的是白色的纸,所以设置border:1px solid white;就可以解决此问题!
使用vue3-print-nb出现一个空白页,百度是找到改文章,我也引入使用。也是加上了border测试就OK了。
加上:style="border:1px solid white;" 或者 style="border:1px solid red;"
打印时只有1页了,后面只需要把red修改成white;把颜色由红边框修改成白边框,这样就看不见了。
五、通过查看打印内部元素是否有margin导致出险空白页
其它几乎所有的多打印一个空白页都是让查看打印内容是否有margin相关元素导致的,如果有考虑把由margin该为有padding实现。
1、height的100%可以考虑height为auto;
2、如果打印的是整页,则需要关注html的height和margin
html {
height: auto;
margin: 0px;
}