import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Select, Form, Input, Button, Modal, Spin } from 'antd'
|
import { EllipsisOutlined } from '@ant-design/icons'
|
import moment from 'moment'
|
|
import Api from '@/api'
|
import UtilsDM from '@/utils/utils-datamanage.js'
|
// import Utils from '@/utils/utils.js'
|
import MKEmitter from '@/utils/events.js'
|
import InvoiceTable from './invoiceTable'
|
import SubTable from './subTable'
|
import './index.scss'
|
|
class InvoiceModule extends Component {
|
static propTpyes = {
|
config: PropTypes.object
|
}
|
|
state = {
|
BID: '',
|
invTypes: [
|
{value: '1', label: '电子发票(增值税专用发票)'},
|
{value: '2', label: '电子发票(普通发票)'},
|
{value: '3', label: '增值税纸质专用发票'},
|
{value: '4', label: '增值税纸质普通发票'},
|
{value: '5', label: '增值税电子普通发票'},
|
{value: '6', label: '增值税电子专用发票'},
|
],
|
invoice_type: '',
|
date: moment().format('YYYY年MM月DD日'),
|
from_to_name: '',
|
from_to_tax_no: '',
|
from_to_addr: '',
|
from_to_tel: '',
|
from_to_bank_name: '',
|
from_to_account_no: '',
|
from_to_mob: '',
|
from_to_email: '',
|
from_to_code: '',
|
orgname: '',
|
tax_no: '',
|
addr: '',
|
tel: '',
|
bank_name: '',
|
account_no: '',
|
remark: '',
|
payee: '',
|
reviewer: '',
|
drawer: '',
|
details: [],
|
book: null,
|
loading: false,
|
tax_type: ''
|
}
|
|
UNSAFE_componentWillMount () {
|
const { config } = this.props
|
|
let _config = fromJS(config).toJS()
|
let BID = ''
|
let BData = ''
|
|
if (_config.setting.supModule) {
|
BData = window.GLOB.CacheData.get(_config.setting.supModule)
|
} else {
|
BData = window.GLOB.CacheData.get(_config.$pageId)
|
}
|
if (BData) {
|
BID = BData.$BID || ''
|
}
|
|
if (_config.wrap.invColor) {
|
_config.style['--inv-color'] = _config.wrap.invColor
|
}
|
|
_config.buyer = this.formatSetting(_config.buyer, 'buyer')
|
_config.detail = this.formatSetting(_config.detail, 'detail')
|
|
let book = null
|
let pas = {}
|
if (config.wrap.supBook) {
|
book = window.GLOB.CacheData.get(config.wrap.supBook) || null
|
|
if (book) {
|
pas = this.resetParam(book)
|
}
|
}
|
|
this.setState({
|
BID: BID || '',
|
config: _config,
|
book,
|
...pas
|
})
|
}
|
|
componentDidMount () {
|
const { config } = this.props
|
|
MKEmitter.addListener('reloadData', this.reloadData)
|
MKEmitter.addListener('resetSelectLine', this.resetParentParam)
|
|
if (config.wrap.datatype === 'dynamic' && config.setting.onload === 'true') {
|
setTimeout(() => {
|
this.loadData()
|
}, config.setting.delay || 0)
|
}
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
/**
|
* @description 组件销毁,清除state更新,清除快捷键设置
|
*/
|
componentWillUnmount () {
|
this.setState = () => {
|
return
|
}
|
MKEmitter.removeListener('reloadData', this.reloadData)
|
MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
|
}
|
|
formatSetting = (item, type) => {
|
item.setting.arr_field = item.columns.map(col => col.field).join(',')
|
item.setting.laypage = item.setting.laypage === 'true'
|
|
if (type === 'buyer') {
|
item.columns = item.columns.map(cell => {
|
if (['from_to_tel', 'from_to_account_no', 'from_to_code'].includes(cell.field)) {
|
cell.Hide = 'true'
|
} else if (['from_to_email', 'from_to_mob'].includes(cell.field)) {
|
cell.Width = 80
|
}
|
return cell
|
})
|
} else {
|
item.columns = item.columns.map(cell => {
|
if (cell.field === 'general_tax_rate') {
|
cell.field = 'tax_rate'
|
cell.label = '税率'
|
}
|
if (['Description', 'id', 'small_tax_rate'].includes(cell.field)) {
|
cell.Hide = 'true'
|
} else if (['spec'].includes(cell.field)) {
|
cell.Width = 150
|
} else if (['unit', 'unitprice', 'tax_rate'].includes(cell.field)) {
|
cell.Width = 80
|
}
|
|
return cell
|
})
|
}
|
|
if (item.setting.interType !== 'system') {
|
item.setting.dataresource = ''
|
return item
|
}
|
|
let regs = [
|
{ reg: /@userName@/ig, value: `'${sessionStorage.getItem('User_Name') || ''}'` },
|
{ reg: /@fullName@/ig, value: `'${sessionStorage.getItem('Full_Name') || ''}'` }
|
]
|
|
if (window.GLOB.externalDatabase !== null) {
|
regs.push({
|
reg: /@db@/ig,
|
value: window.GLOB.externalDatabase
|
})
|
}
|
|
let _customScript = ''
|
let _tailScript = ''
|
item.scripts && item.scripts.forEach(script => {
|
if (script.status === 'false') return
|
if (script.position !== 'back') {
|
_customScript += `
|
${script.sql}
|
`
|
} else {
|
_tailScript += `
|
${script.sql}
|
`
|
}
|
})
|
delete item.scripts
|
|
item.setting.execute = item.setting.execute !== 'false'
|
|
if (!item.setting.execute) {
|
item.setting.dataresource = ''
|
}
|
if (/\s/.test(item.setting.dataresource)) {
|
item.setting.dataresource = '(' + item.setting.dataresource + ') tb'
|
}
|
|
if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
|
item.setting.dataresource = item.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
|
_customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
|
_tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
|
} else {
|
item.setting.dataresource = item.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
|
_customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
|
_tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
|
}
|
|
regs.forEach(cell => {
|
item.setting.dataresource = item.setting.dataresource.replace(cell.reg, cell.value)
|
_customScript = _customScript.replace(cell.reg, cell.value)
|
_tailScript = _tailScript.replace(cell.reg, cell.value)
|
})
|
|
item.setting.customScript = _customScript // 整理后自定义脚本
|
item.setting.tailScript = _tailScript // 后置自定义脚本
|
|
item.setting.custompage = /@pageSize@|@orderBy@/i.test(item.setting.dataresource + item.setting.customScript)
|
|
return item
|
}
|
|
resetParentParam = (MenuID, id, data) => {
|
const { config } = this.state
|
|
if (config.wrap.supBook === MenuID) {
|
let pas = this.resetParam(data)
|
|
this.setState({ book: data, ...pas }, () => {
|
this.loadData()
|
})
|
return
|
}
|
|
if (!config.wrap.supModule || config.wrap.supModule !== MenuID) return
|
if (id !== this.state.BID || id !== '') {
|
this.setState({ BID: id }, () => {
|
this.loadData()
|
})
|
}
|
}
|
|
resetParam = (book) => {
|
return {
|
invTypes: book.invoice_type || [],
|
orgname: book.orgname || '',
|
tax_no: book.tax_no || '',
|
addr: book.addr || '',
|
tel: book.tel || '',
|
bank_name: book.bank_name || '',
|
account_no: book.account_no || '',
|
payee: book.payee || '',
|
reviewer: book.reviewer || '',
|
drawer: book.drawer || '',
|
tax_type: book.tax_type || ''
|
}
|
}
|
|
reloadData = (menuId) => {
|
const { config } = this.state
|
|
if (config.uuid !== menuId) return
|
|
this.loadData()
|
}
|
|
async loadData() {
|
const { config, BID } = this.state
|
|
if (config.wrap.datatype !== 'dynamic') return
|
|
let param = UtilsDM.getQueryDataParams(config.setting, [], config.setting.order, 1, 1, BID)
|
|
this.setState({
|
loading: true
|
})
|
|
let result = await Api.genericInterface(param)
|
if (result.status) {
|
|
this.setState({
|
loading: false
|
})
|
|
UtilsDM.querySuccess(result)
|
} else {
|
this.setState({
|
loading: false
|
})
|
this.timer && this.timer.stop()
|
|
UtilsDM.queryFail(result)
|
}
|
}
|
|
changeType = (val) => {
|
this.setState({invoice_type: val})
|
}
|
|
changeBuyer = (item) => {
|
this.setState({
|
visible: false,
|
from_to_name: item.from_to_name || '',
|
from_to_tax_no: item.from_to_tax_no || '',
|
from_to_addr: item.from_to_addr || '',
|
from_to_tel: item.from_to_tel || '',
|
from_to_bank_name: item.from_to_bank_name || '',
|
from_to_account_no: item.from_to_account_no || '',
|
from_to_mob: item.from_to_mob || '',
|
from_to_email: item.from_to_email || '',
|
from_to_code: item.from_to_code || '',
|
})
|
}
|
|
render() {
|
const { config, book, loading, invTypes, date, from_to_name, from_to_tax_no, from_to_addr, from_to_tel, from_to_bank_name, from_to_account_no, from_to_mob, from_to_email, orgname, tax_no, addr, tel, bank_name, account_no, remark, reviewer, drawer, payee, details, visible, tax_type } = this.state
|
|
if (!book || (config.wrap.datatype === 'dynamic' && !tax_no)) {
|
return <div className="menu-invoice-wrap" style={config.style}>
|
<div className="loading-mask">
|
<div className="ant-spin-blur"></div>
|
<Spin />
|
</div>
|
</div>
|
}
|
|
return (
|
<div className="menu-invoice-wrap" style={config.style}>
|
{loading ?
|
<div className="loading-mask">
|
<div className="ant-spin-blur"></div>
|
<Spin />
|
</div> : null
|
}
|
<div className="inv-action">
|
<Button className="mk-bill">保存单据</Button>
|
<Button className="mk-submit">提交开票</Button>
|
</div>
|
<div className="inv-header">
|
<Select placeholder="请选择发票种类" onChange={this.changeType} dropdownClassName="inv-type-select">
|
{invTypes.map(item => (
|
<Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>
|
))}
|
</Select>
|
<div className="date">开票日期:{date}</div>
|
</div>
|
<div className="inv-body">
|
<div className="inv-main-content">
|
<div className="inv-buyer">
|
<div className="inv-label">购买方</div>
|
<div className="inv-content">
|
<Form.Item label={<>名<span></span>称</>} extra={<EllipsisOutlined onClick={() => this.setState({visible: true})}/>}>
|
<Input placeholder="请输入购买方名称" allowClear value={from_to_name} autoComplete="off" onChange={(e) => this.setState({from_to_name: e.target.value})}/>
|
</Form.Item>
|
<Form.Item label="纳税人识别号">
|
<Input placeholder="请输入购买方纳税人识别号" allowClear value={from_to_tax_no} autoComplete="off" onChange={(e) => this.setState({from_to_tax_no: e.target.value})}/>
|
</Form.Item>
|
<Form.Item className="mutil-input" label={<>地<span></span>址<span></span>、<span></span>电<span></span>话</>}>
|
<Input placeholder="请输入购买方地址" allowClear value={from_to_addr} autoComplete="off" onChange={(e) => this.setState({from_to_addr: e.target.value})}/>
|
<Input placeholder="请输入购买方电话" allowClear value={from_to_tel} autoComplete="off" onChange={(e) => this.setState({from_to_tel: e.target.value})}/>
|
</Form.Item>
|
<Form.Item className="mutil-input" label="开户行及账号">
|
<Input placeholder="请输入购买方开户行" allowClear value={from_to_bank_name} autoComplete="off" onChange={(e) => this.setState({from_to_bank_name: e.target.value})}/>
|
<Input placeholder="请输入购买方账号" allowClear value={from_to_account_no} autoComplete="off" onChange={(e) => this.setState({from_to_account_no: e.target.value})}/>
|
</Form.Item>
|
</div>
|
</div>
|
<div className="inv-notice">
|
<div className="inv-label">通知到</div>
|
<div className="inv-content">
|
<Form.Item label={<>手<span></span>机<span></span>号</>}>
|
<Input placeholder="请输入购买方手机号" allowClear value={from_to_mob} autoComplete="off" onChange={(e) => this.setState({from_to_mob: e.target.value})}/>
|
</Form.Item>
|
<Form.Item label={<>邮<span></span>箱</>}>
|
<Input placeholder="请输入购买方邮箱" allowClear value={from_to_email} autoComplete="off" onChange={(e) => this.setState({from_to_email: e.target.value})}/>
|
</Form.Item>
|
</div>
|
</div>
|
</div>
|
<div className="inv-details">
|
<InvoiceTable data={details} config={config.detail} tax_type={tax_type} onChange={(details) => this.setState({details})}/>
|
</div>
|
<div className="inv-main-content">
|
<div className="inv-buyer">
|
<div className="inv-label">销售方</div>
|
<div className="inv-content">
|
<Form.Item label={<>名<span></span>称</>}>
|
<Input placeholder="请输入销售方名称" value={orgname} autoComplete="off" onChange={(e) => this.setState({orgname: e.target.value})}/>
|
</Form.Item>
|
<Form.Item label="纳税人识别号">
|
<Input placeholder="请输入销售方纳税人识别号" disabled value={tax_no} autoComplete="off"/>
|
</Form.Item>
|
<Form.Item className="mutil-input" label={<>地<span></span>址<span></span>、<span></span>电<span></span>话</>}>
|
<Input placeholder="请输入销售方地址" value={addr} autoComplete="off" onChange={(e) => this.setState({addr: e.target.value})}/>
|
<Input placeholder="请输入销售方电话" value={tel} autoComplete="off" onChange={(e) => this.setState({tel: e.target.value})}/>
|
</Form.Item>
|
<Form.Item className="mutil-input" label="开户行及账号">
|
<Input placeholder="请输入销售方开户行" value={bank_name} autoComplete="off" onChange={(e) => this.setState({bank_name: e.target.value})}/>
|
<Input placeholder="请输入销售方账号" value={account_no} autoComplete="off" onChange={(e) => this.setState({account_no: e.target.value})}/>
|
</Form.Item>
|
</div>
|
</div>
|
<div className="inv-notice">
|
<div className="inv-label">备注</div>
|
<div className="inv-content" style={{paddingTop: '30px'}}>
|
<Form.Item label="">
|
<Input.TextArea placeholder="请输入备注" autoSize={{ minRows: 4, maxRows: 4 }} value={remark} autoComplete="off" onChange={(e) => this.setState({remark: e.target.value})}/>
|
</Form.Item>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div className="inv-tail">
|
<Form.Item label="收款人">
|
<Input placeholder="收款人" value={payee} autoComplete="off" onChange={(e) => this.setState({payee: e.target.value})}/>
|
</Form.Item>
|
<Form.Item label="复核人">
|
<Input placeholder="复核人" value={reviewer} autoComplete="off" onChange={(e) => this.setState({reviewer: e.target.value})}/>
|
</Form.Item>
|
<Form.Item label="开票人">
|
<Input placeholder="开票人" value={drawer} autoComplete="off" onChange={(e) => this.setState({drawer: e.target.value})}/>
|
</Form.Item>
|
</div>
|
<Modal
|
title="客户信息"
|
visible={visible}
|
width="70vw"
|
maskClosable={false}
|
onCancel={() => { this.setState({ visible: false }) }}
|
footer={null}
|
>
|
<SubTable config={config.buyer} onChange={this.changeBuyer}/>
|
</Modal>
|
</div>
|
)
|
}
|
}
|
|
export default InvoiceModule
|