Commit 0afddbf9116c1f9a70d29071736a8ed103b9b431
Merge remote-tracking branch 'origin/afterFeed' into master2
# Conflicts: # src/services/definition.ts # src/services/request.ts
Showing
27 changed files
with
3995 additions
and
395 deletions
Too many changes to show.
To preserve performance only 27 of 67 files are displayed.
.umirc.ts
... | ... | @@ -14,9 +14,9 @@ export default defineConfig({ |
14 | 14 | }, |
15 | 15 | proxy: { |
16 | 16 | '/api/': { |
17 | - target: 'http://localhost:8085/', | |
17 | + // target: 'http://localhost:8085/', | |
18 | 18 | // target: 'http://192.168.1.6:8085/', |
19 | - // target: 'http://39.108.227.113:8085/', | |
19 | + target: 'http://39.108.227.113:8085/', | |
20 | 20 | changeOrigin: true, |
21 | 21 | pathRewrite: { '^/api': '' }, |
22 | 22 | }, |
... | ... | @@ -51,7 +51,6 @@ export default defineConfig({ |
51 | 51 | { |
52 | 52 | name: '订单预警', |
53 | 53 | path: 'OrderWarning', |
54 | - access: 'canReadAdminAndSales', | |
55 | 54 | component: './Order/OrderWarning', |
56 | 55 | }, |
57 | 56 | { |
... | ... | @@ -60,6 +59,11 @@ export default defineConfig({ |
60 | 59 | access: 'canReadAdminAndSalesManager', |
61 | 60 | component: './Order/WarningWhitelist', |
62 | 61 | }, |
62 | + { | |
63 | + name: '订单售后', | |
64 | + path: 'FeedBack', | |
65 | + component: './Order/FeedBack', | |
66 | + }, | |
63 | 67 | ], |
64 | 68 | }, |
65 | 69 | { |
... | ... | @@ -150,11 +154,11 @@ export default defineConfig({ |
150 | 154 | name: '客户管理', |
151 | 155 | path: '/Client', |
152 | 156 | icon: 'BookOutlined', |
153 | - access: 'canReadAdminAndSalesAndWarehouseKeeper', | |
157 | + access: 'canReadAdminAndSales', | |
154 | 158 | routes: [ |
155 | 159 | { |
156 | 160 | name: '客户列表', |
157 | - path: 'clint', | |
161 | + path: 'client', | |
158 | 162 | component: './Client/Client', |
159 | 163 | }, |
160 | 164 | { | ... | ... |
src/pages/Client/Client/Components/ClientDrawer.tsx
... | ... | @@ -8,6 +8,7 @@ import { |
8 | 8 | postResearchGroupsNameSet, |
9 | 9 | postServiceConstClientLevels, |
10 | 10 | postServiceConstClientSource, |
11 | + postServiceOrderQuerySalesCode, | |
11 | 12 | } from '@/services'; |
12 | 13 | |
13 | 14 | import { enumToSelect } from '@/utils'; |
... | ... | @@ -18,7 +19,7 @@ import { |
18 | 19 | } from '@ant-design/pro-components'; |
19 | 20 | import { Button, Form, message } from 'antd'; |
20 | 21 | // import { options } from 'node_modules/axios/index.cjs'; |
21 | -import { useState } from 'react'; | |
22 | +import { useEffect, useState } from 'react'; | |
22 | 23 | |
23 | 24 | export default ({ optType, record, onFinish }) => { |
24 | 25 | const [form] = Form.useForm(); |
... | ... | @@ -26,6 +27,24 @@ export default ({ optType, record, onFinish }) => { |
26 | 27 | const [province, setProvince] = useState(''); |
27 | 28 | const [city, setCity] = useState(''); |
28 | 29 | const [showReferrers, setShowReferrers] = useState(false); // 控制显示的状态,初始为false |
30 | + const [affiliateSalesOptions, setAffiliateSalesOptions] = useState([]); | |
31 | + | |
32 | + useEffect(() => { | |
33 | + const fetchAffiliateSalesOptions = async () => { | |
34 | + try { | |
35 | + const res = await postServiceOrderQuerySalesCode(); | |
36 | + const options = res.data?.map((item) => ({ | |
37 | + label: item.userName, | |
38 | + value: item.userName, | |
39 | + })); | |
40 | + setAffiliateSalesOptions(options || []); | |
41 | + } catch (error) { | |
42 | + console.error('Failed to fetch assign people options:', error); | |
43 | + } | |
44 | + }; | |
45 | + fetchAffiliateSalesOptions(); | |
46 | + }, []); | |
47 | + | |
29 | 48 | const optTypeEnum = { |
30 | 49 | add: { |
31 | 50 | text: '新增', |
... | ... | @@ -152,8 +171,6 @@ export default ({ optType, record, onFinish }) => { |
152 | 171 | console.log(value); |
153 | 172 | |
154 | 173 | if (value !== undefined || value !== null) { |
155 | - console.log('setProvince'); | |
156 | - | |
157 | 174 | setProvince(value); |
158 | 175 | } |
159 | 176 | }} |
... | ... | @@ -350,6 +367,15 @@ export default ({ optType, record, onFinish }) => { |
350 | 367 | label="课题组名称" |
351 | 368 | placeholder="请输入名称" |
352 | 369 | /> |
370 | + <Form.Item label="关联销售" name="affiliateSales"> | |
371 | + <ProFormSelect | |
372 | + name="affiliateSales" | |
373 | + options={affiliateSalesOptions} | |
374 | + placeholder="请选择关联销售" | |
375 | + rules={[{ required: true, message: '请选择关联销售' }]} | |
376 | + mode="multiple" | |
377 | + /> | |
378 | + </Form.Item> | |
353 | 379 | <ProFormText |
354 | 380 | name="department" |
355 | 381 | label="部门" | ... | ... |
src/pages/Client/Client/Components/ClientInformationModal.tsx
1 | 1 | import { RESPONSE_CODE } from '@/constants/enum'; |
2 | -import UploadC from '@/pages/Invoice/waitProcessRecord/components/UploadSingleImg'; | |
3 | 2 | import { |
4 | 3 | postAdminClientAddOrModifyClientComunicationInfo, |
5 | 4 | postAdminClientQueryClientPage, |
... | ... | @@ -10,19 +9,43 @@ import { |
10 | 9 | } from '@/services'; |
11 | 10 | import { enumToSelect } from '@/utils'; |
12 | 11 | import { |
12 | + FormListActionType, | |
13 | 13 | ModalForm, |
14 | + ProCard, | |
14 | 15 | ProFormDateTimePicker, |
16 | + ProFormList, | |
15 | 17 | ProFormSelect, |
16 | 18 | ProFormText, |
17 | 19 | ProFormTextArea, |
18 | 20 | ProFormUploadDragger, |
19 | 21 | } from '@ant-design/pro-components'; |
20 | -import { Button, Col, Form, Row, message } from 'antd'; | |
22 | +import { Button, Form, message } from 'antd'; | |
21 | 23 | import { RcFile } from 'antd/es/upload'; |
24 | +import { useRef } from 'react'; | |
22 | 25 | import './style.css'; |
23 | 26 | export default ({ data, type, reloadTable }) => { |
24 | 27 | const [form] = Form.useForm(); |
28 | + const actionRef = useRef< | |
29 | + FormListActionType<{ | |
30 | + name: string; | |
31 | + }> | |
32 | + >(); | |
33 | + const fileList: any = []; | |
25 | 34 | const onfinish = async (values) => { |
35 | + let list = values.ticketsList; | |
36 | + list = list.map((item) => { | |
37 | + let itemAnnexUrl = null; | |
38 | + // 尝试从 item.filePaths 中获取 annexUrl | |
39 | + if (item?.filePaths) { | |
40 | + itemAnnexUrl = item?.filePaths?.[0]?.response?.data?.[0] || null; | |
41 | + } else { | |
42 | + itemAnnexUrl = null; | |
43 | + } | |
44 | + item.annexUrl = itemAnnexUrl; | |
45 | + return item; | |
46 | + }); | |
47 | + | |
48 | + values.list = list; | |
26 | 49 | const resSearchId = await postAdminClientQueryClientPage({ |
27 | 50 | data: { |
28 | 51 | groupFilter: 'all', |
... | ... | @@ -54,25 +77,32 @@ export default ({ data, type, reloadTable }) => { |
54 | 77 | const editOnfinish = async (values) => { |
55 | 78 | // setEditClientId(data.clientId); |
56 | 79 | values.clientId = data.clientId; |
57 | - console.log(values, '5656editClientId'); | |
58 | - | |
59 | - // const resSearchId = await postAdminClientQueryClientPage({ | |
60 | - // data: { | |
61 | - // groupFilter: 'all', | |
62 | - // }, | |
63 | - // }); | |
64 | - // const matchingItem = resSearchId.data.data.find( | |
65 | - // (item) => item.id === values.name, | |
66 | - // ); | |
80 | + let list = values.ticketsList; | |
81 | + list = list.map((item, index) => { | |
82 | + // 尝试从 item.filePaths 中获取 annexUrl | |
83 | + const itemAnnexUrl = item?.filePaths?.[0]?.response?.data?.[0] || null; | |
67 | 84 | |
85 | + // 如果 itemAnnexUrl 为 null,则使用 data.ticketsList 对应的 annexUrl | |
86 | + if ( | |
87 | + itemAnnexUrl === null && | |
88 | + data.ticketsList[index]?.annexUrl && | |
89 | + index < data.ticketsList.length | |
90 | + ) { | |
91 | + item.annexUrl = data.ticketsList[index].annexUrl; // 确保对比中的 annesUrl 也是 null | |
92 | + } else { | |
93 | + item.annexUrl = itemAnnexUrl; // 否则,使用从 item.filePaths 中获取的值 | |
94 | + } | |
95 | + return item; | |
96 | + }); | |
97 | + values.list = list; | |
68 | 98 | const res = await postAdminClientAddOrModifyClientComunicationInfo({ |
69 | 99 | data: { |
70 | 100 | ...values, |
71 | 101 | // ticketsAttachments: form.getFieldValue("ticketsAttachments"), |
72 | - ticketsAttachments: | |
73 | - form.getFieldValue('ticketsAttachments') !== undefined | |
74 | - ? form.getFieldValue('ticketsAttachments') | |
75 | - : data?.ticketsAttachments, | |
102 | + // ticketsAttachments: | |
103 | + // form.getFieldValue('ticketsAttachments') !== undefined | |
104 | + // ? form.getFieldValue('ticketsAttachments') | |
105 | + // : data?.ticketsAttachments, | |
76 | 106 | // ticketsAttachments: data?.annexUrl, |
77 | 107 | }, |
78 | 108 | }); |
... | ... | @@ -150,18 +180,6 @@ export default ({ data, type, reloadTable }) => { |
150 | 180 | groupFilter: 'all', |
151 | 181 | }, |
152 | 182 | }); |
153 | - console.log(data, '5656data?.nameedit'); | |
154 | - // const namesArray = res.data.data.map((item) => item.name); | |
155 | - // const formattedObject = res.data.data.reduce((acc, name) => { | |
156 | - // acc[name] = name; // 将名称作为键和值 | |
157 | - // return acc; | |
158 | - // }, {}); | |
159 | - // console.log(namesArray, '5656namesArray'); | |
160 | - // const formattedObject = res.data.data.reduce((acc, item) => { | |
161 | - // acc[item.name] = item.name; // 使用 name 作为键,id 作为值 | |
162 | - // return acc; | |
163 | - // }, {}); | |
164 | - // return enumToSelect(formattedObject); | |
165 | 183 | const options = res.data.data.reduce((acc, item) => { |
166 | 184 | acc.push({ label: item.name, value: item.id }); // 使用 name 作为 label,id 作为 value |
167 | 185 | return acc; |
... | ... | @@ -180,7 +198,7 @@ export default ({ data, type, reloadTable }) => { |
180 | 198 | label="联系人" |
181 | 199 | width="sm" |
182 | 200 | placeholder="请输入联系人" |
183 | - initialValue={data?.content} | |
201 | + initialValue={data?.contact} | |
184 | 202 | readonly={optType[type].readOnly} |
185 | 203 | rules={[ |
186 | 204 | { |
... | ... | @@ -194,7 +212,7 @@ export default ({ data, type, reloadTable }) => { |
194 | 212 | label="联系电话" |
195 | 213 | width="sm" |
196 | 214 | placeholder="请输入联系电话" |
197 | - initialValue={data?.content} | |
215 | + initialValue={data?.contactPhone} | |
198 | 216 | readonly={optType[type].readOnly} |
199 | 217 | rules={[ |
200 | 218 | { |
... | ... | @@ -314,7 +332,168 @@ export default ({ data, type, reloadTable }) => { |
314 | 332 | hidden |
315 | 333 | ></ProFormText> |
316 | 334 | <ProFormText initialValue={data?.id} name="id" hidden></ProFormText> |
317 | - <div className="styled-text"> | |
335 | + <h2>工单指派</h2> | |
336 | + <ProFormList | |
337 | + // creatorButtonProps={{ disabled: optType('after-sales-check') }} | |
338 | + // deleteIconProps={!optType('after-sales-check')} | |
339 | + deleteIconProps={true} | |
340 | + name="ticketsList" | |
341 | + label="" | |
342 | + copyIconProps={false} //复制按钮不显示 | |
343 | + // initialValue={[ | |
344 | + // { | |
345 | + // ticketsType: '', | |
346 | + // ticketsDetail: '', | |
347 | + // assignPeople: '', | |
348 | + // ticketsAttachment: '', | |
349 | + // ticketsAttachments: '', | |
350 | + // }, | |
351 | + // ]} | |
352 | + initialValue={ | |
353 | + optType[type].title === '修改跟进记录' | |
354 | + ? data.ticketsList || [] | |
355 | + : [ | |
356 | + { | |
357 | + type: '', | |
358 | + detailText: '', | |
359 | + assignPeople: '', | |
360 | + annexUrl: '', | |
361 | + }, | |
362 | + ] | |
363 | + } | |
364 | + actionGuard={{ | |
365 | + beforeRemoveRow: async () => { | |
366 | + return new Promise((resolve) => { | |
367 | + let list = form.getFieldValue('ticketsList'); | |
368 | + if (list && list.length === 1) { | |
369 | + message.error('至少需要保留一个工单'); | |
370 | + resolve(false); | |
371 | + return; | |
372 | + } | |
373 | + resolve(true); | |
374 | + }); | |
375 | + }, | |
376 | + }} | |
377 | + itemRender={(doms, listMeta) => { | |
378 | + if (optType[type].title === '修改跟进记录') { | |
379 | + // let i = 0; | |
380 | + // // let defaultFileList = data.ticketsList?.annexUrl?.map((annex) => { | |
381 | + // // return { | |
382 | + // // uid: i++, | |
383 | + // // name: annex, | |
384 | + // // status: 'uploaded', | |
385 | + // // url: annex, | |
386 | + // // response: { data: [annex] }, | |
387 | + // // }; | |
388 | + // // }); | |
389 | + let defaultFileList = [ | |
390 | + { | |
391 | + uid: listMeta.index, | |
392 | + name: data.ticketsList[listMeta.index]?.annexUrl, | |
393 | + status: 'uploaded', | |
394 | + url: data.ticketsList[listMeta.index]?.annexUrl, | |
395 | + response: { | |
396 | + data: [data.ticketsList[listMeta.index]?.annexUrl], | |
397 | + }, | |
398 | + }, | |
399 | + ]; | |
400 | + fileList[listMeta.index] = defaultFileList; | |
401 | + } | |
402 | + let itemFileList = fileList[listMeta.index]; | |
403 | + return ( | |
404 | + <ProCard | |
405 | + bordered | |
406 | + extra={doms.action} | |
407 | + title={'工单指派' + (listMeta.index + 1)} | |
408 | + style={{ | |
409 | + marginBlockEnd: 8, | |
410 | + }} | |
411 | + > | |
412 | + {[ | |
413 | + <ProFormSelect | |
414 | + key={'type' + listMeta.index} | |
415 | + name="type" | |
416 | + label="工单类型" | |
417 | + width="sm" | |
418 | + placeholder="请输入工单类型" | |
419 | + readonly={optType[type].readOnly} | |
420 | + fieldProps={{ | |
421 | + labelInValue: false, | |
422 | + }} | |
423 | + // initialValue={data?.ticketsList?.type ? data?.ticketsList?.type + '' : null} | |
424 | + initialValue={ | |
425 | + data?.ticketsList ? data?.ticketsList?.type + '' : null | |
426 | + } | |
427 | + request={async () => { | |
428 | + return [ | |
429 | + { label: '问题', value: 'QUESTION' }, | |
430 | + { label: '需求', value: 'DEMAND' }, | |
431 | + { label: '建议', value: 'ADVICE' }, | |
432 | + ]; | |
433 | + }} | |
434 | + />, | |
435 | + <ProFormTextArea | |
436 | + key={'detailText' + listMeta.index} | |
437 | + name="detailText" | |
438 | + label="工单详情" | |
439 | + placeholder="请输入工单详情" | |
440 | + initialValue={data?.detailText ? data?.detailText + '' : null} | |
441 | + readonly={optType[type].readOnly} | |
442 | + ></ProFormTextArea>, | |
443 | + <ProFormSelect | |
444 | + key={'assignPeople' + listMeta.index} | |
445 | + name="assignPeople" | |
446 | + width="sm" | |
447 | + readonly={optType[type].readOnly} | |
448 | + fieldProps={{ | |
449 | + labelInValue: false, | |
450 | + }} | |
451 | + initialValue={ | |
452 | + data?.assignPeople ? data?.assignPeople + '' : null | |
453 | + } | |
454 | + label="指派人员" | |
455 | + request={async () => { | |
456 | + const res = await postOrderErpUsersListByPage({ | |
457 | + data: { | |
458 | + pageSize: 10000, | |
459 | + }, | |
460 | + }); | |
461 | + | |
462 | + const userOptions = res.data.records | |
463 | + ? res.data.records.map((user) => ({ | |
464 | + label: user.userName, // 或者使用其他需要的属性 | |
465 | + value: user.userName, // 作为value的字段 | |
466 | + })) | |
467 | + : []; | |
468 | + return userOptions; | |
469 | + }} | |
470 | + ></ProFormSelect>, | |
471 | + <> | |
472 | + <ProFormUploadDragger | |
473 | + key={'filePaths' + listMeta.index} | |
474 | + label="附件" | |
475 | + name="filePaths" | |
476 | + action="/api/service/order/fileProcess" | |
477 | + fieldProps={{ | |
478 | + headers: { | |
479 | + Authorization: localStorage.getItem('token'), | |
480 | + }, | |
481 | + // headers: { | |
482 | + // 'Content-Type': | |
483 | + // 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | |
484 | + // }, | |
485 | + itemFileList, | |
486 | + }} | |
487 | + max={1} | |
488 | + /> | |
489 | + </>, | |
490 | + ]} | |
491 | + </ProCard> | |
492 | + ); | |
493 | + }} | |
494 | + actionRef={actionRef} | |
495 | + ></ProFormList> | |
496 | + {/* <div className="styled-text"> | |
318 | 497 | <div className="vertical-line"></div> |
319 | 498 | <span className="text">工单指派</span> |
320 | 499 | </div> |
... | ... | @@ -342,7 +521,7 @@ export default ({ data, type, reloadTable }) => { |
342 | 521 | placeholder="请输入工单详情" |
343 | 522 | initialValue={data?.ticketsDetail ? data?.ticketsDetail + '' : null} |
344 | 523 | readonly={optType[type].readOnly} |
345 | - ></ProFormTextArea> | |
524 | + ></ProFormTextArea> */} | |
346 | 525 | {/* <ProFormUploadDragger |
347 | 526 | label="工单附件" |
348 | 527 | name="ticketsAttachment" |
... | ... | @@ -371,7 +550,7 @@ export default ({ data, type, reloadTable }) => { |
371 | 550 | }} |
372 | 551 | max={1} |
373 | 552 | /> */} |
374 | - <Row> | |
553 | + {/* <Row> | |
375 | 554 | <Col span={4}>附件:</Col> |
376 | 555 | <Col span={20}> |
377 | 556 | <UploadC |
... | ... | @@ -426,13 +605,13 @@ export default ({ data, type, reloadTable }) => { |
426 | 605 | |
427 | 606 | const userOptions = res.data.records |
428 | 607 | ? res.data.records.map((user) => ({ |
429 | - label: user.userName, // 或者使用其他需要的属性 | |
430 | - value: user.userName, // 作为value的字段 | |
431 | - })) | |
608 | + label: user.userName, // 或者使用其他需要的属性 | |
609 | + value: user.userName, // 作为value的字段 | |
610 | + })) | |
432 | 611 | : []; |
433 | 612 | return userOptions; |
434 | 613 | }} |
435 | - ></ProFormSelect> | |
614 | + ></ProFormSelect> */} | |
436 | 615 | </ModalForm> |
437 | 616 | ); |
438 | 617 | }; | ... | ... |
src/pages/Client/Client/Components/ClientModal.tsx
1 | 1 | import { RESPONSE_CODE } from '@/constants/enum'; |
2 | -import UploadC from '@/pages/Invoice/waitProcessRecord/components/UploadSingleImg'; | |
3 | 2 | import { |
4 | 3 | postAdminClientAddOrModifyClientComunicationInfo, |
5 | 4 | postAdminClientQueryClientPage, |
... | ... | @@ -10,74 +9,43 @@ import { |
10 | 9 | } from '@/services'; |
11 | 10 | import { enumToSelect } from '@/utils'; |
12 | 11 | import { |
12 | + FormListActionType, | |
13 | 13 | ModalForm, |
14 | + ProCard, | |
14 | 15 | ProFormDateTimePicker, |
16 | + ProFormList, | |
15 | 17 | ProFormSelect, |
16 | 18 | ProFormText, |
17 | 19 | ProFormTextArea, |
18 | 20 | ProFormUploadDragger, |
19 | 21 | } from '@ant-design/pro-components'; |
20 | -import { Button, Col, Form, Row, message } from 'antd'; | |
22 | +import { Button, Form, message } from 'antd'; | |
21 | 23 | import { RcFile } from 'antd/es/upload'; |
24 | +import { useRef } from 'react'; | |
22 | 25 | import './style.css'; |
23 | -// import { useRef, useState } from 'react'; | |
24 | 26 | export default ({ data, type, reloadTable }) => { |
25 | - // const initialItems = [ | |
26 | - // { label: 'Tab 1', children: 'Content of Tab 1', key: '1' }, | |
27 | - // ]; | |
28 | - // const [activeKey, setActiveKey] = useState(initialItems[0].key); | |
29 | - // const [items, setItems] = useState(initialItems); | |
30 | - // const newTabIndex = useRef(1); | |
31 | - | |
32 | - // const onChange = (newActiveKey: string) => { | |
33 | - // setActiveKey(newActiveKey); | |
34 | - // }; | |
35 | - | |
36 | - // const add = () => { | |
37 | - // // 生成新的标签名,格式为 'Tab {num}' | |
38 | - // const newTabLabel = `Tab ${newTabIndex.current + 1}`; | |
39 | - // // 增加索引,保证下次生成新的Tab名称时,num会递增 | |
40 | - // newTabIndex.current++; | |
41 | - // // 创建新的panes,追加新Tab | |
42 | - // const newActiveKey = `newTab${newTabIndex.current}`; | |
43 | - // const newPanes = [...items]; | |
44 | - // newPanes.push({ label: newTabLabel, children: 'Content of new Tab', key: newActiveKey }); | |
45 | - // setItems(newPanes); | |
46 | - // setActiveKey(newActiveKey); | |
47 | - // }; | |
48 | - | |
49 | - // const remove = (targetKey: TargetKey) => { | |
50 | - // let newActiveKey = activeKey; | |
51 | - // let lastIndex = -1; | |
52 | - // items.forEach((item, i) => { | |
53 | - // if (item.key === targetKey) { | |
54 | - // lastIndex = i - 1; | |
55 | - // } | |
56 | - // }); | |
57 | - // const newPanes = items.filter((item) => item.key !== targetKey); | |
58 | - // if (newPanes.length && newActiveKey === targetKey) { | |
59 | - // if (lastIndex >= 0) { | |
60 | - // newActiveKey = newPanes[lastIndex].key; | |
61 | - // } else { | |
62 | - // newActiveKey = newPanes[0].key; | |
63 | - // } | |
64 | - // } | |
65 | - // setItems(newPanes); | |
66 | - // setActiveKey(newActiveKey); | |
67 | - // }; | |
68 | - | |
69 | - // const onEdit = ( | |
70 | - // targetKey: React.MouseEvent | React.KeyboardEvent | string, | |
71 | - // action: 'add' | 'remove', | |
72 | - // ) => { | |
73 | - // if (action === 'add') { | |
74 | - // add(); | |
75 | - // } else { | |
76 | - // remove(targetKey); | |
77 | - // } | |
78 | - // }; | |
79 | 27 | const [form] = Form.useForm(); |
28 | + const actionRef = useRef< | |
29 | + FormListActionType<{ | |
30 | + name: string; | |
31 | + }> | |
32 | + >(); | |
33 | + const fileList: any = []; | |
80 | 34 | const onfinish = async (values) => { |
35 | + let list = values.list; | |
36 | + | |
37 | + list = list.map((item) => { | |
38 | + let itemAnnexUrl = null; | |
39 | + // 尝试从 item.filePaths 中获取 annexUrl | |
40 | + if (item?.filePaths) { | |
41 | + itemAnnexUrl = item?.filePaths?.[0]?.response?.data?.[0] || null; | |
42 | + } else { | |
43 | + itemAnnexUrl = null; | |
44 | + } | |
45 | + item.annexUrl = itemAnnexUrl; | |
46 | + return item; | |
47 | + }); | |
48 | + values.list = list; | |
81 | 49 | const res = await postAdminClientAddOrModifyClientComunicationInfo({ |
82 | 50 | data: { |
83 | 51 | ...values, |
... | ... | @@ -184,7 +152,7 @@ export default ({ data, type, reloadTable }) => { |
184 | 152 | label="联系人" |
185 | 153 | width="sm" |
186 | 154 | placeholder="请输入联系人" |
187 | - initialValue={data?.content} | |
155 | + initialValue={data?.contact} | |
188 | 156 | readonly={optType[type].readOnly} |
189 | 157 | rules={[ |
190 | 158 | { |
... | ... | @@ -198,7 +166,7 @@ export default ({ data, type, reloadTable }) => { |
198 | 166 | label="联系电话" |
199 | 167 | width="sm" |
200 | 168 | placeholder="请输入联系电话" |
201 | - initialValue={data?.content} | |
169 | + initialValue={data?.contactPhone} | |
202 | 170 | readonly={optType[type].readOnly} |
203 | 171 | rules={[ |
204 | 172 | { |
... | ... | @@ -318,132 +286,140 @@ export default ({ data, type, reloadTable }) => { |
318 | 286 | hidden |
319 | 287 | ></ProFormText> |
320 | 288 | <ProFormText initialValue={data?.id} name="id" hidden></ProFormText> |
321 | - {/* <Tabs | |
322 | - type="editable-card" | |
323 | - onChange={onChange} | |
324 | - activeKey={activeKey} | |
325 | - onEdit={onEdit} | |
326 | - items={items} | |
327 | - /> */} | |
328 | - <div className="styled-text"> | |
329 | - <div className="vertical-line"></div> | |
330 | - <span className="text">工单指派</span> | |
331 | - </div> | |
332 | - <ProFormSelect | |
333 | - name="ticketsType" | |
334 | - label="工单类型" | |
335 | - width="sm" | |
336 | - placeholder="请输入工单类型" | |
337 | - readonly={optType[type].readOnly} | |
338 | - fieldProps={{ | |
339 | - labelInValue: false, | |
340 | - }} | |
341 | - initialValue={data?.type ? data?.type + '' : null} | |
342 | - request={async () => { | |
343 | - return [ | |
344 | - { label: '问题', value: 'QUESTION' }, | |
345 | - { label: '需求', value: 'DEMAND' }, | |
346 | - { label: '建议', value: 'ADVICE' }, | |
347 | - ]; | |
348 | - }} | |
349 | - /> | |
350 | - <ProFormTextArea | |
351 | - name="ticketsDetail" | |
352 | - label="工单详情" | |
353 | - placeholder="请输入工单详情" | |
354 | - initialValue={data?.detailText ? data?.detailText + '' : null} | |
355 | - readonly={optType[type].readOnly} | |
356 | - ></ProFormTextArea> | |
357 | - <Row> | |
358 | - <Col span={4}>附件:</Col> | |
359 | - <Col span={20}> | |
360 | - <UploadC | |
361 | - onFilesChange={async (newFileList) => { | |
362 | - if (newFileList.length > 0) { | |
363 | - const urls = []; // 创建一个数组来存储所有的 URL | |
364 | - | |
365 | - for (const file of newFileList) { | |
366 | - const formData = new FormData(); | |
367 | - formData.append('file', file.originFileObj as RcFile); | |
368 | - | |
369 | - const res = await postOrderErpOrderStagesUpload({ | |
370 | - data: formData, | |
371 | - headers: { | |
372 | - 'Content-Type': | |
373 | - 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | |
374 | - }, | |
375 | - }); | |
376 | - | |
377 | - const url = res.data; // 获取响应中的 URL | |
378 | - urls.push(url); // 将每个 URL 追加到数组中 | |
379 | - } | |
380 | - | |
381 | - // 将所有 URL 使用 ',' 进行拼接 | |
382 | - const combinedUrl = urls.join(','); | |
383 | - form.setFieldValue('ticketsAttachments', combinedUrl); // 设置表单字段值为拼接后的 URL | |
384 | - } else { | |
385 | - form.setFieldValue('ticketsAttachments', null); // 如果没有文件,则清空 URL | |
289 | + <h2>工单指派</h2> | |
290 | + <ProFormList | |
291 | + // creatorButtonProps={{ disabled: optType('after-sales-check') }} | |
292 | + // deleteIconProps={!optType('after-sales-check')} | |
293 | + deleteIconProps={true} | |
294 | + name="list" | |
295 | + label="" | |
296 | + copyIconProps={false} //复制按钮不显示 | |
297 | + initialValue={[ | |
298 | + { | |
299 | + type: '', | |
300 | + detailText: '', | |
301 | + assignPeople: '', | |
302 | + annexUrl: '', | |
303 | + }, | |
304 | + ]} | |
305 | + actionGuard={{ | |
306 | + beforeRemoveRow: async () => { | |
307 | + return new Promise((resolve) => { | |
308 | + let list = form.getFieldValue('list'); | |
309 | + if (list && list.length === 1) { | |
310 | + message.error('至少需要保留一个工单'); | |
311 | + resolve(false); | |
312 | + return; | |
386 | 313 | } |
387 | - }} | |
388 | - ></UploadC> | |
389 | - </Col> | |
390 | - </Row> | |
391 | - {/* <ProFormUploadDragger | |
392 | - label="工单附件" | |
393 | - name="ticketsAttachment" | |
394 | - action="upload.do" | |
395 | - hidden={optType[type].readOnly} | |
396 | - onChange={(info) => { | |
397 | - const uploadFile = async ({ fileList: newFileList }) => { | |
398 | - if (newFileList.length > 0) { | |
399 | - const formData = new FormData(); | |
400 | - formData.append('file', newFileList[0].originFileObj as RcFile); | |
401 | - const res = await postOrderErpOrderStagesUpload({ | |
402 | - data: formData, | |
403 | - headers: { | |
404 | - 'Content-Type': | |
405 | - 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | |
406 | - }, | |
407 | - }); | |
408 | - const url = res.data; | |
409 | - console.log('ticketsAttachments' + JSON.stringify(url)); | |
410 | - form.setFieldValue('ticketsAttachments', url); | |
411 | - } else { | |
412 | - form.setFieldValue('ticketsAttachments', null); | |
413 | - } | |
414 | - }; | |
415 | - uploadFile(info); | |
416 | - }} | |
417 | - max={1} | |
418 | - /> */} | |
419 | - <a hidden={!optType[type].readOnly} href={data?.orderAttachment} download> | |
420 | - 下载附件 | |
421 | - </a> | |
422 | - <ProFormSelect | |
423 | - name="assignPeople" | |
424 | - width="sm" | |
425 | - readonly={optType[type].readOnly} | |
426 | - fieldProps={{ | |
427 | - labelInValue: false, | |
314 | + resolve(true); | |
315 | + }); | |
316 | + }, | |
428 | 317 | }} |
429 | - initialValue={data?.assignPeople ? data?.assignPeople + '' : null} | |
430 | - label="指派人员" | |
431 | - request={async () => { | |
432 | - const res = await postOrderErpUsersListByPage({ | |
433 | - data: { | |
434 | - pageSize: 10000, | |
435 | - }, | |
436 | - }); | |
318 | + itemRender={(doms, listMeta) => { | |
319 | + if (optType[type].modify || optType[type].add || optType[type].add2) { | |
320 | + let i = 0; | |
321 | + let defaultFileList = listMeta.record?.listAnnex?.map((annex) => { | |
322 | + return { | |
323 | + uid: i++, | |
324 | + name: annex, | |
325 | + status: 'uploaded', | |
326 | + url: annex, | |
327 | + response: { data: [annex] }, | |
328 | + }; | |
329 | + }); | |
330 | + fileList[listMeta.index] = defaultFileList; | |
331 | + } | |
332 | + let itemFileList = fileList[listMeta.index]; | |
333 | + return ( | |
334 | + <ProCard | |
335 | + bordered | |
336 | + extra={doms.action} | |
337 | + title={'工单指派' + (listMeta.index + 1)} | |
338 | + style={{ | |
339 | + marginBlockEnd: 8, | |
340 | + }} | |
341 | + > | |
342 | + {[ | |
343 | + <ProFormSelect | |
344 | + key={'type' + listMeta.index} | |
345 | + name="type" | |
346 | + label="工单类型" | |
347 | + width="sm" | |
348 | + placeholder="请输入工单类型" | |
349 | + readonly={optType[type].readOnly} | |
350 | + fieldProps={{ | |
351 | + labelInValue: false, | |
352 | + }} | |
353 | + initialValue={data?.type ? data?.type + '' : null} | |
354 | + request={async () => { | |
355 | + return [ | |
356 | + { label: '问题', value: 'QUESTION' }, | |
357 | + { label: '需求', value: 'DEMAND' }, | |
358 | + { label: '建议', value: 'ADVICE' }, | |
359 | + ]; | |
360 | + }} | |
361 | + />, | |
362 | + <ProFormTextArea | |
363 | + key={'detailText' + listMeta.index} | |
364 | + name="detailText" | |
365 | + label="工单详情" | |
366 | + placeholder="请输入工单详情" | |
367 | + initialValue={data?.detailText ? data?.detailText + '' : null} | |
368 | + readonly={optType[type].readOnly} | |
369 | + ></ProFormTextArea>, | |
370 | + <ProFormSelect | |
371 | + key={'assignPeople' + listMeta.index} | |
372 | + name="assignPeople" | |
373 | + width="sm" | |
374 | + readonly={optType[type].readOnly} | |
375 | + fieldProps={{ | |
376 | + labelInValue: false, | |
377 | + }} | |
378 | + initialValue={ | |
379 | + data?.assignPeople ? data?.assignPeople + '' : null | |
380 | + } | |
381 | + label="指派人员" | |
382 | + request={async () => { | |
383 | + const res = await postOrderErpUsersListByPage({ | |
384 | + data: { | |
385 | + pageSize: 10000, | |
386 | + }, | |
387 | + }); | |
437 | 388 | |
438 | - const userOptions = res.data.records | |
439 | - ? res.data.records.map((user) => ({ | |
440 | - label: user.userName, // 或者使用其他需要的属性 | |
441 | - value: user.userName, // 作为value的字段 | |
442 | - })) | |
443 | - : []; | |
444 | - return userOptions; | |
389 | + const userOptions = res.data.records | |
390 | + ? res.data.records.map((user) => ({ | |
391 | + label: user.userName, // 或者使用其他需要的属性 | |
392 | + value: user.userName, // 作为value的字段 | |
393 | + })) | |
394 | + : []; | |
395 | + return userOptions; | |
396 | + }} | |
397 | + ></ProFormSelect>, | |
398 | + <> | |
399 | + <ProFormUploadDragger | |
400 | + key={'filePaths' + listMeta.index} | |
401 | + label="附件" | |
402 | + name="filePaths" | |
403 | + action="/api/service/order/fileProcess" | |
404 | + fieldProps={{ | |
405 | + headers: { | |
406 | + Authorization: localStorage.getItem('token'), | |
407 | + }, | |
408 | + // headers: { | |
409 | + // 'Content-Type': | |
410 | + // 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | |
411 | + // }, | |
412 | + itemFileList, | |
413 | + }} | |
414 | + max={1} | |
415 | + /> | |
416 | + </>, | |
417 | + ]} | |
418 | + </ProCard> | |
419 | + ); | |
445 | 420 | }} |
446 | - ></ProFormSelect> | |
421 | + actionRef={actionRef} | |
422 | + ></ProFormList> | |
447 | 423 | </ModalForm> |
448 | 424 | ); |
449 | 425 | }; | ... | ... |
src/pages/Client/Client/Components/CommunicationHistoryModal.tsx
... | ... | @@ -138,6 +138,7 @@ export default ({ record }) => { |
138 | 138 | const [createByName, setCreateByName] = useState(''); // 创建人 |
139 | 139 | const [latestObject, setLatestObject] = useState(); // 最新跟进时间 |
140 | 140 | const [recordSave, setRecordSave] = useState(); //新增跟进 |
141 | + const [affiliateSales, setAffiliateSales] = useState([]); | |
141 | 142 | useEffect(() => { |
142 | 143 | const request = async () => { |
143 | 144 | const resShow = await postAdminClientQueryClientComunicationInfo({ |
... | ... | @@ -175,6 +176,7 @@ export default ({ record }) => { |
175 | 176 | setAddress(record.address); |
176 | 177 | setNotes(record.notes); |
177 | 178 | setCreateByName(record.createByName); |
179 | + setAffiliateSales(record.affiliateSales.join(',')); | |
178 | 180 | }; |
179 | 181 | request(); |
180 | 182 | }, []); |
... | ... | @@ -249,6 +251,11 @@ export default ({ record }) => { |
249 | 251 | label: '最新跟进时间', |
250 | 252 | children: latestObject, // 最新跟进时间 |
251 | 253 | }, |
254 | + { | |
255 | + key: '16', | |
256 | + label: '关联销售', | |
257 | + children: affiliateSales, // 创建人 | |
258 | + }, | |
252 | 259 | ]; |
253 | 260 | return ( |
254 | 261 | <ModalForm | ... | ... |
src/pages/Client/Client/Components/InformationHistoryModal.tsx
... | ... | @@ -27,10 +27,6 @@ export default ({ data, reloadTable }) => { |
27 | 27 | const [createTime, setCreateTime] = useState(null); // 创建时间 |
28 | 28 | const [attachments, setAttachments] = useState(); //附件 |
29 | 29 | const [attachmentsName, setAttachmentsName] = useState(''); // 附件名称 |
30 | - const [ticketsType, setTicketsType] = useState(''); // 附件名称 | |
31 | - const [ticketsDetail, setTicketsDetail] = useState(''); // 附件名称 | |
32 | - const [ticketsAttachment, setTicketsAttachment] = useState(''); // 附件名称 | |
33 | - const [assignPeople, setAssignPeople] = useState(''); // 附件名称 | |
34 | 30 | const [comment, setComment] = useState(''); // 客户评价 |
35 | 31 | |
36 | 32 | useEffect(() => { |
... | ... | @@ -56,10 +52,6 @@ export default ({ data, reloadTable }) => { |
56 | 52 | } |
57 | 53 | } |
58 | 54 | setComment(dataSearch.comment); |
59 | - setTicketsType(dataSearch.ticketsTypeText); | |
60 | - setTicketsDetail(dataSearch.ticketsDetail); | |
61 | - setTicketsAttachment(dataSearch.ticketsAttachments); | |
62 | - setAssignPeople(dataSearch.assignPeople); | |
63 | 55 | setDatetime(dataSearch.datetime); // 设置跟进日期 |
64 | 56 | // setDateRange(data.dateRange || []); // 设置跟进时间范围 |
65 | 57 | setCreateByName(dataSearch.createByName); // 设置跟进人员 |
... | ... | @@ -115,26 +107,6 @@ export default ({ data, reloadTable }) => { |
115 | 107 | }, |
116 | 108 | { |
117 | 109 | key: '8', |
118 | - label: '工单类型', | |
119 | - children: ticketsType, // 跟进状态 | |
120 | - }, | |
121 | - { | |
122 | - key: '9', | |
123 | - label: '工单详情', | |
124 | - children: ticketsDetail, // 跟进状态 | |
125 | - }, | |
126 | - // { | |
127 | - // key: '10', | |
128 | - // label: '工单附件', | |
129 | - // children: ticketsAttachment, // 跟进状态 | |
130 | - // }, | |
131 | - { | |
132 | - key: '10', | |
133 | - label: '指派人员', | |
134 | - children: assignPeople, // 跟进状态 | |
135 | - }, | |
136 | - { | |
137 | - key: '11', | |
138 | 110 | label: '客户评价', |
139 | 111 | children: comment, // 跟进状态 |
140 | 112 | }, |
... | ... | @@ -151,6 +123,40 @@ export default ({ data, reloadTable }) => { |
151 | 123 | actionRef?.current?.reload(); // 重新加载表格数据 |
152 | 124 | } |
153 | 125 | }; |
126 | + const TicketDescriptions = ({ data }) => { | |
127 | + return ( | |
128 | + <div> | |
129 | + {data.ticketsList && data.ticketsList.length > 0 ? ( | |
130 | + data.ticketsList.map((ticket, index) => ( | |
131 | + <div key={index} style={{ marginBottom: '20px' }}> | |
132 | + <Descriptions title={`工单 ${index + 1}`} column={1}> | |
133 | + <Descriptions.Item label="工单类型"> | |
134 | + {ticket.typeText} | |
135 | + </Descriptions.Item> | |
136 | + <Descriptions.Item label="工单详情"> | |
137 | + {ticket.detailText} | |
138 | + </Descriptions.Item> | |
139 | + <Descriptions.Item label="指派人员"> | |
140 | + {ticket.assignPeople} | |
141 | + </Descriptions.Item> | |
142 | + </Descriptions> | |
143 | + {ticket.annexUrl && ( | |
144 | + <a | |
145 | + href={ticket.annexUrl} | |
146 | + target="_blank" | |
147 | + rel="noopener noreferrer" | |
148 | + > | |
149 | + 下载工单附件 | |
150 | + </a> | |
151 | + )} | |
152 | + </div> | |
153 | + )) | |
154 | + ) : ( | |
155 | + <p></p> | |
156 | + )} | |
157 | + </div> | |
158 | + ); | |
159 | + }; | |
154 | 160 | return ( |
155 | 161 | <Space> |
156 | 162 | <ModalForm |
... | ... | @@ -215,11 +221,6 @@ export default ({ data, reloadTable }) => { |
215 | 221 | }} |
216 | 222 | > |
217 | 223 | <Descriptions items={items} column={1} /> |
218 | - {/* {attachmentsName && ( | |
219 | - <a href={attachments} download> | |
220 | - 附件:{attachmentsName} | |
221 | - </a> | |
222 | - )} */} | |
223 | 224 | {attachmentsName && ( |
224 | 225 | <div> |
225 | 226 | {attachmentsName.endsWith('.png') || |
... | ... | @@ -242,6 +243,12 @@ export default ({ data, reloadTable }) => { |
242 | 243 | )} |
243 | 244 | </div> |
244 | 245 | )} |
246 | + <TicketDescriptions data={data} /> | |
247 | + {/* {attachmentsName && ( | |
248 | + <a href={attachments} download> | |
249 | + 附件:{attachmentsName} | |
250 | + </a> | |
251 | + )} */} | |
245 | 252 | |
246 | 253 | <div></div> |
247 | 254 | {/* {ticketsAttachment && ( |
... | ... | @@ -271,12 +278,12 @@ export default ({ data, reloadTable }) => { |
271 | 278 | )} |
272 | 279 | </div> |
273 | 280 | )} */} |
274 | - {ticketsAttachment && ( | |
281 | + {/* {ticketsAttachment && ( | |
275 | 282 | <div> |
276 | 283 | {ticketsAttachment.split(',').map((ticketsAttachment, index) => ( |
277 | 284 | <div key={index}> |
278 | 285 | {ticketsAttachment.includes('jpg') || |
279 | - ticketsAttachment.includes('png') ? ( | |
286 | + ticketsAttachment.includes('png') ? ( | |
280 | 287 | <> |
281 | 288 | <img |
282 | 289 | src={ticketsAttachment} |
... | ... | @@ -292,7 +299,7 @@ export default ({ data, reloadTable }) => { |
292 | 299 | </div> |
293 | 300 | ))} |
294 | 301 | </div> |
295 | - )} | |
302 | + )} */} | |
296 | 303 | </ModalForm> |
297 | 304 | </Space> |
298 | 305 | ); | ... | ... |
src/pages/Client/Client/index.tsx
... | ... | @@ -105,6 +105,12 @@ const columns = [ |
105 | 105 | }, |
106 | 106 | }, |
107 | 107 | { |
108 | + title: '关联销售', | |
109 | + hideInSearch: true, | |
110 | + hideInTable: true, | |
111 | + dataIndex: 'affiliateSales', | |
112 | + }, | |
113 | + { | |
108 | 114 | title: '部门', |
109 | 115 | width: 150, |
110 | 116 | ellipsis: true, |
... | ... | @@ -296,46 +302,57 @@ const columns = [ |
296 | 302 | } |
297 | 303 | }; |
298 | 304 | return [ |
299 | - <CommunicationHistoryModal | |
300 | - key={'communicationHistory'} | |
301 | - record={record} | |
302 | - />, | |
303 | - <ClientDrawer | |
304 | - key={'detail'} | |
305 | - record={record} | |
306 | - optType={'detail'} | |
307 | - onFinish={() => { | |
308 | - action.reload(); | |
309 | - }} | |
310 | - ></ClientDrawer>, | |
311 | - <ClientModal | |
312 | - key={'add'} | |
313 | - data={record} | |
314 | - reloadTable={() => { | |
315 | - action?.reload(); | |
316 | - }} | |
317 | - type={'add'} | |
318 | - />, | |
319 | - <ClientDrawer | |
320 | - key={'edit'} | |
321 | - record={record} | |
322 | - optType={'edit'} | |
323 | - onFinish={() => { | |
324 | - action.reload(); | |
325 | - }} | |
326 | - ></ClientDrawer>, | |
327 | - // <a key={'delete'} onClick={handleDelete}> | |
328 | - // 删除 | |
329 | - // </a>, | |
330 | - <ButtonConfirm | |
331 | - key="delete" | |
332 | - className="p-0" | |
333 | - title={'删除该客户,客户下的跟进记录会一并删除'} | |
334 | - text="删除" | |
335 | - onConfirm={async () => { | |
336 | - handleDelete(); | |
337 | - }} | |
338 | - />, | |
305 | + record?.paths?.includes('DETAIL') && ( | |
306 | + <CommunicationHistoryModal | |
307 | + key={'communicationHistory'} | |
308 | + record={record} | |
309 | + /> | |
310 | + ), | |
311 | + | |
312 | + record?.paths?.includes('DETAIL') && ( | |
313 | + <ClientDrawer | |
314 | + key={'detail'} | |
315 | + record={record} | |
316 | + optType={'detail'} | |
317 | + onFinish={() => { | |
318 | + action.reload(); | |
319 | + }} | |
320 | + /> | |
321 | + ), | |
322 | + | |
323 | + record?.paths?.includes('DETAIL') && ( | |
324 | + <ClientModal | |
325 | + key={'add'} | |
326 | + data={record} | |
327 | + reloadTable={() => { | |
328 | + action?.reload(); | |
329 | + }} | |
330 | + type={'add'} | |
331 | + /> | |
332 | + ), | |
333 | + | |
334 | + record?.paths?.includes('EDIT') && ( | |
335 | + <ClientDrawer | |
336 | + key={'edit'} | |
337 | + record={record} | |
338 | + optType={'edit'} | |
339 | + onFinish={() => { | |
340 | + action.reload(); | |
341 | + }} | |
342 | + /> | |
343 | + ), | |
344 | + | |
345 | + record?.paths?.includes('DELETE') && ( | |
346 | + <ButtonConfirm | |
347 | + key="delete" | |
348 | + className="p-0" | |
349 | + title={'删除该客户,客户下的跟进记录会一并删除'} | |
350 | + text="删除" | |
351 | + onConfirm={async () => { | |
352 | + handleDelete(); | |
353 | + }} | |
354 | + /> | |
355 | + ), | |
339 | 356 | ]; |
340 | 357 | }, |
341 | 358 | }, | ... | ... |
src/pages/Client/FollowRecord/Components/ClientModal.tsx
1 | 1 | import { RESPONSE_CODE } from '@/constants/enum'; |
2 | -import UploadC from '@/pages/Invoice/waitProcessRecord/components/UploadSingleImg'; | |
3 | 2 | import { |
4 | 3 | postAdminClientAddOrModifyClientComunicationInfo, |
5 | 4 | postAdminClientQueryClientPage, |
... | ... | @@ -10,21 +9,43 @@ import { |
10 | 9 | } from '@/services'; |
11 | 10 | import { enumToSelect } from '@/utils'; |
12 | 11 | import { |
12 | + FormListActionType, | |
13 | 13 | ModalForm, |
14 | + ProCard, | |
14 | 15 | ProFormDateTimePicker, |
16 | + ProFormList, | |
15 | 17 | ProFormSelect, |
16 | 18 | ProFormText, |
17 | 19 | ProFormTextArea, |
18 | 20 | ProFormUploadDragger, |
19 | 21 | } from '@ant-design/pro-components'; |
20 | -import { Button, Col, Form, Row, message } from 'antd'; | |
22 | +import { Button, Form, message } from 'antd'; | |
21 | 23 | import { RcFile } from 'antd/es/upload'; |
22 | -import { useEffect } from 'react'; | |
24 | +import { useEffect, useRef } from 'react'; | |
23 | 25 | import './style.css'; |
24 | 26 | export default ({ data, type, reloadTable }) => { |
25 | 27 | useEffect(() => {}); |
26 | 28 | const [form] = Form.useForm(); |
29 | + const actionRef = useRef< | |
30 | + FormListActionType<{ | |
31 | + name: string; | |
32 | + }> | |
33 | + >(); | |
34 | + const fileList: any = []; | |
27 | 35 | const onfinish = async (values) => { |
36 | + let list = values.ticketsList; | |
37 | + list = list.map((item) => { | |
38 | + let itemAnnexUrl = null; | |
39 | + // 尝试从 item.filePaths 中获取 annexUrl | |
40 | + if (item?.filePaths) { | |
41 | + itemAnnexUrl = item?.filePaths?.[0]?.response?.data?.[0] || null; | |
42 | + } else { | |
43 | + itemAnnexUrl = null; | |
44 | + } | |
45 | + item.annexUrl = itemAnnexUrl; | |
46 | + return item; | |
47 | + }); | |
48 | + values.list = list; | |
28 | 49 | const resSearchId = await postAdminClientQueryClientPage({ |
29 | 50 | data: { |
30 | 51 | groupFilter: 'all', |
... | ... | @@ -43,7 +64,7 @@ export default ({ data, type, reloadTable }) => { |
43 | 64 | const res = await postAdminClientAddOrModifyClientComunicationInfo({ |
44 | 65 | data: { |
45 | 66 | ...values, |
46 | - ticketsAttachments: form.getFieldValue('ticketsAttachments'), | |
67 | + // ticketsAttachments: form.getFieldValue('ticketsAttachments'), | |
47 | 68 | clientId: matchedId, |
48 | 69 | }, |
49 | 70 | }); |
... | ... | @@ -58,24 +79,35 @@ export default ({ data, type, reloadTable }) => { |
58 | 79 | const editOnfinish = async (values) => { |
59 | 80 | // setEditClientId(data.clientId); |
60 | 81 | values.clientId = data.clientId; |
61 | - | |
62 | - // const resSearchId = await postAdminClientQueryClientPage({ | |
63 | - // data: { | |
64 | - // groupFilter: 'all', | |
65 | - // }, | |
82 | + let list = values.ticketsList; | |
83 | + // list = list.map((item) => { | |
84 | + // // item.annexUrl = item.filePaths?.map((file) => { | |
85 | + // // return { url: file.response.data[0] }; | |
86 | + // // }); | |
87 | + // // item.annexUrl = item?.filePaths[0].response?.data[0]; | |
88 | + // item.annexUrl = item?.filePaths?.[0]?.response?.data?.[0] || null; // 使用 null 或默认值 | |
89 | + // return item; | |
66 | 90 | // }); |
67 | - // const matchingItem = resSearchId.data.data.find( | |
68 | - // (item) => item.id === values.name, | |
69 | - // ); | |
91 | + list = list.map((item, index) => { | |
92 | + // 尝试从 item.filePaths 中获取 annexUrl | |
93 | + const itemAnnexUrl = item?.filePaths?.[0]?.response?.data?.[0] || null; | |
94 | + | |
95 | + // 如果 itemAnnexUrl 为 null,则使用 data.ticketsList 对应的 annexUrl | |
96 | + if ( | |
97 | + itemAnnexUrl === null && | |
98 | + data.ticketsList[index]?.annexUrl && | |
99 | + index < data.ticketsList.length | |
100 | + ) { | |
101 | + item.annexUrl = data.ticketsList[index].annexUrl; // 确保对比中的 annesUrl 也是 null | |
102 | + } else { | |
103 | + item.annexUrl = itemAnnexUrl; // 否则,使用从 item.filePaths 中获取的值 | |
104 | + } | |
105 | + return item; | |
106 | + }); | |
107 | + values.list = list; | |
70 | 108 | const res = await postAdminClientAddOrModifyClientComunicationInfo({ |
71 | 109 | data: { |
72 | 110 | ...values, |
73 | - // ticketsAttachments: form.getFieldValue("ticketsAttachments"), | |
74 | - ticketsAttachments: | |
75 | - form.getFieldValue('ticketsAttachments') !== undefined | |
76 | - ? form.getFieldValue('ticketsAttachments') | |
77 | - : data?.ticketsAttachments, | |
78 | - // ticketsAttachments: data?.annexUrl, | |
79 | 111 | }, |
80 | 112 | }); |
81 | 113 | if (res.result === RESPONSE_CODE.SUCCESS) { |
... | ... | @@ -315,7 +347,168 @@ export default ({ data, type, reloadTable }) => { |
315 | 347 | hidden |
316 | 348 | ></ProFormText> |
317 | 349 | <ProFormText initialValue={data?.id} name="id" hidden></ProFormText> |
318 | - <div className="styled-text"> | |
350 | + <h2>工单指派</h2> | |
351 | + <ProFormList | |
352 | + // creatorButtonProps={{ disabled: optType('after-sales-check') }} | |
353 | + // deleteIconProps={!optType('after-sales-check')} | |
354 | + deleteIconProps={true} | |
355 | + name="ticketsList" | |
356 | + label="" | |
357 | + copyIconProps={false} //复制按钮不显示 | |
358 | + // initialValue={[ | |
359 | + // { | |
360 | + // ticketsType: '', | |
361 | + // ticketsDetail: '', | |
362 | + // assignPeople: '', | |
363 | + // ticketsAttachment: '', | |
364 | + // ticketsAttachments: '', | |
365 | + // }, | |
366 | + // ]} | |
367 | + initialValue={ | |
368 | + optType[type].title === '修改跟进记录' | |
369 | + ? data.ticketsList || [] | |
370 | + : [ | |
371 | + { | |
372 | + type: '', | |
373 | + detailText: '', | |
374 | + assignPeople: '', | |
375 | + annexUrl: '', | |
376 | + }, | |
377 | + ] | |
378 | + } | |
379 | + actionGuard={{ | |
380 | + beforeRemoveRow: async () => { | |
381 | + return new Promise((resolve) => { | |
382 | + let list = form.getFieldValue('ticketsList'); | |
383 | + if (list && list.length === 1) { | |
384 | + message.error('至少需要保留一个工单'); | |
385 | + resolve(false); | |
386 | + return; | |
387 | + } | |
388 | + resolve(true); | |
389 | + }); | |
390 | + }, | |
391 | + }} | |
392 | + itemRender={(doms, listMeta) => { | |
393 | + if (optType[type].title === '修改跟进记录') { | |
394 | + // let i = 0; | |
395 | + // // let defaultFileList = data.ticketsList?.annexUrl?.map((annex) => { | |
396 | + // // return { | |
397 | + // // uid: i++, | |
398 | + // // name: annex, | |
399 | + // // status: 'uploaded', | |
400 | + // // url: annex, | |
401 | + // // response: { data: [annex] }, | |
402 | + // // }; | |
403 | + // // }); | |
404 | + let defaultFileList = [ | |
405 | + { | |
406 | + uid: listMeta.index, | |
407 | + name: data.ticketsList[listMeta.index]?.annexUrl, | |
408 | + status: 'uploaded', | |
409 | + url: data.ticketsList[listMeta.index]?.annexUrl, | |
410 | + response: { | |
411 | + data: [data.ticketsList[listMeta.index]?.annexUrl], | |
412 | + }, | |
413 | + }, | |
414 | + ]; | |
415 | + fileList[listMeta.index] = defaultFileList; | |
416 | + } | |
417 | + let itemFileList = fileList[listMeta.index]; | |
418 | + return ( | |
419 | + <ProCard | |
420 | + bordered | |
421 | + extra={doms.action} | |
422 | + title={'工单指派' + (listMeta.index + 1)} | |
423 | + style={{ | |
424 | + marginBlockEnd: 8, | |
425 | + }} | |
426 | + > | |
427 | + {[ | |
428 | + <ProFormSelect | |
429 | + key={'type' + listMeta.index} | |
430 | + name="type" | |
431 | + label="工单类型" | |
432 | + width="sm" | |
433 | + placeholder="请输入工单类型" | |
434 | + readonly={optType[type].readOnly} | |
435 | + fieldProps={{ | |
436 | + labelInValue: false, | |
437 | + }} | |
438 | + // initialValue={data?.ticketsList?.type ? data?.ticketsList?.type + '' : null} | |
439 | + initialValue={ | |
440 | + data?.ticketsList ? data?.ticketsList?.type + '' : null | |
441 | + } | |
442 | + request={async () => { | |
443 | + return [ | |
444 | + { label: '问题', value: 'QUESTION' }, | |
445 | + { label: '需求', value: 'DEMAND' }, | |
446 | + { label: '建议', value: 'ADVICE' }, | |
447 | + ]; | |
448 | + }} | |
449 | + />, | |
450 | + <ProFormTextArea | |
451 | + key={'detailText' + listMeta.index} | |
452 | + name="detailText" | |
453 | + label="工单详情" | |
454 | + placeholder="请输入工单详情" | |
455 | + initialValue={data?.detailText ? data?.detailText + '' : null} | |
456 | + readonly={optType[type].readOnly} | |
457 | + ></ProFormTextArea>, | |
458 | + <ProFormSelect | |
459 | + key={'assignPeople' + listMeta.index} | |
460 | + name="assignPeople" | |
461 | + width="sm" | |
462 | + readonly={optType[type].readOnly} | |
463 | + fieldProps={{ | |
464 | + labelInValue: false, | |
465 | + }} | |
466 | + initialValue={ | |
467 | + data?.assignPeople ? data?.assignPeople + '' : null | |
468 | + } | |
469 | + label="指派人员" | |
470 | + request={async () => { | |
471 | + const res = await postOrderErpUsersListByPage({ | |
472 | + data: { | |
473 | + pageSize: 10000, | |
474 | + }, | |
475 | + }); | |
476 | + | |
477 | + const userOptions = res.data.records | |
478 | + ? res.data.records.map((user) => ({ | |
479 | + label: user.userName, // 或者使用其他需要的属性 | |
480 | + value: user.userName, // 作为value的字段 | |
481 | + })) | |
482 | + : []; | |
483 | + return userOptions; | |
484 | + }} | |
485 | + ></ProFormSelect>, | |
486 | + <> | |
487 | + <ProFormUploadDragger | |
488 | + key={'filePaths' + listMeta.index} | |
489 | + label="附件" | |
490 | + name="filePaths" | |
491 | + action="/api/service/order/fileProcess" | |
492 | + fieldProps={{ | |
493 | + headers: { | |
494 | + Authorization: localStorage.getItem('token'), | |
495 | + }, | |
496 | + // headers: { | |
497 | + // 'Content-Type': | |
498 | + // 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | |
499 | + // }, | |
500 | + itemFileList, | |
501 | + }} | |
502 | + max={1} | |
503 | + /> | |
504 | + </>, | |
505 | + ]} | |
506 | + </ProCard> | |
507 | + ); | |
508 | + }} | |
509 | + actionRef={actionRef} | |
510 | + ></ProFormList> | |
511 | + {/* <div className="styled-text"> | |
319 | 512 | <div className="vertical-line"></div> |
320 | 513 | <span className="text">工单指派</span> |
321 | 514 | </div> |
... | ... | @@ -348,7 +541,7 @@ export default ({ data, type, reloadTable }) => { |
348 | 541 | }} |
349 | 542 | initialValue={data?.ticketsDetail ? data?.ticketsDetail + '' : null} |
350 | 543 | readonly={optType[type].readOnly} |
351 | - ></ProFormTextArea> | |
544 | + ></ProFormTextArea> */} | |
352 | 545 | {/* <ProFormUploadDragger |
353 | 546 | label="工单附件" |
354 | 547 | name="ticketsAttachment" |
... | ... | @@ -377,7 +570,7 @@ export default ({ data, type, reloadTable }) => { |
377 | 570 | }} |
378 | 571 | max={1} |
379 | 572 | /> */} |
380 | - <Row> | |
573 | + {/* <Row> | |
381 | 574 | <Col span={4}>附件:</Col> |
382 | 575 | <Col span={20}> |
383 | 576 | <UploadC |
... | ... | @@ -416,7 +609,6 @@ export default ({ data, type, reloadTable }) => { |
416 | 609 | </Col> |
417 | 610 | </Row> |
418 | 611 | <a hidden={!optType[type].readOnly} href={data?.orderAttachment} download> |
419 | - {/* <a href={data?.annexUrl} download> */} | |
420 | 612 | 下载附件 |
421 | 613 | </a> |
422 | 614 | <ProFormSelect |
... | ... | @@ -443,7 +635,7 @@ export default ({ data, type, reloadTable }) => { |
443 | 635 | : []; |
444 | 636 | return userOptions; |
445 | 637 | }} |
446 | - ></ProFormSelect> | |
638 | + ></ProFormSelect> */} | |
447 | 639 | </ModalForm> |
448 | 640 | ); |
449 | 641 | }; | ... | ... |
src/pages/Client/FollowRecord/Components/CommunicationHistoryModal.tsx
... | ... | @@ -15,26 +15,15 @@ export default ({ data, reloadTable }) => { |
15 | 15 | const [datetime, setDatetime] = useState(); // 跟进日期 |
16 | 16 | const [createByName, setCreateByName] = useState(''); // 跟进人员 |
17 | 17 | const [clientName, setClientName] = useState(''); // 客户名称 |
18 | - // const [clientAddress, setClientAddress] = useState(''); // 客户地址 | |
19 | 18 | const [way, setWay] = useState(); // 跟进方式 |
20 | 19 | const [tradeStatusText, setTradeStatusText] = useState(); // 状态 |
21 | - // const [clientNameLike, setClientNameLike] = useState(''); // 客户名称模糊查询 | |
22 | - // const [clientAddressLike, setClientAddressLike] = useState(''); // 客户地址模糊查询 | |
23 | - // const [tradeStatus, setTradeStatus] = useState(''); // 客户状态 | |
24 | - // const [tradeStatusLike, setTradeStatusLike] = useState(''); // 客户状态模糊查询 | |
25 | 20 | const [content, setContent] = useState(''); // 跟进详情 |
26 | 21 | const [createTime, setCreateTime] = useState(null); // 创建时间 |
27 | 22 | const [attachments, setAttachments] = useState(); //附件 |
28 | 23 | const [attachmentsName, setAttachmentsName] = useState(''); // 附件名称 |
29 | - const [ticketsType, setTicketsType] = useState(''); // 附件名称 | |
30 | - const [ticketsDetail, setTicketsDetail] = useState(''); // 附件名称 | |
31 | - const [ticketsAttachment, setTicketsAttachment] = useState(); // 附件名称 | |
32 | - // const [ticketsAttachmentName, setTicketsAttachmentName] = useState(''); // 附件名称 | |
33 | 24 | const [comment, setComment] = useState(''); // 客户评价 |
34 | - const [assignPeople, setAssignPeople] = useState(''); // 附件名称 | |
35 | 25 | useEffect(() => { |
36 | 26 | const request = async () => { |
37 | - console.log(data, '5656datatatatata'); | |
38 | 27 | const res = await postAdminClientQueryClientComunicationInfo({ |
39 | 28 | data: { |
40 | 29 | id: data.id, |
... | ... | @@ -82,10 +71,6 @@ export default ({ data, reloadTable }) => { |
82 | 71 | // } |
83 | 72 | // } |
84 | 73 | setComment(dataSearch.comment); |
85 | - setTicketsType(dataSearch.ticketsTypeText); | |
86 | - setTicketsDetail(dataSearch.ticketsDetail); | |
87 | - setTicketsAttachment(dataSearch.ticketsAttachments); | |
88 | - setAssignPeople(dataSearch.assignPeople); | |
89 | 74 | setComment(dataSearch.comment); |
90 | 75 | setDatetime(dataSearch.datetime); // 设置跟进日期 |
91 | 76 | // setDateRange(data.dateRange || []); // 设置跟进时间范围 |
... | ... | @@ -142,29 +127,24 @@ export default ({ data, reloadTable }) => { |
142 | 127 | }, |
143 | 128 | { |
144 | 129 | key: '8', |
145 | - label: '工单类型', | |
146 | - children: ticketsType, // 跟进状态 | |
147 | - }, | |
148 | - { | |
149 | - key: '9', | |
150 | - label: '工单详情', | |
151 | - children: ticketsDetail, // 跟进状态 | |
152 | - }, | |
153 | - // { | |
154 | - // key: '12', | |
155 | - // label: '工单附件', | |
156 | - // children: ticketsAttachment, // 跟进状态 | |
157 | - // }, | |
158 | - { | |
159 | - key: '10', | |
160 | - label: '指派人员', | |
161 | - children: assignPeople, // 跟进状态 | |
162 | - }, | |
163 | - { | |
164 | - key: '11', | |
165 | 130 | label: '客户评价', |
166 | 131 | children: comment, // 跟进状态 |
167 | 132 | }, |
133 | + // { | |
134 | + // key: '9', | |
135 | + // label: '工单类型', | |
136 | + // children: ticketsType, // 跟进状态 | |
137 | + // }, | |
138 | + // { | |
139 | + // key: '10', | |
140 | + // label: '工单详情', | |
141 | + // children: ticketsDetail, // 跟进状态 | |
142 | + // }, | |
143 | + // { | |
144 | + // key: '11', | |
145 | + // label: '指派人员', | |
146 | + // children: assignPeople, // 跟进状态 | |
147 | + // }, | |
168 | 148 | ]; |
169 | 149 | const handleDelete = async () => { |
170 | 150 | // 调用删除接口 |
... | ... | @@ -178,6 +158,40 @@ export default ({ data, reloadTable }) => { |
178 | 158 | actionRef?.current?.reload(); // 重新加载表格数据 |
179 | 159 | } |
180 | 160 | }; |
161 | + const TicketDescriptions = ({ data }) => { | |
162 | + return ( | |
163 | + <div> | |
164 | + {data.ticketsList && data.ticketsList.length > 0 ? ( | |
165 | + data.ticketsList.map((ticket, index) => ( | |
166 | + <div key={index} style={{ marginBottom: '20px' }}> | |
167 | + <Descriptions title={`工单 ${index + 1}`} column={1}> | |
168 | + <Descriptions.Item label="工单类型"> | |
169 | + {ticket.typeText} | |
170 | + </Descriptions.Item> | |
171 | + <Descriptions.Item label="工单详情"> | |
172 | + {ticket.detailText} | |
173 | + </Descriptions.Item> | |
174 | + <Descriptions.Item label="指派人员"> | |
175 | + {ticket.assignPeople} | |
176 | + </Descriptions.Item> | |
177 | + </Descriptions> | |
178 | + {ticket.annexUrl && ( | |
179 | + <a | |
180 | + href={ticket.annexUrl} | |
181 | + target="_blank" | |
182 | + rel="noopener noreferrer" | |
183 | + > | |
184 | + 下载工单附件 | |
185 | + </a> | |
186 | + )} | |
187 | + </div> | |
188 | + )) | |
189 | + ) : ( | |
190 | + <p></p> | |
191 | + )} | |
192 | + </div> | |
193 | + ); | |
194 | + }; | |
181 | 195 | return ( |
182 | 196 | <Space> |
183 | 197 | <ModalForm |
... | ... | @@ -242,17 +256,6 @@ export default ({ data, reloadTable }) => { |
242 | 256 | }} |
243 | 257 | > |
244 | 258 | <Descriptions items={items} column={1} /> |
245 | - {/* {attachmentsName && ( | |
246 | - <a href={attachments} download> | |
247 | - 附件:{attachmentsName} | |
248 | - </a> | |
249 | - )} | |
250 | - <div></div> | |
251 | - {ticketsAttachment && ( | |
252 | - <a href={ticketsAttachment} download> | |
253 | - 工单附件:{ticketsAttachment} | |
254 | - </a> | |
255 | - )} */} | |
256 | 259 | {attachmentsName && ( |
257 | 260 | <div> |
258 | 261 | {attachmentsName.endsWith('.png') || |
... | ... | @@ -275,6 +278,18 @@ export default ({ data, reloadTable }) => { |
275 | 278 | )} |
276 | 279 | </div> |
277 | 280 | )} |
281 | + <TicketDescriptions data={data} /> | |
282 | + {/* {attachmentsName && ( | |
283 | + <a href={attachments} download> | |
284 | + 附件:{attachmentsName} | |
285 | + </a> | |
286 | + )} | |
287 | + <div></div> | |
288 | + {ticketsAttachment && ( | |
289 | + <a href={ticketsAttachment} download> | |
290 | + 工单附件:{ticketsAttachment} | |
291 | + </a> | |
292 | + )} */} | |
278 | 293 | |
279 | 294 | <div></div> |
280 | 295 | {/* {ticketsAttachment && ( |
... | ... | @@ -304,28 +319,6 @@ export default ({ data, reloadTable }) => { |
304 | 319 | )} |
305 | 320 | </div> |
306 | 321 | )} */} |
307 | - {ticketsAttachment && ( | |
308 | - <div> | |
309 | - {ticketsAttachment.split(',').map((ticketsAttachment, index) => ( | |
310 | - <div key={index}> | |
311 | - {ticketsAttachment.includes('jpg') || | |
312 | - ticketsAttachment.includes('png') ? ( | |
313 | - <> | |
314 | - <img | |
315 | - src={ticketsAttachment} | |
316 | - alt={`附件 ${index + 1}`} | |
317 | - style={{ maxWidth: '300px', height: 'auto' }} | |
318 | - /> | |
319 | - <div></div> | |
320 | - </> | |
321 | - ) : null} | |
322 | - <a href={ticketsAttachment} download> | |
323 | - 工单附件:{ticketsAttachment} | |
324 | - </a> | |
325 | - </div> | |
326 | - ))} | |
327 | - </div> | |
328 | - )} | |
329 | 322 | </ModalForm> |
330 | 323 | </Space> |
331 | 324 | ); | ... | ... |
src/pages/Client/FollowRecord/index.tsx
... | ... | @@ -23,7 +23,6 @@ export default () => { |
23 | 23 | |
24 | 24 | // 更新 refreshKey,强制刷新 CommunicationHistoryModal |
25 | 25 | setRefreshKey((prevKey) => prevKey + 1); |
26 | - console.log('5656refresh'); | |
27 | 26 | }; |
28 | 27 | //biaoji |
29 | 28 | const columns = [ |
... | ... | @@ -247,7 +246,6 @@ export default () => { |
247 | 246 | data={record} |
248 | 247 | // reloadTable={() => { |
249 | 248 | // actionRef.current.reload(); |
250 | - // console.log('5656flush'); | |
251 | 249 | // }} |
252 | 250 | reloadTable={reload} |
253 | 251 | />, | ... | ... |
src/pages/Order/FeedBack/AfterSalesDrawer.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { postServiceOrderApplyAfterSales } from '@/services'; | |
3 | +import { enumToSelect } from '@/utils'; | |
4 | +import { | |
5 | + DrawerForm, | |
6 | + ProFormDigit, | |
7 | + ProFormSelect, | |
8 | + ProFormTextArea, | |
9 | + ProFormUploadDragger, | |
10 | +} from '@ant-design/pro-components'; | |
11 | +import { Form, message } from 'antd'; | |
12 | +import { AFTE_SALES_PLAN_OPTIONS } from '../constant'; | |
13 | +export default ({ setVisible, mainOrder, subOrders, onClose }) => { | |
14 | + let subOrderIds = subOrders?.map((item: { id: any }) => { | |
15 | + return item.id; | |
16 | + }); | |
17 | + | |
18 | + let mainOrderId = mainOrder.id; | |
19 | + const [form] = Form.useForm<{ | |
20 | + afterSalesNotes: string; | |
21 | + afterSalesPlan: string; | |
22 | + ids: []; | |
23 | + totalPayment: number; | |
24 | + filePaths: any[]; | |
25 | + }>(); | |
26 | + | |
27 | + return ( | |
28 | + <DrawerForm<{ | |
29 | + afterSalesNotes: string; | |
30 | + afterSalesPlan: string; | |
31 | + subOrderIds: []; | |
32 | + totalPayment: number; | |
33 | + mainId: number; | |
34 | + filePaths: any[]; | |
35 | + }> | |
36 | + title="申请售后" | |
37 | + open | |
38 | + resize={{ | |
39 | + onResize() { | |
40 | + console.log('resize!'); | |
41 | + }, | |
42 | + maxWidth: window.innerWidth * 0.8, | |
43 | + minWidth: 500, | |
44 | + }} | |
45 | + form={form} | |
46 | + autoFocusFirstInput | |
47 | + drawerProps={{ | |
48 | + destroyOnClose: true, | |
49 | + onClose: () => { | |
50 | + setVisible(false); | |
51 | + }, | |
52 | + }} | |
53 | + onFinish={async (values) => { | |
54 | + values.subOrderIds = subOrderIds; | |
55 | + values.mainId = mainOrderId; | |
56 | + values.filePaths = values.filePaths?.map((file) => { | |
57 | + return { url: file.response.data[0] }; | |
58 | + }); | |
59 | + let res = await postServiceOrderApplyAfterSales({ data: values }); | |
60 | + if (res?.result === RESPONSE_CODE.SUCCESS) { | |
61 | + message.success(res.message); | |
62 | + onClose(); | |
63 | + } | |
64 | + }} | |
65 | + > | |
66 | + <ProFormSelect | |
67 | + key="key" | |
68 | + label="售后方案" | |
69 | + width="lg" | |
70 | + showSearch | |
71 | + name="afterSalesPlan" | |
72 | + options={enumToSelect(AFTE_SALES_PLAN_OPTIONS)} | |
73 | + placeholder="请搜索" | |
74 | + rules={[{ required: true, message: '售后方案必填' }]} | |
75 | + ></ProFormSelect> | |
76 | + <ProFormDigit | |
77 | + width="lg" | |
78 | + name="totalPayment" | |
79 | + label="总金额调整" | |
80 | + min={0} | |
81 | + initialValue={mainOrder.totalPayment} | |
82 | + rules={[{ required: true, message: '总金额必填' }]} | |
83 | + /> | |
84 | + <ProFormTextArea | |
85 | + width="lg" | |
86 | + label="售后原因" | |
87 | + name="afterSalesNotes" | |
88 | + rules={[{ required: true, message: '售后原因必填' }]} | |
89 | + /> | |
90 | + <ProFormUploadDragger | |
91 | + key="filePaths" | |
92 | + label="附件" | |
93 | + name="filePaths" | |
94 | + action="/api/service/order/fileProcess" | |
95 | + fieldProps={{ | |
96 | + headers: { Authorization: localStorage.getItem('token') }, | |
97 | + }} | |
98 | + /> | |
99 | + </DrawerForm> | |
100 | + ); | |
101 | +}; | ... | ... |
src/pages/Order/FeedBack/ApplyForInvoicingModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { postServiceOrderApplyInvoicing } from '@/services'; | |
3 | +import { enumToSelect, getAliYunOSSFileNameFromUrl } from '@/utils'; | |
4 | +import { | |
5 | + ModalForm, | |
6 | + ProFormSelect, | |
7 | + ProFormText, | |
8 | + ProFormTextArea, | |
9 | + ProFormUploadDragger, | |
10 | +} from '@ant-design/pro-components'; | |
11 | +import { Form, message } from 'antd'; | |
12 | +import { useEffect, useState } from 'react'; | |
13 | +import { PAYEE_OPTIONS } from '../constant'; | |
14 | +export default ({ | |
15 | + setCheckVisible, | |
16 | + isEdit, | |
17 | + subOrders, | |
18 | + isMainOrder, | |
19 | + totalPayment, | |
20 | + onClose, | |
21 | +}) => { | |
22 | + const [isUrgent, setIsUrgent] = useState(''); | |
23 | + let sumPrice = totalPayment; | |
24 | + | |
25 | + let ids = subOrders?.map((item) => { | |
26 | + return item.id; | |
27 | + }); | |
28 | + | |
29 | + let mainIdSet = new Set(); | |
30 | + subOrders?.forEach((item: { mainOrderId: unknown }) => { | |
31 | + mainIdSet.add(item.mainOrderId); | |
32 | + }); | |
33 | + | |
34 | + let mainIds = Array.from(mainIdSet).join(','); | |
35 | + | |
36 | + let newListAnnex = []; | |
37 | + | |
38 | + //回显,子订单可以编辑备注跟附件 | |
39 | + if (isEdit) { | |
40 | + newListAnnex = subOrders.afterAnnexList?.map((path) => { | |
41 | + let i = 0; | |
42 | + return { | |
43 | + uid: i++, | |
44 | + name: getAliYunOSSFileNameFromUrl(path), | |
45 | + status: 'uploaded', | |
46 | + url: path, | |
47 | + response: { data: [path] }, | |
48 | + }; | |
49 | + }); | |
50 | + subOrders.filePaths = newListAnnex; | |
51 | + } | |
52 | + | |
53 | + const [form] = Form.useForm<{ | |
54 | + applyInvoicingNotes: string; | |
55 | + filePaths: any; | |
56 | + subIds: any[]; | |
57 | + afterInvoicingUpdate: boolean; | |
58 | + receivingCompany: string; | |
59 | + isUrgent: boolean; | |
60 | + deadline: string; | |
61 | + }>(); | |
62 | + | |
63 | + useEffect(() => { | |
64 | + //显示拼接的主订单id | |
65 | + form.setFieldValue('applyInvoicingNotes', mainIds); | |
66 | + }, []); | |
67 | + | |
68 | + return ( | |
69 | + <ModalForm<{ | |
70 | + applyInvoicingNotes: string; | |
71 | + filePaths: any; | |
72 | + subIds: any[]; | |
73 | + afterInvoicingUpdate: boolean; | |
74 | + }> | |
75 | + width={500} | |
76 | + open | |
77 | + title={isEdit ? '修改信息' : '申请开票'} | |
78 | + initialValues={subOrders} | |
79 | + form={form} | |
80 | + autoFocusFirstInput | |
81 | + modalProps={{ | |
82 | + okText: '确认', | |
83 | + cancelText: '取消', | |
84 | + destroyOnClose: true, | |
85 | + onCancel: () => { | |
86 | + setCheckVisible(false); | |
87 | + }, | |
88 | + }} | |
89 | + submitter={{ | |
90 | + render: (props, defaultDoms) => { | |
91 | + return defaultDoms; | |
92 | + }, | |
93 | + }} | |
94 | + submitTimeout={2000} | |
95 | + onFinish={async (values) => { | |
96 | + values.subIds = ids; | |
97 | + //附件处理 | |
98 | + values.filePaths = values.filePaths?.map((item) => { | |
99 | + return { url: item.response.data[0] }; | |
100 | + }); | |
101 | + | |
102 | + if (isEdit) { | |
103 | + values.afterInvoicingUpdate = true; | |
104 | + } else { | |
105 | + values.afterInvoicingUpdate = false; | |
106 | + } | |
107 | + | |
108 | + const res = await postServiceOrderApplyInvoicing({ data: values }); | |
109 | + | |
110 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
111 | + message.success(res.message); | |
112 | + onClose(); | |
113 | + } | |
114 | + }} | |
115 | + onOpenChange={setCheckVisible} | |
116 | + > | |
117 | + {isMainOrder ? ( | |
118 | + <div className="mb-[24px]"> | |
119 | + <span>选中子订单金额之和:</span> | |
120 | + <span className="text-red-500">{sumPrice}¥</span> | |
121 | + </div> | |
122 | + ) : ( | |
123 | + '' | |
124 | + )} | |
125 | + | |
126 | + <div className="mb-1"> | |
127 | + 如果需要合并订单,请将需要合并的订单id写在备注中,id之间用英文逗号隔开。 | |
128 | + </div> | |
129 | + <ProFormTextArea | |
130 | + width="lg" | |
131 | + name="applyInvoicingNotes" | |
132 | + key="applyInvoicingNotes" | |
133 | + placeholder="请输入备注" | |
134 | + onMetaChange={(val) => { | |
135 | + console.log(val); | |
136 | + }} | |
137 | + proFieldProps={{ | |
138 | + onchange: () => { | |
139 | + message.info('change'); | |
140 | + }, | |
141 | + }} | |
142 | + /> | |
143 | + <ProFormText | |
144 | + width="lg" | |
145 | + name="purchaser" | |
146 | + label="抬头名称" | |
147 | + key="purchaser" | |
148 | + placeholder="请输入抬头名称" | |
149 | + rules={[{ required: true, message: '抬头名称必填' }]} | |
150 | + /> | |
151 | + <ProFormSelect | |
152 | + placeholder="选择收款单位" | |
153 | + name="receivingCompany" | |
154 | + width="lg" | |
155 | + key="receivingCompany" | |
156 | + label={ | |
157 | + <div> | |
158 | + <span>开票收款单位</span> | |
159 | + <span className="pl-2 text-xs text-gray-400"> | |
160 | + 财务开票将依据这个字段,选择对应的公司开票(若对[收款单位]没有要求,请任意选择一个) | |
161 | + </span> | |
162 | + </div> | |
163 | + } | |
164 | + options={enumToSelect(PAYEE_OPTIONS)} | |
165 | + rules={[{ required: true, message: '开票收款单位必填' }]} | |
166 | + /> | |
167 | + <ProFormSelect | |
168 | + placeholder="选择是否加急" | |
169 | + name="isUrgent" | |
170 | + width="lg" | |
171 | + key="isUrgent" | |
172 | + label="是否加急" | |
173 | + options={[ | |
174 | + { label: '是', value: 'true' }, | |
175 | + { label: '否', value: 'false' }, | |
176 | + ]} | |
177 | + rules={[{ required: true, message: '是否加急必填' }]} | |
178 | + onChange={(val: any) => { | |
179 | + setIsUrgent(val); | |
180 | + }} | |
181 | + /> | |
182 | + | |
183 | + {/* <ProFormDatePicker | |
184 | + key="deadline" | |
185 | + label="期望开票时间" | |
186 | + name="deadline" | |
187 | + rules={[{ required: isUrgent === 'true', message: '期望开票时间必填' }]} | |
188 | + hidden={isUrgent !== 'true'} | |
189 | + /> */} | |
190 | + | |
191 | + <ProFormTextArea | |
192 | + key="invoicingUrgentCause" | |
193 | + label="加急开票原因" | |
194 | + name="invoicingUrgentCause" | |
195 | + rules={[{ required: isUrgent === 'true', message: '加急开票原因' }]} | |
196 | + hidden={isUrgent !== 'true'} | |
197 | + /> | |
198 | + | |
199 | + <ProFormUploadDragger | |
200 | + key="2" | |
201 | + label={ | |
202 | + <div> | |
203 | + <span>开票明细确认表</span> | |
204 | + <span className="pl-2 text-xs text-gray-400"> | |
205 | + 如果开票信息有变更,如开票内容跟下单内容不一致、下单抬头和付款抬头不一致,请上传开票明细确认表。 | |
206 | + </span> | |
207 | + </div> | |
208 | + } | |
209 | + name="filePaths" | |
210 | + action="/api/service/order/fileProcess" | |
211 | + fieldProps={{ | |
212 | + headers: { Authorization: localStorage.getItem('token') }, | |
213 | + }} | |
214 | + /> | |
215 | + </ModalForm> | |
216 | + ); | |
217 | +}; | ... | ... |
src/pages/Order/FeedBack/AttachmentModal.tsx
0 → 100644
1 | +import { getAliYunOSSFileNameFromUrl, isImageName } from '@/utils'; | |
2 | +import { ModalForm } from '@ant-design/pro-components'; | |
3 | +import { Button, Card, Divider, Empty, Form, Image, List, message } from 'antd'; | |
4 | +import Base64 from 'base-64'; | |
5 | +import { cloneDeep } from 'lodash'; | |
6 | +import React, { useEffect, useState } from 'react'; | |
7 | + | |
8 | +export default ({ data, onClose }) => { | |
9 | + let newData = cloneDeep(data); | |
10 | + const [fileList, setFileList] = useState<[]>([]); | |
11 | + console.log(fileList); | |
12 | + const [form] = Form.useForm<{ | |
13 | + subOrderId: ''; | |
14 | + listAnnex: []; | |
15 | + }>(); | |
16 | + | |
17 | + let newListAnnex = newData.listAnnex?.map((path) => { | |
18 | + let i = 0; | |
19 | + return { | |
20 | + uid: i++, | |
21 | + name: getAliYunOSSFileNameFromUrl(path), | |
22 | + status: 'uploaded', | |
23 | + url: path, | |
24 | + response: { data: [path] }, | |
25 | + }; | |
26 | + }); | |
27 | + newData.listAnnex = newListAnnex; | |
28 | + | |
29 | + //将图片和其他文件区分开 | |
30 | + let images: any[] = []; | |
31 | + let otherAnnex: any[] = []; | |
32 | + newListAnnex.forEach((item: any) => { | |
33 | + if (isImageName(item.name)) { | |
34 | + images.push(item); | |
35 | + } else { | |
36 | + otherAnnex.push(item); | |
37 | + } | |
38 | + }); | |
39 | + | |
40 | + useEffect(() => { | |
41 | + setFileList(newData.listAnnex); | |
42 | + }, []); | |
43 | + | |
44 | + return ( | |
45 | + <ModalForm | |
46 | + width={800} | |
47 | + open | |
48 | + title="查看附件" | |
49 | + initialValues={newData} | |
50 | + form={form} | |
51 | + modalProps={{ | |
52 | + onCancel: onClose, | |
53 | + }} | |
54 | + submitter={{ | |
55 | + render: () => { | |
56 | + return [ | |
57 | + <Button | |
58 | + key="back" | |
59 | + onClick={() => { | |
60 | + onClose(); | |
61 | + }} | |
62 | + > | |
63 | + 返回 | |
64 | + </Button>, | |
65 | + ]; | |
66 | + }, | |
67 | + }} | |
68 | + > | |
69 | + {newListAnnex?.length <= 0 ? ( | |
70 | + <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> | |
71 | + ) : ( | |
72 | + // <ProFormUploadDragger | |
73 | + // name="listAnnex" | |
74 | + // action="/api/service/order/fileProcess" | |
75 | + // disabled | |
76 | + // fieldProps={{ | |
77 | + // headers: { Authorization: localStorage.getItem('token') }, | |
78 | + // // onRemove: (file) => { | |
79 | + // // const index = fileList[listMeta.index].indexOf(file); | |
80 | + // // console.log(index); | |
81 | + // // const newFileList = fileList.slice(); | |
82 | + // // newFileList.splice(index, 1); | |
83 | + // // setFileList(newFileList); | |
84 | + // // }, | |
85 | + // // beforeUpload: (file) => { | |
86 | + // // fileList[listMeta.index] = [...fileList[listMeta.index], file as RcFile]; | |
87 | + // // setFileList(fileList); | |
88 | + // // return true; | |
89 | + // // }, | |
90 | + // fileList, | |
91 | + // // defaultFileList: itemFileList | |
92 | + // }} | |
93 | + // /> | |
94 | + <> | |
95 | + <Card> | |
96 | + <Image.PreviewGroup | |
97 | + className="mr-10" | |
98 | + preview={{ | |
99 | + onChange: (current, prev) => | |
100 | + console.log(`current index: ${current}, prev index: ${prev}`), | |
101 | + }} | |
102 | + > | |
103 | + {images.map((item, index) => ( | |
104 | + <React.Fragment key={index}> | |
105 | + <Image | |
106 | + className="max-h-[200px] max-w-[200px]" | |
107 | + src={item.url} | |
108 | + title={item.name} | |
109 | + />{' '} | |
110 | + <Divider type="vertical" /> | |
111 | + </React.Fragment> | |
112 | + ))} | |
113 | + </Image.PreviewGroup> | |
114 | + </Card> | |
115 | + <Divider /> | |
116 | + | |
117 | + <div> | |
118 | + <List | |
119 | + size="small" | |
120 | + header={<div>其他类型文件</div>} | |
121 | + bordered | |
122 | + dataSource={otherAnnex} | |
123 | + renderItem={(item) => ( | |
124 | + <List.Item | |
125 | + actions={[ | |
126 | + <Button | |
127 | + type="link" | |
128 | + key="key" | |
129 | + href={item.url} | |
130 | + target="blank" | |
131 | + className="py-1" | |
132 | + > | |
133 | + 下载 | |
134 | + </Button>, | |
135 | + <Button | |
136 | + type="link" | |
137 | + key="key" | |
138 | + className="py-1" | |
139 | + onClick={() => { | |
140 | + message.info(item.url); | |
141 | + window.open( | |
142 | + '/previewApi/onlinePreview?url=' + | |
143 | + encodeURIComponent(Base64.encode(item.url)), | |
144 | + ); | |
145 | + }} | |
146 | + > | |
147 | + 预览 | |
148 | + </Button>, | |
149 | + ]} | |
150 | + > | |
151 | + <div> | |
152 | + <span>{item.name}</span> | |
153 | + </div> | |
154 | + </List.Item> | |
155 | + )} | |
156 | + /> | |
157 | + </div> | |
158 | + </> | |
159 | + )} | |
160 | + </ModalForm> | |
161 | + ); | |
162 | +}; | ... | ... |
src/pages/Order/FeedBack/BaseModal.tsx
0 → 100644
1 | +import { ModalForm } from '@ant-design/pro-components'; | |
2 | +import { Form } from 'antd'; | |
3 | + | |
4 | +// import { cloneDeep } from 'lodash'; | |
5 | +export default ({ setVisible, onClose }) => { | |
6 | + const [form] = Form.useForm<{ name: string; company: string }>(); | |
7 | + | |
8 | + return ( | |
9 | + <> | |
10 | + <ModalForm<{ | |
11 | + name: string; | |
12 | + company: string; | |
13 | + }> | |
14 | + width={500} | |
15 | + open | |
16 | + title="标题" | |
17 | + form={form} | |
18 | + autoFocusFirstInput | |
19 | + modalProps={{ | |
20 | + okText: '通过', | |
21 | + cancelText: '取消', | |
22 | + destroyOnClose: true, | |
23 | + onCancel: () => { | |
24 | + setVisible(false); | |
25 | + }, | |
26 | + }} | |
27 | + onFinish={async (values) => { | |
28 | + console.log(values); | |
29 | + onClose(); | |
30 | + }} | |
31 | + onOpenChange={setVisible} | |
32 | + ></ModalForm> | |
33 | + </> | |
34 | + ); | |
35 | +}; | ... | ... |
src/pages/Order/FeedBack/CheckModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { | |
3 | + postPrepaidAudit, | |
4 | + postServiceOrderAfterSalesCheck, | |
5 | + postServiceOrderAudit, | |
6 | + postServiceOrderFileProcess, | |
7 | + postServiceOrderFinanceCheckOrder, | |
8 | + postServiceOrderLeaderAudit, | |
9 | + postServiceOrderToProcureAudit, | |
10 | +} from '@/services'; | |
11 | +import { | |
12 | + ModalForm, | |
13 | + ProFormText, | |
14 | + ProFormTextArea, | |
15 | + ProList, | |
16 | +} from '@ant-design/pro-components'; | |
17 | +import { | |
18 | + Button, | |
19 | + Col, | |
20 | + Divider, | |
21 | + Form, | |
22 | + Image, | |
23 | + Modal, | |
24 | + Row, | |
25 | + Space, | |
26 | + Tag, | |
27 | + UploadFile, | |
28 | + message, | |
29 | +} from 'antd'; | |
30 | +import Upload, { RcFile, UploadProps } from 'antd/es/upload'; | |
31 | +import { useEffect, useRef, useState } from 'react'; | |
32 | +import { | |
33 | + AFTE_SALES_PLAN_OPTIONS, | |
34 | + CHECK_TYPE, | |
35 | + COMFIR_RECEIPT_IMAGES_NUMBER, | |
36 | +} from './constant'; | |
37 | +// import { cloneDeep } from 'lodash'; | |
38 | +import InvoiceSubOrderInfoTable from '@/pages/Order/Order/components/InvoiceSubOrderInfoTable'; | |
39 | +import { enumValueToLabel, transImageFile } from '@/utils'; | |
40 | +import { PlusOutlined } from '@ant-design/icons'; | |
41 | +import { cloneDeep } from 'lodash'; | |
42 | + | |
43 | +export default ({ | |
44 | + setCheckVisible, | |
45 | + data, | |
46 | + subOrders, | |
47 | + orderCheckType, | |
48 | + openOrderDrawer, | |
49 | + onClose, | |
50 | +}) => { | |
51 | + const [previewOpen, setPreviewOpen] = useState(false); | |
52 | + const [aPopoverTitle, setAPopoverTitle] = useState('审核'); | |
53 | + const [previewImage, setPreviewImage] = useState(''); | |
54 | + const [previewTitle, setPreviewTitle] = useState(''); | |
55 | + const [paymentReceiptsImages, setPymentReceiptsImages] = useState<any[]>([]); | |
56 | + const fileListObj = useRef<UploadFile[]>([]); //使用引用类型,使得在useEffect里面设置监听事件后,不用更新监听事件也能保持obj与外界一致 | |
57 | + const getBase64 = (file: RcFile): Promise<string> => | |
58 | + new Promise((resolve, reject) => { | |
59 | + const reader = new FileReader(); | |
60 | + reader.readAsDataURL(file); | |
61 | + reader.onload = () => resolve(reader.result as string); | |
62 | + reader.onerror = (error) => reject(error); | |
63 | + }); | |
64 | + const [fileList, setFileList] = useState<UploadFile[]>([]); | |
65 | + const handleCancel = () => setPreviewOpen(false); | |
66 | + const [messageApi, contextHolder] = message.useMessage(); | |
67 | + const [form] = Form.useForm<{ name: string; company: string }>(); | |
68 | + let subOrderIds: any[] = subOrders?.map((subOrder) => subOrder.id); | |
69 | + const [mainOrderId] = useState(data.id); | |
70 | + | |
71 | + const [afterSalesInfo, setAfterSalesInfo] = useState<any>(); | |
72 | + const [prepaidProofImages, setPrepaidProofImages] = useState<any[]>([]); | |
73 | + /** | |
74 | + * 审核类型 | |
75 | + */ | |
76 | + function checkType(check: string) { | |
77 | + if (orderCheckType === check) { | |
78 | + return true; | |
79 | + } | |
80 | + return false; | |
81 | + } | |
82 | + | |
83 | + const getOrderAfterSalesInfo = async () => { | |
84 | + // let res = await postServiceOrderQueryAfterSalesInfoSnapshot({ | |
85 | + // data: { subOrderIds: subOrderIds }, | |
86 | + // }); | |
87 | + | |
88 | + //附件 | |
89 | + let annex = subOrders[0].afterSalesAnnexList; | |
90 | + let index = 1; | |
91 | + let annexLinks = annex?.map((f) => { | |
92 | + return ( | |
93 | + <Button className="p-0 pr-1" type="link" key="key" href={f}> | |
94 | + {'附件' + index++} | |
95 | + </Button> | |
96 | + ); | |
97 | + }); | |
98 | + | |
99 | + console.log(annexLinks); | |
100 | + | |
101 | + setAfterSalesInfo( | |
102 | + <div className="my-5"> | |
103 | + <Row gutter={[16, 24]}> | |
104 | + <Col span={6}> | |
105 | + <span className="text-[#333333]">售后方案</span> | |
106 | + </Col> | |
107 | + <Col span={18}> | |
108 | + {enumValueToLabel( | |
109 | + subOrders[0]?.afterSalesPlan, | |
110 | + AFTE_SALES_PLAN_OPTIONS, | |
111 | + )} | |
112 | + </Col> | |
113 | + <Col span={6}> | |
114 | + <span className="className='text-[#333333]'">售后原因</span> | |
115 | + </Col> | |
116 | + <Col span={18}>{subOrders[0]?.afterSalesNotes}</Col> | |
117 | + <Col span={6}> | |
118 | + <span className="className='text-[#333333]'">附件</span> | |
119 | + </Col> | |
120 | + <Col span={18}>{annexLinks}</Col> | |
121 | + </Row> | |
122 | + </div>, | |
123 | + ); | |
124 | + }; | |
125 | + | |
126 | + useEffect(() => { | |
127 | + if (checkType(CHECK_TYPE.CONFIRM_DELIVER)) { | |
128 | + setAPopoverTitle('确认发货'); | |
129 | + } | |
130 | + getOrderAfterSalesInfo(); | |
131 | + | |
132 | + let paymentReceiptsImagesList: any[] = []; | |
133 | + subOrders?.forEach((item: any) => { | |
134 | + if (item.paymentReceiptAnnexList) { | |
135 | + paymentReceiptsImagesList.push(...item.paymentReceiptAnnexList); | |
136 | + } | |
137 | + }); | |
138 | + //去重 | |
139 | + paymentReceiptsImagesList = [...new Set(paymentReceiptsImagesList)]; | |
140 | + setPymentReceiptsImages(paymentReceiptsImagesList); | |
141 | + | |
142 | + //预存审核的凭证 | |
143 | + let proofImages: any[] = []; | |
144 | + subOrders?.forEach((item) => { | |
145 | + let images = item.proofImages; | |
146 | + if (images !== null && images !== undefined) { | |
147 | + proofImages.push(...images); | |
148 | + } | |
149 | + }); | |
150 | + setPrepaidProofImages(proofImages); | |
151 | + }, []); | |
152 | + | |
153 | + const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => { | |
154 | + //fileListObj得在change里变化,change的参数是已经处理过的file数组 | |
155 | + //beforeUpload中的参数file是未处理过,还需要Base64拿到文件数据处理 | |
156 | + fileListObj.current = newFileList; | |
157 | + setFileList(newFileList); | |
158 | + }; | |
159 | + | |
160 | + /** 粘贴快捷键的回调 */ | |
161 | + const onPaste = async (e: any) => { | |
162 | + /** 获取剪切板的数据clipboardData */ | |
163 | + let clipboardData = e.clipboardData, | |
164 | + i = 0, | |
165 | + items, | |
166 | + item, | |
167 | + types; | |
168 | + | |
169 | + /** 为空判断 */ | |
170 | + if (clipboardData) { | |
171 | + items = clipboardData.items; | |
172 | + if (!items) { | |
173 | + message.info('您的剪贴板中没有照片'); | |
174 | + return; | |
175 | + } | |
176 | + | |
177 | + item = items[0]; | |
178 | + types = clipboardData.types || []; | |
179 | + /** 遍历剪切板的数据 */ | |
180 | + for (; i < types.length; i++) { | |
181 | + if (types[i] === 'Files') { | |
182 | + item = items[i]; | |
183 | + break; | |
184 | + } | |
185 | + } | |
186 | + | |
187 | + /** 判断文件是否为图片 */ | |
188 | + if (item && item.kind === 'file' && item.type.match(/^image\//i)) { | |
189 | + const imgItem = item.getAsFile(); | |
190 | + const newFileList = cloneDeep(fileListObj.current); | |
191 | + let filteredArray = newFileList.filter( | |
192 | + (obj) => obj.status !== 'removed', | |
193 | + ); //过滤掉状态为已删除的照片 | |
194 | + const listItem = { | |
195 | + ...imgItem, | |
196 | + status: 'done', | |
197 | + url: await getBase64(imgItem), | |
198 | + originFileObj: imgItem, | |
199 | + }; | |
200 | + | |
201 | + if (filteredArray.length >= COMFIR_RECEIPT_IMAGES_NUMBER) { | |
202 | + message.info('发货照片数量不能超过3'); | |
203 | + return; | |
204 | + } | |
205 | + fileListObj.current = filteredArray; | |
206 | + filteredArray.push(listItem); | |
207 | + setFileList(filteredArray); | |
208 | + return; | |
209 | + } | |
210 | + } | |
211 | + | |
212 | + message.info('您的剪贴板中没有照片'); | |
213 | + }; | |
214 | + useEffect(() => { | |
215 | + //回显售后信息 | |
216 | + // if (checkType(CHECK_TYPE.AFTER_SALES)) { | |
217 | + // getOrderAfterSalesInfo(); | |
218 | + // } | |
219 | + | |
220 | + document.addEventListener('paste', onPaste); | |
221 | + return () => { | |
222 | + document.removeEventListener('paste', onPaste); | |
223 | + }; | |
224 | + }, []); | |
225 | + const uploadButton = ( | |
226 | + <div> | |
227 | + <PlusOutlined /> | |
228 | + <div style={{ marginTop: 8 }}>上传凭证</div> | |
229 | + </div> | |
230 | + ); | |
231 | + const handlePreview = async (file: UploadFile) => { | |
232 | + if (!file.url && !file.preview) { | |
233 | + file.preview = await getBase64(file.originFileObj as RcFile); | |
234 | + } | |
235 | + setPreviewImage(file.url || (file.preview as string)); | |
236 | + setPreviewOpen(true); | |
237 | + setPreviewTitle( | |
238 | + file.name || | |
239 | + file.originFileObj?.name || | |
240 | + file.url!.substring(file.url!.lastIndexOf('/') + 1), | |
241 | + ); | |
242 | + }; | |
243 | + | |
244 | + const handleBeforeUpload = (file: any) => { | |
245 | + setFileList([...fileList, file]); | |
246 | + return false; | |
247 | + }; | |
248 | + | |
249 | + const props: UploadProps = { | |
250 | + onRemove: (file) => { | |
251 | + const index = fileList.indexOf(file); | |
252 | + const newFileList = fileList.slice(); | |
253 | + newFileList.splice(index, 1); | |
254 | + setFileList(newFileList); | |
255 | + }, | |
256 | + beforeUpload: handleBeforeUpload, | |
257 | + listType: 'picture-card', | |
258 | + onPreview: handlePreview, | |
259 | + fileList, | |
260 | + onChange: handleChange, | |
261 | + accept: 'image/png, image/jpeg, image/png', | |
262 | + // action: '/api/service/order/fileProcess', | |
263 | + name: 'files', | |
264 | + headers: { Authorization: localStorage.getItem('token') }, | |
265 | + }; | |
266 | + | |
267 | + //仓库审核 | |
268 | + async function doCheck(body: object) { | |
269 | + const data = await postServiceOrderAudit({ | |
270 | + data: body, | |
271 | + }); | |
272 | + if (data.result === RESPONSE_CODE.SUCCESS) { | |
273 | + message.success(data.message); | |
274 | + onClose(); | |
275 | + } | |
276 | + } | |
277 | + | |
278 | + /** | |
279 | + * | |
280 | + * @param body 财务审核 | |
281 | + */ | |
282 | + async function doFinancailCheck(values: any, isAgree: boolean) { | |
283 | + if (fileList.length <= 0) { | |
284 | + message.error('凭证不能为空'); | |
285 | + return; | |
286 | + } | |
287 | + messageApi.open({ | |
288 | + type: 'loading', | |
289 | + content: '正在上传图片...', | |
290 | + duration: 0, | |
291 | + }); | |
292 | + //附件处理 | |
293 | + let formData = new FormData(); | |
294 | + //附件处理 | |
295 | + for (let file of fileList) { | |
296 | + if (file.originFileObj) { | |
297 | + formData.append('files', file.originFileObj as RcFile); | |
298 | + } else { | |
299 | + //有url的话取url(源文件),没url取thumbUrl。有url的时候thumbUrl是略缩图 | |
300 | + if (file?.url === undefined || file?.url === null) { | |
301 | + formData.append( | |
302 | + 'files', | |
303 | + transImageFile(file?.thumbUrl), | |
304 | + file?.originFileObj?.name, | |
305 | + ); | |
306 | + } else { | |
307 | + formData.append( | |
308 | + 'files', | |
309 | + transImageFile(file?.url), | |
310 | + file?.originFileObj?.name, | |
311 | + ); | |
312 | + } | |
313 | + } | |
314 | + } | |
315 | + let res = await postServiceOrderFileProcess({ | |
316 | + data: formData, | |
317 | + }); | |
318 | + messageApi.destroy(); | |
319 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
320 | + message.success('上传成功!'); | |
321 | + | |
322 | + let fileUrls = res?.data?.map((item) => { | |
323 | + return { url: item }; | |
324 | + }); | |
325 | + //财务审核 | |
326 | + const data = await postServiceOrderFinanceCheckOrder({ | |
327 | + data: { | |
328 | + ...values, | |
329 | + checkNotes: values.name, | |
330 | + ids: subOrderIds, | |
331 | + checkPassOrReject: isAgree, | |
332 | + invoicingCheckAnnex: fileUrls, | |
333 | + }, | |
334 | + }); | |
335 | + if (data.result === RESPONSE_CODE.SUCCESS) { | |
336 | + message.success(data.message); | |
337 | + onClose(); | |
338 | + } | |
339 | + } else { | |
340 | + message.success('上传失败'); | |
341 | + } | |
342 | + } | |
343 | + | |
344 | + /** | |
345 | + * | |
346 | + * @param body 售后审核 | |
347 | + */ | |
348 | + async function doAfterSalesCheck(body: object) { | |
349 | + const data = await postServiceOrderAfterSalesCheck({ | |
350 | + data: body, | |
351 | + }); | |
352 | + if (data.result === RESPONSE_CODE.SUCCESS) { | |
353 | + message.success(data.message); | |
354 | + onClose(); | |
355 | + } | |
356 | + } | |
357 | + | |
358 | + /** | |
359 | + * | |
360 | + * @param body 领导审核 | |
361 | + */ | |
362 | + async function doLeaderCheck(body: object) { | |
363 | + const data = await postServiceOrderLeaderAudit({ | |
364 | + data: body, | |
365 | + }); | |
366 | + if (data.result === RESPONSE_CODE.SUCCESS) { | |
367 | + message.success(data.message); | |
368 | + onClose(); | |
369 | + } | |
370 | + } | |
371 | + | |
372 | + /** | |
373 | + * 预存审核 | |
374 | + * @param body | |
375 | + */ | |
376 | + async function doPrepaidAudit(body: any) { | |
377 | + const data = await postPrepaidAudit({ | |
378 | + data: body, | |
379 | + }); | |
380 | + if (data.result === RESPONSE_CODE.SUCCESS) { | |
381 | + message.success(data.message); | |
382 | + onClose(); | |
383 | + } | |
384 | + } | |
385 | + | |
386 | + function computeType() { | |
387 | + let type: string = ''; | |
388 | + if (checkType(CHECK_TYPE.CONFIRM_DELIVER)) { | |
389 | + type = 'confirm_deliver'; | |
390 | + } | |
391 | + if (checkType(CHECK_TYPE.WEARHOUSE_KEEPER)) { | |
392 | + type = 'warehouse_audit'; | |
393 | + } | |
394 | + if (checkType(CHECK_TYPE.WAITING_FOR_POST_AUDIT)) { | |
395 | + type = 'post_audit'; | |
396 | + } | |
397 | + if (checkType(CHECK_TYPE.NODE_OPERATING_AUDIT)) { | |
398 | + type = 'node_operating_audit'; | |
399 | + } | |
400 | + if (checkType(CHECK_TYPE.MODIFY_LEADER_AUDIT)) { | |
401 | + type = 'modify_leader_audit'; | |
402 | + } | |
403 | + if (checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING)) { | |
404 | + type = 'urgent_invoice_audit'; | |
405 | + } | |
406 | + if (checkType(CHECK_TYPE.PAYMENT_RECEIPTS_AUDIT)) { | |
407 | + type = 'payment_receipt_audit'; | |
408 | + } | |
409 | + if (checkType(CHECK_TYPE.CONFIRM_REISSUE)) { | |
410 | + type = 'confirm_reissue'; | |
411 | + } | |
412 | + if (checkType(CHECK_TYPE.CREDIT_AUDIT)) { | |
413 | + type = 'credit_audit'; | |
414 | + } | |
415 | + if (checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING_OLD)) { | |
416 | + type = 'urgent_invoice_audit_old'; | |
417 | + } | |
418 | + if (checkType(CHECK_TYPE.CONFIRM_REISSUE_OLD)) { | |
419 | + type = 'confirm_reissue_old'; | |
420 | + } | |
421 | + return type; | |
422 | + } | |
423 | + | |
424 | + return ( | |
425 | + <> | |
426 | + <ModalForm<{ | |
427 | + name: string; | |
428 | + company: string; | |
429 | + }> | |
430 | + width={500} | |
431 | + open | |
432 | + title={aPopoverTitle} | |
433 | + form={form} | |
434 | + autoFocusFirstInput | |
435 | + modalProps={{ | |
436 | + okText: '通过', | |
437 | + cancelText: '驳回', | |
438 | + destroyOnClose: true, | |
439 | + onCancel: () => { | |
440 | + setCheckVisible(false); | |
441 | + }, | |
442 | + }} | |
443 | + submitter={{ | |
444 | + render: (props, defaultDoms) => { | |
445 | + let myDoms = []; | |
446 | + if (!checkType(CHECK_TYPE.CONFIRM_DELIVER)) { | |
447 | + myDoms.push( | |
448 | + <Button | |
449 | + key="驳回" | |
450 | + onClick={async () => { | |
451 | + if (checkType(CHECK_TYPE.AFTER_SALES)) { | |
452 | + doAfterSalesCheck({ | |
453 | + applyType: 'after-sales', | |
454 | + isAfterSalesSuccess: false, | |
455 | + subOrderIds: subOrderIds, | |
456 | + mainId: mainOrderId, | |
457 | + afterSalesRejectionNotes: form.getFieldValue('name'), | |
458 | + }); | |
459 | + return; | |
460 | + } | |
461 | + | |
462 | + if (checkType(CHECK_TYPE.FINALCIAL)) { | |
463 | + let values = { name: form.getFieldValue('name') }; | |
464 | + doFinancailCheck(values, false); | |
465 | + return; | |
466 | + } | |
467 | + | |
468 | + if (checkType(CHECK_TYPE.LEADER_AUDIT)) { | |
469 | + doLeaderCheck({ | |
470 | + pass: false, | |
471 | + subOrderIds: subOrderIds, | |
472 | + reason: form.getFieldValue('name'), | |
473 | + }); | |
474 | + return; | |
475 | + } | |
476 | + | |
477 | + if (checkType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT)) { | |
478 | + doAfterSalesCheck({ | |
479 | + applyType: 'order-change-normal', | |
480 | + isAfterSalesSuccess: false, | |
481 | + subOrderIds: subOrderIds, | |
482 | + mainId: mainOrderId, | |
483 | + afterSalesRejectionNotes: form.getFieldValue('name'), | |
484 | + }); | |
485 | + return; | |
486 | + } | |
487 | + | |
488 | + //预存审核,先暂时共用同一个审核弹窗 | |
489 | + if (checkType(CHECK_TYPE.PREPAID_AUDIT)) { | |
490 | + return doPrepaidAudit({ | |
491 | + pass: false, | |
492 | + ids: subOrderIds, | |
493 | + auditNotes: form.getFieldValue('name'), | |
494 | + }); | |
495 | + } | |
496 | + | |
497 | + let type = ''; | |
498 | + type = computeType(); | |
499 | + console.log('type:' + type); | |
500 | + doCheck({ | |
501 | + pass: false, | |
502 | + subOrderIds: subOrderIds, | |
503 | + type: type, | |
504 | + notes: form.getFieldValue('name'), | |
505 | + }); | |
506 | + }} | |
507 | + > | |
508 | + 驳回 | |
509 | + </Button>, | |
510 | + ); | |
511 | + } | |
512 | + | |
513 | + //如果是仓库审核,那么显示这个外部采购 | |
514 | + if (checkType(CHECK_TYPE.WEARHOUSE_KEEPER)) { | |
515 | + myDoms.push( | |
516 | + <Button | |
517 | + key="外部采购" | |
518 | + onClick={async () => { | |
519 | + let res = await postServiceOrderToProcureAudit({ | |
520 | + data: { | |
521 | + subOrderIds: subOrderIds, | |
522 | + }, | |
523 | + }); | |
524 | + | |
525 | + if (res && res.result === RESPONSE_CODE.SUCCESS) { | |
526 | + message.success(res.message); | |
527 | + onClose(); | |
528 | + } | |
529 | + }} | |
530 | + > | |
531 | + 外部采购 | |
532 | + </Button>, | |
533 | + ); | |
534 | + } | |
535 | + | |
536 | + //确认 | |
537 | + myDoms.push(defaultDoms[1]); | |
538 | + return myDoms; | |
539 | + }, | |
540 | + }} | |
541 | + submitTimeout={2000} | |
542 | + onFinish={async (values) => { | |
543 | + if (checkType(CHECK_TYPE.AFTER_SALES)) { | |
544 | + //审核通过 | |
545 | + return doAfterSalesCheck({ | |
546 | + applyType: 'after-sales', | |
547 | + isAfterSalesSuccess: true, | |
548 | + subOrderIds: subOrderIds, | |
549 | + mainId: mainOrderId, | |
550 | + afterSalesRejectionNotes: values.name, | |
551 | + }); | |
552 | + } | |
553 | + console.log('h'); | |
554 | + if (checkType(CHECK_TYPE.FINALCIAL)) { | |
555 | + doFinancailCheck(values, true); | |
556 | + return; | |
557 | + } | |
558 | + | |
559 | + if (checkType(CHECK_TYPE.LEADER_AUDIT)) { | |
560 | + doLeaderCheck({ | |
561 | + pass: true, | |
562 | + subOrderIds: subOrderIds, | |
563 | + reason: values.name, | |
564 | + }); | |
565 | + return; | |
566 | + } | |
567 | + | |
568 | + if (checkType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT)) { | |
569 | + //审核通过 | |
570 | + return doAfterSalesCheck({ | |
571 | + applyType: 'order-change-normal', | |
572 | + isAfterSalesSuccess: true, | |
573 | + subOrderIds: subOrderIds, | |
574 | + mainId: mainOrderId, | |
575 | + afterSalesRejectionNotes: values.name, | |
576 | + }); | |
577 | + } | |
578 | + | |
579 | + //预存审核,先暂时共用同一个审核弹窗 | |
580 | + if (checkType(CHECK_TYPE.PREPAID_AUDIT)) { | |
581 | + return doPrepaidAudit({ | |
582 | + pass: true, | |
583 | + ids: subOrderIds, | |
584 | + auditNotes: form.getFieldValue('name'), | |
585 | + }); | |
586 | + } | |
587 | + | |
588 | + let type = ''; | |
589 | + type = computeType(); | |
590 | + doCheck({ | |
591 | + ...values, | |
592 | + pass: true, | |
593 | + subOrderIds: subOrderIds, | |
594 | + type: type, | |
595 | + notes: form.getFieldValue('name'), | |
596 | + }); | |
597 | + }} | |
598 | + onOpenChange={setCheckVisible} | |
599 | + > | |
600 | + {checkType(CHECK_TYPE.AFTER_SALES) ? ( | |
601 | + <> | |
602 | + {afterSalesInfo} | |
603 | + <Button | |
604 | + className="px-0" | |
605 | + type="link" | |
606 | + onClick={() => { | |
607 | + console.log(data); | |
608 | + openOrderDrawer('after-sales-check', mainOrderId); | |
609 | + }} | |
610 | + > | |
611 | + 查看旧订单 | |
612 | + </Button> | |
613 | + </> | |
614 | + ) : ( | |
615 | + '' | |
616 | + )} | |
617 | + | |
618 | + {checkType(CHECK_TYPE.PAYMENT_RECEIPTS_AUDIT) ? ( | |
619 | + <> | |
620 | + <Divider orientation="center"> | |
621 | + <span className="text-sm">回款凭证</span> | |
622 | + </Divider> | |
623 | + <Image.PreviewGroup | |
624 | + className="mr-10" | |
625 | + preview={{ | |
626 | + onChange: (current, prev) => | |
627 | + console.log(`current index: ${current}, prev index: ${prev}`), | |
628 | + }} | |
629 | + > | |
630 | + {paymentReceiptsImages.map((url) => ( | |
631 | + <> | |
632 | + <Image width={120} src={url} /> <Divider type="vertical" /> | |
633 | + </> | |
634 | + ))} | |
635 | + </Image.PreviewGroup> | |
636 | + <Divider></Divider> | |
637 | + </> | |
638 | + ) : ( | |
639 | + '' | |
640 | + )} | |
641 | + | |
642 | + {checkType(CHECK_TYPE.PREPAID_AUDIT) && ( | |
643 | + <> | |
644 | + <Divider orientation="center"> | |
645 | + <span className="text-sm">凭证</span> | |
646 | + </Divider> | |
647 | + <Image.PreviewGroup | |
648 | + className="mr-10" | |
649 | + preview={{ | |
650 | + onChange: (current, prev) => | |
651 | + console.log(`current index: ${current}, prev index: ${prev}`), | |
652 | + }} | |
653 | + > | |
654 | + {prepaidProofImages.map((url) => ( | |
655 | + <> | |
656 | + <Image width={120} src={url} /> <Divider type="vertical" /> | |
657 | + </> | |
658 | + ))} | |
659 | + </Image.PreviewGroup> | |
660 | + <Divider></Divider> | |
661 | + </> | |
662 | + )} | |
663 | + | |
664 | + {checkType('prepaidAudit') ? ( | |
665 | + <div>请特别注意手机号码和充值金额。</div> | |
666 | + ) : ( | |
667 | + <div>请特别注意订单总金额与订单金额。</div> | |
668 | + )} | |
669 | + {!checkType(CHECK_TYPE.CONFIRM_DELIVER) ? ( | |
670 | + <ProFormTextArea | |
671 | + width="lg" | |
672 | + name="name" | |
673 | + placeholder="若驳回,请填写驳回理由" | |
674 | + /> | |
675 | + ) : ( | |
676 | + <></> | |
677 | + )} | |
678 | + {checkType(CHECK_TYPE.FINALCIAL) ? ( | |
679 | + <> | |
680 | + <ProFormText | |
681 | + width="md" | |
682 | + name="bankStatementSerialNumbersText" | |
683 | + label="流水号" | |
684 | + rules={[ | |
685 | + { | |
686 | + required: true, | |
687 | + message: '请输入流水号!', | |
688 | + }, | |
689 | + ]} | |
690 | + placeholder={'多个流水号用逗号隔开'} | |
691 | + /> | |
692 | + <div className="pb-4 text-xs decoration-gray-50"> | |
693 | + 可复制照片粘贴 | |
694 | + </div> | |
695 | + <Upload {...props}> | |
696 | + {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER | |
697 | + ? uploadButton | |
698 | + : ''} | |
699 | + </Upload> | |
700 | + </> | |
701 | + ) : ( | |
702 | + '' | |
703 | + )} | |
704 | + {checkType(CHECK_TYPE.CONFIRM_REISSUE) && ( | |
705 | + <> | |
706 | + <InvoiceSubOrderInfoTable | |
707 | + subOrderIds={subOrderIds} | |
708 | + ></InvoiceSubOrderInfoTable> | |
709 | + </> | |
710 | + )} | |
711 | + {checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING) ? ( | |
712 | + <> | |
713 | + <ProList | |
714 | + rowKey="id" | |
715 | + headerTitle="发票信息" | |
716 | + metas={{ | |
717 | + title: { | |
718 | + dataIndex: 'name', | |
719 | + }, | |
720 | + avatar: { | |
721 | + dataIndex: 'image', | |
722 | + editable: false, | |
723 | + }, | |
724 | + description: { | |
725 | + dataIndex: 'desc', | |
726 | + }, | |
727 | + subTitle: { | |
728 | + render: () => { | |
729 | + return ( | |
730 | + <Space size={0}> | |
731 | + <Tag color="blue">Ant Design</Tag> | |
732 | + <Tag color="#5BD8A6">TechUI</Tag> | |
733 | + </Space> | |
734 | + ); | |
735 | + }, | |
736 | + }, | |
737 | + actions: { | |
738 | + render: (text, row, index, action) => [ | |
739 | + <a | |
740 | + onClick={() => { | |
741 | + action?.startEditable(row.id); | |
742 | + }} | |
743 | + key="link" | |
744 | + > | |
745 | + 编辑 | |
746 | + </a>, | |
747 | + ], | |
748 | + }, | |
749 | + }} | |
750 | + ></ProList> | |
751 | + </> | |
752 | + ) : ( | |
753 | + '' | |
754 | + )} | |
755 | + </ModalForm> | |
756 | + | |
757 | + <Modal | |
758 | + open={previewOpen} | |
759 | + title={previewTitle} | |
760 | + footer={null} | |
761 | + onCancel={handleCancel} | |
762 | + > | |
763 | + <img alt="图片预览" style={{ width: '100%' }} src={previewImage} /> | |
764 | + </Modal> | |
765 | + {contextHolder} | |
766 | + </> | |
767 | + ); | |
768 | +}; | ... | ... |
src/pages/Order/FeedBack/ConfirmReceiptModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { postServiceOrderConfirmReceipt } from '@/services'; | |
3 | +import { PlusOutlined } from '@ant-design/icons'; | |
4 | +import { Button, Modal, Upload, message } from 'antd'; | |
5 | +import { RcFile, UploadFile, UploadProps } from 'antd/es/upload'; | |
6 | +import { cloneDeep } from 'lodash'; | |
7 | +import { useEffect, useRef, useState } from 'react'; | |
8 | +import { COMFIR_RECEIPT_IMAGES_NUMBER } from './constant'; | |
9 | +export default ({ data, onClose }) => { | |
10 | + const subIds = data?.map((item) => { | |
11 | + return item.id; | |
12 | + }); | |
13 | + // const [form] = Form.useForm<{ name: string; company: string }>(); | |
14 | + const [previewOpen, setPreviewOpen] = useState(false); | |
15 | + const [previewImage, setPreviewImage] = useState(''); | |
16 | + const [previewTitle, setPreviewTitle] = useState(''); | |
17 | + const fileListObj = useRef<UploadFile[]>([]); //使用引用类型,使得在useEffect里面设置监听事件后,不用更新监听事件也能保持obj与外界一致 | |
18 | + const getBase64 = (file: RcFile): Promise<string> => | |
19 | + new Promise((resolve, reject) => { | |
20 | + const reader = new FileReader(); | |
21 | + reader.readAsDataURL(file); | |
22 | + reader.onload = () => resolve(reader.result as string); | |
23 | + reader.onerror = (error) => reject(error); | |
24 | + }); | |
25 | + const [fileList, setFileList] = useState<UploadFile[]>([]); | |
26 | + const [uploading, setUploading] = useState(false); | |
27 | + const handleCancel = () => setPreviewOpen(false); | |
28 | + | |
29 | + const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => { | |
30 | + //fileListObj得在change里变化,change的参数是已经处理过的file数组 | |
31 | + //beforeUpload中的参数file是未处理过,还需要Base64拿到文件数据处理 | |
32 | + fileListObj.current = newFileList; | |
33 | + setFileList(newFileList); | |
34 | + }; | |
35 | + | |
36 | + /** 粘贴快捷键的回调 */ | |
37 | + const onPaste = async (e: any) => { | |
38 | + /** 获取剪切板的数据clipboardData */ | |
39 | + let clipboardData = e.clipboardData, | |
40 | + i = 0, | |
41 | + items, | |
42 | + item, | |
43 | + types; | |
44 | + | |
45 | + /** 为空判断 */ | |
46 | + if (clipboardData) { | |
47 | + items = clipboardData.items; | |
48 | + if (!items) { | |
49 | + message.info('您的剪贴板中没有照片'); | |
50 | + return; | |
51 | + } | |
52 | + | |
53 | + item = items[0]; | |
54 | + types = clipboardData.types || []; | |
55 | + /** 遍历剪切板的数据 */ | |
56 | + for (; i < types.length; i++) { | |
57 | + if (types[i] === 'Files') { | |
58 | + item = items[i]; | |
59 | + break; | |
60 | + } | |
61 | + } | |
62 | + | |
63 | + /** 判断文件是否为图片 */ | |
64 | + if (item && item.kind === 'file' && item.type.match(/^image\//i)) { | |
65 | + const imgItem = item.getAsFile(); | |
66 | + const newFileList = cloneDeep(fileListObj.current); | |
67 | + let filteredArray = newFileList.filter( | |
68 | + (obj) => obj.status !== 'removed', | |
69 | + ); //过滤掉状态为已删除的照片 | |
70 | + const listItem = { | |
71 | + ...imgItem, | |
72 | + status: 'done', | |
73 | + url: await getBase64(imgItem), | |
74 | + originFileObj: imgItem, | |
75 | + }; | |
76 | + | |
77 | + if (filteredArray.length >= COMFIR_RECEIPT_IMAGES_NUMBER) { | |
78 | + message.info('发货凭证照片数量不能超过3'); | |
79 | + return; | |
80 | + } | |
81 | + fileListObj.current = filteredArray; | |
82 | + filteredArray.push(listItem); | |
83 | + setFileList(filteredArray); | |
84 | + return; | |
85 | + } | |
86 | + } | |
87 | + | |
88 | + message.info('您的剪贴板中没有照片'); | |
89 | + }; | |
90 | + useEffect(() => { | |
91 | + document.addEventListener('paste', onPaste); | |
92 | + return () => { | |
93 | + document.removeEventListener('paste', onPaste); | |
94 | + }; | |
95 | + }, []); | |
96 | + const uploadButton = ( | |
97 | + <div> | |
98 | + <PlusOutlined /> | |
99 | + <div style={{ marginTop: 8 }}>上传凭证</div> | |
100 | + </div> | |
101 | + ); | |
102 | + const handlePreview = async (file: UploadFile) => { | |
103 | + if (!file.url && !file.preview) { | |
104 | + file.preview = await getBase64(file.originFileObj as RcFile); | |
105 | + } | |
106 | + setPreviewImage(file.url || (file.preview as string)); | |
107 | + setPreviewOpen(true); | |
108 | + setPreviewTitle( | |
109 | + file.name || | |
110 | + file.originFileObj?.name || | |
111 | + file.url!.substring(file.url!.lastIndexOf('/') + 1), | |
112 | + ); | |
113 | + }; | |
114 | + | |
115 | + const handleUpload = async () => { | |
116 | + const formData = new FormData(); | |
117 | + fileList.forEach((file) => { | |
118 | + //originFileObj二进制文件 | |
119 | + formData.append('files', file.originFileObj as RcFile); | |
120 | + }); | |
121 | + // console.log(fileList[0] as RcFile) | |
122 | + // formData.append('file', fileList[0] as RcFile); | |
123 | + formData.append('subIds', subIds); | |
124 | + setUploading(true); | |
125 | + // You can use any AJAX library you like | |
126 | + const res = await postServiceOrderConfirmReceipt({ | |
127 | + data: formData, | |
128 | + headers: { | |
129 | + 'Content-Type': | |
130 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | |
131 | + }, | |
132 | + }); | |
133 | + | |
134 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
135 | + message.success(res.message); | |
136 | + onClose(); | |
137 | + } | |
138 | + | |
139 | + setUploading(false); | |
140 | + }; | |
141 | + | |
142 | + const props: UploadProps = { | |
143 | + onRemove: (file) => { | |
144 | + const index = fileList.indexOf(file); | |
145 | + const newFileList = fileList.slice(); | |
146 | + newFileList.splice(index, 1); | |
147 | + setFileList(newFileList); | |
148 | + }, | |
149 | + beforeUpload: (file) => { | |
150 | + setFileList([...fileList, file]); | |
151 | + return false; | |
152 | + }, | |
153 | + listType: 'picture-card', | |
154 | + onPreview: handlePreview, | |
155 | + fileList, | |
156 | + onChange: handleChange, | |
157 | + accept: 'image/png, image/jpeg, image/png', | |
158 | + }; | |
159 | + | |
160 | + return ( | |
161 | + <> | |
162 | + <Modal | |
163 | + width={500} | |
164 | + open | |
165 | + title="确认收货" | |
166 | + footer={[ | |
167 | + <Button key="cancel" onClick={onClose}> | |
168 | + 取消 | |
169 | + </Button>, | |
170 | + <Button | |
171 | + type="primary" | |
172 | + key="ok" | |
173 | + onClick={handleUpload} | |
174 | + disabled={fileList.length === 0} | |
175 | + loading={uploading} | |
176 | + > | |
177 | + {uploading ? '上传中' : '提交'} | |
178 | + </Button>, | |
179 | + ]} | |
180 | + onCancel={async () => { | |
181 | + onClose(); | |
182 | + }} | |
183 | + > | |
184 | + <div className="pt-4 font-semibold">请将买家确认收货的凭证照片上传</div> | |
185 | + <div className="pb-4 text-xs decoration-gray-50">可复制照片粘贴</div> | |
186 | + <Upload {...props}> | |
187 | + {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER ? uploadButton : ''} | |
188 | + </Upload> | |
189 | + </Modal> | |
190 | + <Modal | |
191 | + open={previewOpen} | |
192 | + title={previewTitle} | |
193 | + footer={null} | |
194 | + onCancel={handleCancel} | |
195 | + > | |
196 | + <img alt="图片预览" style={{ width: '100%' }} src={previewImage} /> | |
197 | + </Modal> | |
198 | + </> | |
199 | + ); | |
200 | +}; | ... | ... |
src/pages/Order/FeedBack/DeliverInfoDrawer.tsx
0 → 100644
1 | +import { postDistrictSelOrderProvince } from '@/services'; | |
2 | +import { enumValueToLabel } from '@/utils'; | |
3 | +import { getReceivingCompanyOptions } from '@/utils/order'; | |
4 | +import { Col, Drawer, Row } from 'antd'; | |
5 | +import { useEffect, useState } from 'react'; | |
6 | +import { PAYEE_OPTIONS } from './constant'; | |
7 | + | |
8 | +export default ({ data, onClose }) => { | |
9 | + const [province, setProvince] = useState(''); | |
10 | + const [city, setCity] = useState(''); | |
11 | + const [district, setDistrict] = useState(''); | |
12 | + | |
13 | + useEffect(() => { | |
14 | + const fetchData = async () => { | |
15 | + if (data.id !== undefined) { | |
16 | + const resp = await postDistrictSelOrderProvince({ | |
17 | + data: data.id, | |
18 | + }); | |
19 | + if (resp && resp.data) { | |
20 | + if (resp.data.province) { | |
21 | + setProvince(resp.data.province); | |
22 | + } | |
23 | + if (resp.data.city) { | |
24 | + setCity(resp.data.city); | |
25 | + } | |
26 | + if (resp.data.district) { | |
27 | + setDistrict(resp.data.district); | |
28 | + } | |
29 | + } | |
30 | + } | |
31 | + }; | |
32 | + | |
33 | + fetchData(); | |
34 | + }, [data.id]); | |
35 | + return ( | |
36 | + <> | |
37 | + <Drawer | |
38 | + width={500} | |
39 | + title="基本信息" | |
40 | + placement="right" | |
41 | + onClose={onClose} | |
42 | + open | |
43 | + > | |
44 | + <Row gutter={[16, 24]}> | |
45 | + <Col span={6}> | |
46 | + <span className="text-[#333333]">收货人</span> | |
47 | + </Col> | |
48 | + <Col span={18}>{data.customerName}</Col> | |
49 | + <Col span={6}> | |
50 | + <span className="className='text-[#333333]'">联系方式</span> | |
51 | + </Col> | |
52 | + <Col span={18}>{data.customerContactNumber}</Col> | |
53 | + <Col span={6}> | |
54 | + <span className="className='text-[#333333]'">省市区</span> | |
55 | + </Col> | |
56 | + <Col span={18}> | |
57 | + {province} {city} {district} | |
58 | + </Col> | |
59 | + <Col span={6}> | |
60 | + <span className="className='text-[#333333]'">收货地址</span> | |
61 | + </Col> | |
62 | + <Col span={18}>{data.customerShippingAddress}</Col> | |
63 | + <Col span={6}> | |
64 | + <span className="className='text-[#333333]'">课题组老师</span> | |
65 | + </Col> | |
66 | + <Col span={18}>{data.institutionContactName}</Col> | |
67 | + <Col span={6}> | |
68 | + <span className="className='text-[#333333]'">单位名称</span> | |
69 | + </Col> | |
70 | + <Col span={18}>{data.institution}</Col> | |
71 | + <Col span={6}> | |
72 | + <span className="className='text-[#333333]'">开户银行</span> | |
73 | + </Col> | |
74 | + <Col span={18}>{data.bank}</Col> | |
75 | + | |
76 | + <Col span={6}> | |
77 | + <span className="className='text-[#333333]'">开票收款单位</span> | |
78 | + </Col> | |
79 | + <Col span={18}> | |
80 | + {enumValueToLabel( | |
81 | + data.receivingCompany, | |
82 | + getReceivingCompanyOptions(PAYEE_OPTIONS), | |
83 | + )} | |
84 | + </Col> | |
85 | + | |
86 | + <Col span={6}> | |
87 | + <span className="className='text-[#333333]'">银行账号</span> | |
88 | + </Col> | |
89 | + <Col span={18}>{data.bankAccountNumber}</Col> | |
90 | + <Col span={6}> | |
91 | + <span className="className='text-[#333333]'">开票识别号</span> | |
92 | + </Col> | |
93 | + <Col span={18}>{data.invoiceIdentificationNumber}</Col> | |
94 | + </Row> | |
95 | + </Drawer> | |
96 | + </> | |
97 | + ); | |
98 | +}; | ... | ... |
src/pages/Order/FeedBack/DeliverModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { | |
3 | + postServiceOrderProcureSend, | |
4 | + postServiceOrderSendProduct, | |
5 | + postServiceOrderSupplierSendOrder, | |
6 | +} from '@/services'; | |
7 | +import { enumToSelect } from '@/utils'; | |
8 | +import { | |
9 | + ProColumns, | |
10 | + ProForm, | |
11 | + ProFormSelect, | |
12 | + ProFormText, | |
13 | + ProTable, | |
14 | +} from '@ant-design/pro-components'; | |
15 | +import { | |
16 | + Button, | |
17 | + Col, | |
18 | + Flex, | |
19 | + Input, | |
20 | + InputNumber, | |
21 | + Modal, | |
22 | + Row, | |
23 | + Select, | |
24 | + message, | |
25 | +} from 'antd'; | |
26 | +import { cloneDeep } from 'lodash'; | |
27 | +import { useEffect, useRef, useState } from 'react'; | |
28 | +import { CHECK_TYPE, LOGISTICS_STATUS_OPTIONS } from '../constant'; | |
29 | + | |
30 | +const DeliverModal = ({ | |
31 | + data: propsData, | |
32 | + isSendProduct, | |
33 | + setVisible, | |
34 | + sendType, | |
35 | + onClose, | |
36 | +}) => { | |
37 | + const [data, setData] = useState(propsData || {}); | |
38 | + const form = useRef(); | |
39 | + | |
40 | + /** | |
41 | + * 是供应商发货还是普通发货 | |
42 | + * @param typeString | |
43 | + * @returns | |
44 | + */ | |
45 | + function optType(typeString: string) { | |
46 | + if (sendType === typeString) { | |
47 | + return true; | |
48 | + } | |
49 | + | |
50 | + return false; | |
51 | + } | |
52 | + | |
53 | + useEffect(() => { | |
54 | + setData(propsData); | |
55 | + }, [propsData]); | |
56 | + | |
57 | + const handleChange = (key: string, index: number, obj: any) => { | |
58 | + const newData = cloneDeep(data); | |
59 | + if (typeof obj !== 'object') { | |
60 | + newData[index][key] = obj; | |
61 | + } else { | |
62 | + newData[index][key] = obj.target?.value; | |
63 | + } | |
64 | + setData(newData); | |
65 | + }; | |
66 | + const columns: ProColumns<any>[] = [ | |
67 | + { | |
68 | + title: 'ID', | |
69 | + dataIndex: 'id', | |
70 | + width: 120, | |
71 | + render: (_, record) => <Input value={record.id} disabled />, | |
72 | + }, | |
73 | + { | |
74 | + title: '商品编号', | |
75 | + dataIndex: 'productCode', | |
76 | + width: 120, | |
77 | + render: (_, record) => <Input value={record.productCode} disabled />, | |
78 | + }, | |
79 | + { | |
80 | + title: '商品名称', | |
81 | + dataIndex: 'productName', | |
82 | + width: 120, | |
83 | + render: (_, record) => <Input value={record.productName} disabled />, | |
84 | + }, | |
85 | + { | |
86 | + title: '商品参数', | |
87 | + dataIndex: 'parameters', | |
88 | + width: 80, | |
89 | + render: (_, record) => <Input value={record.parameters} disabled />, | |
90 | + }, | |
91 | + { | |
92 | + title: '商品数量', | |
93 | + dataIndex: 'status', | |
94 | + render: (_, record) => <InputNumber value={record.quantity} disabled />, | |
95 | + }, | |
96 | + { | |
97 | + title: '包裹数量', | |
98 | + dataIndex: 'packageNumber', | |
99 | + render: (_, record, index) => ( | |
100 | + <InputNumber | |
101 | + min={1} | |
102 | + value={record.packageNumber} | |
103 | + defaultValue={1} | |
104 | + onChange={(value) => handleChange('packageNumber', index, value)} | |
105 | + /> | |
106 | + ), | |
107 | + }, | |
108 | + { | |
109 | + title: '物流方式', | |
110 | + key: 'logisticsMethod', | |
111 | + render: (_, record, index) => ( | |
112 | + <Select | |
113 | + style={{ minWidth: 150 }} | |
114 | + placeholder="请输入物流方式" | |
115 | + value={record.logisticsMethod} | |
116 | + options={enumToSelect(LOGISTICS_STATUS_OPTIONS)} | |
117 | + onChange={(value) => { | |
118 | + handleChange('logisticsMethod', index, value); //修改时更改record数据 | |
119 | + if (value === 'OTHER_LOGISTICS') { | |
120 | + message.info( | |
121 | + '您选择的是[其他物流方式],请将该物流方式写在备注中', | |
122 | + ); | |
123 | + } | |
124 | + }} | |
125 | + /> | |
126 | + ), | |
127 | + }, | |
128 | + { | |
129 | + title: '物流单号', | |
130 | + key: 'serialNumber', | |
131 | + render: (_, record, index) => ( | |
132 | + <Input | |
133 | + placeholder="请输入物流单号" | |
134 | + value={record.serialNumber} | |
135 | + onChange={(value) => { | |
136 | + handleChange('serialNumber', index, value); | |
137 | + }} | |
138 | + /> | |
139 | + ), | |
140 | + }, | |
141 | + { | |
142 | + title: '物流备注', | |
143 | + dataIndex: 'packageNumber', | |
144 | + render: (_, record, index) => ( | |
145 | + <Input.TextArea | |
146 | + value={record.logisticsNotes} | |
147 | + onChange={(value) => handleChange('logisticsNotes', index, value)} | |
148 | + /> | |
149 | + ), | |
150 | + }, | |
151 | + ]; | |
152 | + | |
153 | + return ( | |
154 | + <Modal | |
155 | + open | |
156 | + width={1000} | |
157 | + title={isSendProduct ? '发货' : '修改发货信息'} | |
158 | + onOk={async () => { | |
159 | + //请求体封装 | |
160 | + let list = data.map((item) => { | |
161 | + return { | |
162 | + id: item.id, | |
163 | + logisticsMethod: item.logisticsMethod, | |
164 | + serialNumber: item.serialNumber, | |
165 | + packageNumber: | |
166 | + item.packageNumber === null || item.packageNumber === undefined | |
167 | + ? 1 | |
168 | + : item.packageNumber, | |
169 | + logisticsNotes: item.logisticsNotes, | |
170 | + }; | |
171 | + }); | |
172 | + | |
173 | + for (let item of list) { | |
174 | + let method = item.logisticsMethod; | |
175 | + let notes = item.logisticsNotes; | |
176 | + if ( | |
177 | + method === 'OTHER_LOGISTICS' && | |
178 | + (notes === '' || notes === undefined) | |
179 | + ) { | |
180 | + message.error( | |
181 | + '请检查:物流方式为[其他物流方式]的记录中,物流备注不能为空!请将实际的物流方式填写在备注中!', | |
182 | + ); | |
183 | + return; | |
184 | + } | |
185 | + } | |
186 | + let body = { id: data[0].mainOrderId, list: list, flag: false }; | |
187 | + if (isSendProduct) { | |
188 | + body.flag = true; | |
189 | + } | |
190 | + //发货请求 | |
191 | + let res; | |
192 | + if (optType(CHECK_TYPE.SUPPLIER)) { | |
193 | + res = await postServiceOrderSupplierSendOrder({ data: body }); | |
194 | + } else if (optType(CHECK_TYPE.PROCURE)) { | |
195 | + res = await postServiceOrderProcureSend({ data: body }); | |
196 | + } else { | |
197 | + res = await postServiceOrderSendProduct({ data: body }); | |
198 | + } | |
199 | + | |
200 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
201 | + message.success(res.message); | |
202 | + onClose(); | |
203 | + } | |
204 | + }} | |
205 | + onCancel={() => { | |
206 | + setVisible(false); | |
207 | + }} | |
208 | + footer={[ | |
209 | + <Button | |
210 | + key="back" | |
211 | + onClick={() => { | |
212 | + setVisible(false); | |
213 | + }} | |
214 | + > | |
215 | + 取消 | |
216 | + </Button>, | |
217 | + <Button | |
218 | + key="selfDeliver" | |
219 | + type="primary" | |
220 | + onClick={async () => { | |
221 | + //请求体封装 | |
222 | + let list = data.map((item) => { | |
223 | + return { | |
224 | + id: item.id, | |
225 | + deliverType: 'SELF_DELIVER', | |
226 | + }; | |
227 | + }); | |
228 | + | |
229 | + let body = { id: data[0].mainOrderId, list: list, flag: false }; | |
230 | + if (isSendProduct) { | |
231 | + body.flag = true; | |
232 | + } | |
233 | + //发货请求 | |
234 | + let res; | |
235 | + if (optType(CHECK_TYPE.SUPPLIER)) { | |
236 | + res = await postServiceOrderSupplierSendOrder({ data: body }); | |
237 | + } else if (optType(CHECK_TYPE.PROCURE)) { | |
238 | + res = await postServiceOrderProcureSend({ data: body }); | |
239 | + } else { | |
240 | + res = await postServiceOrderSendProduct({ data: body }); | |
241 | + } | |
242 | + | |
243 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
244 | + message.success(res.message); | |
245 | + onClose(); | |
246 | + } | |
247 | + }} | |
248 | + > | |
249 | + 自行派送 | |
250 | + </Button>, | |
251 | + <Button | |
252 | + key="submit" | |
253 | + type="primary" | |
254 | + onClick={async () => { | |
255 | + //请求体封装 | |
256 | + let list = data.map((item) => { | |
257 | + return { | |
258 | + id: item.id, | |
259 | + logisticsMethod: item.logisticsMethod, | |
260 | + serialNumber: item.serialNumber, | |
261 | + packageNumber: | |
262 | + item.packageNumber === null || | |
263 | + item.packageNumber === undefined | |
264 | + ? 1 | |
265 | + : item.packageNumber, | |
266 | + logisticsNotes: item.logisticsNotes, | |
267 | + }; | |
268 | + }); | |
269 | + | |
270 | + for (let item of list) { | |
271 | + let method = item.logisticsMethod; | |
272 | + let notes = item.logisticsNotes; | |
273 | + if ( | |
274 | + method === 'OTHER_LOGISTICS' && | |
275 | + (notes === '' || notes === undefined) | |
276 | + ) { | |
277 | + message.error( | |
278 | + '请检查:物流方式为[其他物流方式]的记录中,物流备注不能为空!请将实际的物流方式填写在备注中!', | |
279 | + ); | |
280 | + return; | |
281 | + } | |
282 | + } | |
283 | + let body = { id: data[0].mainOrderId, list: list, flag: false }; | |
284 | + if (isSendProduct) { | |
285 | + body.flag = true; | |
286 | + } | |
287 | + //发货请求 | |
288 | + let res; | |
289 | + if (optType(CHECK_TYPE.SUPPLIER)) { | |
290 | + res = await postServiceOrderSupplierSendOrder({ data: body }); | |
291 | + } else if (optType(CHECK_TYPE.PROCURE)) { | |
292 | + res = await postServiceOrderProcureSend({ data: body }); | |
293 | + } else { | |
294 | + res = await postServiceOrderSendProduct({ data: body }); | |
295 | + } | |
296 | + | |
297 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
298 | + message.success(res.message); | |
299 | + onClose(); | |
300 | + } | |
301 | + }} | |
302 | + > | |
303 | + 确认 | |
304 | + </Button>, | |
305 | + ]} | |
306 | + > | |
307 | + <Flex vertical> | |
308 | + <strong>将物流方式和物流单号更新到下方所有订单</strong> | |
309 | + <span className="text-[red] py-1"> | |
310 | + 选择【其他物流方式】时,需要将对应的物流方式填写在备注中。例如:如果发圆通快递,系统上没有这个选项,就需要选【其他物流方式】,然后把“圆通快递”填在备注上。 | |
311 | + </span> | |
312 | + </Flex> | |
313 | + | |
314 | + <ProForm | |
315 | + layout="inline" | |
316 | + submitter={false} | |
317 | + className="mb-8" | |
318 | + formRef={form} | |
319 | + > | |
320 | + <Row gutter={[0, 6]}> | |
321 | + <Col> | |
322 | + <ProFormSelect | |
323 | + placeholder="请输入物流方式" | |
324 | + name="logisticsMethod" | |
325 | + width="sm" | |
326 | + label="物流方式" | |
327 | + options={enumToSelect(LOGISTICS_STATUS_OPTIONS)} | |
328 | + /> | |
329 | + <ProFormText name="logisticsNotes" label="物流备注"></ProFormText> | |
330 | + </Col> | |
331 | + <Col> | |
332 | + <ProFormText name="serialNumber" label="物流单号"></ProFormText> | |
333 | + </Col> | |
334 | + </Row> | |
335 | + | |
336 | + <Button | |
337 | + type="primary" | |
338 | + onClick={() => { | |
339 | + const values = form.current.getFieldsValue(); | |
340 | + if (values.logisticsMethod === 'OTHER_LOGISTICS') { | |
341 | + message.info( | |
342 | + '自动填充成功!您选择的是其他物流方式,请将物流方式写在物流备注中!', | |
343 | + ); | |
344 | + } | |
345 | + let newData = cloneDeep(data); | |
346 | + newData = newData.map((item) => ({ | |
347 | + ...item, | |
348 | + logisticsMethod: values.logisticsMethod, | |
349 | + serialNumber: values.serialNumber, | |
350 | + logisticsNotes: values.logisticsNotes, | |
351 | + })); | |
352 | + setData(newData); | |
353 | + }} | |
354 | + > | |
355 | + 批量更新 | |
356 | + </Button> | |
357 | + </ProForm> | |
358 | + <ProTable<any> | |
359 | + className="px-0" | |
360 | + dataSource={data} | |
361 | + rowKey="id" | |
362 | + pagination={false} | |
363 | + columns={columns} | |
364 | + search={false} | |
365 | + dateFormatter="string" | |
366 | + options={false} | |
367 | + scroll={{ x: 1400 }} | |
368 | + /> | |
369 | + </Modal> | |
370 | + ); | |
371 | +}; | |
372 | + | |
373 | +export default DeliverModal; | ... | ... |
src/pages/Order/FeedBack/FeedbackRegistrationModal.tsx
0 → 100644
1 | +import { postServiceOrderFeedbackRegistration } from '@/services/request'; | |
2 | +import { Input, Modal } from 'antd'; | |
3 | +import { useState } from 'react'; | |
4 | + | |
5 | +// import { cloneDeep } from 'lodash'; | |
6 | +export default ({ setVisible, subOrders, mainOrder, onClose }) => { | |
7 | + const [isModalOpen] = useState(true); | |
8 | + const { TextArea } = Input; | |
9 | + const [textValue, setTextValue] = useState(''); | |
10 | + console.log(mainOrder); | |
11 | + | |
12 | + const handleOk = async () => { | |
13 | + await postServiceOrderFeedbackRegistration({ | |
14 | + data: { | |
15 | + id: subOrders[0].id, | |
16 | + feedbackRegistrationContent: textValue, | |
17 | + }, | |
18 | + }); | |
19 | + onClose(); | |
20 | + // setIsModalOpen(false); | |
21 | + // onClose(); | |
22 | + }; | |
23 | + const handleCancel = () => { | |
24 | + setVisible(false); | |
25 | + onClose(); | |
26 | + // setIsModalOpen(false); | |
27 | + // onClose(); | |
28 | + }; | |
29 | + const handleChange = (e) => { | |
30 | + setTextValue(e.target.value); | |
31 | + }; | |
32 | + return ( | |
33 | + <> | |
34 | + {/* <ModalForm<{ | |
35 | + filePaths: any; | |
36 | + }> | |
37 | + width={500} | |
38 | + open | |
39 | + title="回访登记" | |
40 | + form={form} | |
41 | + autoFocusFirstInput | |
42 | + modalProps={{ | |
43 | + okText: '提交', | |
44 | + cancelText: '取消', | |
45 | + destroyOnClose: true, | |
46 | + onCancel: () => { | |
47 | + setVisible(false); | |
48 | + }, | |
49 | + }} | |
50 | + onFinish={async () => { | |
51 | + onClose(); | |
52 | + }} | |
53 | + onOpenChange={setVisible} | |
54 | + > | |
55 | + <TextArea rows={6} placeholder="请输入" /> | |
56 | + </ModalForm> */} | |
57 | + <Modal | |
58 | + title="回访登记" | |
59 | + open={isModalOpen} | |
60 | + onOk={handleOk} | |
61 | + onCancel={handleCancel} | |
62 | + > | |
63 | + <TextArea | |
64 | + rows={6} | |
65 | + placeholder="请输入" | |
66 | + onChange={handleChange} | |
67 | + value={textValue} | |
68 | + /> | |
69 | + </Modal> | |
70 | + </> | |
71 | + ); | |
72 | +}; | ... | ... |
src/pages/Order/FeedBack/FinancialDrawer.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { | |
3 | + postServiceOrderEditOrder, | |
4 | + postServiceOrderInvoicing, | |
5 | +} from '@/services'; | |
6 | +import { FloatAdd, enumToSelect, enumValueToLabel } from '@/utils'; | |
7 | +import { getReceivingCompanyOptions } from '@/utils/order'; | |
8 | +import { | |
9 | + DrawerForm, | |
10 | + ProFormDatePicker, | |
11 | + ProFormDigit, | |
12 | + ProFormSelect, | |
13 | + ProFormText, | |
14 | + ProFormTextArea, | |
15 | +} from '@ant-design/pro-components'; | |
16 | +import { Button, Form, message } from 'antd'; | |
17 | +import { useEffect, useState } from 'react'; | |
18 | +import { INVOCING_STATUS_OPTIONS_OLD, PAYEE_OPTIONS } from './constant'; | |
19 | + | |
20 | +export default ({ | |
21 | + mainOrder, | |
22 | + subOrders, | |
23 | + isEdit, | |
24 | + isMainOrder, | |
25 | + cancel, | |
26 | + onClose, | |
27 | +}) => { | |
28 | + const [invoicingStatus, setInvoicingStatus] = useState(''); | |
29 | + const subIds = subOrders.map((item) => item.id); | |
30 | + useEffect(() => { | |
31 | + // 在组件挂载或数据变化时,更新组件状态 | |
32 | + if (mainOrder) { | |
33 | + setInvoicingStatus(subOrders[0]?.invoicingStatus); | |
34 | + } | |
35 | + }, [mainOrder]); | |
36 | + useEffect(() => { | |
37 | + console.log(JSON.stringify(subOrders)); | |
38 | + }, []); | |
39 | + | |
40 | + const [form] = Form.useForm<{ name: string; company: string }>(); | |
41 | + | |
42 | + /** | |
43 | + * 自动选择收款公司 | |
44 | + * @param receivingCompany | |
45 | + */ | |
46 | + function chooseReceivingCompany(receivingCompany: any) { | |
47 | + form.setFieldValue('payee', receivingCompany); | |
48 | + } | |
49 | + | |
50 | + /** | |
51 | + * 计算选中子订单的主订单金额之和 | |
52 | + */ | |
53 | + function computeTotalPayment() { | |
54 | + let distinctMap = new Map(); | |
55 | + | |
56 | + subOrders?.forEach((item: any) => { | |
57 | + distinctMap.set(item.mainOrderId, item.totalPayment); | |
58 | + }); | |
59 | + | |
60 | + let sum = 0; | |
61 | + for (let p of distinctMap.values()) { | |
62 | + sum = FloatAdd(p, sum); | |
63 | + } | |
64 | + | |
65 | + form.setFieldValue('money', sum); | |
66 | + } | |
67 | + | |
68 | + return ( | |
69 | + <DrawerForm<{ | |
70 | + name: string; | |
71 | + company: string; | |
72 | + }> | |
73 | + open | |
74 | + title="财务信息" | |
75 | + resize={{ | |
76 | + onResize() { | |
77 | + console.log('resize!'); | |
78 | + }, | |
79 | + maxWidth: window.innerWidth * 0.8, | |
80 | + minWidth: 400, | |
81 | + }} | |
82 | + initialValues={mainOrder} | |
83 | + form={form} | |
84 | + autoFocusFirstInput | |
85 | + drawerProps={{ | |
86 | + destroyOnClose: true, | |
87 | + }} | |
88 | + submitTimeout={2000} | |
89 | + onFinish={async (values) => { | |
90 | + let res; | |
91 | + let body = values; | |
92 | + body.subIds = subIds; | |
93 | + if (isEdit) { | |
94 | + res = await postServiceOrderEditOrder({ data: body }); | |
95 | + } else { | |
96 | + res = await postServiceOrderInvoicing({ data: body }); | |
97 | + } | |
98 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
99 | + message.success(res.message); | |
100 | + onClose(); | |
101 | + } | |
102 | + }} | |
103 | + onOpenChange={(val) => { | |
104 | + return !val && cancel(); | |
105 | + }} | |
106 | + > | |
107 | + {isMainOrder ? ( | |
108 | + <ProFormSelect | |
109 | + placeholder="选择是否需要开票" | |
110 | + name="invoicingStatus" | |
111 | + width="lg" | |
112 | + label="是否需要开票" | |
113 | + options={enumToSelect(INVOCING_STATUS_OPTIONS_OLD)} | |
114 | + onChange={setInvoicingStatus} | |
115 | + initialValue={subOrders[0]?.invoicingStatus} | |
116 | + // disabled={mainInfoDisbled} | |
117 | + rules={[{ required: true, message: '是否需要开票必填' }]} | |
118 | + /> | |
119 | + ) : ( | |
120 | + '' | |
121 | + )} | |
122 | + | |
123 | + <ProFormTextArea | |
124 | + width="lg" | |
125 | + name="invoiceIdentificationNumber" | |
126 | + label="开票信息" | |
127 | + placeholder="请输入开票信息" | |
128 | + disabled | |
129 | + /> | |
130 | + <ProFormText | |
131 | + width="lg" | |
132 | + name="bank" | |
133 | + label="开户银行" | |
134 | + placeholder="请输入开户银行" | |
135 | + disabled | |
136 | + /> | |
137 | + <ProFormText | |
138 | + width="lg" | |
139 | + name="bankAccountNumber" | |
140 | + label="开户银行账号" | |
141 | + placeholder="请输入开户银行账号" | |
142 | + disabled | |
143 | + /> | |
144 | + | |
145 | + {invoicingStatus !== 'UN_INVOICE' | |
146 | + ? [ | |
147 | + <ProFormDatePicker | |
148 | + key="invoicingTime" | |
149 | + width="lg" | |
150 | + name="invoicingTime" | |
151 | + label="开票时间" | |
152 | + disabled={isEdit} | |
153 | + rules={[ | |
154 | + { required: !isEdit ? true : false, message: '这是必填项' }, | |
155 | + ]} | |
156 | + initialValue={subOrders[0]?.invoicingTime} | |
157 | + />, | |
158 | + <ProFormText | |
159 | + key="purchaser" | |
160 | + width="lg" | |
161 | + name="purchaser" | |
162 | + label="抬头名称" | |
163 | + disabled={isEdit} | |
164 | + rules={[ | |
165 | + { required: !isEdit ? true : false, message: '这是必填项' }, | |
166 | + ]} | |
167 | + initialValue={subOrders[0]?.purchaser} | |
168 | + />, | |
169 | + <ProFormDatePicker | |
170 | + key="financialReceiptIssuanceTime" | |
171 | + width="lg" | |
172 | + name="financialReceiptIssuanceTime" | |
173 | + label="开收据时间" | |
174 | + initialValue={subOrders[0]?.financialReceiptIssuanceTime} | |
175 | + />, | |
176 | + <ProFormDatePicker | |
177 | + key="collectMoneyTime" | |
178 | + width="lg" | |
179 | + name="collectMoneyTime" | |
180 | + label="收款时间" | |
181 | + initialValue={subOrders[0]?.collectMoneyTime} | |
182 | + />, | |
183 | + <ProFormText | |
184 | + width="lg" | |
185 | + key="invoiceNumber" | |
186 | + name="invoiceNumber" | |
187 | + label="发票号码" | |
188 | + initialValue={subOrders[0]?.invoiceNumber} | |
189 | + rules={[{ required: true, message: '发票号码必填' }]} | |
190 | + />, | |
191 | + <div | |
192 | + key="salesChooseReceivingCompany" | |
193 | + hidden={subOrders[0].receivingCompany === null} | |
194 | + > | |
195 | + <span className={'pl-2 text-xs text-gray-400'}> | |
196 | + 销售申请开票时选择了: | |
197 | + {enumValueToLabel( | |
198 | + subOrders[0].receivingCompany, | |
199 | + getReceivingCompanyOptions(PAYEE_OPTIONS), | |
200 | + )} | |
201 | + </span> | |
202 | + <span | |
203 | + hidden={subOrders[0].receivingCompany === 'ANY'} | |
204 | + className={ | |
205 | + 'pl-2 text-xs text-[#1677ff] cursor-pointer hover:text-[#64abf7]' | |
206 | + } | |
207 | + onClick={() => { | |
208 | + chooseReceivingCompany(subOrders[0].receivingCompany); | |
209 | + }} | |
210 | + > | |
211 | + 选择 | |
212 | + </span> | |
213 | + </div>, | |
214 | + <ProFormSelect | |
215 | + key="payee" | |
216 | + placeholder="选择收款单位" | |
217 | + name="payee" | |
218 | + width="lg" | |
219 | + showSearch | |
220 | + label="收款单位" | |
221 | + options={enumToSelect(PAYEE_OPTIONS)} | |
222 | + initialValue={subOrders[0]?.payee} | |
223 | + rules={[{ required: true, message: '收款单位必填' }]} | |
224 | + />, | |
225 | + | |
226 | + <div id="total-payment" key="money"> | |
227 | + <ProFormDigit | |
228 | + key="money" | |
229 | + name="money" | |
230 | + width="lg" | |
231 | + label="金额" | |
232 | + rules={[{ required: true, message: '金额必填' }]} | |
233 | + tooltip="点击计算,合计所有子订单对应主订单总额" | |
234 | + fieldProps={{ | |
235 | + addonAfter: ( | |
236 | + <Button | |
237 | + className="rounded-l-none" | |
238 | + type="primary" | |
239 | + onClick={computeTotalPayment} | |
240 | + > | |
241 | + 计算 | |
242 | + </Button> | |
243 | + ), | |
244 | + }} | |
245 | + /> | |
246 | + </div>, | |
247 | + ] | |
248 | + : ''} | |
249 | + | |
250 | + <ProFormSelect | |
251 | + placeholder="是否完全开票" | |
252 | + name="afterInvoicingStatus" | |
253 | + width="lg" | |
254 | + label="是否完全开票" | |
255 | + options={[ | |
256 | + { label: '完全开票', value: 'COMPLETE_INVOICING' }, | |
257 | + { label: '部分开票', value: 'PARTIAL_INVOICING' }, | |
258 | + ]} | |
259 | + // disabled={mainInfoDisbled} | |
260 | + initialValue={ | |
261 | + subOrders[0]?.afterInvoicingStatus === 'APPLY_FOR_INVOICING' | |
262 | + ? 'COMPLETE_INVOICING' | |
263 | + : subOrders[0]?.afterInvoicingStatus | |
264 | + } | |
265 | + rules={[{ required: true, message: '是否完全开票必填' }]} | |
266 | + /> | |
267 | + <ProFormTextArea | |
268 | + width="lg" | |
269 | + name="invoicingNotes" | |
270 | + label="备注" | |
271 | + initialValue={subOrders[0]?.invoicingNotes} | |
272 | + /> | |
273 | + </DrawerForm> | |
274 | + ); | |
275 | +}; | ... | ... |
src/pages/Order/FeedBack/FinancialEditDrawer.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { postServiceOrderNoNeedInvoicingEdit } from '@/services'; | |
3 | +import { enumToSelect } from '@/utils'; | |
4 | +import { | |
5 | + DrawerForm, | |
6 | + ProFormDatePicker, | |
7 | + ProFormSelect, | |
8 | + ProFormText, | |
9 | +} from '@ant-design/pro-components'; | |
10 | +import { Form, message } from 'antd'; | |
11 | +import { useEffect, useState } from 'react'; | |
12 | +import { INVOCING_STATUS_OPTIONS_OLD } from './constant'; | |
13 | + | |
14 | +export default ({ mainOrder, subOrders, setVisible, isMainOrder, onClose }) => { | |
15 | + const [invoicingStatus, setInvoicingStatus] = useState(''); | |
16 | + useEffect(() => { | |
17 | + setInvoicingStatus(subOrders[0]?.invoicingStatus); | |
18 | + }, []); | |
19 | + const subOrderIds = subOrders?.map((subOrder) => { | |
20 | + return subOrder?.id; | |
21 | + }); | |
22 | + const mainOrderId = mainOrder.id; | |
23 | + const [form] = Form.useForm<{ | |
24 | + collectMoneyTime: string; | |
25 | + subIds: []; | |
26 | + financialReceiptIssuanceTime: string; | |
27 | + }>(); | |
28 | + | |
29 | + //回显开收据时间和收款时间 | |
30 | + if (!isMainOrder) { | |
31 | + form.setFieldValue('collectMoneyTime', subOrders[0].collectMoneyTime); | |
32 | + form.setFieldValue( | |
33 | + 'financialReceiptIssuanceTime', | |
34 | + subOrders[0].financialReceiptIssuanceTime, | |
35 | + ); | |
36 | + } | |
37 | + | |
38 | + return ( | |
39 | + <DrawerForm<{ | |
40 | + collectMoneyTime: string; | |
41 | + financialReceiptIssuanceTime: string; | |
42 | + subIds: []; | |
43 | + }> | |
44 | + open | |
45 | + title={isMainOrder ? '编辑开票信息' : '编辑收款时间'} | |
46 | + resize={{ | |
47 | + onResize() { | |
48 | + console.log('resize!'); | |
49 | + }, | |
50 | + maxWidth: window.innerWidth * 0.8, | |
51 | + minWidth: 400, | |
52 | + }} | |
53 | + initialValues={mainOrder} | |
54 | + form={form} | |
55 | + autoFocusFirstInput | |
56 | + drawerProps={{ | |
57 | + destroyOnClose: true, | |
58 | + }} | |
59 | + submitTimeout={2000} | |
60 | + onFinish={async (values) => { | |
61 | + let body = { | |
62 | + ...values, | |
63 | + mainOrderId: mainOrderId, | |
64 | + subIds: subOrderIds, | |
65 | + }; | |
66 | + | |
67 | + if (!isMainOrder) { | |
68 | + body.invoicingStatus = 'UN_INVOICE'; | |
69 | + } | |
70 | + | |
71 | + let res = await postServiceOrderNoNeedInvoicingEdit({ | |
72 | + data: body, | |
73 | + }); | |
74 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
75 | + message.success(res.message); | |
76 | + onClose(); | |
77 | + } | |
78 | + }} | |
79 | + onOpenChange={(val) => { | |
80 | + return !val && setVisible(val); | |
81 | + }} | |
82 | + > | |
83 | + {isMainOrder ? ( | |
84 | + <ProFormSelect | |
85 | + placeholder="选择是否需要开票" | |
86 | + name="invoicingStatus" | |
87 | + width="lg" | |
88 | + label="是否需要开票" | |
89 | + options={enumToSelect(INVOCING_STATUS_OPTIONS_OLD)} | |
90 | + onChange={setInvoicingStatus} | |
91 | + initialValue={subOrders[0]?.invoicingStatus} | |
92 | + // disabled={mainInfoDisbled} | |
93 | + rules={[{ required: true, message: '是否需要开票必填' }]} | |
94 | + /> | |
95 | + ) : ( | |
96 | + '' | |
97 | + )} | |
98 | + | |
99 | + {invoicingStatus !== 'UN_INVOICE' ? ( | |
100 | + <> | |
101 | + <ProFormText | |
102 | + key="invoiceIdentificationNumber" | |
103 | + width="lg" | |
104 | + name="invoiceIdentificationNumber" | |
105 | + label="开票信息" | |
106 | + placeholder="请输入开票信息" | |
107 | + rules={[{ required: true, message: '开票信息必填' }]} | |
108 | + /> | |
109 | + <ProFormText | |
110 | + key="bank" | |
111 | + width="lg" | |
112 | + name="bank" | |
113 | + label="开户银行" | |
114 | + placeholder="请输入开户银行" | |
115 | + /> | |
116 | + <ProFormText | |
117 | + key="bankAccountNumber" | |
118 | + width="lg" | |
119 | + name="bankAccountNumber" | |
120 | + label="开户银行账号" | |
121 | + placeholder="请输入开户银行账号" | |
122 | + /> | |
123 | + </> | |
124 | + ) : ( | |
125 | + '' | |
126 | + )} | |
127 | + | |
128 | + <ProFormDatePicker | |
129 | + key="financialReceiptIssuanceTime" | |
130 | + width="lg" | |
131 | + name="financialReceiptIssuanceTime" | |
132 | + label="开收据时间" | |
133 | + // rules={[ | |
134 | + // { | |
135 | + // required: !isMainOrder && invoicingStatus === 'UN_INVOICE', | |
136 | + // message: '开收据时间必填', | |
137 | + // }, | |
138 | + // ]} | |
139 | + /> | |
140 | + <ProFormDatePicker | |
141 | + key="collectMoneyTime" | |
142 | + width="lg" | |
143 | + name="collectMoneyTime" | |
144 | + label="收款时间" | |
145 | + // rules={[ | |
146 | + // { | |
147 | + // required: !isMainOrder && invoicingStatus === 'UN_INVOICE', | |
148 | + // message: '收款时间必填', | |
149 | + // }, | |
150 | + // ]} | |
151 | + /> | |
152 | + </DrawerForm> | |
153 | + ); | |
154 | +}; | ... | ... |
src/pages/Order/FeedBack/FinancialMergeDrawer.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { enumToSelect } from '@/utils'; | |
3 | +import { | |
4 | + DrawerForm, | |
5 | + ProFormDatePicker, | |
6 | + ProFormDigit, | |
7 | + ProFormSelect, | |
8 | + ProFormText, | |
9 | + ProFormTextArea, | |
10 | +} from '@ant-design/pro-components'; | |
11 | +import { Form, message } from 'antd'; | |
12 | +import { PAYEE_OPTIONS } from './constant'; | |
13 | + | |
14 | +export default ({ dataList, setVisible, onClose }) => { | |
15 | + // let subOrderIds = dataList?.map((item) => { | |
16 | + // return item.id; | |
17 | + // }); | |
18 | + let firstMainOrder = dataList[0]; | |
19 | + let bank = firstMainOrder?.bank; | |
20 | + let bankAccountNumber = firstMainOrder?.bankAccountNumber; | |
21 | + let invoiceIdentificationNumber = firstMainOrder?.invoiceIdentificationNumber; | |
22 | + | |
23 | + const [form] = Form.useForm<{ | |
24 | + invoicingTime: string; | |
25 | + financialReceiptIssuanceTime: string; | |
26 | + invoicingNotes: string; | |
27 | + afterInvoicingStatus: string; | |
28 | + collectMoneyTime: string; | |
29 | + }>(); | |
30 | + return ( | |
31 | + <DrawerForm | |
32 | + open | |
33 | + title="合并开票" | |
34 | + resize={{ | |
35 | + onResize() { | |
36 | + console.log('resize!'); | |
37 | + }, | |
38 | + maxWidth: window.innerWidth * 0.8, | |
39 | + minWidth: 400, | |
40 | + }} | |
41 | + form={form} | |
42 | + autoFocusFirstInput | |
43 | + drawerProps={{ | |
44 | + destroyOnClose: true, | |
45 | + }} | |
46 | + submitTimeout={2000} | |
47 | + onFinish={async (values) => { | |
48 | + console.log(values); | |
49 | + let res; | |
50 | + let body = values; | |
51 | + body.subIds = subIds; | |
52 | + body.mainOrderId = mainOrder.id; | |
53 | + body.mainorderOrSubOrderInvoicing = isMainOrder; | |
54 | + if (isEdit) { | |
55 | + res = await postServiceOrderEditOrder({ data: body }); | |
56 | + } else { | |
57 | + res = await postServiceOrderInvoicing({ data: body }); | |
58 | + } | |
59 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
60 | + message.success(res.message); | |
61 | + onClose(); | |
62 | + } | |
63 | + }} | |
64 | + onOpenChange={(val) => { | |
65 | + return !val && setVisible(); | |
66 | + }} | |
67 | + > | |
68 | + <ProFormText | |
69 | + width="lg" | |
70 | + name="invoiceIdentificationNumber" | |
71 | + label="开票信息" | |
72 | + placeholder="请输入开票信息" | |
73 | + initialValue={invoiceIdentificationNumber} | |
74 | + disabled | |
75 | + /> | |
76 | + <ProFormText | |
77 | + width="lg" | |
78 | + name="bank" | |
79 | + label="开户银行" | |
80 | + placeholder="请输入开户银行" | |
81 | + initialValue={bank} | |
82 | + disabled | |
83 | + /> | |
84 | + <ProFormText | |
85 | + width="lg" | |
86 | + name="bankAccountNumber" | |
87 | + label="开户银行账号" | |
88 | + placeholder="请输入开户银行账号" | |
89 | + initialValue={bankAccountNumber} | |
90 | + disabled | |
91 | + /> | |
92 | + | |
93 | + <ProFormDatePicker | |
94 | + key="invoicingTime" | |
95 | + width="lg" | |
96 | + name="invoicingTime" | |
97 | + label="开票时间" | |
98 | + rules={[{ required: true, message: '这是必填项' }]} | |
99 | + /> | |
100 | + <ProFormDatePicker | |
101 | + key="financialReceiptIssuanceTime" | |
102 | + width="lg" | |
103 | + name="financialReceiptIssuanceTime" | |
104 | + label="开收据时间" | |
105 | + /> | |
106 | + <ProFormDatePicker | |
107 | + key="collectMoneyTime" | |
108 | + width="lg" | |
109 | + name="collectMoneyTime" | |
110 | + label="收款时间" | |
111 | + /> | |
112 | + <ProFormText | |
113 | + width="lg" | |
114 | + key="invoiceNumber" | |
115 | + name="invoiceNumber" | |
116 | + label="发票号码" | |
117 | + rules={[{ required: true, message: '发票号码必填' }]} | |
118 | + /> | |
119 | + <ProFormSelect | |
120 | + key="payee" | |
121 | + placeholder="选择收款单位" | |
122 | + name="payee" | |
123 | + width="lg" | |
124 | + label="收款单位" | |
125 | + options={enumToSelect(PAYEE_OPTIONS)} | |
126 | + rules={[{ required: true, message: '收款单位必填' }]} | |
127 | + /> | |
128 | + | |
129 | + <ProFormDigit | |
130 | + key="money" | |
131 | + name="money" | |
132 | + width="lg" | |
133 | + label="金额" | |
134 | + rules={[{ required: true, message: '金额必填' }]} | |
135 | + /> | |
136 | + <ProFormSelect | |
137 | + placeholder="是否完全开票" | |
138 | + name="afterInvoicingStatus" | |
139 | + width="lg" | |
140 | + label="是否完全开票" | |
141 | + options={[ | |
142 | + { label: '完全开票', value: 'COMPLETE_INVOICING' }, | |
143 | + { label: '部分开票', value: 'PARTIAL_INVOICING' }, | |
144 | + ]} | |
145 | + initialValue={'COMPLETE_INVOICING'} | |
146 | + /> | |
147 | + <ProFormTextArea width="lg" name="invoicingNotes" label="备注" /> | |
148 | + </DrawerForm> | |
149 | + ); | |
150 | +}; | ... | ... |
src/pages/Order/FeedBack/FinancialReceiptsModal.tsx
0 → 100644
1 | +import { postServiceOrderUpdateHirePurchase } from '@/services'; | |
2 | +import { | |
3 | + EditableProTable, | |
4 | + ModalForm, | |
5 | + ProColumns, | |
6 | + ProForm, | |
7 | +} from '@ant-design/pro-components'; | |
8 | +import { Form } from 'antd'; | |
9 | +import { useState } from 'react'; | |
10 | + | |
11 | +// import { cloneDeep } from 'lodash'; | |
12 | +export default ({ setVisible, datas, onClose }) => { | |
13 | + const [form] = Form.useForm<{ name: string; company: string }>(); | |
14 | + type DataSourceType = { | |
15 | + id: React.Key; | |
16 | + hirePurchaseMethod?: string; | |
17 | + hirePurchaseMethodName?: string; | |
18 | + money?: number; | |
19 | + updateTime?: string; | |
20 | + notes?: string; | |
21 | + }; | |
22 | + const defaultData: DataSourceType[] = [ | |
23 | + { | |
24 | + id: 1, | |
25 | + hirePurchaseMethod: 'ADVANCE_CHARGE', | |
26 | + hirePurchaseMethodName: '预付款', | |
27 | + money: undefined, | |
28 | + updateTime: undefined, | |
29 | + notes: undefined, | |
30 | + }, | |
31 | + { | |
32 | + id: 2, | |
33 | + hirePurchaseMethod: 'PAYMENT_FOR_SHIPMENT', | |
34 | + hirePurchaseMethodName: '发货款', | |
35 | + money: undefined, | |
36 | + updateTime: undefined, | |
37 | + notes: undefined, | |
38 | + }, | |
39 | + { | |
40 | + id: 3, | |
41 | + hirePurchaseMethod: 'ACCEPTANCE_PAYMENT', | |
42 | + hirePurchaseMethodName: '验收款', | |
43 | + money: undefined, | |
44 | + updateTime: undefined, | |
45 | + notes: undefined, | |
46 | + }, | |
47 | + { | |
48 | + id: 4, | |
49 | + hirePurchaseMethod: 'BALANCE_PAYMENT', | |
50 | + hirePurchaseMethodName: '尾款', | |
51 | + money: undefined, | |
52 | + updateTime: undefined, | |
53 | + notes: undefined, | |
54 | + }, | |
55 | + ]; | |
56 | + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>(() => | |
57 | + // defaultData.map((item) => item.id), | |
58 | + [1, 2, 3, 4], | |
59 | + ); | |
60 | + const columns: ProColumns<DataSourceType>[] = [ | |
61 | + { | |
62 | + title: '款项', | |
63 | + dataIndex: 'hirePurchaseMethodName', | |
64 | + editable: false, | |
65 | + width: '10%', | |
66 | + }, | |
67 | + { | |
68 | + title: '已收金额', | |
69 | + dataIndex: 'money', | |
70 | + valueType: 'digit', | |
71 | + width: '15%', | |
72 | + }, | |
73 | + { | |
74 | + title: '收款时间', | |
75 | + dataIndex: 'updateTime', | |
76 | + valueType: 'dateTime', | |
77 | + width: '25%', | |
78 | + }, | |
79 | + { | |
80 | + title: '备注', | |
81 | + dataIndex: 'receiptsNotes', | |
82 | + }, | |
83 | + ]; | |
84 | + return ( | |
85 | + <> | |
86 | + <ModalForm<{ | |
87 | + name: string; | |
88 | + company: string; | |
89 | + }> | |
90 | + width={1100} | |
91 | + open | |
92 | + title="收款记录" | |
93 | + form={form} | |
94 | + autoFocusFirstInput | |
95 | + modalProps={{ | |
96 | + okText: '保存', | |
97 | + cancelText: '取消', | |
98 | + destroyOnClose: true, | |
99 | + onCancel: () => { | |
100 | + setVisible(false); | |
101 | + }, | |
102 | + }} | |
103 | + onFinish={async (values) => { | |
104 | + let res = await postServiceOrderUpdateHirePurchase({ | |
105 | + data: { | |
106 | + mainOrderId: datas[0].id, | |
107 | + list: values.dataSource, | |
108 | + }, | |
109 | + }); | |
110 | + console.log(res); | |
111 | + onClose(); | |
112 | + }} | |
113 | + onOpenChange={setVisible} | |
114 | + > | |
115 | + <ProForm.Item | |
116 | + label="" | |
117 | + name="dataSource" | |
118 | + initialValue={defaultData} | |
119 | + trigger="onValuesChange" | |
120 | + > | |
121 | + <EditableProTable<DataSourceType> | |
122 | + rowKey="id" | |
123 | + toolBarRender={false} | |
124 | + columns={columns} | |
125 | + recordCreatorProps={{ | |
126 | + newRecordType: 'dataSource', | |
127 | + position: 'top', | |
128 | + record: () => ({ | |
129 | + id: Date.now(), | |
130 | + addonBefore: 'ccccccc', | |
131 | + decs: 'testdesc', | |
132 | + }), | |
133 | + style: { | |
134 | + display: 'none', | |
135 | + }, | |
136 | + }} | |
137 | + editable={{ | |
138 | + type: 'multiple', | |
139 | + editableKeys, | |
140 | + onChange: setEditableRowKeys, | |
141 | + actionRender: (row, _, dom) => { | |
142 | + return [dom.delete]; | |
143 | + }, | |
144 | + }} | |
145 | + /> | |
146 | + </ProForm.Item> | |
147 | + | |
148 | + {/* <ProForm.Group> | |
149 | + <ProFormText | |
150 | + width="sm" | |
151 | + name="name1" | |
152 | + label="款项" | |
153 | + tooltip="最长为 24 位" | |
154 | + initialValue={"预付款"} | |
155 | + disabled | |
156 | + placeholder="请输入名称" | |
157 | + /> | |
158 | + | |
159 | + <ProFormText | |
160 | + width="sm" | |
161 | + name="company" | |
162 | + label="收款时间" | |
163 | + placeholder="请输入名称" | |
164 | + /> | |
165 | + | |
166 | + <ProFormText | |
167 | + width="sm" | |
168 | + name="price" | |
169 | + label="收款金额" | |
170 | + placeholder="请输入名称" | |
171 | + /> | |
172 | + | |
173 | + <ProFormText | |
174 | + width="sm" | |
175 | + name="notes" | |
176 | + label="备注" | |
177 | + placeholder="请输入名称" | |
178 | + /> | |
179 | + </ProForm.Group> | |
180 | + | |
181 | + <ProForm.Group> | |
182 | + <ProFormText | |
183 | + width="sm" | |
184 | + name="name2" | |
185 | + initialValue={"发货款"} | |
186 | + disabled | |
187 | + tooltip="最长为 24 位" | |
188 | + placeholder="请输入名称" | |
189 | + /> | |
190 | + | |
191 | + <ProFormText | |
192 | + width="sm" | |
193 | + name="company" | |
194 | + placeholder="请输入名称" | |
195 | + /> | |
196 | + | |
197 | + <ProFormText | |
198 | + width="sm" | |
199 | + name="price" | |
200 | + placeholder="请输入名称" | |
201 | + /> | |
202 | + | |
203 | + <ProFormText | |
204 | + width="sm" | |
205 | + name="notes" | |
206 | + placeholder="请输入名称" | |
207 | + /> | |
208 | + </ProForm.Group> | |
209 | + | |
210 | + <ProForm.Group> | |
211 | + <ProFormText | |
212 | + width="sm" | |
213 | + name="name3" | |
214 | + initialValue={"验收款"} | |
215 | + disabled | |
216 | + tooltip="最长为 24 位" | |
217 | + placeholder="请输入名称" | |
218 | + /> | |
219 | + | |
220 | + <ProFormText | |
221 | + width="sm" | |
222 | + name="company" | |
223 | + placeholder="请输入名称" | |
224 | + /> | |
225 | + | |
226 | + <ProFormText | |
227 | + width="sm" | |
228 | + name="price" | |
229 | + placeholder="请输入名称" | |
230 | + /> | |
231 | + | |
232 | + <ProFormText | |
233 | + width="sm" | |
234 | + name="notes" | |
235 | + placeholder="请输入名称" | |
236 | + /> | |
237 | + </ProForm.Group> | |
238 | + | |
239 | + <ProForm.Group> | |
240 | + <ProFormText | |
241 | + width="sm" | |
242 | + name="name4" | |
243 | + disabled | |
244 | + initialValue={"尾款"} | |
245 | + tooltip="最长为 24 位" | |
246 | + placeholder="请输入名称" | |
247 | + /> | |
248 | + | |
249 | + <ProFormText | |
250 | + width="sm" | |
251 | + name="company" | |
252 | + placeholder="请输入名称" | |
253 | + /> | |
254 | + | |
255 | + <ProFormText | |
256 | + width="sm" | |
257 | + name="price" | |
258 | + placeholder="请输入名称" | |
259 | + /> | |
260 | + | |
261 | + <ProFormText | |
262 | + width="sm" | |
263 | + name="notes" | |
264 | + placeholder="请输入名称" | |
265 | + /> | |
266 | + </ProForm.Group> */} | |
267 | + </ModalForm> | |
268 | + </> | |
269 | + ); | |
270 | +}; | ... | ... |
src/pages/Order/FeedBack/HistoryModal.tsx
0 → 100644
1 | +import { postServiceOrderQueryHistoryOrderRecord } from '@/services'; | |
2 | +import { formatDateTime } from '@/utils'; | |
3 | +import { Button, Col, Empty, Flex, Modal, Row, Spin } from 'antd'; | |
4 | +import { useEffect, useState } from 'react'; | |
5 | + | |
6 | +export default ({ subOrders, isCancelledOrder, onClose }) => { | |
7 | + let subOrderIds = subOrders?.map((subOrder: any) => { | |
8 | + return subOrder.id; | |
9 | + }); | |
10 | + | |
11 | + const [data, setData] = useState([]); | |
12 | + const [loading, setLoading] = useState(true); | |
13 | + let i = 0; | |
14 | + | |
15 | + const handleOk = () => { | |
16 | + onClose(); | |
17 | + }; | |
18 | + | |
19 | + /** | |
20 | + * 获取历史记录 | |
21 | + */ | |
22 | + const getHistory = async () => { | |
23 | + let res = await postServiceOrderQueryHistoryOrderRecord({ | |
24 | + data: { ids: subOrderIds, isDeleteQueryOrder: isCancelledOrder }, | |
25 | + }); | |
26 | + setData(res.data); | |
27 | + setLoading(false); | |
28 | + }; | |
29 | + | |
30 | + const getRecord = (history: any) => { | |
31 | + let record = []; | |
32 | + record.push( | |
33 | + <span className="pr-2 text-[#5E5E5E]"> | |
34 | + {formatDateTime(history.createTime)} | |
35 | + </span>, | |
36 | + ); | |
37 | + | |
38 | + record.push(<span className="text-[#3b83e5]">{history.createByName}</span>); | |
39 | + | |
40 | + record.push(<span>进行了</span>); | |
41 | + | |
42 | + // let label = enumValueToLabel(history.status, ORDER_STATUS_OPTIONS); | |
43 | + | |
44 | + // if ( | |
45 | + // history.record !== 'INVOICING' && history.record !== 'order-change-normal' && history.record !== 'order-change-normal-CHECK' && | |
46 | + // history.record?.indexOf(':') === -1 && | |
47 | + // label !== undefined && | |
48 | + // label !== '' | |
49 | + // ) { | |
50 | + // record.push( | |
51 | + // <> | |
52 | + // <span>,订单状态为:</span> | |
53 | + // <span className="text-[#3b83e5]">{label}</span> | |
54 | + // </>, | |
55 | + // ); | |
56 | + // } | |
57 | + | |
58 | + if (history.record?.indexOf(':') !== -1) { | |
59 | + let values = history.record?.split(':'); | |
60 | + let type = values[0]; | |
61 | + let target = values[1]; | |
62 | + if (target === 'null') { | |
63 | + target = '未指定'; | |
64 | + } | |
65 | + //采购转发 | |
66 | + if (type === 'PROCURE_CONVERT_PROCURE') { | |
67 | + record.push( | |
68 | + <> | |
69 | + <span>采购转发,{history.createByName}将订单转发给了</span> | |
70 | + <span className="text-[#3b83e5]">{target}</span> | |
71 | + </>, | |
72 | + ); | |
73 | + } | |
74 | + } else { | |
75 | + record.push( | |
76 | + <span className="text-[#3b83e5]"> | |
77 | + {history.recordText + | |
78 | + (history.record === 'INVOICING' | |
79 | + ? '(开票号码:' + history.invoiceNumber + ')' | |
80 | + : '')} | |
81 | + </span>, | |
82 | + ); | |
83 | + } | |
84 | + | |
85 | + if (history.notes !== null) { | |
86 | + record.push(<span className="pl-1">{'备注:' + history.notes}</span>); | |
87 | + } | |
88 | + | |
89 | + if (history.description !== null) { | |
90 | + record.push( | |
91 | + <span className="pl-1">{'描述:' + history.description}</span>, | |
92 | + ); | |
93 | + } | |
94 | + | |
95 | + return record; | |
96 | + }; | |
97 | + | |
98 | + useEffect(() => { | |
99 | + getHistory(); | |
100 | + }, []); | |
101 | + | |
102 | + const handleCancel = () => { | |
103 | + onClose(); | |
104 | + }; | |
105 | + | |
106 | + return ( | |
107 | + <> | |
108 | + <Modal | |
109 | + title="订单历史记录" | |
110 | + open | |
111 | + width={650} | |
112 | + onOk={handleOk} | |
113 | + onCancel={handleCancel} | |
114 | + footer={() => ( | |
115 | + <> | |
116 | + <Button onClick={handleCancel}>返回</Button> | |
117 | + </> | |
118 | + )} | |
119 | + > | |
120 | + <Spin tip="加载中" spinning={loading}> | |
121 | + <Row className="max-h-[500px] overflow-auto" gutter={[0, 14]}> | |
122 | + {data.map((item) => { | |
123 | + return ( | |
124 | + <Col span={24} key={i}> | |
125 | + <Flex vertical> | |
126 | + <div> | |
127 | + <span className="py-2 text-[#5E5E5E]"> | |
128 | + {'商品' + ++i} | |
129 | + </span> | |
130 | + <span className="text-[#8C8C8C]"> | |
131 | + -【{item.productName}】 | |
132 | + </span> | |
133 | + </div> | |
134 | + | |
135 | + <Flex vertical> | |
136 | + {item.historySubOrderRecordDto?.map((history) => { | |
137 | + return ( | |
138 | + <div className="py-1" key={history.id}> | |
139 | + {getRecord(history)} | |
140 | + </div> | |
141 | + ); | |
142 | + })} | |
143 | + </Flex> | |
144 | + </Flex> | |
145 | + </Col> | |
146 | + ); | |
147 | + })} | |
148 | + </Row> | |
149 | + {data?.length <= 0 ? ( | |
150 | + <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> | |
151 | + ) : ( | |
152 | + '' | |
153 | + )} | |
154 | + </Spin> | |
155 | + </Modal> | |
156 | + </> | |
157 | + ); | |
158 | +}; | ... | ... |
src/pages/Order/FeedBack/ImagesViewerModal.tsx
0 → 100644
1 | +import { postServiceOrderViewImages } from '@/services'; | |
2 | +import { Button, Divider, Image, Modal } from 'antd'; | |
3 | +import { useEffect, useState } from 'react'; | |
4 | +export default ({ setVisible, optType, onClose, orderRow }) => { | |
5 | + const [images, setImages] = useState<any[]>([]); | |
6 | + const [title, setTitle] = useState('收货凭证'); | |
7 | + const handleOk = () => { | |
8 | + onClose(); | |
9 | + setVisible(false); | |
10 | + }; | |
11 | + | |
12 | + const handleCancel = () => { | |
13 | + onClose(); | |
14 | + setVisible(false); | |
15 | + }; | |
16 | + | |
17 | + async function getImages() { | |
18 | + const res = await postServiceOrderViewImages({ | |
19 | + data: { subId: orderRow.id }, | |
20 | + }); | |
21 | + const images = res.data; | |
22 | + setImages(images); | |
23 | + } | |
24 | + useEffect(() => { | |
25 | + if (optType === 'shippingReceipt') { | |
26 | + setTitle('收货凭证'); | |
27 | + getImages(); | |
28 | + } else if (optType === 'paymentReceipt') { | |
29 | + let paymentReceiptsImagesList: any[] = []; | |
30 | + if (orderRow.paymentReceiptAnnexList) { | |
31 | + paymentReceiptsImagesList.push(...orderRow.paymentReceiptAnnexList); | |
32 | + } | |
33 | + //去重 | |
34 | + paymentReceiptsImagesList = [...new Set(paymentReceiptsImagesList)]; | |
35 | + setImages(paymentReceiptsImagesList); | |
36 | + } | |
37 | + }, []); | |
38 | + | |
39 | + return ( | |
40 | + <> | |
41 | + <Modal | |
42 | + title={title} | |
43 | + open | |
44 | + onOk={handleOk} | |
45 | + onCancel={handleCancel} | |
46 | + footer={[ | |
47 | + <Button key="back" onClick={handleCancel}> | |
48 | + 返回 | |
49 | + </Button>, | |
50 | + ]} | |
51 | + > | |
52 | + <Image.PreviewGroup | |
53 | + className="mr-10" | |
54 | + preview={{ | |
55 | + onChange: (current, prev) => | |
56 | + console.log(`current index: ${current}, prev index: ${prev}`), | |
57 | + }} | |
58 | + > | |
59 | + {images.map((url) => ( | |
60 | + <> | |
61 | + <Image width={120} src={url} /> <Divider type="vertical" /> | |
62 | + </> | |
63 | + ))} | |
64 | + </Image.PreviewGroup> | |
65 | + </Modal> | |
66 | + </> | |
67 | + ); | |
68 | +}; | ... | ... |
src/pages/Order/FeedBack/ImportExpressBillModal copy.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { postOrderImportImportWeightAndVolume } from '@/services'; | |
3 | +import { ModalForm, ProFormUploadDragger } from '@ant-design/pro-components'; | |
4 | +import { Button, Form, message } from 'antd'; | |
5 | + | |
6 | +export default () => { | |
7 | + const [form] = Form.useForm(); | |
8 | + const [messageApi, contextHolder] = message.useMessage(); | |
9 | + return ( | |
10 | + <> | |
11 | + <ModalForm | |
12 | + title="导入重量、体积" | |
13 | + trigger={<Button type="primary">导入重量、体积</Button>} | |
14 | + form={form} | |
15 | + autoFocusFirstInput | |
16 | + modalProps={{ | |
17 | + destroyOnClose: true, | |
18 | + }} | |
19 | + submitTimeout={2000} | |
20 | + onFinish={async (values) => { | |
21 | + console.log(values); | |
22 | + const formData = new FormData(); | |
23 | + formData.append('file', values.express[0].originFileObj); | |
24 | + messageApi.open({ | |
25 | + type: 'loading', | |
26 | + content: '正在导入...', | |
27 | + duration: 0, | |
28 | + }); | |
29 | + const res = await postOrderImportImportWeightAndVolume({ | |
30 | + data: formData, | |
31 | + headers: { | |
32 | + 'Content-Type': | |
33 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | |
34 | + }, | |
35 | + }); | |
36 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
37 | + message.error('导入成功'); | |
38 | + } else { | |
39 | + message.error('导入失败'); | |
40 | + } | |
41 | + messageApi.destroy(); | |
42 | + return true; | |
43 | + }} | |
44 | + > | |
45 | + <ProFormUploadDragger max={1} label="上传快递单" name="express" /> | |
46 | + </ModalForm> | |
47 | + {contextHolder} | |
48 | + </> | |
49 | + ); | |
50 | +}; | ... | ... |
src/pages/Order/FeedBack/ImportExpressBillModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { postOrderImportImportWeightAndVolume } from '@/services'; | |
3 | +import { ModalForm, ProFormUploadDragger } from '@ant-design/pro-components'; | |
4 | +import { Button, Form, message } from 'antd'; | |
5 | + | |
6 | +export default () => { | |
7 | + const [form] = Form.useForm(); | |
8 | + const [messageApi, contextHolder] = message.useMessage(); | |
9 | + return ( | |
10 | + <> | |
11 | + <ModalForm | |
12 | + title="导入重量、体积" | |
13 | + trigger={<Button type="primary">导入重量、体积</Button>} | |
14 | + form={form} | |
15 | + autoFocusFirstInput | |
16 | + modalProps={{ | |
17 | + destroyOnClose: true, | |
18 | + }} | |
19 | + submitTimeout={2000} | |
20 | + onFinish={async (values) => { | |
21 | + console.log(values); | |
22 | + const formData = new FormData(); | |
23 | + formData.append('file', values.express[0].originFileObj); | |
24 | + messageApi.open({ | |
25 | + type: 'loading', | |
26 | + content: '正在导入...', | |
27 | + duration: 0, | |
28 | + }); | |
29 | + const res = await postOrderImportImportWeightAndVolume({ | |
30 | + data: formData, | |
31 | + headers: { | |
32 | + 'Content-Type': | |
33 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | |
34 | + }, | |
35 | + }); | |
36 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
37 | + message.error('导入成功'); | |
38 | + } else { | |
39 | + message.error('导入失败'); | |
40 | + } | |
41 | + messageApi.destroy(); | |
42 | + return true; | |
43 | + }} | |
44 | + > | |
45 | + <ProFormUploadDragger max={1} label="上传快递单" name="express" /> | |
46 | + </ModalForm> | |
47 | + {contextHolder} | |
48 | + </> | |
49 | + ); | |
50 | +}; | ... | ... |