vue(網(wǎng)頁)實(shí)現(xiàn)多臺(tái)小票打印機(jī)實(shí)時(shí)打印

1.需求:

  • 商戶端后臺(tái)實(shí)時(shí)獲取后臺(tái)支付訂單狀態(tài),支付完成后根據(jù)單據(jù)內(nèi)容分配對應(yīng)打印機(jī)并自動(dòng)打印小票

2.設(shè)備/技術(shù)支持:

  • GP-C80180I佳博打印機(jī)(網(wǎng)口打印機(jī))
  • 電腦(windows)
  • c-lodop
  • websocket

3.實(shí)現(xiàn)步驟

實(shí)現(xiàn)原理:通過websocket與后臺(tái)建立實(shí)時(shí)連接,獲取打印消息,獲取到消息后自動(dòng)調(diào)用打印方法;打印時(shí)通過c-lodop插件獲取本地電腦打印機(jī),并與接口返回的打印機(jī)進(jìn)行匹配,根據(jù)獲取到的打印機(jī)索引值開啟對應(yīng)的打印機(jī)
  1. 打印機(jī)配置:
  • 打印機(jī)連接路由器,配置ip地址
  • 下載安裝驅(qū)動(dòng)(找到對應(yīng)型號)
  • 安裝成功后,打印機(jī)列表會(huì)顯示出打印機(jī)名稱
  • 在電腦上找到對應(yīng)的打印,配置(打印機(jī)屬性->端口->添加端口(端口號為打印機(jī)ip地址))
  • 配置完成后,可以手動(dòng)執(zhí)行cmd命令連接打印機(jī)(默認(rèn)是未連接的)
//telnet + 空格 + ip + 空格 + 端口號
telnet 192.168.5.6 9100  (打印機(jī)端口號,注意格式)
  • 連接成功跳后,會(huì)打開全黑的cmd窗口,隨便輸入字符,回車,打印機(jī)會(huì)自動(dòng)打印輸入的內(nèi)容
  1. 插件配置
  • 下載C-Lodop
  • 安裝
  • 設(shè)置->端口設(shè)置(端口1自定義設(shè)置(非必要):8099,注意這里如果修改了要跟下邊代碼里配置的保持一致)


    image.png

    image.png

    image.png

3.具體代碼實(shí)現(xiàn)

  • 在項(xiàng)目代碼里,引入官方下載包里的LodopFuncs.js文件(要想在vue里使用需要做出一定修改)
1. 端口配置,需要跟上邊服務(wù)端口等保持一致,否則無法正常連接
//用雙端口加載主JS文件Lodop.js(或CLodopfuncs.js兼容老版本)以防其中某端口被占:
var MainJS = "CLodopfuncs.js",
 URL_WS1 = "ws://localhost:8099/" + MainJS,                //ws用8000/18000
 URL_WS2 = "ws://localhost:18000/" + MainJS,
 URL_HTTP1 = "http://localhost:8099/" + MainJS,              //http用8000/18000
 URL_HTTP2 = "http://localhost:18000/" + MainJS,
 URL_HTTP3 = "https://localhost.lodop.net:8443/" + MainJS;   //https用8000/8443

2. 文件底部增加導(dǎo)出代碼,否者在對應(yīng)vue文件導(dǎo)入時(shí)無法正常調(diào)用
export { getLodop,needCLodop  }; 

  • xx.vue(部分代碼)
import { getLodop, needCLodop } from '@/utils/initPrint.js'

export default {
    methods: {
        onMessage(e) {
      console.log('接收到消息!', e.data)
      let data = JSON.parse(e.data)
     // 自定義打印內(nèi)容
      let str = `
        <div>
          <h3 style="text-align: center;font-weight:400;">${data.enterpriseName}</h3>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">訂單類型:${this.formatOrderType(
            data.orderType
          )}</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">交易類型:${this.formatTradeType(
            data.tradeType
          )}</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">支付方式:${this.format(
            data.payType
          )}</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">打印類型:${
            data.printType == 1 ? '自動(dòng)打印' : '手動(dòng)打印'
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">支付時(shí)間:${
            data.createTime
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">訂 單 號:${
            data.orderNo || '-'
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">流 水 號:${data.flowNo}</div>

          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">員 工 ID:${
            data.createId
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">員工姓名:${
            data.createName
          }</div>

          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">結(jié)算金額:${
            data.payAmount
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">幣 種:元</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">設(shè) 備 號:${data.printNo}</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">設(shè)備名稱:${
            data.printName
          }</div>
          <div style="border-bottom: 1px dashed #000;height:1px;width:100%;margin-top:4px"></div>
          <div style="font-size:12px;margin-bottom:10px;margin-top:5px;">打印時(shí)間:${this.$date.formatDate(
            new Date(),
            'yyyy-MM-dd hh:mm:ss'
          )}</div>
        </div>
      `
      this.getPrinterList(str, data)
    },
// 獲取本地打印
getPrinterList(str, data) {
      if (needCLodop()) { // 這里時(shí)為了判斷插件是否初始化完成,不加這個(gè)判斷,直接調(diào)用getLodop()方法,會(huì)提示“網(wǎng)頁還沒下載完畢,請稍等一下再操作.”
        let LODOP = getLodop()
        this.printNameList = []
        let counter = LODOP.GET_PRINTER_COUNT() // 獲取打印機(jī)個(gè)數(shù)
        let index = -1

        for (let i = 0; i < counter; i++) {
          //將打印機(jī)存入printList數(shù)組中
          this.printNameList.push({
            index: i,
            name: LODOP.GET_PRINTER_NAME(i),
          })
          if (LODOP.GET_PRINTER_NAME(i) === data.printNo) { // 匹配對應(yīng)的打印機(jī)
            index = i
          }
        }

        if (index >= 0 && LODOP.SET_PRINTER_INDEXA(index)) { // 此處是根據(jù)對應(yīng)打印機(jī)的索引值,找到并開啟打印
          
          LODOP.SET_PRINT_PAGESIZE(3, 800, 80, '小票')
          LODOP.ADD_PRINT_HTM(10, 10, '100%', 80, str)
          // LODOP.PREVIEW() //預(yù)覽打印
          LODOP.PRINT() //直接打印
        } else {
          this.$notification.error({
            key: 'api-error',
            message: '此電腦未配置' + data.printNo + '打印機(jī),請配置打印機(jī)后,重新登錄本系統(tǒng)。',
            description: '',
          })
        }
        window.On_CLodop_Opened = null
      }
    },
    }
}
  • 完整代碼
<script>

import { getLodop, needCLodop } from '@/utils/initPrint.js'

export default {
computed: {
    ...mapState({
      printState: (state) => state.user.printState,
    }),
  },
  watch: {
  // 監(jiān)聽打印開啟狀態(tài)
    printState: {
      handler(val) {
         // 頁面刷新后printState會(huì)被初始化,所以再獲取下瀏覽器存儲(chǔ)的狀態(tài)
        let flag = sessionStorage.getItem('printState')
          // 如果頁面刷新了,刷新前開啟了打印,這自動(dòng)與后臺(tái)建立連接
        if (flag == 'true' && !val) {
          this.$store.commit('START_PRINT', true)
        } else {
          if (val) {
            this.initWebsocket(this.$store.getters.userInfo.id)
          } else {
            this.closeSocket()
          }
        }
      },
      immediate: true,
      deep: true,
    },
  },
methods: {
    initWebsocket(id) {
      let that = this
      this.$ws = new WebSocket('ws://xxxxxxxxx/websocket/link?id=' + id)
      this.$ws.onopen = function (evt) {
        that.onOpen(evt)
      }
      this.$ws.onclose = function (evt) {
        that.onClose(evt)
      }
      this.$ws.onmessage = function (evt) {
        that.onMessage(evt)
      }
      this.$ws.onerror = function (evt) {
        that.onError(evt)
      }
    },
    onMessage(e) { // 接收到消息后自動(dòng)打印
      console.log('接收到消息!', e.data)
      let data = JSON.parse(e.data)
      let str = `
        <div>
          <h3 style="text-align: center;font-weight:400;">${data.enterpriseName}</h3>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">訂單類型:${this.formatOrderType(
            data.orderType
          )}</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">交易類型:${this.formatTradeType(
            data.tradeType
          )}</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">支付方式:${this.format(
            data.payType
          )}</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">打印類型:${
            data.printType == 1 ? '自動(dòng)打印' : '手動(dòng)打印'
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">支付時(shí)間:${
            data.createTime
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">訂 單 號:${
            data.orderNo || '-'
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">流 水 號:${data.flowNo}</div>

          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">員 工 ID:${
            data.createId
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">員工姓名:${
            data.createName
          }</div>

          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">結(jié)算金額:${
            data.payAmount
          }</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">幣 種:元</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">設(shè) 備 號:${data.printNo}</div>
          <div style="font-size:12px;margin-bottom:2px;display:inline-block;width:100%;">設(shè)備名稱:${
            data.printName
          }</div>
          <div style="border-bottom: 1px dashed #000;height:1px;width:100%;margin-top:4px"></div>
          <div style="font-size:12px;margin-bottom:10px;margin-top:5px;">打印時(shí)間:${this.$date.formatDate(
            new Date(),
            'yyyy-MM-dd hh:mm:ss'
          )}</div>
        </div>
      `
      this.getPrinterList(str, data)
    },
    formatOrderType(val) {
      let name = ''
      if (val == 1) {
        name = '支付單'
      } else if (val == 2) {
        name = '退款單'
      } else {
        name = '其它'
      }
      return name
    },
    format(val) {
      let name = ''
      if (val == 1) {
        name = '支付寶'
      } else if (val == 2) {
        name = '微信'
      } else {
        name = '其它'
      }
      return name
    },
    formatTradeType(val) {
      let name = ''
      if (val == 1) {
        name = '碼牌支付'
      } else if (val == 2) {
        name = '動(dòng)態(tài)二維碼支付'
      }
      return name
    },
    getPrinterList(str, data) {
      if (needCLodop()) {
        let LODOP = getLodop()
        this.printNameList = []
        let counter = LODOP.GET_PRINTER_COUNT() // 獲取打印機(jī)個(gè)數(shù)
        let index = -1

        for (let i = 0; i < counter; i++) {
          //將打印機(jī)存入printList數(shù)組中
          this.printNameList.push({
            index: i,
            name: LODOP.GET_PRINTER_NAME(i),
          })
          if (LODOP.GET_PRINTER_NAME(i) === data.printNo) {
            index = i
          }
        }

        if (index >= 0 && LODOP.SET_PRINTER_INDEXA(index)) {
          //預(yù)覽打印
          LODOP.SET_PRINT_PAGESIZE(3, 800, 80, '小票')
          LODOP.ADD_PRINT_HTM(10, 10, '100%', 80, str)
          // LODOP.PREVIEW()
          LODOP.PRINT()
        } else {
          this.$notification.error({
            key: 'api-error',
            message: '此電腦未配置' + data.printNo + '打印機(jī),請配置打印機(jī)后,重新登錄本系統(tǒng)。',
            description: '',
          })
        }
        window.On_CLodop_Opened = null
      }
    },
    closeSocket() {
      this.$ws.close()
    },
    onClose(e) { // 斷開連接增加全局彈框提示
      console.log('斷開連接!', e)
      let that = this
      if (this.printState) {
        this.$confirm({
          title: '提示?',
          content: '小票打印服務(wù)已斷開,是否嘗試重新連接?',
          okText: '確認(rèn)',
          cancelText: '取消',
          onOk() {
            that.initWebsocket(that.$store.getters.userInfo.id)
          },
          onCancel() {
            sessionStorage.setItem('printState', false)
            that.$store.commit('START_PRINT', false)
          },
        })
      } else {
        this.$message.error('連接已斷開!')
      }
    },
    onOpen(e) {
      console.log('建立連接!', e)
      this.$message.success('連接成功!')
    },
    onError(e) {
      this.$message.error('打印功能連接出錯(cuò),請重新連接!')
      console.log('出錯(cuò)啦!', e)
    },

}

備注:

  • c-lodop功能強(qiáng)大滿足目前需求,但是通過接口直接打印,打印出的小票底部帶有“本頁”
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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