Commit 100628a37e1f9ec42aef37eb2a97b85dcc875a33

Authored by zhongnanhuang
1 parent 349f730f

feat: update 发票对账

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 }) =&gt; {
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 }) =&gt; {
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 }) =&gt; {
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 }) =&gt; {
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 }) =&gt; {
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,
... ...