Commit 325a0b92f06645791df8551013ef8de58eae2345
Merge remote-tracking branch 'origin/master'
Showing
28 changed files
with
4238 additions
and
73 deletions
Too many changes to show.
To preserve performance only 28 of 39 files are displayed.
.umirc.ts
@@ -66,6 +66,20 @@ export default defineConfig({ | @@ -66,6 +66,20 @@ export default defineConfig({ | ||
66 | access: 'canReadAdminAndFinanceAndSales', | 66 | access: 'canReadAdminAndFinanceAndSales', |
67 | }, | 67 | }, |
68 | { | 68 | { |
69 | + name: '课题组管理', | ||
70 | + path: '/researchGroup', | ||
71 | + component: './ResearchGroup', | ||
72 | + icon: 'AccountBookOutlined', | ||
73 | + access: 'canReadAdminAndSales', | ||
74 | + }, | ||
75 | + { | ||
76 | + name: '分期账单', | ||
77 | + path: '/instalment', | ||
78 | + component: './Instalment', | ||
79 | + icon: 'BookOutlined', | ||
80 | + access: 'canReadLinda', | ||
81 | + }, | ||
82 | + { | ||
69 | name: '打印', | 83 | name: '打印', |
70 | path: '/print', | 84 | path: '/print', |
71 | component: './OrderPrint', | 85 | component: './OrderPrint', |
src/access.ts
1 | export default (initialState: API.UserInfo) => { | 1 | export default (initialState: API.UserInfo) => { |
2 | // 在这里按照初始化数据定义项目中的权限,统一管理 | 2 | // 在这里按照初始化数据定义项目中的权限,统一管理 |
3 | // 参考文档 https://umijs.org/docs/max/access | 3 | // 参考文档 https://umijs.org/docs/max/access |
4 | - const { roleSmallVO } = initialState; | 4 | + const { roleSmallVO, username } = initialState; |
5 | const canReadAdmin = roleSmallVO?.code === 'admin'; | 5 | const canReadAdmin = roleSmallVO?.code === 'admin'; |
6 | const canReadProcure = roleSmallVO?.code === 'procure'; | 6 | const canReadProcure = roleSmallVO?.code === 'procure'; |
7 | const canReadFinance = roleSmallVO?.code === 'finance'; | 7 | const canReadFinance = roleSmallVO?.code === 'finance'; |
@@ -11,9 +11,11 @@ export default (initialState: API.UserInfo) => { | @@ -11,9 +11,11 @@ export default (initialState: API.UserInfo) => { | ||
11 | return { | 11 | return { |
12 | canReadAdmin: canReadAdmin, | 12 | canReadAdmin: canReadAdmin, |
13 | canReadProcure: canReadProcure, | 13 | canReadProcure: canReadProcure, |
14 | + canReadLinda: username === 'Linda' || username === '吴量', | ||
14 | canReadAdminAndFinance: canReadFinance || canReadAdmin, | 15 | canReadAdminAndFinance: canReadFinance || canReadAdmin, |
15 | canReadSales: canReadSales, | 16 | canReadSales: canReadSales, |
16 | canReadAdminAndFinanceAndSales: | 17 | canReadAdminAndFinanceAndSales: |
17 | canReadFinance || canReadAdmin || canReadSales, | 18 | canReadFinance || canReadAdmin || canReadSales, |
19 | + canReadAdminAndSales: canReadAdmin || canReadSales, | ||
18 | }; | 20 | }; |
19 | }; | 21 | }; |
src/pages/Instalment/components/comfire/comfire.tsx
0 → 100644
1 | +import { ModalForm } from '@ant-design/pro-components'; | ||
2 | +import { Form, message } from 'antd'; | ||
3 | +import { useState } from 'react'; | ||
4 | + | ||
5 | +const waitTime = (time: number = 100) => { | ||
6 | + return new Promise((resolve) => { | ||
7 | + setTimeout(() => { | ||
8 | + resolve(true); | ||
9 | + }, time); | ||
10 | + }); | ||
11 | +}; | ||
12 | + | ||
13 | +export default ({ currtDid, sureDelete }) => { | ||
14 | + const [form] = Form.useForm<{ name: string; company: string }>(); | ||
15 | + const [ids, setIds] = useState([]); | ||
16 | + | ||
17 | + function getIds() { | ||
18 | + setIds([]); | ||
19 | + setIds(currtDid); | ||
20 | + } | ||
21 | + return ( | ||
22 | + <ModalForm<{ | ||
23 | + name: string; | ||
24 | + company: string; | ||
25 | + }> | ||
26 | + trigger={ | ||
27 | + <a | ||
28 | + onClick={() => { | ||
29 | + getIds(); | ||
30 | + }} | ||
31 | + > | ||
32 | + 删除 | ||
33 | + </a> | ||
34 | + } | ||
35 | + form={form} | ||
36 | + autoFocusFirstInput | ||
37 | + width={190} | ||
38 | + modalProps={{ | ||
39 | + destroyOnClose: true, | ||
40 | + }} | ||
41 | + onFinish={async () => { | ||
42 | + await waitTime(100); | ||
43 | + sureDelete([ids]); | ||
44 | + message.success('提交成功'); | ||
45 | + return true; | ||
46 | + }} | ||
47 | + > | ||
48 | + <br /> | ||
49 | + <h2>确定删除吗</h2> | ||
50 | + </ModalForm> | ||
51 | + ); | ||
52 | +}; |
src/pages/Instalment/components/detail/detail.tsx
0 → 100644
1 | +import { | ||
2 | + postOrderErpOrderStagesAdd, | ||
3 | + postOrderErpOrderStagesPayWaySaveOrUpdate, | ||
4 | + postOrderErpOrderStagesSearch, | ||
5 | + postOrderErpOrderStagesUpload, | ||
6 | +} from '@/services'; | ||
7 | +import { PlusOutlined } from '@ant-design/icons'; | ||
8 | +import { | ||
9 | + ModalForm, | ||
10 | + ProCard, | ||
11 | + ProForm, | ||
12 | + ProFormDatePicker, | ||
13 | + ProFormText, | ||
14 | + ProFormTextArea, | ||
15 | + ProFormUploadButton, | ||
16 | +} from '@ant-design/pro-components'; | ||
17 | +import { Button, Form, message } from 'antd'; | ||
18 | +import { RcFile } from 'antd/es/upload'; | ||
19 | +import { useEffect, useState } from 'react'; | ||
20 | +import PayWayDetail from '../payWayDetail/payWayDetail'; | ||
21 | +import ProductDetail from '../productDetail/productDetail'; | ||
22 | + | ||
23 | +const waitTime = (time: number = 100) => { | ||
24 | + return new Promise((resolve) => { | ||
25 | + setTimeout(() => { | ||
26 | + resolve(true); | ||
27 | + }, time); | ||
28 | + }); | ||
29 | +}; | ||
30 | + | ||
31 | +export default ({ toReload }) => { | ||
32 | + const [form] = Form.useForm<{ name: string; company: string }>(); | ||
33 | + const [contextBody, setContextBody] = useState<OrderStagesWithListItem>({ | ||
34 | + id: undefined, | ||
35 | + contract: undefined, | ||
36 | + dateRange: undefined, | ||
37 | + terminal: undefined, | ||
38 | + orderStagesDeviceVoList: [], | ||
39 | + totalPrice: undefined, | ||
40 | + payWay: '30/30/30/10', | ||
41 | + annex: undefined, | ||
42 | + remark: undefined, | ||
43 | + }); | ||
44 | + const [editProductBody, setEditProductBody] = useState([]); | ||
45 | + const [total, setTotal] = useState(0); | ||
46 | + const [payWayBody, setPayWayBody] = useState([]); | ||
47 | + const [otherBody, setOtherBody] = useState([]); | ||
48 | + const [isDis] = useState(true); | ||
49 | + | ||
50 | + type OrderStagesWithListItem = { | ||
51 | + //文件编号 | ||
52 | + id?: number; | ||
53 | + //合同编号 | ||
54 | + contract?: string; | ||
55 | + //供应商名称 | ||
56 | + vendor?: string; | ||
57 | + //签合同日期 | ||
58 | + dateRange?: Date; | ||
59 | + //终端名称 | ||
60 | + terminal?: string; | ||
61 | + orderStagesDeviceVoList: orderStagesDevice[]; | ||
62 | + //合同总金额 | ||
63 | + totalPrice?: number; | ||
64 | + //付款方式 | ||
65 | + payWay?: string; | ||
66 | + //附件 | ||
67 | + annex?: string; | ||
68 | + //备注 | ||
69 | + remark?: string; | ||
70 | + }; | ||
71 | + | ||
72 | + type orderStagesDevice = { | ||
73 | + //设备id | ||
74 | + dId: number; | ||
75 | + //设备名称 | ||
76 | + deviceName: string; | ||
77 | + //设备型号 | ||
78 | + deviceModel: string; | ||
79 | + //数量 | ||
80 | + count: number; | ||
81 | + //单价 | ||
82 | + unitPrice: number; | ||
83 | + //总价 | ||
84 | + price: number; | ||
85 | + }; | ||
86 | + | ||
87 | + function setSave(value) { | ||
88 | + setOtherBody(value); | ||
89 | + } | ||
90 | + | ||
91 | + useEffect(() => { | ||
92 | + setContextBody({ ...contextBody, totalPrice: total }); | ||
93 | + form.setFieldValue('totalPrice', total); | ||
94 | + }, [total]); | ||
95 | + | ||
96 | + const handleInputChange = (value: string, no: number, priceNow?: number) => { | ||
97 | + if (value === '') { | ||
98 | + message.info('请输入比例!'); | ||
99 | + } else { | ||
100 | + let totalPay = 0; | ||
101 | + const payValue: string[] = value.split('/'); | ||
102 | + let body: | ||
103 | + | ((prevState: never[]) => never[]) | ||
104 | + | { proportion: string; payPrice: number }[] = []; | ||
105 | + if (no === 1) { | ||
106 | + if (payValue.length !== 4) { | ||
107 | + message.warning('比例个数总和不为4个!'); | ||
108 | + } else { | ||
109 | + payValue.forEach((item) => { | ||
110 | + totalPay += Number(item); | ||
111 | + }); | ||
112 | + } | ||
113 | + if (totalPay !== 100) { | ||
114 | + message.warning('比例总和不为100!'); | ||
115 | + } else { | ||
116 | + message.success('输入有效!'); | ||
117 | + payValue.forEach((item) => { | ||
118 | + body.push({ | ||
119 | + proportion: item + '%', | ||
120 | + payPrice: (Number(item) * total) / 100, | ||
121 | + }); | ||
122 | + }); | ||
123 | + setPayWayBody(body); | ||
124 | + } | ||
125 | + } else { | ||
126 | + payValue.forEach((item) => { | ||
127 | + totalPay += Number(item); | ||
128 | + }); | ||
129 | + payValue.forEach((item) => { | ||
130 | + body.push({ | ||
131 | + proportion: item + '%', | ||
132 | + payPrice: (Number(item) * priceNow) / 100, | ||
133 | + }); | ||
134 | + }); | ||
135 | + setPayWayBody(body); | ||
136 | + } | ||
137 | + } | ||
138 | + }; | ||
139 | + | ||
140 | + function getEditProductBody(value) { | ||
141 | + setEditProductBody(value); | ||
142 | + let price = 0; | ||
143 | + value.map((obj) => (price += obj.count * obj.unitPrice)); | ||
144 | + setTotal(price); | ||
145 | + setContextBody({ ...contextBody, orderStagesDeviceVoList: value }); | ||
146 | + if (contextBody.payWay === '') { | ||
147 | + handleInputChange('30/30/30/10', 0, price); | ||
148 | + } else { | ||
149 | + handleInputChange(contextBody.payWay, 0, price); | ||
150 | + } | ||
151 | + } | ||
152 | + | ||
153 | + function refresh() { | ||
154 | + setEditProductBody([]); | ||
155 | + setContextBody({ | ||
156 | + id: undefined, | ||
157 | + contract: undefined, | ||
158 | + dateRange: undefined, | ||
159 | + terminal: undefined, | ||
160 | + orderStagesDeviceVoList: [], | ||
161 | + totalPrice: undefined, | ||
162 | + payWay: '30/30/30/10', | ||
163 | + annex: undefined, | ||
164 | + remark: undefined, | ||
165 | + }); | ||
166 | + handleInputChange('30/30/30/10', 0, 0); | ||
167 | + } | ||
168 | + | ||
169 | + return ( | ||
170 | + <ModalForm<OrderStagesWithListItem> | ||
171 | + title="新建" | ||
172 | + trigger={ | ||
173 | + <Button | ||
174 | + key="button" | ||
175 | + icon={<PlusOutlined />} | ||
176 | + type="primary" | ||
177 | + onClick={() => refresh()} | ||
178 | + > | ||
179 | + 新增 | ||
180 | + </Button> | ||
181 | + } | ||
182 | + form={form} | ||
183 | + autoFocusFirstInput | ||
184 | + modalProps={{ | ||
185 | + destroyOnClose: true, | ||
186 | + }} | ||
187 | + submitTimeout={2000} | ||
188 | + onFinish={async (values) => { | ||
189 | + console.log(values); | ||
190 | + if (editProductBody.length === 0) { | ||
191 | + message.error('请填写产品数据'); | ||
192 | + return false; | ||
193 | + } | ||
194 | + let remakeValue = []; | ||
195 | + | ||
196 | + const formData = new FormData(); | ||
197 | + let toSendEdit = { | ||
198 | + id: values.id || contextBody.id, | ||
199 | + contract: values.contract || contextBody.contract, | ||
200 | + vendor: values.vendor || contextBody.vendor, | ||
201 | + dateRange: values.dateRange || contextBody.dateRange, | ||
202 | + terminal: values.terminal || contextBody.terminal, | ||
203 | + orderStagesDeviceDoList: | ||
204 | + values.orderStagesDeviceVoList || | ||
205 | + contextBody.orderStagesDeviceVoList, | ||
206 | + totalPrice: values.totalPrice || contextBody.totalPrice, | ||
207 | + payWay: values.payWay || contextBody.payWay, | ||
208 | + annex: contextBody.annex, | ||
209 | + remark: values.remark || contextBody.remark, | ||
210 | + }; | ||
211 | + if (values.annex) { | ||
212 | + formData.append('file', values.annex[0].originFileObj as RcFile); | ||
213 | + const res = await postOrderErpOrderStagesUpload({ | ||
214 | + data: formData, | ||
215 | + headers: { | ||
216 | + 'Content-Type': | ||
217 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | ||
218 | + }, | ||
219 | + }); | ||
220 | + if (res.data) { | ||
221 | + toSendEdit.annex = res.data; | ||
222 | + } | ||
223 | + } | ||
224 | + const isSaveOrUpdate = await postOrderErpOrderStagesAdd({ | ||
225 | + data: { ...toSendEdit }, | ||
226 | + }); | ||
227 | + | ||
228 | + if (isSaveOrUpdate) { | ||
229 | + const promises = []; | ||
230 | + | ||
231 | + otherBody.forEach((item) => { | ||
232 | + let remakeItem = { | ||
233 | + ossId: item.ossId, | ||
234 | + number: item.id, | ||
235 | + dateRange: item.payDate, | ||
236 | + fileName: item.fileName, | ||
237 | + }; | ||
238 | + if ( | ||
239 | + typeof item.fileUrl === 'object' && | ||
240 | + item.fileUrl instanceof File | ||
241 | + ) { | ||
242 | + const formData = new FormData(); | ||
243 | + formData.append('file', item.fileUrl as RcFile); | ||
244 | + const uploadPromise = async () => { | ||
245 | + const res = await postOrderErpOrderStagesUpload({ | ||
246 | + data: formData, | ||
247 | + headers: { | ||
248 | + 'Content-Type': | ||
249 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | ||
250 | + }, | ||
251 | + }); | ||
252 | + if (res.data) { | ||
253 | + remakeItem.fileUrl = res.data; | ||
254 | + } | ||
255 | + }; | ||
256 | + promises.push(uploadPromise()); | ||
257 | + } | ||
258 | + remakeValue.push(remakeItem); | ||
259 | + }); | ||
260 | + | ||
261 | + let makeEnd = []; | ||
262 | + const getRetrunIDPromise = async () => { | ||
263 | + let returnOssID = await postOrderErpOrderStagesSearch({ | ||
264 | + data: { contract: values.contract || contextBody.contract }, | ||
265 | + }); | ||
266 | + console.log(returnOssID.data); | ||
267 | + | ||
268 | + if (returnOssID) { | ||
269 | + makeEnd = remakeValue.map((item) => { | ||
270 | + return { ...item, ossId: returnOssID.data[0].id }; | ||
271 | + }); | ||
272 | + } | ||
273 | + }; | ||
274 | + | ||
275 | + promises.push(getRetrunIDPromise()); | ||
276 | + Promise.all(promises).then(async () => { | ||
277 | + await postOrderErpOrderStagesPayWaySaveOrUpdate({ | ||
278 | + data: makeEnd, | ||
279 | + }); | ||
280 | + }); | ||
281 | + toReload(); | ||
282 | + } | ||
283 | + await waitTime(2000); | ||
284 | + message.success('提交成功'); | ||
285 | + return true; | ||
286 | + }} | ||
287 | + > | ||
288 | + <ProCard title="基本信息" headerBordered bordered> | ||
289 | + <ProForm.Group> | ||
290 | + <ProFormText | ||
291 | + width="md" | ||
292 | + name="vendor" | ||
293 | + rules={[{ required: true, message: '此项为必填项' }]} | ||
294 | + label="供应商名称" | ||
295 | + placeholder="请输入" | ||
296 | + initialValue={contextBody.vendor} | ||
297 | + /> | ||
298 | + | ||
299 | + <ProFormText | ||
300 | + width="md" | ||
301 | + name="terminal" | ||
302 | + rules={[{ required: true, message: '此项为必填项' }]} | ||
303 | + label="终端名称" | ||
304 | + placeholder="请输入" | ||
305 | + initialValue={contextBody.terminal} | ||
306 | + /> | ||
307 | + | ||
308 | + <ProFormDatePicker | ||
309 | + name="dateRange" | ||
310 | + width="md" | ||
311 | + label="签合同日期" | ||
312 | + placeholder="请选择日期" | ||
313 | + fieldProps={{ | ||
314 | + format: (value) => value.format('YYYY-MM-DD'), | ||
315 | + }} | ||
316 | + initialValue={contextBody.dateRange} | ||
317 | + /> | ||
318 | + | ||
319 | + <ProFormText | ||
320 | + width="md" | ||
321 | + name="payWay" | ||
322 | + rules={[{ required: true, message: '此项为必填项' }]} | ||
323 | + label="付款比例" | ||
324 | + placeholder="请输入" | ||
325 | + initialValue={contextBody.payWay} | ||
326 | + disabled={!isDis} | ||
327 | + onBlur={(e) => { | ||
328 | + setContextBody({ ...contextBody, payWay: e.target.value }); | ||
329 | + handleInputChange(e.target.value, 1); | ||
330 | + }} | ||
331 | + /> | ||
332 | + | ||
333 | + <ProFormText | ||
334 | + width="md" | ||
335 | + name="contract" | ||
336 | + rules={[{ required: true, message: '此项为必填项' }]} | ||
337 | + label="合同编号" | ||
338 | + placeholder="请输入" | ||
339 | + initialValue={contextBody.contract} | ||
340 | + /> | ||
341 | + | ||
342 | + <ProFormUploadButton | ||
343 | + width="md" | ||
344 | + name="annex" | ||
345 | + max={1} | ||
346 | + label="合同附件" | ||
347 | + /> | ||
348 | + | ||
349 | + <ProFormText | ||
350 | + width="md" | ||
351 | + name="totalPrice" | ||
352 | + label="合同金额" | ||
353 | + placeholder="请输入" | ||
354 | + disabled={isDis} | ||
355 | + initialValue={'0'} | ||
356 | + /> | ||
357 | + </ProForm.Group> | ||
358 | + </ProCard> | ||
359 | + <ProCard | ||
360 | + title={ | ||
361 | + <> | ||
362 | + <span style={{ color: 'red' }}>*</span>产品明细 | ||
363 | + </> | ||
364 | + } | ||
365 | + style={{ marginTop: 10 }} | ||
366 | + headerBordered | ||
367 | + bordered | ||
368 | + > | ||
369 | + <ProductDetail | ||
370 | + productBody={[]} | ||
371 | + EditProductBody={getEditProductBody} | ||
372 | + ></ProductDetail> | ||
373 | + </ProCard> | ||
374 | + | ||
375 | + <ProCard | ||
376 | + title="付款信息" | ||
377 | + style={{ marginTop: 10 }} | ||
378 | + headerBordered | ||
379 | + bordered | ||
380 | + > | ||
381 | + <PayWayDetail | ||
382 | + payBody={payWayBody} | ||
383 | + thisId={null} | ||
384 | + currtSave={setSave} | ||
385 | + ></PayWayDetail> | ||
386 | + </ProCard> | ||
387 | + | ||
388 | + <ProCard style={{ marginTop: 10 }} headerBordered bordered> | ||
389 | + <ProFormTextArea | ||
390 | + label="备注" | ||
391 | + name="remark" | ||
392 | + initialValue={contextBody.remark} | ||
393 | + /> | ||
394 | + </ProCard> | ||
395 | + </ModalForm> | ||
396 | + ); | ||
397 | +}; |
src/pages/Instalment/components/edit/edit.tsx
0 → 100644
1 | +import { | ||
2 | + postOrderErpOrderStagesPayWaySaveOrUpdate, | ||
3 | + postOrderErpOrderStagesSaveOrUpdate, | ||
4 | + postOrderErpOrderStagesSearch, | ||
5 | + postOrderErpOrderStagesUpload, | ||
6 | +} from '@/services'; | ||
7 | +import { | ||
8 | + ModalForm, | ||
9 | + ProCard, | ||
10 | + ProForm, | ||
11 | + ProFormDatePicker, | ||
12 | + ProFormText, | ||
13 | + ProFormTextArea, | ||
14 | + ProFormUploadButton, | ||
15 | +} from '@ant-design/pro-components'; | ||
16 | +import { Form, message } from 'antd'; | ||
17 | +import { RcFile } from 'antd/es/upload'; | ||
18 | +import { useEffect, useState } from 'react'; | ||
19 | +import PayWayDetail from '../payWayDetail/payWayDetail'; | ||
20 | +import ProductDetail from '../productDetail/productDetail'; | ||
21 | + | ||
22 | +const waitTime = (time: number = 100) => { | ||
23 | + return new Promise((resolve) => { | ||
24 | + setTimeout(() => { | ||
25 | + resolve(true); | ||
26 | + }, time); | ||
27 | + }); | ||
28 | +}; | ||
29 | + | ||
30 | +export default ({ currentContract, toReload }) => { | ||
31 | + const [form] = Form.useForm<{ name: string; company: string }>(); | ||
32 | + const [contextBody, setContextBody] = useState({}); | ||
33 | + const [total, setTotal] = useState(0); | ||
34 | + const [payWayBody, setPayWayBody] = useState([]); | ||
35 | + const [otherBody, setOtherBody] = useState([]); | ||
36 | + | ||
37 | + type OrderStagesWithListItem = { | ||
38 | + //文件编号 | ||
39 | + id: number; | ||
40 | + //合同编号 | ||
41 | + contract: string; | ||
42 | + //供应商名称 | ||
43 | + vendor: string; | ||
44 | + //签合同日期 | ||
45 | + dateRange: Date; | ||
46 | + //终端名称 | ||
47 | + terminal: string; | ||
48 | + orderStagesDeviceVoList: orderStagesDevice[]; | ||
49 | + //合同总金额 | ||
50 | + totalPrice: number; | ||
51 | + //付款方式 | ||
52 | + payWay: string; | ||
53 | + //附件 | ||
54 | + annex: string; | ||
55 | + //备注 | ||
56 | + remark: string; | ||
57 | + }; | ||
58 | + | ||
59 | + type orderStagesDevice = { | ||
60 | + //设备id | ||
61 | + dId: number; | ||
62 | + //设备名称 | ||
63 | + deviceName: string; | ||
64 | + //设备型号 | ||
65 | + deviceModel: string; | ||
66 | + //数量 | ||
67 | + count: number; | ||
68 | + //单价 | ||
69 | + unitPrice: number; | ||
70 | + //总价 | ||
71 | + price: number; | ||
72 | + }; | ||
73 | + | ||
74 | + async function refresh() { | ||
75 | + const res = await postOrderErpOrderStagesSearch({ | ||
76 | + data: { contract: currentContract }, | ||
77 | + }); | ||
78 | + const context = res.data[0]; | ||
79 | + | ||
80 | + if (context.contract !== null) { | ||
81 | + setContextBody(context); | ||
82 | + setTotal(context.totalPrice); | ||
83 | + form.setFieldValue('totalPrice', context.totalPrice); | ||
84 | + } | ||
85 | + } | ||
86 | + | ||
87 | + function setSave(value) { | ||
88 | + setOtherBody(value); | ||
89 | + } | ||
90 | + | ||
91 | + useEffect(() => { | ||
92 | + setContextBody({ ...contextBody, totalPrice: total }); | ||
93 | + form.setFieldValue('totalPrice', total); | ||
94 | + }, [total]); | ||
95 | + | ||
96 | + const handleInputChange = (value: string, no: number, priceNow?: number) => { | ||
97 | + let totalPay = 0; | ||
98 | + const payValue: string[] = value.split('/'); | ||
99 | + let body: | ||
100 | + | ((prevState: never[]) => never[]) | ||
101 | + | { proportion: string; payPrice: number }[] = []; | ||
102 | + if (no === 1) { | ||
103 | + if (payValue.length !== 4) { | ||
104 | + message.warning('比例个数总和不为4个!'); | ||
105 | + } else { | ||
106 | + payValue.forEach((item) => { | ||
107 | + totalPay += Number(item); | ||
108 | + }); | ||
109 | + } | ||
110 | + if (totalPay !== 100) { | ||
111 | + message.warning('比例总和不为100!'); | ||
112 | + } else { | ||
113 | + message.success('输入有效!'); | ||
114 | + const price = total; | ||
115 | + payValue.forEach((item) => { | ||
116 | + body.push({ | ||
117 | + proportion: item + '%', | ||
118 | + payPrice: (Number(item) * price) / 100, | ||
119 | + }); | ||
120 | + }); | ||
121 | + setPayWayBody(body); | ||
122 | + } | ||
123 | + } else { | ||
124 | + payValue.forEach((item) => { | ||
125 | + totalPay += Number(item); | ||
126 | + }); | ||
127 | + payValue.forEach((item) => { | ||
128 | + body.push({ | ||
129 | + proportion: item + '%', | ||
130 | + payPrice: (Number(item) * priceNow) / 100, | ||
131 | + }); | ||
132 | + }); | ||
133 | + setPayWayBody(body); | ||
134 | + } | ||
135 | + }; | ||
136 | + | ||
137 | + async function getBody() { | ||
138 | + const res = await postOrderErpOrderStagesSearch({ | ||
139 | + data: { contract: currentContract }, | ||
140 | + }); | ||
141 | + const context = res.data[0]; | ||
142 | + | ||
143 | + if (context.contract !== null) { | ||
144 | + setContextBody(context); | ||
145 | + setTotal(context.totalPrice); | ||
146 | + form.setFieldValue('totalPrice', context.totalPrice); | ||
147 | + } | ||
148 | + handleInputChange(context.payWay, 0, context.totalPrice); | ||
149 | + } | ||
150 | + | ||
151 | + function getEditProductBody(value) { | ||
152 | + let price = 0; | ||
153 | + value.map((obj) => (price += obj.count * obj.unitPrice)); | ||
154 | + setTotal(price); | ||
155 | + setContextBody({ ...contextBody, orderStagesDeviceVoList: value }); | ||
156 | + handleInputChange(contextBody.payWay, 0, price); | ||
157 | + } | ||
158 | + | ||
159 | + useEffect(() => { | ||
160 | + getBody(); | ||
161 | + }, []); | ||
162 | + | ||
163 | + return ( | ||
164 | + <ModalForm<OrderStagesWithListItem> | ||
165 | + title="新建" | ||
166 | + trigger={<a onClick={refresh}>编辑</a>} | ||
167 | + form={form} | ||
168 | + autoFocusFirstInput | ||
169 | + modalProps={{ | ||
170 | + destroyOnClose: true, | ||
171 | + }} | ||
172 | + submitTimeout={2000} | ||
173 | + onFinish={async (values) => { | ||
174 | + if (contextBody.orderStagesDeviceVoList.length === 0) { | ||
175 | + message.error('请填写产品数据'); | ||
176 | + return false; | ||
177 | + } | ||
178 | + let remakeValue = []; | ||
179 | + const promises = []; | ||
180 | + | ||
181 | + otherBody.forEach((item) => { | ||
182 | + let remakeItem = { | ||
183 | + ossId: contextBody.id, | ||
184 | + number: item.id, | ||
185 | + dateRange: item.payDate, | ||
186 | + fileName: item.fileName, | ||
187 | + }; | ||
188 | + if ( | ||
189 | + typeof item.fileUrl === 'object' && | ||
190 | + item.fileUrl instanceof File | ||
191 | + ) { | ||
192 | + const formData = new FormData(); | ||
193 | + formData.append('file', item.fileUrl as RcFile); | ||
194 | + const uploadPromise = async () => { | ||
195 | + const res = await postOrderErpOrderStagesUpload({ | ||
196 | + data: formData, | ||
197 | + headers: { | ||
198 | + 'Content-Type': | ||
199 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | ||
200 | + }, | ||
201 | + }); | ||
202 | + if (res.data) { | ||
203 | + remakeItem.fileUrl = res.data; | ||
204 | + } | ||
205 | + }; | ||
206 | + promises.push(uploadPromise()); | ||
207 | + } | ||
208 | + remakeValue.push(remakeItem); | ||
209 | + }); | ||
210 | + Promise.all(promises).then(async () => { | ||
211 | + await postOrderErpOrderStagesPayWaySaveOrUpdate({ | ||
212 | + data: remakeValue, | ||
213 | + }); | ||
214 | + }); | ||
215 | + const formData = new FormData(); | ||
216 | + let toSendEdit = { | ||
217 | + id: values.id || contextBody.id, | ||
218 | + contract: values.contract || contextBody.contract, | ||
219 | + vendor: values.vendor || contextBody.vendor, | ||
220 | + dateRange: values.dateRange || contextBody.dateRange, | ||
221 | + terminal: values.terminal || contextBody.terminal, | ||
222 | + orderStagesDeviceDoList: | ||
223 | + values.orderStagesDeviceVoList || | ||
224 | + contextBody.orderStagesDeviceVoList, | ||
225 | + totalPrice: values.totalPrice || contextBody.totalPrice, | ||
226 | + payWay: values.payWay || contextBody.payWay, | ||
227 | + annex: contextBody.annex, | ||
228 | + remark: values.remark || contextBody.remark, | ||
229 | + }; | ||
230 | + if (values.annex) { | ||
231 | + formData.append('file', values.annex[0].originFileObj as RcFile); | ||
232 | + const res = await postOrderErpOrderStagesUpload({ | ||
233 | + data: formData, | ||
234 | + headers: { | ||
235 | + 'Content-Type': | ||
236 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | ||
237 | + }, | ||
238 | + }); | ||
239 | + if (res.data) { | ||
240 | + toSendEdit.annex = res.data; | ||
241 | + } | ||
242 | + } | ||
243 | + const isSaveOrUpdate = await postOrderErpOrderStagesSaveOrUpdate({ | ||
244 | + data: { ...toSendEdit }, | ||
245 | + }); | ||
246 | + if (isSaveOrUpdate) { | ||
247 | + getBody(); | ||
248 | + toReload(); | ||
249 | + } | ||
250 | + await waitTime(2000); | ||
251 | + message.success('提交成功'); | ||
252 | + return true; | ||
253 | + }} | ||
254 | + > | ||
255 | + <ProCard title="基本信息" headerBordered bordered> | ||
256 | + <ProForm.Group> | ||
257 | + <ProFormText | ||
258 | + width="md" | ||
259 | + name="vendor" | ||
260 | + rules={[{ required: true, message: '此项为必填项' }]} | ||
261 | + label="供应商名称" | ||
262 | + placeholder="请输入" | ||
263 | + initialValue={contextBody.vendor} | ||
264 | + /> | ||
265 | + | ||
266 | + <ProFormText | ||
267 | + width="md" | ||
268 | + name="terminal" | ||
269 | + rules={[{ required: true, message: '此项为必填项' }]} | ||
270 | + label="终端名称" | ||
271 | + placeholder="请输入" | ||
272 | + initialValue={contextBody.terminal} | ||
273 | + /> | ||
274 | + | ||
275 | + <ProFormDatePicker | ||
276 | + name="dateRange" | ||
277 | + width="md" | ||
278 | + label="签合同日期" | ||
279 | + placeholder="请选择日期" | ||
280 | + fieldProps={{ | ||
281 | + format: (value) => value.format('YYYY-MM-DD'), | ||
282 | + }} | ||
283 | + initialValue={contextBody.dateRange} | ||
284 | + /> | ||
285 | + | ||
286 | + <ProFormText | ||
287 | + width="md" | ||
288 | + name="payWay" | ||
289 | + rules={[{ required: true, message: '此项为必填项' }]} | ||
290 | + label="付款比例" | ||
291 | + placeholder="请输入" | ||
292 | + initialValue={contextBody.payWay} | ||
293 | + onBlur={(e) => { | ||
294 | + handleInputChange(e.target.value, 1); | ||
295 | + }} | ||
296 | + /> | ||
297 | + | ||
298 | + <ProFormText | ||
299 | + width="md" | ||
300 | + name="contract" | ||
301 | + rules={[{ required: true, message: '此项为必填项' }]} | ||
302 | + label="合同编号" | ||
303 | + placeholder="请输入" | ||
304 | + initialValue={contextBody.contract} | ||
305 | + /> | ||
306 | + | ||
307 | + <ProFormUploadButton | ||
308 | + width="md" | ||
309 | + name="annex" | ||
310 | + max={1} | ||
311 | + label="合同附件" | ||
312 | + /> | ||
313 | + | ||
314 | + <ProFormText | ||
315 | + width="md" | ||
316 | + name="totalPrice" | ||
317 | + label="合同金额" | ||
318 | + placeholder="请输入" | ||
319 | + disabled | ||
320 | + initialValue={contextBody.totalPrice} | ||
321 | + /> | ||
322 | + </ProForm.Group> | ||
323 | + </ProCard> | ||
324 | + | ||
325 | + <ProCard | ||
326 | + title={ | ||
327 | + <> | ||
328 | + <span style={{ color: 'red' }}>*</span>产品明细 | ||
329 | + </> | ||
330 | + } | ||
331 | + style={{ marginTop: 10 }} | ||
332 | + headerBordered | ||
333 | + bordered | ||
334 | + > | ||
335 | + <ProductDetail | ||
336 | + productBody={contextBody.orderStagesDeviceVoList} | ||
337 | + EditProductBody={getEditProductBody} | ||
338 | + ></ProductDetail> | ||
339 | + </ProCard> | ||
340 | + | ||
341 | + <ProCard | ||
342 | + title="付款信息" | ||
343 | + style={{ marginTop: 10 }} | ||
344 | + headerBordered | ||
345 | + bordered | ||
346 | + > | ||
347 | + <PayWayDetail | ||
348 | + payBody={payWayBody} | ||
349 | + thisId={contextBody.id} | ||
350 | + currtSave={setSave} | ||
351 | + ></PayWayDetail> | ||
352 | + </ProCard> | ||
353 | + | ||
354 | + <ProCard style={{ marginTop: 10 }} headerBordered bordered> | ||
355 | + <ProFormTextArea | ||
356 | + label="备注" | ||
357 | + name="remark" | ||
358 | + initialValue={contextBody.remark} | ||
359 | + /> | ||
360 | + </ProCard> | ||
361 | + </ModalForm> | ||
362 | + ); | ||
363 | +}; |
src/pages/Instalment/components/payWayDetail/payWayDetail.css
0 → 100644
1 | +.payway-detail-index td { | ||
2 | + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial, | ||
3 | + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC', | ||
4 | + 'WenQuanYi Micro Hei', sans-serif; | ||
5 | + font-size: 14px; | ||
6 | + margin: 0; | ||
7 | +} | ||
8 | + | ||
9 | +.payway-detail-index td .css-dev-only-do-not-override-nllxry { | ||
10 | + margin-bottom: 0 !important; | ||
11 | +} | ||
12 | + | ||
13 | +.dataChoose { | ||
14 | + margin: 0; | ||
15 | +} |
src/pages/Instalment/components/payWayDetail/payWayDetail.less
0 → 100644
1 | +.payway-detail-index td { | ||
2 | + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial, | ||
3 | + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC', | ||
4 | + 'WenQuanYi Micro Hei', sans-serif; | ||
5 | + font-size: 14px; | ||
6 | + margin: 0; | ||
7 | + | ||
8 | + .css-dev-only-do-not-override-nllxry { | ||
9 | + margin-bottom: 0 !important; | ||
10 | + } | ||
11 | +} | ||
12 | + | ||
13 | +.dataChoose { | ||
14 | + margin: 0; | ||
15 | +} | ||
16 | + | ||
17 | +// .pay-way-detail-index td .css-dev-only-do-not-override-nllxry{ | ||
18 | +// margin-bottom: 0px !important; | ||
19 | +// } |
src/pages/Instalment/components/payWayDetail/payWayDetail.tsx
0 → 100644
1 | +import { postOrderErpOrderStagesPayWaySelect } from '@/services'; | ||
2 | +import type { ProColumns } from '@ant-design/pro-components'; | ||
3 | +import { | ||
4 | + EditableProTable, | ||
5 | + ProFormDatePicker, | ||
6 | + ProFormRadio, | ||
7 | + ProFormUploadButton, | ||
8 | +} from '@ant-design/pro-components'; | ||
9 | +import { message } from 'antd'; | ||
10 | +import React, { useEffect, useState } from 'react'; | ||
11 | +import './payWayDetail.less'; | ||
12 | + | ||
13 | +const waitTime = (time: number = 100) => { | ||
14 | + return new Promise((resolve) => { | ||
15 | + setTimeout(() => { | ||
16 | + resolve(true); | ||
17 | + }, time); | ||
18 | + }); | ||
19 | +}; | ||
20 | + | ||
21 | +type DataSourceType = { | ||
22 | + id: number; | ||
23 | + payStep?: string; | ||
24 | + proportion?: string; | ||
25 | + ossId?: number; | ||
26 | + payPrice?: number; | ||
27 | + payDate?: Date; | ||
28 | + fileName?: string; | ||
29 | + fileUrl?: string; | ||
30 | +}; | ||
31 | + | ||
32 | +export default ({ payBody, thisId, currtSave }) => { | ||
33 | + const defaultData: DataSourceType[] = [ | ||
34 | + { | ||
35 | + id: 1, | ||
36 | + payStep: '预付款', | ||
37 | + proportion: undefined, | ||
38 | + payPrice: undefined, | ||
39 | + ossId: undefined, | ||
40 | + payDate: undefined, | ||
41 | + fileName: undefined, | ||
42 | + fileUrl: undefined, | ||
43 | + }, | ||
44 | + { | ||
45 | + id: 2, | ||
46 | + payStep: '发贷款', | ||
47 | + proportion: undefined, | ||
48 | + payPrice: undefined, | ||
49 | + ossId: undefined, | ||
50 | + payDate: undefined, | ||
51 | + fileName: undefined, | ||
52 | + fileUrl: undefined, | ||
53 | + }, | ||
54 | + { | ||
55 | + id: 3, | ||
56 | + payStep: '验收款', | ||
57 | + proportion: undefined, | ||
58 | + payPrice: undefined, | ||
59 | + ossId: undefined, | ||
60 | + payDate: undefined, | ||
61 | + fileName: undefined, | ||
62 | + fileUrl: undefined, | ||
63 | + }, | ||
64 | + { | ||
65 | + id: 4, | ||
66 | + payStep: '质保金', | ||
67 | + proportion: undefined, | ||
68 | + payPrice: undefined, | ||
69 | + ossId: undefined, | ||
70 | + payDate: undefined, | ||
71 | + fileName: undefined, | ||
72 | + fileUrl: undefined, | ||
73 | + }, | ||
74 | + ]; | ||
75 | + | ||
76 | + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]); | ||
77 | + const [position, setPosition] = useState<'top' | 'bottom' | 'hidden'>( | ||
78 | + 'hidden', | ||
79 | + ); | ||
80 | + const [payWayDetailBody, setPayWayDetailBody] = useState< | ||
81 | + readonly DataSourceType[] | ||
82 | + >([...defaultData]); | ||
83 | + // const [body, setBody] = useState([]) | ||
84 | + const [isAccept, setIsAccept] = useState(null); | ||
85 | + // const [isCurrtSave, setIsCurrtSave] = useState(false); | ||
86 | + | ||
87 | + async function getOther(value, arr) { | ||
88 | + const res = await postOrderErpOrderStagesPayWaySelect({ | ||
89 | + data: { ossId: value }, | ||
90 | + }); | ||
91 | + if (res.data) { | ||
92 | + const context = res.data; | ||
93 | + const remake = arr.map((obj) => { | ||
94 | + let currt = obj; | ||
95 | + context.forEach((object) => { | ||
96 | + if (object.number === obj.id) { | ||
97 | + currt = { | ||
98 | + ...obj, | ||
99 | + ossId: value, | ||
100 | + payDate: object.dateRange, | ||
101 | + fileName: object.fileName, | ||
102 | + fileUrl: object.fileUrl, | ||
103 | + }; | ||
104 | + return currt; | ||
105 | + } | ||
106 | + }); | ||
107 | + return currt; | ||
108 | + }); | ||
109 | + setPayWayDetailBody(remake); | ||
110 | + } | ||
111 | + } | ||
112 | + | ||
113 | + function setPayWay(value) { | ||
114 | + const remakeData = payWayDetailBody.map((obj) => { | ||
115 | + return { | ||
116 | + ...obj, | ||
117 | + proportion: value[obj.id - 1]?.proportion, | ||
118 | + payPrice: value[obj.id - 1]?.payPrice, | ||
119 | + }; | ||
120 | + }); | ||
121 | + // console.log(remakeData); | ||
122 | + | ||
123 | + setPayWayDetailBody(remakeData); | ||
124 | + // console.log(thisId); | ||
125 | + | ||
126 | + if (thisId !== null) { | ||
127 | + getOther(thisId, remakeData); | ||
128 | + } | ||
129 | + } | ||
130 | + // useEffect(() => { | ||
131 | + // getOther(thisId) | ||
132 | + // }, [thisId]) | ||
133 | + | ||
134 | + useEffect(() => { | ||
135 | + setPayWay(payBody); | ||
136 | + }, [payBody]); | ||
137 | + | ||
138 | + // function setCurrtSave(value) { | ||
139 | + // // console.log(value); | ||
140 | + // setIsCurrtSave(payWayDetailBody) | ||
141 | + // } | ||
142 | + | ||
143 | + const columns: ProColumns<DataSourceType>[] = [ | ||
144 | + { | ||
145 | + title: '编号', | ||
146 | + dataIndex: 'id', | ||
147 | + hideInTable: true, | ||
148 | + editable: false, | ||
149 | + }, | ||
150 | + { | ||
151 | + title: '付款信息', | ||
152 | + dataIndex: 'payStep', | ||
153 | + editable: false, | ||
154 | + }, | ||
155 | + { | ||
156 | + title: '付款比例', | ||
157 | + dataIndex: 'proportion', | ||
158 | + editable: false, | ||
159 | + }, | ||
160 | + { | ||
161 | + title: '付款金额', | ||
162 | + dataIndex: 'payPrice', | ||
163 | + editable: false, | ||
164 | + }, | ||
165 | + { | ||
166 | + title: '对应的订单', | ||
167 | + dataIndex: 'ossId', | ||
168 | + editable: false, | ||
169 | + hideInTable: true, | ||
170 | + }, | ||
171 | + { | ||
172 | + title: '付款时间', | ||
173 | + dataIndex: 'payDate', | ||
174 | + editable: false, | ||
175 | + render: (text, record) => { | ||
176 | + const handleChange = (value) => { | ||
177 | + const updatedDataSource = payWayDetailBody.map((item) => { | ||
178 | + if (item.id === record.id) { | ||
179 | + return { | ||
180 | + ...item, | ||
181 | + payDate: value, | ||
182 | + }; | ||
183 | + } | ||
184 | + return item; | ||
185 | + }); | ||
186 | + // console.log(updatedDataSource); | ||
187 | + | ||
188 | + setPayWayDetailBody(updatedDataSource); | ||
189 | + currtSave(updatedDataSource); | ||
190 | + }; | ||
191 | + | ||
192 | + return ( | ||
193 | + <ProFormDatePicker | ||
194 | + className="dataChoose" | ||
195 | + initialValue={record.payDate} | ||
196 | + value={record.payDate} | ||
197 | + placeholder={'请填写时间'} | ||
198 | + fieldProps={{ | ||
199 | + format: (value) => value.format('YYYY-MM-DD'), | ||
200 | + onChange: handleChange, | ||
201 | + }} | ||
202 | + /> | ||
203 | + ); | ||
204 | + }, | ||
205 | + }, | ||
206 | + { | ||
207 | + title: '付款单回执', | ||
208 | + dataIndex: 'fileName', | ||
209 | + render: (text, record) => { | ||
210 | + if (isAccept !== record.id) { | ||
211 | + if ( | ||
212 | + typeof record.fileUrl === 'object' && | ||
213 | + record.fileUrl instanceof File | ||
214 | + ) { | ||
215 | + return ( | ||
216 | + <a onClick={() => message.error('请先保存')}>{record.fileName}</a> | ||
217 | + ); | ||
218 | + } else { | ||
219 | + return <a href={record.fileUrl}>{record.fileName}</a>; | ||
220 | + } | ||
221 | + } else { | ||
222 | + return ( | ||
223 | + <ProFormUploadButton | ||
224 | + name={record.id} | ||
225 | + onChange={(value) => { | ||
226 | + // console.log(value); | ||
227 | + // console.log(payWayDetailBody); | ||
228 | + let remakeBody = []; | ||
229 | + let remakeBodyItem = {}; | ||
230 | + payWayDetailBody.forEach((item) => { | ||
231 | + if (item.id === record.id) { | ||
232 | + remakeBodyItem = { | ||
233 | + ...item, | ||
234 | + fileUrl: value.file.originFileObj, | ||
235 | + fileName: value.file.name, | ||
236 | + }; | ||
237 | + } else { | ||
238 | + remakeBodyItem = { ...item }; | ||
239 | + } | ||
240 | + // if (value.fileList.length == 0) { | ||
241 | + // remakeBodyItem = { ...item, fileUrl: undefined, fileName: undefined } | ||
242 | + // } | ||
243 | + remakeBody.push(remakeBodyItem); | ||
244 | + }); | ||
245 | + setPayWayDetailBody(remakeBody); | ||
246 | + currtSave(remakeBody); | ||
247 | + }} | ||
248 | + width="md" | ||
249 | + max={1} | ||
250 | + /> | ||
251 | + ); | ||
252 | + } | ||
253 | + }, | ||
254 | + }, | ||
255 | + { | ||
256 | + title: '操作', | ||
257 | + valueType: 'option', | ||
258 | + width: 200, | ||
259 | + render: (text, record) => [ | ||
260 | + <a | ||
261 | + key="editable" | ||
262 | + onClick={() => { | ||
263 | + if (isAccept !== record.id) { | ||
264 | + setIsAccept(record.id); | ||
265 | + } else { | ||
266 | + setIsAccept(null); | ||
267 | + } | ||
268 | + }} | ||
269 | + > | ||
270 | + {record.fileName !== undefined && | ||
271 | + record.fileName !== '' && | ||
272 | + record.fileName !== null | ||
273 | + ? '重新上传' | ||
274 | + : '上传回执'} | ||
275 | + </a>, | ||
276 | + ], | ||
277 | + }, | ||
278 | + ]; | ||
279 | + | ||
280 | + return ( | ||
281 | + <> | ||
282 | + <EditableProTable<DataSourceType> | ||
283 | + rowKey="id" | ||
284 | + className="payway-detail-index" | ||
285 | + toolbar={{ style: { display: 'none' } }} | ||
286 | + ghost={true} | ||
287 | + scroll={{ | ||
288 | + x: 960, | ||
289 | + }} | ||
290 | + recordCreatorProps={ | ||
291 | + position !== 'hidden' | ||
292 | + ? { | ||
293 | + position: position as 'top', | ||
294 | + record: () => ({ id: (Math.random() * 1000000).toFixed(0) }), | ||
295 | + } | ||
296 | + : false | ||
297 | + } | ||
298 | + loading={false} | ||
299 | + toolBarRender={() => [ | ||
300 | + <ProFormRadio.Group | ||
301 | + key="render" | ||
302 | + fieldProps={{ | ||
303 | + value: position, | ||
304 | + onChange: (e) => setPosition(e.target.value), | ||
305 | + }} | ||
306 | + />, | ||
307 | + ]} | ||
308 | + columns={columns} | ||
309 | + request={payWayDetailBody} | ||
310 | + value={payWayDetailBody} | ||
311 | + onChange={(value) => { | ||
312 | + setPayWayDetailBody(value); | ||
313 | + // setCurrtSave(payWayDetailBody) | ||
314 | + }} | ||
315 | + editable={{ | ||
316 | + type: 'multiple', | ||
317 | + editableKeys, | ||
318 | + onSave: async () => { | ||
319 | + // console.log(rowKey, data, row); | ||
320 | + await waitTime(2000); | ||
321 | + }, | ||
322 | + onChange: setEditableRowKeys, | ||
323 | + }} | ||
324 | + /> | ||
325 | + </> | ||
326 | + ); | ||
327 | +}; |
src/pages/Instalment/components/productDetail/productDetail.css
0 → 100644
src/pages/Instalment/components/productDetail/productDetail.less
0 → 100644
src/pages/Instalment/components/productDetail/productDetail.tsx
0 → 100644
1 | +import type { ProColumns } from '@ant-design/pro-components'; | ||
2 | +import { EditableProTable, ProFormRadio } from '@ant-design/pro-components'; | ||
3 | +import React, { useEffect, useState } from 'react'; | ||
4 | +import './productDetail.less'; | ||
5 | + | ||
6 | +const waitTime = (time: number = 100) => { | ||
7 | + return new Promise((resolve) => { | ||
8 | + setTimeout(() => { | ||
9 | + resolve(true); | ||
10 | + }, time); | ||
11 | + }); | ||
12 | +}; | ||
13 | + | ||
14 | +// type DataSourceType = { | ||
15 | +// count?: number; | ||
16 | +// id: React.Key; | ||
17 | +// deviceModel?: string; | ||
18 | +// deviceName?: string; | ||
19 | +// price?: number; | ||
20 | +// unitPrice?: number; | ||
21 | +// }; | ||
22 | + | ||
23 | +export default ({ productBody, EditProductBody }) => { | ||
24 | + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]); | ||
25 | + const [dataSource, setDataSource] = useState<readonly DataSourceType[]>([]); | ||
26 | + // const [form] = Form.useForm<{ name: string; company: string }>(); | ||
27 | + const [position, setPosition] = useState<'top' | 'bottom' | 'hidden'>( | ||
28 | + 'bottom', | ||
29 | + ); | ||
30 | + function getDataSourece() { | ||
31 | + if (productBody.length !== 0) { | ||
32 | + setDataSource(productBody); | ||
33 | + } | ||
34 | + } | ||
35 | + function setEditProductBody(value) { | ||
36 | + // console.log(value); | ||
37 | + // console.log(dataSource); | ||
38 | + | ||
39 | + const modifiedArray = value.map((obj) => { | ||
40 | + if (obj.dId && Number(obj.dId) <= 1000) { | ||
41 | + return { | ||
42 | + ...obj, | ||
43 | + count: obj.count, | ||
44 | + dId: null, | ||
45 | + deviceModel: obj.deviceModel, | ||
46 | + deviceName: obj.deviceName, | ||
47 | + price: Number(obj.unitPrice) * Number(obj.count), | ||
48 | + unitPrice: obj.unitPrice, | ||
49 | + }; | ||
50 | + } else { | ||
51 | + return { ...obj, price: Number(obj.unitPrice) * Number(obj.count) }; | ||
52 | + } | ||
53 | + }); | ||
54 | + // console.log(modifiedArray); | ||
55 | + | ||
56 | + EditProductBody(modifiedArray); | ||
57 | + setDataSource(value); | ||
58 | + } | ||
59 | + | ||
60 | + useEffect(() => { | ||
61 | + getDataSourece(); | ||
62 | + }, [productBody]); | ||
63 | + | ||
64 | + type DataSourceType = { | ||
65 | + id: React.Key; | ||
66 | + count: number; | ||
67 | + dId?: number; | ||
68 | + deviceModel: string; | ||
69 | + deviceName: string; | ||
70 | + price: number; | ||
71 | + unitPrice: number; | ||
72 | + }; | ||
73 | + | ||
74 | + const columns: ProColumns<DataSourceType>[] = [ | ||
75 | + { | ||
76 | + title: '设备编号', | ||
77 | + dataIndex: 'dId', | ||
78 | + hideInTable: true, | ||
79 | + }, | ||
80 | + { | ||
81 | + title: '设备名称', | ||
82 | + dataIndex: 'deviceName', | ||
83 | + formItemProps: () => { | ||
84 | + return { | ||
85 | + rules: [{ required: true, message: '此项为必填项' }], | ||
86 | + }; | ||
87 | + }, | ||
88 | + }, | ||
89 | + { | ||
90 | + title: '设备型号', | ||
91 | + dataIndex: 'deviceModel', | ||
92 | + width: '15%', | ||
93 | + formItemProps: () => { | ||
94 | + return { | ||
95 | + rules: [{ required: true, message: '此项为必填项' }], | ||
96 | + }; | ||
97 | + }, | ||
98 | + }, | ||
99 | + { | ||
100 | + title: '数量', | ||
101 | + dataIndex: 'count', | ||
102 | + formItemProps: () => { | ||
103 | + return { | ||
104 | + rules: [{ required: true, message: '此项为必填项' }], | ||
105 | + }; | ||
106 | + }, | ||
107 | + }, | ||
108 | + { | ||
109 | + title: '单价', | ||
110 | + dataIndex: 'unitPrice', | ||
111 | + formItemProps: () => { | ||
112 | + return { | ||
113 | + rules: [{ required: true, message: '此项为必填项' }], | ||
114 | + }; | ||
115 | + }, | ||
116 | + }, | ||
117 | + { | ||
118 | + title: '总价', | ||
119 | + dataIndex: 'price', | ||
120 | + hideInSetting: true, | ||
121 | + disable: true, | ||
122 | + editable: false, | ||
123 | + render: (_text, record) => [ | ||
124 | + <span key={record.dId}>{record.count * record.unitPrice}</span>, | ||
125 | + ], | ||
126 | + }, | ||
127 | + { | ||
128 | + title: '操作', | ||
129 | + valueType: 'option', | ||
130 | + width: 200, | ||
131 | + render: (_text, record, _, action) => [ | ||
132 | + <a | ||
133 | + key="editable" | ||
134 | + onClick={() => { | ||
135 | + if (record.dId) { | ||
136 | + action?.startEditable?.(record.dId); | ||
137 | + } | ||
138 | + }} | ||
139 | + > | ||
140 | + 编辑 | ||
141 | + </a>, | ||
142 | + <a | ||
143 | + key="delete" | ||
144 | + onClick={() => { | ||
145 | + EditProductBody( | ||
146 | + dataSource.filter((item) => item.dId !== record.dId), | ||
147 | + ); | ||
148 | + setDataSource(dataSource.filter((item) => item.dId !== record.dId)); | ||
149 | + }} | ||
150 | + > | ||
151 | + 删除 | ||
152 | + </a>, | ||
153 | + ], | ||
154 | + }, | ||
155 | + ]; | ||
156 | + | ||
157 | + return ( | ||
158 | + <> | ||
159 | + <EditableProTable<DataSourceType> | ||
160 | + className="product-detail-index" | ||
161 | + rowKey="dId" | ||
162 | + toolbar={{ style: { display: 'none' } }} | ||
163 | + ghost={true} | ||
164 | + scroll={{ | ||
165 | + x: 960, | ||
166 | + }} | ||
167 | + recordCreatorProps={ | ||
168 | + position !== 'hidden' | ||
169 | + ? { | ||
170 | + position: position as 'top', | ||
171 | + record: () => ({ dId: (Math.random() * 1000).toFixed(0) }), | ||
172 | + } | ||
173 | + : false | ||
174 | + } | ||
175 | + loading={false} | ||
176 | + toolBarRender={() => [ | ||
177 | + <ProFormRadio.Group | ||
178 | + key="render" | ||
179 | + fieldProps={{ | ||
180 | + value: position, | ||
181 | + onChange: (e) => setPosition(e.target.value), | ||
182 | + }} | ||
183 | + />, | ||
184 | + ]} | ||
185 | + columns={columns} | ||
186 | + request={dataSource} | ||
187 | + value={dataSource} | ||
188 | + onChange={setEditProductBody} | ||
189 | + editable={{ | ||
190 | + type: 'multiple', | ||
191 | + editableKeys, | ||
192 | + onSave: async () => { | ||
193 | + await waitTime(500); | ||
194 | + }, | ||
195 | + onChange: setEditableRowKeys, | ||
196 | + }} | ||
197 | + /> | ||
198 | + </> | ||
199 | + ); | ||
200 | +}; |
src/pages/Instalment/components/read/read.tsx
0 → 100644
1 | +import { | ||
2 | + postOrderErpOrderStagesPayWaySaveOrUpdate, | ||
3 | + postOrderErpOrderStagesSaveOrUpdate, | ||
4 | + postOrderErpOrderStagesSearch, | ||
5 | + postOrderErpOrderStagesUpload, | ||
6 | +} from '@/services'; | ||
7 | +import { | ||
8 | + ModalForm, | ||
9 | + ProCard, | ||
10 | + ProForm, | ||
11 | + ProFormDatePicker, | ||
12 | + ProFormText, | ||
13 | + ProFormTextArea, | ||
14 | +} from '@ant-design/pro-components'; | ||
15 | +import { Form, message } from 'antd'; | ||
16 | +import { RcFile } from 'antd/es/upload'; | ||
17 | +import { useEffect, useState } from 'react'; | ||
18 | +import PayWayDetail from './readPayWay'; | ||
19 | +import ProductDetail from './readProduct'; | ||
20 | + | ||
21 | +const waitTime = (time: number = 100) => { | ||
22 | + return new Promise((resolve) => { | ||
23 | + setTimeout(() => { | ||
24 | + resolve(true); | ||
25 | + }, time); | ||
26 | + }); | ||
27 | +}; | ||
28 | + | ||
29 | +export default ({ currentContract }) => { | ||
30 | + const [form] = Form.useForm<{ name: string; company: string }>(); | ||
31 | + const [contextBody, setContextBody] = useState({}); | ||
32 | + const [, setEditProductBody] = useState([]); | ||
33 | + const [total, setTotal] = useState(0); | ||
34 | + const [payWayBody, setPayWayBody] = useState([]); | ||
35 | + const [otherBody, setOtherBody] = useState([]); | ||
36 | + | ||
37 | + type OrderStagesWithListItem = { | ||
38 | + //文件编号 | ||
39 | + id: number; | ||
40 | + //合同编号 | ||
41 | + contract: string; | ||
42 | + //供应商名称 | ||
43 | + vendor: string; | ||
44 | + //签合同日期 | ||
45 | + dateRange: Date; | ||
46 | + //终端名称 | ||
47 | + terminal: string; | ||
48 | + orderStagesDeviceVoList: orderStagesDevice[]; | ||
49 | + //合同总金额 | ||
50 | + totalPrice: number; | ||
51 | + //付款方式 | ||
52 | + payWay: string; | ||
53 | + //附件 | ||
54 | + annex: string; | ||
55 | + //备注 | ||
56 | + remark: string; | ||
57 | + }; | ||
58 | + | ||
59 | + type orderStagesDevice = { | ||
60 | + //设备id | ||
61 | + dId: number; | ||
62 | + //设备名称 | ||
63 | + deviceName: string; | ||
64 | + //设备型号 | ||
65 | + deviceModel: string; | ||
66 | + //数量 | ||
67 | + count: number; | ||
68 | + //单价 | ||
69 | + unitPrice: number; | ||
70 | + //总价 | ||
71 | + price: number; | ||
72 | + }; | ||
73 | + | ||
74 | + async function refresh() { | ||
75 | + const res = await postOrderErpOrderStagesSearch({ | ||
76 | + data: { contract: currentContract }, | ||
77 | + }); | ||
78 | + const context = res.data[0]; | ||
79 | + // console.log(context); | ||
80 | + | ||
81 | + if (context.contract !== null) { | ||
82 | + setContextBody(context); | ||
83 | + setTotal(context.totalPrice); | ||
84 | + form.setFieldValue('totalPrice', context.totalPrice); | ||
85 | + } | ||
86 | + } | ||
87 | + | ||
88 | + function setSave(value) { | ||
89 | + // console.log(value); | ||
90 | + setOtherBody(value); | ||
91 | + } | ||
92 | + | ||
93 | + useEffect(() => { | ||
94 | + setContextBody({ ...contextBody, totalPrice: total }); | ||
95 | + form.setFieldValue('totalPrice', total); | ||
96 | + }, [total]); | ||
97 | + | ||
98 | + const handleInputChange = (value: string, no: number, priceNow?: number) => { | ||
99 | + let totalPay = 0; | ||
100 | + const payValue: string[] = value.split('/'); | ||
101 | + let body: | ||
102 | + | ((prevState: never[]) => never[]) | ||
103 | + | { proportion: string; payPrice: number }[] = []; | ||
104 | + if (no === 1) { | ||
105 | + if (payValue.length !== 4) { | ||
106 | + message.warning('比例个数总和不为4个!'); | ||
107 | + } else { | ||
108 | + payValue.forEach((item) => { | ||
109 | + totalPay += Number(item); | ||
110 | + }); | ||
111 | + } | ||
112 | + if (totalPay !== 100) { | ||
113 | + message.warning('比例总和不为100!'); | ||
114 | + } else { | ||
115 | + message.success('输入有效!'); | ||
116 | + const price = total; | ||
117 | + payValue.forEach((item) => { | ||
118 | + body.push({ | ||
119 | + proportion: item + '%', | ||
120 | + payPrice: (Number(item) * price) / 100, | ||
121 | + }); | ||
122 | + }); | ||
123 | + setPayWayBody(body); | ||
124 | + } | ||
125 | + } else { | ||
126 | + payValue.forEach((item) => { | ||
127 | + totalPay += Number(item); | ||
128 | + }); | ||
129 | + payValue.forEach((item) => { | ||
130 | + body.push({ | ||
131 | + proportion: item + '%', | ||
132 | + payPrice: (Number(item) * priceNow) / 100, | ||
133 | + }); | ||
134 | + }); | ||
135 | + setPayWayBody(body); | ||
136 | + } | ||
137 | + }; | ||
138 | + | ||
139 | + async function getBody() { | ||
140 | + const res = await postOrderErpOrderStagesSearch({ | ||
141 | + data: { contract: currentContract }, | ||
142 | + }); | ||
143 | + const context = res.data[0]; | ||
144 | + // console.log(context); | ||
145 | + | ||
146 | + if (context.contract !== null) { | ||
147 | + setContextBody(context); | ||
148 | + setTotal(context.totalPrice); | ||
149 | + form.setFieldValue('totalPrice', context.totalPrice); | ||
150 | + } | ||
151 | + handleInputChange(context.payWay, 0, context.totalPrice); | ||
152 | + } | ||
153 | + | ||
154 | + useEffect(() => { | ||
155 | + getBody(); | ||
156 | + }, []); | ||
157 | + | ||
158 | + function getEditProductBody(value) { | ||
159 | + // console.log(value); | ||
160 | + | ||
161 | + setEditProductBody(value); | ||
162 | + let price = 0; | ||
163 | + value.map((obj) => (price += obj.count * obj.unitPrice)); | ||
164 | + setTotal(price); | ||
165 | + setContextBody({ ...contextBody, orderStagesDeviceVoList: value }); | ||
166 | + handleInputChange(contextBody.payWay, 0, price); | ||
167 | + } | ||
168 | + | ||
169 | + return ( | ||
170 | + <ModalForm<OrderStagesWithListItem> | ||
171 | + title="新建" | ||
172 | + trigger={<a onClick={refresh}>查看</a>} | ||
173 | + form={form} | ||
174 | + autoFocusFirstInput | ||
175 | + modalProps={{ | ||
176 | + destroyOnClose: true, | ||
177 | + // onCancel: () => console.log('run'), | ||
178 | + }} | ||
179 | + submitTimeout={2000} | ||
180 | + onFinish={async (values) => { | ||
181 | + // console.log(values); | ||
182 | + // console.log(otherBody); | ||
183 | + let remakeValue = []; | ||
184 | + // 创建一个用于存储所有异步操作的Promise数组 | ||
185 | + const promises = []; | ||
186 | + | ||
187 | + otherBody.forEach((item) => { | ||
188 | + let remakeItem = { | ||
189 | + ossId: item.ossId, | ||
190 | + number: item.id, | ||
191 | + dataRange: item.payDate, | ||
192 | + fileName: item.fileName, | ||
193 | + }; | ||
194 | + if ( | ||
195 | + typeof item.fileUrl === 'object' && | ||
196 | + item.fileUrl instanceof File | ||
197 | + ) { | ||
198 | + const formData = new FormData(); | ||
199 | + formData.append('file', item.fileUrl as RcFile); | ||
200 | + const uploadPromise = async () => { | ||
201 | + const res = await postOrderErpOrderStagesUpload({ | ||
202 | + data: formData, | ||
203 | + headers: { | ||
204 | + 'Content-Type': | ||
205 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | ||
206 | + }, | ||
207 | + }); | ||
208 | + if (res.data) { | ||
209 | + remakeItem.fileUrl = res.data; | ||
210 | + } | ||
211 | + }; | ||
212 | + promises.push(uploadPromise()); | ||
213 | + } | ||
214 | + remakeValue.push(remakeItem); | ||
215 | + }); | ||
216 | + | ||
217 | + // 使用Promise.all等待所有异步操作完成后再执行保存操作 | ||
218 | + Promise.all(promises).then(async () => { | ||
219 | + await postOrderErpOrderStagesPayWaySaveOrUpdate({ | ||
220 | + data: remakeValue, | ||
221 | + }); | ||
222 | + }); | ||
223 | + const formData = new FormData(); | ||
224 | + // let toSendEdit={...values,orderStagesDeviceVoList:contextBody.orderStagesDeviceVoList}; | ||
225 | + let toSendEdit = { | ||
226 | + id: values.id || contextBody.id, | ||
227 | + contract: values.contract || contextBody.contract, | ||
228 | + vendor: values.vendor || contextBody.vendor, | ||
229 | + dateRange: values.dateRange || contextBody.dateRange, | ||
230 | + terminal: values.terminal || contextBody.terminal, | ||
231 | + orderStagesDeviceDoList: | ||
232 | + values.orderStagesDeviceVoList || | ||
233 | + contextBody.orderStagesDeviceVoList, | ||
234 | + totalPrice: values.totalPrice || contextBody.totalPrice, | ||
235 | + payWay: values.payWay || contextBody.payWay, | ||
236 | + annex: contextBody.annex, | ||
237 | + remark: values.remark || contextBody.remark, | ||
238 | + }; | ||
239 | + if (values.annex) { | ||
240 | + formData.append('file', values.annex[0].originFileObj as RcFile); | ||
241 | + const res = await postOrderErpOrderStagesUpload({ | ||
242 | + data: formData, | ||
243 | + headers: { | ||
244 | + 'Content-Type': | ||
245 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | ||
246 | + }, | ||
247 | + }); | ||
248 | + if (res.data) { | ||
249 | + // console.log(values) | ||
250 | + // console.log(contextBody); | ||
251 | + toSendEdit.annex = res.data; | ||
252 | + } | ||
253 | + } | ||
254 | + const isSaveOrUpdate = await postOrderErpOrderStagesSaveOrUpdate({ | ||
255 | + data: { ...toSendEdit }, | ||
256 | + }); | ||
257 | + if (isSaveOrUpdate) { | ||
258 | + // console.log(isSaveOrUpdate); | ||
259 | + getBody(); | ||
260 | + } | ||
261 | + await waitTime(2000); | ||
262 | + message.success('提交成功'); | ||
263 | + return true; | ||
264 | + }} | ||
265 | + > | ||
266 | + <ProCard title="基本信息" headerBordered bordered> | ||
267 | + <ProForm.Group> | ||
268 | + <ProFormText | ||
269 | + width="md" | ||
270 | + name="vendor" | ||
271 | + label="供应商名称" | ||
272 | + placeholder="请输入" | ||
273 | + initialValue={contextBody.vendor} | ||
274 | + readonly | ||
275 | + /> | ||
276 | + | ||
277 | + <ProFormText | ||
278 | + width="md" | ||
279 | + name="terminal" | ||
280 | + label="终端名称" | ||
281 | + placeholder="请输入" | ||
282 | + initialValue={contextBody.terminal} | ||
283 | + readonly | ||
284 | + /> | ||
285 | + | ||
286 | + <ProFormDatePicker | ||
287 | + name="dateRange" | ||
288 | + width="md" | ||
289 | + label="签合同日期" | ||
290 | + placeholder="请选择日期" | ||
291 | + fieldProps={{ | ||
292 | + format: (value) => value.format('YYYY-MM-DD'), | ||
293 | + }} | ||
294 | + initialValue={contextBody.dateRange} | ||
295 | + readonly | ||
296 | + /> | ||
297 | + | ||
298 | + <ProFormText | ||
299 | + width="md" | ||
300 | + name="payWay" | ||
301 | + label="付款比例" | ||
302 | + placeholder="请输入" | ||
303 | + initialValue={contextBody.payWay} | ||
304 | + readonly | ||
305 | + onBlur={(e) => { | ||
306 | + handleInputChange(e.target.value, 1); | ||
307 | + }} | ||
308 | + /> | ||
309 | + | ||
310 | + <ProFormText | ||
311 | + width="md" | ||
312 | + name="contract" | ||
313 | + label="合同编号" | ||
314 | + placeholder="请输入" | ||
315 | + initialValue={contextBody.contract} | ||
316 | + readonly | ||
317 | + /> | ||
318 | + | ||
319 | + {/* <ProFormText | ||
320 | + width="md" | ||
321 | + name="annex" | ||
322 | + label="合同附件" | ||
323 | + placeholder="请输入" | ||
324 | + initialValue={contextBody.fileUrl} | ||
325 | + readonly | ||
326 | + /> */} | ||
327 | + | ||
328 | + <ProFormText | ||
329 | + width="md" | ||
330 | + name="totalPrice" | ||
331 | + label="合同金额" | ||
332 | + placeholder="请输入" | ||
333 | + disabled | ||
334 | + readonly | ||
335 | + // rules={[{ required: true, message: '此项为必填项' }]} | ||
336 | + // value={contextBody.totalPrice} | ||
337 | + initialValue={contextBody.totalPrice} | ||
338 | + /> | ||
339 | + </ProForm.Group> | ||
340 | + </ProCard> | ||
341 | + <ProCard | ||
342 | + title="产品明细" | ||
343 | + style={{ marginTop: 10 }} | ||
344 | + headerBordered | ||
345 | + bordered | ||
346 | + > | ||
347 | + <ProductDetail | ||
348 | + productBody={contextBody.orderStagesDeviceVoList} | ||
349 | + EditProductBody={getEditProductBody} | ||
350 | + ></ProductDetail> | ||
351 | + </ProCard> | ||
352 | + | ||
353 | + <ProCard | ||
354 | + title="付款信息" | ||
355 | + style={{ marginTop: 10 }} | ||
356 | + headerBordered | ||
357 | + bordered | ||
358 | + > | ||
359 | + <PayWayDetail | ||
360 | + payBody={payWayBody} | ||
361 | + thisId={contextBody.id} | ||
362 | + currtSave={setSave} | ||
363 | + ></PayWayDetail> | ||
364 | + </ProCard> | ||
365 | + | ||
366 | + <ProCard style={{ marginTop: 10 }} headerBordered bordered> | ||
367 | + <ProFormTextArea | ||
368 | + label="备注" | ||
369 | + name="remark" | ||
370 | + initialValue={contextBody.remark} | ||
371 | + readonly | ||
372 | + /> | ||
373 | + </ProCard> | ||
374 | + </ModalForm> | ||
375 | + ); | ||
376 | +}; |
src/pages/Instalment/components/read/readPayWay.tsx
0 → 100644
1 | +import { postOrderErpOrderStagesPayWaySelect } from '@/services'; | ||
2 | +import type { ProColumns } from '@ant-design/pro-components'; | ||
3 | +import { | ||
4 | + EditableProTable, | ||
5 | + ProFormRadio, | ||
6 | + ProFormUploadButton, | ||
7 | +} from '@ant-design/pro-components'; | ||
8 | +import { message } from 'antd'; | ||
9 | +import React, { useEffect, useState } from 'react'; | ||
10 | + | ||
11 | +const waitTime = (time: number = 100) => { | ||
12 | + return new Promise((resolve) => { | ||
13 | + setTimeout(() => { | ||
14 | + resolve(true); | ||
15 | + }, time); | ||
16 | + }); | ||
17 | +}; | ||
18 | + | ||
19 | +type DataSourceType = { | ||
20 | + id: number; | ||
21 | + payStep?: string; | ||
22 | + proportion?: string; | ||
23 | + ossId?: number; | ||
24 | + payPrice?: number; | ||
25 | + payDate?: Date; | ||
26 | + fileName?: string; | ||
27 | + fileUrl?: string; | ||
28 | +}; | ||
29 | + | ||
30 | +export default ({ payBody, thisId, currtSave }) => { | ||
31 | + const defaultData: DataSourceType[] = [ | ||
32 | + { | ||
33 | + id: 1, | ||
34 | + payStep: '预付款', | ||
35 | + proportion: undefined, | ||
36 | + payPrice: undefined, | ||
37 | + ossId: undefined, | ||
38 | + payDate: undefined, | ||
39 | + fileName: undefined, | ||
40 | + fileUrl: undefined, | ||
41 | + }, | ||
42 | + { | ||
43 | + id: 2, | ||
44 | + payStep: '发贷款', | ||
45 | + proportion: undefined, | ||
46 | + payPrice: undefined, | ||
47 | + ossId: undefined, | ||
48 | + payDate: undefined, | ||
49 | + fileName: undefined, | ||
50 | + fileUrl: undefined, | ||
51 | + }, | ||
52 | + { | ||
53 | + id: 3, | ||
54 | + payStep: '验收款', | ||
55 | + proportion: undefined, | ||
56 | + payPrice: undefined, | ||
57 | + ossId: undefined, | ||
58 | + payDate: undefined, | ||
59 | + fileName: undefined, | ||
60 | + fileUrl: undefined, | ||
61 | + }, | ||
62 | + { | ||
63 | + id: 4, | ||
64 | + payStep: '质保金', | ||
65 | + proportion: undefined, | ||
66 | + payPrice: undefined, | ||
67 | + ossId: undefined, | ||
68 | + payDate: undefined, | ||
69 | + fileName: undefined, | ||
70 | + fileUrl: undefined, | ||
71 | + }, | ||
72 | + ]; | ||
73 | + | ||
74 | + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]); | ||
75 | + const [position, setPosition] = useState<'top' | 'bottom' | 'hidden'>( | ||
76 | + 'hidden', | ||
77 | + ); | ||
78 | + const [payWayDetailBody, setPayWayDetailBody] = useState< | ||
79 | + readonly DataSourceType[] | ||
80 | + >([...defaultData]); | ||
81 | + const [isAccept] = useState(null); | ||
82 | + // const [isCurrtSave, setIsCurrtSave] = useState(false); | ||
83 | + | ||
84 | + async function getOther(value, arr) { | ||
85 | + const res = await postOrderErpOrderStagesPayWaySelect({ | ||
86 | + data: { ossId: value }, | ||
87 | + }); | ||
88 | + if (res.data) { | ||
89 | + const context = res.data; | ||
90 | + const remake = arr.map((obj) => { | ||
91 | + let currt = obj; | ||
92 | + context.forEach((object) => { | ||
93 | + if (object.number === obj.id) { | ||
94 | + currt = { | ||
95 | + ...obj, | ||
96 | + ossId: value, | ||
97 | + payDate: object.dateRange, | ||
98 | + fileName: object.fileName, | ||
99 | + fileUrl: object.fileUrl, | ||
100 | + }; | ||
101 | + return currt; | ||
102 | + } | ||
103 | + }); | ||
104 | + return currt; | ||
105 | + }); | ||
106 | + setPayWayDetailBody(remake); | ||
107 | + } | ||
108 | + } | ||
109 | + | ||
110 | + function setPayWay(value) { | ||
111 | + const remakeData = payWayDetailBody.map((obj) => { | ||
112 | + return { | ||
113 | + ...obj, | ||
114 | + proportion: value[obj.id - 1]?.proportion, | ||
115 | + payPrice: value[obj.id - 1]?.payPrice, | ||
116 | + }; | ||
117 | + }); | ||
118 | + | ||
119 | + setPayWayDetailBody(remakeData); | ||
120 | + | ||
121 | + if (thisId !== null) { | ||
122 | + getOther(thisId, remakeData); | ||
123 | + } | ||
124 | + } | ||
125 | + // useEffect(() => { | ||
126 | + // getOther(thisId) | ||
127 | + // }, [thisId]) | ||
128 | + | ||
129 | + useEffect(() => { | ||
130 | + setPayWay(payBody); | ||
131 | + }, [payBody]); | ||
132 | + | ||
133 | + // function setCurrtSave(_value) { | ||
134 | + // setIsCurrtSave(payWayDetailBody) | ||
135 | + // } | ||
136 | + | ||
137 | + const columns: ProColumns<DataSourceType>[] = [ | ||
138 | + { | ||
139 | + title: '编号', | ||
140 | + dataIndex: 'id', | ||
141 | + hideInTable: true, | ||
142 | + editable: false, | ||
143 | + }, | ||
144 | + { | ||
145 | + title: '付款信息', | ||
146 | + dataIndex: 'payStep', | ||
147 | + editable: false, | ||
148 | + }, | ||
149 | + { | ||
150 | + title: '付款比例', | ||
151 | + dataIndex: 'proportion', | ||
152 | + editable: false, | ||
153 | + }, | ||
154 | + { | ||
155 | + title: '付款金额', | ||
156 | + dataIndex: 'payPrice', | ||
157 | + editable: false, | ||
158 | + }, | ||
159 | + { | ||
160 | + title: '对应的订单', | ||
161 | + dataIndex: 'ossId', | ||
162 | + editable: false, | ||
163 | + hideInTable: true, | ||
164 | + }, | ||
165 | + { | ||
166 | + title: '付款时间', | ||
167 | + dataIndex: 'payDate', | ||
168 | + editable: false, | ||
169 | + render: (_text, record) => { | ||
170 | + return ( | ||
171 | + <span> | ||
172 | + {new Intl.DateTimeFormat('zh-CN', { | ||
173 | + year: 'numeric', | ||
174 | + month: 'long', | ||
175 | + day: 'numeric', | ||
176 | + }).format(record.payDate)} | ||
177 | + </span> | ||
178 | + // <ProFormDatePicker | ||
179 | + // className='dataChoose' | ||
180 | + // initialValue={record.payDate} | ||
181 | + // value={record.payDate} | ||
182 | + // placeholder={"请填写时间"} | ||
183 | + // fieldProps={{ | ||
184 | + // format: (value) => value.format('YYYY-MM-DD'), | ||
185 | + // onChange: handleChange, | ||
186 | + // }} | ||
187 | + // /> | ||
188 | + ); | ||
189 | + }, | ||
190 | + }, | ||
191 | + { | ||
192 | + title: '付款单回执', | ||
193 | + dataIndex: 'fileName', | ||
194 | + render: (_text, record) => { | ||
195 | + if (isAccept !== record.id) { | ||
196 | + if ( | ||
197 | + typeof record.fileUrl === 'object' && | ||
198 | + record.fileUrl instanceof File | ||
199 | + ) { | ||
200 | + return ( | ||
201 | + <a onClick={() => message.error('请先保存')}>{record.fileName}</a> | ||
202 | + ); | ||
203 | + } else { | ||
204 | + return <a href={record.fileUrl}>{record.fileName}</a>; | ||
205 | + } | ||
206 | + } else { | ||
207 | + return ( | ||
208 | + <ProFormUploadButton | ||
209 | + name={record.id} | ||
210 | + onChange={(value) => { | ||
211 | + let remakeBody = []; | ||
212 | + let remakeBodyItem = {}; | ||
213 | + payWayDetailBody.forEach((item) => { | ||
214 | + if (item.id === record.id) { | ||
215 | + remakeBodyItem = { | ||
216 | + ...item, | ||
217 | + fileUrl: value.file.originFileObj, | ||
218 | + fileName: value.file.name, | ||
219 | + }; | ||
220 | + } else { | ||
221 | + remakeBodyItem = { ...item }; | ||
222 | + } | ||
223 | + if (value.fileList.length === 0) { | ||
224 | + remakeBodyItem = { | ||
225 | + ...item, | ||
226 | + fileUrl: undefined, | ||
227 | + fileName: undefined, | ||
228 | + }; | ||
229 | + } | ||
230 | + remakeBody.push(remakeBodyItem); | ||
231 | + }); | ||
232 | + setPayWayDetailBody(remakeBody); | ||
233 | + currtSave(remakeBody); | ||
234 | + }} | ||
235 | + width="md" | ||
236 | + max={1} | ||
237 | + /> | ||
238 | + ); | ||
239 | + } | ||
240 | + }, | ||
241 | + }, | ||
242 | + ]; | ||
243 | + | ||
244 | + return ( | ||
245 | + <> | ||
246 | + <EditableProTable<DataSourceType> | ||
247 | + rowKey="id" | ||
248 | + className="payway-detail-index" | ||
249 | + toolbar={{ style: { display: 'none' } }} | ||
250 | + ghost={true} | ||
251 | + scroll={{ | ||
252 | + x: 960, | ||
253 | + }} | ||
254 | + recordCreatorProps={ | ||
255 | + position !== 'hidden' | ||
256 | + ? { | ||
257 | + position: position as 'top', | ||
258 | + record: () => ({ id: (Math.random() * 1000000).toFixed(0) }), | ||
259 | + } | ||
260 | + : false | ||
261 | + } | ||
262 | + loading={false} | ||
263 | + toolBarRender={() => [ | ||
264 | + <ProFormRadio.Group | ||
265 | + key="render" | ||
266 | + fieldProps={{ | ||
267 | + value: position, | ||
268 | + onChange: (e) => setPosition(e.target.value), | ||
269 | + }} | ||
270 | + />, | ||
271 | + ]} | ||
272 | + columns={columns} | ||
273 | + request={payWayDetailBody} | ||
274 | + value={payWayDetailBody} | ||
275 | + onChange={(value) => { | ||
276 | + setPayWayDetailBody(value); | ||
277 | + // setCurrtSave(payWayDetailBody) | ||
278 | + }} | ||
279 | + editable={{ | ||
280 | + type: 'multiple', | ||
281 | + editableKeys, | ||
282 | + onSave: async () => { | ||
283 | + await waitTime(2000); | ||
284 | + }, | ||
285 | + onChange: setEditableRowKeys, | ||
286 | + }} | ||
287 | + /> | ||
288 | + </> | ||
289 | + ); | ||
290 | +}; |
src/pages/Instalment/components/read/readProduct.tsx
0 → 100644
1 | +import type { ProColumns } from '@ant-design/pro-components'; | ||
2 | +import { EditableProTable, ProFormRadio } from '@ant-design/pro-components'; | ||
3 | +import { Form } from 'antd'; | ||
4 | +import React, { useEffect, useState } from 'react'; | ||
5 | + | ||
6 | +const waitTime = (time: number = 100) => { | ||
7 | + return new Promise((resolve) => { | ||
8 | + setTimeout(() => { | ||
9 | + resolve(true); | ||
10 | + }, time); | ||
11 | + }); | ||
12 | +}; | ||
13 | + | ||
14 | +// type DataSourceType = { | ||
15 | +// count?: number; | ||
16 | +// id: React.Key; | ||
17 | +// deviceModel?: string; | ||
18 | +// deviceName?: string; | ||
19 | +// price?: number; | ||
20 | +// unitPrice?: number; | ||
21 | +// }; | ||
22 | + | ||
23 | +export default ({ productBody, EditProductBody }) => { | ||
24 | + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]); | ||
25 | + const [dataSource, setDataSource] = useState<readonly DataSourceType[]>([]); | ||
26 | + const [form] = Form.useForm<{ name: string; company: string }>(); | ||
27 | + const [position, setPosition] = useState<'top' | 'bottom' | 'hidden'>( | ||
28 | + 'hidden', | ||
29 | + ); | ||
30 | + function getDataSourece() { | ||
31 | + if (productBody.length !== 0) { | ||
32 | + setDataSource(productBody); | ||
33 | + } | ||
34 | + } | ||
35 | + function setEditProductBody(value) { | ||
36 | + const modifiedArray = value.map((obj) => { | ||
37 | + if (obj.dId && Number(obj.dId) <= 1000) { | ||
38 | + return { | ||
39 | + ...obj, | ||
40 | + count: obj.count, | ||
41 | + dId: null, | ||
42 | + deviceModel: obj.deviceModel, | ||
43 | + deviceName: obj.deviceName, | ||
44 | + price: obj.price, | ||
45 | + unitPrice: obj.unitPrice, | ||
46 | + }; | ||
47 | + } else { | ||
48 | + return obj; | ||
49 | + } | ||
50 | + }); | ||
51 | + | ||
52 | + EditProductBody(modifiedArray); | ||
53 | + setDataSource(value); | ||
54 | + } | ||
55 | + | ||
56 | + useEffect(() => { | ||
57 | + getDataSourece(); | ||
58 | + }, [productBody]); | ||
59 | + | ||
60 | + type DataSourceType = { | ||
61 | + id: React.Key; | ||
62 | + count: number; | ||
63 | + dId?: number; | ||
64 | + deviceModel: string; | ||
65 | + deviceName: string; | ||
66 | + price: number; | ||
67 | + unitPrice: number; | ||
68 | + }; | ||
69 | + | ||
70 | + const columns: ProColumns<DataSourceType>[] = [ | ||
71 | + { | ||
72 | + title: '设备编号', | ||
73 | + dataIndex: 'dId', | ||
74 | + hideInTable: true, | ||
75 | + }, | ||
76 | + { | ||
77 | + title: '设备名称', | ||
78 | + dataIndex: 'deviceName', | ||
79 | + formItemProps: () => { | ||
80 | + return { | ||
81 | + rules: [{ required: true, message: '此项为必填项' }], | ||
82 | + }; | ||
83 | + }, | ||
84 | + }, | ||
85 | + { | ||
86 | + title: '设备型号', | ||
87 | + dataIndex: 'deviceModel', | ||
88 | + width: '15%', | ||
89 | + formItemProps: () => { | ||
90 | + return { | ||
91 | + rules: [{ required: true, message: '此项为必填项' }], | ||
92 | + }; | ||
93 | + }, | ||
94 | + }, | ||
95 | + { | ||
96 | + title: '数量', | ||
97 | + dataIndex: 'count', | ||
98 | + onChange: (e) => { | ||
99 | + const unitPrice = form.getFieldValue(`data[${rowIndex}].unitPrice`); | ||
100 | + form.setFieldsValue({ | ||
101 | + [`data[${rowIndex}].price`]: e * unitPrice, | ||
102 | + }); | ||
103 | + }, | ||
104 | + formItemProps: () => { | ||
105 | + return { | ||
106 | + rules: [{ required: true, message: '此项为必填项' }], | ||
107 | + }; | ||
108 | + }, | ||
109 | + }, | ||
110 | + { | ||
111 | + title: '单价', | ||
112 | + dataIndex: 'unitPrice', | ||
113 | + formItemProps: () => { | ||
114 | + return { | ||
115 | + rules: [{ required: true, message: '此项为必填项' }], | ||
116 | + }; | ||
117 | + }, | ||
118 | + }, | ||
119 | + { | ||
120 | + title: '总价', | ||
121 | + dataIndex: 'price', | ||
122 | + formItemProps: () => { | ||
123 | + return { | ||
124 | + rules: [{ required: true, message: '此项为必填项' }], | ||
125 | + }; | ||
126 | + }, | ||
127 | + }, | ||
128 | + ]; | ||
129 | + | ||
130 | + return ( | ||
131 | + <> | ||
132 | + <EditableProTable<DataSourceType> | ||
133 | + className="product-detail-index" | ||
134 | + rowKey="dId" | ||
135 | + toolbar={{ style: { display: 'none' } }} | ||
136 | + ghost={true} | ||
137 | + scroll={{ | ||
138 | + x: 960, | ||
139 | + }} | ||
140 | + recordCreatorProps={ | ||
141 | + position !== 'hidden' | ||
142 | + ? { | ||
143 | + position: position as 'top', | ||
144 | + record: () => ({ dId: (Math.random() * 1000).toFixed(0) }), | ||
145 | + } | ||
146 | + : false | ||
147 | + } | ||
148 | + loading={false} | ||
149 | + toolBarRender={() => [ | ||
150 | + <ProFormRadio.Group | ||
151 | + key="render" | ||
152 | + fieldProps={{ | ||
153 | + value: position, | ||
154 | + onChange: (e) => setPosition(e.target.value), | ||
155 | + }} | ||
156 | + />, | ||
157 | + ]} | ||
158 | + columns={columns} | ||
159 | + request={dataSource} | ||
160 | + value={dataSource} | ||
161 | + onChange={setEditProductBody} | ||
162 | + editable={{ | ||
163 | + type: 'multiple', | ||
164 | + editableKeys, | ||
165 | + onSave: async () => { | ||
166 | + await waitTime(500); | ||
167 | + }, | ||
168 | + onChange: setEditableRowKeys, | ||
169 | + }} | ||
170 | + /> | ||
171 | + </> | ||
172 | + ); | ||
173 | +}; |
src/pages/Instalment/components/title/title.less
0 → 100644
1 | +.item { | ||
2 | + background: '#0092ff'; | ||
3 | + padding: '8px 0'; | ||
4 | + display: flex; | ||
5 | + flex-flow: row nowrap; | ||
6 | + // flex-direction: row; | ||
7 | + // flex-wrap: nowrap; | ||
8 | + align-content: normal; | ||
9 | + align-items: center; | ||
10 | + padding-bottom: 20px; | ||
11 | +} | ||
12 | + | ||
13 | +// .titleSpan{ | ||
14 | +// font-weight: bold; | ||
15 | +// width: 100px; | ||
16 | +// } | ||
17 | + | ||
18 | +// .Btn{ | ||
19 | +// background: '#0092ff'; | ||
20 | +// padding: '8px 0'; | ||
21 | +// display: flex; | ||
22 | +// flex-flow: row nowrap; | ||
23 | +// // flex-direction: row; | ||
24 | +// // flex-wrap: nowrap; | ||
25 | +// align-content: normal; | ||
26 | +// align-items: center; | ||
27 | +// padding-bottom: 20px; | ||
28 | +// justify-content: space-between; | ||
29 | +// width: 160px; | ||
30 | +// } | ||
31 | + | ||
32 | +.title-index td { | ||
33 | + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial, | ||
34 | + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC', | ||
35 | + 'WenQuanYi Micro Hei', sans-serif; | ||
36 | + font-size: 14px; | ||
37 | +} |
src/pages/Instalment/components/title/title.tsx
0 → 100644
1 | +import { | ||
2 | + deleteOrderErpOrderStagesDelect, | ||
3 | + getOrderErpOrderStagesListAll, | ||
4 | + postOrderErpOrderStagesSearch, | ||
5 | +} from '@/services'; | ||
6 | +import { orderExport } from '@/services/order'; | ||
7 | +import { VerticalAlignTopOutlined } from '@ant-design/icons'; | ||
8 | +import type { ProColumns } from '@ant-design/pro-components'; | ||
9 | +import { ProTable } from '@ant-design/pro-components'; | ||
10 | +import { Button, message } from 'antd'; | ||
11 | +import { useRef } from 'react'; | ||
12 | +import Comfire from '../comfire/comfire'; | ||
13 | +import AddModel from '../detail/detail'; | ||
14 | +import EditorModel from '../edit/edit'; | ||
15 | +import ReadModel from '../read/read'; | ||
16 | +import UploadModel from '../upload/uploadModel'; | ||
17 | +import './title.less'; | ||
18 | +export const waitTimePromise = async (time: number = 100) => { | ||
19 | + return new Promise((resolve) => { | ||
20 | + setTimeout(() => { | ||
21 | + resolve(true); | ||
22 | + }, time); | ||
23 | + }); | ||
24 | +}; | ||
25 | + | ||
26 | +export const waitTime = async (time: number = 100) => { | ||
27 | + await waitTimePromise(time); | ||
28 | +}; | ||
29 | + | ||
30 | +type OrderStagesItem = { | ||
31 | + //文件编号 | ||
32 | + id?: number; | ||
33 | + //合同编号 | ||
34 | + contract?: string; | ||
35 | + //供应商名称 | ||
36 | + vendor?: string; | ||
37 | + //签合同日期 | ||
38 | + dateRange?: Date; | ||
39 | + //终端名称 | ||
40 | + terminal?: string; | ||
41 | + //设备编号 | ||
42 | + dId?: number; | ||
43 | + //设备名称 | ||
44 | + deviceName?: string; | ||
45 | + //设备型号 | ||
46 | + deviceModel?: string; | ||
47 | + //数量 | ||
48 | + count?: number; | ||
49 | + //单价 | ||
50 | + unitPrice?: number; | ||
51 | + //总价 | ||
52 | + price?: number; | ||
53 | + //合同总金额 | ||
54 | + totalPrice?: number; | ||
55 | + //付款方式 | ||
56 | + payWay?: string; | ||
57 | + //附件 | ||
58 | + annex?: string; | ||
59 | + //备注 | ||
60 | + remark?: string; | ||
61 | +}; | ||
62 | + | ||
63 | +type OrderStagesWithListItem = { | ||
64 | + //文件编号 | ||
65 | + id: number; | ||
66 | + //合同编号 | ||
67 | + contract: string; | ||
68 | + //供应商名称 | ||
69 | + vendor: string; | ||
70 | + //签合同日期 | ||
71 | + dateRange: Date; | ||
72 | + //终端名称 | ||
73 | + terminal: string; | ||
74 | + orderStagesDeviceVoList: orderStagesDevice[]; | ||
75 | + //合同总金额 | ||
76 | + totalPrice: number; | ||
77 | + //付款方式 | ||
78 | + payWay: string; | ||
79 | + //附件 | ||
80 | + annex: string; | ||
81 | + //备注 | ||
82 | + remark: string; | ||
83 | +}; | ||
84 | + | ||
85 | +type orderStagesDevice = { | ||
86 | + //设备id | ||
87 | + dId: number; | ||
88 | + //设备名称 | ||
89 | + deviceName: string; | ||
90 | + //设备型号 | ||
91 | + deviceModel: string; | ||
92 | + //数量 | ||
93 | + count: number; | ||
94 | + //单价 | ||
95 | + unitPrice: number; | ||
96 | + //总价 | ||
97 | + price: number; | ||
98 | +}; | ||
99 | + | ||
100 | +export default () => { | ||
101 | + // const actionRef = useRef<ActionType>(); | ||
102 | + // const [TableItem, setTableItem] = useState([]); | ||
103 | + | ||
104 | + interface ActionType { | ||
105 | + reload: (resetPageIndex?: boolean) => void; | ||
106 | + reloadAndRest: () => void; | ||
107 | + reset: () => void; | ||
108 | + clearSelected?: () => void; | ||
109 | + startEditable: (rowKey: Key) => boolean; | ||
110 | + cancelEditable: (rowKey: Key) => boolean; | ||
111 | + } | ||
112 | + | ||
113 | + const ref = useRef<ActionType>({ | ||
114 | + reload: () => { | ||
115 | + // implementation for reload | ||
116 | + }, | ||
117 | + reloadAndRest: () => { | ||
118 | + // implementation for reloadAndRest | ||
119 | + }, | ||
120 | + reset: () => { | ||
121 | + // implementation for reset | ||
122 | + }, | ||
123 | + startEditable: () => { | ||
124 | + // implementation for startEditable | ||
125 | + }, | ||
126 | + cancelEditable: () => { | ||
127 | + // implementation for cancelEditable | ||
128 | + }, | ||
129 | + }); | ||
130 | + | ||
131 | + function reload() { | ||
132 | + ref.current.reload(); | ||
133 | + } | ||
134 | + | ||
135 | + async function toDelete(value) { | ||
136 | + const res = await deleteOrderErpOrderStagesDelect({ | ||
137 | + data: { | ||
138 | + ids: null, | ||
139 | + deviceIds: value, | ||
140 | + }, | ||
141 | + }); | ||
142 | + if (res) { | ||
143 | + message.success('删除成功'); | ||
144 | + ref.current.reload(); | ||
145 | + } else { | ||
146 | + message.error('删除失败'); | ||
147 | + } | ||
148 | + } | ||
149 | + | ||
150 | + const exportLoadingDestory = () => { | ||
151 | + message.success('导出成功'); | ||
152 | + }; | ||
153 | + | ||
154 | + async function toExport() { | ||
155 | + // await getOrderErpOrderStagesExport() | ||
156 | + orderExport( | ||
157 | + '/api/order/erp/orderStages/export', | ||
158 | + '分期订单.xlsx', | ||
159 | + 'get', | ||
160 | + {}, | ||
161 | + exportLoadingDestory, | ||
162 | + ); | ||
163 | + } | ||
164 | + | ||
165 | + const columns: ProColumns<OrderStagesItem>[] = [ | ||
166 | + { | ||
167 | + title: '文件编号', | ||
168 | + dataIndex: 'id', | ||
169 | + width: '7%', | ||
170 | + render: (_, record) => { | ||
171 | + if (record.id) { | ||
172 | + const text = record.id.toString(); | ||
173 | + const paddedText = '0'.repeat(4 - text.length) + text; | ||
174 | + return paddedText; | ||
175 | + } | ||
176 | + }, | ||
177 | + }, | ||
178 | + { | ||
179 | + title: '签合同日期', | ||
180 | + dataIndex: 'dateRange', | ||
181 | + valueType: 'date', | ||
182 | + filters: true, | ||
183 | + onFilter: true, | ||
184 | + ellipsis: true, | ||
185 | + width: '8%', | ||
186 | + }, | ||
187 | + { | ||
188 | + disable: true, | ||
189 | + title: '合同编号', | ||
190 | + dataIndex: 'contract', | ||
191 | + filters: true, | ||
192 | + onFilter: true, | ||
193 | + ellipsis: true, | ||
194 | + width: '9%', | ||
195 | + }, | ||
196 | + { | ||
197 | + disable: true, | ||
198 | + title: '供应商名称', | ||
199 | + dataIndex: 'vendor', | ||
200 | + filters: true, | ||
201 | + onFilter: true, | ||
202 | + ellipsis: true, | ||
203 | + }, | ||
204 | + { | ||
205 | + disable: true, | ||
206 | + title: '终端名称', | ||
207 | + dataIndex: 'terminal', | ||
208 | + filters: true, | ||
209 | + onFilter: true, | ||
210 | + ellipsis: true, | ||
211 | + width: '6%', | ||
212 | + }, | ||
213 | + { | ||
214 | + disable: true, | ||
215 | + title: '设备名称', | ||
216 | + dataIndex: 'deviceName', | ||
217 | + filters: true, | ||
218 | + onFilter: true, | ||
219 | + ellipsis: true, | ||
220 | + }, | ||
221 | + { | ||
222 | + disable: true, | ||
223 | + title: '设备型号', | ||
224 | + dataIndex: 'deviceModel', | ||
225 | + filters: true, | ||
226 | + hideInSearch: true, | ||
227 | + onFilter: false, | ||
228 | + ellipsis: true, | ||
229 | + width: '10%', | ||
230 | + }, | ||
231 | + { | ||
232 | + disable: true, | ||
233 | + title: '数量', | ||
234 | + dataIndex: 'count', | ||
235 | + filters: true, | ||
236 | + hideInSearch: true, | ||
237 | + onFilter: false, | ||
238 | + ellipsis: true, | ||
239 | + width: '4%', | ||
240 | + }, | ||
241 | + { | ||
242 | + disable: true, | ||
243 | + title: '单价', | ||
244 | + dataIndex: 'unitPrice', | ||
245 | + filters: true, | ||
246 | + hideInSearch: true, | ||
247 | + onFilter: false, | ||
248 | + ellipsis: true, | ||
249 | + width: '5%', | ||
250 | + }, | ||
251 | + { | ||
252 | + disable: true, | ||
253 | + title: '总价', | ||
254 | + dataIndex: 'price', | ||
255 | + filters: true, | ||
256 | + hideInSearch: true, | ||
257 | + onFilter: false, | ||
258 | + ellipsis: true, | ||
259 | + width: '5%', | ||
260 | + }, | ||
261 | + { | ||
262 | + disable: true, | ||
263 | + title: '合同总金额', | ||
264 | + dataIndex: 'totalPrice', | ||
265 | + filters: true, | ||
266 | + hideInSearch: true, | ||
267 | + onFilter: false, | ||
268 | + ellipsis: true, | ||
269 | + width: '6%', | ||
270 | + }, | ||
271 | + { | ||
272 | + disable: true, | ||
273 | + title: '付款方式', | ||
274 | + dataIndex: 'payWay', | ||
275 | + filters: true, | ||
276 | + hideInSearch: true, | ||
277 | + onFilter: false, | ||
278 | + ellipsis: true, | ||
279 | + }, | ||
280 | + { | ||
281 | + disable: true, | ||
282 | + title: '附件', | ||
283 | + dataIndex: 'annex', | ||
284 | + filters: true, | ||
285 | + hideInSearch: true, | ||
286 | + onFilter: false, | ||
287 | + ellipsis: true, | ||
288 | + width: '5%', | ||
289 | + render: (_, record) => { | ||
290 | + if (record.id) { | ||
291 | + return <a href={record.annex}>{record.annex}</a>; | ||
292 | + } | ||
293 | + }, | ||
294 | + }, | ||
295 | + { | ||
296 | + disable: true, | ||
297 | + title: '备注', | ||
298 | + dataIndex: 'remark', | ||
299 | + filters: true, | ||
300 | + hideInSearch: true, | ||
301 | + onFilter: false, | ||
302 | + ellipsis: true, | ||
303 | + width: '5%', | ||
304 | + }, | ||
305 | + { | ||
306 | + title: '操作', | ||
307 | + valueType: 'option', | ||
308 | + key: 'option', | ||
309 | + width: '10%', | ||
310 | + render: (_text, record) => { | ||
311 | + if (record?.id) { | ||
312 | + return ( | ||
313 | + <> | ||
314 | + <ReadModel currentContract={record.contract}></ReadModel> | ||
315 | + | ||
316 | + <EditorModel | ||
317 | + currentContract={record.contract} | ||
318 | + toReload={reload} | ||
319 | + ></EditorModel> | ||
320 | + | ||
321 | + {/* <a key="delect" target="_blank" rel="noopener noreferrer" onClick={() => { toDelete([record.dId]) }}> | ||
322 | + 删除 | ||
323 | + </a> */} | ||
324 | + <Comfire currtDid={record.dId} sureDelete={toDelete}></Comfire> | ||
325 | + </> | ||
326 | + ); | ||
327 | + } | ||
328 | + return null; | ||
329 | + }, | ||
330 | + }, | ||
331 | + ]; | ||
332 | + | ||
333 | + return ( | ||
334 | + <ProTable<OrderStagesItem> | ||
335 | + className="title-index" | ||
336 | + columnEmptyText="" | ||
337 | + columns={columns} | ||
338 | + actionRef={ref} | ||
339 | + cardBordered | ||
340 | + request={async (params) => { | ||
341 | + // console.log(params); | ||
342 | + if ( | ||
343 | + params.id !== null || | ||
344 | + params.contract !== null || | ||
345 | + params.vendor !== null || | ||
346 | + params.terminal !== null || | ||
347 | + params.deviceName !== null || | ||
348 | + params.dateRange !== null | ||
349 | + ) { | ||
350 | + // console.log(params.id); | ||
351 | + // console.log(params.contract); | ||
352 | + // console.log(params.vendor); | ||
353 | + let PostOrderErpOrderStagesSearchOption = { | ||
354 | + id: params.id, | ||
355 | + contract: params.contract, | ||
356 | + vendor: params.vendor, | ||
357 | + terminal: params.terminal, | ||
358 | + deviceName: params.deviceName, | ||
359 | + dateRange: params.dateRange, | ||
360 | + }; | ||
361 | + let res = await postOrderErpOrderStagesSearch({ | ||
362 | + data: { ...PostOrderErpOrderStagesSearchOption }, | ||
363 | + }); | ||
364 | + await waitTime(2000); | ||
365 | + if (res) { | ||
366 | + // setTableItem(res.data) | ||
367 | + const orderStagesWithList: OrderStagesWithListItem[] = res?.data; | ||
368 | + let orderStagesList: OrderStagesItem[] = []; | ||
369 | + for (let ind = 0; ind < orderStagesWithList.length; ind++) { | ||
370 | + for ( | ||
371 | + let index = 0; | ||
372 | + index < orderStagesWithList[ind].orderStagesDeviceVoList.length; | ||
373 | + index++ | ||
374 | + ) { | ||
375 | + let item: OrderStagesItem = { | ||
376 | + id: undefined, | ||
377 | + contract: undefined, | ||
378 | + vendor: undefined, | ||
379 | + dateRange: undefined, | ||
380 | + terminal: undefined, | ||
381 | + dId: undefined, | ||
382 | + deviceName: undefined, | ||
383 | + deviceModel: undefined, | ||
384 | + count: undefined, | ||
385 | + unitPrice: undefined, | ||
386 | + price: undefined, | ||
387 | + totalPrice: undefined, | ||
388 | + payWay: undefined, | ||
389 | + annex: undefined, | ||
390 | + remark: undefined, | ||
391 | + }; | ||
392 | + if (index === 0) { | ||
393 | + item.id = orderStagesWithList[ind].id; | ||
394 | + item.contract = orderStagesWithList[ind].contract; | ||
395 | + item.vendor = orderStagesWithList[ind].vendor; | ||
396 | + item.dateRange = orderStagesWithList[ind].dateRange; | ||
397 | + item.terminal = orderStagesWithList[ind].terminal; | ||
398 | + item.dId = | ||
399 | + orderStagesWithList[ind].orderStagesDeviceVoList[index].dId; | ||
400 | + item.deviceName = | ||
401 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
402 | + index | ||
403 | + ].deviceName; | ||
404 | + item.deviceModel = | ||
405 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
406 | + index | ||
407 | + ].deviceModel; | ||
408 | + item.count = | ||
409 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
410 | + index | ||
411 | + ].count; | ||
412 | + item.unitPrice = | ||
413 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
414 | + index | ||
415 | + ].unitPrice; | ||
416 | + item.price = | ||
417 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
418 | + index | ||
419 | + ].price; | ||
420 | + item.totalPrice = orderStagesWithList[ind].totalPrice; | ||
421 | + item.payWay = orderStagesWithList[ind].payWay; | ||
422 | + item.annex = orderStagesWithList[ind].annex; | ||
423 | + item.remark = orderStagesWithList[ind].remark; | ||
424 | + orderStagesList.push(item); | ||
425 | + } else { | ||
426 | + item.id = orderStagesWithList[ind].id; | ||
427 | + item.contract = orderStagesWithList[ind].contract; | ||
428 | + item.vendor = orderStagesWithList[ind].vendor; | ||
429 | + item.dateRange = orderStagesWithList[ind].dateRange; | ||
430 | + item.terminal = orderStagesWithList[ind].terminal; | ||
431 | + item.dId = | ||
432 | + orderStagesWithList[ind].orderStagesDeviceVoList[index].dId; | ||
433 | + item.deviceName = | ||
434 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
435 | + index | ||
436 | + ].deviceName; | ||
437 | + item.deviceModel = | ||
438 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
439 | + index | ||
440 | + ].deviceModel; | ||
441 | + item.count = | ||
442 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
443 | + index | ||
444 | + ].count; | ||
445 | + item.unitPrice = | ||
446 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
447 | + index | ||
448 | + ].unitPrice; | ||
449 | + item.price = | ||
450 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
451 | + index | ||
452 | + ].price; | ||
453 | + item.totalPrice = orderStagesWithList[ind].totalPrice; | ||
454 | + item.payWay = orderStagesWithList[ind].payWay; | ||
455 | + item.annex = orderStagesWithList[ind].annex; | ||
456 | + item.remark = orderStagesWithList[ind].remark; | ||
457 | + orderStagesList.push(item); | ||
458 | + } | ||
459 | + } | ||
460 | + } | ||
461 | + return { | ||
462 | + data: orderStagesList || [], | ||
463 | + }; | ||
464 | + } | ||
465 | + } else { | ||
466 | + let res = await getOrderErpOrderStagesListAll(); | ||
467 | + await waitTime(2000); | ||
468 | + if (res) { | ||
469 | + // setTableItem(res.data) | ||
470 | + const orderStagesWithList: OrderStagesWithListItem[] = res?.data; | ||
471 | + let orderStagesList: OrderStagesItem[] = []; | ||
472 | + for (let ind = 0; ind < orderStagesWithList.length; ind++) { | ||
473 | + for ( | ||
474 | + let index = 0; | ||
475 | + index < orderStagesWithList[ind].orderStagesDeviceVoList.length; | ||
476 | + index++ | ||
477 | + ) { | ||
478 | + let item: OrderStagesItem = { | ||
479 | + id: undefined, | ||
480 | + contract: undefined, | ||
481 | + vendor: undefined, | ||
482 | + dateRange: undefined, | ||
483 | + terminal: undefined, | ||
484 | + dId: undefined, | ||
485 | + deviceName: undefined, | ||
486 | + deviceModel: undefined, | ||
487 | + count: undefined, | ||
488 | + unitPrice: undefined, | ||
489 | + price: undefined, | ||
490 | + totalPrice: undefined, | ||
491 | + payWay: undefined, | ||
492 | + annex: undefined, | ||
493 | + remark: undefined, | ||
494 | + }; | ||
495 | + if (index === 0) { | ||
496 | + item.id = orderStagesWithList[ind].id; | ||
497 | + item.contract = orderStagesWithList[ind].contract; | ||
498 | + item.vendor = orderStagesWithList[ind].vendor; | ||
499 | + item.dateRange = orderStagesWithList[ind].dateRange; | ||
500 | + item.terminal = orderStagesWithList[ind].terminal; | ||
501 | + item.dId = | ||
502 | + orderStagesWithList[ind].orderStagesDeviceVoList[index].dId; | ||
503 | + item.deviceName = | ||
504 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
505 | + index | ||
506 | + ].deviceName; | ||
507 | + item.deviceModel = | ||
508 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
509 | + index | ||
510 | + ].deviceModel; | ||
511 | + item.count = | ||
512 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
513 | + index | ||
514 | + ].count; | ||
515 | + item.unitPrice = | ||
516 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
517 | + index | ||
518 | + ].unitPrice; | ||
519 | + item.price = | ||
520 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
521 | + index | ||
522 | + ].price; | ||
523 | + item.totalPrice = orderStagesWithList[ind].totalPrice; | ||
524 | + item.payWay = orderStagesWithList[ind].payWay; | ||
525 | + item.annex = orderStagesWithList[ind].annex; | ||
526 | + item.remark = orderStagesWithList[ind].remark; | ||
527 | + orderStagesList.push(item); | ||
528 | + } else { | ||
529 | + item.id = orderStagesWithList[ind].id; | ||
530 | + item.contract = orderStagesWithList[ind].contract; | ||
531 | + item.vendor = orderStagesWithList[ind].vendor; | ||
532 | + item.dateRange = orderStagesWithList[ind].dateRange; | ||
533 | + item.terminal = orderStagesWithList[ind].terminal; | ||
534 | + item.dId = | ||
535 | + orderStagesWithList[ind].orderStagesDeviceVoList[index].dId; | ||
536 | + item.deviceName = | ||
537 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
538 | + index | ||
539 | + ].deviceName; | ||
540 | + item.deviceModel = | ||
541 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
542 | + index | ||
543 | + ].deviceModel; | ||
544 | + item.count = | ||
545 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
546 | + index | ||
547 | + ].count; | ||
548 | + item.unitPrice = | ||
549 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
550 | + index | ||
551 | + ].unitPrice; | ||
552 | + item.price = | ||
553 | + orderStagesWithList[ind].orderStagesDeviceVoList[ | ||
554 | + index | ||
555 | + ].price; | ||
556 | + item.totalPrice = orderStagesWithList[ind].totalPrice; | ||
557 | + item.payWay = orderStagesWithList[ind].payWay; | ||
558 | + item.annex = orderStagesWithList[ind].annex; | ||
559 | + item.remark = orderStagesWithList[ind].remark; | ||
560 | + orderStagesList.push(item); | ||
561 | + } | ||
562 | + } | ||
563 | + } | ||
564 | + return { | ||
565 | + data: orderStagesList || [], | ||
566 | + }; | ||
567 | + } | ||
568 | + } | ||
569 | + }} | ||
570 | + editable={{ | ||
571 | + type: 'multiple', | ||
572 | + }} | ||
573 | + columnsState={{ | ||
574 | + persistenceKey: 'pro-table-singe-demos', | ||
575 | + persistenceType: 'localStorage', | ||
576 | + defaultValue: { | ||
577 | + option: { fixed: 'right', disable: true }, | ||
578 | + }, | ||
579 | + // onChange(value) { | ||
580 | + // console.log('value: ', value); | ||
581 | + // }, | ||
582 | + }} | ||
583 | + rowKey="dId" | ||
584 | + search={{ | ||
585 | + labelWidth: 'auto', | ||
586 | + }} | ||
587 | + options={{ | ||
588 | + setting: { | ||
589 | + listsHeight: 800, | ||
590 | + }, | ||
591 | + }} | ||
592 | + form={{ | ||
593 | + syncToUrl: (values, type) => { | ||
594 | + if (type === 'get') { | ||
595 | + return { | ||
596 | + ...values, | ||
597 | + created_at: [values.startTime, values.endTime], | ||
598 | + }; | ||
599 | + } | ||
600 | + return values; | ||
601 | + }, | ||
602 | + }} | ||
603 | + pagination={{ | ||
604 | + pageSize: 10, | ||
605 | + // onChange: (page) => console.log(page), | ||
606 | + }} | ||
607 | + dateFormatter="string" | ||
608 | + headerTitle={[]} | ||
609 | + toolBarRender={() => [ | ||
610 | + <> | ||
611 | + <AddModel toReload={reload}></AddModel> | ||
612 | + <UploadModel toReload={reload}></UploadModel> | ||
613 | + <Button | ||
614 | + type="primary" | ||
615 | + onClick={() => { | ||
616 | + toExport(); | ||
617 | + }} | ||
618 | + > | ||
619 | + <VerticalAlignTopOutlined /> | ||
620 | + 导出 | ||
621 | + </Button> | ||
622 | + </>, | ||
623 | + ]} | ||
624 | + /> | ||
625 | + ); | ||
626 | +}; |
src/pages/Instalment/components/upload/uploadApp.tsx
0 → 100644
1 | +import { InboxOutlined } from '@ant-design/icons'; | ||
2 | +import { Upload } from 'antd'; | ||
3 | +import React from 'react'; | ||
4 | + | ||
5 | +const App: React.FC = ({ uploadFile }) => { | ||
6 | + const { Dragger } = Upload; | ||
7 | + | ||
8 | + const props = { | ||
9 | + name: 'file', | ||
10 | + multiple: true, | ||
11 | + maxCount: 1, | ||
12 | + onChange: (info) => { | ||
13 | + uploadFile(info.file.originFileObj); | ||
14 | + }, | ||
15 | + }; | ||
16 | + | ||
17 | + return ( | ||
18 | + <Dragger {...props}> | ||
19 | + <p className="ant-upload-drag-icon"> | ||
20 | + <InboxOutlined /> | ||
21 | + </p> | ||
22 | + <p className="ant-upload-text"> | ||
23 | + Click or drag file to this area to upload | ||
24 | + </p> | ||
25 | + <p className="ant-upload-hint"> | ||
26 | + Support for a single or bulk upload. Strictly prohibited from uploading | ||
27 | + company data or other banned files. | ||
28 | + </p> | ||
29 | + </Dragger> | ||
30 | + ); | ||
31 | +}; | ||
32 | + | ||
33 | +export default App; |
src/pages/Instalment/components/upload/uploadModel.tsx
0 → 100644
1 | +import { postOrderErpOrderStagesImport } from '@/services/request'; | ||
2 | +import { VerticalAlignBottomOutlined } from '@ant-design/icons'; | ||
3 | +import { ModalForm } from '@ant-design/pro-components'; | ||
4 | +import { Button, Form, message } from 'antd'; | ||
5 | +import { RcFile } from 'antd/es/upload'; | ||
6 | +import { useState } from 'react'; | ||
7 | +import App from './uploadApp'; | ||
8 | + | ||
9 | +// const waitTime = (time: number = 100) => { | ||
10 | +// return new Promise((resolve) => { | ||
11 | +// setTimeout(() => { | ||
12 | +// resolve(true); | ||
13 | +// }, time); | ||
14 | +// }); | ||
15 | +// }; | ||
16 | + | ||
17 | +export default ({ toReload }) => { | ||
18 | + const [form] = Form.useForm<{ name: string; company: string }>(); | ||
19 | + const [uploadFile, setUploadFile] = useState({}); | ||
20 | + // function setUploadFileWay(value) { | ||
21 | + // setUploadFile(value) | ||
22 | + // } | ||
23 | + return ( | ||
24 | + <ModalForm<{ | ||
25 | + name: string; | ||
26 | + company: string; | ||
27 | + }> | ||
28 | + title="新建表单" | ||
29 | + trigger={ | ||
30 | + <Button type="primary"> | ||
31 | + <VerticalAlignBottomOutlined /> | ||
32 | + 导入 | ||
33 | + </Button> | ||
34 | + } | ||
35 | + form={form} | ||
36 | + autoFocusFirstInput | ||
37 | + modalProps={{ | ||
38 | + destroyOnClose: true, | ||
39 | + }} | ||
40 | + submitTimeout={2000} | ||
41 | + onFinish={async () => { | ||
42 | + const formData = new FormData(); | ||
43 | + formData.append('file', uploadFile as RcFile); | ||
44 | + const res = await postOrderErpOrderStagesImport({ | ||
45 | + data: formData, | ||
46 | + headers: { | ||
47 | + 'Content-Type': | ||
48 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | ||
49 | + }, | ||
50 | + }); | ||
51 | + if (res) { | ||
52 | + message.success('提交成功'); | ||
53 | + toReload(); | ||
54 | + return true; | ||
55 | + } | ||
56 | + }} | ||
57 | + > | ||
58 | + <App uploadFile={setUploadFile}></App> | ||
59 | + </ModalForm> | ||
60 | + ); | ||
61 | +}; |
src/pages/Instalment/index.tsx
0 → 100644
src/pages/Order/components/CheckModal.tsx
@@ -401,6 +401,9 @@ export default ({ | @@ -401,6 +401,9 @@ export default ({ | ||
401 | if (checkType(CHECK_TYPE.CONFIRM_REISSUE)) { | 401 | if (checkType(CHECK_TYPE.CONFIRM_REISSUE)) { |
402 | type = 'confirm_reissue'; | 402 | type = 'confirm_reissue'; |
403 | } | 403 | } |
404 | + if (checkType(CHECK_TYPE.CREDIT_AUDIT)) { | ||
405 | + type = 'credit_audit'; | ||
406 | + } | ||
404 | return type; | 407 | return type; |
405 | } | 408 | } |
406 | 409 |
src/pages/Order/components/ImportModal.tsx
@@ -26,7 +26,13 @@ export default ({ onClose }) => { | @@ -26,7 +26,13 @@ export default ({ onClose }) => { | ||
26 | }; | 26 | }; |
27 | const downloadTemplate = async () => { | 27 | const downloadTemplate = async () => { |
28 | exportLoading('正在下载模板...'); | 28 | exportLoading('正在下载模板...'); |
29 | - orderExport('/api/service/order/exportTemplate', {}, exportLoadingDestory); | 29 | + orderExport( |
30 | + '/api/service/order/exportTemplate', | ||
31 | + '订单.xlsx', | ||
32 | + 'post', | ||
33 | + {}, | ||
34 | + exportLoadingDestory, | ||
35 | + ); | ||
30 | }; | 36 | }; |
31 | 37 | ||
32 | const handleUpload = async () => { | 38 | const handleUpload = async () => { |
@@ -59,6 +65,8 @@ export default ({ onClose }) => { | @@ -59,6 +65,8 @@ export default ({ onClose }) => { | ||
59 | exportLoading('正在下载错误信息...'); | 65 | exportLoading('正在下载错误信息...'); |
60 | orderExport( | 66 | orderExport( |
61 | '/api/service/order/errorExcelInformation', | 67 | '/api/service/order/errorExcelInformation', |
68 | + '订单.xlsx', | ||
69 | + 'post', | ||
62 | formData, | 70 | formData, |
63 | exportLoadingDestory, | 71 | exportLoadingDestory, |
64 | ); | 72 | ); |
src/pages/Order/components/ModifiedDiffModal.tsx
1 | import { postServiceOrderModifiedDiff } from '@/services'; | 1 | import { postServiceOrderModifiedDiff } from '@/services'; |
2 | -import { | ||
3 | - enumValueToLabel, | ||
4 | - getAliYunOSSFileNameFromUrl, | ||
5 | - getUserInfo, | ||
6 | -} from '@/utils'; | 2 | +import { enumValueToLabel, getAliYunOSSFileNameFromUrl } from '@/utils'; |
7 | import { getReceivingCompanyOptions, isSupplier } from '@/utils/order'; | 3 | import { getReceivingCompanyOptions, isSupplier } from '@/utils/order'; |
8 | import { Button, Divider, Modal, Space, Table, TableProps } from 'antd'; | 4 | import { Button, Divider, Modal, Space, Table, TableProps } from 'antd'; |
9 | -import Base64 from 'base-64'; | ||
10 | import { useEffect, useState } from 'react'; | 5 | import { useEffect, useState } from 'react'; |
11 | import { | 6 | import { |
12 | PAYEE_OPTIONS, | 7 | PAYEE_OPTIONS, |
8 | + PAYMENT_CHANNEL_OPTIONS, | ||
9 | + PAYMENT_METHOD_OPTIONS, | ||
13 | PRODUCT_BELONG_DEPARTMENT_OPTIONS, | 10 | PRODUCT_BELONG_DEPARTMENT_OPTIONS, |
14 | SHIPPING_WAREHOUSE_OPTIONS, | 11 | SHIPPING_WAREHOUSE_OPTIONS, |
15 | } from '../constant'; | 12 | } from '../constant'; |
16 | import '../table.less'; | 13 | import '../table.less'; |
17 | 14 | ||
18 | export default ({ setVisible, subOrders, mainOrder, onClose }) => { | 15 | export default ({ setVisible, subOrders, mainOrder, onClose }) => { |
19 | - const userInfo = getUserInfo(); | ||
20 | let subIds = subOrders?.map((item: any) => { | 16 | let subIds = subOrders?.map((item: any) => { |
21 | return item.id; | 17 | return item.id; |
22 | }); | 18 | }); |
@@ -77,6 +73,12 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) => { | @@ -77,6 +73,12 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) => { | ||
77 | if (key === '发货仓库') { | 73 | if (key === '发货仓库') { |
78 | newText = enumValueToLabel(text, SHIPPING_WAREHOUSE_OPTIONS); | 74 | newText = enumValueToLabel(text, SHIPPING_WAREHOUSE_OPTIONS); |
79 | } | 75 | } |
76 | + if (key === '支付渠道') { | ||
77 | + newText = enumValueToLabel(text, PAYMENT_CHANNEL_OPTIONS); | ||
78 | + } | ||
79 | + if (key === '支付方式') { | ||
80 | + newText = enumValueToLabel(text, PAYMENT_METHOD_OPTIONS); | ||
81 | + } | ||
80 | if (key === '单价' || key === '合计') { | 82 | if (key === '单价' || key === '合计') { |
81 | newText = '¥' + newText; | 83 | newText = '¥' + newText; |
82 | } | 84 | } |
@@ -186,6 +188,8 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) => { | @@ -186,6 +188,8 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) => { | ||
186 | ['productBelongBusiness', '所属事业部'], | 188 | ['productBelongBusiness', '所属事业部'], |
187 | ['shippingWarehouse', '发货仓库'], | 189 | ['shippingWarehouse', '发货仓库'], |
188 | ['notes', '备注'], | 190 | ['notes', '备注'], |
191 | + ['paymentChannel', '支付渠道'], | ||
192 | + ['paymentMethod', '支付方式'], | ||
189 | ['listAnnex', '附件'], | 193 | ['listAnnex', '附件'], |
190 | ]; | 194 | ]; |
191 | for (let field of visibleFields) { | 195 | for (let field of visibleFields) { |
@@ -234,7 +238,6 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) => { | @@ -234,7 +238,6 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) => { | ||
234 | ['institutionContactName', '单位联系人'], | 238 | ['institutionContactName', '单位联系人'], |
235 | ['institution', '单位'], | 239 | ['institution', '单位'], |
236 | ['totalPayment', '支付总金额'], | 240 | ['totalPayment', '支付总金额'], |
237 | - ['paymentChannel', '支付渠道'], | ||
238 | ['notes', '备注'], | 241 | ['notes', '备注'], |
239 | ['bank', '开户银行'], | 242 | ['bank', '开户银行'], |
240 | ['bankAccountNumber', '银行账号'], | 243 | ['bankAccountNumber', '银行账号'], |
src/pages/Order/components/OrderDrawer.tsx
1 | import { RESPONSE_CODE } from '@/constants/enum'; | 1 | import { RESPONSE_CODE } from '@/constants/enum'; |
2 | import { | 2 | import { |
3 | postCanrdApiUserAddressList, | 3 | postCanrdApiUserAddressList, |
4 | - postCanrdApiUserList, | 4 | + postCanrdApiUserDetail, |
5 | + postCanrdApiUserNowMoneyCheck, | ||
5 | postKingdeeRepCustomerDetail, | 6 | postKingdeeRepCustomerDetail, |
6 | postKingdeeRepMaterial, | 7 | postKingdeeRepMaterial, |
7 | postKingdeeRepMaterialUnit, | 8 | postKingdeeRepMaterialUnit, |
8 | postKingdeeRepMeasureUnit, | 9 | postKingdeeRepMeasureUnit, |
10 | + postPrepaidPhoneAvailableList, | ||
9 | postServiceOrderAddOrder, | 11 | postServiceOrderAddOrder, |
10 | postServiceOrderAfterSalesQuerySnapshotOrder, | 12 | postServiceOrderAfterSalesQuerySnapshotOrder, |
11 | postServiceOrderApplyAfterSales, | 13 | postServiceOrderApplyAfterSales, |
12 | postServiceOrderApplyModify, | 14 | postServiceOrderApplyModify, |
13 | - postServiceOrderQuerySalesCode, | ||
14 | postServiceOrderUpdateOrder, | 15 | postServiceOrderUpdateOrder, |
15 | } from '@/services'; | 16 | } from '@/services'; |
16 | import { | 17 | import { |
@@ -22,6 +23,7 @@ import { | @@ -22,6 +23,7 @@ import { | ||
22 | } from '@/utils'; | 23 | } from '@/utils'; |
23 | import { getDefaultString } from '@/utils/StringUtil'; | 24 | import { getDefaultString } from '@/utils/StringUtil'; |
24 | import { getTeacherCustomFieldNumber } from '@/utils/kingdee'; | 25 | import { getTeacherCustomFieldNumber } from '@/utils/kingdee'; |
26 | +import { getSalesCodeOptions } from '@/utils/order'; | ||
25 | import { | 27 | import { |
26 | DrawerForm, | 28 | DrawerForm, |
27 | FormListActionType, | 29 | FormListActionType, |
@@ -106,6 +108,7 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -106,6 +108,7 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
106 | }, | 108 | }, |
107 | ]; | 109 | ]; |
108 | }>(); | 110 | }>(); |
111 | + const [accountOptions, setAccountOptions] = useState<any>([]); | ||
109 | 112 | ||
110 | let copyData = cloneDeep(data); | 113 | let copyData = cloneDeep(data); |
111 | 114 | ||
@@ -122,15 +125,8 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -122,15 +125,8 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
122 | /** | 125 | /** |
123 | * 获取销售代码枚举,在复制和编辑的时候判断是否为旧的代码 | 126 | * 获取销售代码枚举,在复制和编辑的时候判断是否为旧的代码 |
124 | */ | 127 | */ |
125 | - const getSalesCodeOptions = async () => { | ||
126 | - const res = await postServiceOrderQuerySalesCode(); | ||
127 | - let options = res.data?.map((item) => { | ||
128 | - return { | ||
129 | - label: item.userName, | ||
130 | - value: item.userName, | ||
131 | - number: item.number, | ||
132 | - }; | ||
133 | - }); | 128 | + const loadSalesCodeOptions = async () => { |
129 | + let options = await getSalesCodeOptions(); | ||
134 | setSalesCodeOptions(options); | 130 | setSalesCodeOptions(options); |
135 | 131 | ||
136 | if (optType('copy') || optType('edit')) { | 132 | if (optType('copy') || optType('edit')) { |
@@ -236,6 +232,38 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -236,6 +232,38 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
236 | // } | 232 | // } |
237 | 233 | ||
238 | /** | 234 | /** |
235 | + * 加载预存账号的options | ||
236 | + */ | ||
237 | + async function loadAccountOptions(phone: any) { | ||
238 | + let newAccountOptions = []; | ||
239 | + //预存账号id | ||
240 | + let uid = copyData.prepaidUid; | ||
241 | + let res = await postCanrdApiUserDetail({ data: { uid: uid } }); | ||
242 | + if (res && res.result === RESPONSE_CODE.SUCCESS && res.data !== null) { | ||
243 | + let uidDetail = res.data; | ||
244 | + uidDetail.value = uid; | ||
245 | + uidDetail.label = uidDetail.realName; | ||
246 | + newAccountOptions.push(uidDetail); | ||
247 | + } | ||
248 | + | ||
249 | + //查询当前手机号允许使用的预存账号 | ||
250 | + if (phone) { | ||
251 | + let res = await postPrepaidPhoneAvailableList({ data: { phone: phone } }); | ||
252 | + if (res && res.result === RESPONSE_CODE.SUCCESS) { | ||
253 | + let uidDetails = res.data; | ||
254 | + for (let detail of uidDetails) { | ||
255 | + detail.value = detail.uid; | ||
256 | + detail.label = detail.realName; | ||
257 | + newAccountOptions.push(detail); | ||
258 | + } | ||
259 | + } | ||
260 | + } | ||
261 | + | ||
262 | + console.log(newAccountOptions); | ||
263 | + setAccountOptions(newAccountOptions); | ||
264 | + } | ||
265 | + | ||
266 | + /** | ||
239 | * 构建回显数据 | 267 | * 构建回显数据 |
240 | */ | 268 | */ |
241 | function buildOrderData() { | 269 | function buildOrderData() { |
@@ -303,6 +331,8 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -303,6 +331,8 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
303 | if (!optType('after-sales-check')) { | 331 | if (!optType('after-sales-check')) { |
304 | // showKindeeInfo(); | 332 | // showKindeeInfo(); |
305 | } | 333 | } |
334 | + | ||
335 | + loadAccountOptions(form.getFieldValue('customerContactNumber')); | ||
306 | } | 336 | } |
307 | } | 337 | } |
308 | 338 | ||
@@ -524,6 +554,8 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -524,6 +554,8 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
524 | getDefaultString(option.detail), | 554 | getDefaultString(option.detail), |
525 | ); | 555 | ); |
526 | form.setFieldValue('customerNameString', option.realName); | 556 | form.setFieldValue('customerNameString', option.realName); |
557 | + | ||
558 | + loadAccountOptions(option.phone); | ||
527 | } | 559 | } |
528 | 560 | ||
529 | //erp收货地址:需要与客户联系人中的地址一样:姓名,手机号,地址 | 561 | //erp收货地址:需要与客户联系人中的地址一样:姓名,手机号,地址 |
@@ -586,6 +618,56 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -586,6 +618,56 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
586 | } | 618 | } |
587 | 619 | ||
588 | /** | 620 | /** |
621 | + * 检查用户额度 | ||
622 | + * @param option | ||
623 | + */ | ||
624 | + const checkAccountMoney = async (uid: any, subPrice: any) => { | ||
625 | + let res = await postCanrdApiUserNowMoneyCheck({ | ||
626 | + data: { uid: uid, subPrice: subPrice }, | ||
627 | + }); | ||
628 | + if (res && res.result === RESPONSE_CODE.SUCCESS && res.data) { | ||
629 | + let data = res.data; | ||
630 | + let isCredit = data.isCredit; | ||
631 | + if (isCredit) { | ||
632 | + return true; | ||
633 | + } | ||
634 | + | ||
635 | + message.error( | ||
636 | + '用户余额不足,当前预减的金额为:' + | ||
637 | + data.subPrice + | ||
638 | + ',当前账号余额为:' + | ||
639 | + data.nowMoney + | ||
640 | + ',当前账号可赊账额度为:' + | ||
641 | + data.creditLimit, | ||
642 | + ); | ||
643 | + return false; | ||
644 | + } | ||
645 | + | ||
646 | + return false; | ||
647 | + }; | ||
648 | + | ||
649 | + /** | ||
650 | + * 总金额改变触发事件 | ||
651 | + * 如果是预存单,需要检查余额 | ||
652 | + * @param value | ||
653 | + */ | ||
654 | + const totalPaymentChange = (value: any) => { | ||
655 | + let paymentMethod = form.getFieldValue('paymentMethod'); | ||
656 | + let prepaidUid = form.getFieldValue('prepaidUid'); | ||
657 | + if ( | ||
658 | + value && | ||
659 | + paymentMethod && | ||
660 | + paymentMethod === 'WITHHOLDING_ADVANCE_DEPOSIT' && | ||
661 | + prepaidUid | ||
662 | + ) { | ||
663 | + let valid = checkAccountMoney(prepaidUid, value); | ||
664 | + if (!valid) { | ||
665 | + form.setFieldValue('prepaidUid', undefined); | ||
666 | + } | ||
667 | + } | ||
668 | + }; | ||
669 | + | ||
670 | + /** | ||
589 | * 检查客户是否可以编辑 | 671 | * 检查客户是否可以编辑 |
590 | * @returns | 672 | * @returns |
591 | */ | 673 | */ |
@@ -658,6 +740,19 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -658,6 +740,19 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
658 | } | 740 | } |
659 | } | 741 | } |
660 | 742 | ||
743 | + const validateContactNumber = (_: any, value: any) => { | ||
744 | + console.log(value); | ||
745 | + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; | ||
746 | + const phoneRegex = /^\d{1,11}$/; | ||
747 | + | ||
748 | + if (emailRegex.test(value) || phoneRegex.test(value)) { | ||
749 | + return Promise.resolve(); | ||
750 | + } | ||
751 | + return Promise.reject( | ||
752 | + new Error('联系方式必须是邮箱或手机号格式(不能包含空格等特殊符号)'), | ||
753 | + ); | ||
754 | + }; | ||
755 | + | ||
661 | /** | 756 | /** |
662 | * 刪除草稿数据 | 757 | * 刪除草稿数据 |
663 | */ | 758 | */ |
@@ -667,7 +762,7 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -667,7 +762,7 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
667 | 762 | ||
668 | useEffect(() => { | 763 | useEffect(() => { |
669 | checkHasLocalData(); | 764 | checkHasLocalData(); |
670 | - getSalesCodeOptions(); | 765 | + loadSalesCodeOptions(); |
671 | if (optType('after-sales-check')) { | 766 | if (optType('after-sales-check')) { |
672 | getOldOrderData(data.id); | 767 | getOldOrderData(data.id); |
673 | } else { | 768 | } else { |
@@ -949,7 +1044,6 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -949,7 +1044,6 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
949 | } | 1044 | } |
950 | 1045 | ||
951 | let title = ''; | 1046 | let title = ''; |
952 | - let spanText = ''; | ||
953 | let realName = item.realName; | 1047 | let realName = item.realName; |
954 | let phone = item.phone; | 1048 | let phone = item.phone; |
955 | let province = item.province; | 1049 | let province = item.province; |
@@ -959,31 +1053,41 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -959,31 +1053,41 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
959 | let institution = item.institution; | 1053 | let institution = item.institution; |
960 | let institutionContactName = item.institutionContactName; | 1054 | let institutionContactName = item.institutionContactName; |
961 | 1055 | ||
962 | - title = | ||
963 | - getDefaultString(realName) + | ||
964 | - '|' + | ||
965 | - getDefaultString(phone) + | ||
966 | - '|' + | ||
967 | - getDefaultString(institution) + | ||
968 | - '|' + | ||
969 | - getDefaultString(institutionContactName) + | ||
970 | - '|' + | 1056 | + let address = |
971 | getDefaultString(province) + | 1057 | getDefaultString(province) + |
972 | getDefaultString(city) + | 1058 | getDefaultString(city) + |
973 | getDefaultString(district) + | 1059 | getDefaultString(district) + |
974 | getDefaultString(detail); | 1060 | getDefaultString(detail); |
975 | 1061 | ||
976 | - spanText = | 1062 | + title = |
977 | getDefaultString(realName) + | 1063 | getDefaultString(realName) + |
978 | '|' + | 1064 | '|' + |
979 | getDefaultString(phone) + | 1065 | getDefaultString(phone) + |
980 | '|' + | 1066 | '|' + |
981 | getDefaultString(institution) + | 1067 | getDefaultString(institution) + |
982 | '|' + | 1068 | '|' + |
983 | - getDefaultString(institutionContactName); | 1069 | + getDefaultString(institutionContactName) + |
1070 | + '|' + | ||
1071 | + address; | ||
1072 | + | ||
984 | return ( | 1073 | return ( |
985 | - <div title={title}> | ||
986 | - <span style={{ color: '#333333' }}>{spanText}</span> | 1074 | + <div title={title} className="whitespace-normal"> |
1075 | + <span style={{ color: '#333333' }}> | ||
1076 | + {getDefaultString(realName)} | ||
1077 | + </span> | ||
1078 | + | | ||
1079 | + <span className="text-sky-600"> | ||
1080 | + {getDefaultString(phone)} | ||
1081 | + </span> | ||
1082 | + | | ||
1083 | + <span style={{ color: '#333333' }}> | ||
1084 | + {getDefaultString(institution)} | ||
1085 | + </span> | ||
1086 | + | | ||
1087 | + <span style={{ color: '#333333' }}> | ||
1088 | + {getDefaultString(institutionContactName)} | ||
1089 | + </span> | ||
1090 | + |<span className="text-orange-400">{address}</span> | ||
987 | </div> | 1091 | </div> |
988 | ); | 1092 | ); |
989 | }, | 1093 | }, |
@@ -1047,7 +1151,15 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -1047,7 +1151,15 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
1047 | name="customerContactNumber" | 1151 | name="customerContactNumber" |
1048 | label="联系方式" | 1152 | label="联系方式" |
1049 | placeholder="请输入联系方式" | 1153 | placeholder="请输入联系方式" |
1050 | - rules={[{ required: true, message: '联系方式必填' }]} | 1154 | + fieldProps={{ |
1155 | + onBlur: (v) => { | ||
1156 | + loadAccountOptions(v.target.value); | ||
1157 | + }, | ||
1158 | + }} | ||
1159 | + rules={[ | ||
1160 | + { required: true, message: '联系方式必填' }, | ||
1161 | + { validator: validateContactNumber }, | ||
1162 | + ]} | ||
1051 | /> | 1163 | /> |
1052 | <ProFormText | 1164 | <ProFormText |
1053 | width="lg" | 1165 | width="lg" |
@@ -1081,18 +1193,23 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -1081,18 +1193,23 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
1081 | label="支付总额(¥)" | 1193 | label="支付总额(¥)" |
1082 | rules={[ | 1194 | rules={[ |
1083 | { required: true, message: '支付总额必填' }, | 1195 | { required: true, message: '支付总额必填' }, |
1084 | - // { | ||
1085 | - // validator: (_, value) => { | ||
1086 | - // if (value <= 0) { | ||
1087 | - // return Promise.reject( | ||
1088 | - // new Error( | ||
1089 | - // '支付总额必须大于0 (扣预存的订单现在也必须填写实际金额)', | ||
1090 | - // ), | ||
1091 | - // ); | ||
1092 | - // } | ||
1093 | - // return Promise.resolve(); | ||
1094 | - // }, | ||
1095 | - // }, | 1196 | + { |
1197 | + validator: (_, value) => { | ||
1198 | + let paymentMethod = form.getFieldValue('paymentMethod'); | ||
1199 | + if ( | ||
1200 | + value <= 0 && | ||
1201 | + paymentMethod && | ||
1202 | + paymentMethod === 'WITHHOLDING_ADVANCE_DEPOSIT' | ||
1203 | + ) { | ||
1204 | + return Promise.reject( | ||
1205 | + new Error( | ||
1206 | + '支付总额必须大于0 (扣预存的订单现在也必须填写实际金额)', | ||
1207 | + ), | ||
1208 | + ); | ||
1209 | + } | ||
1210 | + return Promise.resolve(); | ||
1211 | + }, | ||
1212 | + }, | ||
1096 | ]} | 1213 | ]} |
1097 | tooltip="点击计算,合计所有子订单金额" | 1214 | tooltip="点击计算,合计所有子订单金额" |
1098 | fieldProps={{ | 1215 | fieldProps={{ |
@@ -1106,6 +1223,9 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -1106,6 +1223,9 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
1106 | 计算 | 1223 | 计算 |
1107 | </Button> | 1224 | </Button> |
1108 | ), | 1225 | ), |
1226 | + onChange: (value: any) => { | ||
1227 | + totalPaymentChange(value); | ||
1228 | + }, | ||
1109 | }} | 1229 | }} |
1110 | disabled={optType('after-sales-check')} | 1230 | disabled={optType('after-sales-check')} |
1111 | /> | 1231 | /> |
@@ -1141,8 +1261,15 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -1141,8 +1261,15 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
1141 | hidden={paymentMethod !== 'WITHHOLDING_ADVANCE_DEPOSIT'} | 1261 | hidden={paymentMethod !== 'WITHHOLDING_ADVANCE_DEPOSIT'} |
1142 | showSearch | 1262 | showSearch |
1143 | label="预存账号" | 1263 | label="预存账号" |
1144 | - onChange={(option: any) => { | ||
1145 | - form.setFieldValue('prepaidAmount', option.nowMoney); | 1264 | + onChange={(value: any) => { |
1265 | + //检查用户额度 | ||
1266 | + let valid = checkAccountMoney( | ||
1267 | + value, | ||
1268 | + form.getFieldValue('totalPayment'), | ||
1269 | + ); | ||
1270 | + if (!valid) { | ||
1271 | + form.setFieldValue('prepaidUid', undefined); | ||
1272 | + } | ||
1146 | }} | 1273 | }} |
1147 | placeholder="请选择预存账号" | 1274 | placeholder="请选择预存账号" |
1148 | rules={[ | 1275 | rules={[ |
@@ -1173,21 +1300,22 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -1173,21 +1300,22 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
1173 | }, | 1300 | }, |
1174 | }} | 1301 | }} |
1175 | debounceTime={1000} | 1302 | debounceTime={1000} |
1176 | - request={async (value, {}) => { | ||
1177 | - const keywords = value.keyWords; | ||
1178 | - const res = await postCanrdApiUserList({ | ||
1179 | - data: { keywords: keywords, pageSize: 1000000 }, | ||
1180 | - }); | ||
1181 | - let options = res?.data?.data?.map((c: any) => { | ||
1182 | - return { | ||
1183 | - ...c, | ||
1184 | - label: c.realName, | ||
1185 | - value: c.uid, | ||
1186 | - key: c.uid, | ||
1187 | - }; | ||
1188 | - }); | ||
1189 | - return options; | ||
1190 | - }} | 1303 | + // request={async (value, {}) => { |
1304 | + // const keywords = value.keyWords; | ||
1305 | + // const res = await postCanrdApiUserList({ | ||
1306 | + // data: { keywords: keywords, pageSize: 50 }, | ||
1307 | + // }); | ||
1308 | + // let options = res?.data?.data?.map((c: any) => { | ||
1309 | + // return { | ||
1310 | + // ...c, | ||
1311 | + // label: c.realName, | ||
1312 | + // value: c.uid, | ||
1313 | + // key: c.uid, | ||
1314 | + // }; | ||
1315 | + // }); | ||
1316 | + // return options; | ||
1317 | + // }} | ||
1318 | + options={accountOptions} | ||
1191 | /> | 1319 | /> |
1192 | <ProFormSelect | 1320 | <ProFormSelect |
1193 | placeholder="选择是否需要开票" | 1321 | placeholder="选择是否需要开票" |
@@ -1308,8 +1436,6 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -1308,8 +1436,6 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
1308 | (sum, item) => FloatAdd(sum, item.subOrderPayment), | 1436 | (sum, item) => FloatAdd(sum, item.subOrderPayment), |
1309 | 0, | 1437 | 0, |
1310 | ); | 1438 | ); |
1311 | - console.log(reduce); | ||
1312 | - console.log(totalPayment); | ||
1313 | if (reduce === totalPayment || value) { | 1439 | if (reduce === totalPayment || value) { |
1314 | return Promise.resolve(); | 1440 | return Promise.resolve(); |
1315 | } | 1441 | } |
src/pages/Order/constant.ts
@@ -108,6 +108,7 @@ export const CHECK_TYPE = { | @@ -108,6 +108,7 @@ export const CHECK_TYPE = { | ||
108 | PAYMENT_RECEIPTS_AUDIT: 'PAYMENT_RECEIPTS_AUDIT', | 108 | PAYMENT_RECEIPTS_AUDIT: 'PAYMENT_RECEIPTS_AUDIT', |
109 | CONFIRM_REISSUE: 'CONFIRM_REISSUE', | 109 | CONFIRM_REISSUE: 'CONFIRM_REISSUE', |
110 | PREPAID_AUDIT: 'PREPAID_AUDIT', | 110 | PREPAID_AUDIT: 'PREPAID_AUDIT', |
111 | + CREDIT_AUDIT: 'CREDIT_AUDIT', | ||
111 | }; | 112 | }; |
112 | 113 | ||
113 | /** | 114 | /** |
@@ -192,6 +193,7 @@ export const ORDER_STATUS_OPTIONS = { | @@ -192,6 +193,7 @@ export const ORDER_STATUS_OPTIONS = { | ||
192 | AFTER_SALES_FAILURE: '售后失败', | 193 | AFTER_SALES_FAILURE: '售后失败', |
193 | NO_NEED_SEND: '无需发货', | 194 | NO_NEED_SEND: '无需发货', |
194 | PROCURE_CONVERT_WAREHOUSE_KEEPER: '采购转仓库', | 195 | PROCURE_CONVERT_WAREHOUSE_KEEPER: '采购转仓库', |
196 | + CREDIT_CONFIRM: '赊账待审核', | ||
195 | }; | 197 | }; |
196 | 198 | ||
197 | export const MODIFIED_AUDIT_STATUS_OPTIONS = { | 199 | export const MODIFIED_AUDIT_STATUS_OPTIONS = { |
@@ -227,8 +229,10 @@ export const AFTER_INVOICING_STATUS = { | @@ -227,8 +229,10 @@ export const AFTER_INVOICING_STATUS = { | ||
227 | NOT_YET_INVOICED: '尚未开票', | 229 | NOT_YET_INVOICED: '尚未开票', |
228 | APPLY_FOR_INVOICING: '申请开票', | 230 | APPLY_FOR_INVOICING: '申请开票', |
229 | URGENT_INVOICE_AUDITING: '加急待审核', | 231 | URGENT_INVOICE_AUDITING: '加急待审核', |
232 | + URGENT_INVOICE_AUDIT_NOTPASS: '加急审核失败', | ||
230 | PARTIAL_INVOICING: '部分开票', | 233 | PARTIAL_INVOICING: '部分开票', |
231 | COMPLETE_INVOICING: '完全开票', | 234 | COMPLETE_INVOICING: '完全开票', |
235 | + REISSUE: '重新开票', | ||
232 | }; | 236 | }; |
233 | 237 | ||
234 | export const TAGS_COLOR = new Map<string, string>([ | 238 | export const TAGS_COLOR = new Map<string, string>([ |
@@ -274,6 +278,9 @@ export const TAGS_COLOR = new Map<string, string>([ | @@ -274,6 +278,9 @@ export const TAGS_COLOR = new Map<string, string>([ | ||
274 | ['AUDIT_NOTPASS', 'error'], | 278 | ['AUDIT_NOTPASS', 'error'], |
275 | ['WAIT_CONFIRM_DELIVER_AFTER_INVOICE', 'processing'], | 279 | ['WAIT_CONFIRM_DELIVER_AFTER_INVOICE', 'processing'], |
276 | ['SALES_CONFIRM', 'warning'], | 280 | ['SALES_CONFIRM', 'warning'], |
281 | + ['URGENT_INVOICE_AUDIT_NOTPASS', 'red'], | ||
282 | + ['REISSUE', 'processing'], | ||
283 | + ['CREDIT_CONFIRM', 'warning'], | ||
277 | ]); | 284 | ]); |
278 | export const SALES_CODE_OPTIONS = [ | 285 | export const SALES_CODE_OPTIONS = [ |
279 | { label: 'D-Linda', value: 'D-Linda' }, | 286 | { label: 'D-Linda', value: 'D-Linda' }, |
@@ -402,6 +409,7 @@ export const HISTORY_OPT_TYPE = new Map<string, string>([ | @@ -402,6 +409,7 @@ export const HISTORY_OPT_TYPE = new Map<string, string>([ | ||
402 | ['OUTSIDE_SYSTEM_PUSH', '外部系统推送了本订单'], | 409 | ['OUTSIDE_SYSTEM_PUSH', '外部系统推送了本订单'], |
403 | ['cancelSendOrder', '取消发货'], | 410 | ['cancelSendOrder', '取消发货'], |
404 | ['salesConfirm', '商城订单销售确认'], | 411 | ['salesConfirm', '商城订单销售确认'], |
412 | + ['credit_audit', '赊账审核'], | ||
405 | ]); | 413 | ]); |
406 | 414 | ||
407 | export const MAIN_ORDER_COLUMNS = [ | 415 | export const MAIN_ORDER_COLUMNS = [ |
src/pages/Order/index.tsx
@@ -1317,6 +1317,23 @@ const OrderPage = () => { | @@ -1317,6 +1317,23 @@ const OrderPage = () => { | ||
1317 | '' | 1317 | '' |
1318 | )} | 1318 | )} |
1319 | 1319 | ||
1320 | + {optRecord.subPath?.includes('creditAudit') ? ( | ||
1321 | + <Button | ||
1322 | + className="p-0" | ||
1323 | + type="link" | ||
1324 | + onClick={() => { | ||
1325 | + setCurrentMainId(record.id); | ||
1326 | + setCurretnOptSubId(optRecord.id); | ||
1327 | + setCheckVisible(true); | ||
1328 | + setOrderCheckType(CHECK_TYPE.CREDIT_AUDIT); | ||
1329 | + }} | ||
1330 | + > | ||
1331 | + 赊账审核 | ||
1332 | + </Button> | ||
1333 | + ) : ( | ||
1334 | + '' | ||
1335 | + )} | ||
1336 | + | ||
1320 | {optRecord.subPath?.includes('auditPaymentReceipt') ? ( | 1337 | {optRecord.subPath?.includes('auditPaymentReceipt') ? ( |
1321 | <Button | 1338 | <Button |
1322 | className="p-0" | 1339 | className="p-0" |
@@ -1928,7 +1945,7 @@ const OrderPage = () => { | @@ -1928,7 +1945,7 @@ const OrderPage = () => { | ||
1928 | 1945 | ||
1929 | <Flex title={optRecord.notes}> | 1946 | <Flex title={optRecord.notes}> |
1930 | <div | 1947 | <div |
1931 | - className="overflow-hidden whitespace-normal overflow-ellipsis hover:cursor-pointer" | 1948 | + className="max-w-[1100px] overflow-hidden whitespace-normal overflow-ellipsis hover:cursor-pointer" |
1932 | onClick={() => { | 1949 | onClick={() => { |
1933 | copyToClipboard(optRecord.notes); | 1950 | copyToClipboard(optRecord.notes); |
1934 | message.info('备注复制成功:' + optRecord.notes); | 1951 | message.info('备注复制成功:' + optRecord.notes); |
@@ -2850,6 +2867,38 @@ const OrderPage = () => { | @@ -2850,6 +2867,38 @@ const OrderPage = () => { | ||
2850 | '' | 2867 | '' |
2851 | )} | 2868 | )} |
2852 | 2869 | ||
2870 | + {record.mainPath?.includes('creditAudit') ? ( | ||
2871 | + <Button | ||
2872 | + className="p-0" | ||
2873 | + type="link" | ||
2874 | + onClick={() => { | ||
2875 | + let selectedSubOrders = subOrderSelectedMap.get( | ||
2876 | + record.id, | ||
2877 | + ); | ||
2878 | + setSelectedRows(selectedSubOrders); | ||
2879 | + if (selectedSubOrders === undefined) { | ||
2880 | + selectedSubOrders = record.subOrderInformationLists; | ||
2881 | + } | ||
2882 | + for (let i = 0; i < selectedSubOrders.length; i++) { | ||
2883 | + if ( | ||
2884 | + selectedSubOrders[i].orderStatus !== | ||
2885 | + 'CREDIT_CONFIRM' | ||
2886 | + ) { | ||
2887 | + message.error('请选择[赊账待审核]的子订单进行审核'); | ||
2888 | + return; | ||
2889 | + } | ||
2890 | + } | ||
2891 | + createOptObject(null, record.id); | ||
2892 | + setCheckVisible(true); | ||
2893 | + setOrderCheckType(CHECK_TYPE.CREDIT_AUDIT); | ||
2894 | + }} | ||
2895 | + > | ||
2896 | + 赊账审核 | ||
2897 | + </Button> | ||
2898 | + ) : ( | ||
2899 | + '' | ||
2900 | + )} | ||
2901 | + | ||
2853 | {record.mainPath?.includes('editProductionTime') ? ( | 2902 | {record.mainPath?.includes('editProductionTime') ? ( |
2854 | <Button | 2903 | <Button |
2855 | className="p-0" | 2904 | className="p-0" |
@@ -3154,10 +3203,11 @@ const OrderPage = () => { | @@ -3154,10 +3203,11 @@ const OrderPage = () => { | ||
3154 | if ( | 3203 | if ( |
3155 | orderStatus !== 'UNAUDITED' && | 3204 | orderStatus !== 'UNAUDITED' && |
3156 | orderStatus !== 'AUDIT_FAILED' && | 3205 | orderStatus !== 'AUDIT_FAILED' && |
3157 | - orderStatus !== 'LEADER_PROCESS' | 3206 | + orderStatus !== 'LEADER_PROCESS' && |
3207 | + orderStatus !== 'SALES_CONFIRM' | ||
3158 | ) { | 3208 | ) { |
3159 | message.error( | 3209 | message.error( |
3160 | - '请选择未审核或者审核失败的订单进行编辑', | 3210 | + '请选择【未审核、审核失败、销售待确认】的订单进行编辑', |
3161 | ); | 3211 | ); |
3162 | return; | 3212 | return; |
3163 | } | 3213 | } |
@@ -3861,11 +3911,11 @@ const OrderPage = () => { | @@ -3861,11 +3911,11 @@ const OrderPage = () => { | ||
3861 | label: '导出已选中订单', | 3911 | label: '导出已选中订单', |
3862 | key: '1', | 3912 | key: '1', |
3863 | onClick: async () => { | 3913 | onClick: async () => { |
3864 | - if (selectedMainOrderKeys.length === 0) { | 3914 | + if (mainOrderSelectedMap.size === 0) { |
3865 | message.error('请选择订单'); | 3915 | message.error('请选择订单'); |
3866 | return; | 3916 | return; |
3867 | } | 3917 | } |
3868 | - let body = { flag: 30, id: selectedMainOrderKeys }; | 3918 | + let body = { flag: 30, id: Array.from(mainOrderSelectedMap.keys()) }; |
3869 | exportLoading(); | 3919 | exportLoading(); |
3870 | orderExport('/api/service/order/export', body, exportLoadingDestory); | 3920 | orderExport('/api/service/order/export', body, exportLoadingDestory); |
3871 | }, | 3921 | }, |
src/pages/OrderPrint/index.css
0 → 100644
1 | +.font0 { | ||
2 | + color: windowtext; | ||
3 | + font-size: 12pt; | ||
4 | + font-weight: 400; | ||
5 | + font-style: normal; | ||
6 | + text-decoration: none; | ||
7 | + font-family: '宋体'; | ||
8 | +} | ||
9 | + | ||
10 | +.font1 { | ||
11 | + color: windowtext; | ||
12 | + font-size: 16pt; | ||
13 | + font-weight: 400; | ||
14 | + font-style: normal; | ||
15 | + text-decoration: none; | ||
16 | + font-family: '宋体'; | ||
17 | +} | ||
18 | + | ||
19 | +.font2 { | ||
20 | + color: windowtext; | ||
21 | + font-size: 10pt; | ||
22 | + font-weight: 400; | ||
23 | + font-style: normal; | ||
24 | + text-decoration: none; | ||
25 | + font-family: '宋体'; | ||
26 | +} | ||
27 | + | ||
28 | +.font3 { | ||
29 | + color: windowtext; | ||
30 | + font-size: 14pt; | ||
31 | + font-weight: 400; | ||
32 | + font-style: normal; | ||
33 | + text-decoration: none; | ||
34 | + font-family: '宋体'; | ||
35 | +} | ||
36 | + | ||
37 | +.font4 { | ||
38 | + color: windowtext; | ||
39 | + font-size: 8pt; | ||
40 | + font-weight: 400; | ||
41 | + font-style: normal; | ||
42 | + text-decoration: none; | ||
43 | + font-family: '宋体'; | ||
44 | +} | ||
45 | + | ||
46 | +.font5 { | ||
47 | + color: #00f; | ||
48 | + font-size: 11pt; | ||
49 | + font-weight: 400; | ||
50 | + font-style: normal; | ||
51 | + text-decoration: underline; | ||
52 | + font-family: '宋体'; | ||
53 | +} | ||
54 | + | ||
55 | +.font6 { | ||
56 | + color: #800080; | ||
57 | + font-size: 11pt; | ||
58 | + font-weight: 400; | ||
59 | + font-style: normal; | ||
60 | + text-decoration: underline; | ||
61 | + font-family: '宋体'; | ||
62 | +} | ||
63 | + | ||
64 | +.font7 { | ||
65 | + color: #000; | ||
66 | + font-size: 11pt; | ||
67 | + font-weight: 400; | ||
68 | + font-style: normal; | ||
69 | + text-decoration: none; | ||
70 | + font-family: '宋体'; | ||
71 | +} | ||
72 | + | ||
73 | +.font8 { | ||
74 | + color: #f00; | ||
75 | + font-size: 11pt; | ||
76 | + font-weight: 400; | ||
77 | + font-style: normal; | ||
78 | + text-decoration: none; | ||
79 | + font-family: '宋体'; | ||
80 | +} | ||
81 | + | ||
82 | +.font9 { | ||
83 | + color: #44546a; | ||
84 | + font-size: 18pt; | ||
85 | + font-weight: 700; | ||
86 | + font-style: normal; | ||
87 | + text-decoration: none; | ||
88 | + font-family: '宋体'; | ||
89 | +} | ||
90 | + | ||
91 | +.font10 { | ||
92 | + color: #7f7f7f; | ||
93 | + font-size: 11pt; | ||
94 | + font-weight: 400; | ||
95 | + font-style: italic; | ||
96 | + text-decoration: none; | ||
97 | + font-family: '宋体'; | ||
98 | +} | ||
99 | + | ||
100 | +.font11 { | ||
101 | + color: #44546a; | ||
102 | + font-size: 15pt; | ||
103 | + font-weight: 700; | ||
104 | + font-style: normal; | ||
105 | + text-decoration: none; | ||
106 | + font-family: '宋体'; | ||
107 | +} | ||
108 | + | ||
109 | +.font12 { | ||
110 | + color: #44546a; | ||
111 | + font-size: 13pt; | ||
112 | + font-weight: 700; | ||
113 | + font-style: normal; | ||
114 | + text-decoration: none; | ||
115 | + font-family: '宋体'; | ||
116 | +} | ||
117 | + | ||
118 | +.font13 { | ||
119 | + color: #44546a; | ||
120 | + font-size: 11pt; | ||
121 | + font-weight: 700; | ||
122 | + font-style: normal; | ||
123 | + text-decoration: none; | ||
124 | + font-family: '宋体'; | ||
125 | +} | ||
126 | + | ||
127 | +.font14 { | ||
128 | + color: #3f3f76; | ||
129 | + font-size: 11pt; | ||
130 | + font-weight: 400; | ||
131 | + font-style: normal; | ||
132 | + text-decoration: none; | ||
133 | + font-family: '宋体'; | ||
134 | +} | ||
135 | + | ||
136 | +.font15 { | ||
137 | + color: #3f3f3f; | ||
138 | + font-size: 11pt; | ||
139 | + font-weight: 700; | ||
140 | + font-style: normal; | ||
141 | + text-decoration: none; | ||
142 | + font-family: '宋体'; | ||
143 | +} | ||
144 | + | ||
145 | +.font16 { | ||
146 | + color: #fa7d00; | ||
147 | + font-size: 11pt; | ||
148 | + font-weight: 700; | ||
149 | + font-style: normal; | ||
150 | + text-decoration: none; | ||
151 | + font-family: '宋体'; | ||
152 | +} | ||
153 | + | ||
154 | +.font17 { | ||
155 | + color: #fff; | ||
156 | + font-size: 11pt; | ||
157 | + font-weight: 700; | ||
158 | + font-style: normal; | ||
159 | + text-decoration: none; | ||
160 | + font-family: '宋体'; | ||
161 | +} | ||
162 | + | ||
163 | +.font18 { | ||
164 | + color: #fa7d00; | ||
165 | + font-size: 11pt; | ||
166 | + font-weight: 400; | ||
167 | + font-style: normal; | ||
168 | + text-decoration: none; | ||
169 | + font-family: '宋体'; | ||
170 | +} | ||
171 | + | ||
172 | +.font19 { | ||
173 | + color: #000; | ||
174 | + font-size: 11pt; | ||
175 | + font-weight: 700; | ||
176 | + font-style: normal; | ||
177 | + text-decoration: none; | ||
178 | + font-family: '宋体'; | ||
179 | +} | ||
180 | + | ||
181 | +.font20 { | ||
182 | + color: #006100; | ||
183 | + font-size: 11pt; | ||
184 | + font-weight: 400; | ||
185 | + font-style: normal; | ||
186 | + text-decoration: none; | ||
187 | + font-family: '宋体'; | ||
188 | +} | ||
189 | + | ||
190 | +.font21 { | ||
191 | + color: #9c0006; | ||
192 | + font-size: 11pt; | ||
193 | + font-weight: 400; | ||
194 | + font-style: normal; | ||
195 | + text-decoration: none; | ||
196 | + font-family: '宋体'; | ||
197 | +} | ||
198 | + | ||
199 | +.font22 { | ||
200 | + color: #9c6500; | ||
201 | + font-size: 11pt; | ||
202 | + font-weight: 400; | ||
203 | + font-style: normal; | ||
204 | + text-decoration: none; | ||
205 | + font-family: '宋体'; | ||
206 | +} | ||
207 | + | ||
208 | +.font23 { | ||
209 | + color: #fff; | ||
210 | + font-size: 11pt; | ||
211 | + font-weight: 400; | ||
212 | + font-style: normal; | ||
213 | + text-decoration: none; | ||
214 | + font-family: '宋体'; | ||
215 | +} | ||
216 | + | ||
217 | +.font24 { | ||
218 | + color: #000; | ||
219 | + font-size: 11pt; | ||
220 | + font-weight: 400; | ||
221 | + font-style: normal; | ||
222 | + text-decoration: none; | ||
223 | + font-family: '宋体'; | ||
224 | +} | ||
225 | + | ||
226 | +.style0 { | ||
227 | + text-align: general; | ||
228 | + vertical-align: middle; | ||
229 | + white-space: nowrap; | ||
230 | + color: windowtext; | ||
231 | + font-size: 12pt; | ||
232 | + font-weight: 400; | ||
233 | + font-style: normal; | ||
234 | + text-decoration: none; | ||
235 | + font-family: '宋体'; | ||
236 | + border: none; | ||
237 | +} | ||
238 | + | ||
239 | +.style21 { | ||
240 | + color: #00f; | ||
241 | + font-size: 11pt; | ||
242 | + font-weight: 400; | ||
243 | + font-style: normal; | ||
244 | + text-decoration: underline; | ||
245 | + font-family: '宋体'; | ||
246 | +} | ||
247 | + | ||
248 | +.style22 { | ||
249 | + color: #800080; | ||
250 | + font-size: 11pt; | ||
251 | + font-weight: 400; | ||
252 | + font-style: normal; | ||
253 | + text-decoration: underline; | ||
254 | + font-family: '宋体'; | ||
255 | +} | ||
256 | + | ||
257 | +.style23 { | ||
258 | + background: #ffc; | ||
259 | + border: 0.5pt solid #b2b2b2; | ||
260 | +} | ||
261 | + | ||
262 | +.style24 { | ||
263 | + color: #f00; | ||
264 | + font-size: 11pt; | ||
265 | + font-weight: 400; | ||
266 | + font-style: normal; | ||
267 | + text-decoration: none; | ||
268 | + font-family: '宋体'; | ||
269 | +} | ||
270 | + | ||
271 | +.style25 { | ||
272 | + color: #44546a; | ||
273 | + font-size: 18pt; | ||
274 | + font-weight: 700; | ||
275 | + font-style: normal; | ||
276 | + text-decoration: none; | ||
277 | + font-family: '宋体'; | ||
278 | +} | ||
279 | + | ||
280 | +.style26 { | ||
281 | + color: #7f7f7f; | ||
282 | + font-size: 11pt; | ||
283 | + font-weight: 400; | ||
284 | + font-style: italic; | ||
285 | + text-decoration: none; | ||
286 | + font-family: '宋体'; | ||
287 | +} | ||
288 | + | ||
289 | +.style27 { | ||
290 | + color: #44546a; | ||
291 | + font-size: 15pt; | ||
292 | + font-weight: 700; | ||
293 | + font-style: normal; | ||
294 | + text-decoration: none; | ||
295 | + font-family: '宋体'; | ||
296 | + border-bottom: 1pt solid #5b9bd5; | ||
297 | +} | ||
298 | + | ||
299 | +.style28 { | ||
300 | + color: #44546a; | ||
301 | + font-size: 13pt; | ||
302 | + font-weight: 700; | ||
303 | + font-style: normal; | ||
304 | + text-decoration: none; | ||
305 | + font-family: '宋体'; | ||
306 | + border-bottom: 1pt solid #5b9bd5; | ||
307 | +} | ||
308 | + | ||
309 | +.style29 { | ||
310 | + color: #44546a; | ||
311 | + font-size: 11pt; | ||
312 | + font-weight: 700; | ||
313 | + font-style: normal; | ||
314 | + text-decoration: none; | ||
315 | + font-family: '宋体'; | ||
316 | + border-bottom: 1pt solid #acccea; | ||
317 | +} | ||
318 | + | ||
319 | +.style30 { | ||
320 | + color: #44546a; | ||
321 | + font-size: 11pt; | ||
322 | + font-weight: 700; | ||
323 | + font-style: normal; | ||
324 | + text-decoration: none; | ||
325 | + font-family: '宋体'; | ||
326 | +} | ||
327 | + | ||
328 | +.style31 { | ||
329 | + background: #fc9; | ||
330 | + color: #3f3f76; | ||
331 | + font-size: 11pt; | ||
332 | + font-weight: 400; | ||
333 | + font-style: normal; | ||
334 | + text-decoration: none; | ||
335 | + font-family: '宋体'; | ||
336 | + border: 0.5pt solid #7f7f7f; | ||
337 | +} | ||
338 | + | ||
339 | +.style32 { | ||
340 | + background: #f2f2f2; | ||
341 | + color: #3f3f3f; | ||
342 | + font-size: 11pt; | ||
343 | + font-weight: 700; | ||
344 | + font-style: normal; | ||
345 | + text-decoration: none; | ||
346 | + font-family: '宋体'; | ||
347 | + border: 0.5pt solid #3f3f3f; | ||
348 | +} | ||
349 | + | ||
350 | +.style33 { | ||
351 | + background: #f2f2f2; | ||
352 | + color: #fa7d00; | ||
353 | + font-size: 11pt; | ||
354 | + font-weight: 700; | ||
355 | + font-style: normal; | ||
356 | + text-decoration: none; | ||
357 | + font-family: '宋体'; | ||
358 | + border: 0.5pt solid #7f7f7f; | ||
359 | +} | ||
360 | + | ||
361 | +.style34 { | ||
362 | + background: #a5a5a5; | ||
363 | + color: #fff; | ||
364 | + font-size: 11pt; | ||
365 | + font-weight: 700; | ||
366 | + font-style: normal; | ||
367 | + text-decoration: none; | ||
368 | + font-family: '宋体'; | ||
369 | + border: 2pt double #3f3f3f; | ||
370 | +} | ||
371 | + | ||
372 | +.style35 { | ||
373 | + color: #fa7d00; | ||
374 | + font-size: 11pt; | ||
375 | + font-weight: 400; | ||
376 | + font-style: normal; | ||
377 | + text-decoration: none; | ||
378 | + font-family: '宋体'; | ||
379 | + border-bottom: 2pt double #ff8001; | ||
380 | +} | ||
381 | + | ||
382 | +.style36 { | ||
383 | + color: #000; | ||
384 | + font-size: 11pt; | ||
385 | + font-weight: 700; | ||
386 | + font-style: normal; | ||
387 | + text-decoration: none; | ||
388 | + font-family: '宋体'; | ||
389 | + border-top: 0.5pt solid #5b9bd5; | ||
390 | + border-bottom: 2pt double #5b9bd5; | ||
391 | +} | ||
392 | + | ||
393 | +.style37 { | ||
394 | + background: #c6efce; | ||
395 | + color: #006100; | ||
396 | + font-size: 11pt; | ||
397 | + font-weight: 400; | ||
398 | + font-style: normal; | ||
399 | + text-decoration: none; | ||
400 | + font-family: '宋体'; | ||
401 | +} | ||
402 | + | ||
403 | +.style38 { | ||
404 | + background: #ffc7ce; | ||
405 | + color: #9c0006; | ||
406 | + font-size: 11pt; | ||
407 | + font-weight: 400; | ||
408 | + font-style: normal; | ||
409 | + text-decoration: none; | ||
410 | + font-family: '宋体'; | ||
411 | +} | ||
412 | + | ||
413 | +.style39 { | ||
414 | + background: #ffeb9c; | ||
415 | + color: #9c6500; | ||
416 | + font-size: 11pt; | ||
417 | + font-weight: 400; | ||
418 | + font-style: normal; | ||
419 | + text-decoration: none; | ||
420 | + font-family: '宋体'; | ||
421 | +} | ||
422 | + | ||
423 | +.style40 { | ||
424 | + background: #5b9bd5; | ||
425 | + color: #fff; | ||
426 | + font-size: 11pt; | ||
427 | + font-weight: 400; | ||
428 | + font-style: normal; | ||
429 | + text-decoration: none; | ||
430 | + font-family: '宋体'; | ||
431 | +} | ||
432 | + | ||
433 | +.style41 { | ||
434 | + background: #ddebf7; | ||
435 | + color: #000; | ||
436 | + font-size: 11pt; | ||
437 | + font-weight: 400; | ||
438 | + font-style: normal; | ||
439 | + text-decoration: none; | ||
440 | + font-family: '宋体'; | ||
441 | +} | ||
442 | + | ||
443 | +.style42 { | ||
444 | + background: #bdd7ee; | ||
445 | + color: #000; | ||
446 | + font-size: 11pt; | ||
447 | + font-weight: 400; | ||
448 | + font-style: normal; | ||
449 | + text-decoration: none; | ||
450 | + font-family: '宋体'; | ||
451 | +} | ||
452 | + | ||
453 | +.style43 { | ||
454 | + background: #9bc2e6; | ||
455 | + color: #fff; | ||
456 | + font-size: 11pt; | ||
457 | + font-weight: 400; | ||
458 | + font-style: normal; | ||
459 | + text-decoration: none; | ||
460 | + font-family: '宋体'; | ||
461 | +} | ||
462 | + | ||
463 | +.style44 { | ||
464 | + background: #ed7d31; | ||
465 | + color: #fff; | ||
466 | + font-size: 11pt; | ||
467 | + font-weight: 400; | ||
468 | + font-style: normal; | ||
469 | + text-decoration: none; | ||
470 | + font-family: '宋体'; | ||
471 | +} | ||
472 | + | ||
473 | +.style45 { | ||
474 | + background: #fce4d6; | ||
475 | + color: #000; | ||
476 | + font-size: 11pt; | ||
477 | + font-weight: 400; | ||
478 | + font-style: normal; | ||
479 | + text-decoration: none; | ||
480 | + font-family: '宋体'; | ||
481 | +} | ||
482 | + | ||
483 | +.style46 { | ||
484 | + background: #f8cbad; | ||
485 | + color: #000; | ||
486 | + font-size: 11pt; | ||
487 | + font-weight: 400; | ||
488 | + font-style: normal; | ||
489 | + text-decoration: none; | ||
490 | + font-family: '宋体'; | ||
491 | +} | ||
492 | + | ||
493 | +.style47 { | ||
494 | + background: #f4b084; | ||
495 | + color: #fff; | ||
496 | + font-size: 11pt; | ||
497 | + font-weight: 400; | ||
498 | + font-style: normal; | ||
499 | + text-decoration: none; | ||
500 | + font-family: '宋体'; | ||
501 | +} | ||
502 | + | ||
503 | +.style48 { | ||
504 | + background: #a5a5a5; | ||
505 | + color: #fff; | ||
506 | + font-size: 11pt; | ||
507 | + font-weight: 400; | ||
508 | + font-style: normal; | ||
509 | + text-decoration: none; | ||
510 | + font-family: '宋体'; | ||
511 | +} | ||
512 | + | ||
513 | +.style49 { | ||
514 | + background: #ededed; | ||
515 | + color: #000; | ||
516 | + font-size: 11pt; | ||
517 | + font-weight: 400; | ||
518 | + font-style: normal; | ||
519 | + text-decoration: none; | ||
520 | + font-family: '宋体'; | ||
521 | +} | ||
522 | + | ||
523 | +.style50 { | ||
524 | + background: #dbdbdb; | ||
525 | + color: #000; | ||
526 | + font-size: 11pt; | ||
527 | + font-weight: 400; | ||
528 | + font-style: normal; | ||
529 | + text-decoration: none; | ||
530 | + font-family: '宋体'; | ||
531 | +} | ||
532 | + | ||
533 | +.style51 { | ||
534 | + background: #c9c9c9; | ||
535 | + color: #fff; | ||
536 | + font-size: 11pt; | ||
537 | + font-weight: 400; | ||
538 | + font-style: normal; | ||
539 | + text-decoration: none; | ||
540 | + font-family: '宋体'; | ||
541 | +} | ||
542 | + | ||
543 | +.style52 { | ||
544 | + background: #ffc000; | ||
545 | + color: #fff; | ||
546 | + font-size: 11pt; | ||
547 | + font-weight: 400; | ||
548 | + font-style: normal; | ||
549 | + text-decoration: none; | ||
550 | + font-family: '宋体'; | ||
551 | +} | ||
552 | + | ||
553 | +.style53 { | ||
554 | + background: #fff2cc; | ||
555 | + color: #000; | ||
556 | + font-size: 11pt; | ||
557 | + font-weight: 400; | ||
558 | + font-style: normal; | ||
559 | + text-decoration: none; | ||
560 | + font-family: '宋体'; | ||
561 | +} | ||
562 | + | ||
563 | +.style54 { | ||
564 | + background: #ffe699; | ||
565 | + color: #000; | ||
566 | + font-size: 11pt; | ||
567 | + font-weight: 400; | ||
568 | + font-style: normal; | ||
569 | + text-decoration: none; | ||
570 | + font-family: '宋体'; | ||
571 | +} | ||
572 | + | ||
573 | +.style55 { | ||
574 | + background: #ffd966; | ||
575 | + color: #fff; | ||
576 | + font-size: 11pt; | ||
577 | + font-weight: 400; | ||
578 | + font-style: normal; | ||
579 | + text-decoration: none; | ||
580 | + font-family: '宋体'; | ||
581 | +} | ||
582 | + | ||
583 | +.style56 { | ||
584 | + background: #4472c4; | ||
585 | + color: #fff; | ||
586 | + font-size: 11pt; | ||
587 | + font-weight: 400; | ||
588 | + font-style: normal; | ||
589 | + text-decoration: none; | ||
590 | + font-family: '宋体'; | ||
591 | +} | ||
592 | + | ||
593 | +.style57 { | ||
594 | + background: #d9e1f2; | ||
595 | + color: #000; | ||
596 | + font-size: 11pt; | ||
597 | + font-weight: 400; | ||
598 | + font-style: normal; | ||
599 | + text-decoration: none; | ||
600 | + font-family: '宋体'; | ||
601 | +} | ||
602 | + | ||
603 | +.style58 { | ||
604 | + background: #b4c6e7; | ||
605 | + color: #000; | ||
606 | + font-size: 11pt; | ||
607 | + font-weight: 400; | ||
608 | + font-style: normal; | ||
609 | + text-decoration: none; | ||
610 | + font-family: '宋体'; | ||
611 | +} | ||
612 | + | ||
613 | +.style59 { | ||
614 | + background: #8ea9db; | ||
615 | + color: #fff; | ||
616 | + font-size: 11pt; | ||
617 | + font-weight: 400; | ||
618 | + font-style: normal; | ||
619 | + text-decoration: none; | ||
620 | + font-family: '宋体'; | ||
621 | +} | ||
622 | + | ||
623 | +.style60 { | ||
624 | + background: #70ad47; | ||
625 | + color: #fff; | ||
626 | + font-size: 11pt; | ||
627 | + font-weight: 400; | ||
628 | + font-style: normal; | ||
629 | + text-decoration: none; | ||
630 | + font-family: '宋体'; | ||
631 | +} | ||
632 | + | ||
633 | +.style61 { | ||
634 | + background: #e2efda; | ||
635 | + color: #000; | ||
636 | + font-size: 11pt; | ||
637 | + font-weight: 400; | ||
638 | + font-style: normal; | ||
639 | + text-decoration: none; | ||
640 | + font-family: '宋体'; | ||
641 | +} | ||
642 | + | ||
643 | +.style62 { | ||
644 | + background: #c6e0b4; | ||
645 | + color: #000; | ||
646 | + font-size: 11pt; | ||
647 | + font-weight: 400; | ||
648 | + font-style: normal; | ||
649 | + text-decoration: none; | ||
650 | + font-family: '宋体'; | ||
651 | +} | ||
652 | + | ||
653 | +.style63 { | ||
654 | + background: #a9d08e; | ||
655 | + color: #fff; | ||
656 | + font-size: 11pt; | ||
657 | + font-weight: 400; | ||
658 | + font-style: normal; | ||
659 | + text-decoration: none; | ||
660 | + font-family: '宋体'; | ||
661 | +} | ||
662 | + | ||
663 | +td { | ||
664 | + padding-top: 1px; | ||
665 | + padding-right: 1px; | ||
666 | + padding-left: 1px; | ||
667 | + text-align: general; | ||
668 | + vertical-align: middle; | ||
669 | + white-space: nowrap; | ||
670 | + color: windowtext; | ||
671 | + font-size: 12pt; | ||
672 | + font-weight: 400; | ||
673 | + font-style: normal; | ||
674 | + text-decoration: none; | ||
675 | + font-family: '宋体'; | ||
676 | + border: none; | ||
677 | +} | ||
678 | + | ||
679 | +.xl65 { | ||
680 | + text-align: center; | ||
681 | + font-size: 16pt; | ||
682 | +} | ||
683 | + | ||
684 | +.xl66 { | ||
685 | + text-align: center; | ||
686 | + font-size: 10pt; | ||
687 | +} | ||
688 | + | ||
689 | +.xl67 { | ||
690 | + text-align: center; | ||
691 | + font-size: 14pt; | ||
692 | +} | ||
693 | + | ||
694 | +.xl68 { | ||
695 | + text-align: center; | ||
696 | + font-size: 14pt; | ||
697 | +} | ||
698 | + | ||
699 | +.xl69 { | ||
700 | + text-align: left; | ||
701 | + font-size: 8pt; | ||
702 | +} | ||
703 | + | ||
704 | +.xl70 { | ||
705 | + text-align: left; | ||
706 | + font-size: 8pt; | ||
707 | +} | ||
708 | + | ||
709 | +.xl71 { | ||
710 | + text-align: center; | ||
711 | + font-size: 8pt; | ||
712 | + border: 0.5pt solid windowtext; | ||
713 | +} | ||
714 | + | ||
715 | +.xl72 { | ||
716 | + text-align: center; | ||
717 | + font-size: 8pt; | ||
718 | + border: 0.5pt solid windowtext; | ||
719 | + white-space: normal; | ||
720 | +} | ||
721 | + | ||
722 | +.xl73 { | ||
723 | + white-space: normal; | ||
724 | + font-size: 8pt; | ||
725 | + border: 0.5pt solid windowtext; | ||
726 | +} | ||
727 | + | ||
728 | +.xl74 { | ||
729 | + text-align: center; | ||
730 | + white-space: normal; | ||
731 | + font-size: 8pt; | ||
732 | + border: 0.5pt solid windowtext; | ||
733 | +} | ||
734 | + | ||
735 | +.xl75 { | ||
736 | + text-align: center; | ||
737 | + white-space: normal; | ||
738 | + font-size: 8pt; | ||
739 | + border: 0.5pt solid windowtext; | ||
740 | +} | ||
741 | + | ||
742 | +.xl76 { | ||
743 | + font-size: 8pt; | ||
744 | +} | ||
745 | + | ||
746 | +.xl77 { | ||
747 | + font-size: 8pt; | ||
748 | +} | ||
749 | + | ||
750 | +.xl78 { | ||
751 | + text-align: center; | ||
752 | + font-size: 8pt; | ||
753 | +} |
src/pages/ResearchGroup/components/AuditModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | ||
2 | +import { postCommonAudit } from '@/services'; | ||
3 | +import { ModalForm, ProFormTextArea } from '@ant-design/pro-components'; | ||
4 | +import { Button, Form, message } from 'antd'; | ||
5 | +import { cloneDeep } from 'lodash'; | ||
6 | + | ||
7 | +// import { cloneDeep } from 'lodash'; | ||
8 | +export default ({ setVisible, ids, onClose }) => { | ||
9 | + const [form] = Form.useForm(); | ||
10 | + let auditIds = cloneDeep(ids); | ||
11 | + | ||
12 | + const parseValues = (values: any) => { | ||
13 | + values.ids = auditIds; | ||
14 | + values.notes = form.getFieldValue('auditNotes'); | ||
15 | + }; | ||
16 | + | ||
17 | + const doAudit = async (values: any) => { | ||
18 | + values.type = 'research_group_member_request_audit'; | ||
19 | + let res = await postCommonAudit({ data: values }); | ||
20 | + if (res && res.result === RESPONSE_CODE.SUCCESS) { | ||
21 | + message.success(res.message); | ||
22 | + onClose(); | ||
23 | + } | ||
24 | + }; | ||
25 | + | ||
26 | + const loadbtns = (props: any, defaultDoms: any) => { | ||
27 | + let btns = []; | ||
28 | + //取消 | ||
29 | + btns.push(defaultDoms[0]); | ||
30 | + | ||
31 | + //驳回 | ||
32 | + btns.push( | ||
33 | + <Button | ||
34 | + type="primary" | ||
35 | + onClick={() => { | ||
36 | + let values = form.getFieldsValue(); | ||
37 | + values.pass = false; | ||
38 | + parseValues(values); | ||
39 | + doAudit(values); | ||
40 | + }} | ||
41 | + > | ||
42 | + 驳回 | ||
43 | + </Button>, | ||
44 | + ); | ||
45 | + | ||
46 | + //确认 | ||
47 | + btns.push(defaultDoms[1]); | ||
48 | + | ||
49 | + return btns; | ||
50 | + }; | ||
51 | + | ||
52 | + return ( | ||
53 | + <> | ||
54 | + <ModalForm | ||
55 | + width={500} | ||
56 | + open | ||
57 | + title="审核" | ||
58 | + form={form} | ||
59 | + autoFocusFirstInput | ||
60 | + modalProps={{ | ||
61 | + okText: '通过', | ||
62 | + cancelText: '取消', | ||
63 | + destroyOnClose: true, | ||
64 | + onCancel: () => { | ||
65 | + setVisible(false); | ||
66 | + }, | ||
67 | + }} | ||
68 | + onFinish={async (values) => { | ||
69 | + values.pass = true; | ||
70 | + parseValues(values); | ||
71 | + doAudit(values); | ||
72 | + onClose(); | ||
73 | + }} | ||
74 | + onOpenChange={setVisible} | ||
75 | + submitter={{ | ||
76 | + render: (props, defaultDoms) => { | ||
77 | + return loadbtns(props, defaultDoms); | ||
78 | + }, | ||
79 | + }} | ||
80 | + > | ||
81 | + <ProFormTextArea | ||
82 | + name="auditNotes" | ||
83 | + key="auditNotes" | ||
84 | + placeholder="备注" | ||
85 | + label="若驳回,请填写备注" | ||
86 | + /> | ||
87 | + </ModalForm> | ||
88 | + </> | ||
89 | + ); | ||
90 | +}; |
src/pages/ResearchGroup/components/ImportModal.tsx
0 → 100644
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | ||
2 | +import { postResearchGroupsImport } from '@/services'; | ||
3 | +import { orderExport } from '@/services/order'; | ||
4 | +import { UploadOutlined } from '@ant-design/icons'; | ||
5 | +import { Button, Modal, Upload, message } from 'antd'; | ||
6 | +import { RcFile, UploadFile, UploadProps } from 'antd/es/upload'; | ||
7 | +import { useState } from 'react'; | ||
8 | +export default ({ onClose }) => { | ||
9 | + // const [form] = Form.useForm<{ name: string; company: string }>(); | ||
10 | + const [messageApi, contextHolder] = message.useMessage(); | ||
11 | + const [fileList, setFileList] = useState<UploadFile[]>([]); | ||
12 | + const [uploading, setUploading] = useState(false); | ||
13 | + const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => | ||
14 | + setFileList(newFileList); | ||
15 | + | ||
16 | + const exportLoading = (content: string) => { | ||
17 | + messageApi.open({ | ||
18 | + type: 'loading', | ||
19 | + content: content, | ||
20 | + duration: 0, | ||
21 | + }); | ||
22 | + }; | ||
23 | + | ||
24 | + const exportLoadingDestory = () => { | ||
25 | + messageApi.destroy(); | ||
26 | + }; | ||
27 | + const downloadTemplate = async () => { | ||
28 | + exportLoading('正在下载模板...'); | ||
29 | + orderExport( | ||
30 | + '/api/research/groups/download/importTemplate', | ||
31 | + {}, | ||
32 | + exportLoadingDestory, | ||
33 | + ); | ||
34 | + }; | ||
35 | + | ||
36 | + const handleUpload = async () => { | ||
37 | + const formData = new FormData(); | ||
38 | + fileList.forEach((file) => { | ||
39 | + //originFileObj二进制文件 | ||
40 | + formData.append('file', file.originFileObj as RcFile); | ||
41 | + }); | ||
42 | + // console.log(fileList[0] as RcFile) | ||
43 | + // formData.append('file', fileList[0] as RcFile); | ||
44 | + setUploading(true); | ||
45 | + // You can use any AJAX library you like | ||
46 | + const res = await postResearchGroupsImport({ | ||
47 | + data: formData, | ||
48 | + headers: { | ||
49 | + 'Content-Type': | ||
50 | + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq', | ||
51 | + }, | ||
52 | + }); | ||
53 | + | ||
54 | + if (res.result === RESPONSE_CODE.SUCCESS) { | ||
55 | + message.success(res.message); | ||
56 | + onClose(); | ||
57 | + } | ||
58 | + | ||
59 | + setUploading(false); | ||
60 | + }; | ||
61 | + | ||
62 | + const props: UploadProps = { | ||
63 | + onRemove: (file) => { | ||
64 | + const index = fileList.indexOf(file); | ||
65 | + const newFileList = fileList.slice(); | ||
66 | + newFileList.splice(index, 1); | ||
67 | + setFileList(newFileList); | ||
68 | + }, | ||
69 | + beforeUpload: (file) => { | ||
70 | + setFileList([...fileList, file]); | ||
71 | + | ||
72 | + return false; | ||
73 | + }, | ||
74 | + fileList, | ||
75 | + onChange: handleChange, | ||
76 | + accept: '.xlsx', | ||
77 | + }; | ||
78 | + | ||
79 | + return ( | ||
80 | + <> | ||
81 | + <Modal | ||
82 | + width={500} | ||
83 | + open | ||
84 | + title="课题组信息导入" | ||
85 | + footer={[ | ||
86 | + <Button key="cancel" onClick={onClose}> | ||
87 | + 取消 | ||
88 | + </Button>, | ||
89 | + <Button | ||
90 | + type="primary" | ||
91 | + key="ok" | ||
92 | + onClick={handleUpload} | ||
93 | + disabled={fileList.length === 0} | ||
94 | + loading={uploading} | ||
95 | + > | ||
96 | + {uploading ? '上传中' : '提交'} | ||
97 | + </Button>, | ||
98 | + ]} | ||
99 | + onCancel={async () => { | ||
100 | + onClose(); | ||
101 | + }} | ||
102 | + > | ||
103 | + <div className="py-4 font-semibold"> | ||
104 | + 导入课题组信息 | ||
105 | + <Button type="link" onClick={downloadTemplate}> | ||
106 | + 下载模板 | ||
107 | + </Button> | ||
108 | + </div> | ||
109 | + <Upload {...props}> | ||
110 | + <Button icon={<UploadOutlined />} disabled={fileList.length > 0}> | ||
111 | + 点击选择文件 | ||
112 | + </Button> | ||
113 | + </Upload> | ||
114 | + </Modal> | ||
115 | + {contextHolder} | ||
116 | + </> | ||
117 | + ); | ||
118 | +}; |