// import { PlusOutlined } from '@ant-design/icons'; import InvoiceModal from '@/pages/Invoice/waitProcessRecord/components/InvoiceModal'; import { postServiceConstGetPayeeEnum, postServiceConstInitInvoiceDetailNames, postServiceConstInvoiceType, postServiceConstInvoicingType, postServiceConstListInvoiceDetailNames, postServiceInvoiceApplyInvoice, postServiceInvoiceQueryCompanyInfo, postServiceInvoiceWaitReissueInvoices, } from '@/services'; import { FloatAdd, FloatSub, enum2ReverseSelect, enumToSelect } from '@/utils'; import { convertCurrency } from '@/utils/numberUtil'; import { DrawerForm, FormListActionType, ProCard, ProFormDigit, ProFormGroup, ProFormInstance, ProFormList, ProFormMoney, ProFormSelect, ProFormText, ProFormTextArea, } from '@ant-design/pro-components'; import { Button, Divider, Form, Space, Tooltip, message } from 'antd'; import { useEffect, useRef, useState } from 'react'; export default ({ dataList, setVisible, mainOrder, onClose }) => { // let subOrderIds = dataList?.map((item) => { // return item.id; // }) const [form] = Form.useForm(); const [projectOptions] = useState(); const [dataListCopy] = useState(dataList); const listActionRef = useRef<FormListActionType>(); const formRef = useRef<ProFormInstance>(); useEffect(() => { const initOptions = async () => { const res = await postServiceConstInitInvoiceDetailNames({ data: dataListCopy.map((item) => { return item.productName; }), }); const options = res.data; const datas = dataListCopy.map((item) => { return { ...item, projectName: options[item.productName], }; }); const initialValue = datas.map((item) => { return { productName: item.productName, projectName: item.projectName, subOrderId: item.id, specification: item.parameters, unit: item.unit, quantity: item.quantity, price: item.productPrice, totalPrice: item.subOrderPayment, }; }); form.setFieldValue('invoiceDetails', initialValue); form.setFieldValue('contacts', mainOrder.customerName); }; initOptions(); }, []); useEffect(() => {}, [projectOptions]); function copyToClipboard(text: string) { // 创建一个临时的textarea元素 const textarea = document.createElement('textarea'); textarea.value = text; // 将textarea元素添加到DOM中 document.body.appendChild(textarea); // 选中textarea中的文本 textarea.select(); try { // 尝试执行复制命令 document.execCommand('copy'); return true; } catch (err) { return false; } finally { // 移除临时的textarea元素 document.body.removeChild(textarea); } } useEffect(() => {}, []); return ( <DrawerForm open title="申请开票" resize={{ maxWidth: window.innerWidth * 0.8, minWidth: 500, }} form={form} formRef={formRef} autoFocusFirstInput drawerProps={{ destroyOnClose: true, }} submitter={{ render: (props, defaultDoms) => { return [ <InvoiceModal key={'invoicePreview'} button={<Button type="primary"> 发票预览 </Button>} getRecord={() => { const totalPrice = form .getFieldValue('invoiceDetails') .reduce((accumulator, currentValue) => { return FloatAdd(accumulator, currentValue.totalPrice); }, 0); const partyBName = form.getFieldValue('partyBName'); const openBank = form.getFieldValue('openBank'); const bankAccount = form.getFieldValue('bankAccount'); const bankCode = form.getFieldValue('bankCode'); return { ...form.getFieldsValue(), totalPrice: totalPrice, totalPriceText: convertCurrency(totalPrice), comment: '开户名称: ' + partyBName + '\n' + '开户行: ' + openBank + '\n' + '账号: ' + bankAccount + '\n' + '银行联行号: ' + bankCode, }; }} />, ...defaultDoms, ]; }, }} submitTimeout={2000} onFinish={async (values) => { postServiceInvoiceApplyInvoice({ data: { ...values, subOrderIds: dataListCopy.map((item) => { return item.id; }), }, }); onClose(); }} onOpenChange={(val) => { return !val && setVisible(); }} > <ProFormList name="subOrderIdObjs" readonly={true} label="开票订单" initialValue={dataListCopy.map((item) => { return { value: item.id, }; })} deleteIconProps={false} copyIconProps={false} > <ProFormGroup key="group"> <ProFormText readonly={true} name="value" label="" /> </ProFormGroup> </ProFormList> <ProFormSelect name="ReissueInvoiceRecordIds" label="重开的发票" fieldProps={{ mode: 'multiple', }} placeholder="请选择重开发票" request={async () => { let reissueIds = dataListCopy.map((item) => { return item.id; }); let res = await postServiceInvoiceWaitReissueInvoices({ data: reissueIds, }); return enum2ReverseSelect(res.data); }} /> <ProFormSelect key="key" label="购方名称" width="lg" showSearch name="partyAName" placeholder="请搜索购方" rules={[{ required: true, message: '购方名称必填' }]} onChange={(_, option) => { form.setFieldValue('partyATaxid', option.taxId); }} fieldProps={{ optionItemRender(item) { if (item.type === 'add') { return <>{item.name}</>; } return ( <> {item.name} <Divider type="vertical" /> {item.taxId} </> ); }, }} debounceTime={1000} request={async (value) => { const keywords = value.keyWords; const res = await postServiceInvoiceQueryCompanyInfo({ data: { nameLike: keywords, taxIdIsNotNull: true, }, }); let options = res?.data?.map((company) => { return { ...company, label: company.name, value: company.name, key: company.id, }; }); //第一个商品默认为要新增的商品 if (keywords.trim() !== '') { options.unshift({ name: keywords, type: 'add', label: keywords, value: keywords, key: keywords, }); } return options; }} /> <ProFormText width="md" name="partyATaxid" label="购方税号" rules={[{ required: true, message: '购方税号必填' }]} placeholder="请输入名称" /> <ProFormText width="md" name="partyAOpenBank" label="开户银行" placeholder="请输入名称" /> <ProFormText width="md" name="partyABankAccount" label="开户行账号" placeholder="请输入名称" /> <ProFormText name="contacts" label="联系人" rules={[{ required: true, message: '请选择银行联行号!' }]} /> <ProFormSelect name="invoicingType" label="开具类型" request={async () => { let invoicingTypeRet = await postServiceConstInvoicingType(); let options = enumToSelect(invoicingTypeRet.data); return options; }} placeholder="请选择开具类型" rules={[{ required: true, message: '请选择开具类型!' }]} /> <ProFormSelect name="type" label="开票类型" placeholder="请选择开票类型" rules={[{ required: true, message: '请选择开票类型!' }]} request={async () => { let invoiceTypeRet = await postServiceConstInvoiceType(); let options = enumToSelect(invoiceTypeRet.data); return options; }} /> <ProFormSelect name="partyB" label="开票收款单位" request={async () => { const res = await postServiceConstGetPayeeEnum(); let options = res?.data?.map((payee: any) => { return { ...payee, label: payee.payeeName, value: payee.name, }; }); return options; }} onChange={(_, option) => { if (option) { form.setFieldsValue({ partyBName: option.payeeName, partyBTaxid: option.taxId, bankAccount: option.bankAccount, openBank: option.openBank, bankCode: option.bankCode, }); } }} placeholder="请选择收款单位" rules={[{ required: true, message: '请选择收款单位!' }]} /> <ProFormText name="partyBName" label="开票收款单位名称" hidden rules={[{ required: true, message: '请选择收款单位!' }]} /> <ProFormText name="partyBTaxid" label="开票收款单位税号" hidden rules={[{ required: true, message: '请选择收款单位!' }]} /> <ProFormText name="bankAccount" label="账号" hidden rules={[{ required: true, message: '请选择账号!' }]} /> <ProFormText name="openBank" label="开户行" hidden rules={[{ required: true, message: '请选择开户行!' }]} /> <ProFormText name="bankCode" label="银行联行号" hidden rules={[{ required: true, message: '请选择银行联行号!' }]} /> <ProFormSelect name="isUrgent" label="是否加急" valueEnum={{ true: '是', false: '否', }} placeholder="请选择是否加急" rules={[{ required: true, message: '请选择是否加急!' }]} /> <ProFormMoney label="开票金额" name="price" locale="zh-CN" disabled={true} rules={[{ required: true, message: '请填写开票金额!' }]} initialValue={dataListCopy.reduce((accumulator, currentValue) => { return accumulator + currentValue.subOrderPayment; }, 0)} /> <ProFormList name="invoiceDetails" label="开票明细" actionRef={listActionRef} actionGuard={{ beforeRemoveRow: async (index) => { const list = listActionRef.current?.getList(); const totalPrice = list[index].totalPrice; form.setFieldValue( 'price', FloatSub(form.getFieldValue('price'), totalPrice), ); return true; }, }} rules={[ { required: true, validator: async (_, value) => { if (value && value.length > 0) { return; } throw new Error('至少要有一项!'); }, }, ]} itemRender={(doms, listMeta) => { return ( <ProCard bordered extra={doms.action} title={'明细' + (listMeta.index + 1)} style={{ marginBlockEnd: 8, }} > <Tooltip title="点击复制商品名称"> <Space className="hover:cursor-pointer" style={{ margin: 16, marginTop: 4, marginLeft: 0, fontSize: 15, }} onClick={() => { copyToClipboard(listMeta.record.productName); message.info('商品名称复制成功!'); }} > 商品名称:{listMeta.record.productName} </Space> </Tooltip> <ProFormSelect key={'projectName' + listMeta.index} width="md" showSearch name="projectName" rules={[{ required: true, message: '请输入开票项目名称!' }]} request={async (value) => { const keywords = value.keyWords; const res = await postServiceConstListInvoiceDetailNames({ data: { nameLike: keywords, }, }); let options = res?.data?.map((c: any) => { return { ...c, label: '*' + c.productAndServiceCatagoryAbbreviation + '*' + c.name, value: '*' + c.productAndServiceCatagoryAbbreviation + '*' + c?.name, key: c.id, }; }); return options; }} fieldProps={{ filterOption() { return true; }, }} onChange={(_, option) => { let index = listMeta.index; let copyList = form.getFieldValue('invoiceDetails'); let currentData = copyList[index]; currentData.projectName = '*' + option.productAndServiceCatagoryAbbreviation + '*' + option.name; form.setFieldValue('invoiceDetails', copyList); }} debounceTime={1000} label="项目名称" initialValue={listMeta.record.projectName} placeholder="请输入名称" /> <ProFormText key={'specification' + listMeta.index} name="specification" label="规格型号" rules={[ { message: '规格型号不能为空!', required: true, }, { validator: (_, value) => { let len = 0; // 判断是否为全角字符 for (let i = 0; i < value.length; i++) { // 获取字符的Unicode值 const code = value.charCodeAt(i); // 判断是否为全角字符 if ( (code >= 0xff01 && code <= 0xff5e) || (code >= 0x4e00 && code <= 0x9fff) ) { len += 2; // 全角字符 } else { len += 1; // 半角字符 } } if (len <= 40) { return Promise.resolve(); } return Promise.reject( new Error('规格型号不能超过40个字符!'), ); }, }, ]} placeholder="请输入名称" /> <ProFormText key={'unit' + listMeta.index} name="unit" label="单位" placeholder="请输入名称" /> <ProFormDigit key={'quantity' + listMeta.index} label="数量" name="quantity" rules={[ { validator: (_, value) => { if (value === undefined || value > 0) { return Promise.resolve(); } return Promise.reject(new Error('数量必须大于0')); }, }, ]} /> <ProFormDigit key={'price' + listMeta.index} label="单价" name="price" rules={[ { validator: (_, value) => { if (value === undefined || value > 0) { return Promise.resolve(); } return Promise.reject(new Error('单价必须大于0')); }, }, ]} /> <ProFormMoney key={'totalPrice' + listMeta.index} label="金额" name="totalPrice" onChange={() => { const invoiceDetails = form.getFieldValue('invoiceDetails'); console.log('invoiceDetails', invoiceDetails); const totalPrice = invoiceDetails.reduce( (accumulator, currentValue) => { return FloatAdd(accumulator, currentValue.totalPrice); }, 0, ); console.log('totalPrice', totalPrice); form.setFieldValue('price', totalPrice); }} rules={[ { validator: (_, value) => { if (value === undefined || value > 0) { return Promise.resolve(); } return Promise.reject(new Error('金额必须大于0')); }, }, ]} locale="zh-CN" /> </ProCard> ); }} ></ProFormList> <ProFormTextArea name="applyInvoicingNotes" label="备注" placeholder="请输入名称" /> </DrawerForm> ); };