最近项目中,前端采用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\', 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再加上去...待续
github查看更多好文:[https://github.com/xccjk/x-blog](https://github.com/xccjk/x-blog)