Commit 100628a37e1f9ec42aef37eb2a97b85dcc875a33
1 parent
349f730f
feat: update 发票对账
Showing
5 changed files
with
112 additions
and
40 deletions
src/pages/Invoice/components/BankChooseModal.tsx
... | ... | @@ -5,7 +5,7 @@ import { |
5 | 5 | postServiceBankStatementQueryBankStatement, |
6 | 6 | postServiceInvoiceInvoiceWriteOff, |
7 | 7 | } from '@/services'; |
8 | -import { enumValueToLabel, formatDateTime } from '@/utils'; | |
8 | +import { FloatAdd, FloatSub, enumValueToLabel, formatDateTime } from '@/utils'; | |
9 | 9 | import { formatDate } from '@/utils/time'; |
10 | 10 | |
11 | 11 | import { ActionType, ProCard, ProTable } from '@ant-design/pro-components'; |
... | ... | @@ -18,6 +18,7 @@ export default ({ invoiceId, setVisible, onClose }) => { |
18 | 18 | const [selectedStatementIdSet, setSelectedStatementIdSet] = useState( |
19 | 19 | new Set(), |
20 | 20 | ); |
21 | + const [totalAmount, setTotalAmount] = useState(0); | |
21 | 22 | |
22 | 23 | // 添加元素到Set |
23 | 24 | const addElement = (element) => { |
... | ... | @@ -128,6 +129,8 @@ export default ({ invoiceId, setVisible, onClose }) => { |
128 | 129 | key="choose" |
129 | 130 | type="link" |
130 | 131 | onClick={() => { |
132 | + let amount = record.loanAmount || record.transactionAmount || 0; | |
133 | + | |
131 | 134 | //已经选中,取消选中 |
132 | 135 | if (selectedStatementIdSet.has(record.id)) { |
133 | 136 | setSelectedStatement( |
... | ... | @@ -136,12 +139,14 @@ export default ({ invoiceId, setVisible, onClose }) => { |
136 | 139 | }), |
137 | 140 | ); |
138 | 141 | removeElement(record.id); |
142 | + setTotalAmount(parseFloat(FloatSub(totalAmount, amount))); | |
139 | 143 | } else { |
140 | 144 | //添加到已选中区域中 |
141 | 145 | let newSelectedStatement = [...selectedStatement]; |
142 | 146 | newSelectedStatement.push(record); |
143 | 147 | setSelectedStatement(newSelectedStatement); |
144 | 148 | addElement(record.id); |
149 | + setTotalAmount(FloatAdd(totalAmount, amount)); | |
145 | 150 | } |
146 | 151 | }} |
147 | 152 | > |
... | ... | @@ -167,22 +172,36 @@ export default ({ invoiceId, setVisible, onClose }) => { |
167 | 172 | }; |
168 | 173 | |
169 | 174 | const showSelectedStatement = () => { |
170 | - console.log('show'); | |
171 | - console.log(selectedStatement); | |
172 | 175 | let i = 0; |
173 | 176 | |
174 | 177 | let tags = selectedStatement.map((item) => { |
178 | + console.log(item); | |
179 | + let tagText = item.id; | |
180 | + | |
181 | + if (item.payeePayerName) { | |
182 | + tagText += ' ' + item.payeePayerName + ' '; | |
183 | + } | |
184 | + | |
185 | + if (item.loanAmount) { | |
186 | + tagText += item.loanAmount + ' '; | |
187 | + } | |
188 | + | |
189 | + if (item.transactionAmount) { | |
190 | + tagText += item.transactionAmount; | |
191 | + } | |
192 | + | |
175 | 193 | return ( |
176 | 194 | <Tag |
177 | 195 | key={i++} |
178 | 196 | closable={true} |
179 | 197 | style={{ userSelect: 'none' }} |
198 | + color="blue" | |
180 | 199 | onClose={(e) => { |
181 | 200 | e.preventDefault(); //需要加上这句代码,不然删除tag时,当前tag的下一个tag会被设置ant-tag-hidden |
182 | 201 | removeSelectedStatement(item); |
183 | 202 | }} |
184 | 203 | > |
185 | - <span>{item.id}</span> | |
204 | + <span>{tagText}</span> | |
186 | 205 | </Tag> |
187 | 206 | ); |
188 | 207 | }); |
... | ... | @@ -226,11 +245,11 @@ export default ({ invoiceId, setVisible, onClose }) => { |
226 | 245 | }} |
227 | 246 | > |
228 | 247 | <Divider orientation="left" plain> |
229 | - 已选中 | |
248 | + 已选中(合计:¥{totalAmount}) | |
230 | 249 | </Divider> |
231 | 250 | <ProCard className="mb-[16px]" bordered style={{}}> |
232 | - <Flex> | |
233 | - <div>{showSelectedStatement()}</div> | |
251 | + <Flex wrap="wrap" gap="small"> | |
252 | + {showSelectedStatement()} | |
234 | 253 | </Flex> |
235 | 254 | </ProCard> |
236 | 255 | ... | ... |
src/pages/Invoice/components/BankImportModal.tsx
1 | 1 | import { RESPONSE_CODE } from '@/constants/enum'; |
2 | -import { postServiceBankStatementImportBankStatementForm } from '@/services'; | |
2 | + | |
3 | 3 | import { UploadOutlined } from '@ant-design/icons'; |
4 | 4 | import { ModalForm } from '@ant-design/pro-components'; |
5 | 5 | import { Button, Form, Upload, UploadFile, UploadProps, message } from 'antd'; |
... | ... | @@ -14,17 +14,17 @@ export default ({ setVisible, onClose }) => { |
14 | 14 | const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => |
15 | 15 | setFileList(newFileList); |
16 | 16 | |
17 | - const [messageApi] = message.useMessage(); | |
17 | + // const [messageApi] = message.useMessage(); | |
18 | 18 | const [uploadLoading, setUploading] = useState(false); |
19 | 19 | console.log(uploadLoading); |
20 | 20 | |
21 | - const exportLoading = (content: string) => { | |
22 | - messageApi.open({ | |
23 | - type: 'loading', | |
24 | - content: content, | |
25 | - duration: 0, | |
26 | - }); | |
27 | - }; | |
21 | + // const exportLoading = (content: string) => { | |
22 | + // messageApi.open({ | |
23 | + // type: 'loading', | |
24 | + // content: content, | |
25 | + // duration: 0, | |
26 | + // }); | |
27 | + // }; | |
28 | 28 | |
29 | 29 | const downloadImportTemplate = async () => { |
30 | 30 | axios({ |
... | ... | @@ -34,6 +34,7 @@ export default ({ setVisible, onClose }) => { |
34 | 34 | headers: { Authorization: localStorage.getItem('token') }, |
35 | 35 | }) |
36 | 36 | .then((response) => { |
37 | + console.log(response); | |
37 | 38 | // 创建一个新的 Blob 对象,它包含了服务器响应的数据(即你的 Excel 文件) |
38 | 39 | const blob = new Blob([response.data]); // Excel 的 MIME 类型 |
39 | 40 | const downloadUrl = window.URL.createObjectURL(blob); |
... | ... | @@ -53,32 +54,45 @@ export default ({ setVisible, onClose }) => { |
53 | 54 | const handleUpload = async () => { |
54 | 55 | const formData = new FormData(); |
55 | 56 | fileList.forEach((file) => { |
56 | - //originFileObj二进制文件 | |
57 | 57 | formData.append('file', file.originFileObj as RcFile); |
58 | 58 | }); |
59 | - // console.log(fileList[0] as RcFile) | |
60 | - // formData.append('file', fileList[0] as RcFile); | |
61 | 59 | setUploading(true); |
62 | - // You can use any AJAX library you like | |
63 | - const res = await postServiceBankStatementImportBankStatementForm({ | |
64 | - data: formData, | |
60 | + | |
61 | + axios({ | |
62 | + url: '/api/service/bankStatement/importBankStatementForm', | |
63 | + method: 'post', | |
64 | + responseType: 'blob', | |
65 | 65 | headers: { |
66 | + Authorization: localStorage.getItem('token'), | |
66 | 67 | 'Content-Type': |
67 | 68 | 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', |
68 | 69 | }, |
69 | - }); | |
70 | - | |
71 | - if (res.result === RESPONSE_CODE.SUCCESS) { | |
72 | - message.success(res.message); | |
73 | - onClose(); | |
74 | - } else { | |
75 | - if (res.message === '表格中没有数据') { | |
76 | - setUploading(false); | |
77 | - return; | |
78 | - } | |
79 | - //存在错误信息,下载错误信息模板 | |
80 | - exportLoading('正在下载错误信息...'); | |
81 | - } | |
70 | + data: formData, | |
71 | + }) | |
72 | + .then((response) => { | |
73 | + if (response.data?.result === RESPONSE_CODE.SUCCESS) { | |
74 | + message.success(response.data?.message); | |
75 | + } else { | |
76 | + if (response.data?.message) { | |
77 | + message.error(response.data?.message); | |
78 | + } else { | |
79 | + // 创建一个新的 Blob 对象,它包含了服务器响应的数据(即你的 Excel 文件) | |
80 | + const blob = new Blob([response.data]); // Excel 的 MIME 类型 | |
81 | + const downloadUrl = window.URL.createObjectURL(blob); | |
82 | + const a = document.createElement('a'); | |
83 | + a.href = downloadUrl; | |
84 | + a.download = '银行流水导入模板.xlsx'; // 你可以为文件命名 | |
85 | + document.body.appendChild(a); | |
86 | + a.click(); // 模拟点击操作来下载文件 | |
87 | + URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存 | |
88 | + document.body.removeChild(a); | |
89 | + } | |
90 | + } | |
91 | + }) | |
92 | + .catch((error) => { | |
93 | + // 处理错误 | |
94 | + message.error('系统出现异常了,请联系管理员', error); | |
95 | + }); | |
82 | 96 | |
83 | 97 | setUploading(false); |
84 | 98 | }; | ... | ... |
src/pages/Invoice/components/InvoiceVerificationModal.tsx
... | ... | @@ -36,7 +36,7 @@ export default ({ invoiceId, setVisible, onClose }) => { |
36 | 36 | data: { invoiceId: invoiceId }, |
37 | 37 | }); |
38 | 38 | if (res && res.data) { |
39 | - setInvoiceInfo(res.data.queryInvoiceResponseDto); | |
39 | + setInvoiceInfo(res.data); | |
40 | 40 | setRelationOrderIds(res.data.mainOrderIds); |
41 | 41 | setRelationBankStatements(res.data.bankStatementResponseDtos); |
42 | 42 | } | ... | ... |
src/pages/Invoice/constant.tsx
... | ... | @@ -131,11 +131,12 @@ export const INVOICE_COLUMNS = [ |
131 | 131 | export const BANK_STATEMENT_COLUMNS = [ |
132 | 132 | { |
133 | 133 | dataIndex: 'id', |
134 | - title: '主键ID', | |
134 | + title: '编号', | |
135 | 135 | valueType: 'text', |
136 | - width: 100, | |
137 | - hideInTable: true, | |
138 | - hideInSearch: true, | |
136 | + width: 160, | |
137 | + copyable: true, | |
138 | + // hideInTable: true, | |
139 | + // hideInSearch: true, | |
139 | 140 | editable: false, |
140 | 141 | }, |
141 | 142 | { | ... | ... |
src/utils/index.ts
... | ... | @@ -224,7 +224,45 @@ function splitByFirstTwoDashes(str: string) { |
224 | 224 | ]; |
225 | 225 | } |
226 | 226 | |
227 | +//浮点数加法运算 | |
228 | +function FloatAdd(arg1: any, arg2: any) { | |
229 | + let r1, r2, m; | |
230 | + try { | |
231 | + r1 = arg1.toString().split('.')[1].length; | |
232 | + } catch (e) { | |
233 | + r1 = 0; | |
234 | + } | |
235 | + try { | |
236 | + r2 = arg2.toString().split('.')[1].length; | |
237 | + } catch (e) { | |
238 | + r2 = 0; | |
239 | + } | |
240 | + m = Math.pow(10, Math.max(r1, r2)); | |
241 | + return (arg1 * m + arg2 * m) / m; | |
242 | +} | |
243 | + | |
244 | +//浮点数减法运算 | |
245 | +function FloatSub(arg1: any, arg2: any) { | |
246 | + let r1, r2, m, n; | |
247 | + try { | |
248 | + r1 = arg1.toString().split('.')[1].length; | |
249 | + } catch (e) { | |
250 | + r1 = 0; | |
251 | + } | |
252 | + try { | |
253 | + r2 = arg2.toString().split('.')[1].length; | |
254 | + } catch (e) { | |
255 | + r2 = 0; | |
256 | + } | |
257 | + m = Math.pow(10, Math.max(r1, r2)); | |
258 | + //动态控制精度长度 | |
259 | + n = (r1 = r2) ? r1 : r2; | |
260 | + return ((arg1 * m - arg2 * m) / m).toFixed(n); | |
261 | +} | |
262 | + | |
227 | 263 | export { |
264 | + FloatAdd, | |
265 | + FloatSub, | |
228 | 266 | appendFormData, |
229 | 267 | blobToFile, |
230 | 268 | copyToClipboard, | ... | ... |