在react中實現打印功能

最近項目中,前端採用react+antd+dva的組合,已經完成了後頭管理類系統產品的更新迭代工做。css

今天有一個新需求,須要在後臺管理系統中實現點擊打印完成指定頁面的打印功能。html

 

以前也沒接觸過,只知道瀏覽器帶有打印功能的實現,window.print()。前端

 

問題來了,在react中是沒有dom節點的,不過咱們也是能夠轉爲dom節點的。react

 

常規js文件打印:https://blog.csdn.net/u014267869/article/details/52539341npm

 

在react中,其實一樣也是能夠獲取到節點信息的,在你須要打印的內容部分節點添加一個ID瀏覽器

 

打印按鈕點擊事件
print = () => { window.document.body.innerHTML = window.document.getElementById('billDetails').innerHTML; window.print(); window.location.reload(); }

 

  這樣打印出來的內容是沒有帶樣式的,由於通常css文件並不會寫到行內去,因此在生成html的文件字符串時,裏面沒有樣式信息,在打印時就會佈局混亂。antd

 

要想打印出來的效果與網頁上顯示的效果一致,就須要在生成html的文件字符串時,帶上樣式信息。less

 

方法1:把樣式信息寫在行內dom

在文件信息不復雜時,能夠寫在行內佈局

方法2:使用react-inline-css

使用這個npm包,能夠在配置後把樣式自動添加到行內

 

網頁效果圖:

 

打印預覽豎版效果圖:

 

 

橫版效果圖:

 

 

 

打印效果圖:

 

 

完整代碼:

 

import React, { PureComponent } from 'react';
import moment from 'moment';
import { connect } from 'dva';
import { 
  Card, 
  Button, 
  Form, 
  Table, 
  message,
 } from 'antd';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';
import { fixedZeroTo4Bit } from '../../utils/utils';
import styles from './Funds.less';
import { isEmptyObject } from '../../utils/reg';
import { Yuan } from '../../utils/math';
import watermark from '../../assets/icon/revocation.png';

@connect(({ finance, loading }) => ({
  finance,
  loading: loading.models.list,
}))
@Form.create()
export default class LoanSettleMent extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
    };
  }

  componentDidMount() {
    const code = !isEmptyObject(this.props.match) ? this.props.match.params.id : 0;
    this.statisticalInfo({ receiptsCode: code });
  }

  // 結算單列表詳情
  statisticalInfo(params) {
    this.props.dispatch({
      type: 'finance/statisticalInfo',
      payload: params,
    }).then(() => {
      this.setState({
        loading: false,
      })
    });
  }

  // 撤銷操做
  fetchRevocation(params) {
    this.props
      .dispatch({
        type: 'finance/fetchRevocation',
        payload: params,
      })
      .then(() => {
        const { finance: { revocationData } } = this.props;
        const { code } = revocationData;
        if (code === 200) {
          message.info('撤銷貨款單成功!').then(() => {
            window.location.href = '/funds/loansettlement';
          });
        } else {
          message.info('撤銷貨款單失敗!');
        }
      });
  }

  // 撤銷
  cancer = () => {
    const code = !isEmptyObject(this.props.match) ? this.props.match.params.id : 0;
    this.fetchRevocation({
      receiptsCode: code,
    });
  };

  // 返回
  back = () => {
    window.history.back();
  };

  // 打印
  print(){
    window.document.body.innerHTML = window.document.getElementById('billDetails').innerHTML;  
    window.print(); 
    window.location.reload();
  }

  render() {
    const { finance: { statisticalInfo }, loading } = this.props;
    let data = [],
        createName,
        createTime;
    if (statisticalInfo && !Array.isArray(statisticalInfo)) {
      data = statisticalInfo;
      createName = statisticalInfo.createName;
      createTime = statisticalInfo.createTime;
    }

    if (statisticalInfo != undefined) {
      data = statisticalInfo.goodsVos;
    }

    let _data = [],
        receiptsCode;
    if (statisticalInfo && !Array.isArray(statisticalInfo)) {
      _data = statisticalInfo;
      receiptsCode = statisticalInfo.receiptsCode;
    }
    const { supplierName, carNo, stallName, startTime, endTime, enable } = _data;

    const len = data.length;

    const columns = [
      {
        title: '品種',
        dataIndex: 'attrName',
        align: 'center',
      },
      {
        title: '銷售貨款',
        dataIndex: 'goodsAmount',
        align: 'left',
        render: (text, record, index) => {
          const { goodsAmount, goodsPaymentStr } = record;
          const type = goodsPaymentStr !== null ? goodsPaymentStr.split('負').length : -1;
          if (index < len - 1) {
            return <span>{goodsAmount ? Yuan(goodsAmount, 2) : ''}</span>;
          }
          return {
            children:
              type == 2 ? (
                <span className={styles.neg}>{goodsPaymentStr}</span>
              ) : (
                <span className={styles.bold}>{goodsPaymentStr}</span>
              ),
            props: {
              colSpan: 7,
            },
          };
        },
      },
      {
        title: '件數',
        dataIndex: 'number',
        align: 'center',
        render: (text, record, index) => {
          const { number } = record;
          if (index < len - 1) {
            return <span>{number ? number : ''}</span>;
          }
          return {
            children: '',
            props: {
              colSpan: 0,
            },
          };
        },
      },
      {
        title: '重量',
        dataIndex: 'weight',
        align: 'center',
        render: (text, record, index) => {
          const { weight } = record;
          if (index < len - 1) {
            return <span>{weight ? weight : ''}</span>;
          }
          return {
            children: '',
            props: {
              colSpan: 0,
            },
          };
        },
      },
      {
        title: '平均售價',
        dataIndex: 'averageAmount',
        align: 'center',
        render: (text, record, index) => {
          const { averageAmount } = record;
          if (index < len - 1) {
            return <span>{averageAmount ? Yuan(averageAmount, 2) : ''}</span>;
          }
          return {
            children: '',
            props: {
              colSpan: 0,
            },
          };
        },
      },
      {
        title: '平均重量',
        dataIndex: 'averageWeight',
        align: 'center',
        render: (text, record, index) => {
          const { averageWeight } = record;
          if (index < len - 1) {
            return <span>{averageWeight ? averageWeight : ''}</span>;
          }
          return {
            children: '',
            props: {
              colSpan: 0,
            },
          };
        },
      },
      {
        title: '費用類型',
        dataIndex: 'type',
        align: 'center',
        render: (text, record, index) => {
          const { type } = record;
          if (index < len - 1) {
            return <span>{type}</span>;
          }
          return {
            children: '',
            props: {
              colSpan: 0,
            },
          };
        },
      },
      {
        title: '扣款金額',
        dataIndex: 'amount',
        align: 'center',
        render: (text, record, index) => {
          const { amount } = record;
          if (index < len - 1) {
            return <span>{amount !== null ? Yuan(amount, 2) : ''}</span>;
          }
          return {
            children: '',
            props: {
              colSpan: 0,
            },
          };
        },
      },
    ];

    return (
      <PageHeaderLayout>
        <div className={styles.billDetails} id={'billDetails'}>
          <Card
            bordered={false}
            title=""
          >
            <div className={styles.paymentbill}>
              <div style={{display: 'flex', height: '60px', lineHeight: '60px'}}>
                <h1 style={{flex: 1, textAlign: 'center'}}>{stallName}</h1>
                <span style={{position: 'absolute', right: '10px', color: '#FF6666', fontWeight: '600'}}>{`NO:${receiptsCode !== undefined ? receiptsCode : ''}`}</span>
              </div>

              <div style={{display: 'flex'}}>
                <h2 style={{flex: 1, textAlign: 'center'}}>商品銷售車次結算單</h2>
                <div style={{position: 'absolute', right: '10px'}}>
                  <Button type="primary" onClick={this.cancer} disabled={!enable} style={{marginRight: '5px'}}>
                    撤銷
                  </Button>
                  <Button onClick={this.print.bind(this)} style={{marginRight: '5px'}}>打印</Button>
                  <Button type="primary" onClick={this.back} style={{marginRight: '5px'}}>
                    返回
                  </Button>
                </div>
              </div>

              <div style={{display: 'flex'}}>
                <h3 style={{flex: 1, textAlign: 'left'}}>{`貨老闆:${supplierName !== undefined ? supplierName : ''} ${
                  carNo !== undefined ? fixedZeroTo4Bit(carNo, 4) : 0
                }車`}
                </h3>
                <h3 style={{flex: 1}}>{`到貨時間:${moment(startTime).format('YYYY-MM-DD')}`}</h3>
                <h3 style={{flex: 1}}>{`售罄時間:${moment(endTime).format('YYYY-MM-DD')}`}</h3>
              </div>

              <img src={watermark} hidden={enable} style={{position: 'absolute', width: '100px', height: '100px', top: '120px', right: '80px',zIndex: 100}} />
            </div>
          </Card>
          <Card
            bordered={false}
            title=""
            bodyStyle={{ padding: '0 16px' }}
          >
            <Table
              dataSource={data}
              columns={columns}
              bordered
              pagination={false}
              loading={this.state.loading}
            />
          </Card>
          <Card style={{ border: 0 }}>
            <div style={{display: 'flex'}}>
              <h3 style={{flex: 1}}>{`結算人:${createName !== undefined ? createName : ''}`}</h3>
              <h3 style={{flex: 1, textAlign: 'right'}}>{`結算時間:${moment(createTime).format(
                'YYYY-MM-DD'
              )}`}</h3>
            </div>
          </Card>
        </div>
      </PageHeaderLayout>
    );
  }
}

 

 

後續準備把dom節點轉爲pdf再加上去...待續

相關文章
相關標籤/搜索