Commit 1206ec5f5162227af06c4bc68d181e9475a90b74
Merge branch 'znh-invoice' into znh
# Conflicts: # src/services/definition.ts # src/utils/index.ts
Showing
13 changed files
with
1720 additions
and
158 deletions
.umirc.ts
@@ -45,13 +45,13 @@ export default defineConfig({ | @@ -45,13 +45,13 @@ export default defineConfig({ | ||
45 | icon: 'LineChartOutlined', | 45 | icon: 'LineChartOutlined', |
46 | access: 'canReadAdmin', | 46 | access: 'canReadAdmin', |
47 | }, | 47 | }, |
48 | - // { | ||
49 | - // name: '发票管理', | ||
50 | - // path: '/invoiceManage', | ||
51 | - // component: './Invoice', | ||
52 | - // icon: 'BookOutlined', | ||
53 | - // access: 'canReadAdmin', | ||
54 | - // }, | 48 | + { |
49 | + name: '发票管理', | ||
50 | + path: '/invoiceManage', | ||
51 | + component: './Invoice', | ||
52 | + icon: 'BookOutlined', | ||
53 | + access: 'canReadAdminAndFinance', | ||
54 | + }, | ||
55 | { | 55 | { |
56 | name: '打印', | 56 | name: '打印', |
57 | path: '/print', | 57 | path: '/print', |
src/access.ts
@@ -6,5 +6,7 @@ export default (initialState: API.UserInfo) => { | @@ -6,5 +6,7 @@ export default (initialState: API.UserInfo) => { | ||
6 | return { | 6 | return { |
7 | canReadAdmin: roleSmallVO?.code === 'admin', | 7 | canReadAdmin: roleSmallVO?.code === 'admin', |
8 | canReadProcure: roleSmallVO?.code === 'procure', | 8 | canReadProcure: roleSmallVO?.code === 'procure', |
9 | + canReadAdminAndFinance: | ||
10 | + roleSmallVO?.code === 'admin' || roleSmallVO?.code === 'finance', | ||
9 | }; | 11 | }; |
10 | }; | 12 | }; |
src/components/Div/EllipsisDiv.tsx
0 → 100644
src/pages/Invoice/components/BankChooseModal.tsx
0 → 100644
1 | +import EllipsisDiv from '@/components/Div/EllipsisDiv'; | ||
2 | +import { RESPONSE_CODE } from '@/constants/enum'; | ||
3 | +import { INVOCING_STATUS, PAYEE_OPTIONS } from '@/pages/Order/constant'; | ||
4 | +import { | ||
5 | + postServiceBankStatementQueryBankStatement, | ||
6 | + postServiceInvoiceInvoiceWriteOff, | ||
7 | +} from '@/services'; | ||
8 | +import { FloatAdd, FloatSub, enumValueToLabel, formatDateTime } from '@/utils'; | ||
9 | +import { formatDate } from '@/utils/time'; | ||
10 | + | ||
11 | +import { ActionType, ProCard, ProTable } from '@ant-design/pro-components'; | ||
12 | +import { Button, Divider, Flex, Modal, Tag, message } from 'antd'; | ||
13 | +import { useRef, useState } from 'react'; | ||
14 | +import { BANK_STATEMENT_COLUMNS, INVOICE_STATUS } from '../constant'; | ||
15 | +import '../index.less'; | ||
16 | +export default ({ invoiceId, setVisible, onClose }) => { | ||
17 | + const [selectedStatement, setSelectedStatement] = useState([]); | ||
18 | + const [selectedStatementIdSet, setSelectedStatementIdSet] = useState( | ||
19 | + new Set(), | ||
20 | + ); | ||
21 | + const [totalAmount, setTotalAmount] = useState(0); | ||
22 | + | ||
23 | + // 添加元素到Set | ||
24 | + const addElement = (element) => { | ||
25 | + setSelectedStatementIdSet((prevSet) => new Set([...prevSet, element])); | ||
26 | + }; | ||
27 | + | ||
28 | + // 从Set中删除元素 | ||
29 | + const removeElement = (element) => { | ||
30 | + setSelectedStatementIdSet((prevSet) => { | ||
31 | + const newSet = new Set(prevSet); | ||
32 | + newSet.delete(element); | ||
33 | + return newSet; | ||
34 | + }); | ||
35 | + }; | ||
36 | + | ||
37 | + const [btnLoading, setBtnLoading] = useState(false); | ||
38 | + | ||
39 | + const actionRef = useRef<ActionType>(); | ||
40 | + const getTableCellText = (target: any) => { | ||
41 | + if (!target) { | ||
42 | + return ''; | ||
43 | + } | ||
44 | + | ||
45 | + if (target.props) { | ||
46 | + return target.props.text; | ||
47 | + } | ||
48 | + | ||
49 | + return target; | ||
50 | + }; | ||
51 | + | ||
52 | + /** | ||
53 | + * 加载银行流水列表表格的各个列格式 | ||
54 | + */ | ||
55 | + const bankStatementColumnsInit = () => { | ||
56 | + let columns = BANK_STATEMENT_COLUMNS.map((item) => { | ||
57 | + let newItem = { ...item }; | ||
58 | + let dataIndex = item.dataIndex; | ||
59 | + let dataType = item.valueType; | ||
60 | + | ||
61 | + if (item.dataIndex === 'status') { | ||
62 | + newItem.hideInSearch = true; | ||
63 | + } | ||
64 | + | ||
65 | + newItem.render = (text, record) => { | ||
66 | + let textValue = record[dataIndex]; | ||
67 | + | ||
68 | + if (dataType === 'date') { | ||
69 | + textValue = formatDate(textValue); | ||
70 | + } | ||
71 | + | ||
72 | + if (dataType === 'dateTime') { | ||
73 | + textValue = formatDateTime(textValue); | ||
74 | + } | ||
75 | + | ||
76 | + if (dataType === 'money') { | ||
77 | + textValue = '¥' + textValue; | ||
78 | + } | ||
79 | + | ||
80 | + switch (dataIndex) { | ||
81 | + case 'invoiceStatus': | ||
82 | + return ( | ||
83 | + <EllipsisDiv | ||
84 | + text={enumValueToLabel( | ||
85 | + getTableCellText(textValue), | ||
86 | + INVOCING_STATUS, | ||
87 | + )} | ||
88 | + /> | ||
89 | + ); | ||
90 | + | ||
91 | + case 'status': { | ||
92 | + //这里状态不显示在筛选条件中,只能筛异常的流水 | ||
93 | + return ( | ||
94 | + <EllipsisDiv | ||
95 | + text={enumValueToLabel( | ||
96 | + getTableCellText(textValue), | ||
97 | + INVOICE_STATUS, | ||
98 | + )} | ||
99 | + /> | ||
100 | + ); | ||
101 | + } | ||
102 | + case 'payee': | ||
103 | + return ( | ||
104 | + <EllipsisDiv | ||
105 | + text={enumValueToLabel( | ||
106 | + getTableCellText(textValue), | ||
107 | + PAYEE_OPTIONS, | ||
108 | + )} | ||
109 | + /> | ||
110 | + ); | ||
111 | + | ||
112 | + default: | ||
113 | + return <EllipsisDiv text={getTableCellText(textValue)} />; | ||
114 | + } | ||
115 | + }; | ||
116 | + | ||
117 | + return newItem; | ||
118 | + }); | ||
119 | + | ||
120 | + columns.push({ | ||
121 | + title: '操作', | ||
122 | + valueType: 'option', | ||
123 | + key: 'option', | ||
124 | + fixed: 'right', | ||
125 | + width: 70, | ||
126 | + render: (text, record) => [ | ||
127 | + <Button | ||
128 | + className="p-0" | ||
129 | + key="choose" | ||
130 | + type="link" | ||
131 | + onClick={() => { | ||
132 | + let amount = record.loanAmount || record.transactionAmount || 0; | ||
133 | + | ||
134 | + //已经选中,取消选中 | ||
135 | + if (selectedStatementIdSet.has(record.id)) { | ||
136 | + setSelectedStatement( | ||
137 | + selectedStatement.filter((item) => { | ||
138 | + return item.id !== record.id; | ||
139 | + }), | ||
140 | + ); | ||
141 | + removeElement(record.id); | ||
142 | + setTotalAmount(parseFloat(FloatSub(totalAmount, amount))); | ||
143 | + } else { | ||
144 | + //添加到已选中区域中 | ||
145 | + let newSelectedStatement = [...selectedStatement]; | ||
146 | + newSelectedStatement.push(record); | ||
147 | + setSelectedStatement(newSelectedStatement); | ||
148 | + addElement(record.id); | ||
149 | + setTotalAmount(FloatAdd(totalAmount, amount)); | ||
150 | + } | ||
151 | + }} | ||
152 | + > | ||
153 | + {selectedStatementIdSet.has(record.id) ? '取消选中' : '选中'} | ||
154 | + </Button>, | ||
155 | + ], | ||
156 | + }); | ||
157 | + | ||
158 | + return columns; | ||
159 | + }; | ||
160 | + | ||
161 | + /** | ||
162 | + * 删除已选中 | ||
163 | + * @param record | ||
164 | + */ | ||
165 | + const removeSelectedStatement = (record: any) => { | ||
166 | + setSelectedStatement( | ||
167 | + selectedStatement.filter((item) => { | ||
168 | + return item.id !== record.id; | ||
169 | + }), | ||
170 | + ); | ||
171 | + removeElement(record.id); | ||
172 | + }; | ||
173 | + | ||
174 | + const showSelectedStatement = () => { | ||
175 | + let i = 0; | ||
176 | + | ||
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 | + | ||
193 | + return ( | ||
194 | + <Tag | ||
195 | + key={i++} | ||
196 | + closable={true} | ||
197 | + style={{ userSelect: 'none' }} | ||
198 | + color="blue" | ||
199 | + onClose={(e) => { | ||
200 | + e.preventDefault(); //需要加上这句代码,不然删除tag时,当前tag的下一个tag会被设置ant-tag-hidden | ||
201 | + removeSelectedStatement(item); | ||
202 | + }} | ||
203 | + > | ||
204 | + <span>{tagText}</span> | ||
205 | + </Tag> | ||
206 | + ); | ||
207 | + }); | ||
208 | + | ||
209 | + console.log(tags); | ||
210 | + | ||
211 | + return tags; | ||
212 | + }; | ||
213 | + | ||
214 | + return ( | ||
215 | + <> | ||
216 | + <Modal | ||
217 | + open | ||
218 | + width="80%" | ||
219 | + title="添加银行流水" | ||
220 | + className="bank-statement-choose" | ||
221 | + onOk={async () => { | ||
222 | + setBtnLoading(true); | ||
223 | + let bankStatementIds = selectedStatement?.map((item) => { | ||
224 | + return item.id; | ||
225 | + }); | ||
226 | + let res = await postServiceInvoiceInvoiceWriteOff({ | ||
227 | + data: { | ||
228 | + invoiceId: invoiceId, | ||
229 | + bankStatementIds: bankStatementIds, | ||
230 | + }, | ||
231 | + }); | ||
232 | + | ||
233 | + if (res.result === RESPONSE_CODE.SUCCESS) { | ||
234 | + if (res.data?.length > 0) { | ||
235 | + message.info(res.data); | ||
236 | + } else { | ||
237 | + message.success(res.message); | ||
238 | + } | ||
239 | + | ||
240 | + onClose(); | ||
241 | + } | ||
242 | + | ||
243 | + setBtnLoading(false); | ||
244 | + }} | ||
245 | + okButtonProps={{ | ||
246 | + loading: btnLoading, | ||
247 | + }} | ||
248 | + onCancel={() => { | ||
249 | + setVisible(false); | ||
250 | + }} | ||
251 | + > | ||
252 | + <Divider orientation="left" plain> | ||
253 | + 已选中(合计:¥{totalAmount}) | ||
254 | + </Divider> | ||
255 | + <ProCard className="mb-[16px]" bordered style={{}}> | ||
256 | + <Flex wrap="wrap" gap="small"> | ||
257 | + {showSelectedStatement()} | ||
258 | + </Flex> | ||
259 | + </ProCard> | ||
260 | + | ||
261 | + <ProTable | ||
262 | + columns={bankStatementColumnsInit()} | ||
263 | + actionRef={actionRef} | ||
264 | + cardBordered | ||
265 | + pagination={{ | ||
266 | + pageSize: 10, | ||
267 | + }} | ||
268 | + editable={{ | ||
269 | + type: 'multiple', | ||
270 | + onSave: async (rowKey, data) => { | ||
271 | + console.log(rowKey, data); | ||
272 | + }, | ||
273 | + actionRender: (row, config, defaultDom) => [ | ||
274 | + defaultDom.save, | ||
275 | + defaultDom.cancel, | ||
276 | + ], | ||
277 | + }} | ||
278 | + request={async (params) => { | ||
279 | + const res = await postServiceBankStatementQueryBankStatement({ | ||
280 | + data: { ...params, status: 'ABNORMAL' }, | ||
281 | + }); | ||
282 | + if (res) { | ||
283 | + return { | ||
284 | + data: res?.data?.data || [], | ||
285 | + total: res?.data?.total || 0, | ||
286 | + }; | ||
287 | + } | ||
288 | + }} | ||
289 | + columnsState={{ | ||
290 | + persistenceKey: 'pro-table-singe-demos', | ||
291 | + persistenceType: 'localStorage', | ||
292 | + defaultValue: { | ||
293 | + option: { fixed: 'right', disable: true }, | ||
294 | + }, | ||
295 | + onChange(value) { | ||
296 | + console.log('value: ', value); | ||
297 | + }, | ||
298 | + }} | ||
299 | + rowKey="id" | ||
300 | + search={{ | ||
301 | + labelWidth: 'auto', | ||
302 | + }} | ||
303 | + options={{ | ||
304 | + setting: { | ||
305 | + listsHeight: 400, | ||
306 | + }, | ||
307 | + }} | ||
308 | + form={{}} | ||
309 | + dateFormatter="string" | ||
310 | + headerTitle="银行流水列表" | ||
311 | + scroll={{ x: 1400, y: 360 }} | ||
312 | + toolBarRender={() => []} | ||
313 | + /> | ||
314 | + </Modal> | ||
315 | + </> | ||
316 | + ); | ||
317 | +}; |
src/pages/Invoice/components/BankImportModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | ||
2 | +import { blobToJson } from '@/utils'; | ||
3 | + | ||
4 | +import { UploadOutlined } from '@ant-design/icons'; | ||
5 | +import { ModalForm } from '@ant-design/pro-components'; | ||
6 | +import { Button, Form, Upload, UploadFile, UploadProps, message } from 'antd'; | ||
7 | +import { RcFile } from 'antd/es/upload'; | ||
8 | +import axios from 'axios'; | ||
9 | +import { useState } from 'react'; | ||
10 | + | ||
11 | +// import { cloneDeep } from 'lodash'; | ||
12 | +export default ({ setVisible, onClose }) => { | ||
13 | + const [form] = Form.useForm<{ name: string; company: string }>(); | ||
14 | + const [fileList, setFileList] = useState<UploadFile[]>([]); | ||
15 | + const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => | ||
16 | + setFileList(newFileList); | ||
17 | + | ||
18 | + const [messageApi, contextHolder] = message.useMessage(); | ||
19 | + const [uploadLoading, setUploading] = useState(false); | ||
20 | + console.log(uploadLoading); | ||
21 | + | ||
22 | + const exportLoading = (content: string) => { | ||
23 | + messageApi.open({ | ||
24 | + type: 'loading', | ||
25 | + content: content, | ||
26 | + duration: 0, | ||
27 | + }); | ||
28 | + }; | ||
29 | + | ||
30 | + const downloadImportTemplate = async () => { | ||
31 | + exportLoading('正在下载......'); | ||
32 | + axios({ | ||
33 | + url: '/api/service/bankStatement/exportTemplate', | ||
34 | + method: 'post', | ||
35 | + responseType: 'blob', | ||
36 | + headers: { Authorization: localStorage.getItem('token') }, | ||
37 | + }) | ||
38 | + .then((response) => { | ||
39 | + console.log(response); | ||
40 | + // 创建一个新的 Blob 对象,它包含了服务器响应的数据(即你的 Excel 文件) | ||
41 | + const blob = new Blob([response.data]); // Excel 的 MIME 类型 | ||
42 | + const downloadUrl = window.URL.createObjectURL(blob); | ||
43 | + const a = document.createElement('a'); | ||
44 | + a.href = downloadUrl; | ||
45 | + a.download = '银行流水导入模板.xlsx'; // 你可以为文件命名 | ||
46 | + document.body.appendChild(a); | ||
47 | + a.click(); // 模拟点击操作来下载文件 | ||
48 | + URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存 | ||
49 | + document.body.removeChild(a); | ||
50 | + }) | ||
51 | + .catch((error) => { | ||
52 | + // 处理错误 | ||
53 | + console.error('导出错误', error); | ||
54 | + }) | ||
55 | + .finally(() => { | ||
56 | + messageApi.destroy(); | ||
57 | + }); | ||
58 | + }; | ||
59 | + const handleUpload = async () => { | ||
60 | + exportLoading('正在导入......'); | ||
61 | + | ||
62 | + const formData = new FormData(); | ||
63 | + fileList.forEach((file) => { | ||
64 | + formData.append('file', file.originFileObj as RcFile); | ||
65 | + }); | ||
66 | + | ||
67 | + setUploading(true); | ||
68 | + | ||
69 | + axios({ | ||
70 | + url: '/api/service/bankStatement/importBankStatementForm', | ||
71 | + method: 'post', | ||
72 | + responseType: 'blob', | ||
73 | + headers: { | ||
74 | + Authorization: localStorage.getItem('token'), | ||
75 | + 'Content-Type': | ||
76 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | ||
77 | + }, | ||
78 | + data: formData, | ||
79 | + }) | ||
80 | + .then((response) => { | ||
81 | + let data = response.data; | ||
82 | + if (data.type === 'application/json') { | ||
83 | + blobToJson(data).then((dataJson) => { | ||
84 | + if (dataJson?.result === RESPONSE_CODE.SUCCESS) { | ||
85 | + message.success(dataJson?.message); | ||
86 | + } else { | ||
87 | + message.error(dataJson?.message); | ||
88 | + } | ||
89 | + }); | ||
90 | + } else { | ||
91 | + message.error('上传失败,已下载错误信息表格'); | ||
92 | + // 创建一个新的 Blob 对象,它包含了服务器响应的数据(即你的 Excel 文件) | ||
93 | + const blob = new Blob([response.data]); // Excel 的 MIME 类型 | ||
94 | + const downloadUrl = window.URL.createObjectURL(blob); | ||
95 | + const a = document.createElement('a'); | ||
96 | + a.href = downloadUrl; | ||
97 | + a.download = '银行流水导入模板.xlsx'; // 你可以为文件命名 | ||
98 | + document.body.appendChild(a); | ||
99 | + a.click(); // 模拟点击操作来下载文件 | ||
100 | + URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存 | ||
101 | + document.body.removeChild(a); | ||
102 | + onClose(); | ||
103 | + } | ||
104 | + }) | ||
105 | + .catch((error) => { | ||
106 | + // 处理错误 | ||
107 | + message.error('系统出现异常了,请联系管理员', error); | ||
108 | + }) | ||
109 | + .finally(() => { | ||
110 | + setUploading(false); | ||
111 | + messageApi.destroy(); | ||
112 | + }); | ||
113 | + }; | ||
114 | + const props: UploadProps = { | ||
115 | + onRemove: (file) => { | ||
116 | + const index = fileList.indexOf(file); | ||
117 | + const newFileList = fileList.slice(); | ||
118 | + newFileList.splice(index, 1); | ||
119 | + setFileList(newFileList); | ||
120 | + }, | ||
121 | + beforeUpload: (file) => { | ||
122 | + setFileList([...fileList, file]); | ||
123 | + | ||
124 | + return false; | ||
125 | + }, | ||
126 | + fileList, | ||
127 | + onChange: handleChange, | ||
128 | + accept: '.xlsx', | ||
129 | + }; | ||
130 | + | ||
131 | + return ( | ||
132 | + <> | ||
133 | + <ModalForm<{ | ||
134 | + name: string; | ||
135 | + company: string; | ||
136 | + }> | ||
137 | + width={500} | ||
138 | + open | ||
139 | + title="银行流水导入" | ||
140 | + form={form} | ||
141 | + autoFocusFirstInput | ||
142 | + modalProps={{ | ||
143 | + okText: '确定', | ||
144 | + cancelText: '取消', | ||
145 | + destroyOnClose: true, | ||
146 | + onCancel: () => { | ||
147 | + setVisible(false); | ||
148 | + }, | ||
149 | + }} | ||
150 | + onFinish={async () => { | ||
151 | + handleUpload(); | ||
152 | + onClose(); | ||
153 | + }} | ||
154 | + onOpenChange={setVisible} | ||
155 | + > | ||
156 | + <div className="py-4 font-semibold"> | ||
157 | + 导入银行流水 | ||
158 | + <Button type="link" onClick={downloadImportTemplate}> | ||
159 | + 下载导入模板 | ||
160 | + </Button> | ||
161 | + </div> | ||
162 | + <Upload {...props}> | ||
163 | + <Button icon={<UploadOutlined />} disabled={fileList.length > 0}> | ||
164 | + 点击选择文件 | ||
165 | + </Button> | ||
166 | + </Upload> | ||
167 | + </ModalForm> | ||
168 | + | ||
169 | + {contextHolder} | ||
170 | + </> | ||
171 | + ); | ||
172 | +}; |
src/pages/Invoice/components/InvoiceVerificationModal.tsx
0 → 100644
1 | +import ButtonConfirm from '@/components/ButtomConfirm'; | ||
2 | +import EllipsisDiv from '@/components/Div/EllipsisDiv'; | ||
3 | +import { RESPONSE_CODE } from '@/constants/enum'; | ||
4 | +import { INVOCING_STATUS, PAYEE_OPTIONS } from '@/pages/Order/constant'; | ||
5 | +import { | ||
6 | + postServiceInvoiceCancelInvoiceAndBankStatement, | ||
7 | + postServiceInvoiceQueryInvoiceDetail, | ||
8 | +} from '@/services'; | ||
9 | +import { enumValueToLabel, formatDateTime } from '@/utils'; | ||
10 | +import { formatDate } from '@/utils/time'; | ||
11 | +import { PlusOutlined } from '@ant-design/icons'; | ||
12 | +import { | ||
13 | + ActionType, | ||
14 | + ModalForm, | ||
15 | + ProCard, | ||
16 | + ProTable, | ||
17 | +} from '@ant-design/pro-components'; | ||
18 | +import { | ||
19 | + Button, | ||
20 | + Descriptions, | ||
21 | + DescriptionsProps, | ||
22 | + Divider, | ||
23 | + Flex, | ||
24 | + Form, | ||
25 | + message, | ||
26 | +} from 'antd'; | ||
27 | +import { useEffect, useRef, useState } from 'react'; | ||
28 | +import { BANK_STATEMENT_COLUMNS, INVOICE_STATUS } from '../constant'; | ||
29 | +import '../index.less'; | ||
30 | +import BankChooseModal from './BankChooseModal'; | ||
31 | + | ||
32 | +export default ({ invoiceId, setVisible, onClose }) => { | ||
33 | + const [form] = Form.useForm<{ id: string }>(); | ||
34 | + const [bankChooseModalVisible, setBankChooseModalVisible] = useState(false); | ||
35 | + const [invoiceInfo, setInvoiceInfo] = useState({}); | ||
36 | + const [relationOrderIds, setRelationOrderIds] = useState([]); | ||
37 | + const [relationBankStatements, setRelationBankStatements] = useState([]); | ||
38 | + const actionRef = useRef<ActionType>(); | ||
39 | + | ||
40 | + const loadInvoiceData = async () => { | ||
41 | + let res = await postServiceInvoiceQueryInvoiceDetail({ | ||
42 | + data: { invoiceId: invoiceId }, | ||
43 | + }); | ||
44 | + if (res && res.data) { | ||
45 | + setInvoiceInfo(res.data); | ||
46 | + setRelationOrderIds(res.data.mainOrderIds); | ||
47 | + setRelationBankStatements(res.data.bankStatementResponseDtos); | ||
48 | + } | ||
49 | + }; | ||
50 | + | ||
51 | + const showRelationOrders = () => { | ||
52 | + return relationOrderIds?.map((item) => { | ||
53 | + return ( | ||
54 | + <> | ||
55 | + <Button | ||
56 | + className="pl-1 pr-0" | ||
57 | + type="link" | ||
58 | + target="_blank" | ||
59 | + href={'/order?id=' + item} | ||
60 | + > | ||
61 | + {item} | ||
62 | + </Button> | ||
63 | + <Divider type="vertical" /> | ||
64 | + </> | ||
65 | + ); | ||
66 | + }); | ||
67 | + }; | ||
68 | + | ||
69 | + const items: DescriptionsProps['items'] = [ | ||
70 | + { | ||
71 | + key: '1', | ||
72 | + label: '发票号码', | ||
73 | + children: invoiceInfo?.invoiceNumber, | ||
74 | + span: 6, | ||
75 | + }, | ||
76 | + { | ||
77 | + key: '2', | ||
78 | + label: '发票类型', | ||
79 | + children: enumValueToLabel(invoiceInfo?.invoiceStatus, INVOCING_STATUS), | ||
80 | + span: 6, | ||
81 | + }, | ||
82 | + { | ||
83 | + key: '3', | ||
84 | + label: '状态', | ||
85 | + children: enumValueToLabel(invoiceInfo?.status, INVOICE_STATUS), | ||
86 | + span: 4, | ||
87 | + }, | ||
88 | + { | ||
89 | + key: '4', | ||
90 | + label: '购买方', | ||
91 | + children: invoiceInfo?.purchaser, | ||
92 | + span: 8, | ||
93 | + }, | ||
94 | + { | ||
95 | + key: '5', | ||
96 | + label: '收款单位', | ||
97 | + children: enumValueToLabel(invoiceInfo?.payee, PAYEE_OPTIONS), | ||
98 | + span: 12, | ||
99 | + }, | ||
100 | + { | ||
101 | + key: '6', | ||
102 | + label: '联系人', | ||
103 | + children: invoiceInfo?.contacts, | ||
104 | + span: 4, | ||
105 | + }, | ||
106 | + { | ||
107 | + key: '7', | ||
108 | + label: '销售', | ||
109 | + children: invoiceInfo?.sale, | ||
110 | + span: 8, | ||
111 | + }, | ||
112 | + | ||
113 | + { | ||
114 | + key: '9', | ||
115 | + label: '开票日期', | ||
116 | + children: formatDate(invoiceInfo?.invoicingTime), | ||
117 | + span: 12, | ||
118 | + }, | ||
119 | + { | ||
120 | + key: '10', | ||
121 | + label: '收款时间', | ||
122 | + children: formatDate(invoiceInfo?.collectionTime), | ||
123 | + span: 4, | ||
124 | + }, | ||
125 | + { | ||
126 | + key: '8', | ||
127 | + label: '金额', | ||
128 | + children: invoiceInfo?.money, | ||
129 | + span: 10, | ||
130 | + }, | ||
131 | + { | ||
132 | + key: '11', | ||
133 | + label: '备注', | ||
134 | + children: invoiceInfo?.notes, | ||
135 | + span: 24, | ||
136 | + }, | ||
137 | + ]; | ||
138 | + | ||
139 | + const getTableCellText = (target: any) => { | ||
140 | + if (!target) { | ||
141 | + return ''; | ||
142 | + } | ||
143 | + | ||
144 | + if (target.props) { | ||
145 | + return target.props.text; | ||
146 | + } | ||
147 | + | ||
148 | + return target; | ||
149 | + }; | ||
150 | + | ||
151 | + /** | ||
152 | + * 加载银行流水列表表格的各个列格式 | ||
153 | + */ | ||
154 | + const bankStatementColumnsInit = () => { | ||
155 | + let columns = BANK_STATEMENT_COLUMNS.map((item) => { | ||
156 | + let newItem = { ...item }; | ||
157 | + let dataIndex = item.dataIndex; | ||
158 | + let dataType = item.valueType; | ||
159 | + | ||
160 | + newItem.render = (text, record) => { | ||
161 | + let textValue = record[dataIndex]; | ||
162 | + | ||
163 | + if (dataType === 'date') { | ||
164 | + textValue = formatDate(textValue); | ||
165 | + } | ||
166 | + | ||
167 | + if (dataType === 'dateTime') { | ||
168 | + textValue = formatDateTime(textValue); | ||
169 | + } | ||
170 | + | ||
171 | + if (dataType === 'money') { | ||
172 | + textValue = '¥' + textValue; | ||
173 | + } | ||
174 | + | ||
175 | + switch (dataIndex) { | ||
176 | + case 'invoiceStatus': | ||
177 | + return ( | ||
178 | + <EllipsisDiv | ||
179 | + text={enumValueToLabel( | ||
180 | + getTableCellText(textValue), | ||
181 | + INVOCING_STATUS, | ||
182 | + )} | ||
183 | + /> | ||
184 | + ); | ||
185 | + | ||
186 | + case 'status': | ||
187 | + return ( | ||
188 | + <EllipsisDiv | ||
189 | + text={enumValueToLabel( | ||
190 | + getTableCellText(textValue), | ||
191 | + INVOICE_STATUS, | ||
192 | + )} | ||
193 | + /> | ||
194 | + ); | ||
195 | + | ||
196 | + case 'payee': | ||
197 | + return ( | ||
198 | + <EllipsisDiv | ||
199 | + text={enumValueToLabel( | ||
200 | + getTableCellText(textValue), | ||
201 | + PAYEE_OPTIONS, | ||
202 | + )} | ||
203 | + /> | ||
204 | + ); | ||
205 | + | ||
206 | + default: | ||
207 | + return <EllipsisDiv text={getTableCellText(textValue)} />; | ||
208 | + } | ||
209 | + }; | ||
210 | + | ||
211 | + return newItem; | ||
212 | + }); | ||
213 | + | ||
214 | + columns.push({ | ||
215 | + title: '操作', | ||
216 | + valueType: 'option', | ||
217 | + key: 'option', | ||
218 | + fixed: 'right', | ||
219 | + width: 70, | ||
220 | + render: (text, record) => { | ||
221 | + let optBtns = []; | ||
222 | + if (invoiceInfo?.status === 'VERIFIED') { | ||
223 | + return []; | ||
224 | + } | ||
225 | + | ||
226 | + optBtns.push( | ||
227 | + <ButtonConfirm | ||
228 | + key="delete" | ||
229 | + className="p-0" | ||
230 | + title={'确认删除此项吗?'} | ||
231 | + text="删除" | ||
232 | + onConfirm={async () => { | ||
233 | + let res = await postServiceInvoiceCancelInvoiceAndBankStatement({ | ||
234 | + data: { | ||
235 | + invoiceId: invoiceId, | ||
236 | + cancelId: [record.id], | ||
237 | + }, | ||
238 | + }); | ||
239 | + if (res.result === RESPONSE_CODE.SUCCESS) { | ||
240 | + message.success(res.message); | ||
241 | + loadInvoiceData(); | ||
242 | + } | ||
243 | + }} | ||
244 | + />, | ||
245 | + ); | ||
246 | + return optBtns; | ||
247 | + }, | ||
248 | + }); | ||
249 | + | ||
250 | + return columns; | ||
251 | + }; | ||
252 | + | ||
253 | + useEffect(() => { | ||
254 | + loadInvoiceData(); | ||
255 | + }, []); | ||
256 | + | ||
257 | + return ( | ||
258 | + <> | ||
259 | + <ModalForm<{ | ||
260 | + id: string; | ||
261 | + }> | ||
262 | + className="invoice-detail" | ||
263 | + open | ||
264 | + width="80%" | ||
265 | + title="发票详情" | ||
266 | + form={form} | ||
267 | + autoFocusFirstInput | ||
268 | + modalProps={{ | ||
269 | + okText: '确定', | ||
270 | + cancelText: '返回', | ||
271 | + destroyOnClose: true, | ||
272 | + onCancel: () => { | ||
273 | + setVisible(false); | ||
274 | + onClose(); | ||
275 | + }, | ||
276 | + }} | ||
277 | + submitter={{ | ||
278 | + render: (props, defaultDoms) => { | ||
279 | + return [defaultDoms[0]]; | ||
280 | + }, | ||
281 | + }} | ||
282 | + onFinish={async () => { | ||
283 | + onClose(); | ||
284 | + }} | ||
285 | + onOpenChange={setVisible} | ||
286 | + > | ||
287 | + <Divider orientation="left" plain> | ||
288 | + 发票信息 | ||
289 | + </Divider> | ||
290 | + | ||
291 | + <Descriptions | ||
292 | + bordered | ||
293 | + column={24} | ||
294 | + size="small" | ||
295 | + title="" | ||
296 | + items={items} | ||
297 | + /> | ||
298 | + | ||
299 | + <Divider orientation="left" plain> | ||
300 | + 订单号 | ||
301 | + </Divider> | ||
302 | + | ||
303 | + <ProCard bordered style={{}}> | ||
304 | + <Flex> | ||
305 | + <div>{showRelationOrders()}</div> | ||
306 | + </Flex> | ||
307 | + </ProCard> | ||
308 | + | ||
309 | + <Divider plain></Divider> | ||
310 | + | ||
311 | + <ProTable | ||
312 | + columns={bankStatementColumnsInit()} | ||
313 | + actionRef={actionRef} | ||
314 | + cardBordered | ||
315 | + pagination={{ | ||
316 | + pageSize: 10, | ||
317 | + }} | ||
318 | + dataSource={relationBankStatements} | ||
319 | + columnsState={{ | ||
320 | + persistenceKey: 'pro-table-singe-demos', | ||
321 | + persistenceType: 'localStorage', | ||
322 | + defaultValue: { | ||
323 | + option: { fixed: 'right', disable: true }, | ||
324 | + }, | ||
325 | + onChange(value) { | ||
326 | + console.log('value: ', value); | ||
327 | + }, | ||
328 | + }} | ||
329 | + rowKey="id" | ||
330 | + search={false} | ||
331 | + options={{ | ||
332 | + setting: { | ||
333 | + listsHeight: 400, | ||
334 | + }, | ||
335 | + reload: false, | ||
336 | + }} | ||
337 | + form={{ | ||
338 | + // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下 | ||
339 | + syncToUrl: (values, type) => { | ||
340 | + if (type === 'get') { | ||
341 | + return { | ||
342 | + ...values, | ||
343 | + created_at: [values.startTime, values.endTime], | ||
344 | + }; | ||
345 | + } | ||
346 | + return values; | ||
347 | + }, | ||
348 | + }} | ||
349 | + dateFormatter="string" | ||
350 | + headerTitle="银行流水" | ||
351 | + scroll={{ x: 1400, y: 360 }} | ||
352 | + toolBarRender={() => [ | ||
353 | + <Button | ||
354 | + key="button" | ||
355 | + icon={<PlusOutlined />} | ||
356 | + onClick={() => { | ||
357 | + setBankChooseModalVisible(true); | ||
358 | + }} | ||
359 | + hidden={invoiceInfo?.status === 'VERIFIED'} | ||
360 | + type="primary" | ||
361 | + > | ||
362 | + 添加 | ||
363 | + </Button>, | ||
364 | + ]} | ||
365 | + /> | ||
366 | + </ModalForm> | ||
367 | + | ||
368 | + {bankChooseModalVisible ? ( | ||
369 | + <BankChooseModal | ||
370 | + setVisible={setBankChooseModalVisible} | ||
371 | + invoiceId={invoiceId} | ||
372 | + onClose={() => { | ||
373 | + setBankChooseModalVisible(false); | ||
374 | + loadInvoiceData(); | ||
375 | + actionRef.current?.reload(); | ||
376 | + }} | ||
377 | + ></BankChooseModal> | ||
378 | + ) : ( | ||
379 | + '' | ||
380 | + )} | ||
381 | + </> | ||
382 | + ); | ||
383 | +}; |
src/pages/Invoice/constant.tsx
1 | -import { TableDropdown } from '@ant-design/pro-components'; | 1 | +import { enumToProTableEnumValue } from '@/utils'; |
2 | +import { PAYEE_OPTIONS } from '../Order/constant'; | ||
2 | 3 | ||
3 | export type InvoiceItem = { | 4 | export type InvoiceItem = { |
4 | id: number; //id | 5 | id: number; //id |
@@ -15,92 +16,341 @@ export type InvoiceItem = { | @@ -15,92 +16,341 @@ export type InvoiceItem = { | ||
15 | notes: string; //备注 | 16 | notes: string; //备注 |
16 | }; | 17 | }; |
17 | 18 | ||
19 | +export const INVOICE_STATUS = { | ||
20 | + UNVERIFIED: '未核销', | ||
21 | + VERIFIED: '已核销', | ||
22 | + ABNORMAL: '异常', | ||
23 | + PARTIAL_VERIFICATION: '部分核销', | ||
24 | +}; | ||
25 | + | ||
18 | export const INVOICE_COLUMNS = [ | 26 | export const INVOICE_COLUMNS = [ |
19 | { | 27 | { |
28 | + dataIndex: 'invoiceId', | ||
29 | + title: 'id', | ||
30 | + valueType: 'text', | ||
31 | + hideInTable: true, | ||
32 | + hideInSearch: true, | ||
33 | + width: 100, | ||
34 | + }, | ||
35 | + { | ||
20 | dataIndex: 'invoiceNumber', | 36 | dataIndex: 'invoiceNumber', |
21 | title: '发票号码', | 37 | title: '发票号码', |
22 | valueType: 'text', | 38 | valueType: 'text', |
39 | + width: 100, | ||
23 | }, | 40 | }, |
24 | { | 41 | { |
25 | dataIndex: 'invoiceStatus', | 42 | dataIndex: 'invoiceStatus', |
26 | title: '发票类型', | 43 | title: '发票类型', |
27 | valueType: 'select', | 44 | valueType: 'select', |
45 | + width: 100, | ||
46 | + valueEnum: enumToProTableEnumValue({ | ||
47 | + SPECIALLY_INVOICED: '专票', | ||
48 | + COMMON_INVOICED: '普票', | ||
49 | + }), | ||
28 | }, | 50 | }, |
29 | { | 51 | { |
30 | title: '状态', | 52 | title: '状态', |
31 | dataIndex: 'status', | 53 | dataIndex: 'status', |
32 | valueType: 'text', | 54 | valueType: 'text', |
55 | + width: 100, | ||
56 | + valueEnum: enumToProTableEnumValue({ | ||
57 | + UNVERIFIED: '未核销', | ||
58 | + VERIFIED: '已核销', | ||
59 | + PARTIAL_VERIFICATION: '部分核销', | ||
60 | + }), | ||
33 | }, | 61 | }, |
34 | { | 62 | { |
35 | title: '购买方', | 63 | title: '购买方', |
36 | dataIndex: 'purchaser', | 64 | dataIndex: 'purchaser', |
37 | valueType: 'text', | 65 | valueType: 'text', |
66 | + width: 180, | ||
38 | }, | 67 | }, |
39 | { | 68 | { |
40 | title: '收款单位', | 69 | title: '收款单位', |
41 | dataIndex: 'payee', | 70 | dataIndex: 'payee', |
42 | valueType: 'text', | 71 | valueType: 'text', |
72 | + width: 180, | ||
73 | + valueEnum: enumToProTableEnumValue(PAYEE_OPTIONS), | ||
43 | }, | 74 | }, |
44 | { | 75 | { |
45 | title: '联系人', | 76 | title: '联系人', |
46 | dataIndex: 'contacts', | 77 | dataIndex: 'contacts', |
47 | valueType: 'text', | 78 | valueType: 'text', |
79 | + width: 100, | ||
48 | }, | 80 | }, |
49 | { | 81 | { |
50 | title: '销售', | 82 | title: '销售', |
51 | dataIndex: 'sale', | 83 | dataIndex: 'sale', |
52 | valueType: 'text', | 84 | valueType: 'text', |
85 | + width: 100, | ||
53 | }, | 86 | }, |
54 | { | 87 | { |
55 | title: '金额', | 88 | title: '金额', |
56 | dataIndex: 'money', | 89 | dataIndex: 'money', |
57 | valueType: 'money', | 90 | valueType: 'money', |
91 | + width: 100, | ||
58 | }, | 92 | }, |
59 | { | 93 | { |
60 | title: '开票日期', | 94 | title: '开票日期', |
61 | dataIndex: 'invoicingTime', | 95 | dataIndex: 'invoicingTime', |
62 | - valueType: 'date', | 96 | + valueType: 'dateRange', |
97 | + width: 150, | ||
98 | + search: { | ||
99 | + transform: (value) => { | ||
100 | + if (value) { | ||
101 | + return { | ||
102 | + invoicingBeginTime: value[0], | ||
103 | + invoicingEndTime: value[1], | ||
104 | + }; | ||
105 | + } | ||
106 | + }, | ||
107 | + }, | ||
63 | }, | 108 | }, |
64 | { | 109 | { |
65 | title: '收款时间', | 110 | title: '收款时间', |
66 | dataIndex: 'collectionTime', | 111 | dataIndex: 'collectionTime', |
67 | - valueType: 'dateTime', | 112 | + valueType: 'dateRange', |
113 | + width: 200, | ||
114 | + search: { | ||
115 | + transform: (value) => { | ||
116 | + if (value) { | ||
117 | + return { | ||
118 | + collectionBeginTime: value[0], | ||
119 | + collectionEndTime: value[1], | ||
120 | + }; | ||
121 | + } | ||
122 | + }, | ||
123 | + }, | ||
68 | }, | 124 | }, |
69 | { | 125 | { |
70 | title: '备注', | 126 | title: '备注', |
71 | dataIndex: 'notes', | 127 | dataIndex: 'notes', |
72 | valueType: 'text', | 128 | valueType: 'text', |
129 | + width: 250, | ||
130 | + }, | ||
131 | +]; | ||
132 | + | ||
133 | +export const BANK_STATEMENT_COLUMNS = [ | ||
134 | + { | ||
135 | + dataIndex: 'id', | ||
136 | + title: '编号', | ||
137 | + valueType: 'text', | ||
138 | + width: 160, | ||
139 | + copyable: true, | ||
140 | + // hideInTable: true, | ||
141 | + // hideInSearch: true, | ||
142 | + editable: false, | ||
143 | + }, | ||
144 | + { | ||
145 | + dataIndex: 'status', | ||
146 | + title: '状态', | ||
147 | + valueType: 'select', | ||
148 | + width: 100, | ||
149 | + editable: false, | ||
150 | + valueEnum: enumToProTableEnumValue({ | ||
151 | + ABNORMAL: '异常', | ||
152 | + VERIFIED: '已核销', | ||
153 | + }), | ||
154 | + }, | ||
155 | + { | ||
156 | + dataIndex: 'serialNumber', | ||
157 | + title: '流水号', | ||
158 | + valueType: 'text', | ||
159 | + width: 100, | ||
73 | }, | 160 | }, |
74 | { | 161 | { |
75 | - title: '操作', | ||
76 | - valueType: 'option', | ||
77 | - key: 'option', | ||
78 | - fixed: 'right', | ||
79 | - render: (text, record, _, action) => [ | ||
80 | - <a | ||
81 | - key="editable" | ||
82 | - onClick={() => { | ||
83 | - action?.startEditable?.(record.id); | ||
84 | - }} | ||
85 | - > | ||
86 | - 编辑 | ||
87 | - </a>, | ||
88 | - <a href={record.url} target="_blank" rel="noopener noreferrer" key="view"> | ||
89 | - 查看 | ||
90 | - </a>, | ||
91 | - <TableDropdown | ||
92 | - key="actionGroup" | ||
93 | - onSelect={() => action?.reload()} | ||
94 | - menus={[ | ||
95 | - { key: 'copy', name: '复制' }, | ||
96 | - { key: 'delete', name: '删除' }, | ||
97 | - ]} | ||
98 | - />, | ||
99 | - ], | 162 | + dataIndex: 'merchantOrderNumber', |
163 | + title: '商户订单号', | ||
164 | + valueType: 'text', | ||
165 | + width: 100, | ||
166 | + }, | ||
167 | + { | ||
168 | + dataIndex: 'bankOrderNumber', | ||
169 | + title: '银行订单号', | ||
170 | + valueType: 'text', | ||
171 | + width: 100, | ||
172 | + }, | ||
173 | + { | ||
174 | + dataIndex: 'thirdPartyOrderNumber', | ||
175 | + title: '第三方订单号', | ||
176 | + valueType: 'text', | ||
177 | + width: 100, | ||
178 | + }, | ||
179 | + { | ||
180 | + dataIndex: 'accountNumber', | ||
181 | + title: '账号', | ||
182 | + valueType: 'text', | ||
183 | + width: 180, | ||
184 | + }, | ||
185 | + { | ||
186 | + dataIndex: 'accountName', | ||
187 | + title: '帐号名称', | ||
188 | + valueType: 'text', | ||
189 | + width: 260, | ||
190 | + }, | ||
191 | + { | ||
192 | + dataIndex: 'currency', | ||
193 | + title: '币种', | ||
194 | + valueType: 'text', | ||
195 | + width: 100, | ||
196 | + }, | ||
197 | + { | ||
198 | + dataIndex: 'transactionDate', | ||
199 | + title: '交易日', | ||
200 | + valueType: 'dateRange', | ||
201 | + width: 100, | ||
202 | + search: { | ||
203 | + transform: (value) => { | ||
204 | + if (value) { | ||
205 | + return { | ||
206 | + beginTransactionDate: value[0], | ||
207 | + endTransactionDate: value[1], | ||
208 | + }; | ||
209 | + } | ||
210 | + }, | ||
211 | + }, | ||
212 | + }, | ||
213 | + { | ||
214 | + dataIndex: 'transactionTime', | ||
215 | + title: '交易时间', | ||
216 | + valueType: 'text', | ||
217 | + hideInSearch: true, | ||
218 | + width: 100, | ||
219 | + }, | ||
220 | + { | ||
221 | + dataIndex: 'transactionType', | ||
222 | + title: '交易类型', | ||
223 | + valueType: 'text', | ||
224 | + width: 100, | ||
225 | + }, | ||
226 | + { | ||
227 | + dataIndex: 'transactionBankBranch', | ||
228 | + title: '交易行所', | ||
229 | + valueType: 'text', | ||
230 | + width: 100, | ||
231 | + }, | ||
232 | + { | ||
233 | + dataIndex: 'valueDate', | ||
234 | + title: '起息日', | ||
235 | + valueType: 'dateRange', | ||
236 | + width: 100, | ||
237 | + search: { | ||
238 | + transform: (value) => { | ||
239 | + if (value) { | ||
240 | + return { | ||
241 | + beginValueDate: value[0], | ||
242 | + endValueDate: value[1], | ||
243 | + }; | ||
244 | + } | ||
245 | + }, | ||
246 | + }, | ||
247 | + }, | ||
248 | + { | ||
249 | + dataIndex: 'loanAmount', | ||
250 | + title: '贷方金额', | ||
251 | + valueType: 'money', | ||
252 | + width: 100, | ||
253 | + }, | ||
254 | + { | ||
255 | + dataIndex: 'borrowedAmount', | ||
256 | + title: '借方金额', | ||
257 | + valueType: 'money', | ||
258 | + width: 100, | ||
259 | + }, | ||
260 | + { | ||
261 | + dataIndex: 'transactionAmount', | ||
262 | + title: '交易金额', | ||
263 | + valueType: 'money', | ||
264 | + width: 100, | ||
265 | + }, | ||
266 | + { | ||
267 | + dataIndex: 'balance', | ||
268 | + title: '余额', | ||
269 | + valueType: 'money', | ||
270 | + width: 100, | ||
271 | + }, | ||
272 | + { | ||
273 | + dataIndex: 'actualPaymentAmount', | ||
274 | + title: '实付金额', | ||
275 | + valueType: 'money', | ||
276 | + width: 100, | ||
277 | + }, | ||
278 | + { | ||
279 | + dataIndex: 'collectionChannel', | ||
280 | + title: '收款渠道', | ||
281 | + valueType: 'text', | ||
282 | + width: 100, | ||
283 | + }, | ||
284 | + { | ||
285 | + dataIndex: 'paymentType', | ||
286 | + title: '支付类型', | ||
287 | + valueType: 'text', | ||
288 | + width: 100, | ||
289 | + }, | ||
290 | + { | ||
291 | + dataIndex: 'summary', | ||
292 | + title: '摘要', | ||
293 | + valueType: 'text', | ||
294 | + width: 300, | ||
295 | + }, | ||
296 | + { | ||
297 | + dataIndex: 'cashier', | ||
298 | + title: '收银员', | ||
299 | + valueType: 'text', | ||
300 | + width: 100, | ||
301 | + }, | ||
302 | + { | ||
303 | + dataIndex: 'payeePayerUnit', | ||
304 | + title: '收(付)方单位', | ||
305 | + valueType: 'text', | ||
306 | + width: 260, | ||
307 | + }, | ||
308 | + { | ||
309 | + dataIndex: 'payeePayerName', | ||
310 | + title: '收(付)方名称', | ||
311 | + valueType: 'text', | ||
312 | + width: 260, | ||
313 | + }, | ||
314 | + { | ||
315 | + dataIndex: 'payeePayerAccountNumber', | ||
316 | + title: '收(付)方账号', | ||
317 | + valueType: 'text', | ||
318 | + width: 260, | ||
319 | + }, | ||
320 | + { | ||
321 | + dataIndex: 'payeePayerBankBranchCode', | ||
322 | + title: '收(付)方开户行行号', | ||
323 | + valueType: 'text', | ||
324 | + width: 260, | ||
325 | + }, | ||
326 | + { | ||
327 | + dataIndex: 'payeePayerBankName', | ||
328 | + title: '收(付)方开户行名', | ||
329 | + valueType: 'text', | ||
330 | + width: 260, | ||
331 | + }, | ||
332 | + { | ||
333 | + dataIndex: 'payeePayerBankAddress', | ||
334 | + title: '收(付)方开户行地址', | ||
335 | + valueType: 'text', | ||
336 | + width: 260, | ||
337 | + }, | ||
338 | + { | ||
339 | + dataIndex: 'extendedSummary', | ||
340 | + title: '扩展摘要', | ||
341 | + valueType: 'text', | ||
342 | + width: 100, | ||
343 | + }, | ||
344 | + { | ||
345 | + dataIndex: 'transactionAnalysisCode', | ||
346 | + title: '交易分析码', | ||
347 | + valueType: 'text', | ||
348 | + width: 100, | ||
349 | + }, | ||
350 | + { | ||
351 | + dataIndex: 'remarkNote', | ||
352 | + title: '附言', | ||
353 | + valueType: 'text', | ||
354 | + width: 100, | ||
100 | }, | 355 | }, |
101 | ]; | 356 | ]; |
102 | - | ||
103 | -export const INVOICE_STATUS = { | ||
104 | - UNVERIFIED: '未核销', | ||
105 | - VERIFIED: '已核销', | ||
106 | -}; |
src/pages/Invoice/index.less
@@ -4,3 +4,17 @@ | @@ -4,3 +4,17 @@ | ||
4 | 'WenQuanYi Micro Hei', sans-serif; | 4 | 'WenQuanYi Micro Hei', sans-serif; |
5 | font-size: 14px; | 5 | font-size: 14px; |
6 | } | 6 | } |
7 | + | ||
8 | +.invoice-detail td { | ||
9 | + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial, | ||
10 | + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC', | ||
11 | + 'WenQuanYi Micro Hei', sans-serif; | ||
12 | + font-size: 14px; | ||
13 | +} | ||
14 | + | ||
15 | +.bank-statement-choose td { | ||
16 | + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial, | ||
17 | + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC', | ||
18 | + 'WenQuanYi Micro Hei', sans-serif; | ||
19 | + font-size: 14px; | ||
20 | +} |
src/pages/Invoice/index.tsx
1 | -import { INVOICE_COLUMNS, INVOICE_STATUS } from '@/pages/Invoice/constant'; | ||
2 | -import { postServiceInvoiceQueryInvoice } from '@/services'; | ||
3 | -import { enumValueToLabel } from '@/utils'; | 1 | +import ButtonConfirm from '@/components/ButtomConfirm'; |
2 | +import EllipsisDiv from '@/components/Div/EllipsisDiv'; | ||
3 | +import { RESPONSE_CODE } from '@/constants/enum'; | ||
4 | +import { | ||
5 | + BANK_STATEMENT_COLUMNS, | ||
6 | + INVOICE_COLUMNS, | ||
7 | + INVOICE_STATUS, | ||
8 | +} from '@/pages/Invoice/constant'; | ||
9 | +import { | ||
10 | + postServiceBankStatementDeleteBankStatement, | ||
11 | + postServiceBankStatementEditBankStatement, | ||
12 | + postServiceBankStatementQueryBankStatement, | ||
13 | + postServiceInvoiceDeleteInvoice, | ||
14 | + postServiceInvoiceQueryInvoice, | ||
15 | +} from '@/services'; | ||
16 | +import { enumValueToLabel, formatDateTime } from '@/utils'; | ||
17 | +import { formatDate } from '@/utils/time'; | ||
4 | import { getUserInfo } from '@/utils/user'; | 18 | import { getUserInfo } from '@/utils/user'; |
5 | -import { EllipsisOutlined } from '@ant-design/icons'; | 19 | +import { EllipsisOutlined, PlusOutlined } from '@ant-design/icons'; |
6 | import { | 20 | import { |
7 | ActionType, | 21 | ActionType, |
8 | PageContainer, | 22 | PageContainer, |
9 | ProTable, | 23 | ProTable, |
10 | } from '@ant-design/pro-components'; | 24 | } from '@ant-design/pro-components'; |
11 | import { history } from '@umijs/max'; | 25 | import { history } from '@umijs/max'; |
12 | -import { Avatar, Button, Dropdown, Tag } from 'antd'; | ||
13 | -import { useRef } from 'react'; | 26 | +import { Avatar, Button, Dropdown, Tabs, Tag, message } from 'antd'; |
27 | +import { useRef, useState } from 'react'; | ||
14 | import { INVOCING_STATUS, PAYEE_OPTIONS } from '../Order/constant'; | 28 | import { INVOCING_STATUS, PAYEE_OPTIONS } from '../Order/constant'; |
29 | +import BankImportModal from './components/BankImportModal'; | ||
30 | +import InvoiceVerificationModal from './components/InvoiceVerificationModal'; | ||
15 | import './index.less'; | 31 | import './index.less'; |
16 | - | ||
17 | -const userInfo = getUserInfo(); | ||
18 | const InvoicePage = () => { | 32 | const InvoicePage = () => { |
19 | - const actionRef = useRef<ActionType>(); | ||
20 | - // const [pageSize, setPageSize] = useState(10); | ||
21 | - // const [currentPage, setCurrentPage] = useState(1); | ||
22 | - return ( | ||
23 | - <> | ||
24 | - <PageContainer | ||
25 | - className="invoice-index" | ||
26 | - header={{ | ||
27 | - title: '发票管理', | ||
28 | - extra: [ | ||
29 | - <Avatar key="0" style={{ verticalAlign: 'middle' }} size="large"> | ||
30 | - {userInfo?.username} | ||
31 | - </Avatar>, | ||
32 | - <Tag key="nickName">{userInfo?.nickName}</Tag>, | ||
33 | - <Dropdown | ||
34 | - key="dropdown" | ||
35 | - trigger={['click']} | ||
36 | - menu={{ | ||
37 | - items: [ | ||
38 | - { | ||
39 | - label: '退出登录', | ||
40 | - key: '1', | ||
41 | - onClick: () => { | ||
42 | - localStorage.removeItem('token'); | ||
43 | - history.push('/login'); | ||
44 | - }, | ||
45 | - }, | ||
46 | - // { | ||
47 | - // label: '修改密码', | ||
48 | - // key: '2', | ||
49 | - // }, | ||
50 | - ], | 33 | + const invoiceActionRef = useRef<ActionType>(); |
34 | + const bankActionRef = useRef<ActionType>(); | ||
35 | + const [bankImportModalVisible, setBankImportModalVisible] = useState(false); | ||
36 | + const [invoiceVerificationVisible, setInvoiceVerificationVisible] = | ||
37 | + useState(false); | ||
38 | + const [invoiceId, setInvoiceId] = useState(undefined); | ||
39 | + | ||
40 | + const userInfo = getUserInfo(); | ||
41 | + | ||
42 | + const reloadInvoiceTable = () => { | ||
43 | + invoiceActionRef.current?.reload(); | ||
44 | + }; | ||
45 | + | ||
46 | + const reloadBankStatementTable = () => { | ||
47 | + bankActionRef.current?.reload(); | ||
48 | + }; | ||
49 | + | ||
50 | + const getTableCellText = (target: any) => { | ||
51 | + if (!target) { | ||
52 | + return ''; | ||
53 | + } | ||
54 | + | ||
55 | + if (target.props) { | ||
56 | + return target.props.text; | ||
57 | + } | ||
58 | + | ||
59 | + return target; | ||
60 | + }; | ||
61 | + | ||
62 | + /** | ||
63 | + * 加载发票列表表格的各个列格式 | ||
64 | + */ | ||
65 | + const invoicecColumnsInit = () => { | ||
66 | + let columns = INVOICE_COLUMNS.map((item) => { | ||
67 | + let newItem = { ...item }; | ||
68 | + let dataIndex = item.dataIndex; | ||
69 | + let dataType = item.valueType; | ||
70 | + | ||
71 | + newItem.render = (text, record) => { | ||
72 | + let textValue = record[dataIndex]; | ||
73 | + | ||
74 | + if (dataType === 'dateRange' || dataType === 'date') { | ||
75 | + textValue = formatDate(textValue); | ||
76 | + } | ||
77 | + | ||
78 | + if (dataType === 'dateTime') { | ||
79 | + textValue = formatDateTime(textValue); | ||
80 | + } | ||
81 | + | ||
82 | + if (dataType === 'money') { | ||
83 | + textValue = '¥' + textValue; | ||
84 | + } | ||
85 | + | ||
86 | + switch (dataIndex) { | ||
87 | + case 'invoiceStatus': | ||
88 | + return ( | ||
89 | + <EllipsisDiv | ||
90 | + text={enumValueToLabel( | ||
91 | + getTableCellText(textValue), | ||
92 | + INVOCING_STATUS, | ||
93 | + )} | ||
94 | + /> | ||
95 | + ); | ||
96 | + | ||
97 | + case 'status': | ||
98 | + return ( | ||
99 | + <EllipsisDiv | ||
100 | + text={enumValueToLabel( | ||
101 | + getTableCellText(textValue), | ||
102 | + INVOICE_STATUS, | ||
103 | + )} | ||
104 | + /> | ||
105 | + ); | ||
106 | + | ||
107 | + case 'payee': | ||
108 | + return ( | ||
109 | + <EllipsisDiv | ||
110 | + text={enumValueToLabel( | ||
111 | + getTableCellText(textValue), | ||
112 | + PAYEE_OPTIONS, | ||
113 | + )} | ||
114 | + /> | ||
115 | + ); | ||
116 | + | ||
117 | + default: | ||
118 | + return <EllipsisDiv text={getTableCellText(textValue)} />; | ||
119 | + } | ||
120 | + }; | ||
121 | + | ||
122 | + return newItem; | ||
123 | + }); | ||
124 | + | ||
125 | + columns.push({ | ||
126 | + title: '操作', | ||
127 | + valueType: 'option', | ||
128 | + key: 'option', | ||
129 | + fixed: 'right', | ||
130 | + width: 120, | ||
131 | + render: (text, record) => { | ||
132 | + let btns = []; | ||
133 | + if (record.path?.includes('writeOff')) { | ||
134 | + btns.push( | ||
135 | + <a | ||
136 | + key="editable" | ||
137 | + onClick={() => { | ||
138 | + setInvoiceVerificationVisible(true); | ||
139 | + setInvoiceId(record.invoiceId); | ||
51 | }} | 140 | }} |
52 | > | 141 | > |
53 | - <Button key="4" style={{ padding: '0 8px' }}> | ||
54 | - <EllipsisOutlined /> | ||
55 | - </Button> | ||
56 | - </Dropdown>, | ||
57 | - ], | ||
58 | - }} | ||
59 | - > | ||
60 | - <ProTable | ||
61 | - columns={INVOICE_COLUMNS.map((item) => { | ||
62 | - let newItem = { ...item }; | ||
63 | - if (item.dataIndex === 'invoiceStatus') { | ||
64 | - newItem.render = (text) => { | ||
65 | - return enumValueToLabel(text.props.text, INVOCING_STATUS); | ||
66 | - }; | ||
67 | - } | 142 | + 核销 |
143 | + </a>, | ||
144 | + ); | ||
145 | + } | ||
68 | 146 | ||
69 | - if (item.dataIndex === 'status') { | ||
70 | - newItem.render = (text) => { | ||
71 | - return enumValueToLabel(text, INVOICE_STATUS); | ||
72 | - }; | ||
73 | - } | 147 | + if (record.path?.includes('queryInvoiceDetails')) { |
148 | + btns.push( | ||
149 | + <Button | ||
150 | + className="p-0" | ||
151 | + key="view" | ||
152 | + type="link" | ||
153 | + onClick={() => { | ||
154 | + setInvoiceVerificationVisible(true); | ||
155 | + setInvoiceId(record.invoiceId); | ||
156 | + }} | ||
157 | + > | ||
158 | + 查看 | ||
159 | + </Button>, | ||
160 | + ); | ||
161 | + } | ||
74 | 162 | ||
75 | - if (item.dataIndex === 'payee') { | ||
76 | - newItem.render = (text) => { | ||
77 | - return enumValueToLabel(text, PAYEE_OPTIONS); | ||
78 | - }; | ||
79 | - } | ||
80 | - return newItem; | ||
81 | - })} | ||
82 | - actionRef={actionRef} | 163 | + if (record.path?.includes('deleteInvoice')) { |
164 | + btns.push( | ||
165 | + <ButtonConfirm | ||
166 | + key="delete" | ||
167 | + className="p-0" | ||
168 | + title={ | ||
169 | + '确认删除发票号码为[ ' + record.invoiceNumber + ' ]的发票吗?' | ||
170 | + } | ||
171 | + text="删除" | ||
172 | + onConfirm={async () => { | ||
173 | + let res = await postServiceInvoiceDeleteInvoice({ | ||
174 | + data: { invoiceId: record.invoiceId }, | ||
175 | + }); | ||
176 | + if (res) { | ||
177 | + message.success(res.message); | ||
178 | + reloadInvoiceTable(); | ||
179 | + } | ||
180 | + }} | ||
181 | + />, | ||
182 | + ); | ||
183 | + } | ||
184 | + return btns; | ||
185 | + }, | ||
186 | + }); | ||
187 | + | ||
188 | + return columns; | ||
189 | + }; | ||
190 | + | ||
191 | + const bankStatemetColumnsInit = () => { | ||
192 | + let columns = BANK_STATEMENT_COLUMNS.map((item) => { | ||
193 | + let newItem = { ...item }; | ||
194 | + let dataIndex = item.dataIndex; | ||
195 | + let dataType = item.valueType; | ||
196 | + | ||
197 | + newItem.render = (text, record) => { | ||
198 | + let textValue = record[dataIndex]; | ||
199 | + | ||
200 | + if (dataType === 'date') { | ||
201 | + textValue = formatDate(textValue); | ||
202 | + } | ||
203 | + | ||
204 | + if (dataType === 'dateTime') { | ||
205 | + textValue = formatDateTime(textValue); | ||
206 | + } | ||
207 | + | ||
208 | + if (dataType === 'money') { | ||
209 | + if (textValue === null || textValue === undefined) { | ||
210 | + textValue = ''; | ||
211 | + } else { | ||
212 | + textValue = '¥' + textValue; | ||
213 | + } | ||
214 | + } | ||
215 | + | ||
216 | + switch (dataIndex) { | ||
217 | + case 'invoiceStatus': | ||
218 | + return ( | ||
219 | + <EllipsisDiv | ||
220 | + text={enumValueToLabel( | ||
221 | + getTableCellText(textValue), | ||
222 | + INVOCING_STATUS, | ||
223 | + )} | ||
224 | + /> | ||
225 | + ); | ||
226 | + | ||
227 | + case 'status': | ||
228 | + return ( | ||
229 | + <EllipsisDiv | ||
230 | + text={enumValueToLabel( | ||
231 | + getTableCellText(textValue), | ||
232 | + INVOICE_STATUS, | ||
233 | + )} | ||
234 | + /> | ||
235 | + ); | ||
236 | + | ||
237 | + case 'payee': | ||
238 | + return ( | ||
239 | + <EllipsisDiv | ||
240 | + text={enumValueToLabel( | ||
241 | + getTableCellText(textValue), | ||
242 | + PAYEE_OPTIONS, | ||
243 | + )} | ||
244 | + /> | ||
245 | + ); | ||
246 | + | ||
247 | + default: | ||
248 | + return <EllipsisDiv text={getTableCellText(textValue)} />; | ||
249 | + } | ||
250 | + }; | ||
251 | + | ||
252 | + return newItem; | ||
253 | + }); | ||
254 | + | ||
255 | + columns.push({ | ||
256 | + title: '操作', | ||
257 | + valueType: 'option', | ||
258 | + key: 'option', | ||
259 | + fixed: 'right', | ||
260 | + width: 120, | ||
261 | + render: (text, record, _, action) => { | ||
262 | + let btns = []; | ||
263 | + if (record.path?.includes('editBankStatement')) { | ||
264 | + btns.push( | ||
265 | + <a | ||
266 | + key="editable" | ||
267 | + onClick={() => { | ||
268 | + action?.startEditable?.(record.id); | ||
269 | + }} | ||
270 | + > | ||
271 | + 编辑 | ||
272 | + </a>, | ||
273 | + ); | ||
274 | + } | ||
275 | + | ||
276 | + if (record.path?.includes('deleteBankStatement')) { | ||
277 | + btns.push( | ||
278 | + <ButtonConfirm | ||
279 | + key="delete" | ||
280 | + className="p-0" | ||
281 | + title={'是否删除该银行流水记录?'} | ||
282 | + text="删除" | ||
283 | + onConfirm={async () => { | ||
284 | + let res = await postServiceBankStatementDeleteBankStatement({ | ||
285 | + data: { id: record.id }, | ||
286 | + }); | ||
287 | + if (res.result === RESPONSE_CODE.SUCCESS) { | ||
288 | + message.success(res.message); | ||
289 | + reloadBankStatementTable(); | ||
290 | + } | ||
291 | + }} | ||
292 | + />, | ||
293 | + ); | ||
294 | + } | ||
295 | + return btns; | ||
296 | + }, | ||
297 | + }); | ||
298 | + | ||
299 | + return columns; | ||
300 | + }; | ||
301 | + | ||
302 | + const tabsItems = [ | ||
303 | + { | ||
304 | + key: 1, | ||
305 | + label: '发票管理', | ||
306 | + children: ( | ||
307 | + <ProTable | ||
308 | + columns={invoicecColumnsInit()} | ||
309 | + actionRef={invoiceActionRef} | ||
83 | cardBordered | 310 | cardBordered |
84 | pagination={{ | 311 | pagination={{ |
85 | pageSize: 10, | 312 | pageSize: 10, |
@@ -114,23 +341,159 @@ const InvoicePage = () => { | @@ -114,23 +341,159 @@ const InvoicePage = () => { | ||
114 | listsHeight: 400, | 341 | listsHeight: 400, |
115 | }, | 342 | }, |
116 | }} | 343 | }} |
117 | - form={{ | ||
118 | - // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下 | ||
119 | - syncToUrl: (values, type) => { | ||
120 | - if (type === 'get') { | ||
121 | - return { | ||
122 | - ...values, | ||
123 | - created_at: [values.startTime, values.endTime], | ||
124 | - }; | ||
125 | - } | ||
126 | - return values; | 344 | + form={{}} |
345 | + dateFormatter="string" | ||
346 | + headerTitle="发票列表" | ||
347 | + scroll={{ x: 1400, y: 360 }} | ||
348 | + /> | ||
349 | + ), | ||
350 | + }, | ||
351 | + { | ||
352 | + key: 2, | ||
353 | + label: '银行流水', | ||
354 | + children: ( | ||
355 | + <ProTable | ||
356 | + columns={bankStatemetColumnsInit()} | ||
357 | + actionRef={bankActionRef} | ||
358 | + cardBordered | ||
359 | + pagination={{ | ||
360 | + pageSize: 10, | ||
361 | + }} | ||
362 | + editable={{ | ||
363 | + type: 'multiple', | ||
364 | + onSave: async (rowKey, data) => { | ||
365 | + await postServiceBankStatementEditBankStatement({ data: data }); | ||
127 | }, | 366 | }, |
367 | + actionRender: (row, config, defaultDom) => [ | ||
368 | + defaultDom.save, | ||
369 | + defaultDom.cancel, | ||
370 | + ], | ||
371 | + }} | ||
372 | + request={async (params) => { | ||
373 | + const res = await postServiceBankStatementQueryBankStatement({ | ||
374 | + data: { ...params }, | ||
375 | + }); | ||
376 | + if (res) { | ||
377 | + return { | ||
378 | + data: res?.data?.data || [], | ||
379 | + total: res?.data?.total || 0, | ||
380 | + }; | ||
381 | + } | ||
128 | }} | 382 | }} |
383 | + columnsState={{ | ||
384 | + persistenceKey: 'pro-table-singe-demos', | ||
385 | + persistenceType: 'localStorage', | ||
386 | + defaultValue: { | ||
387 | + option: { fixed: 'right', disable: true }, | ||
388 | + }, | ||
389 | + onChange(value) { | ||
390 | + console.log('value: ', value); | ||
391 | + }, | ||
392 | + }} | ||
393 | + rowKey="id" | ||
394 | + search={{ | ||
395 | + labelWidth: 'auto', | ||
396 | + }} | ||
397 | + options={{ | ||
398 | + setting: { | ||
399 | + listsHeight: 400, | ||
400 | + }, | ||
401 | + }} | ||
402 | + form={{}} | ||
129 | dateFormatter="string" | 403 | dateFormatter="string" |
130 | - headerTitle="发票列表" | ||
131 | - scroll={{ x: true }} | 404 | + headerTitle="银行流水列表" |
405 | + scroll={{ x: 1400, y: 360 }} | ||
406 | + toolBarRender={() => [ | ||
407 | + <Button | ||
408 | + key="button" | ||
409 | + icon={<PlusOutlined />} | ||
410 | + onClick={() => { | ||
411 | + setBankImportModalVisible(true); | ||
412 | + }} | ||
413 | + type="primary" | ||
414 | + > | ||
415 | + 导入 | ||
416 | + </Button>, | ||
417 | + ]} | ||
418 | + /> | ||
419 | + ), | ||
420 | + }, | ||
421 | + ]; | ||
422 | + return ( | ||
423 | + <> | ||
424 | + <PageContainer | ||
425 | + className="invoice-index" | ||
426 | + header={{ | ||
427 | + title: '发票管理', | ||
428 | + extra: [ | ||
429 | + <Avatar key="0" style={{ verticalAlign: 'middle' }} size="large"> | ||
430 | + {userInfo?.username} | ||
431 | + </Avatar>, | ||
432 | + <Tag key="nickName">{userInfo?.nickName}</Tag>, | ||
433 | + <Dropdown | ||
434 | + key="dropdown" | ||
435 | + trigger={['click']} | ||
436 | + menu={{ | ||
437 | + items: [ | ||
438 | + { | ||
439 | + label: '退出登录', | ||
440 | + key: '1', | ||
441 | + onClick: () => { | ||
442 | + localStorage.removeItem('token'); | ||
443 | + history.push('/login'); | ||
444 | + }, | ||
445 | + }, | ||
446 | + // { | ||
447 | + // label: '修改密码', | ||
448 | + // key: '2', | ||
449 | + // }, | ||
450 | + ], | ||
451 | + }} | ||
452 | + > | ||
453 | + <Button key="4" style={{ padding: '0 8px' }}> | ||
454 | + <EllipsisOutlined /> | ||
455 | + </Button> | ||
456 | + </Dropdown>, | ||
457 | + ], | ||
458 | + }} | ||
459 | + > | ||
460 | + <Tabs | ||
461 | + defaultActiveKey="1" | ||
462 | + items={tabsItems} | ||
463 | + onChange={(value) => { | ||
464 | + if (value === 1) { | ||
465 | + invoiceActionRef.current?.reload(); | ||
466 | + } else { | ||
467 | + bankActionRef.current?.reload(); | ||
468 | + } | ||
469 | + }} | ||
132 | /> | 470 | /> |
133 | </PageContainer> | 471 | </PageContainer> |
472 | + | ||
473 | + {bankImportModalVisible ? ( | ||
474 | + <BankImportModal | ||
475 | + setVisible={setBankImportModalVisible} | ||
476 | + onClose={() => { | ||
477 | + invoiceActionRef.current?.reload(); | ||
478 | + bankActionRef.current?.reload(); | ||
479 | + }} | ||
480 | + ></BankImportModal> | ||
481 | + ) : ( | ||
482 | + '' | ||
483 | + )} | ||
484 | + | ||
485 | + {invoiceVerificationVisible ? ( | ||
486 | + <InvoiceVerificationModal | ||
487 | + setVisible={setInvoiceVerificationVisible} | ||
488 | + invoiceId={invoiceId} | ||
489 | + onClose={() => { | ||
490 | + invoiceActionRef.current?.reload(); | ||
491 | + bankActionRef.current?.reload(); | ||
492 | + }} | ||
493 | + ></InvoiceVerificationModal> | ||
494 | + ) : ( | ||
495 | + '' | ||
496 | + )} | ||
134 | </> | 497 | </> |
135 | ); | 498 | ); |
136 | }; | 499 | }; |
src/pages/Order/components/FinancialDrawer.tsx
@@ -8,13 +8,14 @@ import { enumToSelect } from '@/utils'; | @@ -8,13 +8,14 @@ import { enumToSelect } from '@/utils'; | ||
8 | import { | 8 | import { |
9 | DrawerForm, | 9 | DrawerForm, |
10 | ProFormDatePicker, | 10 | ProFormDatePicker, |
11 | + ProFormDigit, | ||
11 | ProFormSelect, | 12 | ProFormSelect, |
12 | ProFormText, | 13 | ProFormText, |
13 | ProFormTextArea, | 14 | ProFormTextArea, |
14 | } from '@ant-design/pro-components'; | 15 | } from '@ant-design/pro-components'; |
15 | import { Form, message } from 'antd'; | 16 | import { Form, message } from 'antd'; |
16 | import { useEffect, useState } from 'react'; | 17 | import { useEffect, useState } from 'react'; |
17 | -import { INVOCING_STATUS_OPTIONS_OLD } from '../constant'; | 18 | +import { INVOCING_STATUS_OPTIONS_OLD, PAYEE_OPTIONS } from '../constant'; |
18 | 19 | ||
19 | export default ({ | 20 | export default ({ |
20 | mainOrder, | 21 | mainOrder, |
@@ -141,32 +142,32 @@ export default ({ | @@ -141,32 +142,32 @@ export default ({ | ||
141 | label="收款时间" | 142 | label="收款时间" |
142 | initialValue={subOrders[0]?.collectMoneyTime} | 143 | initialValue={subOrders[0]?.collectMoneyTime} |
143 | />, | 144 | />, |
144 | - // <ProFormText | ||
145 | - // width="lg" | ||
146 | - // key="invoiceNumber" | ||
147 | - // name="invoiceNumber" | ||
148 | - // label="发票号码" | ||
149 | - // initialValue={subOrders[0]?.invoiceNumber} | ||
150 | - // rules={[{ required: true, message: '发票号码必填' }]} | ||
151 | - // />, | ||
152 | - // <ProFormSelect | ||
153 | - // key="payee" | ||
154 | - // placeholder="选择收款单位" | ||
155 | - // name="payee" | ||
156 | - // width="lg" | ||
157 | - // label="收款单位" | ||
158 | - // options={enumToSelect(PAYEE_OPTIONS)} | ||
159 | - // initialValue={subOrders[0]?.payee} | ||
160 | - // rules={[{ required: true, message: '收款单位必填' }]} | ||
161 | - // />, | 145 | + <ProFormText |
146 | + width="lg" | ||
147 | + key="invoiceNumber" | ||
148 | + name="invoiceNumber" | ||
149 | + label="发票号码" | ||
150 | + initialValue={subOrders[0]?.invoiceNumber} | ||
151 | + rules={[{ required: true, message: '发票号码必填' }]} | ||
152 | + />, | ||
153 | + <ProFormSelect | ||
154 | + key="payee" | ||
155 | + placeholder="选择收款单位" | ||
156 | + name="payee" | ||
157 | + width="lg" | ||
158 | + label="收款单位" | ||
159 | + options={enumToSelect(PAYEE_OPTIONS)} | ||
160 | + initialValue={subOrders[0]?.payee} | ||
161 | + rules={[{ required: true, message: '收款单位必填' }]} | ||
162 | + />, | ||
162 | 163 | ||
163 | - // <ProFormDigit | ||
164 | - // key="money" | ||
165 | - // name="money" | ||
166 | - // width="lg" | ||
167 | - // label="金额" | ||
168 | - // rules={[{ required: true, message: '金额必填' }]} | ||
169 | - // />, | 164 | + <ProFormDigit |
165 | + key="money" | ||
166 | + name="money" | ||
167 | + width="lg" | ||
168 | + label="金额" | ||
169 | + rules={[{ required: true, message: '金额必填' }]} | ||
170 | + />, | ||
170 | ] | 171 | ] |
171 | : ''} | 172 | : ''} |
172 | 173 |
src/pages/Order/components/FinancialMergeDrawer.tsx
1 | // import { PlusOutlined } from '@ant-design/icons'; | 1 | // import { PlusOutlined } from '@ant-design/icons'; |
2 | import { RESPONSE_CODE } from '@/constants/enum'; | 2 | import { RESPONSE_CODE } from '@/constants/enum'; |
3 | import { postServiceOrderMergeInvoicing } from '@/services'; | 3 | import { postServiceOrderMergeInvoicing } from '@/services'; |
4 | +import { enumToSelect } from '@/utils'; | ||
4 | import { | 5 | import { |
5 | DrawerForm, | 6 | DrawerForm, |
6 | ProFormDatePicker, | 7 | ProFormDatePicker, |
8 | + ProFormDigit, | ||
7 | ProFormSelect, | 9 | ProFormSelect, |
8 | ProFormText, | 10 | ProFormText, |
9 | ProFormTextArea, | 11 | ProFormTextArea, |
10 | } from '@ant-design/pro-components'; | 12 | } from '@ant-design/pro-components'; |
11 | import { Form, message } from 'antd'; | 13 | import { Form, message } from 'antd'; |
14 | +import { PAYEE_OPTIONS } from '../constant'; | ||
12 | 15 | ||
13 | export default ({ dataList, setVisible, onClose }) => { | 16 | export default ({ dataList, setVisible, onClose }) => { |
14 | let mainOrderIds = dataList?.map((item) => { | 17 | let mainOrderIds = dataList?.map((item) => { |
@@ -104,7 +107,30 @@ export default ({ dataList, setVisible, onClose }) => { | @@ -104,7 +107,30 @@ export default ({ dataList, setVisible, onClose }) => { | ||
104 | name="collectMoneyTime" | 107 | name="collectMoneyTime" |
105 | label="收款时间" | 108 | label="收款时间" |
106 | /> | 109 | /> |
110 | + <ProFormText | ||
111 | + width="lg" | ||
112 | + key="invoiceNumber" | ||
113 | + name="invoiceNumber" | ||
114 | + label="发票号码" | ||
115 | + rules={[{ required: true, message: '发票号码必填' }]} | ||
116 | + /> | ||
117 | + <ProFormSelect | ||
118 | + key="payee" | ||
119 | + placeholder="选择收款单位" | ||
120 | + name="payee" | ||
121 | + width="lg" | ||
122 | + label="收款单位" | ||
123 | + options={enumToSelect(PAYEE_OPTIONS)} | ||
124 | + rules={[{ required: true, message: '收款单位必填' }]} | ||
125 | + /> | ||
107 | 126 | ||
127 | + <ProFormDigit | ||
128 | + key="money" | ||
129 | + name="money" | ||
130 | + width="lg" | ||
131 | + label="金额" | ||
132 | + rules={[{ required: true, message: '金额必填' }]} | ||
133 | + /> | ||
108 | <ProFormSelect | 134 | <ProFormSelect |
109 | placeholder="是否完全开票" | 135 | placeholder="是否完全开票" |
110 | name="afterInvoicingStatus" | 136 | name="afterInvoicingStatus" |
src/pages/Order/index.tsx
@@ -27,8 +27,10 @@ import { | @@ -27,8 +27,10 @@ import { | ||
27 | QuestionCircleOutlined, | 27 | QuestionCircleOutlined, |
28 | } from '@ant-design/icons'; | 28 | } from '@ant-design/icons'; |
29 | import { | 29 | import { |
30 | + ActionType, | ||
30 | PageContainer, | 31 | PageContainer, |
31 | ProColumns, | 32 | ProColumns, |
33 | + ProFormInstance, | ||
32 | ProTable, | 34 | ProTable, |
33 | } from '@ant-design/pro-components'; | 35 | } from '@ant-design/pro-components'; |
34 | import { history } from '@umijs/max'; | 36 | import { history } from '@umijs/max'; |
@@ -47,7 +49,7 @@ import { | @@ -47,7 +49,7 @@ import { | ||
47 | message, | 49 | message, |
48 | } from 'antd'; | 50 | } from 'antd'; |
49 | import { cloneDeep } from 'lodash'; | 51 | import { cloneDeep } from 'lodash'; |
50 | -import React, { Key, useRef, useState } from 'react'; | 52 | +import React, { Key, useEffect, useRef, useState } from 'react'; |
51 | import OrderPrintModal from '../OrderPrint/OrderPrintModal'; | 53 | import OrderPrintModal from '../OrderPrint/OrderPrintModal'; |
52 | import AfterSalesDrawer from './components/AfterSalesDrawer'; | 54 | import AfterSalesDrawer from './components/AfterSalesDrawer'; |
53 | import ApplyForInvoicingModal from './components/ApplyForInvoicingModal'; | 55 | import ApplyForInvoicingModal from './components/ApplyForInvoicingModal'; |
@@ -145,7 +147,8 @@ const OrderPage = () => { | @@ -145,7 +147,8 @@ const OrderPage = () => { | ||
145 | const [mainOrderSelectedRows, setMainOrderSelectedRows] = useState([]); //选中的主订单集合 | 147 | const [mainOrderSelectedRows, setMainOrderSelectedRows] = useState([]); //选中的主订单集合 |
146 | const [onlyShowFinancialToBeProcessed, setOnlyShowFinancialToBeProcessed] = | 148 | const [onlyShowFinancialToBeProcessed, setOnlyShowFinancialToBeProcessed] = |
147 | useState(false); | 149 | useState(false); |
148 | - const mainTableRef = useRef(); | 150 | + const mainTableRef = useRef<ActionType>(); |
151 | + const mainTableFormRef = useRef<ProFormInstance>(); | ||
149 | let [searchParams, setSearchParam] = useState(Object); //表格的查询条件存储 | 152 | let [searchParams, setSearchParam] = useState(Object); //表格的查询条件存储 |
150 | const [messageApi, contextHolder] = message.useMessage(); | 153 | const [messageApi, contextHolder] = message.useMessage(); |
151 | 154 | ||
@@ -2286,7 +2289,10 @@ const OrderPage = () => { | @@ -2286,7 +2289,10 @@ const OrderPage = () => { | ||
2286 | mainOrderSelectedMap.forEach((value) => { | 2289 | mainOrderSelectedMap.forEach((value) => { |
2287 | mainOrders.push(value); | 2290 | mainOrders.push(value); |
2288 | for (let subOrder of value.subOrderInformationLists) { | 2291 | for (let subOrder of value.subOrderInformationLists) { |
2289 | - if (subOrder.afterInvoicingStatus !== 'APPLY_FOR_INVOICING') { | 2292 | + if ( |
2293 | + subOrder.afterInvoicingStatus !== 'APPLY_FOR_INVOICING' && | ||
2294 | + subOrder.afterInvoicingStatus !== 'PARTIAL_INVOICING' | ||
2295 | + ) { | ||
2290 | errorIds.push(value.id); | 2296 | errorIds.push(value.id); |
2291 | return; | 2297 | return; |
2292 | } | 2298 | } |
@@ -2296,7 +2302,7 @@ const OrderPage = () => { | @@ -2296,7 +2302,7 @@ const OrderPage = () => { | ||
2296 | message.error( | 2302 | message.error( |
2297 | '订单号为:' + | 2303 | '订单号为:' + |
2298 | errorIds.join(',') + | 2304 | errorIds.join(',') + |
2299 | - '的订单存在不是[申请开票]状态的子订单,请检查!', | 2305 | + '的订单存在不是[申请开票]或者[部分开票]状态的子订单,请检查!', |
2300 | ); | 2306 | ); |
2301 | return; | 2307 | return; |
2302 | } | 2308 | } |
@@ -2369,6 +2375,15 @@ const OrderPage = () => { | @@ -2369,6 +2375,15 @@ const OrderPage = () => { | ||
2369 | return toolBtns; | 2375 | return toolBtns; |
2370 | } | 2376 | } |
2371 | 2377 | ||
2378 | + useEffect(() => { | ||
2379 | + // 使用URLSearchParams来解析查询参数 | ||
2380 | + const params = new URLSearchParams(location.search); | ||
2381 | + const id = params.get('id'); | ||
2382 | + if (id) { | ||
2383 | + mainTableFormRef.current?.setFieldValue('id', id); | ||
2384 | + } | ||
2385 | + }, []); | ||
2386 | + | ||
2372 | return ( | 2387 | return ( |
2373 | <PageContainer | 2388 | <PageContainer |
2374 | className="order-page-container" | 2389 | className="order-page-container" |
@@ -2412,6 +2427,7 @@ const OrderPage = () => { | @@ -2412,6 +2427,7 @@ const OrderPage = () => { | ||
2412 | // tableStyle={{backgroundColor:'red'}} | 2427 | // tableStyle={{backgroundColor:'red'}} |
2413 | 2428 | ||
2414 | actionRef={mainTableRef} | 2429 | actionRef={mainTableRef} |
2430 | + formRef={mainTableFormRef} | ||
2415 | expandIconColumnIndex={-1} | 2431 | expandIconColumnIndex={-1} |
2416 | columns={mainOrdersColumns} | 2432 | columns={mainOrdersColumns} |
2417 | rowKey="id" | 2433 | rowKey="id" |
@@ -2443,6 +2459,12 @@ const OrderPage = () => { | @@ -2443,6 +2459,12 @@ const OrderPage = () => { | ||
2443 | filter, | 2459 | filter, |
2444 | ) => { | 2460 | ) => { |
2445 | //订单id处理 | 2461 | //订单id处理 |
2462 | + /** | ||
2463 | + * 以params中的id为主,如果params没id,则取url中的id | ||
2464 | + * 第一次进来这个页面,url带有id的话,会自动填充到查询表单中,但是第一次查询params不会带这个id进来 | ||
2465 | + */ | ||
2466 | + let orderIds = mainTableFormRef.current?.getFieldValue('id'); | ||
2467 | + params.id = params.id || orderIds; | ||
2446 | if (params.id !== '') { | 2468 | if (params.id !== '') { |
2447 | if (params.id?.indexOf(',')) { | 2469 | if (params.id?.indexOf(',')) { |
2448 | params.id = params.id.split(','); | 2470 | params.id = params.id.split(','); |
src/pages/OrderReport/components/OrderStatisticCard.tsx
@@ -238,8 +238,8 @@ export default ({ data, statisticsMethod, reFreshData }) => { | @@ -238,8 +238,8 @@ export default ({ data, statisticsMethod, reFreshData }) => { | ||
238 | > | 238 | > |
239 | <CardContent | 239 | <CardContent |
240 | unit="¥" | 240 | unit="¥" |
241 | - content={data.totalPayment} | ||
242 | - sameMonthPercentageChange={data.totalPaymentTrend} | 241 | + content={data?.totalPayment} |
242 | + sameMonthPercentageChange={data?.totalPaymentTrend} | ||
243 | /> | 243 | /> |
244 | </ProCard> | 244 | </ProCard> |
245 | <ProCard | 245 | <ProCard |
@@ -247,7 +247,7 @@ export default ({ data, statisticsMethod, reFreshData }) => { | @@ -247,7 +247,7 @@ export default ({ data, statisticsMethod, reFreshData }) => { | ||
247 | title={<CardTitle title={'指标'} />} | 247 | title={<CardTitle title={'指标'} />} |
248 | bordered | 248 | bordered |
249 | > | 249 | > |
250 | - <CardContent unit="¥" content={data.target} editable={true} /> | 250 | + <CardContent unit="¥" content={data?.target} editable={true} /> |
251 | </ProCard> | 251 | </ProCard> |
252 | <ProCard | 252 | <ProCard |
253 | className="order-statictis-card" | 253 | className="order-statictis-card" |
@@ -256,8 +256,8 @@ export default ({ data, statisticsMethod, reFreshData }) => { | @@ -256,8 +256,8 @@ export default ({ data, statisticsMethod, reFreshData }) => { | ||
256 | > | 256 | > |
257 | <CardContent | 257 | <CardContent |
258 | unit="单" | 258 | unit="单" |
259 | - content={data.totalOrderNumber} | ||
260 | - sameMonthPercentageChange={data.totalOrderNumberTrend} | 259 | + content={data?.totalOrderNumber} |
260 | + sameMonthPercentageChange={data?.totalOrderNumberTrend} | ||
261 | /> | 261 | /> |
262 | </ProCard> | 262 | </ProCard> |
263 | <ProCard | 263 | <ProCard |
@@ -265,21 +265,21 @@ export default ({ data, statisticsMethod, reFreshData }) => { | @@ -265,21 +265,21 @@ export default ({ data, statisticsMethod, reFreshData }) => { | ||
265 | title={<CardTitle title={'总子订单量'} />} | 265 | title={<CardTitle title={'总子订单量'} />} |
266 | bordered | 266 | bordered |
267 | > | 267 | > |
268 | - <CardContent unit="单" content={data.subTotalOrderNumber} /> | 268 | + <CardContent unit="单" content={data?.subTotalOrderNumber} /> |
269 | </ProCard> | 269 | </ProCard> |
270 | <ProCard | 270 | <ProCard |
271 | className="order-statictis-card" | 271 | className="order-statictis-card" |
272 | title={<CardTitle title={'未审核子订单'} />} | 272 | title={<CardTitle title={'未审核子订单'} />} |
273 | bordered | 273 | bordered |
274 | > | 274 | > |
275 | - <CardContent unit="单" content={data.unCheckOrderNumber} /> | 275 | + <CardContent unit="单" content={data?.unCheckOrderNumber} /> |
276 | </ProCard> | 276 | </ProCard> |
277 | <ProCard | 277 | <ProCard |
278 | className="order-statictis-card" | 278 | className="order-statictis-card" |
279 | title={<CardTitle title={'待发货子订单'} />} | 279 | title={<CardTitle title={'待发货子订单'} />} |
280 | bordered | 280 | bordered |
281 | > | 281 | > |
282 | - <CardContent unit="单" content={data.unSendOrderNumber} /> | 282 | + <CardContent unit="单" content={data?.unSendOrderNumber} /> |
283 | </ProCard> | 283 | </ProCard> |
284 | </ProCard> | 284 | </ProCard> |
285 | 285 |