import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Table, Modal, Input, InputNumber, notification, message } from 'antd'
|
// import { EditOutlined } from '@ant-design/icons'
|
|
import Api from '@/api'
|
import Utils from '@/utils/utils.js'
|
import MKEmitter from '@/utils/events.js'
|
import zhCN from '@/locales/zh-CN/main.js'
|
import enUS from '@/locales/en-US/main.js'
|
import '@/assets/css/table.scss'
|
import './index.scss'
|
|
class BodyRow extends React.Component {
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.props.data), fromJS(nextProps.data))
|
}
|
|
render() {
|
let { data, ...resProps } = this.props
|
let style = {}
|
let className = ''
|
|
return <tr {...resProps} className={className} style={style}/>
|
}
|
}
|
|
class BodyCell extends React.Component {
|
state = {
|
editing: false,
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.props.record), fromJS(nextProps.record)) ||
|
nextState.editing !== this.state.editing
|
}
|
|
componentDidMount () {
|
MKEmitter.addListener('tdFocus', this.tdFocus)
|
}
|
|
/**
|
* @description 组件销毁,清除state更新,清除快捷键设置
|
*/
|
componentWillUnmount () {
|
this.setState = () => {
|
return
|
}
|
MKEmitter.removeListener('tdFocus', this.tdFocus)
|
}
|
|
tdFocus = (id) => {
|
const { col, record } = this.props
|
|
if (id !== col.uuid + record.uuid) return
|
|
this.focus()
|
}
|
|
enterPress = () => {
|
const { col, record } = this.props
|
const { value } = this.state
|
|
this.setState({editing: false})
|
|
if (value !== record[col.field]) {
|
let line = {...record, [col.field]: value}
|
|
if (col.field === 'debtor') {
|
line.creditor = ''
|
} else {
|
line.debtor = ''
|
}
|
|
MKEmitter.emit('changeRecord', col.tableId, line)
|
}
|
|
setTimeout(() => {
|
if (col.field === 'creditor') {
|
MKEmitter.emit('nextLine', col, record)
|
} else {
|
let cl = {remark: 'subject', subject: 'debtor', debtor: 'creditor'}
|
MKEmitter.emit('tdFocus', cl[col.uuid] + record.uuid)
|
}
|
}, 50)
|
}
|
|
focus = () => {
|
const { col, record } = this.props
|
|
if (record.type === 'total') return
|
|
this.setState({editing: true, value: record[col.field]}, () => {
|
let node = document.getElementById(col.uuid + record.uuid)
|
node && node.select()
|
})
|
}
|
|
onBlur = () => {
|
const { col, record } = this.props
|
const { value } = this.state
|
|
this.setState({editing: false})
|
|
if (value !== record[col.field]) {
|
let line = {...record, [col.field]: value}
|
|
if (col.field === 'debtor') {
|
line.creditor = ''
|
} else {
|
line.debtor = ''
|
}
|
|
MKEmitter.emit('changeRecord', col.tableId, line)
|
}
|
}
|
|
onChange = (val) => {
|
this.setState({value: val})
|
}
|
|
render() {
|
let { col, record, className } = this.props
|
const { editing } = this.state
|
|
let children = null
|
let colSpan = 1
|
|
if (col.field === 'remark') {
|
let val = record.remark || ''
|
|
if (record.type === 'total') {
|
children = <div className="content-wrap" style={{lineHeight: '60px'}}>合计: {val}</div>
|
colSpan = 2
|
} else {
|
if (editing) {
|
children = <Input.TextArea id={col.uuid + record.uuid} autoSize={false} defaultValue={val} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
|
} else {
|
children = <div className="content-wrap" onClick={this.focus}>{val}</div>
|
}
|
}
|
} else if (col.field === 'subject') {
|
if (record.type === 'total') {
|
colSpan = 0
|
} else {
|
let val = record.subject || ''
|
|
if (editing) {
|
children = <Input.TextArea id={col.uuid + record.uuid} autoSize={false} defaultValue={val} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
|
} else {
|
children = <div className="content-wrap" onClick={this.focus}>{val}</div>
|
}
|
}
|
} else if (col.field === 'debtor') {
|
let val = record.debtor
|
let down = false
|
let vals = []
|
if (typeof(val) === 'number') {
|
if (val < 0) {
|
down = true
|
val = Math.abs(val)
|
}
|
vals = (val * 100).toFixed(0).split('').reverse()
|
}
|
|
if (editing) {
|
children = <InputNumber id={col.uuid + record.uuid} defaultValue={val} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
|
} else {
|
children = <div className={'money-uint' + (down ? ' down' : '')} onClick={this.focus}>
|
<span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
|
<span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
|
</div>
|
}
|
} else if (col.field === 'creditor') {
|
let val = record.creditor
|
let down = false
|
let vals = []
|
if (typeof(val) === 'number') {
|
if (val < 0) {
|
down = true
|
val = Math.abs(val)
|
}
|
vals = (val * 100).toFixed(0).split('').reverse()
|
}
|
|
if (editing) {
|
children = <InputNumber id={col.uuid + record.uuid} defaultValue={val} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
|
} else {
|
children = <div className={'money-uint' + (down ? ' down' : '')} onClick={this.focus}>
|
<span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
|
<span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
|
</div>
|
}
|
}
|
|
if (!colSpan) return null
|
|
return (<td colSpan={colSpan} className={className}>{children}</td>)
|
}
|
}
|
|
class VoucherTable extends Component {
|
static propTpyes = {
|
config: PropTypes.object, // 菜单Id
|
BID: PropTypes.any, // 主表ID
|
data: PropTypes.any, // 表格数据
|
total: PropTypes.any, // 总数
|
loading: PropTypes.bool, // 表格加载中
|
refreshdata: PropTypes.func, // 表格中排序列、页码的变化时刷新
|
}
|
|
state = {
|
dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
|
data: [],
|
edData: [],
|
edColumns: [],
|
tableId: '', // 表格ID
|
pageSize: 10, // 每页数据条数
|
columns: null, // 显示列
|
loading: false,
|
}
|
|
UNSAFE_componentWillMount () {
|
const { config } = this.props
|
|
let data = [
|
{remark: '提现', subject: '1001 库存现金', debtor: 124, creditor: ''},
|
{remark: '购入固定资产', subject: '1001 库存现金', debtor: '', creditor: 124},
|
{remark: '转结销售成本', subject: '1001 库存现金', debtor: -524, creditor: ''},
|
{remark: '提现', subject: '1001 库存现金', debtor: 34, creditor: ''},
|
]
|
|
data = this.initData(data)
|
data.push(this.getTotalLine(data))
|
|
let columns = [
|
{
|
title: '摘要',
|
dataIndex: 'remark',
|
key: 'remark',
|
width: '22%',
|
onCell: record => ({
|
record,
|
col: {uuid: 'remark', field: 'remark', tableId: config.uuid},
|
})
|
},
|
{
|
title: '会计科目',
|
dataIndex: 'subject',
|
key: 'subject',
|
width: '34%',
|
onCell: record => ({
|
record,
|
col: {uuid: 'subject', field: 'subject', tableId: config.uuid},
|
})
|
},
|
{
|
title: () => (<>
|
<div className="money-title">借方金额</div>
|
<div className="money-uint">
|
<span>亿</span> <span>千</span> <span>百</span> <span>十</span> <span>万</span> <span>千</span>
|
<span>百</span> <span>十</span> <span>元</span> <span>角</span> <span className="last">分</span>
|
</div>
|
</>),
|
dataIndex: 'debtor',
|
key: 'debtor',
|
width: '22%',
|
onCell: record => ({
|
record,
|
col: {uuid: 'debtor', field: 'debtor', tableId: config.uuid},
|
})
|
},
|
{
|
title: () => (<>
|
<div className="money-title">贷方金额</div>
|
<div className="money-uint">
|
<span>亿</span> <span>千</span> <span>百</span> <span>十</span> <span>万</span> <span>千</span>
|
<span>百</span> <span>十</span> <span>元</span> <span>角</span> <span className="last">分</span>
|
</div>
|
</>),
|
dataIndex: 'creditor',
|
key: 'creditor',
|
width: '22%',
|
onCell: record => ({
|
record,
|
col: {uuid: 'creditor', field: 'creditor', tableId: config.uuid},
|
})
|
}
|
]
|
|
this.setState({
|
data: data,
|
edData: fromJS(data).toJS(),
|
columns,
|
tableId: config.uuid
|
})
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
componentDidMount () {
|
MKEmitter.addListener('nextLine', this.nextLine)
|
MKEmitter.addListener('delRecord', this.delRecord)
|
MKEmitter.addListener('changeRecord', this.changeRecord)
|
}
|
|
/**
|
* @description 组件销毁,清除state更新
|
*/
|
componentWillUnmount () {
|
this.setState = () => {
|
return
|
}
|
MKEmitter.removeListener('nextLine', this.nextLine)
|
MKEmitter.removeListener('delRecord', this.delRecord)
|
MKEmitter.removeListener('changeRecord', this.changeRecord)
|
}
|
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
|
this.setState({data: nextProps.data || []})
|
}
|
}
|
|
initData = (data) => {
|
let _data = data.map((item, i) => {
|
item.uuid = Utils.getuuid()
|
item.index = i
|
|
return item
|
})
|
|
if (_data.length < 4) {
|
for (let i = _data.length - 1; i < 4; i++) {
|
_data.push({uuid: Utils.getuuid(), index: i + 1, remark: '', subject: '', debtor: '', creditor: ''})
|
}
|
}
|
return _data
|
}
|
|
getTotalLine = (data) => {
|
let totalLine = {uuid: Utils.getuuid(), type: 'total'}
|
let debtor = ''
|
let creditor = ''
|
|
data.forEach(item => {
|
if (typeof(item.debtor) === 'number') {
|
if (debtor === '') {
|
debtor = 0
|
}
|
|
debtor += item.debtor
|
} else if (typeof(item.creditor) === 'number') {
|
if (debtor === '') {
|
debtor = 0
|
}
|
if (creditor === '') {
|
creditor = 0
|
}
|
creditor += item.creditor
|
}
|
})
|
|
totalLine.debtor = debtor
|
totalLine.creditor = creditor
|
|
totalLine.remark = this.changeMoneyToChinese(debtor)
|
|
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
|
}
|
|
nextLine = (col, record) => {
|
const { edData, tableId } = this.state
|
|
if (col.tableId !== tableId) return
|
|
if (record.index < edData.length - 2) {
|
MKEmitter.emit('tdFocus', 'remark' + edData[record.index + 1].uuid)
|
} else {
|
let _data = fromJS(edData).toJS()
|
let line = {uuid: Utils.getuuid(), index: _data.length - 1, remark: record.remark || '', subject: '', debtor: '', creditor: ''}
|
|
_data.splice(_data.length - 1, 0, line)
|
|
this.setState({edData: _data}, () => {
|
MKEmitter.emit('tdFocus', 'remark' + line.uuid)
|
})
|
}
|
}
|
|
plusLine = (initEditLine) => {
|
const { edData } = this.state
|
|
let item = {...edData[edData.length - 1]}
|
|
item.key = item.key + 1
|
item.$$uuid = '$new'
|
|
this.setState({edData: [...edData, item]}, () => {
|
MKEmitter.emit('tdFocus', initEditLine.uuid + item.uuid)
|
})
|
}
|
|
delRecord = (id, record) => {
|
const { tableId, edData } = this.state
|
|
if (id !== tableId) return
|
|
let _data = edData.filter(item => item.uuid !== record.uuid)
|
|
_data.pop()
|
|
if (_data.length < 4) {
|
for (let i = _data.length - 1; i < 4; i++) {
|
_data.push({uuid: Utils.getuuid(), index: i + 1, remark: '', subject: '', debtor: '', creditor: ''})
|
}
|
}
|
|
_data.push(this.getTotalLine(_data))
|
|
this.setState({edData: _data})
|
}
|
|
changeRecord = (tableId, record) => {
|
if (tableId !== this.state.tableId) return
|
|
let _data = this.state.edData.map(item => {
|
if (item.uuid === record.uuid) {
|
return record
|
} else {
|
return item
|
}
|
})
|
|
_data.pop()
|
|
if (record.index === _data.length - 1) {
|
_data.push({uuid: Utils.getuuid(), index: record.index + 1, remark: '', subject: '', debtor: '', creditor: ''})
|
}
|
|
_data.push(this.getTotalLine(_data))
|
|
this.setState({edData: _data})
|
}
|
|
addLine = () => {
|
const { BID } = this.props
|
const { edData } = this.state
|
|
let item = {}
|
if (edData.length > 0) {
|
item = {...edData[edData.length - 1]}
|
item.key = item.key + 1
|
item.$$uuid = '$new'
|
} else {
|
item.key = 0
|
item.$$uuid = '$new'
|
item.$$BID = BID || ''
|
}
|
|
this.setState({edData: [...edData, item]})
|
}
|
|
checkData = () => {
|
const { edData } = this.state
|
|
if (edData.length === 0) {
|
notification.warning({
|
top: 92,
|
message: '提交数据不可为空!',
|
duration: 5
|
})
|
return
|
}
|
let err = ''
|
let data = fromJS(edData).toJS().map(item => {
|
// let line = []
|
// fields.forEach(col => {
|
// if (col.editable !== 'true' || item.$deleted) {
|
// if (col.type === 'number') {
|
// item[col.field] = +item[col.field]
|
// if (isNaN(item[col.field])) {
|
// item[col.field] = 0
|
// }
|
// } else {
|
// item[col.field] = item[col.field] !== undefined ? (item[col.field] + '') : ''
|
// }
|
// return
|
// }
|
// if (col.type === 'text') {
|
// let val = item[col.field] !== undefined ? (item[col.field] + '') : ''
|
// if (col.required === 'true' && !val) {
|
// line.push(`${col.label}不可为空`)
|
// }
|
// item[col.field] = val
|
// } else if (col.type === 'number') {
|
// let val = item[col.field]
|
// if (!val && val !== 0) {
|
// line.push(`${col.label}不可为空`)
|
// return
|
// }
|
// val = +val
|
// if (isNaN(val)) {
|
// line.push(`${col.label}数据格式错误`)
|
// return
|
// }
|
|
// val = +val.toFixed(col.decimal || 0)
|
|
// if (typeof(col.max) === 'number' && val > col.max) {
|
// line.push(`${col.label}不可大于${col.max}`)
|
// } else if (typeof(col.min) === 'number' && val < col.min) {
|
// line.push(`${col.label}不可小于${col.min}`)
|
// }
|
|
// item[col.field] = val
|
// }
|
// })
|
|
return item
|
})
|
|
if (err) {
|
notification.warning({
|
top: 92,
|
message: err,
|
duration: 5
|
})
|
} else {
|
this.submit(data)
|
}
|
}
|
|
submit = (data) => {
|
const { BID } = this.props
|
|
let param = {
|
// excel_in: result.lines,
|
BID: BID || ''
|
}
|
|
this.setState({
|
loading: true
|
})
|
|
param.func = 'submit.innerFunc'
|
|
Api.genericInterface(param).then((res) => {
|
if (res.status) {
|
this.execSuccess(res)
|
} else {
|
this.execError(res)
|
}
|
}, () => {
|
this.execError({})
|
})
|
}
|
|
execSuccess = (res) => {
|
const { submit } = this.props
|
|
if (res && res.ErrCode === 'S') { // 执行成功
|
notification.success({
|
top: 92,
|
message: res.ErrMesg || this.state.dict['main.action.confirm.success'],
|
duration: submit.stime ? submit.stime : 2
|
})
|
} else if (res && res.ErrCode === 'Y') { // 执行成功
|
Modal.success({
|
title: res.ErrMesg || this.state.dict['main.action.confirm.success']
|
})
|
} else if (res && res.ErrCode === '-1') { // 完成后不提示
|
|
}
|
|
this.setState({
|
loading: false
|
})
|
|
if (submit.closetab === 'true') {
|
MKEmitter.emit('popclose')
|
}
|
if (submit.execSuccess !== 'never') {
|
MKEmitter.emit('refreshByButtonResult', submit.$menuId, submit.execSuccess, submit)
|
}
|
}
|
|
execError = (res) => {
|
const { submit } = this.props
|
|
if (res.ErrCode === 'E') {
|
Modal.error({
|
title: res.message || res.ErrMesg,
|
})
|
} else if (res.ErrCode === 'N') {
|
notification.error({
|
top: 92,
|
message: res.message || res.ErrMesg,
|
duration: submit.ntime ? submit.ntime : 10
|
})
|
} else if (res.ErrCode === 'F') {
|
notification.error({
|
className: 'notification-custom-error',
|
top: 92,
|
message: res.message || res.ErrMesg,
|
duration: submit.ftime ? submit.ftime : 10
|
})
|
} else if (res.ErrCode === 'NM') {
|
message.error(res.message || res.ErrMesg)
|
}
|
|
this.setState({
|
loading: false
|
})
|
|
if (submit.execError !== 'never') {
|
MKEmitter.emit('refreshByButtonResult', submit.$menuId, submit.execError, submit)
|
}
|
}
|
|
render() {
|
const { edData, columns} = this.state
|
|
const components = {
|
body: {
|
row: BodyRow,
|
cell: BodyCell
|
}
|
}
|
|
return (
|
<div className="voucher-table-wrap">
|
<Table
|
rowKey="uuid"
|
components={components}
|
columns={columns}
|
dataSource={edData}
|
bordered={true}
|
// loading={this.props.loading}
|
onRow={(record, index) => {
|
return {
|
data: record
|
}
|
}}
|
pagination={false}
|
/>
|
</div>
|
)
|
}
|
}
|
|
export default VoucherTable
|