我一直在开发一个 Vue.js 应用程序来生成发票,此过程的一部分涉及确保每个打印页面显示正确的页码。然而,我遇到了一个障碍:当我打印发票时,所有页面都被标记为“第 1 页,共 20 页”,无论它们在文档中的实际位置如何。这种不一致令人费解,我不知道如何解决它。任何有关故障排除和解决此问题的见解或建议将不胜感激。 这是代码:
<template>
<div style="background-color: lightgray" >
<div style="background-color: white;margin: auto;width: 29.7cm" id="printable-content">
<div class="tfoot " id="pageFooter" style="display: none">
<div class="footerHolder" style="">
<div class="invoice-footer">
<div class="" style="border: 1px solid lightgray;border-radius: 8px;padding: 10px 10px 0">
<div style="display: flex;justify-content: space-between;gap: 30px">
<div style="width: 50%;border-right: 1px solid lightgray;padding-right: 10px">
<h6 class="font-size-12">Köpare</h6>
<div style="display: flex;justify-content: space-between;gap: 20px">
<div style="width: 50%;">
<label for="">Datum</label>
</div>
<div style="width: 50%;">
<label for="">Ort</label>
</div>
</div>
<div class="pb-2">
<label for="">Signatur</label>
</div>
</div>
<div style="width: 50%">
<h6 class="font-size-12">Säljare</h6>
<div style="display: flex;justify-content: space-between;gap: 20px">
<div style="width: 50%;">
<label for="">Datum</label>
</div>
<div style="width: 50%;">
<label for="">Ort</label>
</div>
</div>
<div class="pb-2">
<label for="">Signatur</label>
</div>
</div>
</div>
</div>
<small style="font-size: 8px"> Köparen har tagit del av och godkänt Testbolaget Bil ABs
integritetspolicy</small>
<div class="mt-2"
style=" display: flex; justify-content: space-between; border-top: 1px solid lightgray; padding: 10px;">
<div>
<h6 class="font-size-12">xxx</h6>
<div class="font-size-10">
<div>Munkforsplan 37</div>
<div> xxxxxx</div>
<div> xxxx</div>
<div>xxxxxx</div>
</div>
</div>
<div>
<h6 class="font-size-12">Kontaktuppgifter</h6>
<div class="d-flex gap-1 font-size-10">
<div>
<div>Telefon:</div>
<div>E-post</div>
<div>Hemsidan:</div>
<div>Adress:</div>
</div>
<div>
<div>xxx</div>
<div>xxx</div>
<div>xxx</div>
<div>xxxxxxx</div>
</div>
</div>
</div>
<div>
<h6 class="font-size-12">Betalningsuppgifter</h6>
<div class="d-flex gap-1 font-size-10">
<div>
<div>Bank:</div>
<div>Bankkonto</div>
<div>Bankgiro:</div>
<div>Plusgiro:</div>
<div>Swish:</div>
</div>
<div>
<div>SEB</div>
<div>2311 321231233122</div>
<div>321-31111</div>
<div>321-31111</div>
<div>S070 414 3308</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Display the page number -->
<div class="page-number"></div>
</div>
<table >
<thead>
<tr>
<td>
<div class="invoice-header d-flex align-baseline justify-content-between">
<div class="d-flex align-baseline justify-content-between flex-column">
<div>
<h2 style=" font-weight: 500; color: #191919;font-size: 32px">Köpavtal</h2>
<div>No:12312312312312</div>
<div>Invoice date: 12312312312312</div>
<div>xxx</div>
</div>
</div>
<div class="d-flex align-baseline flex-column">
<div class="mt-2">
<h5>Kunduppgifter</h5>
<div>xxxxx</div>
<div>xxxxx</div>
<div>xxxxxxx</div>
<div>xxxxxxx</div>
</div>
</div>
</div>
<div class="page-header-space"></div>
</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="invoice-body mt-1">
<div style="" class="mb-3">
<h5>text</h5>
<div style="border: 1px solid lightgray; border-radius: 8px; display: flex; flex-direction: column;">
<div
style=" display: flex; justify-content: space-between; border-bottom: 1px solid lightgray; padding: 10px;">
<div>
<label for="">text</label>
<div>text</div>
</div>
<div>
<label for="">text</label>
<div>text-text -text</div>
</div>
<div>
<label for="">text</label>
<div>text</div>
</div>
<div>
<label for="">text</label>
<div>text</div>
</div>
<div>
<label for="">text</label>
<div>text</div>
</div>
</div>
<div style=" display: flex; justify-content: space-between; padding: 10px;">
<div>
<label for="">text</label>
<div>text</div>
</div>
<div>
<label for="">text</label>
<div>654564</div>
</div>
<div>
<label for="">text</label>
<div>text</div>
</div>
<div>
<label for="">text</label>
<div>text</div>
</div>
<div>
<label for="">Garanti</label>
<div>text</div>
</div>
<div>
<label for="">Momsredovisning</label>
<div>text</div>
</div>
</div>
</div>
</div>
<div class="invoiceTableHolder">
<table class="invoice-table table">
<thead>
<tr>
<th>Item</th>
<th>Qty</th>
<th>Pris ex.</th>
<th>Moms</th>
<th>Pris ink.</th>
<th>Totalt</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in items" :key="item.id">
<td>{{ item.name }} {{ index }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price }} sek</td>
<td>{{ item.vat }} sek</td>
<td>{{ item.price_in }} sek</td>
<td>{{ item.totalt }} sek</td>
</tr>
<tr v-for="(item,index) in items" :key="item.id">
<td>{{ item.name }} {{ index }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price }} sek</td>
<td>{{ item.vat }} sek</td>
<td>{{ item.price_in }} sek</td>
<td>{{ item.totalt }} sek</td>
</tr>
<tr v-for="(item,index) in items" :key="item.id">
<td>{{ item.name }} {{ index }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price }} sek</td>
<td>{{ item.vat }} sek</td>
<td>{{ item.price_in }} sek</td>
<td>{{ item.totalt }} sek</td>
</tr>
<tr v-for="(item,index) in items" :key="item.id">
<td>{{ item.name }} {{ index }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price }} sek</td>
<td>{{ item.vat }} sek</td>
<td>{{ item.price_in }} sek</td>
<td>{{ item.totalt }} sek</td>
</tr>
<tr v-for="(item,index) in items" :key="item.id">
<td>{{ item.name }} {{ index }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price }} sek</td>
<td>{{ item.vat }} sek</td>
<td>{{ item.price_in }} sek</td>
<td>{{ item.totalt }} sek</td>
</tr>
<tr v-for="(item,index) in items" :key="item.id">
<td>{{ item.name }} {{ index }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price }} sek</td>
<td>{{ item.vat }} sek</td>
<td>{{ item.price_in }} sek</td>
<td>{{ item.totalt }} sek</td>
</tr>
</tbody>
</table>
</div>
<div class="mt-2 rejectBreak" style="border: 1px solid lightgray;border-radius: 8px;padding: 10px">
<div class="finansHolder d-flex">
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx %</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx %</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxxr</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
<div>
<label for="">xxx</label>
<div>xxx</div>
</div>
</div>
</div>
<div class="mt-2 mb-3 rejectBreak" style="border: 1px solid lightgray;border-radius: 8px;padding: 10px">
<h6 class="font-size-12">Notering</h6>
<div style="min-height: 10px">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean
massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
</div>
</div>
</div>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>
<div class="tfootHolder">
<div class="footerHolder" style="">
<div class="invoice-footer">
<div class="" style="border: 1px solid lightgray;border-radius: 8px;padding: 10px 10px 0">
<div style="display: flex;justify-content: space-between;gap: 30px">
<div style="width: 50%;border-right: 1px solid lightgray;padding-right: 10px">
<h6 class="font-size-12">Köpare11</h6>
<div style="display: flex;justify-content: space-between;gap: 20px">
<div style="width: 50%;">
<label for="">Datum</label>
</div>
<div style="width: 50%;">
<label for="">Ort</label>
</div>
</div>
<div class="pb-2">
<label for="">Signatur</label>
</div>
</div>
<div style="width: 50%">
<h6 class="font-size-12">Säljare</h6>
<div style="display: flex;justify-content: space-between;gap: 20px">
<div style="width: 50%;">
<label for="">Datum</label>
</div>
<div style="width: 50%;">
<label for="">Ort</label>
</div>
</div>
<div class="pb-2">
<label for="">Signatur</label>
</div>
</div>
</div>
</div>
<small style="font-size: 8px"> Köparen har tagit del av och godkänt Testbolaget Bil ABs
integritetspolicy</small>
<div class="mt-2"
style=" display: flex; justify-content: space-between; border-top: 1px solid lightgray; padding: 10px;">
<div>
<h6 class="font-size-12">xxx</h6>
<div class="font-size-10">
<div>xxx 37</div>
<div> xxxxxx</div>
<div> xxxx</div>
<div>xxxxxx</div>
</div>
</div>
<div>
<h6 class="font-size-12">Kontaktuppgifter</h6>
<div class="d-flex gap-1 font-size-10">
<div>
<div>Telefon:</div>
<div>E-post</div>
<div>Hemsidan:</div>
<div>Adress:</div>
</div>
<div>
<div>xxxxx</div>
<div>xxxx</div>
<div>xxxx</div>
<div>xxxxxxx</div>
</div>
</div>
</div>
<div>
<h6 class="font-size-12">Betalningsuppgifter</h6>
<div class="d-flex gap-1 font-size-10">
<div>
<div>Bank:</div>
<div>Bankkonto</div>
<div>Bankgiro:</div>
<div>Plusgiro:</div>
<div>Swish:</div>
</div>
<div>
<div>xx</div>
<div>xxx</div>
<div>xx-x</div>
<div>xxx-xxx</div>
<div>xxx</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="page-footer-space"></div>
</div>
<div class="page-footer-space"></div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
<div class="invoice">
<!-- Your invoice content here -->
<!-- Page number -->
<span class="page-number"> <span class="page-counter"></span></span>
</div>
</template>
<script>
export default {
data() {
return {
pageNumber: 1, // Initialize the page number
items: [
{name: "Item 1", quantity: 2, price: 10, vat: 20, price_in: 1200, totalt: 2000},
{name: "Item 2 with a long name that needs to be truncated", quantity: 1, price: 20},
{name: "Item 3", quantity: 3, price: 15},
{name: "Item 1", quantity: 2, price: 10},
{name: "Item 2 with a long name that needs to be truncated", quantity: 1, price: 20},
{name: "Item 3", quantity: 3, price: 15},
{name: "Item 3", quantity: 3, price: 15},
]
};
},
methods: {
limitNameLength(name) {
const maxLength = 20;
return name.length > maxLength ? name.substring(0, maxLength) + '...' : name;
},
updatePageCounter(totalPages) {
const currentPage = this.pageNumber; // Use the component's data property
this.$nextTick(() => {
const pageCounterElement = document.querySelector('.page-counter');
if (pageCounterElement) {
document.querySelector('.page-counter').textContent = currentPage;
pageCounterElement.textContent = `Page ${currentPage} of ${totalPages}`;
}
});
},
},
mounted() {
const totalPages = 20;
this.updatePageCounter(totalPages);
},
};
</script>
<style lang="scss">
thead td, tfoot td {
padding: 20px;
}
tbody tr td {
padding: 5px 20px;
}
.rejectBreak {
page-break-after: always;
}
@media print {
.page-footer {
position: fixed;
bottom: 0;
right: 0;
left: 0;
padding: 10px;
background-color: white;
border-top: 1px solid lightgray;
text-align: right;
thead {
display: table-header-group;
}
}
tfoot {
display: table-footer-group;
}
button {
display: none;
}
body {
margin: 0;
}
tfoot .tfootHolder {
display: none;
}
.tfoot {
display: block !important;
padding: 20px;
position: fixed;
bottom: 0;
width: 29.7cm;
}
.page-footer-space {
height: 300px;
}
@page {
size: A4;
}
.page {
page-break-after: always;
position: relative;
height: 95vh; /* Adjust based on your content and page size */
padding: 20px;
}
.page:last-child {
page-break-after: avoid;
}
.page-number {
position:fixed;
bottom: 10px;
right: 50px;
font-size: 12px;
}
.page-counter::before {
content: counter();
}
}
</style>
许多 vue 代码可以正确计数但不起作用。
在 Vue 中,不应使用
document.querySelector
,而应使用 ref
(如果使用 Vue 3):
<template>
<div ref="myDiv">lorem ipsum</div>
</template>
<script>
const myDiv = ref(null); // Initialize as null, make sure the variable has the same name as the ref attribute on the div.
</script>
在 Vue 2 中,你会这样做:
<template>
<div ref="myDiv">lorem ipsum</div>
</template>
<script>
export default {
mounted() {
this.$refs.myDiv.innerHTML = 'Page number…';
}
}
</script>
另外,我不确定当您处于打印对话框中时 $nextTick 是否会起作用。
一个想法:
循环查看发票并设置每张发票的高度
<div>
以匹配您要打印的纸张:
<div class="page" v-for="(invoice, index) in invoices" :key="invoice">
<span>Page {{ index + 1 }}</span>
</div>
<style>
@media print {
.page {
height: 793px; /* about 1 A4 page */
break-after: always; /* force page break */
}
}
</style>