最近項目中,前端採用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再加上去...待續