vue-print打印表格打印不全

发布于 2022-09-11 20:31:39 字数 5126 浏览 39 评论 0

问题描述

我需要打印一个包含table的网页,用的是vue-print.js这个插件,但是表格后边总是缺失了一部分,要如何解决?

问题出现的环境背景及自己尝试过哪些方法

1、用的是vue.js vue-print.js
2、打印的html,我是直接通过js来拼接的字符串,因为vue-print插件要求是object(DOM),就另外创建了一个div,然后将字符串给这个div,再获取这个div的html。

尝试过的方法:
1、直接改table的宽度,发现默认情况下,table的最大宽度设置成1175px就可以正常打印,再大右边就会缺失。
但是这样的话,用户在打印预览中进行页边距设置的时候,宽度就会变成固定的大小,右边就会宽或者缺失。
2、想修改vue-print.js的源码,在源码中添加页边距设置,但是改了一天了,还没找到应该在哪里改。

相关代码

有打印按钮的页面 x.vue

import printX from '../export/xxx'  // 拼接字符串的js文件

printEvent(){ // 打印
    let html = printX(a,b)  // a,b是我打印页面需要用到的参数,我在这里省略了参数相关的代码
    let tempNode = document.createElement('div');  // 因为vue-print要求是object
    tempNode.innerHTML = html;
    this.$print(tempNode)   // 开始调用插件
 }
 

print.js // vue-print插件的代码

// 打印类属性、方法定义
/* eslint-disable */
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 () {
      var str = "",
        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;} @media print {header {display: none;}footer {display: none;} }</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) {
      var w, doc, iframe = document.createElement('iframe'),
        f = document.body.appendChild(iframe);
      iframe.id = "myIframe";
      iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;'); // 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) {
      console.log('frameWindow-->', 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';
      }
  };
  const MyPlugin = {}
  MyPlugin.install = function (Vue, options) {
    // 4. 添加实例方法
    Vue.prototype.$print = Print
  }
  export default MyPlugin

你期待的结果是什么?实际看到的错误信息又是什么?

错误信息:打印table的时候,右边缺失,如图:

clipboard.png

大神们,帮我看看,我要如何解决,谢谢了!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

十年九夏 2022-09-18 20:31:39

最终解决办法:
不是用 JS 生成 模板,而是直接先写好一个隐藏的vue文件来存放页面模板,然后点击打印的时候,获取这个页面的整个模板即可解决宽度不自适应的问题。

白首有我共你 2022-09-18 20:31:39

你需要了解下网页打印的基础知识

@media print {} //专用的打印样式
@page {

        /* size: auto; //默认的*/ 
        size: 10cm 25cm;//纸张大小
        /* size: A4 landscape; portrait/landscape //使用系统中的纸张和方向 */
        margin: 0;//清除打印文档的边距
    }
写下不归期 2022-09-18 20:31:39

请问最后有解决方案吗?貌似el-table本身有bug,计算宽度不对

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文