import React, {Component} from 'react'
|
import { Button } from 'antd'
|
import moment from 'moment'
|
import html2Canvas from 'html2canvas'
|
import JsPDF from 'jspdf'
|
|
import './index.scss'
|
|
class printVoucher extends Component {
|
state = {
|
loading: false
|
}
|
|
trigger = () => {
|
this.setState({loading: true})
|
|
setTimeout(() => {
|
this.getCanvas()
|
}, 200)
|
}
|
|
getCanvas = () => {
|
const { ID } = this.props
|
let wrap = document.getElementById(ID)
|
let elements = wrap.querySelectorAll('.mk-voucher-print-pdf-wrap')
|
let pageArr = []
|
const opts = {
|
scale: 1.5, // 缩放比例,提高生成图片清晰度
|
useCORS: false, // 允许加载跨域的图片
|
allowTaint: false, // 允许图片跨域,和 useCORS 二者不可共同使用
|
tainttest: false, // 检测每张图片已经加载完成
|
logging: false // 日志开关,发布的时候记得改成 false
|
}
|
|
elements = Array.from(elements)
|
|
for (let index = 0; index < elements.length; index++) {
|
// eslint-disable-next-line
|
html2Canvas(elements[index], opts).then(canvas => {
|
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
|
const contentWidth = canvas.width
|
const contentHeight = canvas.height
|
const imgWidth = 595.28
|
const imgHeight = (592.28 / contentWidth) * contentHeight
|
const pageData = canvas.toDataURL('image/jpeg', 1.0)
|
// 一页pdf显示html页面生成的canvas高度;
|
const pageHeight = (contentWidth / 592.28) * 841.89
|
// 未生成pdf的html页面高度
|
const leftHeight = contentHeight
|
pageArr.push({ pageData: pageData, pageHeight: pageHeight, leftHeight: leftHeight, imgWidth: imgWidth, imgHeight: imgHeight })
|
|
if (pageArr.length === elements.length) {
|
this.getPdf(pageArr)
|
}
|
})
|
}
|
}
|
|
getPdf = (pageArr) => {
|
const { orgname, vouDate, charName, charInt } = this.props
|
let title = moment(vouDate).format('YYYY-MM-DD') + charName + '-' + charInt + orgname + moment().format('YYYYMMDDHHmmss')
|
const PDF = new JsPDF('', 'pt', 'a4')
|
|
pageArr.forEach((data, index) => {
|
// 页面偏移
|
let position = 0
|
// 转换完毕,save保存名称后浏览器会自动下载
|
// 当内容未超过pdf一页显示的范围,无需分页
|
if (data.leftHeight < data.pageHeight) {
|
// addImage(pageData, 'JPEG', 左,上,宽度,高度)设置
|
PDF.addImage(data.pageData, 'JPEG', 0, 0, data.imgWidth, data.imgHeight)
|
} else {
|
// 超过一页时,分页打印(每页高度841.89)
|
while (data.leftHeight > 0) {
|
PDF.addImage(data.pageData, 'JPEG', 0, position, data.imgWidth, data.imgHeight)
|
data.leftHeight -= data.pageHeight
|
position -= 841.89
|
if (data.leftHeight > 0) {
|
PDF.addPage()
|
}
|
}
|
}
|
|
if (index + 1 === pageArr.length) {
|
PDF.save(title + '.pdf')
|
|
this.setState({loading: false})
|
} else {
|
// 未转换到最后一页时,pdf增加一页
|
PDF.addPage()
|
}
|
})
|
}
|
|
getContent = () => {
|
const { data, orgname, vouDate, charName, charInt, attachments } = this.props
|
|
let list = []
|
let items = []
|
let index = 0
|
|
data.forEach((cell, i) => {
|
if (index < 10) {
|
items.push(cell)
|
index++
|
} else {
|
list.push([...items])
|
index = 0
|
items = []
|
}
|
})
|
|
if (items.length > 0) {
|
while (items.length < 5) {
|
items.push({uuid: index + ''})
|
index++
|
}
|
|
list.push(items)
|
} else if (list.length === 0) {
|
list = [[{uuid: '1'}, {uuid: '2'}, {uuid: '3'}, {uuid: '4'}, {uuid: '5'}]]
|
}
|
|
let total = this.getTotalLine(data)
|
|
if (total.debit) {
|
total.debit = total.debit.toFixed(2)
|
}
|
if (total.credit) {
|
total.credit = total.credit.toFixed(2)
|
}
|
|
return <>
|
{list.map((page, i) => (<div className="mk-voucher-print-pdf-wrap" key={i}>
|
<div className="print-header">
|
<div className="line">
|
<div className="left"></div>
|
<div className="center">记账凭证</div>
|
<div className="right">附单据数:{attachments}</div>
|
</div>
|
<div className="line">
|
<div className="left">单位:{orgname}</div>
|
<div className="center">日期:{moment(vouDate).format('YYYY-MM-DD')}</div>
|
<div className="right">凭证号:{charName}-{charInt}{list.length > 1 ? `(${i + 1}/${list.length})` : ''}</div>
|
</div>
|
</div>
|
<div className="print-body">
|
<div className="print-line" key="0">
|
<div className="remark" style={{textAlign: 'center'}}>摘要</div>
|
<div className="subject" style={{textAlign: 'center'}}>科目</div>
|
<div className="credit" style={{textAlign: 'center'}}>借方金额</div>
|
<div className="credit" style={{textAlign: 'center'}}>贷方金额</div>
|
</div>
|
{page.map(record => {
|
let remark = record.subject_voucher_text || ''
|
|
if (record.count_type === 'Y') {
|
remark += `(数量:${record.fcc_count !== undefined ? record.fcc_count : ''},单价:${record.net_unitprice !== undefined ? record.net_unitprice : ''})`
|
}
|
if (record.foreign_currency_type === 'Y') {
|
remark += `(货币:${record.exratename || ''},汇率:${record.unitratio !== undefined ? record.unitratio : ''},原币:${record.foreign_amount !== undefined ? record.foreign_amount : ''})`
|
}
|
|
let val = ''
|
if (record.subject_code) {
|
val = (record.subject_code || '') + ' ' + (record.subject_name || '')
|
|
if (record.sup_accounting && record.supAccounts) {
|
record.supAccounts.forEach(item => {
|
if (item.sup_acc_type === 'supplier') {
|
val += item.suppliername ? '_' + item.suppliername : ''
|
} else if (item.sup_acc_type === 'customer') {
|
val += item.customername ? '_' + item.customername : ''
|
} else if (item.sup_acc_type === 'department') {
|
val += item.co_pro_name ? '_' + item.co_pro_name : ''
|
} else if (item.sup_acc_type === 'project') {
|
val += item.projectname ? '_' + item.projectname : ''
|
} else if (item.sup_acc_type === 'inventory') {
|
val += item.productname ? '_' + item.productname : ''
|
} else if (item.sup_acc_type === 'employee') {
|
val += item.workername ? '_' + item.workername : ''
|
} else if (item.sup_acc_type === 'cash_flow') {
|
val += item.cash_flow_name ? '_' + item.cash_flow_name : ''
|
} else if (item.sup_acc_name) {
|
val += '_' + item.sup_acc_name
|
}
|
})
|
}
|
}
|
|
let debit = record.debit || record.debit === 0 ? record.debit : ''
|
let credit = record.credit || record.credit === 0 ? record.credit : ''
|
|
if (debit) {
|
debit = debit.toFixed(2)
|
}
|
if (credit) {
|
credit = credit.toFixed(2)
|
}
|
|
return <div className="print-line" key={record.uuid}>
|
<div className="remark">{remark}</div>
|
<div className="subject">{val}</div>
|
<div className="credit">{debit}</div>
|
<div className="credit">{credit}</div>
|
</div>
|
})}
|
<div className="print-line" key="total">
|
<div className="remark" style={{width: '60%'}}>合计:{total.subject_voucher_text}</div>
|
<div className="credit">{total.debit}</div>
|
<div className="credit">{total.credit}</div>
|
</div>
|
</div>
|
<div className="print-footer">
|
<div>主管:</div>
|
<div>记账:</div>
|
<div>审核:</div>
|
<div>出纳:</div>
|
<div>制单:</div>
|
</div>
|
</div>))}
|
</>
|
}
|
|
getTotalLine = (data) => {
|
let totalLine = {uuid: 'total', type: 'total'}
|
let debit = ''
|
let credit = ''
|
|
data.forEach(item => {
|
if (!isNaN(item.debit) && item.debit !== '') {
|
if (debit === '') {
|
debit = 0
|
}
|
|
debit += item.debit
|
} else if (!isNaN(item.credit) && item.credit !== '') {
|
if (debit === '') {
|
debit = 0
|
}
|
if (credit === '') {
|
credit = 0
|
}
|
credit += item.credit
|
}
|
})
|
|
totalLine.debit = debit
|
totalLine.credit = credit
|
|
totalLine.subject_voucher_text = this.changeMoneyToChinese(debit)
|
|
return totalLine
|
}
|
|
changeMoneyToChinese = (money) => {
|
let cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
|
let cnIntRadice = ['', '拾', '佰', '仟']
|
let cnIntUnits = ['', '万', '亿', '兆']
|
let cnDecUnits = ['角', '分', '毫', '厘']
|
let cnInteger = '整'
|
let cnIntLast = '元'
|
let maxNum = 999999999999999.9999 // 最大处理的数字
|
let IntegerNum = null
|
let DecimalNum = null
|
let ChineseStr = ''
|
let parts = null // 分离金额后用的数组,预定义
|
let Symbol = '' // 正负值标记
|
|
if (money === '') return ''
|
|
if (money >= maxNum) return '超出最大处理数字'
|
|
if (money === 0) {
|
ChineseStr = cnNums[0] + cnIntLast + cnInteger;
|
return ChineseStr
|
}
|
if(money < 0) {
|
money = -money
|
Symbol = '负'
|
}
|
money = money.toString() // 转换为字符串
|
if (money.indexOf('.') === -1) {
|
IntegerNum = money
|
DecimalNum = ''
|
} else {
|
parts = money.split('.')
|
IntegerNum = parts[0]
|
DecimalNum = parts[1].substr(0, 4)
|
}
|
|
if (parseInt(IntegerNum, 10) > 0) { // 获取整型部分转换
|
let zeroCount = 0
|
let IntLen = IntegerNum.length
|
for (let i = 0; i < IntLen; i++) {
|
let n = IntegerNum.substr(i, 1)
|
let p = IntLen - i - 1
|
let q = p / 4
|
let m = p % 4
|
|
if (n === '0') {
|
zeroCount++
|
} else {
|
if (zeroCount > 0) {
|
ChineseStr += cnNums[0]
|
}
|
zeroCount = 0 // 归零
|
ChineseStr += cnNums[parseInt(n)] + cnIntRadice[m]
|
}
|
|
if (m === 0 && zeroCount < 4) {
|
ChineseStr += cnIntUnits[q]
|
}
|
}
|
ChineseStr += cnIntLast
|
}
|
|
if (DecimalNum !== '') { // 小数部分
|
let decLen = DecimalNum.length
|
|
for (let i = 0; i < decLen; i++) {
|
let n = DecimalNum.substr(i, 1)
|
if (n !== '0') {
|
ChineseStr += cnNums[Number(n)] + cnDecUnits[i]
|
}
|
}
|
}
|
if (ChineseStr === '') {
|
ChineseStr += cnNums[0] + cnIntLast + cnInteger
|
} else if (DecimalNum === '') {
|
ChineseStr += cnInteger
|
}
|
|
ChineseStr = Symbol + ChineseStr
|
|
return ChineseStr
|
}
|
|
render() {
|
const { disabled, ID } = this.props
|
const { loading } = this.state
|
|
return (
|
<>
|
<Button className="print-background header-btn" loading={loading} disabled={disabled} onClick={this.trigger}>打印</Button>
|
{loading ? <div id={ID} className="mk-voucher-print-wrap">
|
{this.getContent()}
|
</div> : null}
|
</>
|
)
|
}
|
}
|
|
export default printVoucher
|