import {
Button,
Col,
Drawer,
Form,
Input,
InputNumber,
Row,
Space,
Table,
Typography,
message
} from 'antd'
import React, { CSSProperties, ReactNode, useContext, useEffect, useState } from 'react'
import { IBadBillConfirm, IBadBillDetail } from '../../types'
import { badBillConfirm, getBadBillInfo } from './services'
import useModalStore from './store/useModalStore'
import type { FormInstance } from 'antd/es/form'
import { calculateTableListAmount } from '@/views/payment/collectionDetail/list/config/amount'
const { Paragraph } = Typography
const EditableContext = React.createContext<FormInstance<any> | null>(null)
interface EditableRowProps {
index: number
}
interface Item {
key: string
name: string
age: string
address: string
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => {
const [form] = Form.useForm()
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
)
}
interface EditableCellProps {
dataIndex: any
record: any
handleSave: (record: Item) => void
}
const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
children,
dataIndex,
record,
handleSave,
...restProps
}) => {
const form = useContext(EditableContext)!
useEffect(() => {
if (dataIndex === 'bad_amount') {
form.setFieldValue(dataIndex, record[dataIndex])
}
}, [])
let childNode = children
const save = () => {
form.validateFields().then((values) => {
handleSave({ ...record, bad_amount: values?.bad_amount || 0 })
})
}
if (dataIndex === 'bad_amount') {
const unpaid_amount = record?.unpaid_amount ? Number(record?.unpaid_amount) : 0
childNode = (
<Form.Item style={{ margin: 0 }} name={dataIndex}>
<InputNumber
size='middle'
min={0}
max={unpaid_amount < 0 ? 99999999.99 : unpaid_amount}
disabled={unpaid_amount < 0}
controls={false}
placeholder='请输入'
style={{
width: 140
}}
precision={2}
onBlur={save}
/>
</Form.Item>
)
}
return <td {...restProps}>{childNode}</td>
}
interface IComponentModalProps {
// 刷新
refresh: () => void
}
type EditableTableProps = Parameters<typeof Table>[0]
type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>
// 坏账详情确认
const BadBillConfirm: React.FC<IComponentModalProps> = ({ refresh }) => {
const { modalOpen, setModalOpen, selectedRows, setSelectedRowKeys, setSelectedRows } =
useModalStore()
const [disabled, setDisabled] = useState(false) // 禁用
const [loading, setLoading] = useState(false) // 加载中
const [form] = Form.useForm()
const components = {
body: {
row: EditableRow,
cell: EditableCell
}
}
const [dataSource, setDataSource] = useState<IBadBillDetail[]>([])
const defaultColumns: (ColumnTypes[number] & { editable?: boolean; dataIndex: string })[] = [
{
title: '项目名称',
dataIndex: 'project_name',
width: 150,
align: 'center',
render(value) {
return (
<Paragraph style={{ marginBottom: 0 }} ellipsis={{ rows: 2, tooltip: value }}>
{value || ''}
</Paragraph>
)
}
},
{
title: '客户名称',
dataIndex: 'customer_name',
align: 'center',
width: 150,
render(value) {
return (
<Paragraph style={{ marginBottom: 0 }} ellipsis={{ rows: 2, tooltip: value }}>
{value || ''}
</Paragraph>
)
}
},
{
title: '薪资所属月',
dataIndex: 'bill_month',
width: 90,
align: 'center'
},
{
title: '账单金额',
dataIndex: 'bill_amount',
align: 'right',
width: 90
},
{
title: '回款金额',
dataIndex: 'payment_amount',
align: 'right',
width: 90
},
{
title: '剩余应收(不含坏账)',
dataIndex: 'unpaid_amount',
align: 'right',
width: 110
},
{
title: '坏账金额',
dataIndex: 'bad_amount',
align: 'center'
}
]
const columns = defaultColumns.map((col) => {
return {
...col,
onCell: (record: any) => ({
record,
dataIndex: col.dataIndex,
handleSave
})
}
})
useEffect(() => {
modalOpen && selectedRows?.length && getBadBillInfos()
}, [modalOpen, selectedRows?.length])
// 查询坏账信息
const getBadBillInfos = async () => {
try {
setLoading(true)
const bill_ids = selectedRows?.map((item: any) => item?.bill_id)
const { data } = await getBadBillInfo({ bill_ids })
const handleData = data?.map((item: IBadBillDetail, index: number) => {
return {
...item,
keys: `badAmount${index}`
}
})
setLoading(false)
setDataSource(handleData)
} catch (err) {
console.log(err)
} finally {
setLoading(false)
}
}
const handleSave = (row: any) => {
const newData = dataSource ? [...dataSource] : []
const index = newData.findIndex((item) => row.keys === item.keys)
const item = newData[index]
newData.splice(index, 1, {
...item,
...row
})
setDataSource(newData)
}
// 重置状态
const reset = () => {
setDisabled(false)
form.resetFields()
setSelectedRows([])
setSelectedRowKeys([])
setModalOpen(false)
}
// 关闭弹窗
const close = () => {
reset()
}
const onFinish = async (values: IBadBillConfirm) => {
try {
setDisabled(true)
const relation_infos = dataSource?.map((item) => {
return {
repayment_group_detail_id: item?.repayment_group_detail_id,
bad_amount: item?.bad_amount || 0,
bill_id: item?.bill_id,
project_name: item?.project_name
}
})
const params = {
remark: values?.remark,
relation_infos
}
await badBillConfirm(params)
message.success('操作成功')
close()
refresh()
} catch (err) {
console.log(err)
} finally {
setDisabled(false)
}
}
return (
<>
<Drawer
title='坏账详情确认'
placement='right'
onClose={close}
width={900}
open={modalOpen}
className='bad-bill'
footer={[
<Space align='center' style={{ display: 'flex', justifyContent: 'center' }}>
<Button key='cancel' onClick={close}>
取消
</Button>
<Button key='save' type='primary' disabled={disabled} onClick={() => form.submit()}>
保存
</Button>
</Space>
]}
>
<Form
form={form}
labelCol={{
span: 0
}}
wrapperCol={{
span: 24
}}
name='badBill'
layout='horizontal'
onFinish={onFinish}
autoComplete='off'
>
<Row>
<Col span={24}>
<Form.Item name='remark' rules={[{ required: true, message: '请输入坏账原因' }]}>
<Input.TextArea
size='middle'
placeholder='请输入坏账原因'
maxLength={50}
showCount={true}
rows={3}
allowClear
/>
</Form.Item>
</Col>
</Row>
</Form>
<Table
components={components}
bordered
loading={loading}
rowKey={(_, i) => i as any}
dataSource={dataSource}
columns={columns as ColumnTypes}
pagination={false}
scroll={{ x: 'max-content', y: 'calc(100vh - 340px)' }}
summary={() => {
const billAmount = calculateTableListAmount(dataSource ?? [], 'bill_amount') // 账单金额总计
const paymentAmount = calculateTableListAmount(dataSource ?? [], 'payment_amount') // 回款金额总计
const unpaidAmount = calculateTableListAmount(dataSource ?? [], 'unpaid_amount') // 剩余应收(不含坏账)总计
const badAmount = calculateTableListAmount(dataSource ?? [], 'bad_amount') // 坏账金额总计
const cells: {
index: number
content: string | ReactNode
style: CSSProperties
}[] = [
{
index: 0,
content: '',
style: {}
},
{
index: 1,
content: '',
style: {}
},
{
index: 2,
content: '',
style: {}
},
{
index: 3,
content: `${billAmount?.toFixed(2) || '0.00'}`,
style: {
textAlign: 'right'
}
},
{
index: 4,
content: `${paymentAmount?.toFixed(2) || '0.00'}`,
style: {
textAlign: 'right'
}
},
{
index: 5,
content: `${unpaidAmount?.toFixed(2) || '0.00'}`,
style: {
textAlign: 'right'
}
},
{
index: 6,
content: `${badAmount?.toFixed(2) || '0.00'}`,
style: {
textAlign: 'center'
}
}
]
return dataSource?.length > 0 ? (
<Table.Summary fixed>
<Table.Summary.Row>
{(cells ?? []).map((i, index) => (
<Table.Summary.Cell key={`${i.index}-${index}`} index={i.index}>
<div style={i.style}>{i.content}</div>
</Table.Summary.Cell>
))}
</Table.Summary.Row>
</Table.Summary>
) : null
}}
/>
</Drawer>
</>
)
}
export default BadBillConfirm
06-21
188
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
05-17