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 | 45 | icon: 'LineChartOutlined', |
46 | 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 | 56 | name: '打印', |
57 | 57 | path: '/print', | ... | ... |
src/access.ts
... | ... | @@ -6,5 +6,7 @@ export default (initialState: API.UserInfo) => { |
6 | 6 | return { |
7 | 7 | canReadAdmin: roleSmallVO?.code === 'admin', |
8 | 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 | 4 | export type InvoiceItem = { |
4 | 5 | id: number; //id |
... | ... | @@ -15,92 +16,341 @@ export type InvoiceItem = { |
15 | 16 | notes: string; //备注 |
16 | 17 | }; |
17 | 18 | |
19 | +export const INVOICE_STATUS = { | |
20 | + UNVERIFIED: '未核销', | |
21 | + VERIFIED: '已核销', | |
22 | + ABNORMAL: '异常', | |
23 | + PARTIAL_VERIFICATION: '部分核销', | |
24 | +}; | |
25 | + | |
18 | 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 | 36 | dataIndex: 'invoiceNumber', |
21 | 37 | title: '发票号码', |
22 | 38 | valueType: 'text', |
39 | + width: 100, | |
23 | 40 | }, |
24 | 41 | { |
25 | 42 | dataIndex: 'invoiceStatus', |
26 | 43 | title: '发票类型', |
27 | 44 | valueType: 'select', |
45 | + width: 100, | |
46 | + valueEnum: enumToProTableEnumValue({ | |
47 | + SPECIALLY_INVOICED: '专票', | |
48 | + COMMON_INVOICED: '普票', | |
49 | + }), | |
28 | 50 | }, |
29 | 51 | { |
30 | 52 | title: '状态', |
31 | 53 | dataIndex: 'status', |
32 | 54 | valueType: 'text', |
55 | + width: 100, | |
56 | + valueEnum: enumToProTableEnumValue({ | |
57 | + UNVERIFIED: '未核销', | |
58 | + VERIFIED: '已核销', | |
59 | + PARTIAL_VERIFICATION: '部分核销', | |
60 | + }), | |
33 | 61 | }, |
34 | 62 | { |
35 | 63 | title: '购买方', |
36 | 64 | dataIndex: 'purchaser', |
37 | 65 | valueType: 'text', |
66 | + width: 180, | |
38 | 67 | }, |
39 | 68 | { |
40 | 69 | title: '收款单位', |
41 | 70 | dataIndex: 'payee', |
42 | 71 | valueType: 'text', |
72 | + width: 180, | |
73 | + valueEnum: enumToProTableEnumValue(PAYEE_OPTIONS), | |
43 | 74 | }, |
44 | 75 | { |
45 | 76 | title: '联系人', |
46 | 77 | dataIndex: 'contacts', |
47 | 78 | valueType: 'text', |
79 | + width: 100, | |
48 | 80 | }, |
49 | 81 | { |
50 | 82 | title: '销售', |
51 | 83 | dataIndex: 'sale', |
52 | 84 | valueType: 'text', |
85 | + width: 100, | |
53 | 86 | }, |
54 | 87 | { |
55 | 88 | title: '金额', |
56 | 89 | dataIndex: 'money', |
57 | 90 | valueType: 'money', |
91 | + width: 100, | |
58 | 92 | }, |
59 | 93 | { |
60 | 94 | title: '开票日期', |
61 | 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 | 110 | title: '收款时间', |
66 | 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 | 126 | title: '备注', |
71 | 127 | dataIndex: 'notes', |
72 | 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 | 4 | 'WenQuanYi Micro Hei', sans-serif; |
5 | 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 | 18 | import { getUserInfo } from '@/utils/user'; |
5 | -import { EllipsisOutlined } from '@ant-design/icons'; | |
19 | +import { EllipsisOutlined, PlusOutlined } from '@ant-design/icons'; | |
6 | 20 | import { |
7 | 21 | ActionType, |
8 | 22 | PageContainer, |
9 | 23 | ProTable, |
10 | 24 | } from '@ant-design/pro-components'; |
11 | 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 | 28 | import { INVOCING_STATUS, PAYEE_OPTIONS } from '../Order/constant'; |
29 | +import BankImportModal from './components/BankImportModal'; | |
30 | +import InvoiceVerificationModal from './components/InvoiceVerificationModal'; | |
15 | 31 | import './index.less'; |
16 | - | |
17 | -const userInfo = getUserInfo(); | |
18 | 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 | 310 | cardBordered |
84 | 311 | pagination={{ |
85 | 312 | pageSize: 10, |
... | ... | @@ -114,23 +341,159 @@ const InvoicePage = () => { |
114 | 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 | 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 | 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 | 8 | import { |
9 | 9 | DrawerForm, |
10 | 10 | ProFormDatePicker, |
11 | + ProFormDigit, | |
11 | 12 | ProFormSelect, |
12 | 13 | ProFormText, |
13 | 14 | ProFormTextArea, |
14 | 15 | } from '@ant-design/pro-components'; |
15 | 16 | import { Form, message } from 'antd'; |
16 | 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 | 20 | export default ({ |
20 | 21 | mainOrder, |
... | ... | @@ -141,32 +142,32 @@ export default ({ |
141 | 142 | label="收款时间" |
142 | 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 | 1 | // import { PlusOutlined } from '@ant-design/icons'; |
2 | 2 | import { RESPONSE_CODE } from '@/constants/enum'; |
3 | 3 | import { postServiceOrderMergeInvoicing } from '@/services'; |
4 | +import { enumToSelect } from '@/utils'; | |
4 | 5 | import { |
5 | 6 | DrawerForm, |
6 | 7 | ProFormDatePicker, |
8 | + ProFormDigit, | |
7 | 9 | ProFormSelect, |
8 | 10 | ProFormText, |
9 | 11 | ProFormTextArea, |
10 | 12 | } from '@ant-design/pro-components'; |
11 | 13 | import { Form, message } from 'antd'; |
14 | +import { PAYEE_OPTIONS } from '../constant'; | |
12 | 15 | |
13 | 16 | export default ({ dataList, setVisible, onClose }) => { |
14 | 17 | let mainOrderIds = dataList?.map((item) => { |
... | ... | @@ -104,7 +107,30 @@ export default ({ dataList, setVisible, onClose }) => { |
104 | 107 | name="collectMoneyTime" |
105 | 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 | 134 | <ProFormSelect |
109 | 135 | placeholder="是否完全开票" |
110 | 136 | name="afterInvoicingStatus" | ... | ... |
src/pages/Order/index.tsx
... | ... | @@ -27,8 +27,10 @@ import { |
27 | 27 | QuestionCircleOutlined, |
28 | 28 | } from '@ant-design/icons'; |
29 | 29 | import { |
30 | + ActionType, | |
30 | 31 | PageContainer, |
31 | 32 | ProColumns, |
33 | + ProFormInstance, | |
32 | 34 | ProTable, |
33 | 35 | } from '@ant-design/pro-components'; |
34 | 36 | import { history } from '@umijs/max'; |
... | ... | @@ -47,7 +49,7 @@ import { |
47 | 49 | message, |
48 | 50 | } from 'antd'; |
49 | 51 | import { cloneDeep } from 'lodash'; |
50 | -import React, { Key, useRef, useState } from 'react'; | |
52 | +import React, { Key, useEffect, useRef, useState } from 'react'; | |
51 | 53 | import OrderPrintModal from '../OrderPrint/OrderPrintModal'; |
52 | 54 | import AfterSalesDrawer from './components/AfterSalesDrawer'; |
53 | 55 | import ApplyForInvoicingModal from './components/ApplyForInvoicingModal'; |
... | ... | @@ -145,7 +147,8 @@ const OrderPage = () => { |
145 | 147 | const [mainOrderSelectedRows, setMainOrderSelectedRows] = useState([]); //选中的主订单集合 |
146 | 148 | const [onlyShowFinancialToBeProcessed, setOnlyShowFinancialToBeProcessed] = |
147 | 149 | useState(false); |
148 | - const mainTableRef = useRef(); | |
150 | + const mainTableRef = useRef<ActionType>(); | |
151 | + const mainTableFormRef = useRef<ProFormInstance>(); | |
149 | 152 | let [searchParams, setSearchParam] = useState(Object); //表格的查询条件存储 |
150 | 153 | const [messageApi, contextHolder] = message.useMessage(); |
151 | 154 | |
... | ... | @@ -2286,7 +2289,10 @@ const OrderPage = () => { |
2286 | 2289 | mainOrderSelectedMap.forEach((value) => { |
2287 | 2290 | mainOrders.push(value); |
2288 | 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 | 2296 | errorIds.push(value.id); |
2291 | 2297 | return; |
2292 | 2298 | } |
... | ... | @@ -2296,7 +2302,7 @@ const OrderPage = () => { |
2296 | 2302 | message.error( |
2297 | 2303 | '订单号为:' + |
2298 | 2304 | errorIds.join(',') + |
2299 | - '的订单存在不是[申请开票]状态的子订单,请检查!', | |
2305 | + '的订单存在不是[申请开票]或者[部分开票]状态的子订单,请检查!', | |
2300 | 2306 | ); |
2301 | 2307 | return; |
2302 | 2308 | } |
... | ... | @@ -2369,6 +2375,15 @@ const OrderPage = () => { |
2369 | 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 | 2387 | return ( |
2373 | 2388 | <PageContainer |
2374 | 2389 | className="order-page-container" |
... | ... | @@ -2412,6 +2427,7 @@ const OrderPage = () => { |
2412 | 2427 | // tableStyle={{backgroundColor:'red'}} |
2413 | 2428 | |
2414 | 2429 | actionRef={mainTableRef} |
2430 | + formRef={mainTableFormRef} | |
2415 | 2431 | expandIconColumnIndex={-1} |
2416 | 2432 | columns={mainOrdersColumns} |
2417 | 2433 | rowKey="id" |
... | ... | @@ -2443,6 +2459,12 @@ const OrderPage = () => { |
2443 | 2459 | filter, |
2444 | 2460 | ) => { |
2445 | 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 | 2468 | if (params.id !== '') { |
2447 | 2469 | if (params.id?.indexOf(',')) { |
2448 | 2470 | params.id = params.id.split(','); | ... | ... |
src/pages/OrderReport/components/OrderStatisticCard.tsx
... | ... | @@ -238,8 +238,8 @@ export default ({ data, statisticsMethod, reFreshData }) => { |
238 | 238 | > |
239 | 239 | <CardContent |
240 | 240 | unit="¥" |
241 | - content={data.totalPayment} | |
242 | - sameMonthPercentageChange={data.totalPaymentTrend} | |
241 | + content={data?.totalPayment} | |
242 | + sameMonthPercentageChange={data?.totalPaymentTrend} | |
243 | 243 | /> |
244 | 244 | </ProCard> |
245 | 245 | <ProCard |
... | ... | @@ -247,7 +247,7 @@ export default ({ data, statisticsMethod, reFreshData }) => { |
247 | 247 | title={<CardTitle title={'指标'} />} |
248 | 248 | bordered |
249 | 249 | > |
250 | - <CardContent unit="¥" content={data.target} editable={true} /> | |
250 | + <CardContent unit="¥" content={data?.target} editable={true} /> | |
251 | 251 | </ProCard> |
252 | 252 | <ProCard |
253 | 253 | className="order-statictis-card" |
... | ... | @@ -256,8 +256,8 @@ export default ({ data, statisticsMethod, reFreshData }) => { |
256 | 256 | > |
257 | 257 | <CardContent |
258 | 258 | unit="单" |
259 | - content={data.totalOrderNumber} | |
260 | - sameMonthPercentageChange={data.totalOrderNumberTrend} | |
259 | + content={data?.totalOrderNumber} | |
260 | + sameMonthPercentageChange={data?.totalOrderNumberTrend} | |
261 | 261 | /> |
262 | 262 | </ProCard> |
263 | 263 | <ProCard |
... | ... | @@ -265,21 +265,21 @@ export default ({ data, statisticsMethod, reFreshData }) => { |
265 | 265 | title={<CardTitle title={'总子订单量'} />} |
266 | 266 | bordered |
267 | 267 | > |
268 | - <CardContent unit="单" content={data.subTotalOrderNumber} /> | |
268 | + <CardContent unit="单" content={data?.subTotalOrderNumber} /> | |
269 | 269 | </ProCard> |
270 | 270 | <ProCard |
271 | 271 | className="order-statictis-card" |
272 | 272 | title={<CardTitle title={'未审核子订单'} />} |
273 | 273 | bordered |
274 | 274 | > |
275 | - <CardContent unit="单" content={data.unCheckOrderNumber} /> | |
275 | + <CardContent unit="单" content={data?.unCheckOrderNumber} /> | |
276 | 276 | </ProCard> |
277 | 277 | <ProCard |
278 | 278 | className="order-statictis-card" |
279 | 279 | title={<CardTitle title={'待发货子订单'} />} |
280 | 280 | bordered |
281 | 281 | > |
282 | - <CardContent unit="单" content={data.unSendOrderNumber} /> | |
282 | + <CardContent unit="单" content={data?.unSendOrderNumber} /> | |
283 | 283 | </ProCard> |
284 | 284 | </ProCard> |
285 | 285 | ... | ... |