Commit 3498a23d251b2de57c5e4eb41e4a11a402ba087e
Merge branch 'invoice'
# Conflicts: # src/pages/Order/index.tsx # src/services/definition.ts # src/services/request.ts
Showing
20 changed files
with
2464 additions
and
176 deletions
.idea/.name
0 → 100644
1 | +front_project | ... | ... |
.idea/UniappTool.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<project version="4"> | |
3 | + <component name="cn.fjdmy.uniapp.UniappProjectDataService"> | |
4 | + <option name="generalBasePath" value="$PROJECT_DIR$" /> | |
5 | + <option name="manifestPath" value="$PROJECT_DIR$/manifest.json" /> | |
6 | + <option name="pagesPath" value="$PROJECT_DIR$/pages.json" /> | |
7 | + <option name="scanNum" value="1" /> | |
8 | + <option name="type" value="store" /> | |
9 | + </component> | |
10 | +</project> | ... | ... |
.idea/codeStyles/codeStyleConfig.xml
0 → 100644
.idea/rcb-settings.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<project version="4"> | |
3 | + <component name="ReactBuddyPluginProjectSettings"> | |
4 | + <option name="devServerConfigs"> | |
5 | + <DevServerState> | |
6 | + <option name="packageJsonPath" value="$PROJECT_DIR$/package.json" /> | |
7 | + <option name="scriptName" value="build" /> | |
8 | + </DevServerState> | |
9 | + </option> | |
10 | + </component> | |
11 | +</project> | ... | ... |
src/pages/Invoice/components/Invoice.tsx
0 → 100644
1 | +import styled from 'styled-components'; | |
2 | +const InvoiceTmpDiv = styled.div` | |
3 | + font-size: 12px; | |
4 | + width: 1120px; | |
5 | + .title { | |
6 | + font-size: 26px; | |
7 | + color: #b16363; | |
8 | + text-align: center; | |
9 | + line-height: 56px; | |
10 | + padding-top: 0; | |
11 | + } | |
12 | + .extra { | |
13 | + color: #b15b16; | |
14 | + .content { | |
15 | + color: #181818; | |
16 | + } | |
17 | + } | |
18 | + .height84 { | |
19 | + height: 110px; | |
20 | + } | |
21 | + .row { | |
22 | + border: 2px solid #b16363; | |
23 | + border-bottom: none; | |
24 | + color: #b15b16; | |
25 | + .content { | |
26 | + color: #181818; | |
27 | + } | |
28 | + } | |
29 | + .last-row { | |
30 | + .content { | |
31 | + color: #181818; | |
32 | + } | |
33 | + color: #b15b16; | |
34 | + border-top: 2px solid #b16363; | |
35 | + } | |
36 | + .label { | |
37 | + width: 78px; | |
38 | + display: inline-block; | |
39 | + text-align-last: justify; | |
40 | + text-align: justify; | |
41 | + } | |
42 | + .longLabel { | |
43 | + width: 178px; | |
44 | + display: inline-block; | |
45 | + text-align-last: justify; | |
46 | + text-align: justify; | |
47 | + } | |
48 | + .title-label { | |
49 | + width: 52px; | |
50 | + } | |
51 | +`; | |
52 | +const Row = styled.div` | |
53 | + .col_1 { | |
54 | + width: 2.65%; | |
55 | + borderleft: none; | |
56 | + } | |
57 | + .col_4 { | |
58 | + width: 3.75%; | |
59 | + } | |
60 | + .col_9 { | |
61 | + width: 7.4%; | |
62 | + } | |
63 | + .col_2 { | |
64 | + width: 8.33%; | |
65 | + } | |
66 | + .col_3 { | |
67 | + width: 12.5%; | |
68 | + } | |
69 | + .col_5 { | |
70 | + width: 20.83%; | |
71 | + } | |
72 | + .col_6 { | |
73 | + width: 42.5%; | |
74 | + } | |
75 | + .col_7 { | |
76 | + width: 29.16%; | |
77 | + } | |
78 | + .col_8 { | |
79 | + width: 33.33%; | |
80 | + } | |
81 | + .col_14 { | |
82 | + width: 58.33%; | |
83 | + } | |
84 | + .col_15 { | |
85 | + width: 42.5%; | |
86 | + } | |
87 | + .col_17 { | |
88 | + width: 70.83%; | |
89 | + } | |
90 | + .col_18 { | |
91 | + width: 100%; | |
92 | + } | |
93 | + .col_24 { | |
94 | + width: 100%; | |
95 | + } | |
96 | +`; | |
97 | +const Col = styled.span` | |
98 | + display: inline-block; | |
99 | + padding: 8px; | |
100 | + box-sizing: border-box; | |
101 | + vertical-align: middle; | |
102 | + border-left: 2px solid #b16363; | |
103 | + height: 100%; | |
104 | + &.no-border { | |
105 | + border-left: none; | |
106 | + } | |
107 | + .text-center { | |
108 | + text-align: center; | |
109 | + border-left: none; | |
110 | + border-right: none; | |
111 | + } | |
112 | + &.transparent-border { | |
113 | + border-left: 2px solid rgba(0, 0, 0, 0); | |
114 | + } | |
115 | + &.invoice-number { | |
116 | + border-left: none; | |
117 | + color: #b16363; | |
118 | + padding: 0 0 0 800px; | |
119 | + font-size: 14px; | |
120 | + } | |
121 | +`; | |
122 | +const UnderLine = styled.div` | |
123 | + border: 2px solid #b16363; | |
124 | + width: 325px; | |
125 | + height: 8px; | |
126 | + margin: -1% 0 2% 35%; | |
127 | + border-left: none; | |
128 | + border-right: none; | |
129 | +`; | |
130 | +const InvoiceInfo = styled.span` | |
131 | + color: black; | |
132 | +`; | |
133 | +const TitleDescription = styled.div` | |
134 | + margin-top: 4.2%; | |
135 | +`; | |
136 | +const ProjectContainer = styled.div` | |
137 | + width: 100%; | |
138 | + height: 160px; | |
139 | + border-top: 2px solid #b16363; | |
140 | + border-right: 2px solid #b16363; | |
141 | + border-left: 2px solid #b16363; | |
142 | + overflow: auto; | |
143 | + .single-project { | |
144 | + width: 100%; | |
145 | + height: 30px; | |
146 | + } | |
147 | +`; | |
148 | +export default ({ data }) => { | |
149 | + return ( | |
150 | + <div> | |
151 | + <InvoiceTmpDiv> | |
152 | + <Row> | |
153 | + <Col className="col_18 invoice-number"> | |
154 | + 发票号码:<InvoiceInfo>{data.invoiceNumber}</InvoiceInfo> | |
155 | + </Col> | |
156 | + <Col className="title col_18 no-border"> | |
157 | + 电子发票(增值税专用发票) | |
158 | + </Col> | |
159 | + <UnderLine className="UnderLine"> | |
160 | + <div></div> | |
161 | + </UnderLine> | |
162 | + </Row> | |
163 | + <Row className="row height84"> | |
164 | + <Col className="col_1 no-border">购买方信息</Col> | |
165 | + <Col className="col_15"> | |
166 | + <TitleDescription> | |
167 | + <span className="label">名称</span>: | |
168 | + <span className="content">{data.partyAName}</span> | |
169 | + </TitleDescription> | |
170 | + <TitleDescription> | |
171 | + <span className="longLabel">统一社会信用代码/纳税人识别号</span>: | |
172 | + <span className="content">{data.partyATaxid}</span> | |
173 | + </TitleDescription> | |
174 | + </Col> | |
175 | + <Col className="col_1">销售方信息</Col> | |
176 | + <Col className="col_6"> | |
177 | + <TitleDescription> | |
178 | + <span className="label">名称</span>: | |
179 | + <span className="content">{data.partyBName}</span> | |
180 | + </TitleDescription> | |
181 | + <TitleDescription> | |
182 | + <span className="longLabel">统一社会信用代码/纳税人识别号</span>: | |
183 | + <span className="content">{data.partyBTaxid}</span> | |
184 | + </TitleDescription> | |
185 | + </Col> | |
186 | + </Row> | |
187 | + <Row className="row"> | |
188 | + <Col className="col_7 no-border"> | |
189 | + <div className="text-center">项目名称</div> | |
190 | + </Col> | |
191 | + <Col className="col_5"> | |
192 | + <div className="text-center">规格型号</div> | |
193 | + </Col> | |
194 | + <Col className=""> | |
195 | + <div className="text-center">单位</div> | |
196 | + </Col> | |
197 | + <Col className=""> | |
198 | + <div className="text-center">数量</div> | |
199 | + </Col> | |
200 | + <Col className="col_2"> | |
201 | + <div className="text-center">单价</div> | |
202 | + </Col> | |
203 | + <Col className="col_3"> | |
204 | + <div className="text-center">金额</div> | |
205 | + </Col> | |
206 | + <Col className=""> | |
207 | + <div className="text-center">税率/征收率</div> | |
208 | + </Col> | |
209 | + <Col className="col_2"> | |
210 | + <div className="text-center">税额</div> | |
211 | + </Col> | |
212 | + </Row> | |
213 | + <Row> | |
214 | + <ProjectContainer> | |
215 | + {data && | |
216 | + data.invoiceDetails?.map((item) => { | |
217 | + const { | |
218 | + taxPrice, | |
219 | + totalPrice, | |
220 | + specification, | |
221 | + projectName, | |
222 | + quantity, | |
223 | + price, | |
224 | + taxRate, | |
225 | + unit, | |
226 | + } = item; | |
227 | + return ( | |
228 | + <div className="single-project" key={item.id}> | |
229 | + <Col | |
230 | + className="col_7 transparent-border" | |
231 | + key={'projectName'} | |
232 | + > | |
233 | + <div className="text-center">{projectName}</div> | |
234 | + </Col> | |
235 | + <Col | |
236 | + className="col_5 transparent-border" | |
237 | + key={'specification'} | |
238 | + > | |
239 | + <div className="text-center">{specification}</div> | |
240 | + </Col> | |
241 | + <Col className="col_4 transparent-border" key={'unit'}> | |
242 | + <div className="text-center">{unit}</div> | |
243 | + </Col> | |
244 | + <Col className="col_4 transparent-border" key={'quantity'}> | |
245 | + <div className="text-center">{quantity}</div> | |
246 | + </Col> | |
247 | + <Col className="col_2 transparent-border" key={'price'}> | |
248 | + <div className="text-center">{price}</div> | |
249 | + </Col> | |
250 | + <Col | |
251 | + className="col_3 transparent-border" | |
252 | + key={'totalPrice'} | |
253 | + > | |
254 | + <div className="text-center">{totalPrice}</div> | |
255 | + </Col> | |
256 | + <Col className="col_9 transparent-border" key={'taxRate'}> | |
257 | + <div className="text-center">{taxRate}</div> | |
258 | + </Col> | |
259 | + <Col className="col_2 transparent-border" key={'taxPrice'}> | |
260 | + <div className="text-center">{taxPrice}</div> | |
261 | + </Col> | |
262 | + </div> | |
263 | + ); | |
264 | + })} | |
265 | + </ProjectContainer> | |
266 | + </Row> | |
267 | + <Row className="row"> | |
268 | + <Col className="col_15 no-border"> | |
269 | + 价税合计(大写) | |
270 | + <InvoiceInfo>{data.totalPriceText}</InvoiceInfo> | |
271 | + </Col> | |
272 | + <Col className="no-border"> | |
273 | + (小写)<InvoiceInfo>¥{data.totalPrice}</InvoiceInfo> | |
274 | + </Col> | |
275 | + </Row> | |
276 | + <Row className="row height84"> | |
277 | + <Col className="col_1 no-border">备注</Col> | |
278 | + <Col className="col_7"> | |
279 | + <InvoiceInfo>{data.comment}</InvoiceInfo> | |
280 | + </Col> | |
281 | + </Row> | |
282 | + <Row className="last-row"> | |
283 | + <Col className="col_6 no-border"> | |
284 | + 开票人:<InvoiceInfo>{data.invoicingPerson}</InvoiceInfo> | |
285 | + </Col> | |
286 | + </Row> | |
287 | + </InvoiceTmpDiv> | |
288 | + </div> | |
289 | + ); | |
290 | +}; | ... | ... |
src/pages/Invoice/components/InvoiceDetailImportModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { postServiceInvoiceImportInvoiceDetails } from '@/services'; | |
3 | +import { ModalForm, ProFormUploadDragger } from '@ant-design/pro-components'; | |
4 | +import { Button, Form, message } from 'antd'; | |
5 | + | |
6 | +export default ({ recordId }) => { | |
7 | + const [form] = Form.useForm(); | |
8 | + return ( | |
9 | + <ModalForm | |
10 | + title="新建表单" | |
11 | + trigger={<Button type="primary">导入明细</Button>} | |
12 | + form={form} | |
13 | + autoFocusFirstInput | |
14 | + modalProps={{ | |
15 | + destroyOnClose: true, | |
16 | + onCancel: () => console.log('run'), | |
17 | + }} | |
18 | + submitTimeout={2000} | |
19 | + onFinish={async (values) => { | |
20 | + const formData = new FormData(); | |
21 | + // console.log(fileList[0] as RcFile) | |
22 | + // formData.append('file', fileList[0] as RcFile); | |
23 | + formData.append('invoiceRecordId', recordId); | |
24 | + formData.append('detailsExcel', values.detailsExcel[0].originFileObj); | |
25 | + // You can use any AJAX library you like | |
26 | + const res = await postServiceInvoiceImportInvoiceDetails({ | |
27 | + data: formData, | |
28 | + headers: { | |
29 | + 'Content-Type': | |
30 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | |
31 | + }, | |
32 | + }); | |
33 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
34 | + message.success('导入成功'); | |
35 | + return true; | |
36 | + } | |
37 | + }} | |
38 | + > | |
39 | + <ProFormUploadDragger name="detailsExcel" label="导入明细表" /> | |
40 | + </ModalForm> | |
41 | + ); | |
42 | +}; | ... | ... |
src/pages/Invoice/components/InvoiceDetailTable.tsx
0 → 100644
1 | +import InvoiceDetailImportModal from '@/pages/Invoice/components/InvoiceDetailImportModal'; | |
2 | +import { InvoiceProjectSelect } from '@/pages/Invoice/components/InvoiceProjectSelect'; | |
3 | +import { | |
4 | + ActionType, | |
5 | + EditableProTable, | |
6 | + ProColumns, | |
7 | +} from '@ant-design/pro-components'; | |
8 | +import { useEffect, useRef, useState } from 'react'; | |
9 | + | |
10 | +export default ({ recordId, details, updateDetails, readOnly }) => { | |
11 | + const [editableKeys, setEditableRowKeys] = useState([]); | |
12 | + const [invoiceProject, setInvoiceProject] = useState({}); | |
13 | + const ref = useRef<ActionType>(); | |
14 | + useEffect(() => { | |
15 | + updateDetails(details); | |
16 | + }, []); | |
17 | + | |
18 | + useEffect(() => { | |
19 | + setEditableRowKeys(details?.map((item) => item.tid)); | |
20 | + }, [details]); | |
21 | + const columns: ProColumns[] = [ | |
22 | + { | |
23 | + title: '项目名称', | |
24 | + dataIndex: 'projectName', | |
25 | + width: 200, | |
26 | + ellipsis: true, | |
27 | + readonly: readOnly, | |
28 | + renderFormItem: () => { | |
29 | + return ( | |
30 | + <InvoiceProjectSelect | |
31 | + setInvoiceProject={setInvoiceProject} | |
32 | + readOnly={readOnly} | |
33 | + /> | |
34 | + ); | |
35 | + }, | |
36 | + }, | |
37 | + { | |
38 | + title: '规格型号', | |
39 | + readonly: readOnly, | |
40 | + dataIndex: 'specification', | |
41 | + valueType: 'text', | |
42 | + ellipsis: true, | |
43 | + }, | |
44 | + { | |
45 | + title: '单位', | |
46 | + readonly: readOnly, | |
47 | + dataIndex: 'unit', | |
48 | + valueType: 'text', | |
49 | + ellipsis: true, | |
50 | + }, | |
51 | + { | |
52 | + title: '数量', | |
53 | + readonly: readOnly, | |
54 | + dataIndex: 'quantity', | |
55 | + valueType: 'digit', | |
56 | + ellipsis: true, | |
57 | + }, | |
58 | + { | |
59 | + title: '单价', | |
60 | + readonly: readOnly, | |
61 | + dataIndex: 'price', | |
62 | + valueType: 'digit', | |
63 | + ellipsis: true, | |
64 | + }, | |
65 | + { | |
66 | + title: '金额', | |
67 | + readonly: readOnly, | |
68 | + dataIndex: 'totalPrice', | |
69 | + valueType: 'digit', | |
70 | + ellipsis: true, | |
71 | + }, | |
72 | + { | |
73 | + title: '税率/征收率', | |
74 | + readonly: true, | |
75 | + dataIndex: 'taxRate', | |
76 | + valueType: () => ({ | |
77 | + type: 'percent', | |
78 | + }), | |
79 | + ellipsis: true, | |
80 | + }, | |
81 | + { | |
82 | + title: '税额', | |
83 | + readonly: true, | |
84 | + dataIndex: 'taxPrice', | |
85 | + valueType: 'digit', | |
86 | + ellipsis: true, | |
87 | + }, | |
88 | + { | |
89 | + title: '操作', | |
90 | + valueType: 'option', | |
91 | + width: 100, | |
92 | + render: () => { | |
93 | + return null; | |
94 | + }, | |
95 | + }, | |
96 | + ]; | |
97 | + | |
98 | + return ( | |
99 | + <> | |
100 | + <EditableProTable | |
101 | + columns={columns} | |
102 | + actionRef={ref} | |
103 | + rowKey="tid" | |
104 | + scroll={{ | |
105 | + x: 960, | |
106 | + }} | |
107 | + value={details} | |
108 | + controlled={true} | |
109 | + recordCreatorProps={ | |
110 | + readOnly | |
111 | + ? false | |
112 | + : { | |
113 | + newRecordType: 'dataSource', | |
114 | + record: () => ({ | |
115 | + tid: Date.now(), | |
116 | + }), | |
117 | + } | |
118 | + } | |
119 | + toolBarRender={() => { | |
120 | + return [ | |
121 | + <InvoiceDetailImportModal key={'import'} recordId={recordId} />, | |
122 | + ]; | |
123 | + }} | |
124 | + editable={{ | |
125 | + type: 'multiple', | |
126 | + editableKeys, | |
127 | + actionRender: (row, config, defaultDoms) => { | |
128 | + return [defaultDoms.delete]; | |
129 | + }, | |
130 | + | |
131 | + onValuesChange: (record, recordList) => { | |
132 | + //修改recordList中tid为record.tid的元素,将它的specification属性设置为invoiceProject的specification属性 | |
133 | + const records = recordList.map((item) => { | |
134 | + if ( | |
135 | + record && | |
136 | + item.tid === record.tid && | |
137 | + item.projectName !== | |
138 | + '*' + | |
139 | + invoiceProject.productAndServiceCatagoryAbbreviation + | |
140 | + '*' + | |
141 | + invoiceProject?.name && | |
142 | + item.specification !== invoiceProject?.specification | |
143 | + ) { | |
144 | + console.log(item.projectName); | |
145 | + console.log(invoiceProject?.name); | |
146 | + item.projectName = | |
147 | + '*' + | |
148 | + invoiceProject.productAndServiceCatagoryAbbreviation + | |
149 | + '*' + | |
150 | + invoiceProject?.name; | |
151 | + item.specification = invoiceProject?.specification; | |
152 | + item.unit = invoiceProject?.unit; | |
153 | + item.taxRate = invoiceProject?.taxRate * 100; | |
154 | + } | |
155 | + return item; | |
156 | + }); | |
157 | + updateDetails(records); | |
158 | + }, | |
159 | + }} | |
160 | + /> | |
161 | + {/*{<ProCard title="表格数据" headerBordered collapsible defaultCollapsed> | |
162 | + <ProFormField | |
163 | + ignoreFormItem | |
164 | + fieldProps={{ | |
165 | + style: { | |
166 | + width: '100%', | |
167 | + }, | |
168 | + }} | |
169 | + mode="read" | |
170 | + valueType="jsonCode" | |
171 | + text={JSON.stringify(details)} | |
172 | + /> | |
173 | + </ProCard>}*/} | |
174 | + </> | |
175 | + ); | |
176 | +}; | ... | ... |
src/pages/Invoice/components/InvoiceModal.tsx
0 → 100644
1 | +import Invoice from '@/pages/Invoice/components/Invoice'; | |
2 | +import { postServiceInvoiceGetInvoiceRecord } from '@/services'; | |
3 | +import { ModalForm } from '@ant-design/pro-components'; | |
4 | +import { Form } from 'antd'; | |
5 | +import { useEffect, useState } from 'react'; | |
6 | + | |
7 | +export default ({ recordId, getRecord, button }) => { | |
8 | + const [data, setData] = useState<any>({}); | |
9 | + useEffect(() => { | |
10 | + const getData = async () => { | |
11 | + let ret = await postServiceInvoiceGetInvoiceRecord({ | |
12 | + query: { | |
13 | + id: recordId, | |
14 | + }, | |
15 | + }); | |
16 | + setData(ret.data); | |
17 | + }; | |
18 | + if (recordId) { | |
19 | + getData(); | |
20 | + } | |
21 | + }, []); | |
22 | + const [form] = Form.useForm(); | |
23 | + return ( | |
24 | + <ModalForm | |
25 | + title="预览发票" | |
26 | + trigger={button ? button : <a type="primary">预览</a>} | |
27 | + onOpenChange={(open) => { | |
28 | + if (open && getRecord) { | |
29 | + setData(getRecord()); | |
30 | + } | |
31 | + }} | |
32 | + width={1200} | |
33 | + form={form} | |
34 | + autoFocusFirstInput | |
35 | + modalProps={{ | |
36 | + destroyOnClose: true, | |
37 | + }} | |
38 | + > | |
39 | + <hr /> | |
40 | + <Invoice data={data} /> | |
41 | + </ModalForm> | |
42 | + ); | |
43 | +}; | ... | ... |
src/pages/Invoice/components/InvoiceProjectSelect.tsx
0 → 100644
1 | +import { postServiceConstListInvoiceDetailNames } from '@/services'; | |
2 | +import { Select, Tooltip } from 'antd'; | |
3 | +import { useState } from 'react'; | |
4 | + | |
5 | +export const InvoiceProjectSelect = ({ | |
6 | + readOnly, | |
7 | + value, | |
8 | + onChange, | |
9 | + setInvoiceProject, | |
10 | +}) => { | |
11 | + const [options, setOptions] = useState<any[]>([]); | |
12 | + // 定义防抖函数 | |
13 | + let timeoutId = null; | |
14 | + const fetchOptions = async (keywords) => { | |
15 | + clearTimeout(timeoutId); | |
16 | + timeoutId = setTimeout(async () => { | |
17 | + const res = await postServiceConstListInvoiceDetailNames({ | |
18 | + data: { | |
19 | + nameLike: keywords, | |
20 | + }, | |
21 | + }); | |
22 | + const data = res.data; | |
23 | + console.log('invoiceProject' + JSON.stringify(data)); | |
24 | + setOptions( | |
25 | + data.map((item) => { | |
26 | + return { | |
27 | + label: | |
28 | + '*' + | |
29 | + item.productAndServiceCatagoryAbbreviation + | |
30 | + '*' + | |
31 | + item?.name, | |
32 | + value: item.id, | |
33 | + ...item, | |
34 | + }; | |
35 | + }), | |
36 | + ); | |
37 | + // 这里可以放置实际的搜索逻辑,比如发起网络请求等 | |
38 | + }, 500); // 设置延迟时间,单位毫秒 | |
39 | + }; | |
40 | + | |
41 | + return readOnly ? ( | |
42 | + <Tooltip title={value}>{value}</Tooltip> | |
43 | + ) : ( | |
44 | + <Select | |
45 | + key="project" | |
46 | + /*readonly={readonly}*/ | |
47 | + showSearch | |
48 | + placeholder="请选择开票项目" | |
49 | + filterOption={(input, option) => (option?.label ?? '').includes(input)} | |
50 | + onChange={(e) => { | |
51 | + setInvoiceProject(options.find((item) => item.value === e)); | |
52 | + onChange(e); | |
53 | + }} | |
54 | + defaultValue={value} | |
55 | + options={options} | |
56 | + onSearch={(e) => { | |
57 | + fetchOptions(e); | |
58 | + }} | |
59 | + /> | |
60 | + ); | |
61 | +}; | ... | ... |
src/pages/Invoice/components/InvoiceRecordDetailModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import InvoiceDetailTable from '@/pages/Invoice/components/InvoiceDetailTable'; | |
3 | +import { | |
4 | + postServiceConstGetPayeeEnum, | |
5 | + postServiceConstInvoiceType, | |
6 | + postServiceConstInvoicingType, | |
7 | + postServiceInvoiceGetInvoiceRecord, | |
8 | + postServiceInvoiceModifyRecord, | |
9 | +} from '@/services'; | |
10 | +import { enumToSelect } from '@/utils'; | |
11 | +import { | |
12 | + ModalForm, | |
13 | + ProCard, | |
14 | + ProForm, | |
15 | + ProFormFieldSet, | |
16 | + ProFormInstance, | |
17 | + ProFormList, | |
18 | + ProFormSelect, | |
19 | + ProFormText, | |
20 | + ProFormTextArea, | |
21 | +} from '@ant-design/pro-components'; | |
22 | +import { Button, Divider, Form, Space, message } from 'antd'; | |
23 | +import { useEffect, useRef, useState } from 'react'; | |
24 | + | |
25 | +export default ({ id, setVisible }) => { | |
26 | + const [readOnly, setReadOnly] = useState(true); | |
27 | + const [detailTableData, setDetailTableData] = useState([]); | |
28 | + const [payees, setPayees] = useState([]); | |
29 | + const [payeeNameOptions, setPayeeNameOptions] = useState([]); | |
30 | + const formRef = useRef<ProFormInstance>(); | |
31 | + const [form] = Form.useForm(); | |
32 | + | |
33 | + useEffect(() => { | |
34 | + console.log('id' + id); | |
35 | + const getPayees = async () => { | |
36 | + let res = await postServiceConstGetPayeeEnum(); | |
37 | + setPayees(res.data); | |
38 | + let payeeNameOptions = res.data.map((item) => { | |
39 | + return { | |
40 | + label: item.payeeName, | |
41 | + value: item.payeeName, | |
42 | + }; | |
43 | + }); | |
44 | + setPayeeNameOptions(payeeNameOptions); | |
45 | + }; | |
46 | + getPayees(); | |
47 | + }, []); | |
48 | + const getRecord = async (id) => { | |
49 | + let ret = await postServiceInvoiceGetInvoiceRecord({ | |
50 | + query: { | |
51 | + id: id, | |
52 | + }, | |
53 | + }); | |
54 | + const updatedInvoiceDetails = ret.data.invoiceDetails?.map( | |
55 | + (item, index) => ({ | |
56 | + ...item, // 保留原有属性 | |
57 | + tid: index + 1, // 添加tid属性,这里以T开头,后面跟索引+1,仅作示例,实际可根据需求生成tid | |
58 | + }), | |
59 | + ); | |
60 | + setDetailTableData(updatedInvoiceDetails); | |
61 | + }; | |
62 | + useEffect(() => { | |
63 | + getRecord(id); | |
64 | + }, []); | |
65 | + | |
66 | + const updateDetails = (values) => { | |
67 | + setDetailTableData(values); | |
68 | + }; | |
69 | + return ( | |
70 | + <> | |
71 | + <Space> | |
72 | + <ModalForm | |
73 | + open | |
74 | + title="发票详情" | |
75 | + formRef={formRef} | |
76 | + request={async () => { | |
77 | + let ret = await postServiceInvoiceGetInvoiceRecord({ | |
78 | + query: { | |
79 | + id: id, | |
80 | + }, | |
81 | + }); | |
82 | + return ret.data; | |
83 | + }} | |
84 | + submitter={{ | |
85 | + render: () => { | |
86 | + return [ | |
87 | + <Button | |
88 | + type={readOnly ? 'primary' : 'default'} | |
89 | + key="ok" | |
90 | + onClick={() => { | |
91 | + setReadOnly(!readOnly); | |
92 | + }} | |
93 | + > | |
94 | + {readOnly ? '编辑' : '取消编辑'} | |
95 | + </Button>, | |
96 | + <> | |
97 | + {!readOnly && ( | |
98 | + <Button | |
99 | + type="primary" | |
100 | + key="submit" | |
101 | + onClick={async () => { | |
102 | + const result = await postServiceInvoiceModifyRecord({ | |
103 | + data: { | |
104 | + ...form.getFieldsValue(), | |
105 | + invoiceDetails: [...detailTableData], | |
106 | + }, | |
107 | + }); | |
108 | + if (result.result === RESPONSE_CODE.SUCCESS) { | |
109 | + message.success('提交成功'); | |
110 | + } | |
111 | + setVisible(false); | |
112 | + return true; | |
113 | + }} | |
114 | + > | |
115 | + 提交 | |
116 | + </Button> | |
117 | + )} | |
118 | + </>, | |
119 | + /*<Button | |
120 | + type={'default'} | |
121 | + key="ok" | |
122 | + onClick={() => { | |
123 | + setVisible(false) | |
124 | + }} | |
125 | + > | |
126 | + 取消 | |
127 | + </Button>,*/ | |
128 | + ]; | |
129 | + }, | |
130 | + }} | |
131 | + width={1200} | |
132 | + form={form} | |
133 | + autoFocusFirstInput | |
134 | + modalProps={{ | |
135 | + destroyOnClose: true, | |
136 | + onCancel: () => { | |
137 | + setVisible(false); | |
138 | + }, | |
139 | + }} | |
140 | + grid={true} | |
141 | + layout="horizontal" | |
142 | + rowProps={{ | |
143 | + gutter: [0, 0], | |
144 | + }} | |
145 | + submitTimeout={2000} | |
146 | + onFinish={async (values) => { | |
147 | + const result = await postServiceInvoiceModifyRecord({ | |
148 | + data: { | |
149 | + ...values, | |
150 | + invoiceDetails: { | |
151 | + ...detailTableData, | |
152 | + }, | |
153 | + }, | |
154 | + }); | |
155 | + if (result.result === RESPONSE_CODE.SUCCESS) { | |
156 | + message.success('提交成功'); | |
157 | + } | |
158 | + return true; | |
159 | + }} | |
160 | + > | |
161 | + <ProCard | |
162 | + title="基础信息" | |
163 | + bordered | |
164 | + // | |
165 | + headStyle={{}} | |
166 | + headerBordered | |
167 | + size={'small'} | |
168 | + > | |
169 | + <ProForm.Group> | |
170 | + <ProFormText | |
171 | + readonly | |
172 | + name="id" | |
173 | + label="订单批号" | |
174 | + colProps={{ | |
175 | + span: 5, | |
176 | + }} | |
177 | + tooltip="最长为 24 位" | |
178 | + placeholder="请输入名称" | |
179 | + /> | |
180 | + | |
181 | + <ProFormText | |
182 | + readonly | |
183 | + width="md" | |
184 | + colProps={{ | |
185 | + span: 5, | |
186 | + }} | |
187 | + name="createByName" | |
188 | + label="销售代表" | |
189 | + placeholder="请输入名称" | |
190 | + /> | |
191 | + <ProFormText | |
192 | + readonly | |
193 | + width="md" | |
194 | + colProps={{ | |
195 | + span: 5, | |
196 | + }} | |
197 | + name="createTime" | |
198 | + label="申请时间" | |
199 | + placeholder="请输入名称" | |
200 | + /> | |
201 | + <ProFormSelect | |
202 | + name="type" | |
203 | + label="发票类型" | |
204 | + colProps={{ | |
205 | + span: 5, | |
206 | + }} | |
207 | + readonly={readOnly} | |
208 | + request={async () => { | |
209 | + let invoiceTypeRet = await postServiceConstInvoiceType(); | |
210 | + return enumToSelect(invoiceTypeRet.data); | |
211 | + }} | |
212 | + placeholder="Please select a country" | |
213 | + rules={[ | |
214 | + { required: true, message: 'Please select your country!' }, | |
215 | + ]} | |
216 | + /> | |
217 | + <ProFormSelect | |
218 | + name="invoicingType" | |
219 | + readonly={readOnly} | |
220 | + label="开具类型" | |
221 | + colProps={{ | |
222 | + span: 4, | |
223 | + }} | |
224 | + request={async () => { | |
225 | + let invoicingTypeRet = await postServiceConstInvoicingType(); | |
226 | + let options = enumToSelect(invoicingTypeRet.data); | |
227 | + return options; | |
228 | + }} | |
229 | + placeholder="Please select a country" | |
230 | + rules={[ | |
231 | + { required: true, message: 'Please select your country!' }, | |
232 | + ]} | |
233 | + /> | |
234 | + <ProFormFieldSet | |
235 | + name="list" | |
236 | + label="子订单号" | |
237 | + transform={(value: any) => ({ | |
238 | + list: value, | |
239 | + startTime: value[0], | |
240 | + endTime: value[1], | |
241 | + })} | |
242 | + > | |
243 | + <ProFormList | |
244 | + name="subOrderIds" | |
245 | + creatorButtonProps={false} | |
246 | + itemRender={({}, { record }) => { | |
247 | + return ( | |
248 | + <> | |
249 | + <Button | |
250 | + className="pl-1 pr-0" | |
251 | + type="link" | |
252 | + target="_blank" | |
253 | + href={'/order?subOrderId=' + record} | |
254 | + > | |
255 | + {record} | |
256 | + </Button> | |
257 | + <Divider type="vertical" /> | |
258 | + </> | |
259 | + ); | |
260 | + }} | |
261 | + > | |
262 | + <ProFormText allowClear={false} width="xs" name={['name']} /> | |
263 | + </ProFormList> | |
264 | + </ProFormFieldSet> | |
265 | + </ProForm.Group> | |
266 | + </ProCard> | |
267 | + <hr /> | |
268 | + <ProCard title="购方信息" bordered headerBordered size={'small'}> | |
269 | + <ProForm.Group> | |
270 | + <ProFormText | |
271 | + readonly={readOnly} | |
272 | + width="md" | |
273 | + colProps={{ | |
274 | + span: 8, | |
275 | + }} | |
276 | + name="partyAName" | |
277 | + label="购方名称" | |
278 | + placeholder="请输入名称" | |
279 | + /> | |
280 | + <ProFormText | |
281 | + readonly={readOnly} | |
282 | + width="md" | |
283 | + colProps={{ | |
284 | + span: 8, | |
285 | + }} | |
286 | + name="partyATaxid" | |
287 | + label="购方税号" | |
288 | + placeholder="请输入名称" | |
289 | + /> | |
290 | + <ProFormText | |
291 | + readonly={readOnly} | |
292 | + width="md" | |
293 | + colProps={{ | |
294 | + span: 8, | |
295 | + }} | |
296 | + label="开户银行" | |
297 | + name={'partyAOpenBank'} | |
298 | + placeholder="请输入名称" | |
299 | + /> | |
300 | + <ProFormText | |
301 | + readonly={readOnly} | |
302 | + width="md" | |
303 | + colProps={{ | |
304 | + span: 8, | |
305 | + }} | |
306 | + name="partyABankAccount" | |
307 | + label="银行账号" | |
308 | + placeholder="请输入名称" | |
309 | + /> | |
310 | + <ProFormText | |
311 | + readonly={readOnly} | |
312 | + width="md" | |
313 | + colProps={{ | |
314 | + span: 8, | |
315 | + }} | |
316 | + name="partyAAddress" | |
317 | + label="购方地址" | |
318 | + placeholder="请输入名称" | |
319 | + /> | |
320 | + <ProFormText | |
321 | + readonly={readOnly} | |
322 | + width="md" | |
323 | + colProps={{ | |
324 | + span: 8, | |
325 | + }} | |
326 | + name="partyAPhoneNumber" | |
327 | + label="电话" | |
328 | + placeholder="请输入名称" | |
329 | + /> | |
330 | + </ProForm.Group> | |
331 | + </ProCard> | |
332 | + <hr /> | |
333 | + <ProCard title="销方信息" bordered headerBordered size={'small'}> | |
334 | + <ProForm.Group> | |
335 | + <ProFormSelect | |
336 | + readonly={readOnly} | |
337 | + width="md" | |
338 | + name="partyBName" | |
339 | + options={payeeNameOptions} | |
340 | + onChange={(value: any) => { | |
341 | + let payee = payees.find((item: any) => { | |
342 | + return item.payeeName === value; | |
343 | + }); | |
344 | + console.log(JSON.stringify(payee)); | |
345 | + form.setFieldsValue({ | |
346 | + partyBTaxid: payee.taxId, | |
347 | + partyBBankAccount: payee.bankAccount, | |
348 | + partyBOpenBank: payee.openBank, | |
349 | + partyBAddress: payee.address, | |
350 | + partyBPhoneNumber: payee.phoneNumber, | |
351 | + }); | |
352 | + }} | |
353 | + label="销方名称" | |
354 | + colProps={{ | |
355 | + span: 8, | |
356 | + }} | |
357 | + placeholder="请输入名称" | |
358 | + /> | |
359 | + | |
360 | + <ProFormText | |
361 | + readonly | |
362 | + width="md" | |
363 | + name="partyBTaxid" | |
364 | + label="销方税号" | |
365 | + colProps={{ | |
366 | + span: 8, | |
367 | + }} | |
368 | + placeholder="请输入名称" | |
369 | + /> | |
370 | + <ProFormText | |
371 | + readonly | |
372 | + width="md" | |
373 | + name="partyBOpenBank" | |
374 | + label="开户银行" | |
375 | + colProps={{ | |
376 | + span: 8, | |
377 | + }} | |
378 | + placeholder="请输入名称" | |
379 | + /> | |
380 | + <ProFormText | |
381 | + readonly | |
382 | + width="md" | |
383 | + name="partyBBankAccount" | |
384 | + label="银行账号" | |
385 | + colProps={{ | |
386 | + span: 8, | |
387 | + }} | |
388 | + placeholder="请输入名称" | |
389 | + /> | |
390 | + <ProFormText | |
391 | + readonly | |
392 | + width="md" | |
393 | + colProps={{ | |
394 | + span: 8, | |
395 | + }} | |
396 | + name="partyBAddress" | |
397 | + label="销方地址" | |
398 | + placeholder="请输入名称" | |
399 | + /> | |
400 | + <ProFormText | |
401 | + readonly | |
402 | + width="md" | |
403 | + colProps={{ | |
404 | + span: 8, | |
405 | + }} | |
406 | + name="partyBPhoneNumber" | |
407 | + label="电话" | |
408 | + placeholder="请输入名称" | |
409 | + /> | |
410 | + </ProForm.Group> | |
411 | + </ProCard> | |
412 | + <hr /> | |
413 | + <ProCard title="发票明细" bordered headerBordered size={'small'}> | |
414 | + <InvoiceDetailTable | |
415 | + recordId={id} | |
416 | + details={detailTableData} | |
417 | + updateDetails={updateDetails} | |
418 | + readOnly={readOnly} | |
419 | + /> | |
420 | + </ProCard> | |
421 | + <hr /> | |
422 | + <ProCard title="备注" bordered headerBordered size={'small'}> | |
423 | + <ProFormTextArea | |
424 | + readonly={readOnly} | |
425 | + name="comment" | |
426 | + placeholder="请输入备注" | |
427 | + /> | |
428 | + </ProCard> | |
429 | + </ModalForm> | |
430 | + </Space> | |
431 | + </> | |
432 | + ); | |
433 | +}; | ... | ... |
src/pages/Invoice/components/InvoicingModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { postServiceInvoiceInvoicing } from '@/services'; | |
3 | +import { ModalForm } from '@ant-design/pro-components'; | |
4 | +import { Button, Form, message } from 'antd'; | |
5 | + | |
6 | +export default ({ selectedRowKeys, reloadRecordTable }) => { | |
7 | + const [form] = Form.useForm<{ name: string; company: string }>(); | |
8 | + return ( | |
9 | + <ModalForm<{ | |
10 | + name: string; | |
11 | + company: string; | |
12 | + }> | |
13 | + title="开票" | |
14 | + trigger={ | |
15 | + <Button type="primary" disabled={selectedRowKeys?.length === 0}> | |
16 | + 开票 | |
17 | + </Button> | |
18 | + } | |
19 | + form={form} | |
20 | + autoFocusFirstInput | |
21 | + modalProps={{ | |
22 | + destroyOnClose: true, | |
23 | + onCancel: () => console.log('run'), | |
24 | + }} | |
25 | + submitTimeout={2000} | |
26 | + onFinish={async () => { | |
27 | + let res = await postServiceInvoiceInvoicing({ | |
28 | + data: { | |
29 | + invoiceRecordIds: selectedRowKeys, | |
30 | + }, | |
31 | + }); | |
32 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
33 | + message.success(res.message); | |
34 | + } | |
35 | + reloadRecordTable(); | |
36 | + message.success('提交成功'); | |
37 | + return true; | |
38 | + }} | |
39 | + ></ModalForm> | |
40 | + ); | |
41 | +}; | ... | ... |
src/pages/Invoice/index.tsx
... | ... | @@ -2,6 +2,9 @@ import ButtonConfirm from '@/components/ButtomConfirm'; |
2 | 2 | import EllipsisDiv from '@/components/Div/EllipsisDiv'; |
3 | 3 | import { RESPONSE_CODE } from '@/constants/enum'; |
4 | 4 | import AddInvoiceDrawerForm from '@/pages/Invoice/components/AddInvoiceDrawerForm'; |
5 | +import InvoiceModal from '@/pages/Invoice/components/InvoiceModal'; | |
6 | +import InvoiceRecordDetailModal from '@/pages/Invoice/components/InvoiceRecordDetailModal'; | |
7 | +import InvoicingModal from '@/pages/Invoice/components/InvoicingModal'; | |
5 | 8 | import { |
6 | 9 | BANK_STATEMENT_COLUMNS, |
7 | 10 | INVOICE_COLUMNS, |
... | ... | @@ -11,15 +14,28 @@ import { |
11 | 14 | postServiceBankStatementDeleteBankStatement, |
12 | 15 | postServiceBankStatementEditBankStatement, |
13 | 16 | postServiceBankStatementQueryBankStatement, |
17 | + postServiceConstAfterInvoicingInvoiceRecordStatus, | |
18 | + postServiceConstBeforeInvoicingInvoiceRecordStatus, | |
19 | + postServiceConstInvoiceType, | |
20 | + postServiceConstInvoicingType, | |
14 | 21 | postServiceInvoiceDeleteInvoice, |
22 | + postServiceInvoiceInvoicing, | |
15 | 23 | postServiceInvoiceQueryInvoice, |
24 | + postServiceInvoiceQueryInvoiceRecordList, | |
25 | + postServiceOrderQuerySalesCode, | |
16 | 26 | } from '@/services'; |
17 | -import { enumValueToLabel, formatDateTime } from '@/utils'; | |
27 | +import { excelExport } from '@/services/exportRequest'; | |
28 | +import { | |
29 | + enumToProTableEnumValue, | |
30 | + enumToSelect, | |
31 | + enumValueToLabel, | |
32 | + formatDateTime, | |
33 | +} from '@/utils'; | |
18 | 34 | import { formatDate } from '@/utils/time'; |
19 | 35 | import { PlusOutlined } from '@ant-design/icons'; |
20 | -import { ActionType, ProTable } from '@ant-design/pro-components'; | |
21 | -import { Button, Tabs, message } from 'antd'; | |
22 | -import { useRef, useState } from 'react'; | |
36 | +import { ActionType, ModalForm, ProTable } from '@ant-design/pro-components'; | |
37 | +import { Button, Space, Table, Tabs, message } from 'antd'; | |
38 | +import { useEffect, useRef, useState } from 'react'; | |
23 | 39 | import { INVOCING_STATUS, PAYEE_OPTIONS } from '../Order/constant'; |
24 | 40 | import BankImportModal from './components/BankImportModal'; |
25 | 41 | import InvoiceVerificationModal from './components/InvoiceVerificationModal'; |
... | ... | @@ -28,10 +44,51 @@ import './index.less'; |
28 | 44 | const InvoicePage = () => { |
29 | 45 | const invoiceActionRef = useRef<ActionType>(); |
30 | 46 | const bankActionRef = useRef<ActionType>(); |
47 | + const waitDealrecordActionRef = useRef<ActionType>(); | |
48 | + const processedRecordRef = useRef<ActionType>(); | |
49 | + const [invoiceTypeValueEnum, setInvoiceTypeValueEnum] = useState({}); | |
50 | + const [invoicingTypeValueEnum, setInvoicingTypeValueEnum] = useState({}); | |
51 | + const [salesCodeValueEnum, setSalesCodeValueEnum] = useState({}); | |
31 | 52 | const [bankImportModalVisible, setBankImportModalVisible] = useState(false); |
32 | 53 | const [invoiceVerificationVisible, setInvoiceVerificationVisible] = |
33 | 54 | useState(false); |
34 | 55 | const [invoiceId, setInvoiceId] = useState(undefined); |
56 | + const [invoiceRecordDetailVisible, setInvoiceRecordDetailVisible] = | |
57 | + useState(false); | |
58 | + const [invoiceRecord, setInvoiceRecord] = useState({}); | |
59 | + const [messageApi, contextHolder] = message.useMessage(); | |
60 | + | |
61 | + useEffect(() => { | |
62 | + async function extracted() { | |
63 | + let invoiceTypeRet = await postServiceConstInvoiceType(); | |
64 | + setInvoiceTypeValueEnum(invoiceTypeRet.data); | |
65 | + } | |
66 | + extracted().catch(console.error); | |
67 | + }, []); | |
68 | + | |
69 | + useEffect(() => { | |
70 | + async function extracted() { | |
71 | + let invoicingTypeRet = await postServiceConstInvoicingType(); | |
72 | + setInvoicingTypeValueEnum(invoicingTypeRet.data); | |
73 | + } | |
74 | + extracted().catch(console.error); | |
75 | + }, []); | |
76 | + | |
77 | + useEffect(() => { | |
78 | + async function extracted() { | |
79 | + const res = await postServiceOrderQuerySalesCode(); | |
80 | + let map = {}; | |
81 | + res.data?.forEach((item) => { | |
82 | + map[item.userName] = { | |
83 | + text: item.userName, | |
84 | + status: item.userName, | |
85 | + }; | |
86 | + }); | |
87 | + setSalesCodeValueEnum(map); | |
88 | + } | |
89 | + | |
90 | + extracted().catch(console.error); | |
91 | + }, []); | |
35 | 92 | |
36 | 93 | const reloadInvoiceTable = () => { |
37 | 94 | invoiceActionRef.current?.reload(); |
... | ... | @@ -40,6 +97,10 @@ const InvoicePage = () => { |
40 | 97 | const reloadBankStatementTable = () => { |
41 | 98 | bankActionRef.current?.reload(); |
42 | 99 | }; |
100 | + const reloadRecordTable = () => { | |
101 | + waitDealrecordActionRef.current?.reload(); | |
102 | + processedRecordRef.current?.reload(); | |
103 | + }; | |
43 | 104 | |
44 | 105 | const getTableCellText = (target: any) => { |
45 | 106 | if (!target) { |
... | ... | @@ -53,6 +114,454 @@ const InvoicePage = () => { |
53 | 114 | return target; |
54 | 115 | }; |
55 | 116 | |
117 | + const waitDealRecordColumns = [ | |
118 | + { | |
119 | + dataIndex: 'index', | |
120 | + valueType: 'indexBorder', | |
121 | + hideInSearch: true, | |
122 | + ellipsis: true, | |
123 | + width: 48, | |
124 | + }, | |
125 | + { | |
126 | + title: '开票编号', | |
127 | + valueType: 'text', | |
128 | + dataIndex: 'id', | |
129 | + copyable: true, | |
130 | + hideInSearch: true, | |
131 | + ellipsis: true, | |
132 | + width: 100, | |
133 | + }, | |
134 | + { | |
135 | + title: '发票状态', | |
136 | + valueType: 'Text', | |
137 | + dataIndex: 'statusText', | |
138 | + ellipsis: true, | |
139 | + hideInSearch: true, | |
140 | + }, | |
141 | + { | |
142 | + title: '申请开票时间', | |
143 | + dataIndex: 'createTime', | |
144 | + valueType: 'dateTime', | |
145 | + hideInSearch: true, | |
146 | + ellipsis: true, | |
147 | + }, | |
148 | + { | |
149 | + title: '销售代表', | |
150 | + valueType: 'text', | |
151 | + hideInSearch: true, | |
152 | + ellipsis: true, | |
153 | + dataIndex: 'createByName', | |
154 | + }, | |
155 | + { | |
156 | + title: '购方名称', | |
157 | + valueType: 'text', | |
158 | + dataIndex: 'partyAName', | |
159 | + hideInSearch: true, | |
160 | + ellipsis: true, | |
161 | + }, | |
162 | + { | |
163 | + title: '购方税号', | |
164 | + valueType: 'text', | |
165 | + hideInSearch: true, | |
166 | + dataIndex: 'partyATaxid', | |
167 | + ellipsis: true, | |
168 | + }, | |
169 | + { | |
170 | + title: '收款单位', | |
171 | + valueType: 'text', | |
172 | + hideInSearch: true, | |
173 | + dataIndex: 'partyBName', | |
174 | + ellipsis: true, | |
175 | + }, | |
176 | + { | |
177 | + title: '开票金额', | |
178 | + valueType: 'money', | |
179 | + dataIndex: 'price', | |
180 | + hideInSearch: true, | |
181 | + ellipsis: true, | |
182 | + }, | |
183 | + { | |
184 | + title: '开具类型', | |
185 | + valueType: 'Text', | |
186 | + dataIndex: 'invoicingTypeText', | |
187 | + hideInSearch: true, | |
188 | + ellipsis: true, | |
189 | + }, | |
190 | + { | |
191 | + title: '发票类型', | |
192 | + valueType: 'Text', | |
193 | + dataIndex: 'typeText', | |
194 | + hideInSearch: true, | |
195 | + ellipsis: true, | |
196 | + }, | |
197 | + { | |
198 | + title: '是否加急', | |
199 | + valueType: 'Text', | |
200 | + dataIndex: 'isUrgentText', | |
201 | + hideInSearch: true, | |
202 | + ellipsis: true, | |
203 | + }, | |
204 | + { | |
205 | + title: '申请备注', | |
206 | + valueType: 'text', | |
207 | + dataIndex: 'applyInvoicingNotes', | |
208 | + hideInSearch: true, | |
209 | + ellipsis: true, | |
210 | + }, | |
211 | + { | |
212 | + title: '购方名称', | |
213 | + valueType: 'Text', | |
214 | + dataIndex: 'partyANameLike', | |
215 | + hideInTable: true, | |
216 | + }, | |
217 | + { | |
218 | + title: '收款单位', | |
219 | + valueType: 'select', | |
220 | + dataIndex: 'partyB', | |
221 | + filters: true, | |
222 | + onFilter: true, | |
223 | + hideInTable: true, | |
224 | + valueEnum: enumToProTableEnumValue(PAYEE_OPTIONS), | |
225 | + }, | |
226 | + { | |
227 | + title: '主订单号', | |
228 | + valueType: 'Text', | |
229 | + dataIndex: 'mainOrderId', | |
230 | + hideInTable: true, | |
231 | + }, | |
232 | + { | |
233 | + title: '子订单号', | |
234 | + valueType: 'Text', | |
235 | + dataIndex: 'subOrderId', | |
236 | + hideInTable: true, | |
237 | + }, | |
238 | + { | |
239 | + title: '销售代表', | |
240 | + valueType: 'select', | |
241 | + dataIndex: 'salesCode', | |
242 | + filters: true, | |
243 | + onFilter: true, | |
244 | + hideInTable: true, | |
245 | + valueEnum: salesCodeValueEnum, | |
246 | + }, | |
247 | + { | |
248 | + title: '发票类型', | |
249 | + valueType: 'select', | |
250 | + dataIndex: 'type', | |
251 | + filters: true, | |
252 | + onFilter: true, | |
253 | + hideInTable: true, | |
254 | + valueEnum: enumToProTableEnumValue(invoiceTypeValueEnum), | |
255 | + }, | |
256 | + { | |
257 | + title: '开具类型', | |
258 | + valueType: 'select', | |
259 | + dataIndex: 'invoicingType', | |
260 | + filters: true, | |
261 | + onFilter: true, | |
262 | + hideInTable: true, | |
263 | + valueEnum: enumToProTableEnumValue(invoicingTypeValueEnum), | |
264 | + }, | |
265 | + { | |
266 | + title: '开票状态', | |
267 | + valueType: 'select', | |
268 | + dataIndex: 'status', | |
269 | + filters: true, | |
270 | + onFilter: true, | |
271 | + hideInTable: true, | |
272 | + request: async () => { | |
273 | + const res = await postServiceConstBeforeInvoicingInvoiceRecordStatus(); | |
274 | + return enumToSelect(res.data); | |
275 | + }, | |
276 | + }, | |
277 | + { | |
278 | + title: '是否加急', | |
279 | + valueType: 'select', | |
280 | + dataIndex: 'isUrgent', | |
281 | + filters: true, | |
282 | + onFilter: true, | |
283 | + hideInTable: true, | |
284 | + valueEnum: { | |
285 | + true: { | |
286 | + text: '是', | |
287 | + status: true, | |
288 | + }, | |
289 | + false: { | |
290 | + text: '否', | |
291 | + status: false, | |
292 | + }, | |
293 | + }, | |
294 | + }, | |
295 | + { | |
296 | + title: '申请开票时间', | |
297 | + dataIndex: 'createTime', | |
298 | + valueType: 'dateRange', | |
299 | + width: 200, | |
300 | + hideInTable: true, | |
301 | + search: { | |
302 | + transform: (value) => { | |
303 | + if (value) { | |
304 | + return { | |
305 | + createTimeGe: value[0], | |
306 | + createTimeLe: value[1], | |
307 | + }; | |
308 | + } | |
309 | + }, | |
310 | + }, | |
311 | + }, | |
312 | + { | |
313 | + title: '操作', | |
314 | + valueType: 'option', | |
315 | + key: 'option', | |
316 | + render: (text, record) => { | |
317 | + return [ | |
318 | + /*<InvoiceRecordDetailModal | |
319 | + key="detail" | |
320 | + id={record.id} | |
321 | + subOrderIds={record.subOrderIds} | |
322 | + onClose={()=>{ | |
323 | + waitDealrecordActionRef.current?.reload(); | |
324 | + } | |
325 | + } | |
326 | + />*/ | |
327 | + <a | |
328 | + key="detail" | |
329 | + onClick={() => { | |
330 | + setInvoiceRecordDetailVisible(true); | |
331 | + setInvoiceRecord(record); | |
332 | + }} | |
333 | + > | |
334 | + 详情 | |
335 | + </a>, | |
336 | + <InvoiceModal key="invoiceModal" recordId={record.id} />, | |
337 | + ]; | |
338 | + }, | |
339 | + }, | |
340 | + ]; | |
341 | + | |
342 | + const processedRecordColumns = [ | |
343 | + { | |
344 | + dataIndex: 'index', | |
345 | + valueType: 'indexBorder', | |
346 | + }, | |
347 | + { | |
348 | + title: '开票编号', | |
349 | + valueType: 'text', | |
350 | + dataIndex: 'id', | |
351 | + copyable: true, | |
352 | + ellipsis: true, | |
353 | + }, | |
354 | + { | |
355 | + title: '发票号码', | |
356 | + valueType: 'text', | |
357 | + dataIndex: 'invoiceNumber', | |
358 | + copyable: true, | |
359 | + ellipsis: true, | |
360 | + }, | |
361 | + { | |
362 | + title: '开票日期', | |
363 | + dataIndex: 'invoicingTime', | |
364 | + valueType: 'dateTime', | |
365 | + hideInSearch: true, | |
366 | + ellipsis: true, | |
367 | + }, | |
368 | + { | |
369 | + title: '发票类型', | |
370 | + valueType: 'Text', | |
371 | + dataIndex: 'typeText', | |
372 | + hideInSearch: true, | |
373 | + ellipsis: true, | |
374 | + }, | |
375 | + { | |
376 | + title: '发票状态', | |
377 | + valueType: 'Text', | |
378 | + dataIndex: 'statusText', | |
379 | + hideInSearch: true, | |
380 | + ellipsis: true, | |
381 | + }, | |
382 | + { | |
383 | + title: '购方名称', | |
384 | + valueType: 'text', | |
385 | + dataIndex: 'partyAName', | |
386 | + hideInSearch: true, | |
387 | + ellipsis: true, | |
388 | + }, | |
389 | + { | |
390 | + title: '购方税号', | |
391 | + valueType: 'text', | |
392 | + dataIndex: 'partyATaxid', | |
393 | + ellipsis: true, | |
394 | + }, | |
395 | + { | |
396 | + title: '收款单位', | |
397 | + valueType: 'text', | |
398 | + dataIndex: 'partyBName', | |
399 | + hideInSearch: true, | |
400 | + ellipsis: true, | |
401 | + }, | |
402 | + { | |
403 | + title: '联系人', | |
404 | + valueType: 'text', | |
405 | + dataIndex: 'contacts', | |
406 | + hideInSearch: true, | |
407 | + ellipsis: true, | |
408 | + }, | |
409 | + { | |
410 | + title: '申请人', | |
411 | + valueType: 'text', | |
412 | + dataIndex: 'createByName', | |
413 | + hideInSearch: true, | |
414 | + ellipsis: true, | |
415 | + }, | |
416 | + { | |
417 | + title: '开票金额(元)', | |
418 | + valueType: 'money', | |
419 | + dataIndex: 'price', | |
420 | + hideInSearch: true, | |
421 | + ellipsis: true, | |
422 | + }, | |
423 | + { | |
424 | + title: '备注', | |
425 | + valueType: 'text', | |
426 | + dataIndex: 'contacts', | |
427 | + hideInSearch: true, | |
428 | + ellipsis: true, | |
429 | + }, | |
430 | + { | |
431 | + title: '失败原因', | |
432 | + valueType: 'text', | |
433 | + dataIndex: 'failureReason', | |
434 | + hideInSearch: true, | |
435 | + ellipsis: true, | |
436 | + }, | |
437 | + | |
438 | + { | |
439 | + title: '购方名称', | |
440 | + valueType: 'text', | |
441 | + dataIndex: 'partyANameLike', | |
442 | + hideInTable: true, | |
443 | + }, | |
444 | + { | |
445 | + title: '发票类型', | |
446 | + valueType: 'select', | |
447 | + dataIndex: 'type', | |
448 | + filters: true, | |
449 | + onFilter: true, | |
450 | + hideInTable: true, | |
451 | + valueEnum: enumToProTableEnumValue(invoiceTypeValueEnum), | |
452 | + }, | |
453 | + | |
454 | + { | |
455 | + title: '开票状态', | |
456 | + valueType: 'select', | |
457 | + dataIndex: 'status', | |
458 | + filters: true, | |
459 | + onFilter: true, | |
460 | + hideInTable: true, | |
461 | + request: async () => { | |
462 | + const res = await postServiceConstAfterInvoicingInvoiceRecordStatus(); | |
463 | + return enumToSelect(res.data); | |
464 | + }, | |
465 | + }, | |
466 | + { | |
467 | + title: '销售代表', | |
468 | + valueType: 'select', | |
469 | + dataIndex: 'salesCode', | |
470 | + filters: true, | |
471 | + onFilter: true, | |
472 | + hideInTable: true, | |
473 | + valueEnum: salesCodeValueEnum, | |
474 | + }, | |
475 | + { | |
476 | + title: '联系人', | |
477 | + valueType: 'text', | |
478 | + dataIndex: 'contactsLike', | |
479 | + hideInTable: true, | |
480 | + }, | |
481 | + { | |
482 | + title: '开票日期', | |
483 | + dataIndex: 'invoicingTime', | |
484 | + valueType: 'dateRange', | |
485 | + hideInTable: true, | |
486 | + search: { | |
487 | + transform: (value) => { | |
488 | + if (value) { | |
489 | + return { | |
490 | + invoicingTimeGe: value[0], | |
491 | + invoicingTimeLe: value[1], | |
492 | + }; | |
493 | + } | |
494 | + }, | |
495 | + }, | |
496 | + }, | |
497 | + { | |
498 | + title: '收款单位', | |
499 | + valueType: 'select', | |
500 | + dataIndex: 'partyB', | |
501 | + filters: true, | |
502 | + onFilter: true, | |
503 | + hideInTable: true, | |
504 | + valueEnum: enumToProTableEnumValue(PAYEE_OPTIONS), | |
505 | + }, | |
506 | + { | |
507 | + title: '操作', | |
508 | + valueType: 'option', | |
509 | + key: 'option', | |
510 | + render: (text, record) => [ | |
511 | + <a | |
512 | + key="detail" | |
513 | + onClick={() => { | |
514 | + setInvoiceRecordDetailVisible(true); | |
515 | + setInvoiceRecord(record); | |
516 | + }} | |
517 | + > | |
518 | + 详情 | |
519 | + </a>, | |
520 | + <> | |
521 | + {record.status === 'SUCCESS' && ( | |
522 | + <> | |
523 | + {record.status === 'SUCCESS' && ( | |
524 | + <a href={record.invoiceAddress} download> | |
525 | + 下载发票 | |
526 | + </a> | |
527 | + )} | |
528 | + </> | |
529 | + )} | |
530 | + </>, | |
531 | + <> | |
532 | + {record.status === 'FAIL' && ( | |
533 | + <ModalForm | |
534 | + title="提示" | |
535 | + trigger={ | |
536 | + <Button type="link" danger> | |
537 | + 重试 | |
538 | + </Button> | |
539 | + } | |
540 | + autoFocusFirstInput | |
541 | + modalProps={{ | |
542 | + destroyOnClose: true, | |
543 | + }} | |
544 | + submitTimeout={2000} | |
545 | + onFinish={async () => { | |
546 | + const res = await postServiceInvoiceInvoicing({ | |
547 | + data: { | |
548 | + invoiceRecordIds: [record.id], | |
549 | + }, | |
550 | + }); | |
551 | + if (res) { | |
552 | + message.success(res.message); | |
553 | + processedRecordRef?.current?.reload(); | |
554 | + } | |
555 | + return true; | |
556 | + }} | |
557 | + > | |
558 | + 确定重试订单信息吗? | |
559 | + </ModalForm> | |
560 | + )} | |
561 | + </>, | |
562 | + ], | |
563 | + }, | |
564 | + ]; | |
56 | 565 | /** |
57 | 566 | * 加载发票列表表格的各个列格式 |
58 | 567 | */ |
... | ... | @@ -296,6 +805,166 @@ const InvoicePage = () => { |
296 | 805 | const tabsItems = [ |
297 | 806 | { |
298 | 807 | key: 1, |
808 | + label: '待处理', | |
809 | + children: ( | |
810 | + <ProTable | |
811 | + columns={waitDealRecordColumns} | |
812 | + actionRef={waitDealrecordActionRef} | |
813 | + cardBordered | |
814 | + pagination={{ | |
815 | + pageSize: 10, | |
816 | + }} | |
817 | + rowSelection={{ | |
818 | + selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT], | |
819 | + alwaysShowAlert: true, | |
820 | + }} | |
821 | + tableAlertOptionRender={({ selectedRowKeys, selectedRows }) => { | |
822 | + console.log(selectedRows); | |
823 | + console.log(selectedRowKeys); | |
824 | + return ( | |
825 | + <Space size={16}> | |
826 | + <InvoicingModal | |
827 | + reloadRecordTable={reloadRecordTable} | |
828 | + key="button" | |
829 | + selectedRowKeys={selectedRowKeys} | |
830 | + /> | |
831 | + </Space> | |
832 | + ); | |
833 | + }} | |
834 | + request={async (params) => { | |
835 | + let res = await postServiceInvoiceQueryInvoiceRecordList({ | |
836 | + data: { | |
837 | + ...params, | |
838 | + statusIn: [ | |
839 | + 'WAITING_FOR_INVOICING', | |
840 | + 'AUDITING', | |
841 | + 'AUDITING_NOT_PASSED', | |
842 | + 'CANCELED', | |
843 | + ], | |
844 | + needBuildDetails: false, | |
845 | + needBuildSubOrders: true, | |
846 | + }, | |
847 | + }); | |
848 | + return { | |
849 | + data: res?.data?.data, | |
850 | + total: res?.data?.total || 0, | |
851 | + }; | |
852 | + }} | |
853 | + columnsState={{ | |
854 | + persistenceKey: 'pro-table-singe-demos', | |
855 | + persistenceType: 'localStorage', | |
856 | + defaultValue: { | |
857 | + option: { fixed: 'right', disable: true }, | |
858 | + }, | |
859 | + onChange(value) { | |
860 | + console.log('value: ', value); | |
861 | + }, | |
862 | + }} | |
863 | + rowKey="id" | |
864 | + search={{ | |
865 | + labelWidth: 'auto', | |
866 | + }} | |
867 | + options={{ | |
868 | + setting: { | |
869 | + listsHeight: 400, | |
870 | + }, | |
871 | + }} | |
872 | + form={{}} | |
873 | + dateFormatter="string" | |
874 | + headerTitle="待开票列表" | |
875 | + scroll={{ x: 1400, y: 360 }} | |
876 | + /> | |
877 | + ), | |
878 | + }, | |
879 | + { | |
880 | + key: 2, | |
881 | + label: '开票记录', | |
882 | + children: ( | |
883 | + <ProTable | |
884 | + columns={processedRecordColumns} | |
885 | + actionRef={processedRecordRef} | |
886 | + cardBordered | |
887 | + pagination={{ | |
888 | + pageSize: 10, | |
889 | + }} | |
890 | + editable={{ | |
891 | + type: 'multiple', | |
892 | + onSave: async (rowKey, data) => { | |
893 | + await postServiceBankStatementEditBankStatement({ data: data }); | |
894 | + }, | |
895 | + actionRender: (row, config, defaultDom) => [ | |
896 | + defaultDom.save, | |
897 | + defaultDom.cancel, | |
898 | + ], | |
899 | + }} | |
900 | + search={{ | |
901 | + labelWidth: 'auto', | |
902 | + defaultCollapsed: false, | |
903 | + optionRender: (searchConfig, formProps, dom) => [ | |
904 | + ...dom, | |
905 | + <Button | |
906 | + key="out" | |
907 | + onClick={() => { | |
908 | + const values = searchConfig?.form?.getFieldsValue(); | |
909 | + console.log(values); | |
910 | + messageApi.open({ | |
911 | + type: 'loading', | |
912 | + content: '正在导出文件...', | |
913 | + }); | |
914 | + excelExport( | |
915 | + '/api/service/invoice/exportInvoiceRecords', | |
916 | + { | |
917 | + ...values, | |
918 | + statusIn: ['INVOICING', 'SUCCESS', 'FAIL'], | |
919 | + }, | |
920 | + () => { | |
921 | + messageApi.destroy(); | |
922 | + }, | |
923 | + ); | |
924 | + }} | |
925 | + > | |
926 | + 导出 | |
927 | + </Button>, | |
928 | + ], | |
929 | + }} | |
930 | + request={async (params) => { | |
931 | + let res = await postServiceInvoiceQueryInvoiceRecordList({ | |
932 | + data: { | |
933 | + ...params, | |
934 | + statusIn: ['INVOICING', 'SUCCESS', 'FAIL'], | |
935 | + }, | |
936 | + }); | |
937 | + return { | |
938 | + data: res?.data?.data, | |
939 | + total: res?.data?.total || 0, | |
940 | + }; | |
941 | + }} | |
942 | + columnsState={{ | |
943 | + persistenceKey: 'pro-table-singe-demos', | |
944 | + persistenceType: 'localStorage', | |
945 | + defaultValue: { | |
946 | + option: { fixed: 'right', disable: true }, | |
947 | + }, | |
948 | + onChange(value) { | |
949 | + console.log('value: ', value); | |
950 | + }, | |
951 | + }} | |
952 | + rowKey="id" | |
953 | + options={{ | |
954 | + setting: { | |
955 | + listsHeight: 400, | |
956 | + }, | |
957 | + }} | |
958 | + form={{}} | |
959 | + dateFormatter="string" | |
960 | + headerTitle="待开票列表" | |
961 | + scroll={{ x: 1400, y: 360 }} | |
962 | + toolBarRender={() => []} | |
963 | + /> | |
964 | + ), | |
965 | + }, | |
966 | + { | |
967 | + key: 3, | |
299 | 968 | label: '发票管理', |
300 | 969 | children: ( |
301 | 970 | <ProTable |
... | ... | @@ -352,7 +1021,7 @@ const InvoicePage = () => { |
352 | 1021 | ), |
353 | 1022 | }, |
354 | 1023 | { |
355 | - key: 2, | |
1024 | + key: 4, | |
356 | 1025 | label: '银行流水', |
357 | 1026 | children: ( |
358 | 1027 | <ProTable |
... | ... | @@ -461,6 +1130,16 @@ const InvoicePage = () => { |
461 | 1130 | ) : ( |
462 | 1131 | '' |
463 | 1132 | )} |
1133 | + {invoiceRecordDetailVisible ? ( | |
1134 | + <InvoiceRecordDetailModal | |
1135 | + key="detail" | |
1136 | + id={invoiceRecord.id} | |
1137 | + setVisible={setInvoiceRecordDetailVisible} | |
1138 | + /> | |
1139 | + ) : ( | |
1140 | + '' | |
1141 | + )} | |
1142 | + {contextHolder} | |
464 | 1143 | </div> |
465 | 1144 | ); |
466 | 1145 | }; | ... | ... |
src/pages/Order/components/CheckModal.tsx
... | ... | @@ -8,7 +8,11 @@ import { |
8 | 8 | postServiceOrderLeaderAudit, |
9 | 9 | postServiceOrderToProcureAudit, |
10 | 10 | } from '@/services'; |
11 | -import { ModalForm, ProFormTextArea } from '@ant-design/pro-components'; | |
11 | +import { | |
12 | + ModalForm, | |
13 | + ProFormTextArea, | |
14 | + ProList, | |
15 | +} from '@ant-design/pro-components'; | |
12 | 16 | import { |
13 | 17 | Button, |
14 | 18 | Col, |
... | ... | @@ -17,6 +21,8 @@ import { |
17 | 21 | Image, |
18 | 22 | Modal, |
19 | 23 | Row, |
24 | + Space, | |
25 | + Tag, | |
20 | 26 | UploadFile, |
21 | 27 | message, |
22 | 28 | } from 'antd'; |
... | ... | @@ -28,6 +34,7 @@ import { |
28 | 34 | COMFIR_RECEIPT_IMAGES_NUMBER, |
29 | 35 | } from '../constant'; |
30 | 36 | // import { cloneDeep } from 'lodash'; |
37 | +import InvoiceSubOrderInfoTable from '@/pages/Order/components/InvoiceSubOrderInfoTable'; | |
31 | 38 | import { enumValueToLabel, transImageFile } from '@/utils'; |
32 | 39 | import { PlusOutlined } from '@ant-design/icons'; |
33 | 40 | import { cloneDeep } from 'lodash'; |
... | ... | @@ -62,7 +69,6 @@ export default ({ |
62 | 69 | |
63 | 70 | const [afterSalesInfo, setAfterSalesInfo] = useState<any>(); |
64 | 71 | const [prepaidProofImages, setPrepaidProofImages] = useState<any[]>([]); |
65 | - | |
66 | 72 | /** |
67 | 73 | * 审核类型 |
68 | 74 | */ |
... | ... | @@ -674,6 +680,57 @@ export default ({ |
674 | 680 | ) : ( |
675 | 681 | '' |
676 | 682 | )} |
683 | + {checkType(CHECK_TYPE.CONFIRM_REISSUE) && ( | |
684 | + <> | |
685 | + <InvoiceSubOrderInfoTable | |
686 | + subOrderIds={subOrderIds} | |
687 | + ></InvoiceSubOrderInfoTable> | |
688 | + </> | |
689 | + )} | |
690 | + {checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING) ? ( | |
691 | + <> | |
692 | + <ProList | |
693 | + rowKey="id" | |
694 | + headerTitle="发票信息" | |
695 | + metas={{ | |
696 | + title: { | |
697 | + dataIndex: 'name', | |
698 | + }, | |
699 | + avatar: { | |
700 | + dataIndex: 'image', | |
701 | + editable: false, | |
702 | + }, | |
703 | + description: { | |
704 | + dataIndex: 'desc', | |
705 | + }, | |
706 | + subTitle: { | |
707 | + render: () => { | |
708 | + return ( | |
709 | + <Space size={0}> | |
710 | + <Tag color="blue">Ant Design</Tag> | |
711 | + <Tag color="#5BD8A6">TechUI</Tag> | |
712 | + </Space> | |
713 | + ); | |
714 | + }, | |
715 | + }, | |
716 | + actions: { | |
717 | + render: (text, row, index, action) => [ | |
718 | + <a | |
719 | + onClick={() => { | |
720 | + action?.startEditable(row.id); | |
721 | + }} | |
722 | + key="link" | |
723 | + > | |
724 | + 编辑 | |
725 | + </a>, | |
726 | + ], | |
727 | + }, | |
728 | + }} | |
729 | + ></ProList> | |
730 | + </> | |
731 | + ) : ( | |
732 | + '' | |
733 | + )} | |
677 | 734 | </ModalForm> |
678 | 735 | |
679 | 736 | <Modal | ... | ... |
src/pages/Order/components/InvoiceSubOrderInfoTable.tsx
0 → 100644
1 | +import { postServiceOrderGetReissueInfo } from '@/services'; | |
2 | +import type { ProColumns } from '@ant-design/pro-components'; | |
3 | +import { ProTable } from '@ant-design/pro-components'; | |
4 | +import { Button, Divider } from 'antd'; | |
5 | +import { useEffect, useState } from 'react'; | |
6 | + | |
7 | +const columns: ProColumns[] = [ | |
8 | + { | |
9 | + title: '发票号码', | |
10 | + width: 80, | |
11 | + dataIndex: 'invoiceNumber', | |
12 | + render: (_) => _, | |
13 | + }, | |
14 | + { | |
15 | + title: '关联订单', | |
16 | + dataIndex: 'subOrderIds', | |
17 | + render: (_, { subOrderIds }) => { | |
18 | + console.log(JSON.stringify(_)); | |
19 | + console.log(JSON.stringify(subOrderIds)); | |
20 | + return ( | |
21 | + <> | |
22 | + {subOrderIds.map((subOrderId, index) => { | |
23 | + return ( | |
24 | + <> | |
25 | + <Button | |
26 | + key={index} | |
27 | + className="pl-1 pr-0" | |
28 | + type="link" | |
29 | + target="_blank" | |
30 | + href={'/order?id=' + subOrderId} | |
31 | + > | |
32 | + {subOrderId} | |
33 | + </Button> | |
34 | + <Divider type="vertical" /> | |
35 | + </> | |
36 | + ); | |
37 | + })} | |
38 | + </> | |
39 | + ); | |
40 | + }, | |
41 | + }, | |
42 | +]; | |
43 | + | |
44 | +export default ({ subOrderIds }) => { | |
45 | + const [reissueInfos, setReissueInfos] = useState([]); | |
46 | + useEffect(() => { | |
47 | + console.log('info'); | |
48 | + const getReissueInfo = async () => { | |
49 | + let res = await postServiceOrderGetReissueInfo({ | |
50 | + data: subOrderIds, | |
51 | + }); | |
52 | + setReissueInfos(res.data); | |
53 | + }; | |
54 | + getReissueInfo(); | |
55 | + }, []); | |
56 | + return ( | |
57 | + <ProTable | |
58 | + dataSource={reissueInfos} | |
59 | + rowKey="key" | |
60 | + pagination={false} | |
61 | + size={'small'} | |
62 | + //设置左右下边距为0 | |
63 | + options={false} | |
64 | + columns={columns} | |
65 | + search={false} | |
66 | + dateFormatter="string" | |
67 | + headerTitle="发票信息" | |
68 | + /> | |
69 | + ); | |
70 | +}; | ... | ... |
src/pages/Order/components/InvoicingDrawerForm.tsx
1 | +// import { PlusOutlined } from '@ant-design/icons'; | |
2 | +import InvoiceModal from '@/pages/Invoice/components/InvoiceModal'; | |
3 | +import { | |
4 | + postServiceConstGetPayeeEnum, | |
5 | + postServiceConstInvoiceType, | |
6 | + postServiceConstInvoicingType, | |
7 | + postServiceConstListInvoiceDetailNames, | |
8 | + postServiceInvoiceApplyInvoice, | |
9 | +} from '@/services'; | |
10 | +import { enumToSelect } from '@/utils'; | |
1 | 11 | import { |
2 | 12 | DrawerForm, |
3 | - ProForm, | |
4 | - ProFormDateRangePicker, | |
13 | + ProCard, | |
14 | + ProFormDigit, | |
15 | + ProFormGroup, | |
16 | + ProFormList, | |
17 | + ProFormMoney, | |
5 | 18 | ProFormSelect, |
6 | 19 | ProFormText, |
20 | + ProFormTextArea, | |
7 | 21 | } from '@ant-design/pro-components'; |
8 | -import { Form, message } from 'antd'; | |
9 | - | |
10 | -const waitTime = (time: number = 100) => { | |
11 | - return new Promise((resolve) => { | |
12 | - setTimeout(() => { | |
13 | - resolve(true); | |
14 | - }, time); | |
15 | - }); | |
16 | -}; | |
17 | - | |
18 | -export default ({ subOrders, totalPayment, onClose }) => { | |
19 | - const [form] = Form.useForm<{ name: string; company: string }>(); | |
22 | +import { Button, Form } from 'antd'; | |
23 | +import { useEffect } from 'react'; | |
20 | 24 | |
25 | +export default ({ dataList, mainOrder, setVisible, onClose }) => { | |
26 | + // let subOrderIds = dataList?.map((item) => { | |
27 | + // return item.id; | |
28 | + // }); | |
29 | + const [form] = Form.useForm(); | |
30 | + useEffect(() => {}, []); | |
21 | 31 | return ( |
22 | - <DrawerForm<{ | |
23 | - name: string; | |
24 | - company: string; | |
25 | - }> | |
26 | - title="新建表单" | |
32 | + <DrawerForm | |
33 | + open | |
34 | + title="合并开票" | |
27 | 35 | resize={{ |
28 | 36 | onResize() { |
29 | 37 | console.log('resize!'); |
30 | 38 | }, |
31 | 39 | maxWidth: window.innerWidth * 0.8, |
32 | - minWidth: 300, | |
40 | + minWidth: 400, | |
33 | 41 | }} |
34 | 42 | form={form} |
35 | - /*trigger={ | |
36 | - <Button type="primary"> | |
37 | - <PlusOutlined /> | |
38 | - 新建表单 | |
39 | - </Button> | |
40 | - }*/ | |
41 | - open={true} | |
42 | 43 | autoFocusFirstInput |
43 | 44 | drawerProps={{ |
44 | 45 | destroyOnClose: true, |
45 | 46 | }} |
47 | + submitter={{ | |
48 | + render: (props, defaultDoms) => { | |
49 | + return [ | |
50 | + <InvoiceModal | |
51 | + key={'invoicePreview'} | |
52 | + button={<Button type="primary"> 发票预览 </Button>} | |
53 | + getRecord={form.getFieldsValue} | |
54 | + />, | |
55 | + ...defaultDoms, | |
56 | + ]; | |
57 | + }, | |
58 | + }} | |
46 | 59 | submitTimeout={2000} |
47 | 60 | onFinish={async (values) => { |
48 | - await waitTime(2000); | |
49 | - console.log(values); | |
50 | - console.log(subOrders); | |
51 | - console.log(totalPayment); | |
52 | - message.success('提交成功'); | |
61 | + postServiceInvoiceApplyInvoice({ | |
62 | + data: { | |
63 | + ...values, | |
64 | + subOrderIds: dataList.map((item) => { | |
65 | + return item.id; | |
66 | + }), | |
67 | + }, | |
68 | + }); | |
53 | 69 | onClose(); |
54 | - // 不返回不会关闭弹框 | |
55 | - return true; | |
70 | + }} | |
71 | + onOpenChange={(val) => { | |
72 | + return !val && setVisible(); | |
56 | 73 | }} |
57 | 74 | > |
58 | - <ProForm.Group> | |
59 | - <ProFormText | |
60 | - name="name" | |
61 | - width="md" | |
62 | - label="签约客户名称" | |
63 | - tooltip="最长为 24 位" | |
64 | - placeholder="请输入名称" | |
65 | - /> | |
66 | - <ProFormText | |
67 | - rules={[ | |
68 | - { | |
69 | - required: true, | |
70 | - }, | |
71 | - ]} | |
72 | - width="md" | |
73 | - name="company" | |
74 | - label="我方公司名称" | |
75 | - placeholder="请输入名称" | |
76 | - /> | |
77 | - </ProForm.Group> | |
78 | - <ProForm.Group> | |
79 | - <ProFormText | |
80 | - width="md" | |
81 | - name="contract" | |
82 | - label="合同名称" | |
83 | - placeholder="请输入名称" | |
84 | - /> | |
85 | - <ProFormDateRangePicker name="contractTime" label="合同生效时间" /> | |
86 | - </ProForm.Group> | |
87 | - <ProForm.Group> | |
88 | - <ProFormSelect | |
89 | - options={[ | |
90 | - { | |
91 | - value: 'chapter', | |
92 | - label: '盖章后生效', | |
93 | - }, | |
94 | - ]} | |
95 | - width="xs" | |
96 | - name="useMode" | |
97 | - label="合同约定生效方式" | |
98 | - /> | |
99 | - <ProFormSelect | |
100 | - width="xs" | |
101 | - options={[ | |
102 | - { | |
103 | - value: 'time', | |
104 | - label: '履行完终止', | |
105 | - }, | |
106 | - ]} | |
107 | - formItemProps={{ | |
108 | - style: { | |
109 | - margin: 0, | |
110 | - }, | |
111 | - }} | |
112 | - name="unusedMode" | |
113 | - label="合同约定失效效方式" | |
114 | - /> | |
115 | - </ProForm.Group> | |
116 | - <ProFormText width="sm" name="id" label="主合同编号" /> | |
75 | + <ProFormList | |
76 | + name="subOrderIdObjs" | |
77 | + readonly={true} | |
78 | + label="开票订单" | |
79 | + initialValue={dataList.map((item) => { | |
80 | + return { | |
81 | + value: item.id, | |
82 | + }; | |
83 | + })} | |
84 | + deleteIconProps={false} | |
85 | + > | |
86 | + <ProFormGroup key="group"> | |
87 | + <ProFormText readonly={true} name="value" label="" /> | |
88 | + </ProFormGroup> | |
89 | + </ProFormList> | |
90 | + <ProFormText | |
91 | + rules={[ | |
92 | + { | |
93 | + required: true, | |
94 | + }, | |
95 | + ]} | |
96 | + width="md" | |
97 | + name="partyAName" | |
98 | + label="购方名称" | |
99 | + initialValue={mainOrder.institution} | |
100 | + placeholder="请输入名称" | |
101 | + /> | |
117 | 102 | <ProFormText |
118 | - name="project" | |
119 | - disabled | |
120 | - label="项目名称" | |
121 | - initialValue="xxxx项目" | |
103 | + rules={[ | |
104 | + { | |
105 | + required: true, | |
106 | + }, | |
107 | + ]} | |
108 | + width="md" | |
109 | + name="partyATaxid" | |
110 | + label="购方税号" | |
111 | + placeholder="请输入名称" | |
122 | 112 | /> |
123 | 113 | <ProFormText |
124 | - width="xs" | |
125 | - name="mangerName" | |
126 | - disabled | |
127 | - label="商务经理" | |
128 | - initialValue="启途" | |
114 | + width="md" | |
115 | + name="partyAOpenBank" | |
116 | + label="开户银行" | |
117 | + placeholder="请输入名称" | |
118 | + /> | |
119 | + <ProFormText | |
120 | + width="md" | |
121 | + name="partyABankAccount" | |
122 | + label="开户行账号" | |
123 | + placeholder="请输入名称" | |
124 | + /> | |
125 | + <ProFormMoney | |
126 | + label="开票金额" | |
127 | + name="price" | |
128 | + locale="zh-CN" | |
129 | + rules={[{ required: true, message: '请填写开票金额!' }]} | |
130 | + initialValue={dataList.reduce((accumulator, currentValue) => { | |
131 | + return accumulator + currentValue.subOrderPayment; | |
132 | + }, 0)} | |
133 | + /> | |
134 | + <ProFormSelect | |
135 | + name="invoicingType" | |
136 | + label="开具类型" | |
137 | + request={async () => { | |
138 | + let invoicingTypeRet = await postServiceConstInvoicingType(); | |
139 | + let options = enumToSelect(invoicingTypeRet.data); | |
140 | + return options; | |
141 | + }} | |
142 | + placeholder="请选择开具类型" | |
143 | + rules={[{ required: true, message: '请选择开具类型!' }]} | |
144 | + /> | |
145 | + <ProFormSelect | |
146 | + name="type" | |
147 | + label="开票类型" | |
148 | + placeholder="请选择开票类型" | |
149 | + rules={[{ required: true, message: '请选择开票类型!' }]} | |
150 | + request={async () => { | |
151 | + let invoiceTypeRet = await postServiceConstInvoiceType(); | |
152 | + let options = enumToSelect(invoiceTypeRet.data); | |
153 | + return options; | |
154 | + }} | |
155 | + /> | |
156 | + <ProFormSelect | |
157 | + name="partyB" | |
158 | + label="开票收款单位" | |
159 | + request={async () => { | |
160 | + const res = await postServiceConstGetPayeeEnum(); | |
161 | + let options = res?.data?.map((payee: any) => { | |
162 | + return { | |
163 | + ...payee, | |
164 | + label: payee.payeeName, | |
165 | + value: payee.name, | |
166 | + }; | |
167 | + }); | |
168 | + return options; | |
169 | + }} | |
170 | + onChange={(_, option) => { | |
171 | + if (option) { | |
172 | + form.setFieldsValue({ | |
173 | + partyBName: option.payeeName, | |
174 | + partyBTaxid: option.taxId, | |
175 | + }); | |
176 | + } | |
177 | + }} | |
178 | + placeholder="请选择收款单位" | |
179 | + rules={[{ required: true, message: '请选择收款单位!' }]} | |
180 | + /> | |
181 | + <ProFormText | |
182 | + name="partyBName" | |
183 | + label="开票收款单位名称" | |
184 | + hidden | |
185 | + rules={[{ required: true, message: '请选择收款单位!' }]} | |
186 | + /> | |
187 | + <ProFormText | |
188 | + name="partyBTaxid" | |
189 | + label="开票收款单位税号" | |
190 | + hidden | |
191 | + rules={[{ required: true, message: '请选择收款单位!' }]} | |
192 | + /> | |
193 | + <ProFormSelect | |
194 | + name="isUrgent" | |
195 | + label="是否加急" | |
196 | + valueEnum={{ | |
197 | + true: '是', | |
198 | + false: '否', | |
199 | + }} | |
200 | + placeholder="请选择是否加急" | |
201 | + rules={[{ required: true, message: '请选择是否加急!' }]} | |
202 | + /> | |
203 | + <ProFormList | |
204 | + name="invoiceDetails" | |
205 | + label="开票明细" | |
206 | + initialValue={dataList.map((item) => { | |
207 | + return { | |
208 | + subOrderId: item.id, | |
209 | + projectName: item.productName, | |
210 | + specification: item.parameters, | |
211 | + unit: item.unit, | |
212 | + quantity: item.quantity, | |
213 | + price: item.productPrice, | |
214 | + totalPrice: item.totalPayment, | |
215 | + }; | |
216 | + })} | |
217 | + rules={[ | |
218 | + { | |
219 | + required: true, | |
220 | + validator: async (_, value) => { | |
221 | + console.log(value); | |
222 | + if (value && value.length > 0) { | |
223 | + return; | |
224 | + } | |
225 | + throw new Error('至少要有一项!'); | |
226 | + }, | |
227 | + }, | |
228 | + ]} | |
229 | + itemRender={(doms, listMeta) => { | |
230 | + console.log(listMeta); | |
231 | + return ( | |
232 | + <ProCard | |
233 | + bordered | |
234 | + extra={doms.action} | |
235 | + title={'明细' + (listMeta.index + 1)} | |
236 | + style={{ | |
237 | + marginBlockEnd: 8, | |
238 | + }} | |
239 | + > | |
240 | + <ProFormText | |
241 | + key={'subOrderId' + listMeta.index} | |
242 | + name="subOrderId" | |
243 | + label="子订单id" | |
244 | + hidden | |
245 | + /> | |
246 | + <ProFormSelect | |
247 | + key={'projectName' + listMeta.index} | |
248 | + width="md" | |
249 | + showSearch | |
250 | + name="projectName" | |
251 | + request={async (value) => { | |
252 | + const keywords = value.keyWords; | |
253 | + const res = await postServiceConstListInvoiceDetailNames({ | |
254 | + data: { | |
255 | + nameLike: keywords, | |
256 | + }, | |
257 | + }); | |
258 | + let options = res?.data?.map((c: any) => { | |
259 | + return { | |
260 | + ...c, | |
261 | + label: | |
262 | + '*' + | |
263 | + c.productAndServiceCatagoryAbbreviation + | |
264 | + '*' + | |
265 | + c.name, | |
266 | + value: | |
267 | + '*' + | |
268 | + c.productAndServiceCatagoryAbbreviation + | |
269 | + '*' + | |
270 | + c?.name, | |
271 | + key: c.id, | |
272 | + }; | |
273 | + }); | |
274 | + return options; | |
275 | + }} | |
276 | + fieldProps={{ | |
277 | + filterOption() { | |
278 | + return true; | |
279 | + }, | |
280 | + }} | |
281 | + onChange={(_, option) => { | |
282 | + let index = listMeta.index; | |
283 | + let copyList = form.getFieldValue('invoiceDetails'); | |
284 | + let currentData = copyList[index]; | |
285 | + currentData.projectName = | |
286 | + '*' + | |
287 | + option.productAndServiceCatagoryAbbreviation + | |
288 | + '*' + | |
289 | + option.name; | |
290 | + currentData.specification = option.specification; | |
291 | + currentData.unit = option.unit; | |
292 | + form.setFieldValue('invoiceDetails', copyList); | |
293 | + }} | |
294 | + debounceTime={1000} | |
295 | + label="项目名称" | |
296 | + placeholder="请输入名称" | |
297 | + /> | |
298 | + <ProFormText | |
299 | + key={'specification' + listMeta.index} | |
300 | + name="specification" | |
301 | + label="规格型号" | |
302 | + placeholder="请输入名称" | |
303 | + /> | |
304 | + <ProFormText | |
305 | + key={'unit' + listMeta.index} | |
306 | + name="unit" | |
307 | + label="单位" | |
308 | + placeholder="请输入名称" | |
309 | + /> | |
310 | + <ProFormDigit | |
311 | + key={'quantity' + listMeta.index} | |
312 | + label="数量" | |
313 | + name="quantity" | |
314 | + min={0} | |
315 | + /> | |
316 | + <ProFormDigit | |
317 | + key={'price' + listMeta.index} | |
318 | + label="单价" | |
319 | + name="price" | |
320 | + min={0} | |
321 | + /> | |
322 | + <ProFormMoney | |
323 | + key={'totalPrice' + listMeta.index} | |
324 | + label="金额" | |
325 | + name="totalPrice" | |
326 | + locale="zh-CN" | |
327 | + /> | |
328 | + </ProCard> | |
329 | + ); | |
330 | + }} | |
331 | + ></ProFormList> | |
332 | + <ProFormTextArea | |
333 | + name="applyInvoicingNotes" | |
334 | + label="备注" | |
335 | + placeholder="请输入名称" | |
129 | 336 | /> |
130 | 337 | </DrawerForm> |
131 | 338 | ); | ... | ... |
src/pages/Order/components/ReissueModal.tsx
... | ... | @@ -13,7 +13,7 @@ import { |
13 | 13 | import { Form } from 'antd'; |
14 | 14 | import { useEffect, useState } from 'react'; |
15 | 15 | |
16 | -export default ({ setVisible, mainOrder, onClose }) => { | |
16 | +export default ({ setVisible, subOrders, onClose }) => { | |
17 | 17 | const [invoiceSelectList, setInvoiceSelectList] = useState([]); |
18 | 18 | const [mainOrders, setMainOrders] = useState(''); |
19 | 19 | const [submitting, setSubmitting] = useState(false); |
... | ... | @@ -21,10 +21,9 @@ export default ({ setVisible, mainOrder, onClose }) => { |
21 | 21 | const [form] = Form.useForm<{ invoiceId: string; notes: string }>(); |
22 | 22 | |
23 | 23 | let getInvoiceSelectList = async () => { |
24 | - console.log(mainOrder); | |
25 | 24 | const res = await postServiceInvoiceFindInvoice({ |
26 | 25 | data: { |
27 | - mainOrderId: mainOrder.id, | |
26 | + subOrderIdIn: subOrders.map((item) => item.id), | |
28 | 27 | }, |
29 | 28 | }); |
30 | 29 | setInvoiceSelectList([]); | ... | ... |
src/pages/Order/constant.ts
... | ... | @@ -117,11 +117,10 @@ export const CHECK_TYPE = { |
117 | 117 | */ |
118 | 118 | export const getNeedInvoicing = (subOrder: any) => { |
119 | 119 | if (subOrder.invoicingTime !== null && subOrder.invoicingTime !== undefined) { |
120 | - if (subOrder.afterInvoicingStatus === 'REISSUE') { | |
121 | - return '重新开票'; | |
122 | - } else { | |
123 | - return '已开票'; | |
124 | - } | |
120 | + return '已开票'; | |
121 | + } | |
122 | + if (subOrder.afterInvoicingStatus === 'REISSUE') { | |
123 | + return '重新开票'; | |
125 | 124 | } |
126 | 125 | if (subOrder.invoicingStatus === 'UN_INVOICE') { |
127 | 126 | return '不需开票'; |
... | ... | @@ -232,6 +231,7 @@ export const AFTER_INVOICING_STATUS = { |
232 | 231 | URGENT_INVOICE_AUDIT_NOTPASS: '加急审核失败', |
233 | 232 | PARTIAL_INVOICING: '部分开票', |
234 | 233 | COMPLETE_INVOICING: '完全开票', |
234 | + INVOICING: '开票中', | |
235 | 235 | REISSUE: '重新开票', |
236 | 236 | }; |
237 | 237 | |
... | ... | @@ -277,6 +277,7 @@ export const TAGS_COLOR = new Map<string, string>([ |
277 | 277 | ['AUDIT_PASS', 'success'], |
278 | 278 | ['AUDIT_NOTPASS', 'error'], |
279 | 279 | ['WAIT_CONFIRM_DELIVER_AFTER_INVOICE', 'processing'], |
280 | + ['INVOICING', 'processing'], | |
280 | 281 | ['SALES_CONFIRM', 'warning'], |
281 | 282 | ['URGENT_INVOICE_AUDIT_NOTPASS', 'red'], |
282 | 283 | ['REISSUE', 'processing'], |
... | ... | @@ -426,6 +427,12 @@ export const MAIN_ORDER_COLUMNS = [ |
426 | 427 | hideInTable: true, |
427 | 428 | }, |
428 | 429 | { |
430 | + title: '子订单编号', | |
431 | + dataIndex: 'subOrderId', | |
432 | + valueType: 'text', | |
433 | + hideInTable: true, | |
434 | + }, | |
435 | + { | |
429 | 436 | title: '销售代表', |
430 | 437 | dataIndex: 'salesCode', |
431 | 438 | valueType: 'text', | ... | ... |
src/pages/Order/index.tsx
... | ... | @@ -6,6 +6,8 @@ import ReissueModal from '@/pages/Order/components/ReissueModal'; |
6 | 6 | import { |
7 | 7 | postKingdeeRepSalBillOutbound, |
8 | 8 | postKingdeeRepSalOrderSave, |
9 | + postServiceConstCanApplyAfterInvoicingStatus, | |
10 | + postServiceInvoiceCancelApply, | |
9 | 11 | postServiceOrderCancelSend, |
10 | 12 | postServiceOrderGetCurrentOptNode, |
11 | 13 | postServiceOrderNoNeedSend, |
... | ... | @@ -127,8 +129,6 @@ const OrderPage = () => { |
127 | 129 | const [allMainChecked, setAllMainChecked] = useState(false); |
128 | 130 | const [imagesViewerModalVisible, setImagesViewerModalVisible] = |
129 | 131 | useState<boolean>(false); |
130 | - const [InvoicingDrawerFormVisible, setInvoicingDrawerFormVisible] = | |
131 | - useState<boolean>(false); | |
132 | 132 | const [data, setData] = useState([]); //列表数据 |
133 | 133 | const [notesEditVisible, setNotesEditVisible] = useState<boolean>(false); |
134 | 134 | const [financialMergeDrawerVisible, setFinancialMergeDrawerVisible] = |
... | ... | @@ -159,6 +159,8 @@ const OrderPage = () => { |
159 | 159 | useState<boolean>(false); |
160 | 160 | const [procureConvertModalVisible, setProcureConvertModalVisible] = |
161 | 161 | useState<boolean>(false); |
162 | + const [invoicingDrawerFormVisible, setInvoicingDrawerFormVisible] = | |
163 | + useState<boolean>(false); | |
162 | 164 | const [confirmReceiptVisible, setConfirmReceiptVisible] = |
163 | 165 | useState<boolean>(false); |
164 | 166 | const [productionTimeModalVisible, setProductionTimeModalVisible] = |
... | ... | @@ -197,6 +199,8 @@ const OrderPage = () => { |
197 | 199 | shippingWarehouseChangeModalVisible, |
198 | 200 | setShippingWarehouseChangeModalVisible, |
199 | 201 | ] = useState(false); |
202 | + const [canApplyAfterInvoicingStatus, setCanApplyAfterInvoicingStatus] = | |
203 | + useState([]); | |
200 | 204 | const [ids, setIds] = useState([]); |
201 | 205 | const [recordOptNode, setRecordOptNode] = useState(null); |
202 | 206 | const roleCode = userInfo?.roleSmallVO?.code; |
... | ... | @@ -223,13 +227,43 @@ const OrderPage = () => { |
223 | 227 | }; |
224 | 228 | |
225 | 229 | const refreshTable = () => { |
226 | - console.log('刷新表格'); | |
227 | 230 | mainTableRef.current?.reload(); |
228 | 231 | //刷新表格数据的时候,取消选中行 |
229 | 232 | setSelectedRows([]); |
230 | 233 | setSelectedSubOrderKeys([]); |
231 | 234 | }; |
232 | 235 | |
236 | + /*useEffect(() => { | |
237 | + let initAfterInvoicingStatus = async () => { | |
238 | + const afteInvoicingStatus = await getAfterInvoicingStatus(); | |
239 | + setAfterInvoicingStatus(afteInvoicingStatus); | |
240 | + }; | |
241 | + initAfterInvoicingStatus(); | |
242 | + }, []);*/ | |
243 | + | |
244 | + useEffect(() => { | |
245 | + // 使用URLSearchParams来解析查询参数 | |
246 | + const params = new URLSearchParams(location.search); | |
247 | + const id = params.get('id'); | |
248 | + const subOrderId = params.get('subOrderId'); | |
249 | + if (id) { | |
250 | + mainTableFormRef.current?.setFieldValue('id', id); | |
251 | + } | |
252 | + if (subOrderId) { | |
253 | + mainTableFormRef.current?.setFieldValue('subOrderId', subOrderId); | |
254 | + } | |
255 | + }, []); | |
256 | + | |
257 | + useEffect(() => { | |
258 | + const initEnum = async () => { | |
259 | + let invoiceTypeRet = await postServiceConstCanApplyAfterInvoicingStatus(); | |
260 | + if (invoiceTypeRet.result === RESPONSE_CODE.SUCCESS) { | |
261 | + setCanApplyAfterInvoicingStatus(invoiceTypeRet.data); | |
262 | + } | |
263 | + }; | |
264 | + initEnum(); | |
265 | + }, []); | |
266 | + | |
233 | 267 | /** |
234 | 268 | * 复制订单到剪贴板 |
235 | 269 | * @param record |
... | ... | @@ -583,9 +617,6 @@ const OrderPage = () => { |
583 | 617 | mainOrderSelectedMap.clear(); |
584 | 618 | subOrderSelectedMap.clear(); |
585 | 619 | } |
586 | - | |
587 | - console.log(mainOrderSelectedMap); | |
588 | - console.log(subOrderSelectedMap); | |
589 | 620 | }; |
590 | 621 | |
591 | 622 | //表头渲染 |
... | ... | @@ -1324,8 +1355,8 @@ const OrderPage = () => { |
1324 | 1355 | type="link" |
1325 | 1356 | onClick={() => { |
1326 | 1357 | setCurrentMainId(record.id); |
1358 | + setCurretnOptSubId(optRecord.id); | |
1327 | 1359 | setReissueVisible(true); |
1328 | - console.log(reissueVisible); | |
1329 | 1360 | }} |
1330 | 1361 | > |
1331 | 1362 | 重新开票 |
... | ... | @@ -1356,7 +1387,6 @@ const OrderPage = () => { |
1356 | 1387 | className="p-0" |
1357 | 1388 | type="link" |
1358 | 1389 | onClick={() => { |
1359 | - console.log('here'); | |
1360 | 1390 | setCurrentMainId(record.id); |
1361 | 1391 | setCurretnOptSubId(optRecord.id); |
1362 | 1392 | setCheckVisible(true); |
... | ... | @@ -1466,7 +1496,7 @@ const OrderPage = () => { |
1466 | 1496 | '' |
1467 | 1497 | )} |
1468 | 1498 | |
1469 | - {optRecord.subPath?.includes('saleCancelInvoicing') ? ( | |
1499 | + {/*{optRecord.subPath?.includes('saleCancelInvoicing') ? ( | |
1470 | 1500 | <ButtonConfirm |
1471 | 1501 | className="p-0" |
1472 | 1502 | title="确认取消申请开票?" |
... | ... | @@ -1486,6 +1516,27 @@ const OrderPage = () => { |
1486 | 1516 | /> |
1487 | 1517 | ) : ( |
1488 | 1518 | '' |
1519 | + )}*/} | |
1520 | + {optRecord.subPath?.includes('saleCancelInvoicing') ? ( | |
1521 | + <ButtonConfirm | |
1522 | + className="p-0" | |
1523 | + title="确认取消申请开票?" | |
1524 | + text="取消申请" | |
1525 | + onConfirm={async () => { | |
1526 | + let res = await postServiceInvoiceCancelApply({ | |
1527 | + data: { | |
1528 | + subOrderIds: [optRecord.id], | |
1529 | + }, | |
1530 | + }); | |
1531 | + | |
1532 | + if (res && res.result === RESPONSE_CODE.SUCCESS) { | |
1533 | + message.success(res.message); | |
1534 | + refreshTable(); | |
1535 | + } | |
1536 | + }} | |
1537 | + /> | |
1538 | + ) : ( | |
1539 | + '' | |
1489 | 1540 | )} |
1490 | 1541 | {optRecord.subPath?.includes('noNeedInvoicingEdit') ? ( |
1491 | 1542 | <Button |
... | ... | @@ -1701,7 +1752,7 @@ const OrderPage = () => { |
1701 | 1752 | '' |
1702 | 1753 | )} |
1703 | 1754 | |
1704 | - {optRecord.subPath?.includes('applyInvoicing') ? ( | |
1755 | + {/*{optRecord.subPath?.includes('applyInvoicing') ? ( | |
1705 | 1756 | <Button |
1706 | 1757 | className="p-0" |
1707 | 1758 | type="link" |
... | ... | @@ -1716,6 +1767,23 @@ const OrderPage = () => { |
1716 | 1767 | </Button> |
1717 | 1768 | ) : ( |
1718 | 1769 | '' |
1770 | + )}*/} | |
1771 | + | |
1772 | + {optRecord.subPath?.includes('applyInvoicing') ? ( | |
1773 | + <Button | |
1774 | + className="p-0" | |
1775 | + type="link" | |
1776 | + onClick={() => { | |
1777 | + setInvoicingDrawerFormVisible(true); | |
1778 | + createOptObject(optRecord.id, record.id); | |
1779 | + setIsEdit(false); | |
1780 | + setIsMainOrder(false); | |
1781 | + }} | |
1782 | + > | |
1783 | + 申请开票 | |
1784 | + </Button> | |
1785 | + ) : ( | |
1786 | + '' | |
1719 | 1787 | )} |
1720 | 1788 | |
1721 | 1789 | {optRecord.subPath?.includes('checkOrder') ? ( |
... | ... | @@ -2231,9 +2299,6 @@ const OrderPage = () => { |
2231 | 2299 | |
2232 | 2300 | setSelectedSubOrderKeys(newSelectedSubOrderKeys); |
2233 | 2301 | setSelectedRows(currentMainOrderSelectedSubOrderList); |
2234 | - | |
2235 | - console.log(mainOrderSelectedMap); | |
2236 | - console.log(subOrderSelectedMap); | |
2237 | 2302 | }, |
2238 | 2303 | selectedRowKeys: selectedSubOrderKeys, |
2239 | 2304 | // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom |
... | ... | @@ -2711,7 +2776,6 @@ const OrderPage = () => { |
2711 | 2776 | onClick={() => { |
2712 | 2777 | setCurrentMainId(record.id); |
2713 | 2778 | setReissueVisible(true); |
2714 | - console.log(reissueVisible); | |
2715 | 2779 | }} |
2716 | 2780 | > |
2717 | 2781 | 重新开票 |
... | ... | @@ -3150,7 +3214,7 @@ const OrderPage = () => { |
3150 | 3214 | '' |
3151 | 3215 | )} |
3152 | 3216 | |
3153 | - {record.mainPath?.includes('applyInvoicing') ? ( | |
3217 | + {/*{record.mainPath?.includes('applyInvoicing') ? ( | |
3154 | 3218 | <Button |
3155 | 3219 | type="link" |
3156 | 3220 | className="p-0" |
... | ... | @@ -3185,6 +3249,43 @@ const OrderPage = () => { |
3185 | 3249 | </Button> |
3186 | 3250 | ) : ( |
3187 | 3251 | '' |
3252 | + )}*/} | |
3253 | + | |
3254 | + {record.mainPath?.includes('applyInvoicing') ? ( | |
3255 | + <Button | |
3256 | + type="link" | |
3257 | + className="p-0" | |
3258 | + onClick={() => { | |
3259 | + let selectedSubOrders = subOrderSelectedMap.get( | |
3260 | + record.id, | |
3261 | + ); | |
3262 | + if (selectedSubOrders === undefined) { | |
3263 | + selectedSubOrders = record.subOrderInformationLists; | |
3264 | + } | |
3265 | + for (let i = 0; i < selectedSubOrders.length; i++) { | |
3266 | + if ( | |
3267 | + selectedSubOrders[i].invoicingStatus === | |
3268 | + 'UN_INVOICE' || | |
3269 | + selectedSubOrders[i].afterInvoicingStatus === | |
3270 | + 'APPLY_FOR_INVOICING' | |
3271 | + ) { | |
3272 | + message.error( | |
3273 | + '请选择需要开票且未申请开票的子订单进行申请', | |
3274 | + ); | |
3275 | + return; | |
3276 | + } | |
3277 | + } | |
3278 | + | |
3279 | + createOptObject(null, record.id); | |
3280 | + setInvoicingDrawerFormVisible(true); | |
3281 | + setIsEdit(false); | |
3282 | + setIsMainOrder(false); | |
3283 | + }} | |
3284 | + > | |
3285 | + 申请开票 | |
3286 | + </Button> | |
3287 | + ) : ( | |
3288 | + '' | |
3188 | 3289 | )} |
3189 | 3290 | |
3190 | 3291 | {record.mainPath?.includes('updateOrder') ? ( |
... | ... | @@ -3402,7 +3503,6 @@ const OrderPage = () => { |
3402 | 3503 | selectedSubOrders = record.subOrderInformationLists; |
3403 | 3504 | } |
3404 | 3505 | |
3405 | - console.log(selectedSubOrders); | |
3406 | 3506 | for (let i = 0; i < selectedSubOrders.length; i++) { |
3407 | 3507 | if ( |
3408 | 3508 | selectedSubOrders[i].afterInvoicingStatus !== |
... | ... | @@ -3990,39 +4090,39 @@ const OrderPage = () => { |
3990 | 4090 | //导出按钮配置 |
3991 | 4091 | const auditItems: MenuProps['items'] = [ |
3992 | 4092 | { |
3993 | - label: '领导审核', | |
3994 | - key: '2', | |
4093 | + label: '后置审核', | |
4094 | + key: '1', | |
3995 | 4095 | onClick: async () => { |
3996 | 4096 | setIsMainOrder(true); |
3997 | 4097 | setCheckVisible(true); |
3998 | - setOrderCheckType(CHECK_TYPE.LEADER_AUDIT); | |
4098 | + setOrderCheckType(CHECK_TYPE.WAITING_FOR_POST_AUDIT); | |
3999 | 4099 | }, |
4000 | 4100 | }, |
4001 | 4101 | { |
4002 | - label: '后置审核', | |
4003 | - key: '1', | |
4102 | + label: '加急开票审核', | |
4103 | + key: '2', | |
4004 | 4104 | onClick: async () => { |
4005 | 4105 | setIsMainOrder(true); |
4006 | 4106 | setCheckVisible(true); |
4007 | - setOrderCheckType(CHECK_TYPE.WAITING_FOR_POST_AUDIT); | |
4107 | + setOrderCheckType(CHECK_TYPE.URGENT_INVOICE_AUDITING); | |
4008 | 4108 | }, |
4009 | 4109 | }, |
4010 | 4110 | { |
4011 | - label: '修改申请审核', | |
4111 | + label: '领导审核', | |
4012 | 4112 | key: '3', |
4013 | 4113 | onClick: async () => { |
4014 | 4114 | setIsMainOrder(true); |
4015 | 4115 | setCheckVisible(true); |
4016 | - setOrderCheckType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT); | |
4116 | + setOrderCheckType(CHECK_TYPE.LEADER_AUDIT); | |
4017 | 4117 | }, |
4018 | 4118 | }, |
4019 | 4119 | { |
4020 | - label: '加急开票审核', | |
4120 | + label: '修改申请审核', | |
4021 | 4121 | key: '4', |
4022 | 4122 | onClick: async () => { |
4023 | 4123 | setIsMainOrder(true); |
4024 | 4124 | setCheckVisible(true); |
4025 | - setOrderCheckType(CHECK_TYPE.URGENT_INVOICE_AUDITING); | |
4125 | + setOrderCheckType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT); | |
4026 | 4126 | }, |
4027 | 4127 | }, |
4028 | 4128 | ]; |
... | ... | @@ -4116,19 +4216,6 @@ const OrderPage = () => { |
4116 | 4216 | ); |
4117 | 4217 | } |
4118 | 4218 | |
4119 | - <Button | |
4120 | - type="primary" | |
4121 | - key="out" | |
4122 | - onClick={() => { | |
4123 | - setIsEdit(false); | |
4124 | - setIsMainOrder(true); | |
4125 | - setInvoicingDrawerFormVisible(true); | |
4126 | - }} | |
4127 | - disabled={selectedSubOrderKeys?.length === 0} | |
4128 | - > | |
4129 | - 申请开票 | |
4130 | - </Button>; | |
4131 | - | |
4132 | 4219 | if (rolePath?.includes('mergeInvoicing')) { |
4133 | 4220 | toolBtns.push( |
4134 | 4221 | <Button |
... | ... | @@ -4165,6 +4252,35 @@ const OrderPage = () => { |
4165 | 4252 | ); |
4166 | 4253 | } |
4167 | 4254 | |
4255 | + toolBtns.push( | |
4256 | + <Button | |
4257 | + type="primary" | |
4258 | + key="inv" | |
4259 | + onClick={() => { | |
4260 | + setIsMainOrder(true); | |
4261 | + let flat = [...subOrderSelectedMap.values()].flat(); | |
4262 | + //遍历flat,判断afterInvoicingStatusList存在于canApplyAfterInvoicingStatus | |
4263 | + flat.forEach((item) => { | |
4264 | + if ( | |
4265 | + item.invoicingStatus === 'UN_INVOICE' || | |
4266 | + (item.afterInvoicingStatus !== null && | |
4267 | + !canApplyAfterInvoicingStatus.includes( | |
4268 | + item.afterInvoicingStatus, | |
4269 | + )) | |
4270 | + ) { | |
4271 | + message.error('存在不能进行开票的订单'); | |
4272 | + return; | |
4273 | + } | |
4274 | + }); | |
4275 | + //遍历afterInvoicingStatusList | |
4276 | + setInvoicingDrawerFormVisible(true); | |
4277 | + }} | |
4278 | + disabled={selectedSubOrderKeys?.length === 0} | |
4279 | + > | |
4280 | + 申请开票 | |
4281 | + </Button>, | |
4282 | + ); | |
4283 | + | |
4168 | 4284 | if (rolePath?.includes('addOrder')) { |
4169 | 4285 | toolBtns.push( |
4170 | 4286 | <Button |
... | ... | @@ -4210,15 +4326,6 @@ const OrderPage = () => { |
4210 | 4326 | return toolBtns; |
4211 | 4327 | } |
4212 | 4328 | |
4213 | - useEffect(() => { | |
4214 | - // 使用URLSearchParams来解析查询参数 | |
4215 | - const params = new URLSearchParams(location.search); | |
4216 | - const id = params.get('id'); | |
4217 | - if (id) { | |
4218 | - mainTableFormRef.current?.setFieldValue('id', id); | |
4219 | - } | |
4220 | - }, []); | |
4221 | - | |
4222 | 4329 | return ( |
4223 | 4330 | <div className="order-page-container"> |
4224 | 4331 | <div id="resizeDiv"></div> |
... | ... | @@ -4282,7 +4389,10 @@ const OrderPage = () => { |
4282 | 4389 | * 第一次进来这个页面,url带有id的话,会自动填充到查询表单中,但是第一次查询params不会带这个id进来 |
4283 | 4390 | */ |
4284 | 4391 | let orderIds = mainTableFormRef.current?.getFieldValue('id'); |
4392 | + let subOrderId = | |
4393 | + mainTableFormRef.current?.getFieldValue('subOrderId'); | |
4285 | 4394 | params.id = params.id || orderIds; |
4395 | + params.subOrderId = params.subOrderId || subOrderId; | |
4286 | 4396 | if (params.id !== '') { |
4287 | 4397 | params.id = params.id?.replace(/ /g, ''); |
4288 | 4398 | if (params.id?.indexOf(',')) { |
... | ... | @@ -4715,13 +4825,15 @@ const OrderPage = () => { |
4715 | 4825 | <ReissueModal |
4716 | 4826 | setVisible={(val: boolean) => { |
4717 | 4827 | setReissueVisible(val); |
4718 | - console.log(reissueVisible); | |
4719 | 4828 | if (!val) { |
4720 | 4829 | clearOptObject(); |
4721 | 4830 | } |
4722 | 4831 | }} |
4723 | - mainOrder={buildMainOrder()} | |
4724 | - subOrders={buildSubOrders()} | |
4832 | + subOrders={ | |
4833 | + isMainOrder | |
4834 | + ? [...subOrderSelectedMap.values()].flat() | |
4835 | + : buildSubOrders() | |
4836 | + } | |
4725 | 4837 | onClose={() => { |
4726 | 4838 | setReissueVisible(false); |
4727 | 4839 | clearOptObject(); |
... | ... | @@ -4780,24 +4892,28 @@ const OrderPage = () => { |
4780 | 4892 | }} |
4781 | 4893 | /> |
4782 | 4894 | )} |
4783 | - | |
4784 | - {InvoicingDrawerFormVisible && ( | |
4895 | + {invoicingDrawerFormVisible && ( | |
4785 | 4896 | <InvoicingDrawerForm |
4786 | - subOrders={ | |
4897 | + dataList={ | |
4787 | 4898 | isMainOrder |
4788 | 4899 | ? [...subOrderSelectedMap.values()].flat() |
4789 | 4900 | : buildSubOrders() |
4790 | 4901 | } |
4791 | - totalPayment={getApplyInvoicingTotalPayment()} | |
4902 | + setVisible={(val: boolean) => { | |
4903 | + setInvoicingDrawerFormVisible(val); | |
4904 | + if (!val) { | |
4905 | + clearOptObject(); | |
4906 | + } | |
4907 | + }} | |
4908 | + mainOrder={isMainOrder ? getFirstMainOrder() : buildMainOrder()} | |
4792 | 4909 | onClose={() => { |
4793 | - setApplyForInvoicingVisible(false); | |
4794 | - setIsMainOrder(false); | |
4910 | + setInvoicingDrawerFormVisible(false); | |
4911 | + setIsMainOrder(true); | |
4795 | 4912 | clearOptObject(); |
4796 | 4913 | refreshTable(); |
4797 | 4914 | }} |
4798 | - ></InvoicingDrawerForm> | |
4915 | + /> | |
4799 | 4916 | )} |
4800 | - | |
4801 | 4917 | {contextHolder} |
4802 | 4918 | <FloatButton.BackTop visibilityHeight={0} /> |
4803 | 4919 | </div> | ... | ... |
src/services/exportRequest.ts
0 → 100644
1 | +import axios from 'axios'; | |
2 | + | |
3 | +export const excelExport = async ( | |
4 | + url: any = '', | |
5 | + data: any = {}, | |
6 | + exportLoadingDestory: any, | |
7 | +) => { | |
8 | + axios({ | |
9 | + url: url, | |
10 | + method: 'post', | |
11 | + responseType: 'blob', | |
12 | + headers: { Authorization: localStorage.getItem('token') }, | |
13 | + data, | |
14 | + }) | |
15 | + .then((response) => { | |
16 | + // 我这里在拦截器里直接返回的response.data | |
17 | + const body = response.data; | |
18 | + let fileUrl = window.URL.createObjectURL( | |
19 | + new Blob([body], { | |
20 | + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | |
21 | + }), | |
22 | + ); | |
23 | + let a = document.createElement('a'); | |
24 | + a.style.display = 'none'; | |
25 | + a.href = fileUrl; | |
26 | + a.download = '开票记录.xlsx'; | |
27 | + document.body.appendChild(a); | |
28 | + a.click(); | |
29 | + window.URL.revokeObjectURL(a.href); | |
30 | + document.body.removeChild(a); | |
31 | + }) | |
32 | + .catch((error) => { | |
33 | + // 处理错误 | |
34 | + console.error('导出错误', error); | |
35 | + }) | |
36 | + .finally(() => { | |
37 | + exportLoadingDestory(); | |
38 | + }); | |
39 | +}; | ... | ... |
src/utils/index.ts