山东大学项目实训开发日志——基于vue+springboot的医院耗材管理系统(11)

山东大学项目实训开发日志——基于vue+springboot的医院耗材管理系统(11),第1张

        近期也新增了一项功能:打印单据

        这一功能并不复杂,但是要在很多地方都上线,所以写出其中的一个,剩余的只需稍作修改即可正常使用。因此我只以打印中心库库存列表为例写此篇博客。

        首先从网上学习并借鉴了网页上打印的方法并稍做修改。

optionsDefault 的说明:
   表头数据 - 列属性
   Array - 必填
   {
       field,          // 列字段
       name,           // 表头名称
       style,          // 表头样式
       columnSize,     // 列宽 单位为 % - 默认 100%
    }

properties的说明:
    data
    Array
    {
       [表头字段]: T,
    }
   

import {Message} from 'element-ui';
import {number2chinese} from './common';

// 默认配置
const optionsDefault = {
  
  properties: [],
  
  data: null,
  // 单据名
  // HTML 或 String
  // 例如:随货同行单
  title: '',
  // 订单号 - 必填
  orderNumber: '',
  // 单据创建时间
  // String - 必填
  // 格式必须为 xxxx-xx-xx
  createTime: '',
  // 制单人
  creator: '',
  //制单人所属科室
  billBranch: '',
  // 单据来源
  // HTML 或 String
  // 例如:供货单位、申领人
  fromWho: '',
  fromBranch: '',
  // 单据二维码
  qrcode: null,
  // 是否显示序号
  showIds: false,
  /**
   * 统计 - 累加 - 某条属性(必须为 number)
   * 一般为总价
   *
   * {
   *    val: '',      // 是否已有计算好的值,若没有则不填,可指定字段进行累加统计
   *    unit: '',     // 合计的单位,默认为 「元」
   *    field: '',    // 要累加的字段值(val 有值则不会累加统计)
   *    name: '',     // 对应的名字,默认为 「合计」
   *    colspan: 2,   // 字段名所占的单元格数,默认为 「2」
   *    showChinese: false, // 是否显示中文大写统计
   * }
   *
   */
  total: {},

  mulTotal: [],

  // header
  // HTML 或 String
  // 最上方的文字,例如医院名称、公司名称
  header: '临沂市河东区妇幼保健院',
  headerStyle: '',
  // 自定义 footer
  // HTML
  footer: '',
  // table item style
  formStyle: `border: 1px solid #000; padding: 5px 0; word-break: break-word;`,
  // table header style
  formHeaderStyle: `border: 1px solid #000; padding: 5px 0; word-break: break-word;`,
  // 序号列的宽度
  idsWidth: '2rem',
  // 文本对齐
  // center, left, right
  textAlign: 'center',

  // 空数据填充
  stuffing: '-',
  showStuffing:false,

};


const CONFIG = {
  a4: ['210mm', '297mm'],
  // 页边距 [上 右 下 左]
  pageMargin: ['0', '12.7mm', '12.7mm', '12.7mm'],
  // 二维码大小
  qrCodeSize: 70,
}

class PrintForm {

  options = {};
  _id = 1; // 起始序号
  _html = '';
  _class = 'print-form';  // 标识 div ,用于清除
  _iframe = null; // 当前 iframe
  _columnSize = '100%'; // 默认列宽
  _flagError = false;

  constructor(opts) {
    this.options = {...optionsDefault, ...opts};

    if (this.options.properties === null || this.options.length === 0) {
      console.error('表头为空');
      this.showMessage();
      return;
    }

    this.generateHtml();
  }

  /**
   * 生成 HTML 片段
   */
  generateHtml() {
    let page = 0;
    let flagStop = false; // 终止生成新页面

    if (this._html !== '') this._html = '';

    while (!flagStop) {
      flagStop = this.generateHtmlPage(page);
    }

    // 单据二维码
    if (this.options.qrcode) {
      this._html += `
        
        
      `;
    }
  }

  /**
   * 生成页面
   * @param {int} page 页码
   * @return {boolean} 是否停止继续生成新页面
   */
  generateHtmlPage(page) {
    this._html += `
      
    `;

    // 1级标题
    this._html += `
      ${this.options.header}
    `;

    // 2级标题
    this._html += `
      
        ${this.options.title}
      
    `;

    // 单据二维码
    if (this.options.qrcode && page === 0) {
      this._html += ``;
    }

    /** start: 顶部基本信息 */
    let textCreateTime = `制单时间:${this.options.createTime}`;

    // 单据编号
    this._html += `
      
        单据编号:
        
          NO${this.options.orderNumber ? this.options.orderNumber : this.options.stuffing}
        
      
    `;
    // 来源和创建时间
    if (this.options.billBranch === '中心库') {
      this._html += `
        
         申请科室:${this.options.fromBranch}
        ${this.options.fromWho}
        ${textCreateTime}
      
      `;
    } else {
      this._html += `
      
        ${this.options.fromWho}
        ${textCreateTime}
      
    `;
    }

    /** end: 顶部基本信息 */

    this._html += ``;


    /** start: 表头 */
    this._html += ``;
    // 显示序号
    if (this.options.showIds) {
      this._html += ``;
    }
    if (this.options.showStuffing){
      this.options.stuffing = ' ';
    }
    for (let i = 0; i < this.options.properties.length; i++) {
      this._html += `
        `;
    }
    this._html += ``;
    /** end: 表头 */


    /** start: 表行数据 */
    this._html += ``;
    if (this.options.data !== null) {
      for (let i = 0; i < this.options.data.length; i++) {
        this._html += ``;

        // 显示序号
        if (this.options.showIds) {
          this._html += `
            
          `;

          this._id++;
        }

        const rowData = this.options.data[i];
        let textData = null;

        // 只打印表头中存在的字段
        for (let j = 0; j < this.options.properties.length; j++) {
          const property = this.options.properties[j];

          textData = rowData[property.field] ? rowData[property.field] : this.options.stuffing;

          this._html += `
            
          `;
        }

        this._html += ``;
      }

      // 合计某个属性
      if (Object.keys(this.options.total).length > 0 && this.options.total.showChinese) {
        let __total = 0;
        let __totalChinese = '';  // 统计 - 中文大写

        // 已传入计算好的值,则无需累加 *** 作
        if (this.options.total.val) {
          __total = this.options.total.val;
        } else {
          for (let i = 0; i < this.options.data.length; i++) {
            __total += this.options.data[i][this.options.total.field];
          }
        }
        __total = __total.toFixed(2)

        const __totalName = this.options.total.name ? this.options.total.name : '合计';
        const __unit = this.options.total.unit ? this.options.total.unit : '元';
        const __colspanName = this.options.total.colspan ? this.options.total.colspan : 2;
        let __colspanVal = this.options.properties.length - __colspanName;
        let __colspanChinese = 0;

        if (this.options.showIds) __colspanVal++;

        // 统计 - 金额 - 中文大写
        if (this.options.total.showChinese) {
          __colspanVal = Math.ceil((this.options.properties.length - __colspanName) / 2);
          __colspanChinese = this.options.properties.length - __colspanName - __colspanVal;
          if (this.options.showIds) __colspanVal++;
        }

        this._html += `
          
        `;

        if (__colspanChinese > 0) {
          __totalChinese = number2chinese(__total);

          this._html += `
            
          `;
        }
        this._html += '';
      }

      //展示试剂出入库统计中的合计
      if (this.options.mulTotal.length > 0) {
        const __totalName = '合计';
        const __colspanName = this.options.mulTotal.colspan ? this.options.mulTotal.colspan : 3;
        let __colspanVal = 1;
        this._html += `
          
        `;

        for (let i = 0; i < this.options.mulTotal.length; i++) {
          this._html += `
           
        `;
        }
        this._html += '';
      }
    }

    this._html += ``;
    /** end: 表行数据 */

    // this._html += `
    //   
    //       
    //   `;
    this._html += `
序号${this.options.properties[i].name}
${this._id} ${textData}
${__totalName} ${__total} ${__unit}${__totalChinese}
${__totalName}${this.options.mulTotal[i]}
每页都有的表尾
`; /** start: 底部数据 */ this._html += ``; if (this.options.creator !== '') { this._html += ` 制表人:${this.options.creator} `; } this._html += this.options.footer; // todo 分页与总页码 // this._html += `${page + 1} / 1`; this._html += ``; /** 底部数据 */ this._html += ``; return true; } calculateHeight() { // todo 计算高度,实现分页 // new UnitConversion().px2mm(value) } /** * 挂载代码片 */ mountHtml() { if (this._flagError) return; this.clearAll(); let iframe = document.createElement('iframe'); iframe.setAttribute('class', this._class); // iframe.setAttribute('style', 'width: 900px; height: 500px; margin-left: 300px;'); iframe.setAttribute('style', 'position: absolute; width: 0; height: 0; left: -500px; top: -500px;'); window.document.body.appendChild(iframe); iframe.contentWindow.document.write(this._html); iframe.contentWindow.document.body.style.margin = '0'; this._iframe = iframe; } /** * 打印 */ async toPrint() { if (this._flagError) return; this.mountHtml(); // 需要等待二维码生成 if (this.options.qrcode) { const _divQrCode = this._iframe.contentWindow.document.querySelector("#printFormQrCode"); await this._waitGenerateQrcode(_divQrCode); } this._iframe.contentWindow.print(); this._iframe.parentNode.removeChild(this._iframe); this._iframe = null; // this.clearAll(); } /** * 等待二维码生成 */ _waitGenerateQrcode(_divQrCode) { return new Promise(resolve => { setTimeout(() => { resolve(); }, 300); }); // const _this = this; // if (!this._iframe) return; // if (_divQrCode.getAttribute('title')) { // this._iframe.contentWindow.print(); // return new Promise.resolve(); // } else { // setTimeout(() => { // const rr = _this._waitGenerateQrcode(_divQrCode); // return _this._waitGenerateQrcode(_divQrCode); // }, 100); // } // return new Promise(resolve => { // if (_divQrCode.getAttribute('title')) { // resolve(); // } else { // setTimeout(() => { // _this._waitGenerateQrcode(_divQrCode); // }, 100); // } // }) } /** * 清除挂载的所有单据 */ clearAll() { const arrDom = document.body.querySelectorAll(`.${this._class}`); for (let i = 0; i < arrDom.length; i++) { window.document.body.removeChild(arrDom[i]); } this._iframe = null; } /** * 给用户的提醒 */ showMessage() { // 目前只用到 error this._flagError = true; Message.error('打印单数据处理错误,请联系管理员'); } } export { PrintForm }

        然后在前端页面确定要打印的数据

const printFormColumn = [ 
  { 
    field: 'reagentName', 
    name: '耗材名称', 
    columnSize: '200%' 
  }, 
  { 
    field: 'reagentType', 
    name: '型号规格', 
    columnSize: '100%' 
  }, 
  { 
    field: 'factory', 
    name: '生产厂家', 
  }, 
  { 
    field: 'supplierName', 
    name: '供货商', 
  }, 
  { 
    field: 'reagentUnit', 
    name: '单位', 
    columnSize: '60%' 
  }, 
  { 
    field: 'quantity', 
    name: '数量', 
    columnSize: '60%' 
  }, 
  { 
    field: 'reagentTemp', 
    name: '储存温度', 
    columnSize: '50%' 
  }, 
]; 

        在前端调用打印方法 

handlePrint() { 
      if (this.list === null) { 
        Message.error('库存数据获取失败'); 
        return; 
      } 
 
      const _data = this.list; 

      const _createTime = formatDate(new Date(), 'yyyy-MM-dd hh:mm:ss'); 

      const pf = new PrintForm({ 
        orderNumber: Math.floor((Math.random() + Math.floor(Math.random() * 9 + 1)) * Math.pow(10, 9)), 
        creator: `${this.trueName}`, 
        createTime: _createTime, 
        title: '库存汇总', 
        properties: printFormColumn, 
        data: _data, 
        showIds: true, 
        total: { 
          field: 'quantity', 
          showChinese: false, 
        }, 
      }); 
      pf.toPrint(); 
    }, 

        同时记得import相应的方法,并且在按钮里设置onclick方法。

        这样打印的方法就完成了,稍作修改便可在所有需要的地方进行打印。

        打印效果预览如图:

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1323168.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-12
下一篇 2022-06-12

发表评论

登录后才能评论

评论列表(0条)

保存