• 在react中实现打印功能


    最近项目中,前端采用react+antd+dva的组合,已经完成了后头管理类系统产品的更新迭代工作。

    今天有一个新需求,需要在后台管理系统中实现点击打印完成指定页面的打印功能。

    之前也没接触过,只知道浏览器带有打印功能的实现,window.print()。

    问题来了,在react中是没有dom节点的,不过我们也是可以转为dom节点的。

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

    在react中,其实同样也是可以获取到节点信息的,在你需要打印的内容部分节点添加一个ID

    打印按钮点击事件
    print = () => { window.document.body.innerHTML = window.document.getElementById('billDetails').innerHTML; window.print(); window.location.reload(); }

      这样打印出来的内容是没有带样式的,因为一般css文件并不会写到行内去,所以在生成html的文件字符串时,里面没有样式信息,在打印时就会布局混乱。

    要想打印出来的效果与网页上显示的效果一致,就需要在生成html的文件字符串时,带上样式信息。

    方法1:把样式信息写在行内

    在文件信息不复杂时,可以写在行内

    方法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',  '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再加上去...待续

  • 相关阅读:
    eg_5
    浅谈Java中的Hashmap
    java中方法传入参数时:值传递还是址传递?
    重温概率学(一)期望、均值、标准差、方差
    博客搬家
    golang sync/atomic
    单机配置kafka和zookeeper
    异步消息队列组件
    2017总结
    看完轻松年薪30w+
  • 原文地址:https://www.cnblogs.com/sk-3/p/9664496.html
Copyright © 2020-2023  润新知