import ButtonConfirm from '@/components/ButtomConfirm'; import EllipsisDiv from '@/components/Div/EllipsisDiv'; import { RESPONSE_CODE } from '@/constants/enum'; import AddInvoiceDrawerForm from '@/pages/Invoice/components/AddInvoiceDrawerForm'; import InvoiceModal from '@/pages/Invoice/components/InvoiceModal'; import InvoiceRecordDetailModal from '@/pages/Invoice/components/InvoiceRecordDetailModal'; import InvoicingModal from '@/pages/Invoice/components/InvoicingModal'; import { BANK_STATEMENT_COLUMNS, INVOICE_COLUMNS, INVOICE_STATUS, } from '@/pages/Invoice/constant'; import { postServiceBankStatementDeleteBankStatement, postServiceBankStatementEditBankStatement, postServiceBankStatementQueryBankStatement, postServiceConstAfterInvoicingInvoiceRecordStatus, postServiceConstBeforeInvoicingInvoiceRecordStatus, postServiceConstInvoiceType, postServiceConstInvoicingType, postServiceInvoiceDeleteInvoice, postServiceInvoiceInvoicing, postServiceInvoiceQueryInvoice, postServiceInvoiceQueryInvoiceRecordList, postServiceOrderQuerySalesCode, } from '@/services'; import { enumToProTableEnumValue, enumToSelect, enumValueToLabel, formatDateTime, } from '@/utils'; import { formatDate } from '@/utils/time'; import { PlusOutlined } from '@ant-design/icons'; import { ActionType, ModalForm, ProTable } from '@ant-design/pro-components'; import { Button, Space, Table, Tabs, message } from 'antd'; import { useEffect, useRef, useState } from 'react'; import { INVOCING_STATUS, PAYEE_OPTIONS } from '../Order/constant'; import BankImportModal from './components/BankImportModal'; import InvoiceVerificationModal from './components/InvoiceVerificationModal'; import './index.less'; const InvoicePage = () => { const invoiceActionRef = useRef<ActionType>(); const bankActionRef = useRef<ActionType>(); const waitDealrecordActionRef = useRef<ActionType>(); const processedRecordRef = useRef<ActionType>(); const [invoiceTypeValueEnum, setInvoiceTypeValueEnum] = useState({}); const [invoicingTypeValueEnum, setInvoicingTypeValueEnum] = useState({}); const [salesCodeValueEnum, setSalesCodeValueEnum] = useState({}); const [bankImportModalVisible, setBankImportModalVisible] = useState(false); const [invoiceVerificationVisible, setInvoiceVerificationVisible] = useState(false); const [invoiceId, setInvoiceId] = useState(undefined); useEffect(() => { async function extracted() { let invoiceTypeRet = await postServiceConstInvoiceType(); setInvoiceTypeValueEnum(invoiceTypeRet.data); } extracted().catch(console.error); }, []); useEffect(() => { async function extracted() { let invoicingTypeRet = await postServiceConstInvoicingType(); setInvoicingTypeValueEnum(invoicingTypeRet.data); } extracted().catch(console.error); }, []); useEffect(() => { async function extracted() { const res = await postServiceOrderQuerySalesCode(); let map = {}; res.data?.forEach((item) => { map[item.userName] = { text: item.userName, status: item.userName, }; }); setSalesCodeValueEnum(map); } extracted().catch(console.error); }, []); const reloadInvoiceTable = () => { invoiceActionRef.current?.reload(); }; const reloadBankStatementTable = () => { bankActionRef.current?.reload(); }; const reloadRecordTable = () => { waitDealrecordActionRef.current?.reload(); processedRecordRef.current?.reload(); }; const getTableCellText = (target: any) => { if (!target) { return ''; } if (target.props) { return target.props.text; } return target; }; const waitDealRecordColumns = [ { dataIndex: 'index', valueType: 'indexBorder', hideInSearch: true, ellipsis: true, width: 48, }, { title: '开票编号', valueType: 'text', dataIndex: 'id', copyable: true, hideInSearch: true, ellipsis: true, width: 100, }, { title: '发票状态', valueType: 'Text', dataIndex: 'statusText', ellipsis: true, hideInSearch: true, }, { title: '申请开票时间', dataIndex: 'createTime', valueType: 'dateTime', hideInSearch: true, ellipsis: true, }, { title: '销售代表', valueType: 'text', hideInSearch: true, ellipsis: true, dataIndex: 'createByName', }, { title: '购方名称', valueType: 'text', dataIndex: 'partyAName', hideInSearch: true, ellipsis: true, }, { title: '购方税号', valueType: 'text', hideInSearch: true, dataIndex: 'partyATaxid', ellipsis: true, }, { title: '收款单位', valueType: 'text', hideInSearch: true, dataIndex: 'partyBName', ellipsis: true, }, { title: '开票金额', valueType: 'money', dataIndex: 'price', hideInSearch: true, ellipsis: true, }, { title: '开具类型', valueType: 'Text', dataIndex: 'invoicingTypeText', hideInSearch: true, ellipsis: true, }, { title: '发票类型', valueType: 'Text', dataIndex: 'typeText', hideInSearch: true, ellipsis: true, }, { title: '是否加急', valueType: 'Text', dataIndex: 'isUrgentText', hideInSearch: true, ellipsis: true, }, { title: '购方名称', valueType: 'Text', dataIndex: 'partyANameLike', hideInTable: true, }, { title: '收款单位', valueType: 'select', dataIndex: 'partyB', filters: true, onFilter: true, hideInTable: true, valueEnum: enumToProTableEnumValue(PAYEE_OPTIONS), }, { title: '主订单号', valueType: 'Text', dataIndex: 'mainOrderId', hideInTable: true, }, { title: '子订单号', valueType: 'Text', dataIndex: 'subOrderId', hideInTable: true, }, { title: '销售代表', valueType: 'select', dataIndex: 'salesCode', filters: true, onFilter: true, hideInTable: true, valueEnum: salesCodeValueEnum, }, { title: '发票类型', valueType: 'select', dataIndex: 'type', filters: true, onFilter: true, hideInTable: true, valueEnum: enumToProTableEnumValue(invoiceTypeValueEnum), }, { title: '开具类型', valueType: 'select', dataIndex: 'invoicingType', filters: true, onFilter: true, hideInTable: true, valueEnum: enumToProTableEnumValue(invoicingTypeValueEnum), }, { title: '开票状态', valueType: 'select', dataIndex: 'status', filters: true, onFilter: true, hideInTable: true, request: async () => { const res = await postServiceConstBeforeInvoicingInvoiceRecordStatus(); return enumToSelect(res.data); }, }, { title: '是否加急', valueType: 'select', dataIndex: 'isUrgent', filters: true, onFilter: true, hideInTable: true, valueEnum: { true: { text: '是', status: true, }, false: { text: '否', status: false, }, }, }, { title: '申请开票时间', dataIndex: 'createTime', valueType: 'dateRange', width: 200, hideInTable: true, search: { transform: (value) => { if (value) { return { createTimeGe: value[0], createTimeLe: value[1], }; } }, }, }, { title: '操作', valueType: 'option', key: 'option', render: (text, record) => { return [ <InvoiceRecordDetailModal key="detail" id={record.id} subOrderIds={record.subOrderIds} />, <InvoiceModal key="invoiceModal" recordId={record.id} />, ]; }, }, ]; const processedRecordColumns = [ { dataIndex: 'index', valueType: 'indexBorder', }, { title: '开票编号', valueType: 'text', dataIndex: 'id', copyable: true, ellipsis: true, }, { title: '发票号码', valueType: 'text', dataIndex: 'invoiceNumber', copyable: true, ellipsis: true, }, { title: '开票日期', dataIndex: 'invoicingTime', valueType: 'dateTime', hideInSearch: true, ellipsis: true, }, { title: '发票类型', valueType: 'Text', dataIndex: 'typeText', hideInSearch: true, ellipsis: true, }, { title: '发票状态', valueType: 'Text', dataIndex: 'statusText', hideInSearch: true, ellipsis: true, }, { title: '购方名称', valueType: 'text', dataIndex: 'partyAName', hideInSearch: true, ellipsis: true, }, { title: '购方税号', valueType: 'text', dataIndex: 'partyATaxid', ellipsis: true, }, { title: '收款单位', valueType: 'text', dataIndex: 'partyBName', hideInSearch: true, ellipsis: true, }, { title: '联系人', valueType: 'text', dataIndex: 'contacts', hideInSearch: true, ellipsis: true, }, { title: '申请人', valueType: 'text', dataIndex: 'createByName', hideInSearch: true, ellipsis: true, }, { title: '开票金额(元)', valueType: 'money', dataIndex: 'price', hideInSearch: true, ellipsis: true, }, { title: '备注', valueType: 'text', dataIndex: 'contacts', hideInSearch: true, ellipsis: true, }, { title: '购方名称', valueType: 'text', dataIndex: 'partyANameLike', hideInTable: true, }, { title: '发票类型', valueType: 'select', dataIndex: 'type', filters: true, onFilter: true, hideInTable: true, valueEnum: enumToProTableEnumValue(invoiceTypeValueEnum), }, { title: '开票状态', valueType: 'select', dataIndex: 'status', filters: true, onFilter: true, hideInTable: true, request: async () => { const res = await postServiceConstAfterInvoicingInvoiceRecordStatus(); return enumToSelect(res.data); }, }, { title: '销售代表', valueType: 'select', dataIndex: 'salesCode', filters: true, onFilter: true, hideInTable: true, valueEnum: salesCodeValueEnum, }, { title: '联系人', valueType: 'text', dataIndex: 'contactsLike', hideInTable: true, }, { title: '开票日期', dataIndex: 'invoicingTime', valueType: 'dateRange', hideInTable: true, search: { transform: (value) => { if (value) { return { invoicingTimeGe: value[0], invoicingTimeLe: value[1], }; } }, }, }, { title: '收款单位', valueType: 'select', dataIndex: 'partyB', filters: true, onFilter: true, hideInTable: true, valueEnum: enumToProTableEnumValue(PAYEE_OPTIONS), }, { title: '操作', valueType: 'option', key: 'option', render: (text, record) => [ <InvoiceRecordDetailModal key="detail" id={record.id} subOrderIds={record.subOrderIds} />, <> {record.status === 'SUCCESS' && ( <> {record.status === 'SUCCESS' && ( <a href={record.invoiceAddress} download> 下载发票 </a> )} </> )} </>, <> {record.status === 'FAIL' && ( <ModalForm title="提示" trigger={ <Button type="link" danger> 重试 </Button> } autoFocusFirstInput modalProps={{ destroyOnClose: true, }} submitTimeout={2000} onFinish={async () => { const res = await postServiceInvoiceInvoicing({ data: { invoiceRecordIds: [record.id], }, }); if (res) { message.success(res.message); processedRecordRef?.current?.reload(); } return true; }} > 确定重试订单信息吗? </ModalForm> )} </>, ], }, ]; /** * 加载发票列表表格的各个列格式 */ const invoicecColumnsInit = () => { let columns = INVOICE_COLUMNS.map((item) => { let newItem = { ...item }; let dataIndex = item.dataIndex; let dataType = item.valueType; newItem.render = (text, record) => { let textValue = record[dataIndex]; if (dataType === 'dateRange' || dataType === 'date') { textValue = formatDate(textValue); } if (dataType === 'dateTime') { textValue = formatDateTime(textValue); } if (dataType === 'money') { textValue = '¥' + textValue; } switch (dataIndex) { case 'invoiceStatus': return ( <EllipsisDiv text={enumValueToLabel( getTableCellText(textValue), INVOCING_STATUS, )} /> ); case 'status': return ( <EllipsisDiv text={enumValueToLabel( getTableCellText(textValue), INVOICE_STATUS, )} /> ); case 'payee': return ( <EllipsisDiv text={enumValueToLabel( getTableCellText(textValue), PAYEE_OPTIONS, )} /> ); default: return <EllipsisDiv text={getTableCellText(textValue)} />; } }; return newItem; }); columns.push({ title: '操作', valueType: 'option', key: 'option', fixed: 'right', width: 120, render: (text, record) => { let btns = []; if (record.path?.includes('writeOff')) { btns.push( <a key="editable" onClick={() => { setInvoiceVerificationVisible(true); setInvoiceId(record.invoiceId); }} > 核销 </a>, ); } if (record.path?.includes('queryInvoiceDetails')) { btns.push( <Button className="p-0" key="view" type="link" onClick={() => { setInvoiceVerificationVisible(true); setInvoiceId(record.invoiceId); }} > 查看 </Button>, ); } if (record.path?.includes('deleteInvoice')) { btns.push( <ButtonConfirm key="delete" className="p-0" title={ '确认删除发票号码为[ ' + record.invoiceNumber + ' ]的发票吗?' } text="删除" onConfirm={async () => { let res = await postServiceInvoiceDeleteInvoice({ data: { invoiceId: record.invoiceId }, }); if (res) { message.success(res.message); reloadInvoiceTable(); } }} />, ); } return btns; }, }); return columns; }; const bankStatemetColumnsInit = () => { let columns = BANK_STATEMENT_COLUMNS.map((item) => { let newItem = { ...item }; let dataIndex = item.dataIndex; let dataType = item.valueType; newItem.render = (text, record) => { let textValue = record[dataIndex]; if (dataType === 'date') { textValue = formatDate(textValue); } if (dataType === 'dateTime') { textValue = formatDateTime(textValue); } if (dataType === 'money') { if (textValue === null || textValue === undefined) { textValue = ''; } else { textValue = '¥' + textValue; } } switch (dataIndex) { case 'invoiceStatus': return ( <EllipsisDiv text={enumValueToLabel( getTableCellText(textValue), INVOCING_STATUS, )} /> ); case 'status': return ( <EllipsisDiv text={enumValueToLabel( getTableCellText(textValue), INVOICE_STATUS, )} /> ); case 'payee': return ( <EllipsisDiv text={enumValueToLabel( getTableCellText(textValue), PAYEE_OPTIONS, )} /> ); default: return <EllipsisDiv text={getTableCellText(textValue)} />; } }; return newItem; }); columns.push({ title: '操作', valueType: 'option', key: 'option', fixed: 'right', width: 120, render: (text, record, _, action) => { let btns = []; if (record.path?.includes('editBankStatement')) { btns.push( <a key="editable" onClick={() => { action?.startEditable?.(record.id); }} > 编辑 </a>, ); } if (record.path?.includes('deleteBankStatement')) { btns.push( <ButtonConfirm key="delete" className="p-0" title={'是否删除该银行流水记录?'} text="删除" onConfirm={async () => { let res = await postServiceBankStatementDeleteBankStatement({ data: { id: record.id }, }); if (res.result === RESPONSE_CODE.SUCCESS) { message.success(res.message); reloadBankStatementTable(); } }} />, ); } return btns; }, }); return columns; }; const tabsItems = [ { key: 1, label: '待处理', children: ( <ProTable columns={waitDealRecordColumns} actionRef={waitDealrecordActionRef} cardBordered pagination={{ pageSize: 10, }} rowSelection={{ selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT], alwaysShowAlert: true, }} tableAlertOptionRender={({ selectedRowKeys, selectedRows }) => { console.log(selectedRows); console.log(selectedRowKeys); return ( <Space size={16}> <InvoicingModal reloadRecordTable={reloadRecordTable} key="button" selectedRowKeys={selectedRowKeys} /> </Space> ); }} request={async (params) => { let res = await postServiceInvoiceQueryInvoiceRecordList({ data: { ...params, statusIn: [ 'WAITING_FOR_INVOICING', 'AUDITING', 'AUDITING_NOT_PASSED', 'CANCELED', ], }, }); return { data: res?.data?.data, total: res?.data?.total || 0, }; }} columnsState={{ persistenceKey: 'pro-table-singe-demos', persistenceType: 'localStorage', defaultValue: { option: { fixed: 'right', disable: true }, }, onChange(value) { console.log('value: ', value); }, }} rowKey="id" search={{ labelWidth: 'auto', }} options={{ setting: { listsHeight: 400, }, }} form={{}} dateFormatter="string" headerTitle="待开票列表" scroll={{ x: 1400, y: 360 }} /> ), }, { key: 2, label: '开票记录', children: ( <ProTable columns={processedRecordColumns} actionRef={processedRecordRef} cardBordered pagination={{ pageSize: 10, }} editable={{ type: 'multiple', onSave: async (rowKey, data) => { await postServiceBankStatementEditBankStatement({ data: data }); }, actionRender: (row, config, defaultDom) => [ defaultDom.save, defaultDom.cancel, ], }} request={async (params) => { let res = await postServiceInvoiceQueryInvoiceRecordList({ data: { ...params, statusIn: ['INVOICING', 'SUCCESS', 'FAIL'], }, }); return { data: res?.data?.data, total: res?.data?.total || 0, }; }} columnsState={{ persistenceKey: 'pro-table-singe-demos', persistenceType: 'localStorage', defaultValue: { option: { fixed: 'right', disable: true }, }, onChange(value) { console.log('value: ', value); }, }} rowKey="id" search={{ labelWidth: 'auto', }} options={{ setting: { listsHeight: 400, }, }} form={{}} dateFormatter="string" headerTitle="待开票列表" scroll={{ x: 1400, y: 360 }} toolBarRender={() => []} /> ), }, { key: 3, label: '发票管理', children: ( <ProTable columns={invoicecColumnsInit()} actionRef={invoiceActionRef} cardBordered pagination={{ pageSize: 10, }} request={async (params) => { const res = await postServiceInvoiceQueryInvoice({ data: { ...params }, }); if (res) { return { data: res?.data?.data || [], total: res?.data?.total || 0, }; } }} columnsState={{ persistenceKey: 'pro-table-singe-demos', persistenceType: 'localStorage', defaultValue: { option: { fixed: 'right', disable: true }, }, onChange(value) { console.log('value: ', value); }, }} rowKey="id" search={{ labelWidth: 'auto', }} options={{ setting: { listsHeight: 400, }, }} form={{}} dateFormatter="string" headerTitle="发票列表" scroll={{ x: 1400, y: 360 }} toolBarRender={() => [ <AddInvoiceDrawerForm onClose={() => { invoiceActionRef.current?.reload(); bankActionRef.current?.reload(); }} key="add" ></AddInvoiceDrawerForm>, ]} /> ), }, { key: 4, label: '银行流水', children: ( <ProTable columns={bankStatemetColumnsInit()} actionRef={bankActionRef} cardBordered pagination={{ pageSize: 10, }} editable={{ type: 'multiple', onSave: async (rowKey, data) => { await postServiceBankStatementEditBankStatement({ data: data }); }, actionRender: (row, config, defaultDom) => [ defaultDom.save, defaultDom.cancel, ], }} request={async (params) => { const res = await postServiceBankStatementQueryBankStatement({ data: { ...params }, }); if (res) { return { data: res?.data?.data || [], total: res?.data?.total || 0, }; } }} columnsState={{ persistenceKey: 'pro-table-singe-demos', persistenceType: 'localStorage', defaultValue: { option: { fixed: 'right', disable: true }, }, onChange(value) { console.log('value: ', value); }, }} rowKey="id" search={{ labelWidth: 'auto', }} options={{ setting: { listsHeight: 400, }, }} form={{}} dateFormatter="string" headerTitle="银行流水列表" scroll={{ x: 1400, y: 360 }} toolBarRender={() => [ <Button key="button" icon={<PlusOutlined />} onClick={() => { setBankImportModalVisible(true); }} type="primary" > 导入 </Button>, ]} /> ), }, ]; return ( <div className="invoice-index"> <Tabs defaultActiveKey="1" items={tabsItems} onChange={(value) => { if (value === 1) { invoiceActionRef.current?.reload(); } else { bankActionRef.current?.reload(); } }} /> {bankImportModalVisible ? ( <BankImportModal setVisible={setBankImportModalVisible} onClose={() => { setBankImportModalVisible(false); invoiceActionRef.current?.reload(); bankActionRef.current?.reload(); }} ></BankImportModal> ) : ( '' )} {invoiceVerificationVisible ? ( <InvoiceVerificationModal setVisible={setInvoiceVerificationVisible} invoiceId={invoiceId} onClose={() => { invoiceActionRef.current?.reload(); bankActionRef.current?.reload(); }} ></InvoiceVerificationModal> ) : ( '' )} </div> ); }; export default InvoicePage;