Commit c89daffdcb177f6131e3fccdb8780f44b1039ceb

Authored by 柏杨
2 parents 1243cef9 4dc9675c

Merge branch 'bugfix-invoicestatus' into dev

Too many changes to show.

To preserve performance only 15 of 24 files are displayed.

src/pages/Invoice/InvoiceRecord/components/InvoiceRecordDetailModal.tsx
@@ -3,7 +3,6 @@ import InvoiceDetailTable from '@/pages/Invoice/InvoiceRecord/components/Invoice @@ -3,7 +3,6 @@ import InvoiceDetailTable from '@/pages/Invoice/InvoiceRecord/components/Invoice
3 import { 3 import {
4 postServiceConstGetPayeeEnum, 4 postServiceConstGetPayeeEnum,
5 postServiceConstInvoiceType, 5 postServiceConstInvoiceType,
6 - postServiceConstInvoicingType,  
7 postServiceInvoiceGetInvoiceRecord, 6 postServiceInvoiceGetInvoiceRecord,
8 postServiceInvoiceModifyRecord, 7 postServiceInvoiceModifyRecord,
9 } from '@/services'; 8 } from '@/services';
@@ -230,7 +229,7 @@ export default ({ id, setVisible, reloadTable }) => { @@ -230,7 +229,7 @@ export default ({ id, setVisible, reloadTable }) => {
230 { required: true, message: 'Please select your country!' }, 229 { required: true, message: 'Please select your country!' },
231 ]} 230 ]}
232 /> 231 />
233 - <ProFormSelect 232 + {/* <ProFormSelect
234 name="invoicingType" 233 name="invoicingType"
235 readonly={readOnly} 234 readonly={readOnly}
236 label="开具类型" 235 label="开具类型"
@@ -246,7 +245,7 @@ export default ({ id, setVisible, reloadTable }) =&gt; { @@ -246,7 +245,7 @@ export default ({ id, setVisible, reloadTable }) =&gt; {
246 rules={[ 245 rules={[
247 { required: true, message: 'Please select your country!' }, 246 { required: true, message: 'Please select your country!' },
248 ]} 247 ]}
249 - /> 248 + /> */}
250 <ProFormList 249 <ProFormList
251 label="订单号" 250 label="订单号"
252 name="orderIdList" 251 name="orderIdList"
src/pages/Invoice/InvoiceVerification/components/InvoiceRecordDetailModal.tsx
@@ -3,7 +3,6 @@ import InvoiceDetailTable from &#39;@/pages/Invoice/InvoiceVerification/components/I @@ -3,7 +3,6 @@ import InvoiceDetailTable from &#39;@/pages/Invoice/InvoiceVerification/components/I
3 import { 3 import {
4 postServiceConstGetPayeeEnum, 4 postServiceConstGetPayeeEnum,
5 postServiceConstInvoiceType, 5 postServiceConstInvoiceType,
6 - postServiceConstInvoicingType,  
7 postServiceInvoiceGetInvoiceRecord, 6 postServiceInvoiceGetInvoiceRecord,
8 postServiceInvoiceModifyRecord, 7 postServiceInvoiceModifyRecord,
9 } from '@/services'; 8 } from '@/services';
@@ -229,7 +228,7 @@ export default ({ id, setVisible }) =&gt; { @@ -229,7 +228,7 @@ export default ({ id, setVisible }) =&gt; {
229 { required: true, message: 'Please select your country!' }, 228 { required: true, message: 'Please select your country!' },
230 ]} 229 ]}
231 /> 230 />
232 - <ProFormSelect 231 + {/* <ProFormSelect
233 name="invoicingType" 232 name="invoicingType"
234 readonly={readOnly} 233 readonly={readOnly}
235 label="开具类型" 234 label="开具类型"
@@ -245,7 +244,7 @@ export default ({ id, setVisible }) =&gt; { @@ -245,7 +244,7 @@ export default ({ id, setVisible }) =&gt; {
245 rules={[ 244 rules={[
246 { required: true, message: 'Please select your country!' }, 245 { required: true, message: 'Please select your country!' },
247 ]} 246 ]}
248 - /> 247 + /> */}
249 <ProFormList 248 <ProFormList
250 label="订单号" 249 label="订单号"
251 name="orderIdList" 250 name="orderIdList"
src/pages/Invoice/waitProcessRecord/components/ManualInvoiceModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import { PAYEE_OPTIONS } from '@/pages/Order/constant';
  3 +import { postServiceOrderInvoicing } from '@/services';
  4 +import {
  5 + ModalForm,
  6 + ProFormDatePicker,
  7 + ProFormDigit,
  8 + ProFormSelect,
  9 + ProFormText,
  10 +} from '@ant-design/pro-components';
  11 +import { Form, message } from 'antd';
  12 +import { useState } from 'react';
  13 +
  14 +interface ManualInvoiceModalProps {
  15 + record: any;
  16 + onSuccess?: () => void;
  17 +}
  18 +
  19 +const ManualInvoiceModal: React.FC<ManualInvoiceModalProps> = ({
  20 + record,
  21 + onSuccess,
  22 +}) => {
  23 + const [form] = Form.useForm();
  24 + const [visible, setVisible] = useState(false);
  25 +
  26 + // 转换PAYEE_OPTIONS为Select组件需要的格式
  27 + const payeeOptions = Object.entries(PAYEE_OPTIONS).map(([value, label]) => ({
  28 + value,
  29 + label,
  30 + }));
  31 +
  32 + return (
  33 + <ModalForm
  34 + title="手动开票"
  35 + trigger={
  36 + <a
  37 + key="invoice"
  38 + style={{ color: '#1890ff' }}
  39 + onClick={() => setVisible(true)}
  40 + >
  41 + 开票
  42 + </a>
  43 + }
  44 + width={600}
  45 + layout={'horizontal'}
  46 + form={form}
  47 + open={visible}
  48 + onOpenChange={setVisible}
  49 + autoFocusFirstInput
  50 + modalProps={{
  51 + destroyOnClose: true,
  52 + }}
  53 + initialValues={{
  54 + purchaser: record.partyAName,
  55 + payee: record.partyB,
  56 + money: record.price,
  57 + }}
  58 + submitTimeout={2000}
  59 + onFinish={async (values) => {
  60 + try {
  61 + const body = {
  62 + invoiceIdentificationNumber: values.purchaser,
  63 + invoicingTime: values.invoicingTime,
  64 + purchaser: values.purchaser,
  65 + financialReceiptIssuanceTime:
  66 + values.financialReceiptIssuanceTime || values.invoicingTime,
  67 + collectMoneyTime: values.collectMoneyTime || values.invoicingTime,
  68 + invoiceNumber: values.invoiceNumber,
  69 + payee: values.payee,
  70 + money: values.money,
  71 + afterInvoicingStatus: [record.type],
  72 + mainOrderIds: record.mainOrderIds,
  73 + invoiceRecordIds: [record.id],
  74 + };
  75 +
  76 + // 根据现有组件实现,使用data来传递参数
  77 + const res = await postServiceOrderInvoicing({
  78 + data: body,
  79 + });
  80 +
  81 + if (res.result === RESPONSE_CODE.SUCCESS) {
  82 + message.success('开票成功');
  83 + if (onSuccess) {
  84 + onSuccess();
  85 + }
  86 + return true;
  87 + } else {
  88 + message.error('开票失败');
  89 + return false;
  90 + }
  91 + } catch (error) {
  92 + message.error('操作失败');
  93 + return false;
  94 + }
  95 + }}
  96 + >
  97 + <ProFormText
  98 + width="md"
  99 + name="purchaser"
  100 + label="抬头名称"
  101 + rules={[{ required: true, message: '请输入抬头名称' }]}
  102 + disabled
  103 + />
  104 +
  105 + <ProFormText
  106 + width="md"
  107 + name="invoiceType"
  108 + label="发票类型"
  109 + initialValue="普票"
  110 + disabled
  111 + />
  112 +
  113 + <ProFormDigit
  114 + width="md"
  115 + name="money"
  116 + label="发票金额"
  117 + fieldProps={{
  118 + precision: 2,
  119 + prefix: '¥',
  120 + }}
  121 + rules={[{ required: true, message: '请输入发票金额' }]}
  122 + disabled
  123 + />
  124 +
  125 + <ProFormSelect
  126 + width="md"
  127 + name="payee"
  128 + label="收款单位"
  129 + options={payeeOptions}
  130 + rules={[{ required: true, message: '请选择收款单位' }]}
  131 + disabled
  132 + />
  133 +
  134 + <ProFormText
  135 + width="md"
  136 + name="invoiceNumber"
  137 + label="发票号码"
  138 + rules={[{ required: true, message: '请输入发票号码' }]}
  139 + />
  140 +
  141 + <ProFormDatePicker
  142 + width="md"
  143 + name="invoicingTime"
  144 + label="开票时间"
  145 + rules={[{ required: true, message: '请选择开票时间' }]}
  146 + fieldProps={{
  147 + format: 'YYYY-MM-DD',
  148 + }}
  149 + />
  150 + </ModalForm>
  151 + );
  152 +};
  153 +
  154 +export default ManualInvoiceModal;
src/pages/Invoice/waitProcessRecord/index.tsx
@@ -2,6 +2,7 @@ import { RESPONSE_CODE } from &#39;@/constants/enum&#39;; @@ -2,6 +2,7 @@ import { RESPONSE_CODE } from &#39;@/constants/enum&#39;;
2 import InvoiceRecordDetailModal from '@/pages/Invoice/InvoiceRecord/components/InvoiceRecordDetailModal'; 2 import InvoiceRecordDetailModal from '@/pages/Invoice/InvoiceRecord/components/InvoiceRecordDetailModal';
3 import InvoiceModal from '@/pages/Invoice/waitProcessRecord/components/InvoiceModal'; 3 import InvoiceModal from '@/pages/Invoice/waitProcessRecord/components/InvoiceModal';
4 import InvoicingModal from '@/pages/Invoice/waitProcessRecord/components/InvoicingModal'; 4 import InvoicingModal from '@/pages/Invoice/waitProcessRecord/components/InvoicingModal';
  5 +import ManualInvoiceModal from '@/pages/Invoice/waitProcessRecord/components/ManualInvoiceModal';
5 import ManualInvoicingModal from '@/pages/Invoice/waitProcessRecord/components/ManualInvoicingModal'; 6 import ManualInvoicingModal from '@/pages/Invoice/waitProcessRecord/components/ManualInvoicingModal';
6 import { PAYEE_OPTIONS } from '@/pages/Order/constant'; 7 import { PAYEE_OPTIONS } from '@/pages/Order/constant';
7 import { 8 import {
@@ -20,6 +21,7 @@ import { @@ -20,6 +21,7 @@ import {
20 Popconfirm, 21 Popconfirm,
21 Space, 22 Space,
22 Table, 23 Table,
  24 + Tabs,
23 Tooltip, 25 Tooltip,
24 message, 26 message,
25 } from 'antd'; 27 } from 'antd';
@@ -27,12 +29,15 @@ import { useEffect, useRef, useState } from &#39;react&#39;; @@ -27,12 +29,15 @@ import { useEffect, useRef, useState } from &#39;react&#39;;
27 29
28 const InvoiceRecord = () => { 30 const InvoiceRecord = () => {
29 const waitDealrecordActionRef = useRef<ActionType>(); 31 const waitDealrecordActionRef = useRef<ActionType>();
  32 + const manualInvoiceActionRef = useRef<ActionType>();
30 const [invoiceTypeValueEnum, setInvoiceTypeValueEnum] = useState({}); 33 const [invoiceTypeValueEnum, setInvoiceTypeValueEnum] = useState({});
31 const [invoicingTypeValueEnum, setInvoicingTypeValueEnum] = useState({}); 34 const [invoicingTypeValueEnum, setInvoicingTypeValueEnum] = useState({});
32 const [salesCodeValueEnum, setSalesCodeValueEnum] = useState({}); 35 const [salesCodeValueEnum, setSalesCodeValueEnum] = useState({});
33 const [invoiceRecordDetailVisible, setInvoiceRecordDetailVisible] = 36 const [invoiceRecordDetailVisible, setInvoiceRecordDetailVisible] =
34 useState(false); 37 useState(false);
35 const [invoiceRecord, setInvoiceRecord] = useState({}); 38 const [invoiceRecord, setInvoiceRecord] = useState({});
  39 + const [activeTab, setActiveTab] = useState('auto');
  40 +
36 useEffect(() => { 41 useEffect(() => {
37 async function extracted() { 42 async function extracted() {
38 let invoiceTypeRet = await postServiceConstInvoiceType(); 43 let invoiceTypeRet = await postServiceConstInvoiceType();
@@ -65,7 +70,11 @@ const InvoiceRecord = () =&gt; { @@ -65,7 +70,11 @@ const InvoiceRecord = () =&gt; {
65 }, []); 70 }, []);
66 71
67 const reloadRecordTable = () => { 72 const reloadRecordTable = () => {
68 - waitDealrecordActionRef.current?.reload(); 73 + if (activeTab === 'auto') {
  74 + waitDealrecordActionRef.current?.reload();
  75 + } else {
  76 + manualInvoiceActionRef.current?.reload();
  77 + }
69 }; 78 };
70 79
71 const waitDealRecordColumns = [ 80 const waitDealRecordColumns = [
@@ -287,11 +296,11 @@ const InvoiceRecord = () =&gt; { @@ -287,11 +296,11 @@ const InvoiceRecord = () =&gt; {
287 valueEnum: { 296 valueEnum: {
288 true: { 297 true: {
289 text: '是', 298 text: '是',
290 - status: true, 299 + status: 'true',
291 }, 300 },
292 false: { 301 false: {
293 text: '否', 302 text: '否',
294 - status: false, 303 + status: 'false',
295 }, 304 },
296 }, 305 },
297 }, 306 },
@@ -319,15 +328,6 @@ const InvoiceRecord = () =&gt; { @@ -319,15 +328,6 @@ const InvoiceRecord = () =&gt; {
319 width: 200, 328 width: 200,
320 render: (text, record) => { 329 render: (text, record) => {
321 return [ 330 return [
322 - /*<InvoiceRecordDetailModal  
323 - key="detail"  
324 - id={record.id}  
325 - subOrderIds={record.subOrderIds}  
326 - onClose={()=>{  
327 - waitDealrecordActionRef.current?.reload();  
328 - }  
329 - }  
330 - />*/  
331 <> 331 <>
332 {record.paths.includes('DETAIL') && ( 332 {record.paths.includes('DETAIL') && (
333 <a 333 <a
@@ -368,7 +368,7 @@ const InvoiceRecord = () =&gt; { @@ -368,7 +368,7 @@ const InvoiceRecord = () =&gt; {
368 if (res.result === RESPONSE_CODE.SUCCESS) { 368 if (res.result === RESPONSE_CODE.SUCCESS) {
369 message.success('取消成功'); 369 message.success('取消成功');
370 } 370 }
371 - waitDealrecordActionRef?.current?.reload(); 371 + reloadRecordTable();
372 }} 372 }}
373 okText="确定" 373 okText="确定"
374 cancelText="取消" 374 cancelText="取消"
@@ -383,74 +383,327 @@ const InvoiceRecord = () =&gt; { @@ -383,74 +383,327 @@ const InvoiceRecord = () =&gt; {
383 }, 383 },
384 }, 384 },
385 ]; 385 ];
386 - return (  
387 - <div className="invoice-index">  
388 - <ProTable  
389 - columns={waitDealRecordColumns}  
390 - actionRef={waitDealrecordActionRef}  
391 - cardBordered  
392 - pagination={{  
393 - showSizeChanger: true, // 显示可以选择每页显示条数的下拉菜单  
394 - pageSizeOptions: ['10', '20', '50', '100'], // 设置可以选择的每页显示条数选项  
395 - }}  
396 - rowSelection={{  
397 - selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],  
398 - alwaysShowAlert: true,  
399 - }}  
400 - tableAlertOptionRender={({ selectedRowKeys, selectedRows }) => {  
401 - console.log(selectedRows);  
402 - console.log(selectedRowKeys);  
403 - return (  
404 - <Space size={16}>  
405 - <InvoicingModal  
406 - reloadRecordTable={reloadRecordTable}  
407 - key="button"  
408 - selectedRowKeys={selectedRowKeys}  
409 - />  
410 - </Space>  
411 - );  
412 - }}  
413 - request={async (params) => {  
414 - let res = await postServiceInvoiceQueryInvoiceRecordList({  
415 - data: {  
416 - ...params,  
417 - statusIn: [  
418 - 'WAITING_FOR_INVOICING',  
419 - 'AUDITING',  
420 - 'AUDITING_NOT_PASSED',  
421 - ],  
422 - needBuildDetails: true,  
423 - needBuildSubOrders: true,  
424 - }, 386 +
  387 + // 手动开票表格列配置
  388 + const manualInvoiceColumns = [
  389 + {
  390 + dataIndex: 'index',
  391 + valueType: 'indexBorder',
  392 + hideInSearch: true,
  393 + ellipsis: true,
  394 + width: 48,
  395 + },
  396 + {
  397 + title: '开票编号',
  398 + valueType: 'text',
  399 + dataIndex: 'id',
  400 + copyable: true,
  401 + hideInSearch: true,
  402 + ellipsis: true,
  403 + width: 100,
  404 + },
  405 + {
  406 + title: '订单号',
  407 + valueType: 'text',
  408 + dataIndex: 'mainOrderIds',
  409 + hideInSearch: true,
  410 + ellipsis: true,
  411 + width: 150,
  412 + },
  413 + {
  414 + title: '开票金额',
  415 + valueType: 'money',
  416 + dataIndex: 'price',
  417 + width: 100,
  418 + hideInSearch: true,
  419 + ellipsis: true,
  420 + },
  421 + {
  422 + title: '购方名称',
  423 + valueType: 'text',
  424 + dataIndex: 'partyAName',
  425 + width: 150,
  426 + hideInSearch: true,
  427 + ellipsis: true,
  428 + },
  429 + {
  430 + title: '收款单位',
  431 + valueType: 'text',
  432 + hideInSearch: true,
  433 + width: 150,
  434 + dataIndex: 'partyBName',
  435 + ellipsis: true,
  436 + },
  437 + {
  438 + title: '开票类型',
  439 + valueType: 'Text',
  440 + dataIndex: 'typeText',
  441 + width: 100,
  442 + hideInSearch: true,
  443 + ellipsis: true,
  444 + },
  445 + {
  446 + title: '是否加急',
  447 + valueType: 'Text',
  448 + dataIndex: 'isUrgentText',
  449 + width: 80,
  450 + hideInSearch: true,
  451 + ellipsis: true,
  452 + },
  453 + {
  454 + title: '附件',
  455 + key: 'filePaths',
  456 + ellipsis: true,
  457 + width: 100,
  458 + hideInSearch: true,
  459 + render: (_, record) => {
  460 + if (record.filePaths && record.filePaths.length > 0) {
  461 + return record.filePaths.map((item) => {
  462 + const url = item;
  463 + const filenameMatch = url.match(/\/([^/]+)\?/);
  464 + const filename = filenameMatch ? filenameMatch[1] : 'file';
  465 +
  466 + const decodedFilename = decodeURIComponent(filename);
  467 +
  468 + const cleanFilename = decodedFilename.replace(/^\d+-\d+-/, '');
  469 +
  470 + return (
  471 + <div style={{ marginBottom: '5px' }} key={url}>
  472 + <a
  473 + href={url}
  474 + rel="noopener noreferrer"
  475 + download={cleanFilename}
  476 + >
  477 + {cleanFilename}
  478 + </a>
  479 + </div>
  480 + );
425 }); 481 });
426 - return {  
427 - data: res?.data?.data,  
428 - total: res?.data?.total || 0,  
429 - };  
430 - }}  
431 - columnsState={{  
432 - persistenceKey: 'pro-table-singe-demos',  
433 - persistenceType: 'localStorage',  
434 - defaultValue: {  
435 - option: { fixed: 'right', disable: true }, 482 + }
  483 + return '-';
  484 + },
  485 + },
  486 + {
  487 + title: '申请时间',
  488 + dataIndex: 'createTime',
  489 + valueType: 'dateTime',
  490 + width: 160,
  491 + hideInSearch: true,
  492 + ellipsis: true,
  493 + },
  494 + {
  495 + title: '申请人',
  496 + valueType: 'text',
  497 + hideInSearch: false,
  498 + ellipsis: true,
  499 + width: 100,
  500 + dataIndex: 'createByName',
  501 + },
  502 + {
  503 + title: '操作',
  504 + valueType: 'option',
  505 + key: 'option',
  506 + width: 120,
  507 + render: (_, record) => {
  508 + return [
  509 + <ManualInvoiceModal
  510 + key="invoice"
  511 + record={record}
  512 + onSuccess={() => reloadRecordTable()}
  513 + />,
  514 + <Popconfirm
  515 + key="cancel"
  516 + title="取消开票"
  517 + description="确认取消开票?"
  518 + onConfirm={async () => {
  519 + let res = await postServiceInvoiceCancelInvoiceRecord({
  520 + data: {
  521 + invoiceRecordIds: [record.id],
  522 + },
  523 + });
  524 + if (res.result === RESPONSE_CODE.SUCCESS) {
  525 + message.success('取消成功');
  526 + }
  527 + reloadRecordTable();
  528 + }}
  529 + okText="确定"
  530 + cancelText="取消"
  531 + >
  532 + <a key="cancel" style={{ color: '#ff4d4f' }}>
  533 + 取消
  534 + </a>
  535 + </Popconfirm>,
  536 + ];
  537 + },
  538 + },
  539 + // 搜索项
  540 + {
  541 + title: '订单号',
  542 + valueType: 'Text',
  543 + dataIndex: 'mainOrderIds',
  544 + hideInTable: true,
  545 + },
  546 + {
  547 + title: '购方名称',
  548 + valueType: 'Text',
  549 + dataIndex: 'partyANameLike',
  550 + hideInTable: true,
  551 + },
  552 + {
  553 + title: '收款单位',
  554 + valueType: 'select',
  555 + dataIndex: 'partyB',
  556 + filters: true,
  557 + onFilter: true,
  558 + hideInTable: true,
  559 + valueEnum: enumToProTableEnumValue(PAYEE_OPTIONS),
  560 + },
  561 + {
  562 + title: '发票类型',
  563 + valueType: 'select',
  564 + dataIndex: 'type',
  565 + filters: true,
  566 + onFilter: true,
  567 + hideInTable: true,
  568 + valueEnum: enumToProTableEnumValue(invoiceTypeValueEnum),
  569 + },
  570 + {
  571 + title: '是否加急',
  572 + valueType: 'select',
  573 + dataIndex: 'isUrgent',
  574 + filters: true,
  575 + onFilter: true,
  576 + hideInTable: true,
  577 + valueEnum: {
  578 + true: {
  579 + text: '是',
  580 + status: 'true',
  581 + },
  582 + false: {
  583 + text: '否',
  584 + status: 'false',
  585 + },
  586 + },
  587 + },
  588 + {
  589 + title: '申请时间',
  590 + dataIndex: 'createTime',
  591 + valueType: 'dateTimeRange',
  592 + width: 200,
  593 + hideInTable: true,
  594 + search: {
  595 + transform: (value) => {
  596 + if (value) {
  597 + return {
  598 + createTimeGe: value[0],
  599 + createTimeLe: value[1],
  600 + };
  601 + }
  602 + },
  603 + },
  604 + },
  605 + ];
  606 +
  607 + const renderProTable = (isManual) => {
  608 + const tableProps = {
  609 + columns: isManual ? manualInvoiceColumns : waitDealRecordColumns,
  610 + actionRef: isManual ? manualInvoiceActionRef : waitDealrecordActionRef,
  611 + cardBordered: true,
  612 + pagination: {
  613 + showSizeChanger: true, // 显示可以选择每页显示条数的下拉菜单
  614 + pageSizeOptions: ['10', '20', '50', '100'], // 设置可以选择的每页显示条数选项
  615 + },
  616 + request: async (params) => {
  617 + let res = await postServiceInvoiceQueryInvoiceRecordList({
  618 + data: {
  619 + ...params,
  620 + isManual: isManual,
  621 + statusIn: [
  622 + 'WAITING_FOR_INVOICING',
  623 + 'AUDITING',
  624 + 'AUDITING_NOT_PASSED',
  625 + ],
  626 + needBuildDetails: true,
  627 + needBuildSubOrders: true,
436 }, 628 },
437 - onChange(value) {  
438 - console.log('value: ', value); 629 + });
  630 + return {
  631 + data: res?.data?.data,
  632 + total: res?.data?.total || 0,
  633 + };
  634 + },
  635 + columnsState: {
  636 + persistenceKey: isManual
  637 + ? 'manual-invoice-table'
  638 + : 'auto-invoice-table',
  639 + persistenceType: 'localStorage',
  640 + defaultValue: {
  641 + option: { fixed: 'right', disable: true },
  642 + },
  643 + onChange(value) {
  644 + console.log('value: ', value);
  645 + },
  646 + },
  647 + rowKey: 'id',
  648 + search: {
  649 + labelWidth: 'auto',
  650 + },
  651 + options: {
  652 + setting: {
  653 + listsHeight: 400,
  654 + },
  655 + },
  656 + form: {},
  657 + dateFormatter: 'string',
  658 + headerTitle: isManual ? '手动开票列表' : '自动开票列表',
  659 + scroll: { x: 2000, y: 500 },
  660 + };
  661 +
  662 + // 如果不是手动开票,添加多选功能
  663 + if (!isManual) {
  664 + tableProps.rowSelection = {
  665 + selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
  666 + alwaysShowAlert: true,
  667 + };
  668 +
  669 + tableProps.tableAlertOptionRender = ({
  670 + selectedRowKeys,
  671 + selectedRows,
  672 + }) => {
  673 + console.log(selectedRows);
  674 + console.log(selectedRowKeys);
  675 + return (
  676 + <Space size={16}>
  677 + <InvoicingModal
  678 + reloadRecordTable={reloadRecordTable}
  679 + key="button"
  680 + selectedRowKeys={selectedRowKeys}
  681 + />
  682 + </Space>
  683 + );
  684 + };
  685 + }
  686 +
  687 + return <ProTable {...tableProps} />;
  688 + };
  689 +
  690 + return (
  691 + <div className="invoice-index">
  692 + <Tabs
  693 + activeKey={activeTab}
  694 + onChange={(key) => setActiveTab(key)}
  695 + items={[
  696 + {
  697 + key: 'auto',
  698 + label: '自动开票',
  699 + children: renderProTable(false),
439 }, 700 },
440 - }}  
441 - rowKey="id"  
442 - search={{  
443 - labelWidth: 'auto',  
444 - }}  
445 - options={{  
446 - setting: {  
447 - listsHeight: 400, 701 + {
  702 + key: 'manual',
  703 + label: '手动开票',
  704 + children: renderProTable(true),
448 }, 705 },
449 - }}  
450 - form={{}}  
451 - dateFormatter="string"  
452 - headerTitle="待开票列表"  
453 - scroll={{ x: 2000, y: 500 }} 706 + ]}
454 /> 707 />
455 {invoiceRecordDetailVisible ? ( 708 {invoiceRecordDetailVisible ? (
456 <InvoiceRecordDetailModal 709 <InvoiceRecordDetailModal
@@ -458,7 +711,7 @@ const InvoiceRecord = () =&gt; { @@ -458,7 +711,7 @@ const InvoiceRecord = () =&gt; {
458 id={invoiceRecord.id} 711 id={invoiceRecord.id}
459 setVisible={setInvoiceRecordDetailVisible} 712 setVisible={setInvoiceRecordDetailVisible}
460 reloadTable={() => { 713 reloadTable={() => {
461 - waitDealrecordActionRef?.current?.reload(); 714 + reloadRecordTable();
462 }} 715 }}
463 /> 716 />
464 ) : ( 717 ) : (
src/pages/Order/FeedBack/InvoicingDrawerForm.tsx
@@ -4,7 +4,6 @@ import { @@ -4,7 +4,6 @@ import {
4 postServiceConstGetPayeeEnum, 4 postServiceConstGetPayeeEnum,
5 postServiceConstInitInvoiceDetailNames, 5 postServiceConstInitInvoiceDetailNames,
6 postServiceConstInvoiceType, 6 postServiceConstInvoiceType,
7 - postServiceConstInvoicingType,  
8 postServiceConstListInvoiceDetailNames, 7 postServiceConstListInvoiceDetailNames,
9 postServiceInvoiceApplyInvoice, 8 postServiceInvoiceApplyInvoice,
10 postServiceInvoiceQueryCompanyInfo, 9 postServiceInvoiceQueryCompanyInfo,
@@ -298,7 +297,7 @@ export default ({ dataList, setVisible, mainOrder, onClose }) =&gt; { @@ -298,7 +297,7 @@ export default ({ dataList, setVisible, mainOrder, onClose }) =&gt; {
298 label="联系人" 297 label="联系人"
299 rules={[{ required: true, message: '请选择银行联行号!' }]} 298 rules={[{ required: true, message: '请选择银行联行号!' }]}
300 /> 299 />
301 - <ProFormSelect 300 + {/* <ProFormSelect
302 name="invoicingType" 301 name="invoicingType"
303 label="开具类型" 302 label="开具类型"
304 request={async () => { 303 request={async () => {
@@ -308,7 +307,7 @@ export default ({ dataList, setVisible, mainOrder, onClose }) =&gt; { @@ -308,7 +307,7 @@ export default ({ dataList, setVisible, mainOrder, onClose }) =&gt; {
308 }} 307 }}
309 placeholder="请选择开具类型" 308 placeholder="请选择开具类型"
310 rules={[{ required: true, message: '请选择开具类型!' }]} 309 rules={[{ required: true, message: '请选择开具类型!' }]}
311 - /> 310 + /> */}
312 <ProFormSelect 311 <ProFormSelect
313 name="type" 312 name="type"
314 label="开票类型" 313 label="开票类型"
src/pages/Order/FeedBack/OrderDrawer.tsx
@@ -1492,7 +1492,19 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1492,7 +1492,19 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1492 onChange={(val: any) => { 1492 onChange={(val: any) => {
1493 setPaymentMethod(val); 1493 setPaymentMethod(val);
1494 }} 1494 }}
1495 - options={enumToSelect(PAYMENT_METHOD_OPTIONS)} 1495 + options={(() => {
  1496 + // 使用Set记录已经处理过的选项值,避免重复
  1497 + const processedValues = new Set();
  1498 + const finalOptions = [];
  1499 +
  1500 + // 处理可选项
  1501 + enumToSelect(PAYMENT_METHOD_OPTIONS).forEach((option) => {
  1502 + finalOptions.push(option);
  1503 + processedValues.add(option.value);
  1504 + });
  1505 +
  1506 + return finalOptions;
  1507 + })()}
1496 rules={[{ required: true, message: '支付方式必填' }]} 1508 rules={[{ required: true, message: '支付方式必填' }]}
1497 disabled={optType('after-sales-check')} 1509 disabled={optType('after-sales-check')}
1498 /> 1510 />
src/pages/Order/FeedBack/constant.ts
@@ -24,9 +24,10 @@ export const RECEIPTS_RECORD_TYPES = { @@ -24,9 +24,10 @@ export const RECEIPTS_RECORD_TYPES = {
24 export const PAYMENT_METHOD_OPTIONS = { 24 export const PAYMENT_METHOD_OPTIONS = {
25 UNPAID: '未付款', 25 UNPAID: '未付款',
26 TAOBAO_ORDER_HAS_BEEN_PAID: '淘宝订单已付款', 26 TAOBAO_ORDER_HAS_BEEN_PAID: '淘宝订单已付款',
27 - OFFICIAL_WEBSITE_ORDER_HAS_BEEN_PAID: '官网订单已付款',  
28 - PAYMENT_IN_ADVANCE: '预付款',  
29 - WITHHOLDING_ADVANCE_DEPOSIT: '扣预存', 27 + OFFICIAL_WEBSITE_ORDER_HAS_BEEN_PAID: '官网已付',
  28 + PAYMENT_IN_ADVANCE: '预付',
  29 + PAYMENT_IN_TAOBAO: '淘宝',
  30 + WITHHOLDING_ADVANCE_DEPOSIT: '预付',
30 PLATFORM_SETTLEMENT: '平台结算', 31 PLATFORM_SETTLEMENT: '平台结算',
31 CASH_ON_DELIVERY: '货到付款', 32 CASH_ON_DELIVERY: '货到付款',
32 HIRE_PURCHASE: '分期付款', 33 HIRE_PURCHASE: '分期付款',
@@ -250,12 +251,8 @@ export const FINANCIAL_STATUS_OPTIONS = { @@ -250,12 +251,8 @@ export const FINANCIAL_STATUS_OPTIONS = {
250 export const AFTER_INVOICING_STATUS = { 251 export const AFTER_INVOICING_STATUS = {
251 NOT_YET_INVOICED: '尚未开票', 252 NOT_YET_INVOICED: '尚未开票',
252 APPLY_FOR_INVOICING: '申请开票', 253 APPLY_FOR_INVOICING: '申请开票',
253 - URGENT_INVOICE_AUDITING: '加急待审核',  
254 - URGENT_INVOICE_AUDIT_NOTPASS: '加急审核失败',  
255 PARTIAL_INVOICING: '部分开票', 254 PARTIAL_INVOICING: '部分开票',
256 COMPLETE_INVOICING: '完全开票', 255 COMPLETE_INVOICING: '完全开票',
257 - INVOICING: '开票中',  
258 - REISSUE: '重新开票',  
259 }; 256 };
260 257
261 export const TAGS_COLOR = new Map<string, string>([ 258 export const TAGS_COLOR = new Map<string, string>([
src/pages/Order/Order/components/InvoicingDrawerForm.tsx
@@ -4,7 +4,6 @@ import { @@ -4,7 +4,6 @@ import {
4 postServiceConstGetPayeeEnum, 4 postServiceConstGetPayeeEnum,
5 postServiceConstInitInvoiceDetailNames, 5 postServiceConstInitInvoiceDetailNames,
6 postServiceConstInvoiceType, 6 postServiceConstInvoiceType,
7 - postServiceConstInvoicingType,  
8 postServiceConstListInvoiceDetailNames, 7 postServiceConstListInvoiceDetailNames,
9 postServiceInvoiceApplyInvoice, 8 postServiceInvoiceApplyInvoice,
10 postServiceInvoiceQueryCompanyInfo, 9 postServiceInvoiceQueryCompanyInfo,
@@ -326,7 +325,7 @@ export default ({ @@ -326,7 +325,7 @@ export default ({
326 label="联系人" 325 label="联系人"
327 rules={[{ required: true, message: '请选择银行联行号!' }]} 326 rules={[{ required: true, message: '请选择银行联行号!' }]}
328 /> 327 />
329 - <ProFormSelect 328 + {/* <ProFormSelect
330 name="invoicingType" 329 name="invoicingType"
331 label="开具类型" 330 label="开具类型"
332 request={async () => { 331 request={async () => {
@@ -336,7 +335,7 @@ export default ({ @@ -336,7 +335,7 @@ export default ({
336 }} 335 }}
337 placeholder="请选择开具类型" 336 placeholder="请选择开具类型"
338 rules={[{ required: true, message: '请选择开具类型!' }]} 337 rules={[{ required: true, message: '请选择开具类型!' }]}
339 - /> 338 + /> */}
340 <ProFormSelect 339 <ProFormSelect
341 name="type" 340 name="type"
342 label="开票类型" 341 label="开票类型"
src/pages/Order/Order/components/OrderDrawer.tsx
@@ -1501,7 +1501,19 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1501,7 +1501,19 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1501 onChange={(val: any) => { 1501 onChange={(val: any) => {
1502 setPaymentMethod(val); 1502 setPaymentMethod(val);
1503 }} 1503 }}
1504 - options={enumToSelect(PAYMENT_METHOD_OPTIONS)} 1504 + options={(() => {
  1505 + // 使用Set记录已经处理过的选项值,避免重复
  1506 + const processedValues = new Set();
  1507 + const finalOptions = [];
  1508 +
  1509 + // 处理可选项
  1510 + enumToSelect(PAYMENT_METHOD_OPTIONS).forEach((option) => {
  1511 + finalOptions.push(option);
  1512 + processedValues.add(option.value);
  1513 + });
  1514 +
  1515 + return finalOptions;
  1516 + })()}
1505 rules={[{ required: true, message: '支付方式必填' }]} 1517 rules={[{ required: true, message: '支付方式必填' }]}
1506 disabled={optType('after-sales-check')} 1518 disabled={optType('after-sales-check')}
1507 /> 1519 />
src/pages/Order/Order/index.tsx
@@ -120,7 +120,7 @@ const OrderPage = () =&gt; { @@ -120,7 +120,7 @@ const OrderPage = () =&gt; {
120 <div className="order-page-container"> 120 <div className="order-page-container">
121 <div id="resizeDiv"></div> 121 <div id="resizeDiv"></div>
122 <div id="resizeDiv"></div> 122 <div id="resizeDiv"></div>
123 - {roleCode === 'SALES_MANAGER' && ( 123 + {roleCode !== 'SALES_MANAGER' && (
124 <Modal 124 <Modal
125 title="订单预警提醒" 125 title="订单预警提醒"
126 open={open} 126 open={open}
@@ -135,6 +135,11 @@ const OrderPage = () =&gt; { @@ -135,6 +135,11 @@ const OrderPage = () =&gt; {
135 > 135 >
136 去处理 136 去处理
137 </Button>, 137 </Button>,
  138 + roleCode === 'ADMIN' && (
  139 + <Button key="cancel" size="large" onClick={() => setOpen(false)}>
  140 + 取消
  141 + </Button>
  142 + ),
138 ]} 143 ]}
139 > 144 >
140 <ProCard 145 <ProCard
src/pages/Order/OrderList/ApplyForInvoicingModal.tsx
1 import { RESPONSE_CODE } from '@/constants/enum'; 1 import { RESPONSE_CODE } from '@/constants/enum';
2 -import { postServiceOrderApplyInvoicing } from '@/services';  
3 -import { enumToSelect, getAliYunOSSFileNameFromUrl } from '@/utils'; 2 +import {
  3 + postServiceOrderApplyInvoicing,
  4 + postServiceOrderQueryServiceOrder,
  5 +} from '@/services';
  6 +import { FloatAdd, enumToSelect, getAliYunOSSFileNameFromUrl } from '@/utils';
4 import { 7 import {
5 ModalForm, 8 ModalForm,
  9 + ProFormMoney,
6 ProFormSelect, 10 ProFormSelect,
7 ProFormText, 11 ProFormText,
8 ProFormTextArea, 12 ProFormTextArea,
@@ -11,21 +15,140 @@ import { @@ -11,21 +15,140 @@ import {
11 import { Form, message } from 'antd'; 15 import { Form, message } from 'antd';
12 import { useEffect, useState } from 'react'; 16 import { useEffect, useState } from 'react';
13 import { PAYEE_OPTIONS } from '../constant'; 17 import { PAYEE_OPTIONS } from '../constant';
  18 +
  19 +// 定义选项类型
  20 +interface SelectOption {
  21 + label: string;
  22 + value: string;
  23 +}
  24 +
14 export default ({ 25 export default ({
15 setCheckVisible, 26 setCheckVisible,
16 isEdit, 27 isEdit,
17 subOrders, 28 subOrders,
18 - isMainOrder,  
19 - totalPayment, 29 + mainOrders,
20 onClose, 30 onClose,
  31 +}: {
  32 + setCheckVisible: (val: boolean) => void;
  33 + isEdit?: boolean;
  34 + subOrders: any[];
  35 + mainOrders: any[];
  36 + onClose: () => void;
21 }) => { 37 }) => {
22 const [isUrgent, setIsUrgent] = useState(''); 38 const [isUrgent, setIsUrgent] = useState('');
23 - let sumPrice = totalPayment; 39 + const [receivingCompanyOptions, setReceivingCompanyOptions] = useState<
  40 + SelectOption[]
  41 + >([]);
  42 + const [additionalMainOrders, setAdditionalMainOrders] = useState<any[]>([]);
24 43
25 let ids = subOrders?.map((item) => { 44 let ids = subOrders?.map((item) => {
26 return item.id; 45 return item.id;
27 }); 46 });
28 47
  48 + // 定义返回类型接口
  49 + interface MainOrderData {
  50 + value: string | number;
  51 + totalPayment: number;
  52 + invoiceIssuedAmount: number;
  53 + availableAmount: number;
  54 + }
  55 +
  56 + // 解析输入框内容,识别格式如 "23123,2507310003"
  57 + const parseInputContent = (content: string): string[] => {
  58 + if (!content) return [];
  59 + return content
  60 + .split(',')
  61 + .map((id) => id.trim())
  62 + .filter((id) => id);
  63 + };
  64 +
  65 + // 查询未选择的订单数据
  66 + const queryMissingOrders = async (missingIds: string[]) => {
  67 + try {
  68 + const { data } = await postServiceOrderQueryServiceOrder({
  69 + // @ts-ignore
  70 + data: {
  71 + current: 1,
  72 + pageSize: 10,
  73 + id: missingIds,
  74 + condition: 0,
  75 + sorted: false,
  76 + isDeleteQueryOrder: false,
  77 + },
  78 + });
  79 +
  80 + if (data?.data) {
  81 + setAdditionalMainOrders(data.data);
  82 + }
  83 + } catch (error) {
  84 + console.error('查询订单失败:', error);
  85 + message.error('查询订单数据失败');
  86 + }
  87 + };
  88 +
  89 + // 获取唯一的主订单ID及其相关金额信息
  90 + const getUniqueMainOrderIds = (): MainOrderData[] => {
  91 + console.log(subOrders, mainOrders);
  92 + const mainOrderIds = subOrders?.map((item: any) => item.mainOrderId);
  93 + const uniqueIds = [...new Set(mainOrderIds)].filter(Boolean);
  94 +
  95 + const result = uniqueIds.map((id) => {
  96 + // 获取该主订单的数据
  97 + const mainOrder = mainOrders
  98 + ? mainOrders.find((item: any) => item.id === id)
  99 + : null;
  100 +
  101 + // 获取该主订单下所有子订单
  102 + const orderSubOrders = subOrders.filter(
  103 + (item: any) => item.mainOrderId === id,
  104 + );
  105 +
  106 + // 计算该主订单的总金额
  107 + let totalPayment = mainOrder ? mainOrder.totalPayment : 0;
  108 + if (!totalPayment) {
  109 + orderSubOrders.forEach((item: any) => {
  110 + totalPayment = FloatAdd(totalPayment, item.totalPayment || 0);
  111 + });
  112 + }
  113 +
  114 + // 计算已开票金额(如果有的话)
  115 + let invoiceIssuedAmount = mainOrder
  116 + ? mainOrder.invoiceIssuedAmount || 0
  117 + : 0;
  118 + if (!invoiceIssuedAmount) {
  119 + orderSubOrders.forEach((item: any) => {
  120 + invoiceIssuedAmount = FloatAdd(
  121 + invoiceIssuedAmount,
  122 + item.invoiceIssuedAmount || 0,
  123 + );
  124 + });
  125 + }
  126 +
  127 + // 计算可开票金额
  128 + const availableAmount = Math.max(0, totalPayment - invoiceIssuedAmount);
  129 +
  130 + return {
  131 + value: String(id),
  132 + totalPayment,
  133 + invoiceIssuedAmount,
  134 + availableAmount,
  135 + };
  136 + });
  137 +
  138 + // 添加额外查询到的订单数据
  139 + const additionalOrders = additionalMainOrders.map((order) => ({
  140 + value: String(order.id),
  141 + totalPayment: order.totalPayment || 0,
  142 + invoiceIssuedAmount: order.invoiceIssuedAmount || 0,
  143 + availableAmount: Math.max(
  144 + 0,
  145 + (order.totalPayment || 0) - (order.invoiceIssuedAmount || 0),
  146 + ),
  147 + }));
  148 +
  149 + return [...result, ...additionalOrders];
  150 + };
  151 +
29 let mainIdSet = new Set(); 152 let mainIdSet = new Set();
30 subOrders?.forEach((item: { mainOrderId: unknown }) => { 153 subOrders?.forEach((item: { mainOrderId: unknown }) => {
31 mainIdSet.add(item.mainOrderId); 154 mainIdSet.add(item.mainOrderId);
@@ -58,13 +181,58 @@ export default ({ @@ -58,13 +181,58 @@ export default ({
58 receivingCompany: string; 181 receivingCompany: string;
59 isUrgent: boolean; 182 isUrgent: boolean;
60 deadline: string; 183 deadline: string;
  184 + invoiceType: string; // 新增发票类型字段
61 }>(); 185 }>();
62 186
  187 + // 处理备注内容变化
  188 + const handleNotesChange = async (value: string) => {
  189 + const inputIds = parseInputContent(value);
  190 + const selectedMainOrderIds = Array.from(mainIdSet).map((id) => String(id));
  191 +
  192 + console.log('输入的订单ID:', inputIds);
  193 + console.log('已选择的主订单ID:', selectedMainOrderIds);
  194 +
  195 + // 找出输入框中存在但未选择的订单ID
  196 + const missingIds = inputIds.filter(
  197 + (id) => !selectedMainOrderIds.includes(id),
  198 + );
  199 +
  200 + console.log('缺失的订单ID:', missingIds);
  201 +
  202 + if (missingIds.length > 0) {
  203 + await queryMissingOrders(missingIds);
  204 + } else {
  205 + // 如果没有缺失的订单,清空额外的订单数据
  206 + setAdditionalMainOrders([]);
  207 + }
  208 + };
  209 +
63 useEffect(() => { 210 useEffect(() => {
64 //显示拼接的主订单id 211 //显示拼接的主订单id
65 form.setFieldValue('applyInvoicingNotes', mainIds); 212 form.setFieldValue('applyInvoicingNotes', mainIds);
  213 +
  214 + // 转换收款单位选项并保存
  215 + const options = enumToSelect(PAYEE_OPTIONS);
  216 + setReceivingCompanyOptions(options);
66 }, []); 217 }, []);
67 218
  219 + useEffect(() => {
  220 + // 当额外的主订单数据变化时,设置可开票金额初始值
  221 + const mainOrders = getUniqueMainOrderIds();
  222 + mainOrders.forEach((order) => {
  223 + // 只为新添加的订单设置初始值,避免覆盖用户已输入的值
  224 + const currentValue = form.getFieldValue(
  225 + `invoiceAvailableAmount_${order.value}`,
  226 + );
  227 + if (currentValue === undefined || currentValue === null) {
  228 + form.setFieldValue(
  229 + `invoiceAvailableAmount_${order.value}`,
  230 + order.availableAmount,
  231 + );
  232 + }
  233 + });
  234 + }, [additionalMainOrders]);
  235 +
68 return ( 236 return (
69 <ModalForm<{ 237 <ModalForm<{
70 applyInvoicingNotes: string; 238 applyInvoicingNotes: string;
@@ -93,7 +261,26 @@ export default ({ @@ -93,7 +261,26 @@ export default ({
93 }} 261 }}
94 submitTimeout={2000} 262 submitTimeout={2000}
95 onFinish={async (values) => { 263 onFinish={async (values) => {
96 - values.subIds = ids; 264 + // 收集所有相关的子订单ID,包括额外查询到的主订单下的子订单
  265 + const allSubIds = [...ids]; // 原始选择的子订单ID
  266 +
  267 + console.log('原始子订单ID:', ids);
  268 + console.log('额外查询的主订单:', additionalMainOrders);
  269 +
  270 + // 添加额外查询到的主订单下的子订单ID
  271 + additionalMainOrders.forEach((mainOrder: any) => {
  272 + if (mainOrder.subOrderInformationLists) {
  273 + mainOrder.subOrderInformationLists.forEach((subOrder: any) => {
  274 + if (subOrder.id && !allSubIds.includes(subOrder.id)) {
  275 + console.log('添加子订单ID:', subOrder.id);
  276 + allSubIds.push(subOrder.id);
  277 + }
  278 + });
  279 + }
  280 + });
  281 +
  282 + console.log('最终子订单ID列表:', allSubIds);
  283 + values.subIds = allSubIds;
97 //附件处理 284 //附件处理
98 values.filePaths = values.filePaths?.map((item) => { 285 values.filePaths = values.filePaths?.map((item) => {
99 return { url: item.response.data[0] }; 286 return { url: item.response.data[0] };
@@ -105,7 +292,43 @@ export default ({ @@ -105,7 +292,43 @@ export default ({
105 values.afterInvoicingUpdate = false; 292 values.afterInvoicingUpdate = false;
106 } 293 }
107 294
108 - const res = await postServiceOrderApplyInvoicing({ data: values }); 295 + // 收集主订单可开票金额
  296 + const invoiceOrderAmounts = getUniqueMainOrderIds().map((item) => ({
  297 + orderId: Number(item.value), // 确保为 number 类型
  298 + availableAmount: values[`invoiceAvailableAmount_${item.value}`],
  299 + }));
  300 + // 校验所有主订单可开票金额之和等于price字段
  301 + const price = values.price;
  302 + let sumAvailable = 0;
  303 + invoiceOrderAmounts.forEach((item) => {
  304 + sumAvailable = FloatAdd(sumAvailable, item.availableAmount || 0);
  305 + });
  306 + if (Math.abs(sumAvailable - price) > 0.01) {
  307 + message.error(
  308 + `所有主订单可开票金额之和(${sumAvailable})必须等于开票金额(${price})`,
  309 + );
  310 + return;
  311 + }
  312 +
  313 + // 获取receivingCompany对应的名称
  314 + const selectedOption = receivingCompanyOptions.find(
  315 + (option) => option.value === values.receivingCompany,
  316 + );
  317 + const receivingCompanyName = selectedOption ? selectedOption.label : '';
  318 +
  319 + // 构建包含所有订单的mainOrderIds字符串
  320 + const allMainOrderIds = getUniqueMainOrderIds()
  321 + .map((item) => item.value)
  322 + .join(',');
  323 +
  324 + // 添加到请求数据中
  325 + const reqData = {
  326 + ...values,
  327 + receivingCompanyName, // 添加收款单位名称
  328 + mainOrderIds: allMainOrderIds, // 使用包含所有订单的ID字符串
  329 + invoiceOrderAmounts,
  330 + };
  331 + const res = await postServiceOrderApplyInvoicing({ data: reqData });
109 332
110 if (res.result === RESPONSE_CODE.SUCCESS) { 333 if (res.result === RESPONSE_CODE.SUCCESS) {
111 message.success(res.message); 334 message.success(res.message);
@@ -114,14 +337,86 @@ export default ({ @@ -114,14 +337,86 @@ export default ({
114 }} 337 }}
115 onOpenChange={setCheckVisible} 338 onOpenChange={setCheckVisible}
116 > 339 >
117 - {isMainOrder ? (  
118 - <div className="mb-[24px]">  
119 - <span>选中子订单金额之和:</span>  
120 - <span className="text-red-500">{sumPrice}¥</span> 340 + {/* 主订单金额表格,任何情况都显示 */}
  341 + <div style={{ marginBottom: 24 }}>
  342 + <div
  343 + style={{
  344 + display: 'flex',
  345 + fontWeight: 'bold',
  346 + marginBottom: 8,
  347 + padding: '8px 0',
  348 + borderBottom: '1px solid #f0f0f0',
  349 + }}
  350 + >
  351 + <div style={{ flex: 25 }}>订单号</div>
  352 + <div style={{ flex: 18, textAlign: 'right' }}>订单金额</div>
  353 + <div style={{ flex: 18, textAlign: 'right' }}>已开票金额</div>
  354 + <div style={{ flex: 39, textAlign: 'right' }}>可开票金额</div>
121 </div> 355 </div>
122 - ) : (  
123 - ''  
124 - )} 356 + {getUniqueMainOrderIds().map((item, index) => {
  357 + const maxAvailable = Math.max(
  358 + 0,
  359 + item.totalPayment - item.invoiceIssuedAmount,
  360 + );
  361 +
  362 + // 检查是否是额外查询到的订单
  363 + const isAdditionalOrder = additionalMainOrders.some(
  364 + (order) => String(order.id) === String(item.value),
  365 + );
  366 +
  367 + return (
  368 + <div
  369 + key={index}
  370 + style={{
  371 + display: 'flex',
  372 + marginBottom: 8,
  373 + padding: '8px 0',
  374 + borderBottom: '1px solid #f0f0f0',
  375 + backgroundColor: isAdditionalOrder ? '#f6ffed' : 'transparent', // 浅绿色背景表示新查询的订单
  376 + border: isAdditionalOrder ? '1px solid #b7eb8f' : 'none',
  377 + borderRadius: isAdditionalOrder ? '4px' : '0',
  378 + }}
  379 + >
  380 + <div style={{ flex: 25 }}>
  381 + {item.value}
  382 + {isAdditionalOrder}
  383 + </div>
  384 + <div style={{ flex: 18, textAlign: 'right' }}>
  385 + ¥ {item.totalPayment.toFixed(2)}
  386 + </div>
  387 + <div style={{ flex: 18, textAlign: 'right' }}>
  388 + ¥ {item.invoiceIssuedAmount.toFixed(2)}
  389 + </div>
  390 + <div style={{ flex: 39, textAlign: 'right' }}>
  391 + <ProFormMoney
  392 + name={`invoiceAvailableAmount_${item.value}`}
  393 + locale="zh-CN"
  394 + fieldProps={{
  395 + precision: 2,
  396 + style: { width: '70%' },
  397 + }}
  398 + initialValue={item.availableAmount}
  399 + rules={[
  400 + { required: true, message: '请填写可开票金额!' },
  401 + {
  402 + validator: (_, value) => {
  403 + if (value > maxAvailable) {
  404 + return Promise.reject(
  405 + `可开票金额不能超过${maxAvailable.toFixed(2)}`,
  406 + );
  407 + } else if (value === 0) {
  408 + return Promise.reject(`可开票金额不能为0`);
  409 + }
  410 + return Promise.resolve();
  411 + },
  412 + },
  413 + ]}
  414 + />
  415 + </div>
  416 + </div>
  417 + );
  418 + })}
  419 + </div>
125 420
126 <div className="mb-1"> 421 <div className="mb-1">
127 如果需要合并订单,请将需要合并的订单id写在备注中,id之间用英文逗号隔开。 422 如果需要合并订单,请将需要合并的订单id写在备注中,id之间用英文逗号隔开。
@@ -131,12 +426,9 @@ export default ({ @@ -131,12 +426,9 @@ export default ({
131 name="applyInvoicingNotes" 426 name="applyInvoicingNotes"
132 key="applyInvoicingNotes" 427 key="applyInvoicingNotes"
133 placeholder="请输入备注" 428 placeholder="请输入备注"
134 - onMetaChange={(val) => {  
135 - console.log(val);  
136 - }}  
137 - proFieldProps={{  
138 - onchange: () => {  
139 - message.info('change'); 429 + fieldProps={{
  430 + onChange: (e) => {
  431 + handleNotesChange(e.target.value);
140 }, 432 },
141 }} 433 }}
142 /> 434 />
@@ -161,9 +453,24 @@ export default ({ @@ -161,9 +453,24 @@ export default ({
161 </span> 453 </span>
162 </div> 454 </div>
163 } 455 }
164 - options={enumToSelect(PAYEE_OPTIONS)} 456 + options={receivingCompanyOptions}
165 rules={[{ required: true, message: '开票收款单位必填' }]} 457 rules={[{ required: true, message: '开票收款单位必填' }]}
166 /> 458 />
  459 +
  460 + {/* 新增发票类型选择 */}
  461 + <ProFormSelect
  462 + placeholder="选择发票类型"
  463 + name="invoiceType"
  464 + width="lg"
  465 + key="invoiceType"
  466 + label="发票类型"
  467 + options={[
  468 + { label: '普票', value: 'ORDINARY_TICKET' },
  469 + { label: '专票', value: 'SPECIAL_TICKET' },
  470 + ]}
  471 + rules={[{ required: true, message: '发票类型必填' }]}
  472 + />
  473 +
167 <ProFormSelect 474 <ProFormSelect
168 placeholder="选择是否加急" 475 placeholder="选择是否加急"
169 name="isUrgent" 476 name="isUrgent"
src/pages/Order/OrderList/FinancialMergeDrawer.tsx
@@ -142,7 +142,6 @@ export default ({ dataList, setVisible, onClose }) =&gt; { @@ -142,7 +142,6 @@ export default ({ dataList, setVisible, onClose }) =&gt; {
142 { label: '完全开票', value: 'COMPLETE_INVOICING' }, 142 { label: '完全开票', value: 'COMPLETE_INVOICING' },
143 { label: '部分开票', value: 'PARTIAL_INVOICING' }, 143 { label: '部分开票', value: 'PARTIAL_INVOICING' },
144 ]} 144 ]}
145 - initialValue={'COMPLETE_INVOICING'}  
146 /> 145 />
147 <ProFormTextArea width="lg" name="invoicingNotes" label="备注" /> 146 <ProFormTextArea width="lg" name="invoicingNotes" label="备注" />
148 </DrawerForm> 147 </DrawerForm>
src/pages/Order/OrderList/HirePurchaseUploadPayBillModal.tsx
@@ -22,6 +22,14 @@ interface HirePurchaseUploadPayBillModalProps { @@ -22,6 +22,14 @@ interface HirePurchaseUploadPayBillModalProps {
22 subOrders?: any[]; 22 subOrders?: any[];
23 } 23 }
24 24
  25 +// Helper function to display dash for empty values
  26 +// const displayValue = (value: any, formatter?: (val: any) => string): string => {
  27 +// if (value === null || value === undefined || value === '') {
  28 +// return '-';
  29 +// }
  30 +// return formatter ? formatter(value) : String(value);
  31 +// };
  32 +
25 const HirePurchaseUploadPayBillModal: React.FC< 33 const HirePurchaseUploadPayBillModal: React.FC<
26 HirePurchaseUploadPayBillModalProps 34 HirePurchaseUploadPayBillModalProps
27 > = ({ 35 > = ({
@@ -309,7 +317,12 @@ const HirePurchaseUploadPayBillModal: React.FC&lt; @@ -309,7 +317,12 @@ const HirePurchaseUploadPayBillModal: React.FC&lt;
309 }} 317 }}
310 > 318 >
311 <span>订单总金额:</span> 319 <span>订单总金额:</span>
312 - <span>{totalPayment.toFixed(2)}元</span> 320 + <span>
  321 + {totalPayment !== null && totalPayment !== undefined
  322 + ? totalPayment.toFixed(2)
  323 + : '-'}
  324 + 元
  325 + </span>
313 </div> 326 </div>
314 <div 327 <div
315 style={{ 328 style={{
@@ -319,7 +332,12 @@ const HirePurchaseUploadPayBillModal: React.FC&lt; @@ -319,7 +332,12 @@ const HirePurchaseUploadPayBillModal: React.FC&lt;
319 }} 332 }}
320 > 333 >
321 <span>已回款金额:</span> 334 <span>已回款金额:</span>
322 - <span>{installedMoney.toFixed(2)}元</span> 335 + <span>
  336 + {installedMoney !== null && installedMoney !== undefined
  337 + ? installedMoney.toFixed(2)
  338 + : '-'}
  339 + 元
  340 + </span>
323 </div> 341 </div>
324 <div 342 <div
325 style={{ 343 style={{
@@ -329,7 +347,12 @@ const HirePurchaseUploadPayBillModal: React.FC&lt; @@ -329,7 +347,12 @@ const HirePurchaseUploadPayBillModal: React.FC&lt;
329 }} 347 }}
330 > 348 >
331 <span>待回款金额:</span> 349 <span>待回款金额:</span>
332 - <span>{remainingMoney.toFixed(2)}元</span> 350 + <span>
  351 + {remainingMoney !== null && remainingMoney !== undefined
  352 + ? remainingMoney.toFixed(2)
  353 + : '-'}
  354 + 元
  355 + </span>
333 </div> 356 </div>
334 </div> 357 </div>
335 <Form.Item 358 <Form.Item
src/pages/Order/OrderList/InvoicingDrawerForm.tsx
@@ -4,7 +4,6 @@ import { @@ -4,7 +4,6 @@ import {
4 postServiceConstGetPayeeEnum, 4 postServiceConstGetPayeeEnum,
5 postServiceConstInitInvoiceDetailNames, 5 postServiceConstInitInvoiceDetailNames,
6 postServiceConstInvoiceType, 6 postServiceConstInvoiceType,
7 - postServiceConstInvoicingType,  
8 postServiceConstListInvoiceDetailNames, 7 postServiceConstListInvoiceDetailNames,
9 postServiceInvoiceApplyInvoice, 8 postServiceInvoiceApplyInvoice,
10 postServiceInvoiceQueryCompanyInfo, 9 postServiceInvoiceQueryCompanyInfo,
@@ -16,7 +15,6 @@ import { @@ -16,7 +15,6 @@ import {
16 FormListActionType, 15 FormListActionType,
17 ProCard, 16 ProCard,
18 ProFormDigit, 17 ProFormDigit,
19 - ProFormGroup,  
20 ProFormInstance, 18 ProFormInstance,
21 ProFormList, 19 ProFormList,
22 ProFormMoney, 20 ProFormMoney,
@@ -31,8 +29,16 @@ export default ({ @@ -31,8 +29,16 @@ export default ({
31 dataList, 29 dataList,
32 setVisible, 30 setVisible,
33 mainOrder, 31 mainOrder,
  32 + mainOrders,
34 onClose, 33 onClose,
35 type = 'applyInvoicing', 34 type = 'applyInvoicing',
  35 +}: {
  36 + dataList: any[];
  37 + setVisible: (val: boolean) => void;
  38 + mainOrder: any;
  39 + mainOrders?: any[];
  40 + onClose: () => void;
  41 + type?: string;
36 }) => { 42 }) => {
37 // let subOrderIds = dataList?.map((item) => { 43 // let subOrderIds = dataList?.map((item) => {
38 // return item.id; 44 // return item.id;
@@ -82,6 +88,60 @@ export default ({ @@ -82,6 +88,60 @@ export default ({
82 }); 88 });
83 types.set('reissue', { title: '重新申请', subOrderIdsName: '重开订单' }); 89 types.set('reissue', { title: '重新申请', subOrderIdsName: '重开订单' });
84 90
  91 + // Get unique main order IDs from the dataList
  92 + // 定义返回类型接口
  93 + interface MainOrderData {
  94 + value: string | number;
  95 + totalPayment: number;
  96 + invoiceIssuedAmount: number;
  97 + availableAmount: number;
  98 + }
  99 +
  100 + const getUniqueMainOrderIds = (): MainOrderData[] => {
  101 + // Extract main order IDs from dataList
  102 + const mainOrderIds = dataListCopy.map(
  103 + (item: any) => item.mainOrderId || item.orderId,
  104 + );
  105 + // Get unique IDs
  106 + const uniqueIds = [...new Set(mainOrderIds)].filter(Boolean);
  107 + return uniqueIds.map((id) => {
  108 + // 确保id是string或number类型
  109 + const orderId = String(id);
  110 +
  111 + // 优先从传入的mainOrders中获取数据
  112 + const mainOrderData = mainOrders
  113 + ? mainOrders.find((item: any) => item.id === id)
  114 + : null;
  115 +
  116 + // 如果没有找到主订单数据,则从dataList中查找
  117 + const orderData =
  118 + mainOrderData ||
  119 + dataListCopy.find((d: any) => d.mainOrderId === id || d.orderId === id);
  120 +
  121 + const totalPayment = orderData?.totalPayment || 0;
  122 + const invoiceIssuedAmount = orderData?.invoiceIssuedAmount || 0;
  123 + const availableAmount = Math.max(0, totalPayment - invoiceIssuedAmount);
  124 +
  125 + return {
  126 + value: orderId,
  127 + totalPayment,
  128 + invoiceIssuedAmount,
  129 + availableAmount,
  130 + };
  131 + });
  132 + };
  133 +
  134 + // Set initial values for invoice available amounts
  135 + useEffect(() => {
  136 + const mainOrders = getUniqueMainOrderIds();
  137 + mainOrders.forEach((order) => {
  138 + form.setFieldValue(
  139 + `invoiceAvailableAmount_${order.value}`,
  140 + order.availableAmount,
  141 + );
  142 + });
  143 + }, []);
  144 +
85 function copyToClipboard(text: string) { 145 function copyToClipboard(text: string) {
86 // 创建一个临时的textarea元素 146 // 创建一个临时的textarea元素
87 const textarea = document.createElement('textarea'); 147 const textarea = document.createElement('textarea');
@@ -135,6 +195,8 @@ export default ({ @@ -135,6 +195,8 @@ export default ({
135 autoFocusFirstInput 195 autoFocusFirstInput
136 drawerProps={{ 196 drawerProps={{
137 destroyOnClose: true, 197 destroyOnClose: true,
  198 + maskClosable: false,
  199 + onClose: () => setVisible(false),
138 }} 200 }}
139 submitter={{ 201 submitter={{
140 render: (props, defaultDoms) => { 202 render: (props, defaultDoms) => {
@@ -177,9 +239,31 @@ export default ({ @@ -177,9 +239,31 @@ export default ({
177 }} 239 }}
178 submitTimeout={2000} 240 submitTimeout={2000}
179 onFinish={async (values) => { 241 onFinish={async (values) => {
  242 + // Collect invoice available amounts in the recommended format
  243 + const invoiceOrderAmounts = getUniqueMainOrderIds().map((item) => ({
  244 + orderId: item.value,
  245 + availableAmount: values[`invoiceAvailableAmount_${item.value}`],
  246 + }));
  247 +
  248 + // 获取开票金额(price 字段)
  249 + const price = values.price;
  250 + // 计算所有主订单可开票金额之和
  251 + let sumAvailable = 0;
  252 + invoiceOrderAmounts.forEach((item) => {
  253 + sumAvailable = FloatAdd(sumAvailable, item.availableAmount || 0);
  254 + });
  255 + // 允许0.01误差
  256 + if (Math.abs(sumAvailable - price) > 0.01) {
  257 + message.error(
  258 + `所有主订单可开票金额之和(${sumAvailable})必须等于开票金额(${price})`,
  259 + );
  260 + return;
  261 + }
  262 +
180 postServiceInvoiceApplyInvoice({ 263 postServiceInvoiceApplyInvoice({
181 data: { 264 data: {
182 ...values, 265 ...values,
  266 + invoiceOrderAmounts, // 使用数组对象格式
183 subOrderIds: dataListCopy.map((item) => { 267 subOrderIds: dataListCopy.map((item) => {
184 return item.id; 268 return item.id;
185 }), 269 }),
@@ -192,22 +276,73 @@ export default ({ @@ -192,22 +276,73 @@ export default ({
192 return !val && setVisible(); 276 return !val && setVisible();
193 }} 277 }}
194 > 278 >
195 - <ProFormList  
196 - name="subOrderIdObjs"  
197 - readonly={true}  
198 - label={types.get(type).subOrderIdsName}  
199 - initialValue={dataListCopy.map((item) => {  
200 - return {  
201 - value: item.id,  
202 - }; 279 + <div style={{ marginBottom: 24 }}>
  280 + <div
  281 + style={{
  282 + display: 'flex',
  283 + fontWeight: 'bold',
  284 + marginBottom: 8,
  285 + padding: '8px 0',
  286 + borderBottom: '1px solid #f0f0f0',
  287 + }}
  288 + >
  289 + <div style={{ flex: 25 }}>订单号</div>
  290 + <div style={{ flex: 18, textAlign: 'right' }}>订单金额</div>
  291 + <div style={{ flex: 18, textAlign: 'right' }}>已开票金额</div>
  292 + <div style={{ flex: 39, textAlign: 'right' }}>可开票金额</div>
  293 + </div>
  294 + {getUniqueMainOrderIds().map((item, index) => {
  295 + const maxAvailable = Math.max(
  296 + 0,
  297 + item.totalPayment - item.invoiceIssuedAmount,
  298 + );
  299 + return (
  300 + <div
  301 + key={index}
  302 + style={{
  303 + display: 'flex',
  304 + marginBottom: 8,
  305 + padding: '8px 0',
  306 + borderBottom: '1px solid #f0f0f0',
  307 + }}
  308 + >
  309 + <div style={{ flex: 25 }}>{item.value}</div>
  310 + <div style={{ flex: 18, textAlign: 'right' }}>
  311 + ¥ {item.totalPayment.toFixed(2)}
  312 + </div>
  313 + <div style={{ flex: 18, textAlign: 'right' }}>
  314 + ¥ {item.invoiceIssuedAmount.toFixed(2)}
  315 + </div>
  316 + <div style={{ flex: 39, textAlign: 'right' }}>
  317 + <ProFormMoney
  318 + name={`invoiceAvailableAmount_${item.value}`}
  319 + locale="zh-CN"
  320 + fieldProps={{
  321 + precision: 2,
  322 + style: { width: '70%' },
  323 + }}
  324 + initialValue={item.availableAmount}
  325 + rules={[
  326 + { required: true, message: '请填写可开票金额!' },
  327 + {
  328 + validator: (_, value) => {
  329 + if (value > maxAvailable) {
  330 + return Promise.reject(
  331 + `可开票金额不能超过${maxAvailable.toFixed(2)}`,
  332 + );
  333 + } else if (value === 0) {
  334 + return Promise.reject(`可开票金额不能为0`);
  335 + }
  336 + return Promise.resolve();
  337 + },
  338 + },
  339 + ]}
  340 + />
  341 + </div>
  342 + </div>
  343 + );
203 })} 344 })}
204 - deleteIconProps={false}  
205 - copyIconProps={false}  
206 - >  
207 - <ProFormGroup key="group">  
208 - <ProFormText readonly={true} name="value" label="" />  
209 - </ProFormGroup>  
210 - </ProFormList> 345 + </div>
211 {/*<ProFormSelect 346 {/*<ProFormSelect
212 name="ReissueInvoiceRecordIds" 347 name="ReissueInvoiceRecordIds"
213 label="重开的发票" 348 label="重开的发票"
@@ -320,17 +455,6 @@ export default ({ @@ -320,17 +455,6 @@ export default ({
320 rules={[{ required: true, message: '请选择银行联行号!' }]} 455 rules={[{ required: true, message: '请选择银行联行号!' }]}
321 /> 456 />
322 <ProFormSelect 457 <ProFormSelect
323 - name="invoicingType"  
324 - label="开具类型"  
325 - request={async () => {  
326 - let invoicingTypeRet = await postServiceConstInvoicingType();  
327 - let options = enumToSelect(invoicingTypeRet.data);  
328 - return options;  
329 - }}  
330 - placeholder="请选择开具类型"  
331 - rules={[{ required: true, message: '请选择开具类型!' }]}  
332 - />  
333 - <ProFormSelect  
334 name="type" 458 name="type"
335 label="开票类型" 459 label="开票类型"
336 placeholder="请选择开票类型" 460 placeholder="请选择开票类型"
src/pages/Order/OrderList/OrderDrawer.tsx
@@ -156,7 +156,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -156,7 +156,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
156 let entity_number = await getTeacherCustomFieldNumber(); 156 let entity_number = await getTeacherCustomFieldNumber();
157 157
158 //在单位详细信息中拿到自定义字段的值 158 //在单位详细信息中拿到自定义字段的值
159 - let customField = res?.custom_field; 159 + let customField = res?.customField;
160 if (customField) { 160 if (customField) {
161 let teacherName = customField[entity_number]; 161 let teacherName = customField[entity_number];
162 //填充到课题组老师表单字段中 162 //填充到课题组老师表单字段中
@@ -309,22 +309,22 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -309,22 +309,22 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
309 309
310 copyData.customerNameString = copyData.customerName; 310 copyData.customerNameString = copyData.customerName;
311 311
312 - // 清空支付方式和支付渠道  
313 - if (  
314 - copyData.paymentChannel === 'TAOBAO' ||  
315 - [  
316 - 'UNPAID',  
317 - 'TAOBAO_ORDER_HAS_BEEN_PAID',  
318 - 'OFFICIAL_WEBSITE_ORDER_HAS_BEEN_PAID',  
319 - 'WITHHOLDING_ADVANCE_DEPOSIT',  
320 - 'PLATFORM_SETTLEMENT',  
321 - 'PAYMENT_RECEIPT',  
322 - 'PREPAID_NO_NEED_SEND',  
323 - ].includes(copyData.paymentMethod)  
324 - ) {  
325 - copyData.paymentMethod = '';  
326 - copyData.paymentChannel = '';  
327 - } 312 + // // 清空支付方式和支付渠道
  313 + // if (
  314 + // copyData.paymentChannel === 'TAOBAO' ||
  315 + // [
  316 + // 'UNPAID',
  317 + // 'TAOBAO_ORDER_HAS_BEEN_PAID',
  318 + // 'OFFICIAL_WEBSITE_ORDER_HAS_BEEN_PAID',
  319 + // 'WITHHOLDING_ADVANCE_DEPOSIT',
  320 + // 'PLATFORM_SETTLEMENT',
  321 + // 'PAYMENT_RECEIPT',
  322 + // 'PREPAID_NO_NEED_SEND',
  323 + // ].includes(copyData.paymentMethod)
  324 + // ) {
  325 + // copyData.paymentMethod = '';
  326 + // copyData.paymentChannel = '';
  327 + // }
328 328
329 setPaymentMethod(copyData.paymentMethod); 329 setPaymentMethod(copyData.paymentMethod);
330 330
@@ -396,7 +396,18 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -396,7 +396,18 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
396 */ 396 */
397 function getInvoicingSelect() { 397 function getInvoicingSelect() {
398 if (optType('edit') || optType('after-sales-check')) { 398 if (optType('edit') || optType('after-sales-check')) {
399 - return enumToSelect(INVOCING_STATUS_OPTIONS_OLD); 399 + const options = enumToSelect(INVOCING_STATUS_OPTIONS_OLD);
  400 +
  401 + // 永远禁止选择专票和普票,但保留这些选项用于显示历史数据
  402 + return options.map((option: any) => {
  403 + if (
  404 + option.value === 'SPECIALLY_INVOICED' ||
  405 + option.value === 'COMMON_INVOICED'
  406 + ) {
  407 + return { ...option, disabled: true };
  408 + }
  409 + return option;
  410 + });
400 } 411 }
401 return enumToSelect(INVOCING_STATUS_OPTIONS); 412 return enumToSelect(INVOCING_STATUS_OPTIONS);
402 } 413 }
@@ -437,6 +448,34 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -437,6 +448,34 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
437 if (optType('add')) { 448 if (optType('add')) {
438 form.resetFields(['list']); 449 form.resetFields(['list']);
439 } 450 }
  451 +
  452 + // 如果是复制操作,检查销售代码是否为淘宝相关代码
  453 + if (optType('copy')) {
  454 + const salesCode = data?.salesCode;
  455 + const isTaobaoSalesCode = [
  456 + 'TB',
  457 + 'TBC',
  458 + 'HCTB',
  459 + '淘宝',
  460 + 'TAOBAO',
  461 + '新能源材料网',
  462 + 'scilab固态电解质商城',
  463 + 'T-ACG',
  464 + 'ALBB',
  465 + ].includes(salesCode);
  466 +
  467 + if (isTaobaoSalesCode) {
  468 + // 锁定支付渠道和支付方式,但保留原有值
  469 + setPaymentChannelDisabled(true);
  470 + setPaymentMethodDisabled(true);
  471 +
  472 + // 确保控制台日志
  473 + console.log('复制淘宝订单,锁定支付渠道和支付方式:', {
  474 + paymentChannel: data?.paymentChannel,
  475 + paymentMethod: data?.paymentMethod,
  476 + });
  477 + }
  478 + }
440 }, [data]); 479 }, [data]);
441 480
442 /** 481 /**
@@ -1152,35 +1191,65 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1152,35 +1191,65 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1152 autoFillSalesInfo(option); 1191 autoFillSalesInfo(option);
1153 1192
1154 // 检查是否是特殊的淘宝销售代码 1193 // 检查是否是特殊的淘宝销售代码
1155 - const isTaobaoSalesCode = ['TB', 'TBC', 'HCTB'].includes(value);  
1156 -  
1157 - // 清空支付渠道和支付方式  
1158 - form.setFieldsValue({  
1159 - paymentChannel: undefined,  
1160 - paymentMethod: undefined,  
1161 - });  
1162 -  
1163 - // 重置支付渠道和支付方式的禁用状态  
1164 - setPaymentChannelDisabled(false);  
1165 - setPaymentMethodDisabled(false);  
1166 -  
1167 - if (isTaobaoSalesCode) {  
1168 - // 设置支付渠道为淘宝并锁定  
1169 - form.setFieldsValue({ paymentChannel: 'TAOBAO' }); 1194 + const isTaobaoSalesCode = [
  1195 + 'TB',
  1196 + 'TBC',
  1197 + 'HCTB',
  1198 + '淘宝',
  1199 + 'TAOBAO',
  1200 + '新能源材料网',
  1201 + 'scilab固态电解质商城',
  1202 + 'T-ACG',
  1203 + 'ALBB',
  1204 + ].includes(value);
  1205 +
  1206 + // 如果是复制操作且是淘宝销售代码,锁定支付方式和支付渠道,不清空值
  1207 + if (optType('copy') && isTaobaoSalesCode) {
  1208 + // 保留当前的支付渠道和支付方式值,只锁定选择器
1170 setPaymentChannelDisabled(true); 1209 setPaymentChannelDisabled(true);
1171 -  
1172 - // 支付方式默认锁定为预付  
1173 - form.setFieldsValue({ paymentMethod: 'PAYMENT_IN_ADVANCE' });  
1174 - setPaymentMethod('PAYMENT_IN_ADVANCE');  
1175 setPaymentMethodDisabled(true); 1210 setPaymentMethodDisabled(true);
1176 - } else {  
1177 - // 如果不是淘宝销售代码,解除锁定  
1178 - setPaymentChannelDisabled(false);  
1179 - // 只有当前支付渠道不是扣预存时才解除付款方式的锁定 1211 +
  1212 + // 如果当前没有值,则设置默认值
1180 const currentPaymentChannel = 1213 const currentPaymentChannel =
1181 form.getFieldValue('paymentChannel'); 1214 form.getFieldValue('paymentChannel');
1182 - if (currentPaymentChannel !== 'BALANCE') {  
1183 - setPaymentMethodDisabled(false); 1215 + if (!currentPaymentChannel) {
  1216 + form.setFieldsValue({ paymentChannel: 'TAOBAO' });
  1217 + }
  1218 +
  1219 + const currentPaymentMethod = form.getFieldValue('paymentMethod');
  1220 + if (!currentPaymentMethod) {
  1221 + form.setFieldsValue({ paymentMethod: 'PAYMENT_IN_TAOBAO' });
  1222 + setPaymentMethod('PAYMENT_IN_TAOBAO');
  1223 + }
  1224 + } else if (!optType('copy')) {
  1225 + // 非复制操作时,清空支付渠道和支付方式
  1226 + form.setFieldsValue({
  1227 + paymentChannel: undefined,
  1228 + paymentMethod: undefined,
  1229 + });
  1230 +
  1231 + // 重置支付渠道和支付方式的禁用状态
  1232 + setPaymentChannelDisabled(false);
  1233 + setPaymentMethodDisabled(false);
  1234 +
  1235 + if (isTaobaoSalesCode) {
  1236 + // 设置支付渠道为淘宝并锁定
  1237 + form.setFieldsValue({ paymentChannel: 'TAOBAO' });
  1238 + setPaymentChannelDisabled(true);
  1239 +
  1240 + // 支付方式默认锁定为淘宝
  1241 + form.setFieldsValue({ paymentMethod: 'PAYMENT_IN_TAOBAO' });
  1242 + setPaymentMethod('PAYMENT_IN_TAOBAO');
  1243 + setPaymentMethodDisabled(true);
  1244 + } else {
  1245 + // 如果不是淘宝销售代码,解除锁定
  1246 + setPaymentChannelDisabled(false);
  1247 + // 只有当前支付渠道不是扣预存时才解除付款方式的锁定
  1248 + const currentPaymentChannel =
  1249 + form.getFieldValue('paymentChannel');
  1250 + if (currentPaymentChannel !== 'BALANCE') {
  1251 + setPaymentMethodDisabled(false);
  1252 + }
1184 } 1253 }
1185 } 1254 }
1186 }} 1255 }}
@@ -1845,22 +1914,112 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1845,22 +1914,112 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1845 disabled={optType('after-sales-check')} 1914 disabled={optType('after-sales-check')}
1846 /> 1915 />
1847 </div> 1916 </div>
  1917 + <ProFormSelect
  1918 + placeholder="请输入支付方式"
  1919 + name="paymentMethod"
  1920 + width="lg"
  1921 + key="paymentMethod"
  1922 + label="支付方式"
  1923 + onChange={(val: any) => {
  1924 + setPaymentMethod(val);
  1925 + }}
  1926 + options={(() => {
  1927 + // 使用Set记录已经处理过的选项值,避免重复
  1928 + const processedValues = new Set();
  1929 + const finalOptions = [];
  1930 +
  1931 + // 先处理默认可选项
  1932 + enumToSelect(PAYMENT_METHOD_OPTIONS_4_ADD).forEach((option) => {
  1933 + // 将淘宝选项设置为禁用状态,使其无法手动选择
  1934 + if (option.value === 'PAYMENT_IN_TAOBAO') {
  1935 + finalOptions.push({ ...option, disabled: true });
  1936 + } else {
  1937 + finalOptions.push(option);
  1938 + }
  1939 + processedValues.add(option.value);
  1940 + });
  1941 +
  1942 + // 添加强制禁用项,但只添加尚未存在的选项
  1943 + const disabledOptions = [
  1944 + {
  1945 + label: '淘宝订单已付款',
  1946 + value: 'TAOBAO_ORDER_HAS_BEEN_PAID',
  1947 + disabled: true,
  1948 + },
  1949 + {
  1950 + label: '官网已付',
  1951 + value: 'OFFICIAL_WEBSITE_ORDER_HAS_BEEN_PAID',
  1952 + disabled: true,
  1953 + },
  1954 + { label: '淘宝', value: 'PAYMENT_IN_TAOBAO', disabled: true },
  1955 + {
  1956 + label: '预付',
  1957 + value: 'WITHHOLDING_ADVANCE_DEPOSIT',
  1958 + disabled: true,
  1959 + },
  1960 + {
  1961 + label: '平台结算',
  1962 + value: 'PLATFORM_SETTLEMENT',
  1963 + disabled: true,
  1964 + },
  1965 + {
  1966 + label: '预存款无需发货',
  1967 + value: 'PREPAID_NO_NEED_SEND',
  1968 + disabled: true,
  1969 + },
  1970 + ];
  1971 +
  1972 + disabledOptions.forEach((option) => {
  1973 + if (!processedValues.has(option.value)) {
  1974 + finalOptions.push(option);
  1975 + processedValues.add(option.value);
  1976 + }
  1977 + });
1848 1978
  1979 + return finalOptions;
  1980 + })()}
  1981 + rules={[{ required: true, message: '支付方式必填' }]}
  1982 + disabled={optType('after-sales-check') || paymentMethodDisabled}
  1983 + fieldProps={{
  1984 + style: paymentMethodDisabled ? { backgroundColor: '#f5f5f5' } : {},
  1985 + }}
  1986 + />
1849 <ProFormSelect 1987 <ProFormSelect
1850 placeholder="请输入支付渠道" 1988 placeholder="请输入支付渠道"
1851 name="paymentChannel" 1989 name="paymentChannel"
1852 width="lg" 1990 width="lg"
1853 key="paymentChannel" 1991 key="paymentChannel"
1854 label="支付渠道" 1992 label="支付渠道"
1855 - options={enumToSelect(PAYMENT_CHANNEL_OPTIONS).map((option) => {  
1856 - // 将淘宝选项设置为禁用状态,使其无法手动选择  
1857 - if (option.value === 'TAOBAO') {  
1858 - return { ...option, disabled: true };  
1859 - }  
1860 - return option;  
1861 - })} 1993 + options={(() => {
  1994 + // 获取当前支付方式
  1995 + const currentPaymentMethod =
  1996 + paymentMethod || form.getFieldValue('paymentMethod');
  1997 +
  1998 + return enumToSelect(PAYMENT_CHANNEL_OPTIONS).map((option) => {
  1999 + // 将淘宝选项设置为禁用状态,使其无法手动选择
  2000 + if (option.value === 'TAOBAO') {
  2001 + return { ...option, disabled: true };
  2002 + }
  2003 +
  2004 + // 如果选择了"预存款无需发货",禁用"平台结算"和"官网已付"选项
  2005 + if (currentPaymentMethod === 'PREPAID_NO_NEED_SEND') {
  2006 + if (
  2007 + option.value === 'PLATFORM' ||
  2008 + option.value === 'OFFICIAL_WEBSITE' ||
  2009 + option.value === 'BALANCE'
  2010 + ) {
  2011 + return { ...option, disabled: true };
  2012 + }
  2013 + }
  2014 +
  2015 + return option;
  2016 + });
  2017 + })()}
1862 rules={[{ required: true, message: '支付渠道必填' }]} 2018 rules={[{ required: true, message: '支付渠道必填' }]}
1863 disabled={optType('after-sales-check') || paymentChannelDisabled} 2019 disabled={optType('after-sales-check') || paymentChannelDisabled}
  2020 + fieldProps={{
  2021 + style: paymentChannelDisabled ? { backgroundColor: '#f5f5f5' } : {},
  2022 + }}
1864 onChange={(val: any) => { 2023 onChange={(val: any) => {
1865 // 根据支付渠道设置不同的支付方式 2024 // 根据支付渠道设置不同的支付方式
1866 if (val === 'BALANCE') { 2025 if (val === 'BALANCE') {
@@ -1871,56 +2030,16 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1871,56 +2030,16 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1871 }); 2030 });
1872 setPaymentMethod('WITHHOLDING_ADVANCE_DEPOSIT'); 2031 setPaymentMethod('WITHHOLDING_ADVANCE_DEPOSIT');
1873 } else if (val === 'TAOBAO') { 2032 } else if (val === 'TAOBAO') {
1874 - // 支付渠道为淘宝时,支付方式设置为预付 2033 + // 支付渠道为淘宝时,支付方式设置为淘宝
1875 setPaymentMethodDisabled(true); 2034 setPaymentMethodDisabled(true);
1876 - form.setFieldsValue({ paymentMethod: 'PAYMENT_IN_ADVANCE' });  
1877 - setPaymentMethod('PAYMENT_IN_ADVANCE'); 2035 + form.setFieldsValue({ paymentMethod: 'PAYMENT_IN_TAOBAO' });
  2036 + setPaymentMethod('PAYMENT_IN_TAOBAO');
1878 } else { 2037 } else {
1879 // 支付渠道修改为其他的去除锁定状态 2038 // 支付渠道修改为其他的去除锁定状态
1880 setPaymentMethodDisabled(false); 2039 setPaymentMethodDisabled(false);
1881 } 2040 }
1882 }} 2041 }}
1883 /> 2042 />
1884 - <ProFormSelect  
1885 - placeholder="请输入支付方式"  
1886 - name="paymentMethod"  
1887 - width="lg"  
1888 - key="paymentMethod"  
1889 - label="支付方式"  
1890 - onChange={(val: any) => {  
1891 - setPaymentMethod(val);  
1892 - }}  
1893 - options={[  
1894 - // 默认可选项  
1895 - ...enumToSelect(PAYMENT_METHOD_OPTIONS_4_ADD),  
1896 - // 强制禁用项  
1897 - { label: '未付款', value: 'UNPAID', disabled: true },  
1898 - {  
1899 - label: '淘宝订单已付款',  
1900 - value: 'TAOBAO_ORDER_HAS_BEEN_PAID',  
1901 - disabled: true,  
1902 - },  
1903 - {  
1904 - label: '官网订单已付款',  
1905 - value: 'OFFICIAL_WEBSITE_ORDER_HAS_BEEN_PAID',  
1906 - disabled: true,  
1907 - },  
1908 - {  
1909 - label: '预付',  
1910 - value: 'WITHHOLDING_ADVANCE_DEPOSIT',  
1911 - disabled: true,  
1912 - },  
1913 - { label: '平台结算', value: 'PLATFORM_SETTLEMENT', disabled: true },  
1914 - { label: '已回款', value: 'PAYMENT_RECEIPT', disabled: true },  
1915 - {  
1916 - label: '预存款无需发货',  
1917 - value: 'PREPAID_NO_NEED_SEND',  
1918 - disabled: true,  
1919 - },  
1920 - ]}  
1921 - rules={[{ required: true, message: '支付方式必填' }]}  
1922 - disabled={optType('after-sales-check') || paymentMethodDisabled}  
1923 - />  
1924 {/* 隐藏字段用于存储真实UID和privatePocket标志 */} 2043 {/* 隐藏字段用于存储真实UID和privatePocket标志 */}
1925 <ProFormText name="realPrepaidUid" hidden /> 2044 <ProFormText name="realPrepaidUid" hidden />
1926 <ProFormText name="privatePocket" hidden /> 2045 <ProFormText name="privatePocket" hidden />
@@ -2050,7 +2169,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -2050,7 +2169,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
2050 placeholder="选择是否需要开票" 2169 placeholder="选择是否需要开票"
2051 name="invoicingStatus" 2170 name="invoicingStatus"
2052 width="lg" 2171 width="lg"
2053 - key="invoicingStatus" 2172 + key={`invoicingStatus-${invoicingStatus}`}
2054 label="是否需要开票" 2173 label="是否需要开票"
2055 options={getInvoicingSelect()} 2174 options={getInvoicingSelect()}
2056 disabled={optType('after-sales-check')} 2175 disabled={optType('after-sales-check')}