最近項目中,前端采用react+antd+dva的組合,
今天有一個新需求,
需要在后臺管理系統中實現 點擊打印 完成指定頁面的打印功能。
我們道瀏覽器帶有打印功能的實現,window.print()。
然而,在react中是沒有dom節點的,不過我們也是可以轉為dom節點的。就是在需要打印的內容部分節點添加一個ID
只不過,這樣打印出來的內容是沒有帶樣式的,因為一般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 styles from './Funds.less';@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'}><Cardbordered={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><Cardbordered={false}title=""bodyStyle={{ padding: '0 16px' }}><TabledataSource={data}columns={columns}borderedpagination={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>);}
}
一般直接使用window.print();是直接打印了整個頁面,但只打印其中的一部分時就需要一些方法了
1、在頁面的代碼頭部處加入JavaScript:
<script language=javascript>function doPrint() { bdhtml = window.document.body.innerHTML; sprnstr = "<!--startprint-->"; //開始打印標識字符串有17個字符eprnstr = "<!--endprint-->"; //結束打印標識字符串prnhtml = bdhtml.substr(bdhtml.indexOf(sprnstr)+17); //從開始打印標識之后的內容prnhtmlstr = prnhtml.substring(0,prnhtml.indexOf(eprnstr)); //截取開始標識和結束標識之間的內容window.document.body.innerHTML = prnhtmlstr ; //把需要打印的指定內容賦給body.innerHTMLwindow.print(); //調用瀏覽器的打印功能打印指定區域window.document.body.innerHTML = bdhtml;//重新給頁面內容賦值;}
</script>
2、在頁面正文處加上<!–startprint–>與<!–endprint–>標識。
也就是在需要用戶打印保存的正文所對應的html處附加上。同時,如果采用小偷程序獲得遠程數據并需打印,可將此等數據置于該定義標簽之內即可。
3、截取內容部分已完成,現在加個“打印”的鏈接:
要打印的內容在
<!–startprint–>startprint與endprint之間的區域
<!–endprint–>里。
添加打印鏈接事件<a href="javascript:;" onClick="doPrint()">打印</a>
總結
以上是生活随笔為你收集整理的react项目中实现打印预览功能的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。