Commit d38ab3b576dd2cfcf8f35da3d503a86483374e79

Authored by 曾国涛
1 parent b6fd4607

fix: 添加核销功能的可编辑表格和模态框

在Invoice页面的核销功能中,添加了可编辑表格和模态框组件。用户现在可以从“发票”和“银行流水”表格中选择
和编辑项目,并通过模态框进行添加操作。此更改包括对AddInvoiceModal和AddBankStatementModal组件的更新,
以及在invoiceWriteOffModal.tsx中集成这些组件以实现核销功能。
src/models/enum.ts 0 → 100644
  1 +import { postServiceConstPayees } from '@/services';
  2 +import { useCallback } from 'react';
  3 +
  4 +export default () => {
  5 + const getPayees = useCallback(async () => {
  6 + const result = await postServiceConstPayees();
  7 + return result.data;
  8 + }, []);
  9 + return { getPayees };
  10 +};
... ...
src/pages/Invoice/Invoice/components/AddBankStatementModal.tsx 0 → 100644
  1 +import { postServiceBankStatementQueryBankStatement } from '@/services';
  2 +import { ModalForm, ProCard, ProTable } from '@ant-design/pro-components';
  3 +import { Button, Divider, Flex, Form, Tag } from 'antd';
  4 +import React from 'react';
  5 +
  6 +export default ({ getRows, onFinish }) => {
  7 + const [form] = Form.useForm();
  8 + const [selectedRows, setSelectedRows] = React.useState<any[]>([]);
  9 +
  10 + const columns = [
  11 + {
  12 + title: '编号',
  13 + hideInSearch: true,
  14 + dataIndex: 'id',
  15 + },
  16 + {
  17 + title: '流水号',
  18 + hideInSearch: true,
  19 + dataIndex: 'serialNumber',
  20 + },
  21 + {
  22 + title: '收款时间',
  23 + dataIndex: 'collectionDatetime',
  24 + hideInSearch: true,
  25 + valueType: 'date',
  26 + },
  27 + {
  28 + title: '收款方',
  29 + hideInTable: true,
  30 + dataIndex: 'payeeText',
  31 + },
  32 + {
  33 + title: '付款方',
  34 + hideInSearch: true,
  35 + dataIndex: 'payer',
  36 + },
  37 + {
  38 + title: '金额',
  39 + dataIndex: 'amount',
  40 + hideInSearch: true,
  41 + valueType: 'money',
  42 + },
  43 + {
  44 + title: '操作',
  45 + valueType: 'option',
  46 + width: 200,
  47 + render: (text, record) => [
  48 + <a
  49 + key="selected"
  50 + onClick={() => {
  51 + let selectedRowsCopy;
  52 + if (!selectedRows || !Array.isArray(selectedRows)) {
  53 + selectedRowsCopy = []; // 初始化为一个空数组
  54 + } else {
  55 + selectedRowsCopy = selectedRows;
  56 + }
  57 + if (!selectedRows?.map((item) => item.id).includes(record.id)) {
  58 + setSelectedRows([...selectedRowsCopy, record]);
  59 + } else {
  60 + setSelectedRows(
  61 + selectedRowsCopy.filter((item) => item.id !== record.id),
  62 + );
  63 + }
  64 + }}
  65 + >
  66 + {selectedRows?.map((item) => item.id).includes(record.id)
  67 + ? '取消选中'
  68 + : '选中'}
  69 + </a>,
  70 + ],
  71 + },
  72 + ];
  73 + return (
  74 + <ModalForm
  75 + title="添加银行流水"
  76 + trigger={<Button type="primary">添加</Button>}
  77 + form={form}
  78 + autoFocusFirstInput
  79 + modalProps={{
  80 + destroyOnClose: true,
  81 + onCancel: () => console.log('run'),
  82 + }}
  83 + onOpenChange={(visible) => {
  84 + if (visible) {
  85 + setSelectedRows(getRows());
  86 + }
  87 + }}
  88 + layout={'horizontal'}
  89 + width={1500}
  90 + submitTimeout={2000}
  91 + onFinish={async (values) => {
  92 + onFinish(selectedRows);
  93 + console.log(values);
  94 + return true;
  95 + }}
  96 + >
  97 + <Divider orientation="left" plain>
  98 + 已选中(合计:¥
  99 + {selectedRows?.reduce((acc, cur) => acc + cur.amount, 0)}元)
  100 + </Divider>
  101 + <ProCard className="mb-[16px]" bordered style={{}}>
  102 + <Flex wrap="wrap" gap="small">
  103 + {selectedRows?.map((item, i) => {
  104 + return (
  105 + <Tag
  106 + key={i + ''}
  107 + closable={true}
  108 + style={{ userSelect: 'none' }}
  109 + color="blue"
  110 + onClose={(e) => {
  111 + e.preventDefault(); //需要加上这句代码,不然删除tag时,当前tag的下一个tag会被设置ant-tag-hidden
  112 + }}
  113 + >
  114 + <span>{item.serialNumber}</span>
  115 + </Tag>
  116 + );
  117 + })}
  118 + </Flex>
  119 + </ProCard>
  120 + <ProTable
  121 + columns={columns}
  122 + request={async (params) => {
  123 + const res = await postServiceBankStatementQueryBankStatement({
  124 + data: {
  125 + ...params,
  126 + writeOffIdIsNull: true,
  127 + },
  128 + });
  129 + return res.data;
  130 + }}
  131 + options={false}
  132 + rowKey="id"
  133 + headerTitle="添加银行流水"
  134 + />
  135 + </ModalForm>
  136 + );
  137 +};
... ...
src/pages/Invoice/Invoice/components/AddInvoiceModal.tsx 0 → 100644
  1 +import { postServiceInvoiceQueryInvoice } from '@/services';
  2 +import { enumToSelect } from '@/utils';
  3 +import { ModalForm, ProCard, ProTable } from '@ant-design/pro-components';
  4 +import { useModel } from '@umijs/max';
  5 +import { Button, Divider, Flex, Form, Tag } from 'antd';
  6 +import React from 'react';
  7 +
  8 +export default ({ getRows, onFinish }) => {
  9 + const [form] = Form.useForm();
  10 + const [selectedRows, setSelectedRows] = React.useState<any[]>([]);
  11 + const { getPayees } = useModel('enum');
  12 + const columns = [
  13 + {
  14 + title: '发票号码',
  15 + hideInSearch: true,
  16 + dataIndex: 'invoiceNumber',
  17 + },
  18 + {
  19 + title: '发票号码',
  20 + hideInTable: true,
  21 + dataIndex: 'invoiceNumber',
  22 + },
  23 + {
  24 + title: '收款方',
  25 + hideInTable: true,
  26 + valueType: 'select',
  27 + dataIndex: 'payee',
  28 + request: async () => {
  29 + const payees = await getPayees();
  30 + return enumToSelect(payees);
  31 + },
  32 + },
  33 + {
  34 + title: '收款方',
  35 + hideInSearch: true,
  36 + dataIndex: 'payeeText',
  37 + },
  38 + {
  39 + title: '付款方',
  40 + hideInSearch: true,
  41 + dataIndex: 'purchaser',
  42 + },
  43 + {
  44 + title: '付款方',
  45 + hideInTable: true,
  46 + dataIndex: 'purchaser',
  47 + },
  48 + {
  49 + title: '金额',
  50 + dataIndex: 'money',
  51 + hideInSearch: true,
  52 + valueType: 'money',
  53 + },
  54 + {
  55 + title: '日期',
  56 + dataIndex: 'invoicingTime',
  57 + hideInSearch: true,
  58 + valueType: 'date',
  59 + },
  60 + {
  61 + title: '操作',
  62 + valueType: 'option',
  63 + width: 200,
  64 + render: (text, record) => [
  65 + <a
  66 + key="selected"
  67 + onClick={() => {
  68 + let selectedRowsCopy;
  69 + if (!selectedRows || !Array.isArray(selectedRows)) {
  70 + selectedRowsCopy = []; // 初始化为一个空数组
  71 + } else {
  72 + selectedRowsCopy = selectedRows;
  73 + }
  74 + if (!selectedRows?.map((item) => item.id).includes(record.id)) {
  75 + setSelectedRows([...selectedRowsCopy, record]);
  76 + } else {
  77 + setSelectedRows(
  78 + selectedRowsCopy.filter((item) => item.id !== record.id),
  79 + );
  80 + }
  81 + }}
  82 + >
  83 + {selectedRows?.map((item) => item.id).includes(record.id)
  84 + ? '取消选中'
  85 + : '选中'}
  86 + </a>,
  87 + ],
  88 + },
  89 + ];
  90 + return (
  91 + <ModalForm
  92 + title="添加发票"
  93 + trigger={<Button type="primary">添加</Button>}
  94 + form={form}
  95 + autoFocusFirstInput
  96 + onOpenChange={(visible) => {
  97 + if (visible) {
  98 + setSelectedRows(getRows());
  99 + }
  100 + }}
  101 + modalProps={{
  102 + destroyOnClose: true,
  103 +
  104 + onCancel: () => console.log('run'),
  105 + }}
  106 + layout={'horizontal'}
  107 + width={1500}
  108 + submitTimeout={2000}
  109 + onFinish={async () => {
  110 + onFinish(selectedRows);
  111 + return true;
  112 + }}
  113 + >
  114 + <Divider orientation="left" plain>
  115 + 已选中(合计:¥{selectedRows?.reduce((acc, cur) => acc + cur.money, 0)}
  116 + )
  117 + </Divider>
  118 + <ProCard className="mb-[16px]" bordered style={{}}>
  119 + <Flex wrap="wrap" gap="small">
  120 + {selectedRows?.map((item, i) => {
  121 + return (
  122 + <Tag
  123 + key={i}
  124 + closable={true}
  125 + style={{ userSelect: 'none' }}
  126 + color="blue"
  127 + onClose={(e) => {
  128 + e.preventDefault(); //需要加上这句代码,不然删除tag时,当前tag的下一个tag会被设置ant-tag-hidden
  129 + }}
  130 + >
  131 + <span>{item.invoiceNumber}</span>
  132 + </Tag>
  133 + );
  134 + })}
  135 + </Flex>
  136 + </ProCard>
  137 + <ProTable
  138 + columns={columns}
  139 + request={async (params) => {
  140 + const res = await postServiceInvoiceQueryInvoice({
  141 + data: {
  142 + ...params,
  143 + writeOffIdIsNull: true,
  144 + },
  145 + });
  146 + return res.data;
  147 + }}
  148 + options={false}
  149 + rowKey="id"
  150 + headerTitle="添加发票"
  151 + />
  152 + </ModalForm>
  153 + );
  154 +};
... ...
src/pages/Invoice/Invoice/components/InvoiceVerificationModal.tsx
1   -import ButtonConfirm from '@/components/ButtomConfirm';
2   -import EllipsisDiv from '@/components/Div/EllipsisDiv';
3   -import { RESPONSE_CODE } from '@/constants/enum';
4 1 import { INVOCING_STATUS, PAYEE_OPTIONS } from '@/pages/Order/constant';
5   -import {
6   - postServiceInvoiceCancelInvoiceAndBankStatement,
7   - postServiceInvoiceQueryInvoiceDetail,
8   -} from '@/services';
9   -import { enumValueToLabel, formatDateTime } from '@/utils';
  2 +import { postServiceInvoiceQueryInvoiceDetail } from '@/services';
  3 +import { enumValueToLabel } from '@/utils';
10 4 import { formatDate } from '@/utils/time';
11   -import { PlusOutlined } from '@ant-design/icons';
12   -import {
13   - ActionType,
14   - ModalForm,
15   - ProCard,
16   - ProTable,
17   -} from '@ant-design/pro-components';
  5 +import { ActionType, ModalForm, ProCard } from '@ant-design/pro-components';
18 6 import {
19 7 Button,
20 8 Descriptions,
... ... @@ -22,10 +10,8 @@ import {
22 10 Divider,
23 11 Flex,
24 12 Form,
25   - message,
26 13 } from 'antd';
27 14 import { useEffect, useRef, useState } from 'react';
28   -import { BANK_STATEMENT_COLUMNS, INVOICE_STATUS } from '../../constant';
29 15 import '../index.less';
30 16 import BankChooseModal from './BankChooseModal';
31 17  
... ... @@ -34,7 +20,7 @@ export default ({ invoiceId, setVisible, onClose }) =&gt; {
34 20 const [bankChooseModalVisible, setBankChooseModalVisible] = useState(false);
35 21 const [invoiceInfo, setInvoiceInfo] = useState({});
36 22 const [relationOrderIds, setRelationOrderIds] = useState([]);
37   - const [relationBankStatements, setRelationBankStatements] = useState([]);
  23 + const [setRelationBankStatements] = useState([]);
38 24 const actionRef = useRef<ActionType>();
39 25  
40 26 const loadInvoiceData = async () => {
... ... @@ -137,116 +123,6 @@ export default ({ invoiceId, setVisible, onClose }) =&gt; {
137 123 },
138 124 ];
139 125  
140   - const getTableCellText = (target: any) => {
141   - if (!target) {
142   - return '';
143   - }
144   -
145   - if (target.props) {
146   - return target.props.text;
147   - }
148   -
149   - return target;
150   - };
151   -
152   - /**
153   - * 加载表格的各个列格式
154   - */
155   - const bankStatementColumnsInit = () => {
156   - let columns = BANK_STATEMENT_COLUMNS.map((item) => {
157   - let newItem = { ...item };
158   - let dataIndex = item.dataIndex;
159   - let dataType = item.valueType;
160   -
161   - newItem.render = (text, record) => {
162   - let textValue = record[dataIndex];
163   -
164   - if (dataType === 'date') {
165   - textValue = formatDate(textValue);
166   - }
167   -
168   - if (dataType === 'dateTime') {
169   - textValue = formatDateTime(textValue);
170   - }
171   -
172   - if (dataType === 'money') {
173   - textValue = '¥' + textValue;
174   - }
175   -
176   - switch (dataIndex) {
177   - case 'invoiceStatus':
178   - return (
179   - <EllipsisDiv
180   - text={enumValueToLabel(
181   - getTableCellText(textValue),
182   - INVOCING_STATUS,
183   - )}
184   - />
185   - );
186   -
187   - case 'status':
188   - return (
189   - <EllipsisDiv
190   - text={enumValueToLabel(
191   - getTableCellText(textValue),
192   - INVOICE_STATUS,
193   - )}
194   - />
195   - );
196   -
197   - case 'payee':
198   - return (
199   - <EllipsisDiv
200   - text={enumValueToLabel(
201   - getTableCellText(textValue),
202   - PAYEE_OPTIONS,
203   - )}
204   - />
205   - );
206   -
207   - default:
208   - return <EllipsisDiv text={getTableCellText(textValue)} />;
209   - }
210   - };
211   -
212   - return newItem;
213   - });
214   -
215   - columns.push({
216   - title: '操作',
217   - valueType: 'option',
218   - key: 'option',
219   - fixed: 'right',
220   - width: 70,
221   - render: (text, record) => {
222   - let optBtns = [];
223   - optBtns.push(
224   - <ButtonConfirm
225   - key="delete"
226   - className="p-0"
227   - title={'确认删除此项吗?'}
228   - text="删除"
229   - onConfirm={async () => {
230   - let res = await postServiceInvoiceCancelInvoiceAndBankStatement({
231   - data: {
232   - invoiceId: invoiceId,
233   - cancelId: [record.id],
234   - },
235   - });
236   - if (res.result === RESPONSE_CODE.SUCCESS) {
237   - message.success(res.message);
238   - loadInvoiceData();
239   - }
240   - }}
241   - />,
242   - );
243   - return optBtns;
244   - },
245   - });
246   -
247   - return columns;
248   - };
249   -
250 126 useEffect(() => {
251 127 loadInvoiceData();
252 128 }, []);
... ... @@ -304,61 +180,6 @@ export default ({ invoiceId, setVisible, onClose }) =&gt; {
304 180 </ProCard>
305 181  
306 182 <Divider plain></Divider>
307   -
308   - <ProTable
309   - columns={bankStatementColumnsInit()}
310   - actionRef={actionRef}
311   - cardBordered
312   - pagination={{
313   - pageSize: 10,
314   - }}
315   - dataSource={relationBankStatements}
316   - columnsState={{
317   - persistenceKey: 'pro-table-singe-demos',
318   - persistenceType: 'localStorage',
319   - defaultValue: {
320   - option: { fixed: 'right', disable: true },
321   - },
322   - onChange(value) {
323   - console.log('value: ', value);
324   - },
325   - }}
326   - rowKey="id"
327   - search={false}
328   - options={{
329   - setting: {
330   - listsHeight: 400,
331   - },
332   - reload: false,
333   - }}
334   - form={{
335   - // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下
336   - syncToUrl: (values, type) => {
337   - if (type === 'get') {
338   - return {
339   - ...values,
340   - created_at: [values.startTime, values.endTime],
341   - };
342   - }
343   - return values;
344   - },
345   - }}
346   - dateFormatter="string"
347   - headerTitle="银行流水"
348   - scroll={{ x: 1400, y: 360 }}
349   - toolBarRender={() => [
350   - <Button
351   - key="button"
352   - icon={<PlusOutlined />}
353   - onClick={() => {
354   - setBankChooseModalVisible(true);
355   - }}
356   - type="primary"
357   - >
358   - 添加
359   - </Button>,
360   - ]}
361   - />
362 183 </ModalForm>
363 184  
364 185 {bankChooseModalVisible ? (
... ...
src/pages/Invoice/Invoice/components/invoiceWriteOffModal.tsx
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import AddBankStatementModal from '@/pages/Invoice/Invoice/components/AddBankStatementModal';
  3 +import AddInvoiceModal from '@/pages/Invoice/Invoice/components/AddInvoiceModal';
  4 +import { postServiceInvoiceInvoiceWriteOff } from '@/services';
1 5 import {
2 6 EditableFormInstance,
3 7 EditableProTable,
4 8 ModalForm,
5 9 ProCard,
6   - ProColumns,
7 10 ProForm,
8 11 ProFormDependency,
9 12 ProFormField,
10 13 ProFormInstance,
11   - ProFormSwitch,
  14 + ProFormText,
12 15 } from '@ant-design/pro-components';
13   -import { Button } from 'antd';
  16 +import { Button, Divider, Flex, message } from 'antd';
14 17 import React, { useRef, useState } from 'react';
15 18  
16   -type DataSourceType = {
17   - id: React.Key;
18   - title?: string;
19   - decs?: string;
20   - state?: string;
21   - created_at?: number;
22   - update_at?: number;
23   - children?: DataSourceType[];
24   -};
25   -
26   -const defaultData: DataSourceType[] = [
27   - {
28   - id: '624748504',
29   - title: '活动名称一',
30   - decs: '这个活动真好玩',
31   - state: 'open',
32   - created_at: 1590486176000,
33   - update_at: 1590486176000,
34   - },
35   - {
36   - id: '624691229',
37   - title: '活动名称二',
38   - decs: '这个活动真好玩',
39   - state: 'closed',
40   - created_at: 1590481162000,
41   - update_at: 1590481162000,
42   - },
43   -];
44   -
45 19 let i = 0;
46 20  
47   -export default () => {
48   - const [editableKeys, setEditableRowKeys] = useState<React.Key[]>(() => []);
49   - const [controlled, setControlled] = useState<boolean>(false);
  21 +export default ({ getData, triggerButton, readOnly }) => {
  22 + const [InvoiceEditableKeys, setInvoiceEditableKeys] = useState<React.Key[]>(
  23 + () => [],
  24 + );
50 25 const formRef = useRef<ProFormInstance<any>>();
51   - const editorFormRef = useRef<EditableFormInstance<DataSourceType>>();
52   - const columns: ProColumns<DataSourceType>[] = [
53   - {
54   - title: '活动名称',
55   - dataIndex: 'title',
56   - formItemProps: () => {
57   - return {
58   - rules: [{ required: true, message: '此项为必填项' }],
59   - };
  26 +
  27 + const invoiceEditorFormRef = useRef<EditableFormInstance>();
  28 + const getInvoiceColumns = () => {
  29 + let columns = [
  30 + {
  31 + title: '发票号码',
  32 + dataIndex: 'invoiceNumber',
60 33 },
61   - },
62   - {
63   - title: '状态',
64   - key: 'state',
65   - dataIndex: 'state',
66   - valueType: 'select',
67   - valueEnum: {
68   - all: { text: '全部', status: 'Default' },
69   - open: {
70   - text: '未解决',
71   - status: 'Error',
72   - },
73   - closed: {
74   - text: '已解决',
75   - status: 'Success',
76   - },
  34 + {
  35 + title: '收款方',
  36 + dataIndex: 'payeeText',
77 37 },
78   - },
79   - {
80   - title: '描述',
81   - dataIndex: 'decs',
82   - },
83   - {
84   - title: '活动时间',
85   - dataIndex: 'created_at',
86   - valueType: 'date',
87   - },
88   - {
89   - title: '操作',
90   - valueType: 'option',
91   - width: 200,
92   - render: (text, record, _, action) => [
93   - <a
94   - key="editable"
95   - onClick={() => {
96   - action?.startEditable?.(record.id, record);
97   - }}
98   - >
99   - 编辑
100   - </a>,
101   - <a
102   - key="delete"
103   - onClick={() => {
104   - const tableDataSource = formRef.current?.getFieldValue(
105   - 'table',
106   - ) as DataSourceType[];
107   - formRef.current?.setFieldsValue({
108   - table: tableDataSource.filter((item) => item.id !== record.id),
109   - });
110   - }}
111   - >
112   - 删除
113   - </a>,
114   - ],
115   - },
116   - ];
  38 + {
  39 + title: '付款方',
  40 + dataIndex: 'purchaser',
  41 + },
  42 + {
  43 + title: '金额',
  44 + dataIndex: 'money',
  45 + valueType: 'money',
  46 + },
  47 + {
  48 + title: '日期',
  49 + dataIndex: 'invoicingTime',
  50 + valueType: 'date',
  51 + },
  52 + ];
  53 + if (!readOnly) {
  54 + columns.push({
  55 + title: '操作',
  56 + valueType: 'option',
  57 + render: (text, record) => [
  58 + <a
  59 + key="delete"
  60 + onClick={() => {
  61 + const tableDataSource =
  62 + formRef.current?.getFieldValue('invoices');
  63 + console.log(JSON.stringify(tableDataSource));
  64 + formRef.current?.setFieldValue(
  65 + 'invoices',
  66 + tableDataSource.filter((item) => item.id !== record.id),
  67 + );
  68 + }}
  69 + >
  70 + 删除
  71 + </a>,
  72 + ],
  73 + });
  74 + }
  75 + return columns;
  76 + };
  77 +
  78 + const [bankStatementEditableKeys, setBankStatementEditableKeys] = useState<
  79 + React.Key[]
  80 + >(() => []);
  81 + const bankStatementEditorFormRef = useRef<EditableFormInstance>();
  82 + const getBankStatementColumns = () => {
  83 + let columns = [
  84 + {
  85 + title: '流水号',
  86 + dataIndex: 'serialNumber',
  87 + },
  88 + {
  89 + title: '收款方',
  90 + dataIndex: 'payeeText',
  91 + },
  92 + {
  93 + title: '付款方',
  94 + dataIndex: 'payer',
  95 + },
  96 + {
  97 + title: '金额',
  98 + dataIndex: 'amount',
  99 + valueType: 'money',
  100 + },
  101 + {
  102 + title: '日期',
  103 + dataIndex: 'collectionDatetime',
  104 + valueType: 'date',
  105 + },
  106 + ];
  107 + if (!readOnly) {
  108 + columns.push({
  109 + title: '操作',
  110 + valueType: 'option',
  111 + width: 200,
  112 + render: (text, record) => [
  113 + <a
  114 + key="delete"
  115 + onClick={() => {
  116 + const tableDataSource =
  117 + formRef.current?.getFieldValue('bankStatements');
  118 + console.log(JSON.stringify(tableDataSource));
  119 + formRef.current?.setFieldValue(
  120 + 'bankStatements',
  121 + tableDataSource.filter((item) => item.id !== record.id),
  122 + );
  123 + }}
  124 + >
  125 + 删除
  126 + </a>,
  127 + ],
  128 + });
  129 + }
  130 + return columns;
  131 + };
117 132  
118 133 return (
119 134 <ModalForm
  135 + title={'发票核销'}
120 136 formRef={formRef}
121   - initialValues={{
122   - table: defaultData,
  137 + onFinish={async (values) => {
  138 + const body = {
  139 + invoiceWriteOffId: values.invoiceWriteOffId,
  140 + invoiceIds: values.invoices?.map((item) => item.id),
  141 + bankStatementIds: values.bankStatements?.map((item) => item.id),
  142 + };
  143 + const res = await postServiceInvoiceInvoiceWriteOff({
  144 + data: body,
  145 + });
  146 + if (res.result === RESPONSE_CODE.SUCCESS) {
  147 + message.success('核销成功');
  148 + return true;
  149 + }
  150 + //return true;
123 151 }}
124   - trigger={<Button type="primary">核销</Button>}
  152 + trigger={triggerButton}
125 153 validateTrigger="onBlur"
  154 + request={async () => {
  155 + return getData();
  156 + }}
  157 + /*initialValues={{
  158 + invoiceWriteOffId:invoiceWriteOffId,
  159 + invoices:originInvoices,
  160 + }}*/
126 161 >
127   - <EditableProTable<DataSourceType>
  162 + <ProFormText name={'invoiceWriteOffId'} hidden={true}></ProFormText>
  163 +
  164 + <EditableProTable
  165 + key={'invoices'}
128 166 rowKey="id"
129   - scroll={{
130   - x: 960,
131   - }}
132   - editableFormRef={editorFormRef}
133   - headerTitle="可编辑表格"
134   - maxLength={5}
135   - name="table"
136   - controlled={controlled}
  167 + editableFormRef={invoiceEditorFormRef}
  168 + headerTitle="发票"
  169 + maxLength={10}
  170 + name="invoices"
  171 + controlled={true}
137 172 recordCreatorProps={false}
138 173 toolBarRender={() => [
139   - <ProFormSwitch
140   - key="render"
141   - fieldProps={{
142   - style: {
143   - marginBlockEnd: 0,
144   - },
145   - checked: controlled,
146   - onChange: (value) => {
147   - setControlled(value);
148   - },
149   - }}
150   - checkedChildren="数据更新通知 Form"
151   - unCheckedChildren="保存后通知 Form"
152   - noStyle
153   - />,
154   - <Button
155   - key="rows"
156   - onClick={() => {
157   - const rows = editorFormRef.current?.getRowsData?.();
158   - console.log(rows);
159   - }}
160   - >
161   - 获取 table 的数据
162   - </Button>,
  174 + <>
  175 + {!readOnly && (
  176 + <AddInvoiceModal
  177 + key={'addInvoice'}
  178 + getRows={() => formRef.current?.getFieldValue('invoices')}
  179 + onFinish={(datas) => {
  180 + const invoices = formRef.current?.getFieldValue('invoices');
  181 + // 添加非空判断,并处理为空的情况
  182 + const mergedInvoices =
  183 + invoices && Array.isArray(invoices) ? invoices : [];
  184 + const mergedDatas =
  185 + datas && Array.isArray(datas) ? datas : [];
  186 + let res = [...mergedInvoices, ...mergedDatas];
  187 + //对res 进行去重处理,根据id去重
  188 + const resMap = new Map();
  189 + res.forEach((item) => {
  190 + resMap.set(item.id, item);
  191 + });
  192 + res = Array.from(resMap.values());
  193 + formRef.current?.setFieldValue('invoices', res);
  194 + }}
  195 + />
  196 + )}
  197 + </>,
163 198 ]}
164   - columns={columns}
  199 + columns={getInvoiceColumns()}
165 200 editable={{
166 201 type: 'multiple',
167   - editableKeys,
168   - onChange: setEditableRowKeys,
  202 + editableKeys: InvoiceEditableKeys,
  203 + onChange: setInvoiceEditableKeys,
169 204 actionRender: (row, config, defaultDom) => {
170 205 return [
171 206 defaultDom.save,
... ... @@ -176,7 +211,7 @@ export default () =&gt; {
176 211 onClick={() => {
177 212 console.log(config.index);
178 213 i++;
179   - editorFormRef.current?.setRowData?.(config.index!, {
  214 + invoiceEditorFormRef.current?.setRowData?.(config.index!, {
180 215 title: '动态设置的title' + i,
181 216 });
182 217 }}
... ... @@ -188,9 +223,143 @@ export default () =&gt; {
188 223 }}
189 224 />
190 225 <ProForm.Item>
191   - <ProCard title="表格数据" headerBordered collapsible defaultCollapsed>
192   - <ProFormDependency name={['table']}>
193   - {({ table }) => {
  226 + <ProCard
  227 + hidden={true}
  228 + title="表格数据"
  229 + headerBordered
  230 + collapsible
  231 + defaultCollapsed
  232 + >
  233 + <ProFormDependency name={['invoices']}>
  234 + {({ invoices }) => {
  235 + return (
  236 + <ProFormField
  237 + ignoreFormItem
  238 + fieldProps={{
  239 + style: {
  240 + width: '100%',
  241 + },
  242 + }}
  243 + mode="read"
  244 + valueType="jsonCode"
  245 + text={JSON.stringify(invoices)}
  246 + />
  247 + );
  248 + }}
  249 + </ProFormDependency>
  250 + </ProCard>
  251 + </ProForm.Item>
  252 +
  253 + <Divider orientation="left" plain>
  254 + 发票关联订单号
  255 + </Divider>
  256 + <ProCard bordered style={{}}>
  257 + <Flex>
  258 + <div>
  259 + <ProFormDependency name={['invoices']}>
  260 + {({ invoices }) => {
  261 + return invoices?.map((item) => (
  262 + <>
  263 + {item.invoiceNumber}(
  264 + {item.mainOrderIds?.map((mainId) => (
  265 + <>
  266 + <Button
  267 + className="pl-1 pr-0"
  268 + type="link"
  269 + target="_blank"
  270 + href={'/order?id=' + mainId}
  271 + >
  272 + {mainId}
  273 + </Button>
  274 + <Divider type="vertical" />
  275 + </>
  276 + ))}
  277 + )
  278 + <Divider type="vertical" />
  279 + </>
  280 + ));
  281 + }}
  282 + </ProFormDependency>
  283 + </div>
  284 + </Flex>
  285 + </ProCard>
  286 +
  287 + <EditableProTable
  288 + key={'bankStatements'}
  289 + rowKey="id"
  290 + editableFormRef={bankStatementEditorFormRef}
  291 + headerTitle="流水"
  292 + maxLength={10}
  293 + name="bankStatements"
  294 + controlled={true}
  295 + recordCreatorProps={false}
  296 + toolBarRender={() => [
  297 + <>
  298 + {!readOnly && (
  299 + <AddBankStatementModal
  300 + getRows={() => formRef.current?.getFieldValue('bankStatements')}
  301 + onFinish={(datas) => {
  302 + const bankStatements =
  303 + formRef.current?.getFieldValue('bankStatements');
  304 + // 添加非空判断,并处理为空的情况
  305 + const mergedBankStatements =
  306 + bankStatements && Array.isArray(bankStatements)
  307 + ? bankStatements
  308 + : [];
  309 + const mergedDatas =
  310 + datas && Array.isArray(datas) ? datas : [];
  311 + let res = [...mergedBankStatements, ...mergedDatas];
  312 + //对res 进行去重处理,根据id去重
  313 + const resMap = new Map();
  314 + res.forEach((item) => {
  315 + resMap.set(item.id, item);
  316 + });
  317 + res = Array.from(resMap.values());
  318 + formRef.current?.setFieldValue('bankStatements', res);
  319 + }}
  320 + />
  321 + )}
  322 + </>,
  323 + ]}
  324 + columns={getBankStatementColumns()}
  325 + editable={{
  326 + type: 'multiple',
  327 + editableKeys: bankStatementEditableKeys,
  328 + onChange: setBankStatementEditableKeys,
  329 + actionRender: (row, config, defaultDom) => {
  330 + return [
  331 + defaultDom.save,
  332 + defaultDom.delete,
  333 + defaultDom.cancel,
  334 + <a
  335 + key="set"
  336 + onClick={() => {
  337 + console.log(config.index);
  338 + i++;
  339 + bankStatementEditorFormRef.current?.setRowData?.(
  340 + config.index!,
  341 + {
  342 + title: '动态设置的title' + i,
  343 + },
  344 + );
  345 + }}
  346 + >
  347 + 动态设置此项
  348 + </a>,
  349 + ];
  350 + },
  351 + }}
  352 + />
  353 + <ProForm.Item>
  354 + <ProCard
  355 + hidden={true}
  356 + title="表格数据"
  357 + headerBordered
  358 + collapsible
  359 + defaultCollapsed
  360 + >
  361 + <ProFormDependency name={['bankStatements']}>
  362 + {({ bankStatements }) => {
194 363 return (
195 364 <ProFormField
196 365 ignoreFormItem
... ... @@ -201,7 +370,7 @@ export default () =&gt; {
201 370 }}
202 371 mode="read"
203 372 valueType="jsonCode"
204   - text={JSON.stringify(table)}
  373 + text={JSON.stringify(bankStatements)}
205 374 />
206 375 );
207 376 }}
... ...
src/pages/Invoice/Invoice/index.tsx
... ... @@ -8,6 +8,7 @@ import { INVOICE_COLUMNS } from &#39;@/pages/Invoice/constant&#39;;
8 8 import { INVOCING_STATUS, PAYEE_OPTIONS } from '@/pages/Order/constant';
9 9 import {
10 10 postServiceInvoiceDeleteInvoice,
  11 + postServiceInvoiceGetWriteOffRecord,
11 12 postServiceInvoiceQueryInvoice,
12 13 } from '@/services';
13 14 import { enumValueToLabel, formatDateTime } from '@/utils';
... ... @@ -95,21 +96,46 @@ const InvoiceRecord = () =&gt; {
95 96 valueType: 'option',
96 97 key: 'option',
97 98 fixed: 'right',
98   - width: 120,
  99 + width: 160,
99 100 render: (text, record) => {
100 101 let btns = [];
101   - if (record.paths?.includes('writeOff')) {
  102 + if (!record.writeOffId) {
102 103 btns.push(
103   - <a
104   - key="editable"
105   - onClick={() => {
106   - console.log(JSON.stringify(record));
107   - setInvoiceVerificationVisible(true);
108   - setInvoiceId(record.id);
  104 + <InvoiceWriteOffModal
  105 + getData={() => {
  106 + return {
  107 + invoices: [record],
  108 + };
109 109 }}
110   - >
111   - 核销
112   - </a>,
  110 + key="writeOff"
  111 + triggerButton={
  112 + <Button size={'small'} type="link">
  113 + 核销
  114 + </Button>
  115 + }
  116 + readOnly={false}
  117 + />,
  118 + );
  119 + }
  120 +
  121 + if (record.writeOffId) {
  122 + btns.push(
  123 + <InvoiceWriteOffModal
  124 + getData={async () => {
  125 + const res = await postServiceInvoiceGetWriteOffRecord({
  126 + data: { id: record.writeOffId },
  127 + });
  128 + const data = res.data;
  129 + return {
  130 + invoiceWriteOffId: data.id,
  131 + invoices: data.invoiceDtos,
  132 + bankStatements: data.bankStatementDtos,
  133 + };
  134 + }}
  135 + key="writeOff"
  136 + triggerButton={<Button type="link">核销记录</Button>}
  137 + readOnly={true}
  138 + />,
113 139 );
114 140 }
115 141  
... ... @@ -207,7 +233,12 @@ const InvoiceRecord = () =&gt; {
207 233 }}
208 234 key="add"
209 235 ></AddInvoiceDrawerForm>,
210   - <InvoiceWriteOffModal key="writeOff" />,
  236 + <InvoiceWriteOffModal
  237 + readOnly={false}
  238 + getData={() => ({})}
  239 + key="writeOff"
  240 + triggerButton={<Button type="primary">核销</Button>}
  241 + />,
211 242 ]}
212 243 />
213 244  
... ...
src/pages/Invoice/InvoiceRecord/components/InvoiceRecordDetailModal.tsx
... ... @@ -30,7 +30,6 @@ export default ({ id, setVisible, reloadTable }) =&gt; {
30 30 const [form] = Form.useForm();
31 31  
32 32 useEffect(() => {
33   - console.log('id' + id);
34 33 const getPayees = async () => {
35 34 let res = await postServiceConstGetPayeeEnum();
36 35 setPayees(res.data);
... ...
src/pages/Invoice/InvoiceVerification/components/InvoiceVerificationModal.tsx
1   -import ButtonConfirm from '@/components/ButtomConfirm';
2   -import EllipsisDiv from '@/components/Div/EllipsisDiv';
3   -import { RESPONSE_CODE } from '@/constants/enum';
4 1 import { INVOCING_STATUS, PAYEE_OPTIONS } from '@/pages/Order/constant';
5   -import {
6   - postServiceInvoiceCancelInvoiceAndBankStatement,
7   - postServiceInvoiceQueryInvoiceDetail,
8   -} from '@/services';
9   -import { enumValueToLabel, formatDateTime } from '@/utils';
  2 +import { postServiceInvoiceQueryInvoiceDetail } from '@/services';
  3 +import { enumValueToLabel } from '@/utils';
10 4 import { formatDate } from '@/utils/time';
11   -import { PlusOutlined } from '@ant-design/icons';
12   -import {
13   - ActionType,
14   - ModalForm,
15   - ProCard,
16   - ProTable,
17   -} from '@ant-design/pro-components';
  5 +import { ActionType, ModalForm, ProCard } from '@ant-design/pro-components';
18 6 import {
19 7 Button,
20 8 Descriptions,
... ... @@ -22,10 +10,9 @@ import {
22 10 Divider,
23 11 Flex,
24 12 Form,
25   - message,
26 13 } from 'antd';
27 14 import { useEffect, useRef, useState } from 'react';
28   -import { BANK_STATEMENT_COLUMNS, INVOICE_STATUS } from '../../constant';
  15 +import { INVOICE_STATUS } from '../../constant';
29 16 import '../index.less';
30 17 import BankChooseModal from './BankChooseModal';
31 18  
... ... @@ -34,7 +21,7 @@ export default ({ invoiceId, setVisible, onClose }) =&gt; {
34 21 const [bankChooseModalVisible, setBankChooseModalVisible] = useState(false);
35 22 const [invoiceInfo, setInvoiceInfo] = useState({});
36 23 const [relationOrderIds, setRelationOrderIds] = useState([]);
37   - const [relationBankStatements, setRelationBankStatements] = useState([]);
  24 + const [setRelationBankStatements] = useState([]);
38 25 const actionRef = useRef<ActionType>();
39 26  
40 27 const loadInvoiceData = async () => {
... ... @@ -137,120 +124,6 @@ export default ({ invoiceId, setVisible, onClose }) =&gt; {
137 124 },
138 125 ];
139 126  
140   - const getTableCellText = (target: any) => {
141   - if (!target) {
142   - return '';
143   - }
144   -
145   - if (target.props) {
146   - return target.props.text;
147   - }
148   -
149   - return target;
150   - };
151   -
152   - /**
153   - * 加载表格的各个列格式
154   - */
155   - const bankStatementColumnsInit = () => {
156   - let columns = BANK_STATEMENT_COLUMNS.map((item) => {
157   - let newItem = { ...item };
158   - let dataIndex = item.dataIndex;
159   - let dataType = item.valueType;
160   -
161   - newItem.render = (text, record) => {
162   - let textValue = record[dataIndex];
163   -
164   - if (dataType === 'date') {
165   - textValue = formatDate(textValue);
166   - }
167   -
168   - if (dataType === 'dateTime') {
169   - textValue = formatDateTime(textValue);
170   - }
171   -
172   - if (dataType === 'money') {
173   - textValue = '¥' + textValue;
174   - }
175   -
176   - switch (dataIndex) {
177   - case 'invoiceStatus':
178   - return (
179   - <EllipsisDiv
180   - text={enumValueToLabel(
181   - getTableCellText(textValue),
182   - INVOCING_STATUS,
183   - )}
184   - />
185   - );
186   -
187   - case 'status':
188   - return (
189   - <EllipsisDiv
190   - text={enumValueToLabel(
191   - getTableCellText(textValue),
192   - INVOICE_STATUS,
193   - )}
194   - />
195   - );
196   -
197   - case 'payee':
198   - return (
199   - <EllipsisDiv
200   - text={enumValueToLabel(
201   - getTableCellText(textValue),
202   - PAYEE_OPTIONS,
203   - )}
204   - />
205   - );
206   -
207   - default:
208   - return <EllipsisDiv text={getTableCellText(textValue)} />;
209   - }
210   - };
211   -
212   - return newItem;
213   - });
214   -
215   - columns.push({
216   - title: '操作',
217   - valueType: 'option',
218   - key: 'option',
219   - fixed: 'right',
220   - width: 70,
221   - render: (text, record) => {
222   - let optBtns = [];
223   - if (invoiceInfo?.status === 'VERIFIED') {
224   - return [];
225   - }
226   -
227   - optBtns.push(
228   - <ButtonConfirm
229   - key="delete"
230   - className="p-0"
231   - title={'确认删除此项吗?'}
232   - text="删除"
233   - onConfirm={async () => {
234   - let res = await postServiceInvoiceCancelInvoiceAndBankStatement({
235   - data: {
236   - invoiceId: invoiceId,
237   - cancelId: [record.id],
238   - },
239   - });
240   - if (res.result === RESPONSE_CODE.SUCCESS) {
241   - message.success(res.message);
242   - loadInvoiceData();
243   - }
244   - }}
245   - />,
246   - );
247   - return optBtns;
248   - },
249   - });
250   -
251   - return columns;
252   - };
253   -
254 127 useEffect(() => {
255 128 loadInvoiceData();
256 129 }, []);
... ... @@ -308,61 +181,6 @@ export default ({ invoiceId, setVisible, onClose }) =&gt; {
308 181 </ProCard>
309 182  
310 183 <Divider plain></Divider>
311   -
312   - <ProTable
313   - columns={bankStatementColumnsInit()}
314   - actionRef={actionRef}
315   - cardBordered
316   - pagination={{
317   - pageSize: 10,
318   - }}
319   - dataSource={relationBankStatements}
320   - columnsState={{
321   - persistenceKey: 'pro-table-singe-demos',
322   - persistenceType: 'localStorage',
323   - defaultValue: {
324   - option: { fixed: 'right', disable: true },
325   - },
326   - onChange(value) {
327   - console.log('value: ', value);
328   - },
329   - }}
330   - rowKey="id"
331   - search={false}
332   - options={{
333   - setting: {
334   - listsHeight: 400,
335   - },
336   - reload: false,
337   - }}
338   - form={{
339   - // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下
340   - syncToUrl: (values, type) => {
341   - if (type === 'get') {
342   - return {
343   - ...values,
344   - created_at: [values.startTime, values.endTime],
345   - };
346   - }
347   - return values;
348   - },
349   - }}
350   - dateFormatter="string"
351   - headerTitle="银行流水"
352   - scroll={{ x: 1400, y: 360 }}
353   - toolBarRender={() => [
354   - <Button
355   - key="button"
356   - icon={<PlusOutlined />}
357   - onClick={() => {
358   - setBankChooseModalVisible(true);
359   - }}
360   - type="primary"
361   - >
362   - 添加
363   - </Button>,
364   - ]}
365   - />
366 184 </ModalForm>
367 185  
368 186 {bankChooseModalVisible ? (
... ...
src/pages/Invoice/InvoiceVerification/index.tsx
... ... @@ -117,10 +117,10 @@ const InvoiceRecord = () =&gt; {
117 117 valueType: 'option',
118 118 key: 'option',
119 119 fixed: 'right',
120   - width: 120,
  120 + width: 80,
121 121 render: (text, record, _, action) => {
122 122 let btns = [];
123   - if (record.path?.includes('editBankStatement')) {
  123 + if (record.paths?.includes('editBankStatement')) {
124 124 btns.push(
125 125 <a
126 126 key="editable"
... ... @@ -133,7 +133,7 @@ const InvoiceRecord = () =&gt; {
133 133 );
134 134 }
135 135  
136   - if (record.path?.includes('deleteBankStatement')) {
  136 + if (record.paths?.includes('deleteBankStatement')) {
137 137 btns.push(
138 138 <ButtonConfirm
139 139 key="delete"
... ...
src/pages/Invoice/constant.tsx
... ... @@ -62,13 +62,19 @@ export const INVOICE_COLUMNS = [
62 62 },
63 63 {
64 64 title: '状态',
65   - dataIndex: 'status',
  65 + dataIndex: 'writeOffIdIsNull',
66 66 valueType: 'select',
67 67 width: 100,
68   - valueEnum: enumToProTableEnumValue({
69   - UNVERIFIED: '未核销',
70   - VERIFIED: '已核销',
71   - }),
  68 + valueEnum: {
  69 + true: {
  70 + text: '未核销',
  71 + status: false,
  72 + },
  73 + false: {
  74 + text: '已核销',
  75 + status: true,
  76 + },
  77 + },
72 78 hideInTable: true,
73 79 },
74 80 {
... ... @@ -170,6 +176,30 @@ export const BANK_STATEMENT_COLUMNS = [
170 176 editable: false,
171 177 },
172 178 {
  179 + dataIndex: 'statusText',
  180 + title: '状态',
  181 + hideInSearch: true,
  182 + valueType: 'text',
  183 + width: 100,
  184 + },
  185 + {
  186 + dataIndex: 'writeOffIdIsNull',
  187 + title: '状态',
  188 + hideInTable: true,
  189 + valueType: 'select',
  190 + valueEnum: {
  191 + true: {
  192 + text: '未核销',
  193 + status: false,
  194 + },
  195 + false: {
  196 + text: '已核销',
  197 + status: true,
  198 + },
  199 + },
  200 + width: 100,
  201 + },
  202 + {
173 203 dataIndex: 'serialNumber',
174 204 title: '流水号',
175 205 valueType: 'text',
... ...
src/pages/Order/index.tsx
... ... @@ -10,6 +10,7 @@ import {
10 10 postServiceConstCanApplyAfterInvoicingStatus,
11 11 postServiceInvoiceCancelApply,
12 12 postServiceOrderCancelSend,
  13 + postServiceOrderConfirmInvoice,
13 14 postServiceOrderGetCurrentOptNode,
14 15 postServiceOrderNoNeedSend,
15 16 postServiceOrderOrderCancel,
... ... @@ -2072,6 +2073,25 @@ const OrderPage = () =&gt; {
2072 2073 ''
2073 2074 )}
2074 2075  
  2076 + {optRecord.paths?.includes('confirmInvoice') ? (
  2077 + <ButtonConfirm
  2078 + className="p-0"
  2079 + title="已和客户确认发票??"
  2080 + text="确认发票"
  2081 + onConfirm={async () => {
  2082 + let body = { ids: [optRecord.id] };
  2083 + const data = await postServiceOrderConfirmInvoice({
  2084 + data: body,
  2085 + });
  2086 + if (data.result === RESPONSE_CODE.SUCCESS) {
  2087 + message.success(data.message);
  2088 + refreshTable();
  2089 + }
  2090 + }}
  2091 + />
  2092 + ) : (
  2093 + ''
  2094 + )}
2075 2095 {optRecord.paths?.includes('orderCancel') ? (
2076 2096 <ButtonConfirm
2077 2097 className="p-0"
... ... @@ -3846,6 +3866,32 @@ const OrderPage = () =&gt; {
3846 3866 ''
3847 3867 )}
3848 3868  
  3869 + {record.paths?.includes('confirmInvoice') ? (
  3870 + <ButtonConfirm
  3871 + className="p-0"
  3872 + title="已和客户确认发票?"
  3873 + text="确认发票"
  3874 + onConfirm={async () => {
  3875 + let body = {
  3876 + ids: [
  3877 + ...record.subOrderInformationLists.map(
  3878 + (subOrder) => subOrder.id,
  3879 + ),
  3880 + ],
  3881 + };
  3882 + const data = await postServiceOrderConfirmInvoice({
  3883 + data: body,
  3884 + });
  3885 + if (data.result === RESPONSE_CODE.SUCCESS) {
  3886 + message.success(data.message);
  3887 + refreshTable();
  3888 + }
  3889 + }}
  3890 + />
  3891 + ) : (
  3892 + ''
  3893 + )}
  3894 +
3849 3895 {record.paths?.includes('orderCancel') ? (
3850 3896 <ButtonConfirm
3851 3897 className="p-0"
... ...
src/services/definition.ts
... ... @@ -1472,6 +1472,7 @@ export interface InvoiceDto {
1472 1472 * 收款单位
1473 1473 */
1474 1474 payee?: string;
  1475 + payeeText?: string;
1475 1476 /**
1476 1477 * @description
1477 1478 * 购买方
... ... @@ -1500,6 +1501,8 @@ export interface InvoiceDto {
1500 1501 updateByName?: string;
1501 1502 /** @format date-time */
1502 1503 updateTime?: string;
  1504 + /** @format int64 */
  1505 + writeOffId?: number;
1503 1506 }
1504 1507  
1505 1508 export interface InvoiceRecordDTO {
... ... @@ -2782,6 +2785,9 @@ export interface QueryBankStatementDto {
2782 2785 status?: string;
2783 2786 /** @format int32 */
2784 2787 total?: number;
  2788 + /** @format int64 */
  2789 + writeOffId?: number;
  2790 + writeOffIdIsNull?: boolean;
2785 2791 }
2786 2792  
2787 2793 export interface QueryClientDto {
... ... @@ -3166,6 +3172,14 @@ export interface QueryUseOldInvoicingDto {
3166 3172 total?: number;
3167 3173 }
3168 3174  
  3175 +export interface QueryWriteOffRecordDto {
  3176 + /** @format int64 */
  3177 + id?: number;
  3178 + idIn?: Array<number>;
  3179 + /** @format int64 */
  3180 + invoiceId?: number;
  3181 +}
  3182 +
3169 3183 export interface ReissueInvoiceDto {
3170 3184 /** @format int64 */
3171 3185 invoiceId?: number;
... ...
src/services/request.ts
... ... @@ -63,7 +63,6 @@ import type {
63 63 MaterialUnitListRes,
64 64 MeasureUnitListRes,
65 65 MessageQueryDTO,
66   - ModelAndView,
67 66 OrderAddVO,
68 67 OrderAuditLogQueryVO,
69 68 OrderBaseInfoQueryVO,
... ... @@ -101,6 +100,7 @@ import type {
101 100 QueryProcureReturnBillDto,
102 101 QueryReportFormsDto,
103 102 QueryUseOldInvoicingDto,
  103 + QueryWriteOffRecordDto,
104 104 ReissueInvoiceDto,
105 105 ResearchGroupAddRequest,
106 106 ResearchGroupDeleteRequest,
... ... @@ -3232,7 +3232,9 @@ export interface GetErrorResponse {
3232 3232 * @description
3233 3233 * OK
3234 3234 */
3235   - 200: ModelAndView;
  3235 + 200: {
  3236 + [propertyName: string]: any;
  3237 + };
3236 3238 /**
3237 3239 * @description
3238 3240 * Unauthorized
... ... @@ -3253,9 +3255,9 @@ export interface GetErrorResponse {
3253 3255 export type GetErrorResponseSuccess = GetErrorResponse[200];
3254 3256 /**
3255 3257 * @description
3256   - * errorHtml
  3258 + * error
3257 3259 * @tags basic-error-controller
3258   - * @produces text/html
  3260 + * @produces *
3259 3261 */
3260 3262 export const getError = /* #__PURE__ */ (() => {
3261 3263 const method = 'get';
... ... @@ -3279,7 +3281,9 @@ export interface PutErrorResponse {
3279 3281 * @description
3280 3282 * OK
3281 3283 */
3282   - 200: ModelAndView;
  3284 + 200: {
  3285 + [propertyName: string]: any;
  3286 + };
3283 3287 /**
3284 3288 * @description
3285 3289 * Created
... ... @@ -3305,9 +3309,9 @@ export interface PutErrorResponse {
3305 3309 export type PutErrorResponseSuccess = PutErrorResponse[200];
3306 3310 /**
3307 3311 * @description
3308   - * errorHtml
  3312 + * error
3309 3313 * @tags basic-error-controller
3310   - * @produces text/html
  3314 + * @produces *
3311 3315 * @consumes application/json
3312 3316 */
3313 3317 export const putError = /* #__PURE__ */ (() => {
... ... @@ -3332,7 +3336,9 @@ export interface PostErrorResponse {
3332 3336 * @description
3333 3337 * OK
3334 3338 */
3335   - 200: ModelAndView;
  3339 + 200: {
  3340 + [propertyName: string]: any;
  3341 + };
3336 3342 /**
3337 3343 * @description
3338 3344 * Created
... ... @@ -3358,9 +3364,9 @@ export interface PostErrorResponse {
3358 3364 export type PostErrorResponseSuccess = PostErrorResponse[200];
3359 3365 /**
3360 3366 * @description
3361   - * errorHtml
  3367 + * error
3362 3368 * @tags basic-error-controller
3363   - * @produces text/html
  3369 + * @produces *
3364 3370 * @consumes application/json
3365 3371 */
3366 3372 export const postError = /* #__PURE__ */ (() => {
... ... @@ -3385,7 +3391,9 @@ export interface DeleteErrorResponse {
3385 3391 * @description
3386 3392 * OK
3387 3393 */
3388   - 200: ModelAndView;
  3394 + 200: {
  3395 + [propertyName: string]: any;
  3396 + };
3389 3397 /**
3390 3398 * @description
3391 3399 * No Content
... ... @@ -3406,9 +3414,9 @@ export interface DeleteErrorResponse {
3406 3414 export type DeleteErrorResponseSuccess = DeleteErrorResponse[200];
3407 3415 /**
3408 3416 * @description
3409   - * errorHtml
  3417 + * error
3410 3418 * @tags basic-error-controller
3411   - * @produces text/html
  3419 + * @produces *
3412 3420 */
3413 3421 export const deleteError = /* #__PURE__ */ (() => {
3414 3422 const method = 'delete';
... ... @@ -3432,7 +3440,9 @@ export interface OptionsErrorResponse {
3432 3440 * @description
3433 3441 * OK
3434 3442 */
3435   - 200: ModelAndView;
  3443 + 200: {
  3444 + [propertyName: string]: any;
  3445 + };
3436 3446 /**
3437 3447 * @description
3438 3448 * No Content
... ... @@ -3453,9 +3463,9 @@ export interface OptionsErrorResponse {
3453 3463 export type OptionsErrorResponseSuccess = OptionsErrorResponse[200];
3454 3464 /**
3455 3465 * @description
3456   - * errorHtml
  3466 + * error
3457 3467 * @tags basic-error-controller
3458   - * @produces text/html
  3468 + * @produces *
3459 3469 * @consumes application/json
3460 3470 */
3461 3471 export const optionsError = /* #__PURE__ */ (() => {
... ... @@ -3480,7 +3490,9 @@ export interface HeadErrorResponse {
3480 3490 * @description
3481 3491 * OK
3482 3492 */
3483   - 200: ModelAndView;
  3493 + 200: {
  3494 + [propertyName: string]: any;
  3495 + };
3484 3496 /**
3485 3497 * @description
3486 3498 * No Content
... ... @@ -3501,9 +3513,9 @@ export interface HeadErrorResponse {
3501 3513 export type HeadErrorResponseSuccess = HeadErrorResponse[200];
3502 3514 /**
3503 3515 * @description
3504   - * errorHtml
  3516 + * error
3505 3517 * @tags basic-error-controller
3506   - * @produces text/html
  3518 + * @produces *
3507 3519 * @consumes application/json
3508 3520 */
3509 3521 export const headError = /* #__PURE__ */ (() => {
... ... @@ -3528,7 +3540,9 @@ export interface PatchErrorResponse {
3528 3540 * @description
3529 3541 * OK
3530 3542 */
3531   - 200: ModelAndView;
  3543 + 200: {
  3544 + [propertyName: string]: any;
  3545 + };
3532 3546 /**
3533 3547 * @description
3534 3548 * No Content
... ... @@ -3549,9 +3563,9 @@ export interface PatchErrorResponse {
3549 3563 export type PatchErrorResponseSuccess = PatchErrorResponse[200];
3550 3564 /**
3551 3565 * @description
3552   - * errorHtml
  3566 + * error
3553 3567 * @tags basic-error-controller
3554   - * @produces text/html
  3568 + * @produces *
3555 3569 * @consumes application/json
3556 3570 */
3557 3571 export const patchError = /* #__PURE__ */ (() => {
... ... @@ -13443,6 +13457,60 @@ export const postServiceConstNotCanModifyInvoiceRecordStatus =
13443 13457 return request;
13444 13458 })();
13445 13459  
  13460 +/** @description response type for postServiceConstPayees */
  13461 +export interface PostServiceConstPayeesResponse {
  13462 + /**
  13463 + * @description
  13464 + * OK
  13465 + */
  13466 + 200: ServerResult;
  13467 + /**
  13468 + * @description
  13469 + * Created
  13470 + */
  13471 + 201: any;
  13472 + /**
  13473 + * @description
  13474 + * Unauthorized
  13475 + */
  13476 + 401: any;
  13477 + /**
  13478 + * @description
  13479 + * Forbidden
  13480 + */
  13481 + 403: any;
  13482 + /**
  13483 + * @description
  13484 + * Not Found
  13485 + */
  13486 + 404: any;
  13487 +}
  13488 +
  13489 +export type PostServiceConstPayeesResponseSuccess =
  13490 + PostServiceConstPayeesResponse[200];
  13491 +/**
  13492 + * @description
  13493 + * 开具类型
  13494 + * @tags front-const-controller
  13495 + * @produces *
  13496 + * @consumes application/json
  13497 + */
  13498 +export const postServiceConstPayees = /* #__PURE__ */ (() => {
  13499 + const method = 'post';
  13500 + const url = '/service/const/payees';
  13501 + function request(): Promise<PostServiceConstPayeesResponseSuccess> {
  13502 + return requester(request.url, {
  13503 + method: request.method,
  13504 + }) as unknown as Promise<PostServiceConstPayeesResponseSuccess>;
  13505 + }
  13506 +
  13507 + /** http method */
  13508 + request.method = method;
  13509 + /** request url */
  13510 + request.url = url;
  13511 + return request;
  13512 +})();
  13513 +
13446 13514 /** @description response type for postServiceConstProcureReturnBills */
13447 13515 export interface PostServiceConstProcureReturnBillsResponse {
13448 13516 /**
... ... @@ -14639,6 +14707,77 @@ export const postServiceInvoiceGetInvoicingAccount = /* #__PURE__ */ (() =&gt; {
14639 14707 return request;
14640 14708 })();
14641 14709  
  14710 +/** @description request parameter type for postServiceInvoiceGetWriteOffRecord */
  14711 +export interface PostServiceInvoiceGetWriteOffRecordOption {
  14712 + /**
  14713 + * @description
  14714 + * dto
  14715 + */
  14716 + body: {
  14717 + /**
  14718 + @description
  14719 + dto */
  14720 + dto: QueryWriteOffRecordDto;
  14721 + };
  14722 +}
  14723 +
  14724 +/** @description response type for postServiceInvoiceGetWriteOffRecord */
  14725 +export interface PostServiceInvoiceGetWriteOffRecordResponse {
  14726 + /**
  14727 + * @description
  14728 + * OK
  14729 + */
  14730 + 200: ServerResult;
  14731 + /**
  14732 + * @description
  14733 + * Created
  14734 + */
  14735 + 201: any;
  14736 + /**
  14737 + * @description
  14738 + * Unauthorized
  14739 + */
  14740 + 401: any;
  14741 + /**
  14742 + * @description
  14743 + * Forbidden
  14744 + */
  14745 + 403: any;
  14746 + /**
  14747 + * @description
  14748 + * Not Found
  14749 + */
  14750 + 404: any;
  14751 +}
  14752 +
  14753 +export type PostServiceInvoiceGetWriteOffRecordResponseSuccess =
  14754 + PostServiceInvoiceGetWriteOffRecordResponse[200];
  14755 +/**
  14756 + * @description
  14757 + * 获取核销记录
  14758 + * @tags 发票
  14759 + * @produces *
  14760 + * @consumes application/json
  14761 + */
  14762 +export const postServiceInvoiceGetWriteOffRecord = /* #__PURE__ */ (() => {
  14763 + const method = 'post';
  14764 + const url = '/service/invoice/getWriteOffRecord';
  14765 + function request(
  14766 + option: PostServiceInvoiceGetWriteOffRecordOption,
  14767 + ): Promise<PostServiceInvoiceGetWriteOffRecordResponseSuccess> {
  14768 + return requester(request.url, {
  14769 + method: request.method,
  14770 + ...option,
  14771 + }) as unknown as Promise<PostServiceInvoiceGetWriteOffRecordResponseSuccess>;
  14772 + }
  14773 +
  14774 + /** http method */
  14775 + request.method = method;
  14776 + /** request url */
  14777 + request.url = url;
  14778 + return request;
  14779 +})();
  14780 +
14642 14781 /** @description request parameter type for postServiceInvoiceImportInvoiceDetails */
14643 14782 export interface PostServiceInvoiceImportInvoiceDetailsOption {
14644 14783 /**
... ... @@ -16332,6 +16471,77 @@ export const postServiceOrderCancelSend = /* #__PURE__ */ (() =&gt; {
16332 16471 return request;
16333 16472 })();
16334 16473  
  16474 +/** @description request parameter type for postServiceOrderConfirmInvoice */
  16475 +export interface PostServiceOrderConfirmInvoiceOption {
  16476 + /**
  16477 + * @description
  16478 + * subIds
  16479 + */
  16480 + query: {
  16481 + /**
  16482 + @description
  16483 + subIds */
  16484 + subIds: Array<number>;
  16485 + };
  16486 +}
  16487 +
  16488 +/** @description response type for postServiceOrderConfirmInvoice */
  16489 +export interface PostServiceOrderConfirmInvoiceResponse {
  16490 + /**
  16491 + * @description
  16492 + * OK
  16493 + */
  16494 + 200: ServerResult;
  16495 + /**
  16496 + * @description
  16497 + * Created
  16498 + */
  16499 + 201: any;
  16500 + /**
  16501 + * @description
  16502 + * Unauthorized
  16503 + */
  16504 + 401: any;
  16505 + /**
  16506 + * @description
  16507 + * Forbidden
  16508 + */
  16509 + 403: any;
  16510 + /**
  16511 + * @description
  16512 + * Not Found
  16513 + */
  16514 + 404: any;
  16515 +}
  16516 +
  16517 +export type PostServiceOrderConfirmInvoiceResponseSuccess =
  16518 + PostServiceOrderConfirmInvoiceResponse[200];
  16519 +/**
  16520 + * @description
  16521 + * 确认发票
  16522 + * @tags 内部订单
  16523 + * @produces *
  16524 + * @consumes application/json
  16525 + */
  16526 +export const postServiceOrderConfirmInvoice = /* #__PURE__ */ (() => {
  16527 + const method = 'post';
  16528 + const url = '/service/order/confirmInvoice';
  16529 + function request(
  16530 + option: PostServiceOrderConfirmInvoiceOption,
  16531 + ): Promise<PostServiceOrderConfirmInvoiceResponseSuccess> {
  16532 + return requester(request.url, {
  16533 + method: request.method,
  16534 + ...option,
  16535 + }) as unknown as Promise<PostServiceOrderConfirmInvoiceResponseSuccess>;
  16536 + }
  16537 +
  16538 + /** http method */
  16539 + request.method = method;
  16540 + /** request url */
  16541 + request.url = url;
  16542 + return request;
  16543 +})();
  16544 +
16335 16545 /** @description request parameter type for postServiceOrderConfirmReceipt */
16336 16546 export interface PostServiceOrderConfirmReceiptOption {
16337 16547 /**
... ...