vue3 html2canvas+jspdf 實現(xiàn)小票打印功能

html2canvas把dom生成圖片 然后通過jspdf生成pdf去打印

<template>

  <div class="body">
    <div style="width: 100%;display:flex;justify-content: center;">
      <a-button @click="onPrintSubmit" class="printBtn" type="primary" shape="round" size="large">
        確認(rèn)打印
      </a-button>
    </div>
    <div class="receipt" ref="receipt">
      <div class="shopName">
        {{ printData?.shopName }}
      </div>
      <div class="totalIncome">
        匯總收入
      </div>
      <div class="prinitTime">
        <div class="label"><span>開始時間:</span><span>{{ starTime }}</span></div>
        <div class="label"><span>結(jié)束時間:</span><span>{{ endTime }}</span></div>
        <div class="label"><span>制單時間:</span><span>{{ currenTime }}</span></div>
      </div>
      <div class="line"></div>
      <div>
        <div class="section items">
          <div class="table">
            <div class="title">
              <div class="label1">菜品</div>
              <div class="label2">數(shù)量</div>
              <div class="label3">實收金額</div>
            </div>
            <div class="column" v-for="item in printData?.singleProductSummaryDataList">
              <div class="label1">{{ item.productName }}</div>
              <div class="label2">{{ item.salesVolume }}</div>
              <div class="label3">{{ item.salesAmount }}</div>
            </div>
          </div>

        </div>
        <div class="prinitTime">
          <div class="label">營業(yè)應(yīng)收總額:{{ printData?.totalReceivables }}</div>
          <div class="label">營業(yè)實際收入: {{ printData?.realTotalAmountReceived }}元</div>
        </div>
        <div class="line"></div>
        <div class="section items">
          <div class="table">
            <div class="title">
              <div class="label1"> </div>
              <div class="label2">訂單數(shù)量</div>
              <div class="label3">總額</div>
            </div>
            <!-- <div class="column">
              <div class="label1">訂單原價</div>
              <div class="label2">{{ printData?.orderOriginalPrice }}</div>
              <div class="label3">{{ printData?.orderOriginalPrice }}</div>
            </div> -->
            <div class="column">
              <div class="label1">微信支付</div>
              <div class="label2">{{ printData?.wechatOrderTotal }}</div>
              <div class="label3">{{ printData?.wechatOrderTotalAmount }}</div>
            </div>
            <div class="column">
              <div class="label1">余額支付</div>
              <div class="label2">{{ printData?.personalBalancePayOrderTotal }}</div>
              <div class="label3">{{ printData?.personalBalancePayOrderTotalAmount }}</div>
            </div>
            <div class="column">
              <div class="label1">餐卡支付</div>
              <div class="label2">{{ printData?.mealCardPayOrderTotal }}</div>
              <div class="label3">{{ printData?.mealCardPayOrderTotalAmount }}</div>
            </div>
            <div class="column">
              <div class="label1">優(yōu)惠券優(yōu)惠</div>
              <div class="label2">{{ printData?.redPacketOrderTotal }}</div>
              <div class="label3">{{ printData?.redPacketTotalAmount }}</div>
            </div>
            <div class="column">
              <div class="label1">員工優(yōu)惠</div>
              <div class="label2">{{ printData?.employeeDiscountOrderTotal }}</div>
              <div class="label3">{{ printData?.employeeDiscountOrderTotalAmount }}</div>
            </div>
            <div class="column">
              <div class="label1">退款總額</div>
              <div class="label2"></div>
              <div class="label3">{{ printData?.refundTotalAmount }}</div>
            </div>
          </div>

        </div>

      </div>
    </div>
  </div>
</template>

<script setup>
import { ref,  onMounted } from "vue";
import { getCurrentDateTime, getCurrentYYMMDD } from "/src/utils/utils.js"
import html2canvas from "html2canvas";
import jsPDF from "jspdf";

const receipt = ref(null);

const props = defineProps({
  printData: {
    type: Object,
    default: {},
  },
  starTime: {
    type: Object,
    default: getCurrentYYMMDD() + ' 00:00:00',
  },
  endTime: {
    type: Object,
    default: getCurrentYYMMDD() + ' 23:59:59',
  },
});


const currenTime = ref(null)
onMounted(() => {
  currenTime.value = getCurrentDateTime()
})

const onPrintSubmit = async () => {
  const element = receipt.value;
  const elementWidth = element.offsetWidth;
  const elementHeight = element.offsetHeight;

  const scale = 12; // 縮小比例   我是在小票機(jī)上打印的 應(yīng)該是 縮放比例越小打印的越清晰  當(dāng)然了  加載的時候就會略慢一下
  const canvasWidth = elementWidth * scale;
  const canvasHeight = elementHeight * scale;

  html2canvas(element, { scale }).then((canvas) => {
    const imgData = canvas.toDataURL("image/png");

    const pdf = new jsPDF({
      orientation: "p",
      unit: "px",
    });

    const pageWidth = pdf.internal.pageSize.getWidth();
    const pageHeight = pdf.internal.pageSize.getHeight();

    // 計算比例,保持圖片等比例縮放
    const ratio = Math.min(pageWidth / canvasWidth, pageHeight / canvasHeight);
    const imgWidth = canvasWidth * ratio;
    const imgHeight = canvasHeight * ratio;

    // 居中顯示圖片
    const x = (pageWidth - imgWidth) / 2;
    const y = (pageHeight - imgHeight) / 2;
    //                                                  X   Y   
    pdf.addImage(imgData, "PNG", 15, 20, imgWidth / 2.8, imgHeight / 2.8);
    //  解釋一下為什么這里要/2.8       比如 打印在A4上面 W是21  但是圖片是41的話 這時候 你就要自己去等比的縮放了
    pdf.autoPrint();

    const pdfURL = pdf.output("bloburl");
    const printWindow = window.open(pdfURL, "_blank");
    printWindow.focus();
  }).catch((error) => {
    console.error("打印失?。?, error);
  });
}
</script>

<style scoped>
.body {

  margin: 0;

}

.printBtn {
  margin: 0 auto;
}

.line {
  margin-top: 6px;
  width: 100%;
  height: 1px;
  border-bottom: 1px dotted #000000;
}

.shopName {

  width: 260px;
  text-align: center;
  font-weight: bold;
  font-size: 20px
}

.totalIncome {
  padding: 0;
  width: 260px;
  margin: 0 auto 0;
  text-align: center;
  font-size: 14px
}


.prinitTime {
  font-size: 16PX;
  margin-top: 4px;
}

.receipt {
  font-family: Microsoft Sans-serif;
  color: #000;


  width: 100%;
  max-height: 700px;

}

.receipt h2 {
  text-align: center;
  margin-bottom: 20px;
}

.receipt .section {
  margin-bottom: 20px;
}

.receipt .section .label {
  font-weight: bold;
}

.receipt .section .value {
  margin-left: 10px;
}

.receipt .total {
  font-weight: bold;
  font-size: 1.2em;
}

.receipt .items .table {
  margin-top: 20px;
  width: 100%;
  border-collapse: collapse;
}

.table .title,
.table .column {
  font-family: Microsoft Sans-serif;
  display: flex;
}

.table .label1 {
  width: 160px;
  font-size: 16px;
}

.table .label2,
.table .label3 {
  width: 90px;
  font-size: 16px;
  text-align: right;
}

/* 打印樣式 */
@media print {
  .print-button {
    display: none;
  }

  .receipt {
    width: 100%;
    padding: 0;
    margin: 0;
    border: none;
    font-size: 12px;
    /* 調(diào)整字體大小 */
  }

  .receipt .items table th,
  .receipt .items table td {
    padding: 2px;
  }

  .receipt .section {
    margin-bottom: 10px;
  }
}
</style>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容