Blame view

src/pages/Order/components/CheckModal.tsx 17.7 KB
zhongnanhuang authored
1
import { RESPONSE_CODE } from '@/constants/enum';
zhongnanhuang authored
2
import {
zhongnanhuang authored
3
  postServiceOrderAfterSalesCheck,
zhongnanhuang authored
4
  postServiceOrderAudit,
5
  postServiceOrderFileProcess,
zhongnanhuang authored
6
  postServiceOrderFinanceCheckOrder,
7
  postServiceOrderLeaderAudit,
zhongnanhuang authored
8
  postServiceOrderToProcureAudit,
zhongnanhuang authored
9
} from '@/services';
sanmu authored
10
import { ModalForm, ProFormTextArea } from '@ant-design/pro-components';
zhongnanhuang authored
11
import { Button, Col, Form, Modal, Row, UploadFile, message, Image, Divider } from 'antd';
12
import Upload, { RcFile, UploadProps } from 'antd/es/upload';
zhongnanhuang authored
13
import { useEffect, useRef, useState } from 'react';
zhongnanhuang authored
14
15
16
17
18
import {
  AFTE_SALES_PLAN_OPTIONS,
  CHECK_TYPE,
  COMFIR_RECEIPT_IMAGES_NUMBER,
} from '../constant';
19
// import { cloneDeep } from 'lodash';
zhongnanhuang authored
20
21
22
23
24
import {
  enumValueToLabel,
  getAliYunOSSFileNameFromUrl,
  transImageFile,
} from '@/utils';
25
import { PlusOutlined } from '@ant-design/icons';
zhongnanhuang authored
26
import { cloneDeep } from 'lodash';
zhongnanhuang authored
27
28
29
30
31
export default ({
  setCheckVisible,
  data,
  subOrders,
  orderCheckType,
zhongnanhuang authored
32
  openOrderDrawer,
zhongnanhuang authored
33
34
  onClose,
}) => {
35
36
37
  const [previewOpen, setPreviewOpen] = useState(false);
  const [previewImage, setPreviewImage] = useState('');
  const [previewTitle, setPreviewTitle] = useState('');
zhongnanhuang authored
38
  const [paymentReceiptsImages, setPymentReceiptsImages] = useState<any[]>([]);
39
40
41
42
43
44
45
46
47
48
  const fileListObj = useRef<UploadFile[]>([]); //使用引用类型,使得在useEffect里面设置监听事件后,不用更新监听事件也能保持obj与外界一致
  const getBase64 = (file: RcFile): Promise<string> =>
    new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result as string);
      reader.onerror = (error) => reject(error);
    });
  const [fileList, setFileList] = useState<UploadFile[]>([]);
  const handleCancel = () => setPreviewOpen(false);
49
  const [messageApi, contextHolder] = message.useMessage();
zhongnanhuang authored
50
51
  const [form] = Form.useForm<{ name: string; company: string }>();
  let subOrderIds: any[] = subOrders.map((subOrder) => subOrder.id);
zhongnanhuang authored
52
  const [mainOrderId] = useState(data.id);
zhongnanhuang authored
53
zhongnanhuang authored
54
  const [afterSalesInfo, setAfterSalesInfo] = useState<any>();
zhongnanhuang authored
55
zhongnanhuang authored
56
57
58
59
60
61
62
63
64
65
  /**
   * 审核类型
   */
  function checkType(check: string) {
    if (orderCheckType === check) {
      return true;
    }
    return false;
  }
zhongnanhuang authored
66
  const getOrderAfterSalesInfo = async () => {
67
68
69
    // let res = await postServiceOrderQueryAfterSalesInfoSnapshot({
    //   data: { subOrderIds: subOrderIds },
    // });
zhongnanhuang authored
70
zhongnanhuang authored
71
    //附件
72
    let annex = subOrders[0].afterAnnexList;
zhongnanhuang authored
73
74
    let annexLinks = annex?.map((f) => {
      return (
75
        <Button className="p-0 pr-1" type="link" key="key" href={f}>
zhongnanhuang authored
76
77
78
79
          {getAliYunOSSFileNameFromUrl(f)}
        </Button>
      );
    });
zhongnanhuang authored
80
81
82
    console.log(annexLinks);
zhongnanhuang authored
83
84
85
86
87
88
89
90
    setAfterSalesInfo(
      <div className="my-5">
        <Row gutter={[16, 24]}>
          <Col span={6}>
            <span className="text-[#333333]">售后方案</span>
          </Col>
          <Col span={18}>
            {enumValueToLabel(
91
              subOrders[0]?.afterSalesPlan,
zhongnanhuang authored
92
93
94
95
96
97
              AFTE_SALES_PLAN_OPTIONS,
            )}
          </Col>
          <Col span={6}>
            <span className="className='text-[#333333]'">售后原因</span>
          </Col>
98
          <Col span={18}>{subOrders[0]?.afterSalesNotes}</Col>
zhongnanhuang authored
99
100
101
102
103
104
105
106
          <Col span={6}>
            <span className="className='text-[#333333]'">附件</span>
          </Col>
          <Col span={18}>{annexLinks}</Col>
        </Row>
      </div>,
    );
  };
zhongnanhuang authored
107
zhongnanhuang authored
108
109
  useEffect(() => {
    getOrderAfterSalesInfo();
zhongnanhuang authored
110
111
112
113
114
115
116
117
118
119

    let paymentReceiptsImagesList: any[] = [];
    subOrders?.forEach((item: any) => {
      if (item.paymentReceiptAnnexList) {
        paymentReceiptsImagesList.push(...item.paymentReceiptAnnexList);
      }
    })
    //去重
    paymentReceiptsImagesList = [...new Set(paymentReceiptsImagesList)];
    setPymentReceiptsImages(paymentReceiptsImagesList);
zhongnanhuang authored
120
  }, []);
zhongnanhuang authored
121
122
123
124
125
126
127
128
  const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
    //fileListObj得在change里变化,change的参数是已经处理过的file数组
    //beforeUpload中的参数file是未处理过,还需要Base64拿到文件数据处理
    fileListObj.current = newFileList;
    setFileList(newFileList);
  };
zhongnanhuang authored
129
130
131
132
133
134
135
136
  /** 粘贴快捷键的回调 */
  const onPaste = async (e: any) => {
    /** 获取剪切板的数据clipboardData */
    let clipboardData = e.clipboardData,
      i = 0,
      items,
      item,
      types;
137
zhongnanhuang authored
138
139
140
141
142
143
144
    /** 为空判断 */
    if (clipboardData) {
      items = clipboardData.items;
      if (!items) {
        message.info('您的剪贴板中没有照片');
        return;
      }
145
zhongnanhuang authored
146
147
148
149
150
151
152
153
154
      item = items[0];
      types = clipboardData.types || [];
      /** 遍历剪切板的数据 */
      for (; i < types.length; i++) {
        if (types[i] === 'Files') {
          item = items[i];
          break;
        }
      }
155
zhongnanhuang authored
156
157
158
159
160
161
162
163
164
165
166
167
168
      /** 判断文件是否为图片 */
      if (item && item.kind === 'file' && item.type.match(/^image\//i)) {
        const imgItem = item.getAsFile();
        const newFileList = cloneDeep(fileListObj.current);
        let filteredArray = newFileList.filter(
          (obj) => obj.status !== 'removed',
        ); //过滤掉状态为已删除的照片
        const listItem = {
          ...imgItem,
          status: 'done',
          url: await getBase64(imgItem),
          originFileObj: imgItem,
        };
169
zhongnanhuang authored
170
171
172
173
174
175
176
177
178
179
        if (filteredArray.length >= COMFIR_RECEIPT_IMAGES_NUMBER) {
          message.info('发货照片数量不能超过3');
          return;
        }
        fileListObj.current = filteredArray;
        filteredArray.push(listItem);
        setFileList(filteredArray);
        return;
      }
    }
180
zhongnanhuang authored
181
182
183
    message.info('您的剪贴板中没有照片');
  };
  useEffect(() => {
zhongnanhuang authored
184
    //回显售后信息
zhongnanhuang authored
185
186
187
    // if (checkType(CHECK_TYPE.AFTER_SALES)) {
    //   getOrderAfterSalesInfo();
    // }
zhongnanhuang authored
188
zhongnanhuang authored
189
190
191
192
193
    document.addEventListener('paste', onPaste);
    return () => {
      document.removeEventListener('paste', onPaste);
    };
  }, []);
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  const uploadButton = (
    <div>
      <PlusOutlined />
      <div style={{ marginTop: 8 }}>上传凭证</div>
    </div>
  );
  const handlePreview = async (file: UploadFile) => {
    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj as RcFile);
    }
    setPreviewImage(file.url || (file.preview as string));
    setPreviewOpen(true);
    setPreviewTitle(
      file.name ||
zhongnanhuang authored
208
209
      file.originFileObj?.name ||
      file.url!.substring(file.url!.lastIndexOf('/') + 1),
210
211
212
213
214
    );
  };

  const handleBeforeUpload = (file: any) => {
    setFileList([...fileList, file]);
215
    return false;
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
  };

  const props: UploadProps = {
    onRemove: (file) => {
      const index = fileList.indexOf(file);
      const newFileList = fileList.slice();
      newFileList.splice(index, 1);
      setFileList(newFileList);
    },
    beforeUpload: handleBeforeUpload,
    listType: 'picture-card',
    onPreview: handlePreview,
    fileList,
    onChange: handleChange,
    accept: 'image/png, image/jpeg, image/png',
231
    // action: '/api/service/order/fileProcess',
232
233
234
235
    name: 'files',
    headers: { Authorization: localStorage.getItem('token') },
  };
zhongnanhuang authored
236
  //仓库审核
237
  async function doCheck(body: object) {
zhongnanhuang authored
238
    const data = await postServiceOrderAudit({
239
240
      data: body,
    });
zhongnanhuang authored
241
242
    if (data.result === RESPONSE_CODE.SUCCESS) {
      message.success(data.message);
zhongnanhuang authored
243
      onClose();
244
245
    }
  }
zhongnanhuang authored
246
247
248
249
250

  /**
   *
   * @param body 财务审核
   */
251
  async function doFinancailCheck(values: any, isAgree: boolean) {
zhongnanhuang authored
252
253
254
255
    if (fileList.length <= 0) {
      message.error('凭证不能为空');
      return;
    }
256
257
258
259
260
261
262
263
264
    messageApi.open({
      type: 'loading',
      content: '正在上传图片...',
      duration: 0,
    });
    //附件处理
    let formData = new FormData();
    //附件处理
    for (let file of fileList) {
265
266
      if (file.originFileObj) {
        formData.append('files', file.originFileObj as RcFile);
267
      } else {
268
269
270
271
272
273
274
275
276
277
278
279
280
281
        //有url的话取url(源文件),没url取thumbUrl。有url的时候thumbUrl是略缩图
        if (file?.url === undefined || file?.url === null) {
          formData.append(
            'files',
            transImageFile(file?.thumbUrl),
            file?.originFileObj?.name,
          );
        } else {
          formData.append(
            'files',
            transImageFile(file?.url),
            file?.originFileObj?.name,
          );
        }
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
      }
    }
    let res = await postServiceOrderFileProcess({
      data: formData,
    });
    messageApi.destroy();
    if (res.result === RESPONSE_CODE.SUCCESS) {
      message.success('上传成功!');

      let fileUrls = res?.data?.map((item) => {
        return { url: item };
      });
      //财务审核
      const data = await postServiceOrderFinanceCheckOrder({
        data: {
          checkNotes: values.name,
          ids: subOrderIds,
          checkPassOrReject: isAgree,
          invoicingCheckAnnex: fileUrls,
        },
      });
      if (data.result === RESPONSE_CODE.SUCCESS) {
        message.success(data.message);
        onClose();
      }
    } else {
      message.success('上传失败');
    }
  }

  /**
   *
   * @param body 售后审核
   */
  async function doAfterSalesCheck(body: object) {
zhongnanhuang authored
317
    const data = await postServiceOrderAfterSalesCheck({
zhongnanhuang authored
318
319
320
321
322
323
324
325
      data: body,
    });
    if (data.result === RESPONSE_CODE.SUCCESS) {
      message.success(data.message);
      onClose();
    }
  }
326
327
328
329
330
331
332
333
334
335
336
337
338
339
  /**
   *
   * @param body 领导审核
   */
  async function doLeaderCheck(body: object) {
    const data = await postServiceOrderLeaderAudit({
      data: body,
    });
    if (data.result === RESPONSE_CODE.SUCCESS) {
      message.success(data.message);
      onClose();
    }
  }
sanmu authored
340
  return (
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
    <>
      <ModalForm<{
        name: string;
        company: string;
      }>
        width={500}
        open
        title="审核"
        form={form}
        autoFocusFirstInput
        modalProps={{
          okText: '通过',
          cancelText: '驳回',
          destroyOnClose: true,
          onCancel: () => {
            setCheckVisible(false);
          },
        }}
        submitter={{
          render: (props, defaultDoms) => {
            let myDoms = [];
zhongnanhuang authored
362
363
            myDoms.push(
              <Button
364
                key="驳回"
365
366
367
                onClick={async () => {
                  if (checkType(CHECK_TYPE.AFTER_SALES)) {
                    doAfterSalesCheck({
368
                      applyType: 'after-sales',
zhongnanhuang authored
369
370
                      isAfterSalesSuccess: false,
                      subOrderIds: subOrderIds,
zhongnanhuang authored
371
                      mainId: mainOrderId,
zhongnanhuang authored
372
                      afterSalesRejectionNotes: form.getFieldValue('name'),
373
374
375
376
377
378
379
                    });
                    return;
                  }

                  if (checkType(CHECK_TYPE.FINALCIAL)) {
                    let values = { name: form.getFieldValue('name') };
                    doFinancailCheck(values, false);
380
                    return;
381
                  }
382
383
384
385
386
387
388

                  if (checkType(CHECK_TYPE.LEADER_AUDIT)) {
                    doLeaderCheck({
                      pass: false,
                      subOrderIds: subOrderIds,
                      reason: form.getFieldValue('name'),
                    });
389
                    return;
390
                  }
391
392
393
394
395
396
397
398
399
400
401

                  if (checkType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT)) {
                    doAfterSalesCheck({
                      applyType: 'order-change-normal',
                      isAfterSalesSuccess: false,
                      subOrderIds: subOrderIds,
                      mainId: mainOrderId,
                      afterSalesRejectionNotes: form.getFieldValue('name'),
                    });
                    return;
                  }
zhongnanhuang authored
402
403
404
405
406
                  let type = '';
                  if (checkType(CHECK_TYPE.WEARHOUSE_KEEPER)) {
                    type = 'warehouse_audit';
                  }
zhongnanhuang authored
407
                  if (checkType(CHECK_TYPE.WAITING_FOR_POST_AUDIT)) {
408
409
410
411
                    type = 'post_audit';
                  }
                  if (checkType(CHECK_TYPE.NODE_OPERATING_AUDIT)) {
                    type = 'node_operating_audit';
zhongnanhuang authored
412
                  }
413
414
415
                  if (checkType(CHECK_TYPE.MODIFY_LEADER_AUDIT)) {
                    type = 'modify_leader_audit';
                  }
zhongnanhuang authored
416
417
418
                  if (checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING)) {
                    type = 'urgent_invoice_audit';
                  }
zhongnanhuang authored
419
420
421
                  if (checkType(CHECK_TYPE.PAYMENT_RECEIPTS_AUDIT)) {
                    type = 'payment_receipt_audit';
                  }
422
423
424
425
426
427
                  doCheck({
                    pass: false,
                    subOrderIds: subOrderIds,
                    type: type,
                    notes: form.getFieldValue('name'),
                  });
zhongnanhuang authored
428
429
                }}
              >
430
                驳回
zhongnanhuang authored
431
432
              </Button>,
            );
433
434
            //如果是仓库审核,那么显示这个外部采购
zhongnanhuang authored
435
            if (checkType(CHECK_TYPE.WEARHOUSE_KEEPER)) {
436
437
438
              myDoms.push(
                <Button
                  key="外部采购"
zhongnanhuang authored
439
440
441
442
443
                  onClick={async () => {
                    let res = await postServiceOrderToProcureAudit({
                      data: {
                        subOrderIds: subOrderIds,
                      },
444
                    });
zhongnanhuang authored
445
446
447
448
449

                    if (res && res.result === RESPONSE_CODE.SUCCESS) {
                      message.success(res.message);
                      onClose();
                    }
450
451
452
453
454
455
456
457
458
459
460
461
462
463
                  }}
                >
                  外部采购
                </Button>,
              );
            }

            //确认
            myDoms.push(defaultDoms[1]);
            return myDoms;
          },
        }}
        submitTimeout={2000}
        onFinish={async (values) => {
464
465
466
          if (checkType(CHECK_TYPE.AFTER_SALES)) {
            //审核通过
            return doAfterSalesCheck({
467
              applyType: 'after-sales',
zhongnanhuang authored
468
469
              isAfterSalesSuccess: true,
              subOrderIds: subOrderIds,
zhongnanhuang authored
470
              mainId: mainOrderId,
zhongnanhuang authored
471
              afterSalesRejectionNotes: values.name,
472
473
            });
          }
474
          console.log('h');
475
476
          if (checkType(CHECK_TYPE.FINALCIAL)) {
            doFinancailCheck(values, true);
477
            return;
478
          }
479
480
481
482
483
484
485

          if (checkType(CHECK_TYPE.LEADER_AUDIT)) {
            doLeaderCheck({
              pass: true,
              subOrderIds: subOrderIds,
              reason: values.name,
            });
486
            return;
487
          }
488
489
490
491
492
493
494
495
496
497
498

          if (checkType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT)) {
            //审核通过
            return doAfterSalesCheck({
              applyType: 'order-change-normal',
              isAfterSalesSuccess: true,
              subOrderIds: subOrderIds,
              mainId: mainOrderId,
              afterSalesRejectionNotes: values.name,
            });
          }
zhongnanhuang authored
499
500
501
502
503
          let type = '';
          if (checkType(CHECK_TYPE.WEARHOUSE_KEEPER)) {
            type = 'warehouse_audit';
          }
zhongnanhuang authored
504
          if (checkType(CHECK_TYPE.WAITING_FOR_POST_AUDIT)) {
505
506
507
508
509
510
511
            type = 'post_audit';
          }
          if (checkType(CHECK_TYPE.NODE_OPERATING_AUDIT)) {
            type = 'node_operating_audit';
          }
          if (checkType(CHECK_TYPE.MODIFY_LEADER_AUDIT)) {
            type = 'modify_leader_audit';
zhongnanhuang authored
512
          }
zhongnanhuang authored
513
514
515
          if (checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING)) {
            type = 'urgent_invoice_audit';
          }
zhongnanhuang authored
516
517
518
          if (checkType(CHECK_TYPE.PAYMENT_RECEIPTS_AUDIT)) {
            type = 'payment_receipt_audit';
          }
519
520
521
522
523
524
          doCheck({
            pass: true,
            subOrderIds: subOrderIds,
            type: type,
            notes: form.getFieldValue('name'),
          });
525
526
527
        }}
        onOpenChange={setCheckVisible}
      >
zhongnanhuang authored
528
        {checkType(CHECK_TYPE.AFTER_SALES) ? (
zhongnanhuang authored
529
530
531
532
533
534
535
536
537
538
539
540
541
          <>
            {afterSalesInfo}
            <Button
              className="px-0"
              type="link"
              onClick={() => {
                console.log(data);
                openOrderDrawer('after-sales-check', mainOrderId);
              }}
            >
              查看旧订单
            </Button>
          </>
zhongnanhuang authored
542
543
544
        ) : (
          ''
        )}
zhongnanhuang authored
545
zhongnanhuang authored
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
        {
          checkType(CHECK_TYPE.PAYMENT_RECEIPTS_AUDIT) ? (
            <>
              <Divider orientation="center"><span className='text-sm'>回款凭证</span></Divider>
              <Image.PreviewGroup
                className="mr-10"
                preview={{
                  onChange: (current, prev) =>
                    console.log(`current index: ${current}, prev index: ${prev}`),
                }}
              >
                {paymentReceiptsImages.map((url) => (
                  <>
                    <Image width={120} src={url} /> <Divider type="vertical" />
                  </>
                ))}
              </Image.PreviewGroup>
              <Divider></Divider>
            </>
          )
            : ""
        }
569
570
571
572
573
574
575
576
        <div>请特别注意订单总金额与订单金额。</div>
        <ProFormTextArea
          width="lg"
          name="name"
          placeholder="若驳回,请填写驳回理由"
        />
        {checkType(CHECK_TYPE.FINALCIAL) ? (
          <>
zhongnanhuang authored
577
578
579
            <div className="pb-4 text-xs decoration-gray-50">
              可复制照片粘贴
            </div>
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
            <Upload {...props}>
              {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER
                ? uploadButton
                : ''}
            </Upload>
          </>
        ) : (
          ''
        )}
      </ModalForm>

      <Modal
        open={previewOpen}
        title={previewTitle}
        footer={null}
        onCancel={handleCancel}
      >
        <img alt="图片预览" style={{ width: '100%' }} src={previewImage} />
      </Modal>
599
      {contextHolder}
600
    </>
sanmu authored
601
602
  );
};