環境:react,antd,antd-pro
將選中的數據進行打印,能夠自定義分頁的大小。
因爲打印的列等多個因素,致使若是寫成組件在使用的時候依舊會改變源碼,因此採用了寫成頁面的方式,css
進行傳值的時候,剛開始使用的是在經過this.props.location進行傳值,可是這樣數據被寫死了,致使再次進入頁面的時候沒法更新打印的值。
最後採用了一個全局的model進行實現的傳值。react
分爲四部分進行生成,分別是標題、表頭、表格、表尾。其中表頭,表尾由於需求的緣由寫死。
如下爲代碼:antd
createTitle = (title)=>( <div> <h1 style={styleObj.title}>{title}</h1> </div> ) createHeader = (headerData)=>{ headerData = [ { orderID:'訂單編號', value:'P201901020002', },{ people:'採購人員', value:'xxx', },{ time:'採購時間', value:'2019年01月01日', } ]; return ( <table> <tbody style={styleObj.header}> <tr> <th>訂單編號:</th> <th colSpan="7"> <input style={styleObj.printInput} value="P201901020002" /> </th> </tr> <tr> <th>採購員:</th> <th colSpan="7"> <input style={styleObj.printInput} value="xxx" /> </th> <th>採購時間:</th> <th colSpan="7"> <input style={styleObj.printInput} value="2019年01月01日" /> </th> </tr> </tbody> </table> ) } createForm = (printCol,printData)=>( <table style={styleObj.printTable}> <tbody> { ( <tr style={styleObj.printTableTr}> {printCol.map(item=><th style={{...styleObj[item.key],...styleObj.printTableTh}}><div>{item.name}</div></th>)} </tr> ) } { printData.map(item=> ( <tr style={styleObj.printTableTr}> {Object.keys(item).map(i => <th style={styleObj.printTableTh}>{item[i]}</th>)} </tr> ) ) } </tbody> </table> ) createFooter = (footerData)=>{ return ( <table> <tbody style={styleObj.footer}> <tr> <th>供應商(簽字)</th> <th> <div style={styleObj.footerSpace} /> </th> <th colSpan="4"> <input style={styleObj.printInputFooter} /> </th> <th>庫管員(簽字)</th> <th> <div style={styleObj.footerSpace} /> </th> <th colSpan="4"> <input style={styleObj.printInputFooter} /> </th> <th>{`第${footerData.current}頁`}</th> <th>{`共${footerData.total}頁`}</th> </tr> </tbody> </table> ) } createPrintArea = (printCol)=>{ const {printGroupData} = this.state; return ( printGroupData.map((item,index)=>{ if(item.length){ return ( <div style={styleObj.printArea}> {this.createTitle('xxxxxxx公司xxx單')} {this.createHeader('asd')} {this.createForm(printCol,item)} {this.createFooter({current:index+1,total:printGroupData.length})} </div> ) } }) ) }
最主要的是CSS的調整,由於以後的打印需求將全部的CSS內聯:
如下爲css:app
export const styleObj = { printArea:{ width: '500px', fontSize: '12px', align:'center' }, printInput:{ fontWeight:'bold', border: 'none', }, title:{ textAlign: 'center', fontSize: '15px', fontWeight: '700', }, header:{ fontWeight:'bold', fontSize: '12px', }, printTable:{ fontSize: '12px', fontWeight: '700', color: 'black', border: '1px black', borderCollapse: 'collapse', textAlign: 'center', }, printTableTh:{ padding: '4px', border: '1px solid black', textAlign: 'center', }, printTableTr:{ textAlign:'center', padding: '4px', border: '1px solid black', }, number:{ width: '60px', }, goodsName:{ width: '180px', }, unitName:{ width: '75px', }, specifications:{ width: '90px', }, goodsType:{ width: '90px', }, footer:{ fontSize:'12px', }, footerSpace:{ width: '20px', display: 'block', }, printInputFooter:{ fontWeight:'bold', border:'none', width: '85px', }, };
分頁即將數據進行分割,而後每次生成表格的時候將分割後的每一個表格數據依次傳入表格生成函數,從而生成所有表格。
分頁函數:函數
//傳入的數據爲:分頁的大小,須要分頁的數據。 page = (pageNumber,printData)=>{ const printDataBack = printData.concat(); const printGroupData = []; while(printDataBack.length >= pageNumber){ let tempGroup = []; tempGroup = printDataBack.splice(0,pageNumber); printGroupData.push(tempGroup); } if(printDataBack.length){ printGroupData.push(printDataBack); } printGroupData.forEach((item)=>{ item.forEach((i,index)=>{ i.number = index+1; }) }); return printGroupData; }
注意:解構出來的數據是引用,須要進行備份。
設置一個input框以及一個按鈕,input框用於輸入分頁的數字,再點擊按鈕以及第一次進入頁面的時候進行分頁。this
直接在本頁面進行刷新
優勢:css不用內嵌。
缺點:致使本頁面刷新,某些數據丟失。spa
實現方法:直接獲取到須要打印的區域,而後將本頁面的innerHTML設置爲獲取的區域,而後調用系統的print,最後調用reloadcode
代碼:component
print = () => { window.document.body.innerHTML = window.document.getElementById('billDetails').innerHTML; window.print(); window.location.reload(); }
打開一個頁面進行打印
優勢:打印不在關乎本頁面的業務
缺點:CSS須要內聯
代碼:orm
handlePrint = () => { const win = window.open('','printwindow'); win.document.write(window.document.getElementById('printArea').innerHTML); win.print(); win.close(); }
如下爲完整代碼:
index.js
import React, { PureComponent } from 'react'; import { connect } from 'dva'; import { Row, Button, Col, Card, Form, message, InputNumber, } from 'antd'; import PageHeaderWrapper from '@/components/PageHeaderWrapper'; import {styleObj} from './style'; @Form.create() @connect(({ print }) => ({ print, })) class PrintTable extends PureComponent { state = { printData:[], printCol:[], pageNumber:10, printGroupData:[], } componentDidMount() { const printCol = [ { key:'number', name:'序號', },{ key:'goodsName', name:'商品名稱', },{ key:'goodsType', name:'商品類型', },{ key:'unitName', name:'單位', },{ key:'specifications', name:'規格', }]; const printData = []; const { pageNumber } = this.state; const { print:{ payload:{formPrintData} } } = this.props; formPrintData.forEach((i,index)=>{ const colData = {}; printCol.forEach(j=>{ colData[j.key] = i[j.key]; }) colData.number = index+1; printData.push(colData); }); const printGroupData = this.page(pageNumber,printData); this.setState({ printData, printCol, printGroupData, }) } componentWillReceiveProps(nextProps){ const printCol = [ { key:'number', name:'序號', },{ key:'goodsName', name:'商品名稱', },{ key:'goodsType', name:'商品類型', },{ key:'unitName', name:'單位', },{ key:'specifications', name:'規格', }]; const printData = []; const { pageNumber } = this.state; const { print:{ payload:{formPrintData} } } = nextProps; formPrintData.forEach((i,index)=>{ const colData = {}; printCol.forEach(j=>{ colData[j.key] = i[j.key]; }) colData.number = index+1; printData.push(colData); }); const printGroupData = this.page(pageNumber,printData); this.setState({ printData, printCol, printGroupData, }) } createTitle = (title)=>( <div> <h1 style={styleObj.title}>{title}</h1> </div> ) createHeader = (headerData)=>{ headerData = [ { orderID:'訂單編號', value:'P201901020002', },{ people:'採購人員', value:'xxx', },{ time:'採購時間', value:'2019年01月01日', } ]; return ( <table> <tbody style={styleObj.header}> <tr> <th>訂單編號:</th> <th colSpan="7"> <input style={styleObj.printInput} value="P201901020002" /> </th> </tr> <tr> <th>採購員:</th> <th colSpan="7"> <input style={styleObj.printInput} value="xxx" /> </th> <th>採購時間:</th> <th colSpan="7"> <input style={styleObj.printInput} value="2019年01月01日" /> </th> </tr> </tbody> </table> ) } createForm = (printCol,printData)=>( <table style={styleObj.printTable}> <tbody> { ( <tr style={styleObj.printTableTr}> {printCol.map(item=><th style={{...styleObj[item.key],...styleObj.printTableTh}}><div>{item.name}</div></th>)} </tr> ) } { printData.map(item=> ( <tr style={styleObj.printTableTr}> {Object.keys(item).map(i => <th style={styleObj.printTableTh}>{item[i]}</th>)} </tr> ) ) } </tbody> </table> ) createFooter = (footerData)=>{ return ( <table> <tbody style={styleObj.footer}> <tr> <th>供應商(簽字)</th> <th> <div style={styleObj.footerSpace} /> </th> <th colSpan="4"> <input style={styleObj.printInputFooter} /> </th> <th>庫管員(簽字)</th> <th> <div style={styleObj.footerSpace} /> </th> <th colSpan="4"> <input style={styleObj.printInputFooter} /> </th> <th>{`第${footerData.current}頁`}</th> <th>{`共${footerData.total}頁`}</th> </tr> </tbody> </table> ) } handlePrint = () => { const win = window.open('','printwindow'); win.document.write(window.document.getElementById('printArea').innerHTML); win.print(); win.close(); } createPrintArea = (printCol)=>{ const {printGroupData} = this.state; return ( printGroupData.map((item,index)=>{ if(item.length){ return ( <div style={styleObj.printArea}> {this.createTitle('xxxxxxx公司xxx單')} {this.createHeader('asd')} {this.createForm(printCol,item)} {this.createFooter({current:index+1,total:printGroupData.length})} </div> ) } }) ) } handlePage = ()=>{ const { pageNumber, printData } = this.state; if(pageNumber <= 0){ message.warning('輸出正確的分頁'); return; } this.setState({ printGroupData:this.page(pageNumber, printData) }) } page = (pageNumber,printData)=>{ const printDataBack = printData.concat(); const printGroupData = []; while(printDataBack.length >= pageNumber){ let tempGroup = []; tempGroup = printDataBack.splice(0,pageNumber); printGroupData.push(tempGroup); } if(printDataBack.length){ printGroupData.push(printDataBack); } printGroupData.forEach((item)=>{ item.forEach((i,index)=>{ i.number = index+1; }) }); return printGroupData; } onChange = (value)=>{ this.setState({ pageNumber:value, }) } render() { const { printCol, printData } = this.state; return ( <PageHeaderWrapper title="查詢表格"> <Card> <Row> <Col span={6}> <Row> <Col span={12}> <InputNumber onChange={this.onChange} placeholder='輸入自定義分頁數量' style={{width:'100%'}}/> </Col> <Button onClick={this.handlePage}>確認分頁</Button> </Row> <Row> <Button onClick={this.handlePrint} type='primary'>打印</Button> </Row> </Col> <Col span={12}> <div id='printArea'> <div style={styleObj.printArea}> {printCol.length&&printData.length? this.createPrintArea(printCol):null} </div> </div> </Col> </Row> </Card> </PageHeaderWrapper> ); } } export default PrintTable;
style.js
export const styleObj = { printArea:{ width: '500px', fontSize: '12px', align:'center' }, printInput:{ fontWeight:'bold', border: 'none', }, title:{ textAlign: 'center', fontSize: '15px', fontWeight: '700', }, header:{ fontWeight:'bold', fontSize: '12px', }, printTable:{ fontSize: '12px', fontWeight: '700', color: 'black', border: '1px black', borderCollapse: 'collapse', textAlign: 'center', }, printTableTh:{ padding: '4px', border: '1px solid black', textAlign: 'center', }, printTableTr:{ textAlign:'center', padding: '4px', border: '1px solid black', }, number:{ width: '60px', }, goodsName:{ width: '180px', }, unitName:{ width: '75px', }, specifications:{ width: '90px', }, goodsType:{ width: '90px', }, footer:{ fontSize:'12px', }, footerSpace:{ width: '20px', display: 'block', }, printInputFooter:{ fontWeight:'bold', border:'none', width: '85px', }, };