Commit 37038e0f92ab70367e33bd53bde61ee7d733d9d8

Authored by boyang
1 parent a9848f98

订单预警页面

Showing 60 changed files with 4266 additions and 195 deletions

Too many changes to show.

To preserve performance only 60 of 120 files are displayed.

.umirc.ts
@@ -41,8 +41,24 @@ export default defineConfig({ @@ -41,8 +41,24 @@ export default defineConfig({
41 { 41 {
42 name: '订单管理', 42 name: '订单管理',
43 path: '/order', 43 path: '/order',
44 - component: './Order',  
45 icon: 'ProfileOutlined', 44 icon: 'ProfileOutlined',
  45 + routes: [
  46 + {
  47 + name: '订单列表',
  48 + path: 'order',
  49 + component: './Order/Order',
  50 + },
  51 + {
  52 + name: '订单预警',
  53 + path: 'OrderWarning',
  54 + component: './Order/OrderWarning',
  55 + },
  56 + {
  57 + name: '预警白名单',
  58 + path: 'WarningWhitelist',
  59 + component: './Order/WarningWhitelist',
  60 + },
  61 + ],
46 }, 62 },
47 { 63 {
48 name: '订单报表', 64 name: '订单报表',
src/components/UserHeader/index.tsx
1 import { RESPONSE_CODE } from '@/constants/enum'; 1 import { RESPONSE_CODE } from '@/constants/enum';
2 -import MessageListDrawer from '@/pages/Order/components/MessageListDrawer'; 2 +import MessageListDrawer from '@/pages/Order/Order/components/MessageListDrawer';
3 import { postOrderErpMessageGetUnreadNum } from '@/services'; 3 import { postOrderErpMessageGetUnreadNum } from '@/services';
4 import { getUserInfo } from '@/utils'; 4 import { getUserInfo } from '@/utils';
5 import { BellOutlined, EllipsisOutlined } from '@ant-design/icons'; 5 import { BellOutlined, EllipsisOutlined } from '@ant-design/icons';
src/pages/Order/components/AfterSalesDrawer.tsx renamed to src/pages/Order/Order/components/AfterSalesDrawer.tsx
@@ -9,7 +9,7 @@ import { @@ -9,7 +9,7 @@ import {
9 ProFormUploadDragger, 9 ProFormUploadDragger,
10 } from '@ant-design/pro-components'; 10 } from '@ant-design/pro-components';
11 import { Form, message } from 'antd'; 11 import { Form, message } from 'antd';
12 -import { AFTE_SALES_PLAN_OPTIONS } from '../constant'; 12 +import { AFTE_SALES_PLAN_OPTIONS } from '../../constant';
13 export default ({ setVisible, mainOrder, subOrders, onClose }) => { 13 export default ({ setVisible, mainOrder, subOrders, onClose }) => {
14 let subOrderIds = subOrders?.map((item: { id: any }) => { 14 let subOrderIds = subOrders?.map((item: { id: any }) => {
15 return item.id; 15 return item.id;
src/pages/Order/components/ApplyForInvoicingModal.tsx renamed to src/pages/Order/Order/components/ApplyForInvoicingModal.tsx
@@ -10,7 +10,7 @@ import { @@ -10,7 +10,7 @@ import {
10 } from '@ant-design/pro-components'; 10 } from '@ant-design/pro-components';
11 import { Form, message } from 'antd'; 11 import { Form, message } from 'antd';
12 import { useEffect, useState } from 'react'; 12 import { useEffect, useState } from 'react';
13 -import { PAYEE_OPTIONS } from '../constant'; 13 +import { PAYEE_OPTIONS } from '../../constant';
14 export default ({ 14 export default ({
15 setCheckVisible, 15 setCheckVisible,
16 isEdit, 16 isEdit,
src/pages/Order/components/AttachmentModal.tsx renamed to src/pages/Order/Order/components/AttachmentModal.tsx
src/pages/Order/components/BaseModal.tsx renamed to src/pages/Order/Order/components/BaseModal.tsx
src/pages/Order/components/CheckModal.tsx renamed to src/pages/Order/Order/components/CheckModal.tsx
@@ -32,9 +32,9 @@ import { @@ -32,9 +32,9 @@ import {
32 AFTE_SALES_PLAN_OPTIONS, 32 AFTE_SALES_PLAN_OPTIONS,
33 CHECK_TYPE, 33 CHECK_TYPE,
34 COMFIR_RECEIPT_IMAGES_NUMBER, 34 COMFIR_RECEIPT_IMAGES_NUMBER,
35 -} from '../constant'; 35 +} from '../../constant';
36 // import { cloneDeep } from 'lodash'; 36 // import { cloneDeep } from 'lodash';
37 -import InvoiceSubOrderInfoTable from '@/pages/Order/components/InvoiceSubOrderInfoTable'; 37 +import InvoiceSubOrderInfoTable from '@/pages/Order/Order/components/InvoiceSubOrderInfoTable';
38 import { enumValueToLabel, transImageFile } from '@/utils'; 38 import { enumValueToLabel, transImageFile } from '@/utils';
39 import { PlusOutlined } from '@ant-design/icons'; 39 import { PlusOutlined } from '@ant-design/icons';
40 import { cloneDeep } from 'lodash'; 40 import { cloneDeep } from 'lodash';
@@ -235,8 +235,8 @@ export default ({ @@ -235,8 +235,8 @@ export default ({
235 setPreviewOpen(true); 235 setPreviewOpen(true);
236 setPreviewTitle( 236 setPreviewTitle(
237 file.name || 237 file.name ||
238 - file.originFileObj?.name ||  
239 - file.url!.substring(file.url!.lastIndexOf('/') + 1), 238 + file.originFileObj?.name ||
  239 + file.url!.substring(file.url!.lastIndexOf('/') + 1),
240 ); 240 );
241 }; 241 };
242 242
src/pages/Order/components/ConfirmReceiptModal.tsx renamed to src/pages/Order/Order/components/ConfirmReceiptModal.tsx
@@ -5,7 +5,7 @@ import { Button, Modal, Upload, message } from 'antd'; @@ -5,7 +5,7 @@ import { Button, Modal, Upload, message } from 'antd';
5 import { RcFile, UploadFile, UploadProps } from 'antd/es/upload'; 5 import { RcFile, UploadFile, UploadProps } from 'antd/es/upload';
6 import { cloneDeep } from 'lodash'; 6 import { cloneDeep } from 'lodash';
7 import { useEffect, useRef, useState } from 'react'; 7 import { useEffect, useRef, useState } from 'react';
8 -import { COMFIR_RECEIPT_IMAGES_NUMBER } from '../constant'; 8 +import { COMFIR_RECEIPT_IMAGES_NUMBER } from '../../constant';
9 export default ({ data, onClose }) => { 9 export default ({ data, onClose }) => {
10 const subIds = data?.map((item) => { 10 const subIds = data?.map((item) => {
11 return item.id; 11 return item.id;
@@ -107,8 +107,8 @@ export default ({ data, onClose }) => { @@ -107,8 +107,8 @@ export default ({ data, onClose }) => {
107 setPreviewOpen(true); 107 setPreviewOpen(true);
108 setPreviewTitle( 108 setPreviewTitle(
109 file.name || 109 file.name ||
110 - file.originFileObj?.name ||  
111 - file.url!.substring(file.url!.lastIndexOf('/') + 1), 110 + file.originFileObj?.name ||
  111 + file.url!.substring(file.url!.lastIndexOf('/') + 1),
112 ); 112 );
113 }; 113 };
114 114
src/pages/Order/components/DeliverInfoDrawer.tsx renamed to src/pages/Order/Order/components/DeliverInfoDrawer.tsx
@@ -3,7 +3,7 @@ import { enumValueToLabel } from '@/utils'; @@ -3,7 +3,7 @@ import { enumValueToLabel } from '@/utils';
3 import { getReceivingCompanyOptions } from '@/utils/order'; 3 import { getReceivingCompanyOptions } from '@/utils/order';
4 import { Col, Drawer, Row } from 'antd'; 4 import { Col, Drawer, Row } from 'antd';
5 import { useEffect, useState } from 'react'; 5 import { useEffect, useState } from 'react';
6 -import { PAYEE_OPTIONS } from '../constant'; 6 +import { PAYEE_OPTIONS } from '../../constant';
7 7
8 export default ({ data, onClose }) => { 8 export default ({ data, onClose }) => {
9 const [province, setProvince] = useState(''); 9 const [province, setProvince] = useState('');
src/pages/Order/components/DeliverModal.tsx renamed to src/pages/Order/Order/components/DeliverModal.tsx
@@ -25,7 +25,7 @@ import { @@ -25,7 +25,7 @@ import {
25 } from 'antd'; 25 } from 'antd';
26 import { cloneDeep } from 'lodash'; 26 import { cloneDeep } from 'lodash';
27 import { useEffect, useRef, useState } from 'react'; 27 import { useEffect, useRef, useState } from 'react';
28 -import { CHECK_TYPE, LOGISTICS_STATUS_OPTIONS } from '../constant'; 28 +import { CHECK_TYPE, LOGISTICS_STATUS_OPTIONS } from '../../constant';
29 29
30 const DeliverModal = ({ 30 const DeliverModal = ({
31 data: propsData, 31 data: propsData,
@@ -260,7 +260,7 @@ const DeliverModal = ({ @@ -260,7 +260,7 @@ const DeliverModal = ({
260 serialNumber: item.serialNumber, 260 serialNumber: item.serialNumber,
261 packageNumber: 261 packageNumber:
262 item.packageNumber === null || 262 item.packageNumber === null ||
263 - item.packageNumber === undefined 263 + item.packageNumber === undefined
264 ? 1 264 ? 1
265 : item.packageNumber, 265 : item.packageNumber,
266 logisticsNotes: item.logisticsNotes, 266 logisticsNotes: item.logisticsNotes,
src/pages/Order/components/FinancialDrawer.tsx renamed to src/pages/Order/Order/components/FinancialDrawer.tsx
@@ -15,7 +15,7 @@ import { @@ -15,7 +15,7 @@ import {
15 } from '@ant-design/pro-components'; 15 } from '@ant-design/pro-components';
16 import { Button, Form, message } from 'antd'; 16 import { Button, Form, message } from 'antd';
17 import { useEffect, useState } from 'react'; 17 import { useEffect, useState } from 'react';
18 -import { INVOCING_STATUS_OPTIONS_OLD, PAYEE_OPTIONS } from '../constant'; 18 +import { INVOCING_STATUS_OPTIONS_OLD, PAYEE_OPTIONS } from '../../constant';
19 19
20 export default ({ 20 export default ({
21 mainOrder, 21 mainOrder,
@@ -144,107 +144,107 @@ export default ({ @@ -144,107 +144,107 @@ export default ({
144 144
145 {invoicingStatus !== 'UN_INVOICE' 145 {invoicingStatus !== 'UN_INVOICE'
146 ? [ 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} 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 + }}
194 > 210 >
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 - />, 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 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 - ] 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 : ''} 248 : ''}
249 249
250 <ProFormSelect 250 <ProFormSelect
src/pages/Order/components/FinancialEditDrawer.tsx renamed to src/pages/Order/Order/components/FinancialEditDrawer.tsx
@@ -9,7 +9,7 @@ import { @@ -9,7 +9,7 @@ import {
9 } from '@ant-design/pro-components'; 9 } from '@ant-design/pro-components';
10 import { Form, message } from 'antd'; 10 import { Form, message } from 'antd';
11 import { useEffect, useState } from 'react'; 11 import { useEffect, useState } from 'react';
12 -import { INVOCING_STATUS_OPTIONS_OLD } from '../constant'; 12 +import { INVOCING_STATUS_OPTIONS_OLD } from '../../constant';
13 13
14 export default ({ mainOrder, subOrders, setVisible, isMainOrder, onClose }) => { 14 export default ({ mainOrder, subOrders, setVisible, isMainOrder, onClose }) => {
15 const [invoicingStatus, setInvoicingStatus] = useState(''); 15 const [invoicingStatus, setInvoicingStatus] = useState('');
@@ -130,24 +130,24 @@ export default ({ mainOrder, subOrders, setVisible, isMainOrder, onClose }) =&gt; { @@ -130,24 +130,24 @@ export default ({ mainOrder, subOrders, setVisible, isMainOrder, onClose }) =&gt; {
130 width="lg" 130 width="lg"
131 name="financialReceiptIssuanceTime" 131 name="financialReceiptIssuanceTime"
132 label="开收据时间" 132 label="开收据时间"
133 - // rules={[  
134 - // {  
135 - // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',  
136 - // message: '开收据时间必填',  
137 - // },  
138 - // ]} 133 + // rules={[
  134 + // {
  135 + // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
  136 + // message: '开收据时间必填',
  137 + // },
  138 + // ]}
139 /> 139 />
140 <ProFormDatePicker 140 <ProFormDatePicker
141 key="collectMoneyTime" 141 key="collectMoneyTime"
142 width="lg" 142 width="lg"
143 name="collectMoneyTime" 143 name="collectMoneyTime"
144 label="收款时间" 144 label="收款时间"
145 - // rules={[  
146 - // {  
147 - // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',  
148 - // message: '收款时间必填',  
149 - // },  
150 - // ]} 145 + // rules={[
  146 + // {
  147 + // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
  148 + // message: '收款时间必填',
  149 + // },
  150 + // ]}
151 /> 151 />
152 </DrawerForm> 152 </DrawerForm>
153 ); 153 );
src/pages/Order/components/FinancialMergeDrawer.tsx renamed to src/pages/Order/Order/components/FinancialMergeDrawer.tsx
@@ -9,7 +9,7 @@ import { @@ -9,7 +9,7 @@ import {
9 ProFormTextArea, 9 ProFormTextArea,
10 } from '@ant-design/pro-components'; 10 } from '@ant-design/pro-components';
11 import { Form, message } from 'antd'; 11 import { Form, message } from 'antd';
12 -import { PAYEE_OPTIONS } from '../constant'; 12 +import { PAYEE_OPTIONS } from '../../constant';
13 13
14 export default ({ dataList, setVisible, onClose }) => { 14 export default ({ dataList, setVisible, onClose }) => {
15 // let subOrderIds = dataList?.map((item) => { 15 // let subOrderIds = dataList?.map((item) => {
src/pages/Order/components/FinancialReceiptsModal.tsx renamed to src/pages/Order/Order/components/FinancialReceiptsModal.tsx
src/pages/Order/components/HistoryModal.tsx renamed to src/pages/Order/Order/components/HistoryModal.tsx
src/pages/Order/components/ImagesViewerModal.tsx renamed to src/pages/Order/Order/components/ImagesViewerModal.tsx
src/pages/Order/components/ImportExpressBillModal.tsx renamed to src/pages/Order/Order/components/ImportExpressBillModal.tsx
src/pages/Order/components/ImportModal.tsx renamed to src/pages/Order/Order/components/ImportModal.tsx
src/pages/Order/components/InvoiceSubOrderInfoTable.tsx renamed to src/pages/Order/Order/components/InvoiceSubOrderInfoTable.tsx
src/pages/Order/components/InvoicingDrawerForm.tsx renamed to src/pages/Order/Order/components/InvoicingDrawerForm.tsx
src/pages/Order/components/KingdeeCustomerModal.tsx renamed to src/pages/Order/Order/components/KingdeeCustomerModal.tsx
src/pages/Order/components/LazySelect.tsx renamed to src/pages/Order/Order/components/LazySelect.tsx
src/pages/Order/components/MessageListDrawer.tsx renamed to src/pages/Order/Order/components/MessageListDrawer.tsx
src/pages/Order/components/ModifiedDiffModal.tsx renamed to src/pages/Order/Order/components/ModifiedDiffModal.tsx
@@ -9,7 +9,7 @@ import { @@ -9,7 +9,7 @@ import {
9 PAYMENT_METHOD_OPTIONS, 9 PAYMENT_METHOD_OPTIONS,
10 PRODUCT_BELONG_DEPARTMENT_OPTIONS, 10 PRODUCT_BELONG_DEPARTMENT_OPTIONS,
11 SHIPPING_WAREHOUSE_OPTIONS, 11 SHIPPING_WAREHOUSE_OPTIONS,
12 -} from '../constant'; 12 +} from '../../constant';
13 import '../table.less'; 13 import '../table.less';
14 14
15 export default ({ setVisible, subOrders, mainOrder, onClose }) => { 15 export default ({ setVisible, subOrders, mainOrder, onClose }) => {
@@ -106,7 +106,7 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; { @@ -106,7 +106,7 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
106 onClick={() => { 106 onClick={() => {
107 window.open( 107 window.open(
108 '/previewApi/onlinePreview?url=' + 108 '/previewApi/onlinePreview?url=' +
109 - encodeURIComponent(Base64.encode(item)), 109 + encodeURIComponent(Base64.encode(item)),
110 ); 110 );
111 }} 111 }}
112 > 112 >
src/pages/Order/components/OrderDrawer copy.tsx renamed to src/pages/Order/Order/components/OrderDrawer copy.tsx
src/pages/Order/components/OrderDrawer.tsx renamed to src/pages/Order/Order/components/OrderDrawer.tsx
@@ -51,7 +51,7 @@ import { @@ -51,7 +51,7 @@ import {
51 PAYMENT_METHOD_OPTIONS, 51 PAYMENT_METHOD_OPTIONS,
52 PRODUCT_BELONG_DEPARTMENT_OPTIONS, 52 PRODUCT_BELONG_DEPARTMENT_OPTIONS,
53 SHIPPING_WAREHOUSE_OPTIONS, 53 SHIPPING_WAREHOUSE_OPTIONS,
54 -} from '../constant'; 54 +} from '../../constant';
55 import KingdeeCustomerModal from './KingdeeCustomerModal'; 55 import KingdeeCustomerModal from './KingdeeCustomerModal';
56 56
57 export default ({ onClose, data, subOrders, orderOptType }) => { 57 export default ({ onClose, data, subOrders, orderOptType }) => {
@@ -556,9 +556,9 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -556,9 +556,9 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
556 form.setFieldValue( 556 form.setFieldValue(
557 'customerShippingAddress', 557 'customerShippingAddress',
558 getDefaultString(option.province) + 558 getDefaultString(option.province) +
559 - getDefaultString(option.city) +  
560 - getDefaultString(option.district) +  
561 - getDefaultString(option.detail), 559 + getDefaultString(option.city) +
  560 + getDefaultString(option.district) +
  561 + getDefaultString(option.detail),
562 ); 562 );
563 form.setFieldValue('customerNameString', option.realName); 563 form.setFieldValue('customerNameString', option.realName);
564 564
@@ -641,11 +641,11 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -641,11 +641,11 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
641 641
642 message.error( 642 message.error(
643 '用户余额不足,当前预减的金额为:' + 643 '用户余额不足,当前预减的金额为:' +
644 - data.subPrice +  
645 - ',当前账号余额为:' +  
646 - data.nowMoney +  
647 - ',当前账号可赊账额度为:' +  
648 - data.creditLimit, 644 + data.subPrice +
  645 + ',当前账号余额为:' +
  646 + data.nowMoney +
  647 + ',当前账号可赊账额度为:' +
  648 + data.creditLimit,
649 ); 649 );
650 return false; 650 return false;
651 } 651 }
@@ -1110,7 +1110,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1110,7 +1110,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1110 }, 1110 },
1111 }} 1111 }}
1112 debounceTime={1000} 1112 debounceTime={1000}
1113 - request={async (value, {}) => { 1113 + request={async (value, { }) => {
1114 const keywords = value.keyWords; 1114 const keywords = value.keyWords;
1115 if (keywords === '') { 1115 if (keywords === '') {
1116 return []; 1116 return [];
@@ -1865,7 +1865,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1865,7 +1865,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1865 placeholder="请输入商品参数" 1865 placeholder="请输入商品参数"
1866 disabled={ 1866 disabled={
1867 productParametersDisabledFlagList[listMeta.index] !== 1867 productParametersDisabledFlagList[listMeta.index] !==
1868 - false || optType('after-sales-check') 1868 + false || optType('after-sales-check')
1869 } 1869 }
1870 />, 1870 />,
1871 <ProFormDigit 1871 <ProFormDigit
@@ -1918,7 +1918,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1918,7 +1918,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1918 placeholder="请输入商品单位" 1918 placeholder="请输入商品单位"
1919 disabled={ 1919 disabled={
1920 productParametersDisabledFlagList[listMeta.index] !== 1920 productParametersDisabledFlagList[listMeta.index] !==
1921 - false || optType('after-sales-check') 1921 + false || optType('after-sales-check')
1922 } 1922 }
1923 rules={[{ required: true, message: '商品单位必填' }]} 1923 rules={[{ required: true, message: '商品单位必填' }]}
1924 />, 1924 />,
src/pages/Order/components/OrderNotesEditModal.tsx renamed to src/pages/Order/Order/components/OrderNotesEditModal.tsx
src/pages/Order/components/OtherInfoModal.tsx renamed to src/pages/Order/Order/components/OtherInfoModal.tsx
src/pages/Order/components/ProcureCheckModal.tsx renamed to src/pages/Order/Order/components/ProcureCheckModal.tsx
src/pages/Order/components/ProcureConvertModal.tsx renamed to src/pages/Order/Order/components/ProcureConvertModal.tsx
src/pages/Order/components/ProcureNotesEditModal.tsx renamed to src/pages/Order/Order/components/ProcureNotesEditModal.tsx
src/pages/Order/components/ProductionTimeModal.tsx renamed to src/pages/Order/Order/components/ProductionTimeModal.tsx
src/pages/Order/components/ReissueModal.tsx renamed to src/pages/Order/Order/components/ReissueModal.tsx
src/pages/Order/components/ReissueModal_old.tsx renamed to src/pages/Order/Order/components/ReissueModal_old.tsx
src/pages/Order/components/ShippingWarehouseChangeModal.tsx renamed to src/pages/Order/Order/components/ShippingWarehouseChangeModal.tsx
@@ -3,7 +3,7 @@ import { postServiceOrderShippingWarehouseChange } from &#39;@/services&#39;; @@ -3,7 +3,7 @@ import { postServiceOrderShippingWarehouseChange } from &#39;@/services&#39;;
3 import { enumToSelect } from '@/utils'; 3 import { enumToSelect } from '@/utils';
4 import { ModalForm, ProFormSelect } from '@ant-design/pro-components'; 4 import { ModalForm, ProFormSelect } from '@ant-design/pro-components';
5 import { Form, message } from 'antd'; 5 import { Form, message } from 'antd';
6 -import { SHIPPING_WAREHOUSE_OPTIONS } from '../constant'; 6 +import { SHIPPING_WAREHOUSE_OPTIONS } from '../../constant';
7 7
8 export default ({ 8 export default ({
9 setVisible, 9 setVisible,
src/pages/Order/components/UploadPayBillModal.tsx renamed to src/pages/Order/Order/components/UploadPayBillModal.tsx
@@ -3,7 +3,7 @@ import { Form, Modal, Upload, UploadFile, UploadProps, message } from &#39;antd&#39;; @@ -3,7 +3,7 @@ import { Form, Modal, Upload, UploadFile, UploadProps, message } from &#39;antd&#39;;
3 import { RcFile } from 'antd/lib/upload'; 3 import { RcFile } from 'antd/lib/upload';
4 import { cloneDeep } from 'lodash'; 4 import { cloneDeep } from 'lodash';
5 import { useEffect, useRef, useState } from 'react'; 5 import { useEffect, useRef, useState } from 'react';
6 -import { COMFIR_RECEIPT_IMAGES_NUMBER } from '../constant'; 6 +import { COMFIR_RECEIPT_IMAGES_NUMBER } from '../../constant';
7 import { PlusOutlined } from '@ant-design/icons'; 7 import { PlusOutlined } from '@ant-design/icons';
8 import { transImageFile } from '@/utils'; 8 import { transImageFile } from '@/utils';
9 import { postServiceOrderFileProcess, postServiceOrderUploadPaymentReceipt } from '@/services'; 9 import { postServiceOrderFileProcess, postServiceOrderUploadPaymentReceipt } from '@/services';
src/pages/Order/hooks.ts renamed to src/pages/Order/Order/hooks.ts
src/pages/Order/index.less renamed to src/pages/Order/Order/index.less
src/pages/Order/index.tsx renamed to src/pages/Order/Order/index.tsx
1 import ButtonConfirm from '@/components/ButtomConfirm'; 1 import ButtonConfirm from '@/components/ButtomConfirm';
2 import { RESPONSE_CODE } from '@/constants/enum'; 2 import { RESPONSE_CODE } from '@/constants/enum';
3 -import ImportExpressBillModal from '@/pages/Order/components/ImportExpressBillModal';  
4 -import InvoicingDrawerForm from '@/pages/Order/components/InvoicingDrawerForm';  
5 -import ReissueModal from '@/pages/Order/components/ReissueModal';  
6 -import ReissueModal_old from '@/pages/Order/components/ReissueModal_old'; 3 +import ImportExpressBillModal from '@/pages/Order/Order/components/ImportExpressBillModal';
  4 +import InvoicingDrawerForm from '@/pages/Order/Order/components/InvoicingDrawerForm';
  5 +import ReissueModal from '@/pages/Order/Order/components/ReissueModal';
  6 +import ReissueModal_old from '@/pages/Order/Order/components/ReissueModal_old';
7 import { 7 import {
8 postKingdeeRepSalBillOutbound, 8 postKingdeeRepSalBillOutbound,
9 postKingdeeRepSalOrderSave, 9 postKingdeeRepSalOrderSave,
@@ -78,7 +78,7 @@ import { @@ -78,7 +78,7 @@ import {
78 import Base64 from 'base-64'; 78 import Base64 from 'base-64';
79 import { cloneDeep } from 'lodash'; 79 import { cloneDeep } from 'lodash';
80 import React, { Key, useEffect, useMemo, useRef, useState } from 'react'; 80 import React, { Key, useEffect, useMemo, useRef, useState } from 'react';
81 -import OrderPrintModal from '../OrderPrint/OrderPrintModal'; 81 +import OrderPrintModal from '../../OrderPrint/OrderPrintModal';
82 import AfterSalesDrawer from './components/AfterSalesDrawer'; 82 import AfterSalesDrawer from './components/AfterSalesDrawer';
83 import ApplyForInvoicingModal from './components/ApplyForInvoicingModal'; 83 import ApplyForInvoicingModal from './components/ApplyForInvoicingModal';
84 import AttachmentModal from './components/AttachmentModal'; 84 import AttachmentModal from './components/AttachmentModal';
@@ -119,7 +119,7 @@ import { @@ -119,7 +119,7 @@ import {
119 TAGS_COLOR, 119 TAGS_COLOR,
120 getInvoicingType, 120 getInvoicingType,
121 getNeedInvoicing, 121 getNeedInvoicing,
122 -} from './constant'; 122 +} from '../constant';
123 import './index.less'; 123 import './index.less';
124 import { OrderListItemType, OrderType } from './type.d'; 124 import { OrderListItemType, OrderType } from './type.d';
125 125
@@ -830,7 +830,7 @@ const OrderPage = () =&gt; { @@ -830,7 +830,7 @@ const OrderPage = () =&gt; {
830 onConfirm={() => { 830 onConfirm={() => {
831 window.open( 831 window.open(
832 '/previewApi/onlinePreview?url=' + 832 '/previewApi/onlinePreview?url=' +
833 - encodeURIComponent(Base64.encode(item.url)), 833 + encodeURIComponent(Base64.encode(item.url)),
834 ); 834 );
835 }} 835 }}
836 onCancel={() => { 836 onCancel={() => {
@@ -902,7 +902,7 @@ const OrderPage = () =&gt; { @@ -902,7 +902,7 @@ const OrderPage = () =&gt; {
902 </span> 902 </span>
903 {(roleCode === 'salesRepresentative' || 903 {(roleCode === 'salesRepresentative' ||
904 roleCode === 'salesManager') && 904 roleCode === 'salesManager') &&
905 - !optRecord.isCurrentUserOrder ? ( 905 + !optRecord.isCurrentUserOrder ? (
906 <span className="text-[#f44e4e]">(非本账号订单)</span> 906 <span className="text-[#f44e4e]">(非本账号订单)</span>
907 ) : ( 907 ) : (
908 '' 908 ''
@@ -1086,13 +1086,13 @@ const OrderPage = () =&gt; { @@ -1086,13 +1086,13 @@ const OrderPage = () =&gt; {
1086 <Tooltip 1086 <Tooltip
1087 title={ 1087 title={
1088 optRecord.invoicingUrgentCause !== null && 1088 optRecord.invoicingUrgentCause !== null &&
1089 - optRecord.afterInvoicingStatus === 1089 + optRecord.afterInvoicingStatus ===
1090 'URGENT_INVOICE_AUDITING' 1090 'URGENT_INVOICE_AUDITING'
1091 ? optRecord.invoicingUrgentCause 1091 ? optRecord.invoicingUrgentCause
1092 : enumValueToLabel( 1092 : enumValueToLabel(
1093 - optRecord.afterInvoicingStatus,  
1094 - AFTER_INVOICING_STATUS,  
1095 - ) 1093 + optRecord.afterInvoicingStatus,
  1094 + AFTER_INVOICING_STATUS,
  1095 + )
1096 } 1096 }
1097 > 1097 >
1098 <Tag 1098 <Tag
@@ -1123,7 +1123,7 @@ const OrderPage = () =&gt; { @@ -1123,7 +1123,7 @@ const OrderPage = () =&gt; {
1123 )} 1123 )}
1124 1124
1125 {(roleCode === 'warehouseKeeper' || roleCode === 'admin') && 1125 {(roleCode === 'warehouseKeeper' || roleCode === 'admin') &&
1126 - optRecord.shippingWarehouse !== null ? ( 1126 + optRecord.shippingWarehouse !== null ? (
1127 <div 1127 <div
1128 className="overflow-hidden whitespace-no-wrap overflow-ellipsis" 1128 className="overflow-hidden whitespace-no-wrap overflow-ellipsis"
1129 title={enumValueToLabel( 1129 title={enumValueToLabel(
@@ -1145,7 +1145,7 @@ const OrderPage = () =&gt; { @@ -1145,7 +1145,7 @@ const OrderPage = () =&gt; {
1145 {/* 生产时间 */} 1145 {/* 生产时间 */}
1146 <div className="overflow-hidden whitespace-no-wrap overflow-ellipsis"> 1146 <div className="overflow-hidden whitespace-no-wrap overflow-ellipsis">
1147 {optRecord.productionStartTime !== null || 1147 {optRecord.productionStartTime !== null ||
1148 - optRecord.productionEndTime !== null ? ( 1148 + optRecord.productionEndTime !== null ? (
1149 <MyToolTip 1149 <MyToolTip
1150 title={ 1150 title={
1151 formatdate(optRecord.productionStartTime) + 1151 formatdate(optRecord.productionStartTime) +
@@ -1175,7 +1175,7 @@ const OrderPage = () =&gt; { @@ -1175,7 +1175,7 @@ const OrderPage = () =&gt; {
1175 <Tag 1175 <Tag
1176 color={ 1176 color={
1177 optRecord.invoicingTime === null || 1177 optRecord.invoicingTime === null ||
1178 - optRecord.invoicingTime === undefined 1178 + optRecord.invoicingTime === undefined
1179 ? TAGS_COLOR.get(optRecord.invoicingStatus) 1179 ? TAGS_COLOR.get(optRecord.invoicingStatus)
1180 : 'success' 1180 : 'success'
1181 } 1181 }
@@ -1203,7 +1203,7 @@ const OrderPage = () =&gt; { @@ -1203,7 +1203,7 @@ const OrderPage = () =&gt; {
1203 1203
1204 {/**采购是否已下单状态 */} 1204 {/**采购是否已下单状态 */}
1205 {optRecord.procureOrderStatus !== null && 1205 {optRecord.procureOrderStatus !== null &&
1206 - optRecord.procureOrderStatus !== undefined ? ( 1206 + optRecord.procureOrderStatus !== undefined ? (
1207 <div className="overflow-hidden whitespace-no-wrap overflow-ellipsis"> 1207 <div className="overflow-hidden whitespace-no-wrap overflow-ellipsis">
1208 <Tag color="success"> 1208 <Tag color="success">
1209 {enumValueToLabel( 1209 {enumValueToLabel(
@@ -1219,21 +1219,21 @@ const OrderPage = () =&gt; { @@ -1219,21 +1219,21 @@ const OrderPage = () =&gt; {
1219 {/* 物流信息 */} 1219 {/* 物流信息 */}
1220 <div className="overflow-hidden whitespace-no-wrap overflow-ellipsis"> 1220 <div className="overflow-hidden whitespace-no-wrap overflow-ellipsis">
1221 {optRecord.orderStatus === 'CONFIRM_RECEIPT' || 1221 {optRecord.orderStatus === 'CONFIRM_RECEIPT' ||
1222 - optRecord.orderStatus === 'AFTER_SALES_COMPLETION' ||  
1223 - optRecord.orderStatus === 'IN_AFTER_SALES' ||  
1224 - optRecord.orderStatus === 'SHIPPED' ? ( 1222 + optRecord.orderStatus === 'AFTER_SALES_COMPLETION' ||
  1223 + optRecord.orderStatus === 'IN_AFTER_SALES' ||
  1224 + optRecord.orderStatus === 'SHIPPED' ? (
1225 <MyToolTip 1225 <MyToolTip
1226 title={ 1226 title={
1227 optRecord.serialNumber === undefined 1227 optRecord.serialNumber === undefined
1228 ? '暂无物流信息' 1228 ? '暂无物流信息'
1229 : enumValueToLabel( 1229 : enumValueToLabel(
1230 - optRecord.logisticsMethod,  
1231 - LOGISTICS_STATUS_OPTIONS,  
1232 - ) +  
1233 - ' ' +  
1234 - optRecord.serialNumber +  
1235 - ' ' +  
1236 - optRecord.logisticsNotes 1230 + optRecord.logisticsMethod,
  1231 + LOGISTICS_STATUS_OPTIONS,
  1232 + ) +
  1233 + ' ' +
  1234 + optRecord.serialNumber +
  1235 + ' ' +
  1236 + optRecord.logisticsNotes
1237 } 1237 }
1238 content={ 1238 content={
1239 <Button type="link" size="small" style={{ padding: 0 }}> 1239 <Button type="link" size="small" style={{ padding: 0 }}>
@@ -1247,7 +1247,7 @@ const OrderPage = () =&gt; { @@ -1247,7 +1247,7 @@ const OrderPage = () =&gt; {
1247 1247
1248 {/* 修改审核状态 */} 1248 {/* 修改审核状态 */}
1249 {optRecord.modifiedAuditStatus !== null && 1249 {optRecord.modifiedAuditStatus !== null &&
1250 - optRecord.modifiedAuditStatus !== 'AUDIT_FAILURE' ? ( 1250 + optRecord.modifiedAuditStatus !== 'AUDIT_FAILURE' ? (
1251 <div className="overflow-hidden whitespace-no-wrap overflow-ellipsis"> 1251 <div className="overflow-hidden whitespace-no-wrap overflow-ellipsis">
1252 <Tooltip 1252 <Tooltip
1253 title={recordOptNode ? recordOptNode : <Spin />} 1253 title={recordOptNode ? recordOptNode : <Spin />}
@@ -1687,7 +1687,7 @@ const OrderPage = () =&gt; { @@ -1687,7 +1687,7 @@ const OrderPage = () =&gt; {
1687 )} 1687 )}
1688 1688
1689 {optRecord.paths?.includes('queryAnnex') && 1689 {optRecord.paths?.includes('queryAnnex') &&
1690 - optRecord.listAnnex?.length > 0 ? ( 1690 + optRecord.listAnnex?.length > 0 ? (
1691 <Button 1691 <Button
1692 className="p-0" 1692 className="p-0"
1693 type="link" 1693 type="link"
@@ -2121,7 +2121,7 @@ const OrderPage = () =&gt; { @@ -2121,7 +2121,7 @@ const OrderPage = () =&gt; {
2121 </Flex> 2121 </Flex>
2122 2122
2123 {(isProcure() || isWarehousekeeper() || isSales() || isAdmin()) && 2123 {(isProcure() || isWarehousekeeper() || isSales() || isAdmin()) &&
2124 - !isSupplier() ? ( 2124 + !isSupplier() ? (
2125 <div className="pt-2"> 2125 <div className="pt-2">
2126 <Flex title={optRecord.supplierName}> 2126 <Flex title={optRecord.supplierName}>
2127 <div> 2127 <div>
@@ -2196,7 +2196,7 @@ const OrderPage = () =&gt; { @@ -2196,7 +2196,7 @@ const OrderPage = () =&gt; {
2196 <span className="text-[#8C8C8C]"> 2196 <span className="text-[#8C8C8C]">
2197 申请开票备注: 2197 申请开票备注:
2198 {optRecord.applyInvoicingNotes === undefined || 2198 {optRecord.applyInvoicingNotes === undefined ||
2199 - optRecord.applyInvoicingNotes === null 2199 + optRecord.applyInvoicingNotes === null
2200 ? '暂无备注' 2200 ? '暂无备注'
2201 : optRecord.applyInvoicingNotes} 2201 : optRecord.applyInvoicingNotes}
2202 </span> 2202 </span>
@@ -2224,7 +2224,7 @@ const OrderPage = () =&gt; { @@ -2224,7 +2224,7 @@ const OrderPage = () =&gt; {
2224 <span className="text-[#8C8C8C] mr-3"> 2224 <span className="text-[#8C8C8C] mr-3">
2225 财务审核备注: 2225 财务审核备注:
2226 {optRecord.checkNotes === undefined || 2226 {optRecord.checkNotes === undefined ||
2227 - optRecord.checkNotes === null 2227 + optRecord.checkNotes === null
2228 ? '暂无备注' 2228 ? '暂无备注'
2229 : optRecord.checkNotes} 2229 : optRecord.checkNotes}
2230 </span> 2230 </span>
@@ -2248,7 +2248,7 @@ const OrderPage = () =&gt; { @@ -2248,7 +2248,7 @@ const OrderPage = () =&gt; {
2248 <span className="text-[#8C8C8C]"> 2248 <span className="text-[#8C8C8C]">
2249 重新开票备注: 2249 重新开票备注:
2250 {optRecord.reissueNotes === undefined || 2250 {optRecord.reissueNotes === undefined ||
2251 - optRecord.reissueNotes === null 2251 + optRecord.reissueNotes === null
2252 ? '暂无备注' 2252 ? '暂无备注'
2253 : optRecord.reissueNotes} 2253 : optRecord.reissueNotes}
2254 </span> 2254 </span>
@@ -2552,9 +2552,9 @@ const OrderPage = () =&gt; { @@ -2552,9 +2552,9 @@ const OrderPage = () =&gt; {
2552 <span className="text-slate-700"> 2552 <span className="text-slate-700">
2553 {record.receivingCompany !== null 2553 {record.receivingCompany !== null
2554 ? enumValueToLabel( 2554 ? enumValueToLabel(
2555 - record.receivingCompany,  
2556 - getReceivingCompanyOptions(PAYEE_OPTIONS),  
2557 - ) 2555 + record.receivingCompany,
  2556 + getReceivingCompanyOptions(PAYEE_OPTIONS),
  2557 + )
2558 : '暂无'} 2558 : '暂无'}
2559 </span> 2559 </span>
2560 </div> 2560 </div>
@@ -3346,9 +3346,9 @@ const OrderPage = () =&gt; { @@ -3346,9 +3346,9 @@ const OrderPage = () =&gt; {
3346 for (let i = 0; i < selectedSubOrders.length; i++) { 3346 for (let i = 0; i < selectedSubOrders.length; i++) {
3347 if ( 3347 if (
3348 selectedSubOrders[i].invoicingStatus === 3348 selectedSubOrders[i].invoicingStatus ===
3349 - 'UN_INVOICE' || 3349 + 'UN_INVOICE' ||
3350 selectedSubOrders[i].afterInvoicingStatus === 3350 selectedSubOrders[i].afterInvoicingStatus ===
3351 - 'APPLY_FOR_INVOICING' 3351 + 'APPLY_FOR_INVOICING'
3352 ) { 3352 ) {
3353 message.error( 3353 message.error(
3354 '请选择需要开票且未申请开票的子订单进行申请', 3354 '请选择需要开票且未申请开票的子订单进行申请',
@@ -3383,9 +3383,9 @@ const OrderPage = () =&gt; { @@ -3383,9 +3383,9 @@ const OrderPage = () =&gt; {
3383 for (let i = 0; i < selectedSubOrders.length; i++) { 3383 for (let i = 0; i < selectedSubOrders.length; i++) {
3384 if ( 3384 if (
3385 selectedSubOrders[i].invoicingStatus === 3385 selectedSubOrders[i].invoicingStatus ===
3386 - 'UN_INVOICE' || 3386 + 'UN_INVOICE' ||
3387 selectedSubOrders[i].afterInvoicingStatus === 3387 selectedSubOrders[i].afterInvoicingStatus ===
3388 - 'APPLY_FOR_INVOICING' 3388 + 'APPLY_FOR_INVOICING'
3389 ) { 3389 ) {
3390 message.error( 3390 message.error(
3391 '请选择需要开票且未申请开票的子订单进行申请', 3391 '请选择需要开票且未申请开票的子订单进行申请',
@@ -3576,13 +3576,13 @@ const OrderPage = () =&gt; { @@ -3576,13 +3576,13 @@ const OrderPage = () =&gt; {
3576 if ( 3576 if (
3577 selectedSubOrders[i].orderStatus !== 'AUDITED' && 3577 selectedSubOrders[i].orderStatus !== 'AUDITED' &&
3578 selectedSubOrders[i].orderStatus !== 3578 selectedSubOrders[i].orderStatus !==
3579 - 'PROCURE_PROCESS' && 3579 + 'PROCURE_PROCESS' &&
3580 selectedSubOrders[i].orderStatus !== 3580 selectedSubOrders[i].orderStatus !==
3581 - 'PROCURE_PROCESS_FOR_MINE' && 3581 + 'PROCURE_PROCESS_FOR_MINE' &&
3582 selectedSubOrders[i].orderStatus !== 3582 selectedSubOrders[i].orderStatus !==
3583 - 'PROCURE_WAIT_SHIP' && 3583 + 'PROCURE_WAIT_SHIP' &&
3584 selectedSubOrders[i].orderStatus !== 3584 selectedSubOrders[i].orderStatus !==
3585 - 'SUPPLIER_WAIT_SHIP' && 3585 + 'SUPPLIER_WAIT_SHIP' &&
3586 selectedSubOrders[i].orderStatus !== 'WAIT_SHIP' 3586 selectedSubOrders[i].orderStatus !== 'WAIT_SHIP'
3587 ) { 3587 ) {
3588 message.error( 3588 message.error(
@@ -3668,9 +3668,9 @@ const OrderPage = () =&gt; { @@ -3668,9 +3668,9 @@ const OrderPage = () =&gt; {
3668 if ( 3668 if (
3669 selectedSubOrders[i].orderStatus !== 'UNAUDITED' && 3669 selectedSubOrders[i].orderStatus !== 'UNAUDITED' &&
3670 selectedSubOrders[i].orderStatus !== 3670 selectedSubOrders[i].orderStatus !==
3671 - 'FINANCE_PROCESS' && 3671 + 'FINANCE_PROCESS' &&
3672 selectedSubOrders[i].orderStatus !== 3672 selectedSubOrders[i].orderStatus !==
3673 - 'LEADER_AUDITED' 3673 + 'LEADER_AUDITED'
3674 ) { 3674 ) {
3675 message.error( 3675 message.error(
3676 '请选择[未审核]、[财务待审核]、[领导已审核]的子订单进行审核', 3676 '请选择[未审核]、[财务待审核]、[领导已审核]的子订单进行审核',
@@ -3738,9 +3738,9 @@ const OrderPage = () =&gt; { @@ -3738,9 +3738,9 @@ const OrderPage = () =&gt; {
3738 for (let i = 0; i < selectedSubOrders.length; i++) { 3738 for (let i = 0; i < selectedSubOrders.length; i++) {
3739 if ( 3739 if (
3740 selectedSubOrders[i].orderStatus !== 3740 selectedSubOrders[i].orderStatus !==
3741 - 'CONFIRM_RECEIPT' && 3741 + 'CONFIRM_RECEIPT' &&
3742 selectedSubOrders[i].orderStatus !== 3742 selectedSubOrders[i].orderStatus !==
3743 - 'AFTER_SALES_FAILURE' 3743 + 'AFTER_SALES_FAILURE'
3744 ) { 3744 ) {
3745 message.error('请选择确认收货状态的子订单进行售后'); 3745 message.error('请选择确认收货状态的子订单进行售后');
3746 return; 3746 return;
@@ -4203,7 +4203,7 @@ const OrderPage = () =&gt; { @@ -4203,7 +4203,7 @@ const OrderPage = () =&gt; {
4203 4203
4204 const exportMenuProps = { 4204 const exportMenuProps = {
4205 items: exportItems, 4205 items: exportItems,
4206 - onClick: () => {}, 4206 + onClick: () => { },
4207 }; 4207 };
4208 4208
4209 //导出按钮配置 4209 //导出按钮配置
@@ -4249,7 +4249,7 @@ const OrderPage = () =&gt; { @@ -4249,7 +4249,7 @@ const OrderPage = () =&gt; {
4249 4249
4250 const auditProps = { 4250 const auditProps = {
4251 items: auditItems, 4251 items: auditItems,
4252 - onClick: () => {}, 4252 + onClick: () => { },
4253 }; 4253 };
4254 4254
4255 if (rolePath?.includes('leaderMergeAudit')) { 4255 if (rolePath?.includes('leaderMergeAudit')) {
@@ -4370,8 +4370,8 @@ const OrderPage = () =&gt; { @@ -4370,8 +4370,8 @@ const OrderPage = () =&gt; {
4370 if (errorIds.size > 0) { 4370 if (errorIds.size > 0) {
4371 message.error( 4371 message.error(
4372 '订单号为:' + 4372 '订单号为:' +
4373 - [...errorIds.values()].join(',') +  
4374 - '的订单存在不是[申请开票]或者[部分开票]状态的子订单,请检查!', 4373 + [...errorIds.values()].join(',') +
  4374 + '的订单存在不是[申请开票]或者[部分开票]状态的子订单,请检查!',
4375 ); 4375 );
4376 return; 4376 return;
4377 } 4377 }
src/pages/Order/table.less renamed to src/pages/Order/Order/table.less
src/pages/Order/type.d.ts renamed to src/pages/Order/Order/type.d.ts
src/pages/Order/OrderWarning/components/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/OrderWarning/components/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/OrderWarning/components/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/OrderWarning/components/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/OrderWarning/components/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 + ProFormTextArea,
  14 + ProList,
  15 +} from '@ant-design/pro-components';
  16 +import {
  17 + Button,
  18 + Col,
  19 + Divider,
  20 + Form,
  21 + Image,
  22 + Modal,
  23 + Row,
  24 + Space,
  25 + Tag,
  26 + UploadFile,
  27 + message,
  28 +} from 'antd';
  29 +import Upload, { RcFile, UploadProps } from 'antd/es/upload';
  30 +import { useEffect, useRef, useState } from 'react';
  31 +import {
  32 + AFTE_SALES_PLAN_OPTIONS,
  33 + CHECK_TYPE,
  34 + COMFIR_RECEIPT_IMAGES_NUMBER,
  35 +} from '../../constant';
  36 +// import { cloneDeep } from 'lodash';
  37 +import InvoiceSubOrderInfoTable from '@/pages/Order/Order/components/InvoiceSubOrderInfoTable';
  38 +import { enumValueToLabel, transImageFile } from '@/utils';
  39 +import { PlusOutlined } from '@ant-design/icons';
  40 +import { cloneDeep } from 'lodash';
  41 +
  42 +export default ({
  43 + setCheckVisible,
  44 + data,
  45 + subOrders,
  46 + orderCheckType,
  47 + openOrderDrawer,
  48 + onClose,
  49 +}) => {
  50 + const [previewOpen, setPreviewOpen] = useState(false);
  51 + const [aPopoverTitle, setAPopoverTitle] = useState('审核');
  52 + const [previewImage, setPreviewImage] = useState('');
  53 + const [previewTitle, setPreviewTitle] = useState('');
  54 + const [paymentReceiptsImages, setPymentReceiptsImages] = useState<any[]>([]);
  55 + const fileListObj = useRef<UploadFile[]>([]); //使用引用类型,使得在useEffect里面设置监听事件后,不用更新监听事件也能保持obj与外界一致
  56 + const getBase64 = (file: RcFile): Promise<string> =>
  57 + new Promise((resolve, reject) => {
  58 + const reader = new FileReader();
  59 + reader.readAsDataURL(file);
  60 + reader.onload = () => resolve(reader.result as string);
  61 + reader.onerror = (error) => reject(error);
  62 + });
  63 + const [fileList, setFileList] = useState<UploadFile[]>([]);
  64 + const handleCancel = () => setPreviewOpen(false);
  65 + const [messageApi, contextHolder] = message.useMessage();
  66 + const [form] = Form.useForm<{ name: string; company: string }>();
  67 + let subOrderIds: any[] = subOrders?.map((subOrder) => subOrder.id);
  68 + const [mainOrderId] = useState(data.id);
  69 +
  70 + const [afterSalesInfo, setAfterSalesInfo] = useState<any>();
  71 + const [prepaidProofImages, setPrepaidProofImages] = useState<any[]>([]);
  72 + /**
  73 + * 审核类型
  74 + */
  75 + function checkType(check: string) {
  76 + if (orderCheckType === check) {
  77 + return true;
  78 + }
  79 + return false;
  80 + }
  81 +
  82 + const getOrderAfterSalesInfo = async () => {
  83 + // let res = await postServiceOrderQueryAfterSalesInfoSnapshot({
  84 + // data: { subOrderIds: subOrderIds },
  85 + // });
  86 +
  87 + //附件
  88 + let annex = subOrders[0].afterSalesAnnexList;
  89 + let index = 1;
  90 + let annexLinks = annex?.map((f) => {
  91 + return (
  92 + <Button className="p-0 pr-1" type="link" key="key" href={f}>
  93 + {'附件' + index++}
  94 + </Button>
  95 + );
  96 + });
  97 +
  98 + console.log(annexLinks);
  99 +
  100 + setAfterSalesInfo(
  101 + <div className="my-5">
  102 + <Row gutter={[16, 24]}>
  103 + <Col span={6}>
  104 + <span className="text-[#333333]">售后方案</span>
  105 + </Col>
  106 + <Col span={18}>
  107 + {enumValueToLabel(
  108 + subOrders[0]?.afterSalesPlan,
  109 + AFTE_SALES_PLAN_OPTIONS,
  110 + )}
  111 + </Col>
  112 + <Col span={6}>
  113 + <span className="className='text-[#333333]'">售后原因</span>
  114 + </Col>
  115 + <Col span={18}>{subOrders[0]?.afterSalesNotes}</Col>
  116 + <Col span={6}>
  117 + <span className="className='text-[#333333]'">附件</span>
  118 + </Col>
  119 + <Col span={18}>{annexLinks}</Col>
  120 + </Row>
  121 + </div>,
  122 + );
  123 + };
  124 +
  125 + useEffect(() => {
  126 + if (checkType(CHECK_TYPE.CONFIRM_DELIVER)) {
  127 + setAPopoverTitle('确认发货');
  128 + }
  129 + getOrderAfterSalesInfo();
  130 +
  131 + let paymentReceiptsImagesList: any[] = [];
  132 + subOrders?.forEach((item: any) => {
  133 + if (item.paymentReceiptAnnexList) {
  134 + paymentReceiptsImagesList.push(...item.paymentReceiptAnnexList);
  135 + }
  136 + });
  137 + //去重
  138 + paymentReceiptsImagesList = [...new Set(paymentReceiptsImagesList)];
  139 + setPymentReceiptsImages(paymentReceiptsImagesList);
  140 +
  141 + //预存审核的凭证
  142 + let proofImages: any[] = [];
  143 + subOrders?.forEach((item) => {
  144 + let images = item.proofImages;
  145 + if (images !== null && images !== undefined) {
  146 + proofImages.push(...images);
  147 + }
  148 + });
  149 + setPrepaidProofImages(proofImages);
  150 + }, []);
  151 +
  152 + const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
  153 + //fileListObj得在change里变化,change的参数是已经处理过的file数组
  154 + //beforeUpload中的参数file是未处理过,还需要Base64拿到文件数据处理
  155 + fileListObj.current = newFileList;
  156 + setFileList(newFileList);
  157 + };
  158 +
  159 + /** 粘贴快捷键的回调 */
  160 + const onPaste = async (e: any) => {
  161 + /** 获取剪切板的数据clipboardData */
  162 + let clipboardData = e.clipboardData,
  163 + i = 0,
  164 + items,
  165 + item,
  166 + types;
  167 +
  168 + /** 为空判断 */
  169 + if (clipboardData) {
  170 + items = clipboardData.items;
  171 + if (!items) {
  172 + message.info('您的剪贴板中没有照片');
  173 + return;
  174 + }
  175 +
  176 + item = items[0];
  177 + types = clipboardData.types || [];
  178 + /** 遍历剪切板的数据 */
  179 + for (; i < types.length; i++) {
  180 + if (types[i] === 'Files') {
  181 + item = items[i];
  182 + break;
  183 + }
  184 + }
  185 +
  186 + /** 判断文件是否为图片 */
  187 + if (item && item.kind === 'file' && item.type.match(/^image\//i)) {
  188 + const imgItem = item.getAsFile();
  189 + const newFileList = cloneDeep(fileListObj.current);
  190 + let filteredArray = newFileList.filter(
  191 + (obj) => obj.status !== 'removed',
  192 + ); //过滤掉状态为已删除的照片
  193 + const listItem = {
  194 + ...imgItem,
  195 + status: 'done',
  196 + url: await getBase64(imgItem),
  197 + originFileObj: imgItem,
  198 + };
  199 +
  200 + if (filteredArray.length >= COMFIR_RECEIPT_IMAGES_NUMBER) {
  201 + message.info('发货照片数量不能超过3');
  202 + return;
  203 + }
  204 + fileListObj.current = filteredArray;
  205 + filteredArray.push(listItem);
  206 + setFileList(filteredArray);
  207 + return;
  208 + }
  209 + }
  210 +
  211 + message.info('您的剪贴板中没有照片');
  212 + };
  213 + useEffect(() => {
  214 + //回显售后信息
  215 + // if (checkType(CHECK_TYPE.AFTER_SALES)) {
  216 + // getOrderAfterSalesInfo();
  217 + // }
  218 +
  219 + document.addEventListener('paste', onPaste);
  220 + return () => {
  221 + document.removeEventListener('paste', onPaste);
  222 + };
  223 + }, []);
  224 + const uploadButton = (
  225 + <div>
  226 + <PlusOutlined />
  227 + <div style={{ marginTop: 8 }}>上传凭证</div>
  228 + </div>
  229 + );
  230 + const handlePreview = async (file: UploadFile) => {
  231 + if (!file.url && !file.preview) {
  232 + file.preview = await getBase64(file.originFileObj as RcFile);
  233 + }
  234 + setPreviewImage(file.url || (file.preview as string));
  235 + setPreviewOpen(true);
  236 + setPreviewTitle(
  237 + file.name ||
  238 + file.originFileObj?.name ||
  239 + file.url!.substring(file.url!.lastIndexOf('/') + 1),
  240 + );
  241 + };
  242 +
  243 + const handleBeforeUpload = (file: any) => {
  244 + setFileList([...fileList, file]);
  245 + return false;
  246 + };
  247 +
  248 + const props: UploadProps = {
  249 + onRemove: (file) => {
  250 + const index = fileList.indexOf(file);
  251 + const newFileList = fileList.slice();
  252 + newFileList.splice(index, 1);
  253 + setFileList(newFileList);
  254 + },
  255 + beforeUpload: handleBeforeUpload,
  256 + listType: 'picture-card',
  257 + onPreview: handlePreview,
  258 + fileList,
  259 + onChange: handleChange,
  260 + accept: 'image/png, image/jpeg, image/png',
  261 + // action: '/api/service/order/fileProcess',
  262 + name: 'files',
  263 + headers: { Authorization: localStorage.getItem('token') },
  264 + };
  265 +
  266 + //仓库审核
  267 + async function doCheck(body: object) {
  268 + const data = await postServiceOrderAudit({
  269 + data: body,
  270 + });
  271 + if (data.result === RESPONSE_CODE.SUCCESS) {
  272 + message.success(data.message);
  273 + onClose();
  274 + }
  275 + }
  276 +
  277 + /**
  278 + *
  279 + * @param body 财务审核
  280 + */
  281 + async function doFinancailCheck(values: any, isAgree: boolean) {
  282 + if (fileList.length <= 0) {
  283 + message.error('凭证不能为空');
  284 + return;
  285 + }
  286 + messageApi.open({
  287 + type: 'loading',
  288 + content: '正在上传图片...',
  289 + duration: 0,
  290 + });
  291 + //附件处理
  292 + let formData = new FormData();
  293 + //附件处理
  294 + for (let file of fileList) {
  295 + if (file.originFileObj) {
  296 + formData.append('files', file.originFileObj as RcFile);
  297 + } else {
  298 + //有url的话取url(源文件),没url取thumbUrl。有url的时候thumbUrl是略缩图
  299 + if (file?.url === undefined || file?.url === null) {
  300 + formData.append(
  301 + 'files',
  302 + transImageFile(file?.thumbUrl),
  303 + file?.originFileObj?.name,
  304 + );
  305 + } else {
  306 + formData.append(
  307 + 'files',
  308 + transImageFile(file?.url),
  309 + file?.originFileObj?.name,
  310 + );
  311 + }
  312 + }
  313 + }
  314 + let res = await postServiceOrderFileProcess({
  315 + data: formData,
  316 + });
  317 + messageApi.destroy();
  318 + if (res.result === RESPONSE_CODE.SUCCESS) {
  319 + message.success('上传成功!');
  320 +
  321 + let fileUrls = res?.data?.map((item) => {
  322 + return { url: item };
  323 + });
  324 + //财务审核
  325 + const data = await postServiceOrderFinanceCheckOrder({
  326 + data: {
  327 + checkNotes: values.name,
  328 + ids: subOrderIds,
  329 + checkPassOrReject: isAgree,
  330 + invoicingCheckAnnex: fileUrls,
  331 + },
  332 + });
  333 + if (data.result === RESPONSE_CODE.SUCCESS) {
  334 + message.success(data.message);
  335 + onClose();
  336 + }
  337 + } else {
  338 + message.success('上传失败');
  339 + }
  340 + }
  341 +
  342 + /**
  343 + *
  344 + * @param body 售后审核
  345 + */
  346 + async function doAfterSalesCheck(body: object) {
  347 + const data = await postServiceOrderAfterSalesCheck({
  348 + data: body,
  349 + });
  350 + if (data.result === RESPONSE_CODE.SUCCESS) {
  351 + message.success(data.message);
  352 + onClose();
  353 + }
  354 + }
  355 +
  356 + /**
  357 + *
  358 + * @param body 领导审核
  359 + */
  360 + async function doLeaderCheck(body: object) {
  361 + const data = await postServiceOrderLeaderAudit({
  362 + data: body,
  363 + });
  364 + if (data.result === RESPONSE_CODE.SUCCESS) {
  365 + message.success(data.message);
  366 + onClose();
  367 + }
  368 + }
  369 +
  370 + /**
  371 + * 预存审核
  372 + * @param body
  373 + */
  374 + async function doPrepaidAudit(body: any) {
  375 + const data = await postPrepaidAudit({
  376 + data: body,
  377 + });
  378 + if (data.result === RESPONSE_CODE.SUCCESS) {
  379 + message.success(data.message);
  380 + onClose();
  381 + }
  382 + }
  383 +
  384 + function computeType() {
  385 + let type: string = '';
  386 + if (checkType(CHECK_TYPE.CONFIRM_DELIVER)) {
  387 + type = 'confirm_deliver';
  388 + }
  389 + if (checkType(CHECK_TYPE.WEARHOUSE_KEEPER)) {
  390 + type = 'warehouse_audit';
  391 + }
  392 + if (checkType(CHECK_TYPE.WAITING_FOR_POST_AUDIT)) {
  393 + type = 'post_audit';
  394 + }
  395 + if (checkType(CHECK_TYPE.NODE_OPERATING_AUDIT)) {
  396 + type = 'node_operating_audit';
  397 + }
  398 + if (checkType(CHECK_TYPE.MODIFY_LEADER_AUDIT)) {
  399 + type = 'modify_leader_audit';
  400 + }
  401 + if (checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING)) {
  402 + type = 'urgent_invoice_audit';
  403 + }
  404 + if (checkType(CHECK_TYPE.PAYMENT_RECEIPTS_AUDIT)) {
  405 + type = 'payment_receipt_audit';
  406 + }
  407 + if (checkType(CHECK_TYPE.CONFIRM_REISSUE)) {
  408 + type = 'confirm_reissue';
  409 + }
  410 + if (checkType(CHECK_TYPE.CREDIT_AUDIT)) {
  411 + type = 'credit_audit';
  412 + }
  413 + if (checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING_OLD)) {
  414 + type = 'urgent_invoice_audit_old';
  415 + }
  416 + if (checkType(CHECK_TYPE.CONFIRM_REISSUE_OLD)) {
  417 + type = 'confirm_reissue_old';
  418 + }
  419 + return type;
  420 + }
  421 +
  422 + return (
  423 + <>
  424 + <ModalForm<{
  425 + name: string;
  426 + company: string;
  427 + }>
  428 + width={500}
  429 + open
  430 + title={aPopoverTitle}
  431 + form={form}
  432 + autoFocusFirstInput
  433 + modalProps={{
  434 + okText: '通过',
  435 + cancelText: '驳回',
  436 + destroyOnClose: true,
  437 + onCancel: () => {
  438 + setCheckVisible(false);
  439 + },
  440 + }}
  441 + submitter={{
  442 + render: (props, defaultDoms) => {
  443 + let myDoms = [];
  444 + if (!checkType(CHECK_TYPE.CONFIRM_DELIVER)) {
  445 + myDoms.push(
  446 + <Button
  447 + key="驳回"
  448 + onClick={async () => {
  449 + if (checkType(CHECK_TYPE.AFTER_SALES)) {
  450 + doAfterSalesCheck({
  451 + applyType: 'after-sales',
  452 + isAfterSalesSuccess: false,
  453 + subOrderIds: subOrderIds,
  454 + mainId: mainOrderId,
  455 + afterSalesRejectionNotes: form.getFieldValue('name'),
  456 + });
  457 + return;
  458 + }
  459 +
  460 + if (checkType(CHECK_TYPE.FINALCIAL)) {
  461 + let values = { name: form.getFieldValue('name') };
  462 + doFinancailCheck(values, false);
  463 + return;
  464 + }
  465 +
  466 + if (checkType(CHECK_TYPE.LEADER_AUDIT)) {
  467 + doLeaderCheck({
  468 + pass: false,
  469 + subOrderIds: subOrderIds,
  470 + reason: form.getFieldValue('name'),
  471 + });
  472 + return;
  473 + }
  474 +
  475 + if (checkType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT)) {
  476 + doAfterSalesCheck({
  477 + applyType: 'order-change-normal',
  478 + isAfterSalesSuccess: false,
  479 + subOrderIds: subOrderIds,
  480 + mainId: mainOrderId,
  481 + afterSalesRejectionNotes: form.getFieldValue('name'),
  482 + });
  483 + return;
  484 + }
  485 +
  486 + //预存审核,先暂时共用同一个审核弹窗
  487 + if (checkType(CHECK_TYPE.PREPAID_AUDIT)) {
  488 + return doPrepaidAudit({
  489 + pass: false,
  490 + ids: subOrderIds,
  491 + auditNotes: form.getFieldValue('name'),
  492 + });
  493 + }
  494 +
  495 + let type = '';
  496 + type = computeType();
  497 + console.log('type:' + type);
  498 + doCheck({
  499 + pass: false,
  500 + subOrderIds: subOrderIds,
  501 + type: type,
  502 + notes: form.getFieldValue('name'),
  503 + });
  504 + }}
  505 + >
  506 + 驳回
  507 + </Button>,
  508 + );
  509 + }
  510 +
  511 + //如果是仓库审核,那么显示这个外部采购
  512 + if (checkType(CHECK_TYPE.WEARHOUSE_KEEPER)) {
  513 + myDoms.push(
  514 + <Button
  515 + key="外部采购"
  516 + onClick={async () => {
  517 + let res = await postServiceOrderToProcureAudit({
  518 + data: {
  519 + subOrderIds: subOrderIds,
  520 + },
  521 + });
  522 +
  523 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  524 + message.success(res.message);
  525 + onClose();
  526 + }
  527 + }}
  528 + >
  529 + 外部采购
  530 + </Button>,
  531 + );
  532 + }
  533 +
  534 + //确认
  535 + myDoms.push(defaultDoms[1]);
  536 + return myDoms;
  537 + },
  538 + }}
  539 + submitTimeout={2000}
  540 + onFinish={async (values) => {
  541 + if (checkType(CHECK_TYPE.AFTER_SALES)) {
  542 + //审核通过
  543 + return doAfterSalesCheck({
  544 + applyType: 'after-sales',
  545 + isAfterSalesSuccess: true,
  546 + subOrderIds: subOrderIds,
  547 + mainId: mainOrderId,
  548 + afterSalesRejectionNotes: values.name,
  549 + });
  550 + }
  551 + console.log('h');
  552 + if (checkType(CHECK_TYPE.FINALCIAL)) {
  553 + doFinancailCheck(values, true);
  554 + return;
  555 + }
  556 +
  557 + if (checkType(CHECK_TYPE.LEADER_AUDIT)) {
  558 + doLeaderCheck({
  559 + pass: true,
  560 + subOrderIds: subOrderIds,
  561 + reason: values.name,
  562 + });
  563 + return;
  564 + }
  565 +
  566 + if (checkType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT)) {
  567 + //审核通过
  568 + return doAfterSalesCheck({
  569 + applyType: 'order-change-normal',
  570 + isAfterSalesSuccess: true,
  571 + subOrderIds: subOrderIds,
  572 + mainId: mainOrderId,
  573 + afterSalesRejectionNotes: values.name,
  574 + });
  575 + }
  576 +
  577 + //预存审核,先暂时共用同一个审核弹窗
  578 + if (checkType(CHECK_TYPE.PREPAID_AUDIT)) {
  579 + return doPrepaidAudit({
  580 + pass: true,
  581 + ids: subOrderIds,
  582 + auditNotes: form.getFieldValue('name'),
  583 + });
  584 + }
  585 +
  586 + let type = '';
  587 + type = computeType();
  588 + doCheck({
  589 + pass: true,
  590 + subOrderIds: subOrderIds,
  591 + type: type,
  592 + notes: form.getFieldValue('name'),
  593 + });
  594 + }}
  595 + onOpenChange={setCheckVisible}
  596 + >
  597 + {checkType(CHECK_TYPE.AFTER_SALES) ? (
  598 + <>
  599 + {afterSalesInfo}
  600 + <Button
  601 + className="px-0"
  602 + type="link"
  603 + onClick={() => {
  604 + console.log(data);
  605 + openOrderDrawer('after-sales-check', mainOrderId);
  606 + }}
  607 + >
  608 + 查看旧订单
  609 + </Button>
  610 + </>
  611 + ) : (
  612 + ''
  613 + )}
  614 +
  615 + {checkType(CHECK_TYPE.PAYMENT_RECEIPTS_AUDIT) ? (
  616 + <>
  617 + <Divider orientation="center">
  618 + <span className="text-sm">回款凭证</span>
  619 + </Divider>
  620 + <Image.PreviewGroup
  621 + className="mr-10"
  622 + preview={{
  623 + onChange: (current, prev) =>
  624 + console.log(`current index: ${current}, prev index: ${prev}`),
  625 + }}
  626 + >
  627 + {paymentReceiptsImages.map((url) => (
  628 + <>
  629 + <Image width={120} src={url} /> <Divider type="vertical" />
  630 + </>
  631 + ))}
  632 + </Image.PreviewGroup>
  633 + <Divider></Divider>
  634 + </>
  635 + ) : (
  636 + ''
  637 + )}
  638 +
  639 + {checkType(CHECK_TYPE.PREPAID_AUDIT) && (
  640 + <>
  641 + <Divider orientation="center">
  642 + <span className="text-sm">凭证</span>
  643 + </Divider>
  644 + <Image.PreviewGroup
  645 + className="mr-10"
  646 + preview={{
  647 + onChange: (current, prev) =>
  648 + console.log(`current index: ${current}, prev index: ${prev}`),
  649 + }}
  650 + >
  651 + {prepaidProofImages.map((url) => (
  652 + <>
  653 + <Image width={120} src={url} /> <Divider type="vertical" />
  654 + </>
  655 + ))}
  656 + </Image.PreviewGroup>
  657 + <Divider></Divider>
  658 + </>
  659 + )}
  660 +
  661 + {checkType('prepaidAudit') ? (
  662 + <div>请特别注意手机号码和充值金额。</div>
  663 + ) : (
  664 + <div>请特别注意订单总金额与订单金额。</div>
  665 + )}
  666 + {!checkType(CHECK_TYPE.CONFIRM_DELIVER) ? (
  667 + <ProFormTextArea
  668 + width="lg"
  669 + name="name"
  670 + placeholder="若驳回,请填写驳回理由"
  671 + />
  672 + ) : (
  673 + <></>
  674 + )}
  675 + {checkType(CHECK_TYPE.FINALCIAL) ? (
  676 + <>
  677 + <div className="pb-4 text-xs decoration-gray-50">
  678 + 可复制照片粘贴
  679 + </div>
  680 + <Upload {...props}>
  681 + {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER
  682 + ? uploadButton
  683 + : ''}
  684 + </Upload>
  685 + </>
  686 + ) : (
  687 + ''
  688 + )}
  689 + {checkType(CHECK_TYPE.CONFIRM_REISSUE) && (
  690 + <>
  691 + <InvoiceSubOrderInfoTable
  692 + subOrderIds={subOrderIds}
  693 + ></InvoiceSubOrderInfoTable>
  694 + </>
  695 + )}
  696 + {checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING) ? (
  697 + <>
  698 + <ProList
  699 + rowKey="id"
  700 + headerTitle="发票信息"
  701 + metas={{
  702 + title: {
  703 + dataIndex: 'name',
  704 + },
  705 + avatar: {
  706 + dataIndex: 'image',
  707 + editable: false,
  708 + },
  709 + description: {
  710 + dataIndex: 'desc',
  711 + },
  712 + subTitle: {
  713 + render: () => {
  714 + return (
  715 + <Space size={0}>
  716 + <Tag color="blue">Ant Design</Tag>
  717 + <Tag color="#5BD8A6">TechUI</Tag>
  718 + </Space>
  719 + );
  720 + },
  721 + },
  722 + actions: {
  723 + render: (text, row, index, action) => [
  724 + <a
  725 + onClick={() => {
  726 + action?.startEditable(row.id);
  727 + }}
  728 + key="link"
  729 + >
  730 + 编辑
  731 + </a>,
  732 + ],
  733 + },
  734 + }}
  735 + ></ProList>
  736 + </>
  737 + ) : (
  738 + ''
  739 + )}
  740 + </ModalForm>
  741 +
  742 + <Modal
  743 + open={previewOpen}
  744 + title={previewTitle}
  745 + footer={null}
  746 + onCancel={handleCancel}
  747 + >
  748 + <img alt="图片预览" style={{ width: '100%' }} src={previewImage} />
  749 + </Modal>
  750 + {contextHolder}
  751 + </>
  752 + );
  753 +};
src/pages/Order/OrderWarning/components/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/OrderWarning/components/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}&nbsp;{city}&nbsp;{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/OrderWarning/components/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/OrderWarning/components/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/OrderWarning/components/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/OrderWarning/components/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/OrderWarning/components/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/OrderWarning/components/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/OrderWarning/components/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 +
  40 + return (
  41 + <>
  42 + <Modal
  43 + title={title}
  44 + open
  45 + onOk={handleOk}
  46 + onCancel={handleCancel}
  47 + footer={[
  48 + <Button key="back" onClick={handleCancel}>
  49 + 返回
  50 + </Button>,
  51 + ]}
  52 + >
  53 + <Image.PreviewGroup
  54 + className="mr-10"
  55 + preview={{
  56 + onChange: (current, prev) =>
  57 + console.log(`current index: ${current}, prev index: ${prev}`),
  58 + }}
  59 + >
  60 + {images.map((url) => (
  61 + <>
  62 + <Image width={120} src={url} /> <Divider type="vertical" />
  63 + </>
  64 + ))}
  65 + </Image.PreviewGroup>
  66 + </Modal>
  67 + </>
  68 + );
  69 +};
src/pages/Order/OrderWarning/components/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 +};
src/pages/Order/OrderWarning/components/ImportModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import { postServiceOrderImportExcel } from '@/services';
  3 +import { orderExport } from '@/services/order';
  4 +import { UploadOutlined } from '@ant-design/icons';
  5 +import { Button, Modal, Upload, message } from 'antd';
  6 +import { RcFile, UploadFile, UploadProps } from 'antd/es/upload';
  7 +import { useState } from 'react';
  8 +export default ({ onClose }) => {
  9 + // const [form] = Form.useForm<{ name: string; company: string }>();
  10 + const [messageApi, contextHolder] = message.useMessage();
  11 + const [fileList, setFileList] = useState<UploadFile[]>([]);
  12 + const [uploading, setUploading] = useState(false);
  13 + const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) =>
  14 + setFileList(newFileList);
  15 +
  16 + const exportLoading = (content: string) => {
  17 + messageApi.open({
  18 + type: 'loading',
  19 + content: content,
  20 + duration: 0,
  21 + });
  22 + };
  23 +
  24 + const exportLoadingDestory = () => {
  25 + messageApi.destroy();
  26 + };
  27 + const downloadTemplate = async () => {
  28 + exportLoading('正在下载模板...');
  29 + orderExport(
  30 + '/api/service/order/exportTemplate',
  31 + '订单.xlsx',
  32 + 'post',
  33 + {},
  34 + exportLoadingDestory,
  35 + );
  36 + };
  37 +
  38 + const handleUpload = async () => {
  39 + const formData = new FormData();
  40 + fileList.forEach((file) => {
  41 + //originFileObj二进制文件
  42 + formData.append('file', file.originFileObj as RcFile);
  43 + });
  44 + // console.log(fileList[0] as RcFile)
  45 + // formData.append('file', fileList[0] as RcFile);
  46 + setUploading(true);
  47 + // You can use any AJAX library you like
  48 + const res = await postServiceOrderImportExcel({
  49 + data: formData,
  50 + headers: {
  51 + 'Content-Type':
  52 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  53 + },
  54 + });
  55 +
  56 + if (res.result === RESPONSE_CODE.SUCCESS) {
  57 + message.success(res.message);
  58 + onClose();
  59 + } else {
  60 + if (res.message === '表格中没有数据') {
  61 + setUploading(false);
  62 + return;
  63 + }
  64 + //存在错误信息,下载错误信息模板
  65 + exportLoading('正在下载错误信息...');
  66 + orderExport(
  67 + '/api/service/order/errorExcelInformation',
  68 + '订单.xlsx',
  69 + 'post',
  70 + formData,
  71 + exportLoadingDestory,
  72 + );
  73 + }
  74 +
  75 + setUploading(false);
  76 + };
  77 +
  78 + const props: UploadProps = {
  79 + onRemove: (file) => {
  80 + const index = fileList.indexOf(file);
  81 + const newFileList = fileList.slice();
  82 + newFileList.splice(index, 1);
  83 + setFileList(newFileList);
  84 + },
  85 + beforeUpload: (file) => {
  86 + setFileList([...fileList, file]);
  87 +
  88 + return false;
  89 + },
  90 + fileList,
  91 + onChange: handleChange,
  92 + accept: '.xlsx',
  93 + };
  94 +
  95 + return (
  96 + <>
  97 + <Modal
  98 + width={500}
  99 + open
  100 + title="批量发货"
  101 + footer={[
  102 + <Button key="cancel" onClick={onClose}>
  103 + 取消
  104 + </Button>,
  105 + <Button
  106 + type="primary"
  107 + key="ok"
  108 + onClick={handleUpload}
  109 + disabled={fileList.length === 0}
  110 + loading={uploading}
  111 + >
  112 + {uploading ? '上传中' : '提交'}
  113 + </Button>,
  114 + ]}
  115 + onCancel={async () => {
  116 + onClose();
  117 + }}
  118 + >
  119 + <div className="py-4 font-semibold">
  120 + 导入发货信息
  121 + <Button type="link" onClick={downloadTemplate}>
  122 + 下载模板
  123 + </Button>
  124 + </div>
  125 + <Upload {...props}>
  126 + <Button icon={<UploadOutlined />} disabled={fileList.length > 0}>
  127 + 点击选择文件
  128 + </Button>
  129 + </Upload>
  130 + </Modal>
  131 + {contextHolder}
  132 + </>
  133 + );
  134 +};
src/pages/Order/OrderWarning/components/InvoiceSubOrderInfoTable.tsx 0 → 100644
  1 +import { postServiceOrderGetReissueInfo } from '@/services';
  2 +import type { ProColumns } from '@ant-design/pro-components';
  3 +import { ProTable } from '@ant-design/pro-components';
  4 +import { Button, Divider } from 'antd';
  5 +import { useEffect, useState } from 'react';
  6 +
  7 +const columns: ProColumns[] = [
  8 + {
  9 + title: '发票号码',
  10 + width: 80,
  11 + dataIndex: 'invoiceNumber',
  12 + render: (_) => _,
  13 + },
  14 + {
  15 + title: '关联订单',
  16 + dataIndex: 'subOrderIds',
  17 + render: (_, { subOrderIds }) => {
  18 + console.log(JSON.stringify(_));
  19 + console.log(JSON.stringify(subOrderIds));
  20 + return (
  21 + <>
  22 + {subOrderIds.map((subOrderId, index) => {
  23 + return (
  24 + <>
  25 + <Button
  26 + key={index}
  27 + className="pl-1 pr-0"
  28 + type="link"
  29 + target="_blank"
  30 + href={'/order?id=' + subOrderId}
  31 + >
  32 + {subOrderId}
  33 + </Button>
  34 + <Divider type="vertical" />
  35 + </>
  36 + );
  37 + })}
  38 + </>
  39 + );
  40 + },
  41 + },
  42 +];
  43 +
  44 +export default ({ subOrderIds }) => {
  45 + const [reissueInfos, setReissueInfos] = useState([]);
  46 + useEffect(() => {
  47 + console.log('info');
  48 + const getReissueInfo = async () => {
  49 + let res = await postServiceOrderGetReissueInfo({
  50 + data: subOrderIds,
  51 + });
  52 + setReissueInfos(res.data);
  53 + };
  54 + getReissueInfo();
  55 + }, []);
  56 + return (
  57 + <ProTable
  58 + dataSource={reissueInfos}
  59 + rowKey="key"
  60 + pagination={false}
  61 + size={'small'}
  62 + //设置左右下边距为0
  63 + options={false}
  64 + columns={columns}
  65 + search={false}
  66 + dateFormatter="string"
  67 + headerTitle="发票信息"
  68 + />
  69 + );
  70 +};
src/pages/Order/OrderWarning/components/InvoicingDrawerForm.tsx 0 → 100644
  1 +// import { PlusOutlined } from '@ant-design/icons';
  2 +import InvoiceModal from '@/pages/Invoice/InvoiceVerification/components/InvoiceModal';
  3 +import {
  4 + postServiceConstGetPayeeEnum,
  5 + postServiceConstInitInvoiceDetailNames,
  6 + postServiceConstInvoiceType,
  7 + postServiceConstInvoicingType,
  8 + postServiceConstListInvoiceDetailNames,
  9 + postServiceInvoiceApplyInvoice,
  10 + postServiceInvoiceQueryCompanyInfo,
  11 + postServiceInvoiceWaitReissueInvoices,
  12 +} from '@/services';
  13 +import { FloatAdd, FloatSub, enum2ReverseSelect, enumToSelect } from '@/utils';
  14 +import { convertCurrency } from '@/utils/numberUtil';
  15 +import {
  16 + DrawerForm,
  17 + FormListActionType,
  18 + ProCard,
  19 + ProFormDigit,
  20 + ProFormGroup,
  21 + ProFormInstance,
  22 + ProFormList,
  23 + ProFormMoney,
  24 + ProFormSelect,
  25 + ProFormText,
  26 + ProFormTextArea,
  27 +} from '@ant-design/pro-components';
  28 +import { Button, Divider, Form, Space, Tooltip, message } from 'antd';
  29 +import { useEffect, useRef, useState } from 'react';
  30 +
  31 +export default ({ dataList, setVisible, mainOrder, onClose }) => {
  32 + // let subOrderIds = dataList?.map((item) => {
  33 + // return item.id;
  34 + // })
  35 + const [form] = Form.useForm();
  36 + const [projectOptions] = useState();
  37 + const [dataListCopy] = useState(dataList);
  38 + const listActionRef = useRef<FormListActionType>();
  39 + const formRef = useRef<ProFormInstance>();
  40 + useEffect(() => {
  41 + const initOptions = async () => {
  42 + const res = await postServiceConstInitInvoiceDetailNames({
  43 + data: dataListCopy.map((item) => {
  44 + return item.productName;
  45 + }),
  46 + });
  47 + const options = res.data;
  48 + const datas = dataListCopy.map((item) => {
  49 + return {
  50 + ...item,
  51 + projectName: options[item.productName],
  52 + };
  53 + });
  54 + const initialValue = datas.map((item) => {
  55 + return {
  56 + productName: item.productName,
  57 + projectName: item.projectName,
  58 + subOrderId: item.id,
  59 + specification: item.parameters,
  60 + unit: item.unit,
  61 + quantity: item.quantity,
  62 + price: item.productPrice,
  63 + totalPrice: item.subOrderPayment,
  64 + };
  65 + });
  66 + form.setFieldValue('invoiceDetails', initialValue);
  67 + form.setFieldValue('contacts', mainOrder.customerName);
  68 + };
  69 + initOptions();
  70 + }, []);
  71 +
  72 + useEffect(() => {}, [projectOptions]);
  73 +
  74 + function copyToClipboard(text: string) {
  75 + // 创建一个临时的textarea元素
  76 + const textarea = document.createElement('textarea');
  77 + textarea.value = text;
  78 +
  79 + // 将textarea元素添加到DOM中
  80 + document.body.appendChild(textarea);
  81 +
  82 + // 选中textarea中的文本
  83 + textarea.select();
  84 +
  85 + try {
  86 + // 尝试执行复制命令
  87 + document.execCommand('copy');
  88 + return true;
  89 + } catch (err) {
  90 + return false;
  91 + } finally {
  92 + // 移除临时的textarea元素
  93 + document.body.removeChild(textarea);
  94 + }
  95 + }
  96 +
  97 + useEffect(() => {}, []);
  98 + return (
  99 + <DrawerForm
  100 + open
  101 + title="申请开票"
  102 + resize={{
  103 + maxWidth: window.innerWidth * 0.8,
  104 + minWidth: 500,
  105 + }}
  106 + form={form}
  107 + formRef={formRef}
  108 + autoFocusFirstInput
  109 + drawerProps={{
  110 + destroyOnClose: true,
  111 + }}
  112 + submitter={{
  113 + render: (props, defaultDoms) => {
  114 + return [
  115 + <InvoiceModal
  116 + key={'invoicePreview'}
  117 + button={<Button type="primary"> 发票预览 </Button>}
  118 + getRecord={() => {
  119 + const totalPrice = form
  120 + .getFieldValue('invoiceDetails')
  121 + .reduce((accumulator, currentValue) => {
  122 + return FloatAdd(accumulator, currentValue.totalPrice);
  123 + }, 0);
  124 + const partyBName = form.getFieldValue('partyBName');
  125 + const openBank = form.getFieldValue('openBank');
  126 + const bankAccount = form.getFieldValue('bankAccount');
  127 + const bankCode = form.getFieldValue('bankCode');
  128 + return {
  129 + ...form.getFieldsValue(),
  130 + totalPrice: totalPrice,
  131 + totalPriceText: convertCurrency(totalPrice),
  132 + comment:
  133 + '开户名称: ' +
  134 + partyBName +
  135 + '\n' +
  136 + '开户行: ' +
  137 + openBank +
  138 + '\n' +
  139 + '账号: ' +
  140 + bankAccount +
  141 + '\n' +
  142 + '银行联行号: ' +
  143 + bankCode,
  144 + };
  145 + }}
  146 + />,
  147 + ...defaultDoms,
  148 + ];
  149 + },
  150 + }}
  151 + submitTimeout={2000}
  152 + onFinish={async (values) => {
  153 + postServiceInvoiceApplyInvoice({
  154 + data: {
  155 + ...values,
  156 + subOrderIds: dataListCopy.map((item) => {
  157 + return item.id;
  158 + }),
  159 + },
  160 + });
  161 + onClose();
  162 + }}
  163 + onOpenChange={(val) => {
  164 + return !val && setVisible();
  165 + }}
  166 + >
  167 + <ProFormList
  168 + name="subOrderIdObjs"
  169 + readonly={true}
  170 + label="开票订单"
  171 + initialValue={dataListCopy.map((item) => {
  172 + return {
  173 + value: item.id,
  174 + };
  175 + })}
  176 + deleteIconProps={false}
  177 + copyIconProps={false}
  178 + >
  179 + <ProFormGroup key="group">
  180 + <ProFormText readonly={true} name="value" label="" />
  181 + </ProFormGroup>
  182 + </ProFormList>
  183 + <ProFormSelect
  184 + name="ReissueInvoiceRecordIds"
  185 + label="重开的发票"
  186 + fieldProps={{
  187 + mode: 'multiple',
  188 + }}
  189 + placeholder="请选择重开发票"
  190 + request={async () => {
  191 + let reissueIds = dataListCopy.map((item) => {
  192 + return item.id;
  193 + });
  194 + let res = await postServiceInvoiceWaitReissueInvoices({
  195 + data: reissueIds,
  196 + });
  197 + return enum2ReverseSelect(res.data);
  198 + }}
  199 + />
  200 + <ProFormSelect
  201 + key="key"
  202 + label="购方名称"
  203 + width="lg"
  204 + showSearch
  205 + name="partyAName"
  206 + placeholder="请搜索购方"
  207 + rules={[{ required: true, message: '购方名称必填' }]}
  208 + onChange={(_, option) => {
  209 + form.setFieldValue('partyATaxid', option.taxId);
  210 + }}
  211 + fieldProps={{
  212 + optionItemRender(item) {
  213 + if (item.type === 'add') {
  214 + return <>{item.name}</>;
  215 + }
  216 + return (
  217 + <>
  218 + {item.name}
  219 + <Divider type="vertical" />
  220 + {item.taxId}
  221 + </>
  222 + );
  223 + },
  224 + }}
  225 + debounceTime={1000}
  226 + request={async (value) => {
  227 + const keywords = value.keyWords;
  228 + const res = await postServiceInvoiceQueryCompanyInfo({
  229 + data: {
  230 + nameLike: keywords,
  231 + taxIdIsNotNull: true,
  232 + },
  233 + });
  234 + let options = res?.data?.map((company) => {
  235 + return {
  236 + ...company,
  237 + label: company.name,
  238 + value: company.name,
  239 + key: company.id,
  240 + };
  241 + });
  242 +
  243 + //第一个商品默认为要新增的商品
  244 + if (keywords.trim() !== '') {
  245 + options.unshift({
  246 + name: keywords,
  247 + type: 'add',
  248 + label: keywords,
  249 + value: keywords,
  250 + key: keywords,
  251 + });
  252 + }
  253 + return options;
  254 + }}
  255 + />
  256 + <ProFormText
  257 + width="md"
  258 + name="partyATaxid"
  259 + label="购方税号"
  260 + rules={[{ required: true, message: '购方税号必填' }]}
  261 + placeholder="请输入名称"
  262 + />
  263 + <ProFormText
  264 + width="md"
  265 + name="partyAOpenBank"
  266 + label="开户银行"
  267 + placeholder="请输入名称"
  268 + />
  269 + <ProFormText
  270 + width="md"
  271 + name="partyABankAccount"
  272 + label="开户行账号"
  273 + placeholder="请输入名称"
  274 + />
  275 + <ProFormText
  276 + name="contacts"
  277 + label="联系人"
  278 + rules={[{ required: true, message: '请选择银行联行号!' }]}
  279 + />
  280 + <ProFormSelect
  281 + name="invoicingType"
  282 + label="开具类型"
  283 + request={async () => {
  284 + let invoicingTypeRet = await postServiceConstInvoicingType();
  285 + let options = enumToSelect(invoicingTypeRet.data);
  286 + return options;
  287 + }}
  288 + placeholder="请选择开具类型"
  289 + rules={[{ required: true, message: '请选择开具类型!' }]}
  290 + />
  291 + <ProFormSelect
  292 + name="type"
  293 + label="开票类型"
  294 + placeholder="请选择开票类型"
  295 + rules={[{ required: true, message: '请选择开票类型!' }]}
  296 + request={async () => {
  297 + let invoiceTypeRet = await postServiceConstInvoiceType();
  298 + let options = enumToSelect(invoiceTypeRet.data);
  299 + return options;
  300 + }}
  301 + />
  302 + <ProFormSelect
  303 + name="partyB"
  304 + label="开票收款单位"
  305 + request={async () => {
  306 + const res = await postServiceConstGetPayeeEnum();
  307 + let options = res?.data?.map((payee: any) => {
  308 + return {
  309 + ...payee,
  310 + label: payee.payeeName,
  311 + value: payee.name,
  312 + };
  313 + });
  314 + return options;
  315 + }}
  316 + onChange={(_, option) => {
  317 + if (option) {
  318 + form.setFieldsValue({
  319 + partyBName: option.payeeName,
  320 + partyBTaxid: option.taxId,
  321 + bankAccount: option.bankAccount,
  322 + openBank: option.openBank,
  323 + bankCode: option.bankCode,
  324 + });
  325 + }
  326 + }}
  327 + placeholder="请选择收款单位"
  328 + rules={[{ required: true, message: '请选择收款单位!' }]}
  329 + />
  330 + <ProFormText
  331 + name="partyBName"
  332 + label="开票收款单位名称"
  333 + hidden
  334 + rules={[{ required: true, message: '请选择收款单位!' }]}
  335 + />
  336 + <ProFormText
  337 + name="partyBTaxid"
  338 + label="开票收款单位税号"
  339 + hidden
  340 + rules={[{ required: true, message: '请选择收款单位!' }]}
  341 + />
  342 + <ProFormText
  343 + name="bankAccount"
  344 + label="账号"
  345 + hidden
  346 + rules={[{ required: true, message: '请选择账号!' }]}
  347 + />
  348 + <ProFormText
  349 + name="openBank"
  350 + label="开户行"
  351 + hidden
  352 + rules={[{ required: true, message: '请选择开户行!' }]}
  353 + />
  354 + <ProFormText
  355 + name="bankCode"
  356 + label="银行联行号"
  357 + hidden
  358 + rules={[{ required: true, message: '请选择银行联行号!' }]}
  359 + />
  360 + <ProFormSelect
  361 + name="isUrgent"
  362 + label="是否加急"
  363 + valueEnum={{
  364 + true: '是',
  365 + false: '否',
  366 + }}
  367 + placeholder="请选择是否加急"
  368 + rules={[{ required: true, message: '请选择是否加急!' }]}
  369 + />
  370 + <ProFormMoney
  371 + label="开票金额"
  372 + name="price"
  373 + locale="zh-CN"
  374 + disabled={true}
  375 + rules={[{ required: true, message: '请填写开票金额!' }]}
  376 + initialValue={dataListCopy.reduce((accumulator, currentValue) => {
  377 + return accumulator + currentValue.subOrderPayment;
  378 + }, 0)}
  379 + />
  380 + <ProFormList
  381 + name="invoiceDetails"
  382 + label="开票明细"
  383 + actionRef={listActionRef}
  384 + actionGuard={{
  385 + beforeRemoveRow: async (index) => {
  386 + const list = listActionRef.current?.getList();
  387 + const totalPrice = list[index].totalPrice;
  388 + form.setFieldValue(
  389 + 'price',
  390 + FloatSub(form.getFieldValue('price'), totalPrice),
  391 + );
  392 + return true;
  393 + },
  394 + }}
  395 + rules={[
  396 + {
  397 + required: true,
  398 + validator: async (_, value) => {
  399 + if (value && value.length > 0) {
  400 + return;
  401 + }
  402 + throw new Error('至少要有一项!');
  403 + },
  404 + },
  405 + ]}
  406 + itemRender={(doms, listMeta) => {
  407 + return (
  408 + <ProCard
  409 + bordered
  410 + extra={doms.action}
  411 + title={'明细' + (listMeta.index + 1)}
  412 + style={{
  413 + marginBlockEnd: 8,
  414 + }}
  415 + >
  416 + <Tooltip title="点击复制商品名称">
  417 + <Space
  418 + className="hover:cursor-pointer"
  419 + style={{
  420 + margin: 16,
  421 + marginTop: 4,
  422 + marginLeft: 0,
  423 + fontSize: 15,
  424 + }}
  425 + onClick={() => {
  426 + copyToClipboard(listMeta.record.productName);
  427 + message.info('商品名称复制成功!');
  428 + }}
  429 + >
  430 + 商品名称:{listMeta.record.productName}
  431 + </Space>
  432 + </Tooltip>
  433 + <ProFormSelect
  434 + key={'projectName' + listMeta.index}
  435 + width="md"
  436 + showSearch
  437 + name="projectName"
  438 + rules={[{ required: true, message: '请输入开票项目名称!' }]}
  439 + request={async (value) => {
  440 + const keywords = value.keyWords;
  441 + const res = await postServiceConstListInvoiceDetailNames({
  442 + data: {
  443 + nameLike: keywords,
  444 + },
  445 + });
  446 + let options = res?.data?.map((c: any) => {
  447 + return {
  448 + ...c,
  449 + label:
  450 + '*' +
  451 + c.productAndServiceCatagoryAbbreviation +
  452 + '*' +
  453 + c.name,
  454 + value:
  455 + '*' +
  456 + c.productAndServiceCatagoryAbbreviation +
  457 + '*' +
  458 + c?.name,
  459 + key: c.id,
  460 + };
  461 + });
  462 + return options;
  463 + }}
  464 + fieldProps={{
  465 + filterOption() {
  466 + return true;
  467 + },
  468 + }}
  469 + onChange={(_, option) => {
  470 + let index = listMeta.index;
  471 + let copyList = form.getFieldValue('invoiceDetails');
  472 + let currentData = copyList[index];
  473 + currentData.projectName =
  474 + '*' +
  475 + option.productAndServiceCatagoryAbbreviation +
  476 + '*' +
  477 + option.name;
  478 + form.setFieldValue('invoiceDetails', copyList);
  479 + }}
  480 + debounceTime={1000}
  481 + label="项目名称"
  482 + initialValue={listMeta.record.projectName}
  483 + placeholder="请输入名称"
  484 + />
  485 + <ProFormText
  486 + key={'specification' + listMeta.index}
  487 + name="specification"
  488 + label="规格型号"
  489 + rules={[
  490 + {
  491 + message: '规格型号不能为空!',
  492 + required: true,
  493 + },
  494 + {
  495 + validator: (_, value) => {
  496 + let len = 0;
  497 + // 判断是否为全角字符
  498 + for (let i = 0; i < value.length; i++) {
  499 + // 获取字符的Unicode值
  500 + const code = value.charCodeAt(i);
  501 + // 判断是否为全角字符
  502 + if (
  503 + (code >= 0xff01 && code <= 0xff5e) ||
  504 + (code >= 0x4e00 && code <= 0x9fff)
  505 + ) {
  506 + len += 2; // 全角字符
  507 + } else {
  508 + len += 1; // 半角字符
  509 + }
  510 + }
  511 + if (len <= 40) {
  512 + return Promise.resolve();
  513 + }
  514 + return Promise.reject(
  515 + new Error('规格型号不能超过40个字符!'),
  516 + );
  517 + },
  518 + },
  519 + ]}
  520 + placeholder="请输入名称"
  521 + />
  522 + <ProFormText
  523 + key={'unit' + listMeta.index}
  524 + name="unit"
  525 + label="单位"
  526 + placeholder="请输入名称"
  527 + />
  528 + <ProFormDigit
  529 + key={'quantity' + listMeta.index}
  530 + label="数量"
  531 + name="quantity"
  532 + rules={[
  533 + {
  534 + validator: (_, value) => {
  535 + if (value === undefined || value > 0) {
  536 + return Promise.resolve();
  537 + }
  538 + return Promise.reject(new Error('数量必须大于0'));
  539 + },
  540 + },
  541 + ]}
  542 + />
  543 + <ProFormDigit
  544 + key={'price' + listMeta.index}
  545 + label="单价"
  546 + name="price"
  547 + rules={[
  548 + {
  549 + validator: (_, value) => {
  550 + if (value === undefined || value > 0) {
  551 + return Promise.resolve();
  552 + }
  553 + return Promise.reject(new Error('单价必须大于0'));
  554 + },
  555 + },
  556 + ]}
  557 + />
  558 + <ProFormMoney
  559 + key={'totalPrice' + listMeta.index}
  560 + label="金额"
  561 + name="totalPrice"
  562 + onChange={() => {
  563 + const invoiceDetails = form.getFieldValue('invoiceDetails');
  564 + console.log('invoiceDetails', invoiceDetails);
  565 + const totalPrice = invoiceDetails.reduce(
  566 + (accumulator, currentValue) => {
  567 + return FloatAdd(accumulator, currentValue.totalPrice);
  568 + },
  569 + 0,
  570 + );
  571 + console.log('totalPrice', totalPrice);
  572 + form.setFieldValue('price', totalPrice);
  573 + }}
  574 + rules={[
  575 + {
  576 + validator: (_, value) => {
  577 + if (value === undefined || value > 0) {
  578 + return Promise.resolve();
  579 + }
  580 + return Promise.reject(new Error('金额必须大于0'));
  581 + },
  582 + },
  583 + ]}
  584 + locale="zh-CN"
  585 + />
  586 + </ProCard>
  587 + );
  588 + }}
  589 + ></ProFormList>
  590 + <ProFormTextArea
  591 + name="applyInvoicingNotes"
  592 + label="备注"
  593 + placeholder="请输入名称"
  594 + />
  595 + </DrawerForm>
  596 + );
  597 +};
src/pages/Order/OrderWarning/components/KingdeeCustomerModal.tsx 0 → 100644
  1 +import {
  2 + postKingdeeRepCustomerDetail,
  3 + postKingdeeRepCustomerSave,
  4 +} from '@/services';
  5 +import { getTeacherCustomFieldNumber } from '@/utils/kingdee';
  6 +import { CloseCircleOutlined } from '@ant-design/icons';
  7 +import {
  8 + ModalForm,
  9 + ProFormGroup,
  10 + ProFormList,
  11 + ProFormText,
  12 +} from '@ant-design/pro-components';
  13 +import { Form, message } from 'antd';
  14 +
  15 +// import { cloneDeep } from 'lodash';
  16 +export default ({ setVisible, data, onClose }) => {
  17 + const [form] = Form.useForm();
  18 +
  19 + /**
  20 + * 回显客户信息
  21 + * @param id
  22 + */
  23 + async function queryAndShowCustomer(id: any) {
  24 + //查询客户信息
  25 + let res = await postKingdeeRepCustomerDetail({
  26 + data: {
  27 + id: id,
  28 + },
  29 + });
  30 +
  31 + if (res) {
  32 + form.setFieldValue('name', res.name);
  33 + form.setFieldValue('id', res.id);
  34 + form.setFieldValue('contact_persons', res.bomentity);
  35 + let customFiledNumber = await getTeacherCustomFieldNumber();
  36 + form.setFieldValue('teacherName', res.custom_field[customFiledNumber]);
  37 + }
  38 + }
  39 +
  40 + if (data) {
  41 + //修改
  42 + if (data.id) {
  43 + queryAndShowCustomer(data.id);
  44 + } else {
  45 + //新增
  46 + form.setFieldValue('name', data.name);
  47 + form.setFieldValue('contact_persons', [{}]);
  48 + }
  49 + }
  50 + return (
  51 + <>
  52 + <ModalForm
  53 + width={900}
  54 + open
  55 + title="客户信息"
  56 + form={form}
  57 + autoFocusFirstInput
  58 + modalProps={{
  59 + okText: '保存',
  60 + cancelText: '取消',
  61 + destroyOnClose: true,
  62 + onCancel: () => {
  63 + setVisible(false);
  64 + },
  65 + }}
  66 + onFinish={async (values) => {
  67 + //查询客户自定义字段,课题组
  68 + let custom_field_umber = await getTeacherCustomFieldNumber();
  69 +
  70 + if (custom_field_umber) {
  71 + let customFieldObj = {};
  72 + customFieldObj[custom_field_umber] = values.teacherName;
  73 + values.custom_field = customFieldObj;
  74 + }
  75 + let customSaveRes = await postKingdeeRepCustomerSave({
  76 + data: values,
  77 + });
  78 + if (customSaveRes) {
  79 + let id_number_map = customSaveRes.id_number_map;
  80 + let ids = customSaveRes.ids;
  81 + if (id_number_map && ids) {
  82 + message.success('保存成功');
  83 + let id = ids[0];
  84 + onClose(id);
  85 + }
  86 + }
  87 + }}
  88 + onOpenChange={setVisible}
  89 + >
  90 + <ProFormText key="key" name="id" label="id" placeholder="id" hidden />
  91 + <ProFormGroup key="group">
  92 + <ProFormText
  93 + name="name"
  94 + width="md"
  95 + label={
  96 + <>
  97 + <span>客户名称</span>
  98 + <span className="pl-2 text-xs text-gray-400">
  99 + 请按照[单位]-[姓名][手机号]命名,例如:清华大学-张三12345678919
  100 + </span>
  101 + </>
  102 + }
  103 + initialValue={data}
  104 + placeholder="请输入客户名称"
  105 + rules={[
  106 + {
  107 + required: true,
  108 + pattern: new RegExp('^.+-.+$'),
  109 + message:
  110 + '格式错误,若无单位可写:“无-姓名手机号”,例如:无-张三12345678919',
  111 + },
  112 + { required: true, message: '客户名称必填' },
  113 + ]}
  114 + />
  115 + <ProFormText
  116 + name="teacherName"
  117 + width="md"
  118 + label="课题组老师"
  119 + placeholder="请输入课题组老师"
  120 + rules={[
  121 + { required: true, message: '课题组老师必填,若没有请填“无”' },
  122 + ]}
  123 + />
  124 + </ProFormGroup>
  125 +
  126 + <ProFormList
  127 + creatorButtonProps={{ disabled: false }}
  128 + name="contact_persons"
  129 + label="联系人信息"
  130 + actionGuard={{
  131 + beforeRemoveRow: async () => {
  132 + return new Promise((resolve) => {
  133 + let contactPersons = form.getFieldValue('contact_persons');
  134 + if (contactPersons.length === 1) {
  135 + message.error('至少要有一个联系人');
  136 + resolve(false);
  137 + return;
  138 + }
  139 + resolve(true);
  140 + });
  141 + },
  142 + beforeAddRow: (defaultValue) => {
  143 + defaultValue.id = undefined; //复制的时候要把id去掉
  144 + return defaultValue;
  145 + },
  146 + }}
  147 + deleteIconProps={{
  148 + Icon: CloseCircleOutlined,
  149 + tooltipText: '不需要这行了',
  150 + }}
  151 + >
  152 + <ProFormGroup key="group">
  153 + {[
  154 + <ProFormText
  155 + key="key"
  156 + name="id"
  157 + label="id"
  158 + placeholder="id"
  159 + hidden
  160 + />,
  161 + <ProFormText
  162 + key="key"
  163 + name="contact_person"
  164 + label="收货人姓名"
  165 + placeholder="联系人姓名"
  166 + rules={[{ required: true, message: '收货人姓名必填' }]}
  167 + />,
  168 + <ProFormText
  169 + key="key"
  170 + name="mobile"
  171 + label="联系方式"
  172 + placeholder="联系方式"
  173 + rules={[{ required: true, message: '联系方式必填' }]}
  174 + />,
  175 + <ProFormText
  176 + key="key"
  177 + name="contact_address"
  178 + label="收货地址"
  179 + width="md"
  180 + placeholder="请输入收货地址"
  181 + rules={[{ required: true, message: '收货地址必填' }]}
  182 + />,
  183 + ]}
  184 + </ProFormGroup>
  185 + </ProFormList>
  186 + </ModalForm>
  187 + </>
  188 + );
  189 +};