Commit 1564fd17b183856118735bb0799ddcb1377f38bc
1 parent
adfd7a78
feat: 开票功能开发
Showing
7 changed files
with
161 additions
and
73 deletions
src/pages/Invoice/components/Invoice.tsx
1 | -import { postServiceInvoiceGetInvoiceRecord } from '@/services'; | |
2 | -import { useEffect, useState } from 'react'; | |
3 | 1 | import styled from 'styled-components'; |
4 | 2 | const InvoiceTmpDiv = styled.div` |
5 | 3 | font-size: 12px; |
... | ... | @@ -147,19 +145,7 @@ const ProjectContainer = styled.div` |
147 | 145 | height: 30px; |
148 | 146 | } |
149 | 147 | `; |
150 | -export default ({ recordId }) => { | |
151 | - const [data, setData] = useState<any>({}); | |
152 | - useEffect(() => { | |
153 | - const getData = async () => { | |
154 | - let ret = await postServiceInvoiceGetInvoiceRecord({ | |
155 | - query: { | |
156 | - id: recordId, | |
157 | - }, | |
158 | - }); | |
159 | - setData(ret.data); | |
160 | - }; | |
161 | - getData(); | |
162 | - }, []); | |
148 | +export default ({ data }) => { | |
163 | 149 | return ( |
164 | 150 | <div> |
165 | 151 | <InvoiceTmpDiv> | ... | ... |
src/pages/Invoice/components/InvoiceModal.tsx
1 | 1 | import Invoice from '@/pages/Invoice/components/Invoice'; |
2 | +import { postServiceInvoiceGetInvoiceRecord } from '@/services'; | |
2 | 3 | import { ModalForm } from '@ant-design/pro-components'; |
3 | -import { Form, message } from 'antd'; | |
4 | -import { useEffect } from 'react'; | |
4 | +import { Form } from 'antd'; | |
5 | +import { useEffect, useState } from 'react'; | |
5 | 6 | |
6 | -const waitTime = (time: number = 100) => { | |
7 | - return new Promise((resolve) => { | |
8 | - setTimeout(() => { | |
9 | - resolve(true); | |
10 | - }, time); | |
11 | - }); | |
12 | -}; | |
13 | - | |
14 | -export default ({ recordId }) => { | |
15 | - const [form] = Form.useForm(); | |
7 | +export default ({ recordId, getRecord, button }) => { | |
8 | + const [data, setData] = useState<any>({}); | |
16 | 9 | useEffect(() => { |
17 | - console.log('recordId', recordId); | |
10 | + const getData = async () => { | |
11 | + let ret = await postServiceInvoiceGetInvoiceRecord({ | |
12 | + query: { | |
13 | + id: recordId, | |
14 | + }, | |
15 | + }); | |
16 | + setData(ret.data); | |
17 | + }; | |
18 | + if (recordId) { | |
19 | + getData(); | |
20 | + } | |
18 | 21 | }, []); |
22 | + const [form] = Form.useForm(); | |
19 | 23 | return ( |
20 | 24 | <ModalForm |
21 | 25 | title="预览发票" |
22 | - trigger={<a type="primary">预览</a>} | |
26 | + trigger={button ? button : <a type="primary">预览</a>} | |
27 | + onOpenChange={(open) => { | |
28 | + if (open && getRecord) { | |
29 | + setData(getRecord()); | |
30 | + } | |
31 | + }} | |
23 | 32 | width={1200} |
24 | 33 | form={form} |
25 | 34 | autoFocusFirstInput |
26 | 35 | modalProps={{ |
27 | 36 | destroyOnClose: true, |
28 | - onCancel: () => console.log('run'), | |
29 | - }} | |
30 | - submitTimeout={2000} | |
31 | - onFinish={async (values) => { | |
32 | - await waitTime(2000); | |
33 | - console.log(values.name); | |
34 | - message.success('提交成功'); | |
35 | - return true; | |
36 | 37 | }} |
37 | 38 | > |
38 | 39 | <hr /> |
39 | - <Invoice recordId={recordId} /> | |
40 | + <Invoice data={data} /> | |
40 | 41 | </ModalForm> |
41 | 42 | ); |
42 | 43 | }; | ... | ... |
src/pages/Invoice/components/InvoiceRecordDetailModal.tsx
src/pages/Invoice/index.tsx
... | ... | @@ -24,6 +24,7 @@ import { |
24 | 24 | postServiceInvoiceQueryInvoiceRecordList, |
25 | 25 | postServiceOrderQuerySalesCode, |
26 | 26 | } from '@/services'; |
27 | +import { excelExport } from '@/services/exportRequest'; | |
27 | 28 | import { |
28 | 29 | enumToProTableEnumValue, |
29 | 30 | enumToSelect, |
... | ... | @@ -55,6 +56,7 @@ const InvoicePage = () => { |
55 | 56 | const [invoiceRecordDetailVisible, setInvoiceRecordDetailVisible] = |
56 | 57 | useState(false); |
57 | 58 | const [invoiceRecord, setInvoiceRecord] = useState({}); |
59 | + const [messageApi] = message.useMessage(); | |
58 | 60 | |
59 | 61 | useEffect(() => { |
60 | 62 | async function extracted() { |
... | ... | @@ -199,7 +201,13 @@ const InvoicePage = () => { |
199 | 201 | hideInSearch: true, |
200 | 202 | ellipsis: true, |
201 | 203 | }, |
202 | - | |
204 | + { | |
205 | + title: '申请备注', | |
206 | + valueType: 'text', | |
207 | + dataIndex: 'applyInvoicingNotes', | |
208 | + hideInSearch: true, | |
209 | + ellipsis: true, | |
210 | + }, | |
203 | 211 | { |
204 | 212 | title: '购方名称', |
205 | 213 | valueType: 'Text', |
... | ... | @@ -419,6 +427,13 @@ const InvoicePage = () => { |
419 | 427 | hideInSearch: true, |
420 | 428 | ellipsis: true, |
421 | 429 | }, |
430 | + { | |
431 | + title: '失败原因', | |
432 | + valueType: 'text', | |
433 | + dataIndex: 'failureReason', | |
434 | + hideInSearch: true, | |
435 | + ellipsis: true, | |
436 | + }, | |
422 | 437 | |
423 | 438 | { |
424 | 439 | title: '购方名称', |
... | ... | @@ -826,6 +841,8 @@ const InvoicePage = () => { |
826 | 841 | 'AUDITING_NOT_PASSED', |
827 | 842 | 'CANCELED', |
828 | 843 | ], |
844 | + needBuildDetails: false, | |
845 | + needBuildSubOrders: true, | |
829 | 846 | }, |
830 | 847 | }); |
831 | 848 | return { |
... | ... | @@ -880,6 +897,37 @@ const InvoicePage = () => { |
880 | 897 | defaultDom.cancel, |
881 | 898 | ], |
882 | 899 | }} |
900 | + search={{ | |
901 | + labelWidth: 'auto', | |
902 | + defaultCollapsed: false, | |
903 | + optionRender: (searchConfig, formProps, dom) => [ | |
904 | + ...dom, | |
905 | + <Button | |
906 | + key="out" | |
907 | + onClick={() => { | |
908 | + const values = searchConfig?.form?.getFieldsValue(); | |
909 | + console.log(values); | |
910 | + messageApi.open({ | |
911 | + type: 'loading', | |
912 | + content: '正在导出文件...', | |
913 | + duration: 0, | |
914 | + }); | |
915 | + excelExport( | |
916 | + '/api/service/invoice/exportInvoiceRecords', | |
917 | + { | |
918 | + ...values, | |
919 | + statusIn: ['INVOICING', 'SUCCESS', 'FAIL'], | |
920 | + }, | |
921 | + () => { | |
922 | + messageApi.destroy(); | |
923 | + }, | |
924 | + ); | |
925 | + }} | |
926 | + > | |
927 | + 导出 | |
928 | + </Button>, | |
929 | + ], | |
930 | + }} | |
883 | 931 | request={async (params) => { |
884 | 932 | let res = await postServiceInvoiceQueryInvoiceRecordList({ |
885 | 933 | data: { |
... | ... | @@ -903,9 +951,6 @@ const InvoicePage = () => { |
903 | 951 | }, |
904 | 952 | }} |
905 | 953 | rowKey="id" |
906 | - search={{ | |
907 | - labelWidth: 'auto', | |
908 | - }} | |
909 | 954 | options={{ |
910 | 955 | setting: { |
911 | 956 | listsHeight: 400, | ... | ... |
src/pages/Order/components/InvoicingDrawerForm.tsx
1 | 1 | // import { PlusOutlined } from '@ant-design/icons'; |
2 | +import InvoiceModal from '@/pages/Invoice/components/InvoiceModal'; | |
2 | 3 | import { |
4 | + postServiceConstGetPayeeEnum, | |
3 | 5 | postServiceConstInvoiceType, |
4 | 6 | postServiceConstInvoicingType, |
5 | 7 | postServiceConstListInvoiceDetailNames, |
... | ... | @@ -16,11 +18,9 @@ import { |
16 | 18 | ProFormSelect, |
17 | 19 | ProFormText, |
18 | 20 | ProFormTextArea, |
19 | - ProFormUploadDragger, | |
20 | 21 | } from '@ant-design/pro-components'; |
21 | -import { Form } from 'antd'; | |
22 | +import { Button, Form } from 'antd'; | |
22 | 23 | import { useEffect } from 'react'; |
23 | -import { PAYEE_OPTIONS } from '../constant'; | |
24 | 24 | |
25 | 25 | export default ({ dataList, mainOrder, setVisible, onClose }) => { |
26 | 26 | // let subOrderIds = dataList?.map((item) => { |
... | ... | @@ -44,6 +44,18 @@ export default ({ dataList, mainOrder, setVisible, onClose }) => { |
44 | 44 | drawerProps={{ |
45 | 45 | destroyOnClose: true, |
46 | 46 | }} |
47 | + submitter={{ | |
48 | + render: (props, defaultDoms) => { | |
49 | + return [ | |
50 | + <InvoiceModal | |
51 | + key={'invoicePreview'} | |
52 | + button={<Button type="primary"> 发票预览 </Button>} | |
53 | + getRecord={form.getFieldsValue} | |
54 | + />, | |
55 | + ...defaultDoms, | |
56 | + ]; | |
57 | + }, | |
58 | + }} | |
47 | 59 | submitTimeout={2000} |
48 | 60 | onFinish={async (values) => { |
49 | 61 | postServiceInvoiceApplyInvoice({ |
... | ... | @@ -142,12 +154,42 @@ export default ({ dataList, mainOrder, setVisible, onClose }) => { |
142 | 154 | }} |
143 | 155 | /> |
144 | 156 | <ProFormSelect |
145 | - name="partyBName" | |
157 | + name="partyB" | |
146 | 158 | label="开票收款单位" |
147 | - options={enumToSelect(PAYEE_OPTIONS)} | |
159 | + request={async () => { | |
160 | + const res = await postServiceConstGetPayeeEnum(); | |
161 | + let options = res?.data?.map((payee: any) => { | |
162 | + return { | |
163 | + ...payee, | |
164 | + label: payee.payeeName, | |
165 | + value: payee.name, | |
166 | + }; | |
167 | + }); | |
168 | + return options; | |
169 | + }} | |
170 | + onChange={(_, option) => { | |
171 | + if (option) { | |
172 | + form.setFieldsValue({ | |
173 | + partyBName: option.payeeName, | |
174 | + partyBTaxid: option.taxId, | |
175 | + }); | |
176 | + } | |
177 | + }} | |
148 | 178 | placeholder="请选择收款单位" |
149 | 179 | rules={[{ required: true, message: '请选择收款单位!' }]} |
150 | 180 | /> |
181 | + <ProFormText | |
182 | + name="partyBName" | |
183 | + label="开票收款单位名称" | |
184 | + hidden | |
185 | + rules={[{ required: true, message: '请选择收款单位!' }]} | |
186 | + /> | |
187 | + <ProFormText | |
188 | + name="partyBTaxid" | |
189 | + label="开票收款单位税号" | |
190 | + hidden | |
191 | + rules={[{ required: true, message: '请选择收款单位!' }]} | |
192 | + /> | |
151 | 193 | <ProFormSelect |
152 | 194 | name="isUrgent" |
153 | 195 | label="是否加急" |
... | ... | @@ -158,15 +200,6 @@ export default ({ dataList, mainOrder, setVisible, onClose }) => { |
158 | 200 | placeholder="请选择是否加急" |
159 | 201 | rules={[{ required: true, message: '请选择是否加急!' }]} |
160 | 202 | /> |
161 | - <ProFormUploadDragger | |
162 | - key="filePaths" | |
163 | - label="附件" | |
164 | - name="filePaths" | |
165 | - action="/api/service/order/fileProcess" | |
166 | - fieldProps={{ | |
167 | - headers: { Authorization: localStorage.getItem('token') }, | |
168 | - }} | |
169 | - /> | |
170 | 203 | <ProFormList |
171 | 204 | name="invoiceDetails" |
172 | 205 | label="开票明细" | ... | ... |
src/pages/Order/index.tsx
... | ... | @@ -213,7 +213,6 @@ const OrderPage = () => { |
213 | 213 | }; |
214 | 214 | |
215 | 215 | const refreshTable = () => { |
216 | - console.log('刷新表格'); | |
217 | 216 | mainTableRef.current?.reload(); |
218 | 217 | //刷新表格数据的时候,取消选中行 |
219 | 218 | setSelectedRows([]); |
... | ... | @@ -604,9 +603,6 @@ const OrderPage = () => { |
604 | 603 | mainOrderSelectedMap.clear(); |
605 | 604 | subOrderSelectedMap.clear(); |
606 | 605 | } |
607 | - | |
608 | - console.log(mainOrderSelectedMap); | |
609 | - console.log(subOrderSelectedMap); | |
610 | 606 | }; |
611 | 607 | |
612 | 608 | //表头渲染 |
... | ... | @@ -1289,7 +1285,6 @@ const OrderPage = () => { |
1289 | 1285 | setCurrentMainId(record.id); |
1290 | 1286 | setCurretnOptSubId(optRecord.mainOrderId); |
1291 | 1287 | setReissueVisible(true); |
1292 | - console.log(reissueVisible); | |
1293 | 1288 | }} |
1294 | 1289 | > |
1295 | 1290 | 重新开票 |
... | ... | @@ -1320,7 +1315,6 @@ const OrderPage = () => { |
1320 | 1315 | className="p-0" |
1321 | 1316 | type="link" |
1322 | 1317 | onClick={() => { |
1323 | - console.log('here'); | |
1324 | 1318 | setCurrentMainId(record.id); |
1325 | 1319 | setCurretnOptSubId(optRecord.id); |
1326 | 1320 | setCheckVisible(true); |
... | ... | @@ -1355,7 +1349,6 @@ const OrderPage = () => { |
1355 | 1349 | className="p-0" |
1356 | 1350 | type="link" |
1357 | 1351 | onClick={() => { |
1358 | - console.log('here'); | |
1359 | 1352 | setCurrentMainId(record.id); |
1360 | 1353 | setCurretnOptSubId(optRecord.id); |
1361 | 1354 | setCheckVisible(true); |
... | ... | @@ -2251,9 +2244,6 @@ const OrderPage = () => { |
2251 | 2244 | |
2252 | 2245 | setSelectedSubOrderKeys(newSelectedSubOrderKeys); |
2253 | 2246 | setSelectedRows(currentMainOrderSelectedSubOrderList); |
2254 | - | |
2255 | - console.log(mainOrderSelectedMap); | |
2256 | - console.log(subOrderSelectedMap); | |
2257 | 2247 | }, |
2258 | 2248 | selectedRowKeys: selectedSubOrderKeys, |
2259 | 2249 | // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom |
... | ... | @@ -2685,7 +2675,6 @@ const OrderPage = () => { |
2685 | 2675 | onClick={() => { |
2686 | 2676 | setCurrentMainId(record.id); |
2687 | 2677 | setReissueVisible(true); |
2688 | - console.log(reissueVisible); | |
2689 | 2678 | }} |
2690 | 2679 | > |
2691 | 2680 | 重新开票 |
... | ... | @@ -3396,7 +3385,6 @@ const OrderPage = () => { |
3396 | 3385 | selectedSubOrders = record.subOrderInformationLists; |
3397 | 3386 | } |
3398 | 3387 | |
3399 | - console.log(selectedSubOrders); | |
3400 | 3388 | for (let i = 0; i < selectedSubOrders.length; i++) { |
3401 | 3389 | if ( |
3402 | 3390 | selectedSubOrders[i].afterInvoicingStatus !== |
... | ... | @@ -4128,9 +4116,6 @@ const OrderPage = () => { |
4128 | 4116 | let flat = [...subOrderSelectedMap.values()].flat(); |
4129 | 4117 | //遍历flat,判断afterInvoicingStatusList存在于canApplyAfterInvoicingStatus |
4130 | 4118 | flat.forEach((item) => { |
4131 | - console.log(item); | |
4132 | - console.log(item.invoicingStatus === 'UN_INVOICE'); | |
4133 | - console.log(item.afterInvoicingStatus !== null); | |
4134 | 4119 | if ( |
4135 | 4120 | item.invoicingStatus === 'UN_INVOICE' || |
4136 | 4121 | (item.afterInvoicingStatus !== null && |
... | ... | @@ -4695,7 +4680,6 @@ const OrderPage = () => { |
4695 | 4680 | <ReissueModal |
4696 | 4681 | setVisible={(val: boolean) => { |
4697 | 4682 | setReissueVisible(val); |
4698 | - console.log(reissueVisible); | |
4699 | 4683 | if (!val) { |
4700 | 4684 | clearOptObject(); |
4701 | 4685 | } | ... | ... |
src/services/exportRequest.ts
0 → 100644
1 | +import axios from 'axios'; | |
2 | + | |
3 | +export const excelExport = async ( | |
4 | + url: any = '', | |
5 | + data: any = {}, | |
6 | + exportLoadingDestory: any, | |
7 | +) => { | |
8 | + axios({ | |
9 | + url: url, | |
10 | + method: 'post', | |
11 | + responseType: 'blob', | |
12 | + headers: { Authorization: localStorage.getItem('token') }, | |
13 | + data, | |
14 | + }) | |
15 | + .then((response) => { | |
16 | + // 我这里在拦截器里直接返回的response.data | |
17 | + const body = response.data; | |
18 | + let fileUrl = window.URL.createObjectURL( | |
19 | + new Blob([body], { | |
20 | + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | |
21 | + }), | |
22 | + ); | |
23 | + let a = document.createElement('a'); | |
24 | + a.style.display = 'none'; | |
25 | + a.href = fileUrl; | |
26 | + a.download = '开票记录.xlsx'; | |
27 | + document.body.appendChild(a); | |
28 | + a.click(); | |
29 | + window.URL.revokeObjectURL(a.href); | |
30 | + document.body.removeChild(a); | |
31 | + }) | |
32 | + .catch((error) => { | |
33 | + // 处理错误 | |
34 | + console.error('导出错误', error); | |
35 | + }) | |
36 | + .finally(() => { | |
37 | + exportLoadingDestory(); | |
38 | + }); | |
39 | +}; | ... | ... |