vue print function

Requirements:
request back-end data, render it into a form, and print it out through a printer
insert image description here
insert image description here

Code implementation:
list.vue

<template>
  <div>
    <div class="printBox">
      <div>
        <el-button type="primary" @click="printBtn" size="small">打印</el-button>
      </div>
      <div ref="printContent">
        <div class="receiptListBox">
          <div class="time">
            预计到货日期:{
   
   {detailInfo.arrivalDate}}
          </div>
          <div class="typeNum">
            商品种类:{
   
   {detailInfo.totalSguQty}} 发货总数:{
   
   {detailInfo.totalGoodsQty}}
          </div>
          <!-- 表格: tableData表体数组 propsList表头 -->
          <print-table 
            v-if="detailInfo.orderGoodsSummaryVoList && detailInfo.orderGoodsSummaryVoList.length > 0"
            class="print-table" 
            :pages="false"
            :tableData="detailInfo.orderGoodsSummaryVoList"
            :propsList="propsList"
          />
        </div>
        <div class="curTime">
          打印时间:{
   
   {currentTime}}
        </div>
      </div>
    </div>
  </div>
</template>

<script>

const activityUrl = {
      
      
  // 合伙人-收货单详情
  receiveOrderSummaryDetail: '/bazaar/a/o/copartner/summaryOrder/receiveOrderSummaryDetail',
  // 合伙人-播种单
  selectSowOrder: '/bazaar/a/o/copartner/summaryOrder/selectSowOrder',
}

import Storage from "@/utils/localStorage"
import PrintTable from '@/components/Common/Print/PrintTable'
import winPrinter from '@/utils/winPrinter';
import {
      
      dateFormat} from '@/utils/utils'

export default {
      
      
  name: 'receiptDetail',
  data() {
      
      
    return {
      
      
      detailInfo: {
      
      },
      searchInfo: {
      
      },
      propsList: [
        {
      
      
          name: '序号',
          props: 'index',
          align: 'center'
        },
        {
      
      
          name: '商品编码',
          props: 'goodsNo',
          align: 'center'
        },
        {
      
      
          name: '商品名称',
          props: 'goodsName',
          align: 'center'
        },
        {
      
      
          name: '商品规格',
          props: 'spec',
          align: 'center'
        },
        {
      
      
          name: '存储温度',
          props: 'storageTypeName',
          align: 'center'
        },
        {
      
      
          name: '应收件数',
          props: 'totalQuantity',
          align: 'center'
        },
        {
      
      
          name: '发货件数',
          props: 'totalPickQty',
          align: 'center'
        },
        {
      
      
          name: '缺货件数',
          props: 'totalLackQty',
          align: 'center'
        }
      ],
      currentTime: dateFormat('yyyy-MM-dd HH:mm', new Date().getTime()), // 当前时间
    }
  },
  components: {
      
      
    'print-table': PrintTable
  },
  created() {
      
      
   let pathArr = this.$route.path.split('/')
    let pageId = pathArr[2]
    if (Storage.get('jumpReport') && Storage.get('jumpReport') != 'undefined') {
      
      
      let obj = Storage.get('jumpReport')
      for (let key in obj) {
      
      
        let keyArr = key.split('/')
        let _pageId = keyArr[1]
        if (_pageId == pageId) {
      
      
          let searchInfo = obj[key]['/report/48317/detail']
          this.searchInfo = searchInfo
          this.getDetail()
        }
     }
    }
    
  },
  methods: {
      
      
    printBtn() {
      
      
      this.currentTime = dateFormat('yyyy-MM-dd HH:mm', new Date().getTime())
      winPrinter(this.$refs.printContent)
    },
   
    getDetail(_param) {
      
      
      this.$loading.show()
      let params = {
      
       arrivalDate: this.searchInfo.arrivalDate }
      this.$http
        .post(activityUrl.receiveOrderSummaryDetail, params)
        .then((res) => {
      
      
          this.$loading.hide()
          if (res.code === 0) {
      
      
            // 获取表格数据
            if (res.data) {
      
      
              this.detailInfo = res.data
            } else {
      
      
              this.detailInfo = {
      
      }
            }
            return
          }
          throw new Error(res.msg)
        })
        .catch((e) => {
      
      
          this.$loading.hide()
          this.$notify.error({
      
      
            title: '提示',
            message: e.msg
          })
        })
    },
  }
}
</script>

PrintTable.view

<template>
  <table
    style="border: 1px solid #000 ; border-collapse:collapse"
    width="96%"
    cellspacing="0"
    cellpadding="0"
    v-html="tableHtmlData">
  </table>
</template>

<script>
import {
      
      fixedNum} from '@/utils/utils'
export default {
      
      
  name: 'PrintTable',
  props: {
      
      
    /*
    * 此处的tableData 是一个表格的数据, 多个表格要V-for 此组件
    * 格式:[{name:'葡萄',count:'1','payment':'¥12'}]
    * tableData
    *  */
    tableData: {
      
      
      type: Array,
      default: []
    },
    /*
    * 格式:[{name:'数量',props:'count'}]
    * data中props的属性
    *  */
    propsList: {
      
      
      type: Array,
      default: []
    },
    extraData: {
      
      
      type: Array,
      default: () => []
    },
    pages: {
      
      
      type: Boolean,
      default: true
    },
    showSequenceNum: {
      
      
      type: Boolean,
      default: false
    }
  },
  created () {
      
      
    this.tableHtmlData = this._getTableHtml(this.tableData, this.propsList)
  },
  watch: {
      
      
    tableData (newValue, oldValue) {
      
      
      if (newValue === oldValue) {
      
      
        return
      }
      this.tableHtmlData = this._getTableHtml(newValue, this.propsList)
    },
    propsList (newValue, oldValue) {
      
      
      if (newValue === oldValue) {
      
      
        return
      }
      this.tableHtmlData = this._getTableHtml(this.tableData, newValue)
    },
    pages(newValue, oldValue) {
      
      
      if (newValue === oldValue) {
      
      
        return
      }
      this.tableHtmlData = this._getTableHtml(this.tableData, this.propsList)
    }
  },
  computed: {
      
      },
  data () {
      
      
    return {
      
      
      tableHtmlData: ''
    }
  },
  methods: {
      
      
    /**
     *根据propsList创建出一个table 的内部Dom的innerHtml --> string
     * */
    _getTableHtml (data, propsList) {
      
      
      // data 数据
      // propsList 表头
      if (this.showSequenceNum) {
      
      
        let hasOrder = propsList.find((item) => {
      
      
          return item.name === '序号'
        })
        if (hasOrder == null) {
      
      
          propsList.splice(0, 0, {
      
      name: '序号', props: 'index'})
        }
      }
      // 表头
      let tableHtmlStr = '<thead><tr>'
      for (let item of propsList) {
      
      
        tableHtmlStr += `<th style="border: 1px solid #000"><font size="3">${ 
        item.name}</font></th>`
      }
      tableHtmlStr += '</tr></thead>'
      // 表体
      for (let dataIndex = 0; dataIndex < data.length; dataIndex++) {
      
      
        let item = data[dataIndex]
        item.index = dataIndex + 1
        let tempLabel = '<tr>'
        for (let i = 0; i < propsList.length; i++) {
      
      
          let tempItem = ''
          if (item.hasOwnProperty(propsList[i].props)) {
      
      
            if (/^([0-9]{1,}[.][0-9]*)$/.test(item[propsList[i].props])) {
      
      
              tempItem = fixedNum(item[propsList[i].props], 4)
            } else {
      
      
              tempItem = item[propsList[i].props]
            }
          }
          // 宽
          let width = ''
          if (propsList[i].hasOwnProperty('width')) {
      
      
            width = `width: ${ 
        propsList[i].width}`
          }
          // 对齐方式
          let align = propsList[i].hasOwnProperty('align') ? propsList[i].align : 'left'
          if (i === propsList.length - 1) {
      
      
            tempLabel += `<td style="border: 1px solid #000;text-align: ${ 
        align};${ 
        width}"><font size="3">${ 
        tempItem}<font></td></tr>`
          } else {
      
      
            tempLabel += `<td style="border: 1px solid #000;text-align: ${ 
        align};${ 
        width}"><font size="3">${ 
        tempItem}</font></td>`
          }
        }
        tableHtmlStr += tempLabel
      }
      let extraLable = ''
      let colspanLength = propsList.length
      if (this.extraData.length > 0) {
      
      
        for (let i = 0; i < this.extraData.length; i++) {
      
      
          extraLable += `<tr><td colspan="${ 
        colspanLength}" style="border: 1px solid #000;text-align: left;"><font size="3"><span>${ 
        this.extraData[i].name}:</span><span style="margin-left: 20px">${ 
        this.extraData[i].data}</span><font></td></tr>`
        }
        tableHtmlStr += extraLable
      }
      if (this.pages) {
      
      
        tableHtmlStr += `<tfoot><td tdata="pageNO" colspan=2 format="##" align="left"><p align="center">第<font color="#0000FF">##</font>页</p></td>
      <td colspan="${ 
        colspanLength - 1}"  tdata="pageCount" format="##" align="left">
        <p align="left">共<font color="#0000FF">##</font>页</p></td></tfoot>`
      }
      return tableHtmlStr
    }
  }
}
</script>

winPrinter.js

// 打印类属性、方法定义
const Print = function(dom, options) {
    
    
  if (!(this instanceof Print)) return new Print(dom, options);

  this.options = this.extend(
    {
    
    
      noPrint: '.no-print'
    },
    options
  );

  if (typeof dom === 'string') {
    
    
    this.dom = document.querySelector(dom);
  } else {
    
    
    this.isDOM(dom);

    this.dom = this.isDOM(dom) ? dom : dom.$el;
  }

  this.init();
};

Print.prototype = {
    
    
  init: function() {
    
    
    var content = this.getStyle() + this.getHtml();

    this.writeIframe(content);
  },

  extend: function(obj, obj2) {
    
    
    for (var k in obj2) {
    
    
      obj[k] = obj2[k];
    }

    return obj;
  },

  getStyle: function() {
    
    
    let str = '';
    let styles = document.querySelectorAll('style,link');

    for (var i = 0; i < styles.length; i++) {
    
    
      str += styles[i].outerHTML;
    }

    str += '<style>' + (this.options.noPrint ? this.options.noPrint : '.no-print') + '{display:none;}</style>';
    str += '<style>html,body,div{height: auto!important;}</style>';

    return str;
  },

  getHtml: function() {
    
    
    var inputs = document.querySelectorAll('input');

    var textareas = document.querySelectorAll('textarea');

    var selects = document.querySelectorAll('select');

    for (var k = 0; k < inputs.length; k++) {
    
    
      if (inputs[k].type == 'checkbox' || inputs[k].type == 'radio') {
    
    
        if (inputs[k].checked == true) {
    
    
          inputs[k].setAttribute('checked', 'checked');
        } else {
    
    
          inputs[k].removeAttribute('checked');
        }
      } else if (inputs[k].type == 'text') {
    
    
        inputs[k].setAttribute('value', inputs[k].value);
      } else {
    
    
        inputs[k].setAttribute('value', inputs[k].value);
      }
    }

    for (var k2 = 0; k2 < textareas.length; k2++) {
    
    
      if (textareas[k2].type == 'textarea') {
    
    
        textareas[k2].innerHTML = textareas[k2].value;
      }
    }

    for (var k3 = 0; k3 < selects.length; k3++) {
    
    
      if (selects[k3].type == 'select-one') {
    
    
        var child = selects[k3].children;

        for (var i in child) {
    
    
          if (child[i].tagName == 'OPTION') {
    
    
            if (child[i].selected == true) {
    
    
              child[i].setAttribute('selected', 'selected');
            } else {
    
    
              child[i].removeAttribute('selected');
            }
          }
        }
      }
    }

    return this.dom.outerHTML;
  },

  writeIframe: function(content) {
    
    
    let w;
    let doc;
    let iframe = document.createElement('iframe');
    let f = document.body.appendChild(iframe);

    iframe.id = 'myIframe'; //iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";

    iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;');

    w = f.contentWindow || f.contentDocument;

    doc = f.contentDocument || f.contentWindow.document;

    doc.open();

    doc.write(content);

    doc.close();

    var _this = this;

    iframe.onload = function() {
    
    
      _this.toPrint(w);

      setTimeout(function() {
    
    
        document.body.removeChild(iframe);
      }, 100);
    };
  },

  toPrint: function(frameWindow) {
    
    
    try {
    
    
      setTimeout(function() {
    
    
        frameWindow.focus();

        try {
    
    
          if (!frameWindow.document.execCommand('print', false, null)) {
    
    
            frameWindow.print();
          }
        } catch (e) {
    
    
          frameWindow.print();
        }

        frameWindow.close();
      }, 10);
    } catch (err) {
    
    
      console.log('err', err);
    }
  },

  isDOM:
      typeof HTMLElement === 'object'
        ? function(obj) {
    
    
          return obj instanceof HTMLElement;
        }
        : function(obj) {
    
    
          return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
        }
};

export default Print;

utils.js

/**
 * 推荐使用此方法格式化日期
 * @description: 将时间戳转换成制定格式的日期
 * @param {fmt} 要转化成的时间格式 yyyy/MM/dd HH:mm:ss 任意变化
 * @param {_timestamp} 时间戳 默认3位长度 10位长度会乘以1000
 * @return: 格式化之后的时间
 */
export function dateFormat (fmt, _timestamp) {
    
    
  if(_timestamp.toString().length === 10) {
    
    
    _timestamp = _timestamp * 1000
  }
  let date = new Date(_timestamp)
  let ret;
  let opt = {
    
    
    "y+": date.getFullYear().toString(),
    "M+": (date.getMonth() + 1).toString(),
    "d+": date.getDate().toString(),
    "H+": date.getHours().toString(),
    "m+": date.getMinutes().toString(),
    "s+": date.getSeconds().toString()
  };
  for (let k in opt) {
    
    
    ret = new RegExp("(" + k + ")").exec(fmt);
    if (ret) {
    
    
      fmt = fmt.replace(ret[1], (ret[1].length === 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
    };
  };
  return fmt;
}

Guess you like

Origin blog.csdn.net/guairena/article/details/123822851
Recommended