Commit bc9db829e40de19f6ee76d2e9590ab4039648bc2
1 parent
dd3e22ff
新增置换补贴
Showing
1 changed file
with
171 additions
and
50 deletions
src/pages/order3/CarPurchaseSubsidy/ReplacementSubsidy/subpages/AddConfig/index.tsx
1 | 1 | import React, { useEffect, useState } from 'react'; |
2 | -import { Table, Modal, Button, Form, Space, DatePicker, Tree, Input, message, Card, Row, Col} from 'antd'; | |
3 | -import CarSelect from '@/pages/order3/Common/CarSelect/index'; | |
2 | +import { Table, Button, Form, Space, DatePicker, Tree, Input, message, Card, Row, Col, Radio, Select, InputNumber} from 'antd'; | |
4 | 3 | import {saveReplacementApi, ApplyData} from '@/pages/order3/CarPurchaseSubsidy/ReplacementSubsidy/api'; |
5 | 4 | import { getAllBrandApi, getSeriesApi } from "@/common/api"; |
6 | 5 | import useInitial from '@/hooks/useInitail'; |
7 | 6 | import NewDataModal from '@/pages/order3/Common/NewDataModal/index'; |
8 | 7 | import moment from 'moment'; |
9 | 8 | import { PageHeaderWrapper } from '@ant-design/pro-layout'; |
9 | +import CarTableTreeAuth from '@/components/CarTableTreeAuth'; | |
10 | +import { PlusSquareOutlined } from '@ant-design/icons'; | |
11 | +import { CarAuthList } from '@/components/CarTableTreeAuth/entity'; | |
12 | +import { getShopApi, ShopVo, RequestShopParams } from '@/pages/order3/Common/api'; | |
10 | 13 | import { isNil } from 'lodash'; |
11 | 14 | |
12 | 15 | interface DataNode { |
... | ... | @@ -15,22 +18,21 @@ interface DataNode { |
15 | 18 | isLeaf?: boolean; |
16 | 19 | children?: DataNode[]; |
17 | 20 | } |
21 | +const Requirements = [{value: true, label: '必买'}, {value: false, label: '非必买'}]; | |
18 | 22 | |
19 | 23 | export default function ApplyModal() { |
20 | 24 | const [form] = Form.useForm(); |
21 | 25 | const [loading, setLoading] = useState<boolean>(false); |
22 | - const [showTree, setShowTree] = useState<any[]>([]); | |
23 | 26 | const {data} = useInitial(getAllBrandApi, [], {}); |
24 | - const [subinfo, setSubinfo] = useState<number[]>([]); | |
25 | - const [afterCar, setAfterCar] = useState<number[]>([]); | |
26 | - const [hidden, setHidden] = useState<boolean>(true); | |
27 | 27 | const [treeData, setTreeData] = useState<any>([]); |
28 | 28 | const [checked, setChecked] = useState<any[]>([]); |
29 | - const [specKey, setSpecKey] = useState<any[]>([]); | |
30 | - const [brand, setBrand] = useState<any>(); | |
31 | 29 | const [beforeData, setBeforeData] = useState<ApplyData[]>([]); // 前置资料 |
32 | 30 | const [afterData, setAfterData] = useState<ApplyData[]>([]); // 后置资料 |
33 | 31 | const [afterDay, setAfterDay] = useState<number>(); // 后置资料上传天数 |
32 | + const [shopList, setShopList] = useState<ShopVo[]>([]); | |
33 | + const [shopLoading, setShopLoading] = useState<boolean>(false); | |
34 | + const [carSelectData, setCarSelectData] = useState<CarAuthList[]>([]); | |
35 | + const [insure, setInsure] = useState<any>([{mustBuyTci: undefined, mustBuyVci: undefined, vciBuyAmount: undefined, id: 1}]); | |
34 | 36 | |
35 | 37 | useEffect(() => { |
36 | 38 | if (data.length) { |
... | ... | @@ -49,18 +51,6 @@ export default function ApplyModal() { |
49 | 51 | } |
50 | 52 | }, [checked.length]); |
51 | 53 | |
52 | - useEffect(() => { | |
53 | - brand && setChecked([brand]); | |
54 | - }, [brand]); | |
55 | - | |
56 | - useEffect(() => { | |
57 | - if (subinfo.length>0) { | |
58 | - form.setFieldsValue({subsidyDataList: subinfo}); | |
59 | - } else { | |
60 | - form.setFieldsValue({subsidyDataList: undefined}); | |
61 | - } | |
62 | - }, [subinfo.length]); | |
63 | - | |
64 | 54 | const onCheck = (value:any) => { |
65 | 55 | setChecked(value); |
66 | 56 | }; |
... | ... | @@ -116,11 +106,7 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): |
116 | 106 | setTreeData((origin:any) => updateTreeData(origin, key, _childrenNode)); |
117 | 107 | }; |
118 | 108 | const handleCancel = () => { |
119 | - setSpecKey([]); | |
120 | - setSubinfo([]); | |
121 | - setAfterCar([]); | |
122 | 109 | setChecked([]); |
123 | - setHidden(true); | |
124 | 110 | setChecked([]); |
125 | 111 | }; |
126 | 112 | const onFinsh = async () => { |
... | ... | @@ -137,6 +123,9 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): |
137 | 123 | applyShops: param.applyShops.map((item:any) => { return {shopId: item.value, shopName: item.label}; }), // 门店列表 |
138 | 124 | subsidyDataUploadApply: beforeData.map((v:any) => { return {applyUpload: 1, dataType: v.dataType, dataName: v.dataName}; }), // 申请时上传资料 |
139 | 125 | subsidyType: 2, |
126 | + applyCarList: handleCarData(param.optionalAuth), | |
127 | + containOrder: param.containOrder, | |
128 | + insuranceRequire: param.insuranceRequire | |
140 | 129 | }; |
141 | 130 | if (checked.length === 0) { |
142 | 131 | message.error("请选择本品牌范围!"); |
... | ... | @@ -144,44 +133,35 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): |
144 | 133 | } else if (!isNil(afterDay) && afterData.length === 0) { |
145 | 134 | message.error("请勾选交车后N天内上传的资料!"); |
146 | 135 | return; |
147 | - } else if (param.applyCarType === 2 && param.applySeriesList.length === 0) { // 部分车系 | |
148 | - message.error("请选择适用车辆!"); | |
136 | + } else if (param.insuranceRequire && isNil(insure[0].mustBuyTci)) { | |
137 | + message.error("请选择是否购买交强险!"); | |
138 | + return; | |
139 | + } else if (param.insuranceRequire && isNil(insure[0].mustBuyVci)) { | |
140 | + message.error("请选择商是否购买商业险购!"); | |
149 | 141 | return; |
150 | - } else if (param.applyCarType === 3 && showTree.length === 0) { // 部分车型 | |
151 | - message.error("请选择适用车辆!"); | |
142 | + } else if (param.insuranceRequire && isNil(insure[0].vciBuyAmount)) { | |
143 | + message.error("请选择输入商业险金额!"); | |
152 | 144 | return; |
153 | 145 | } |
154 | 146 | if (!isNil(afterDay)) { |
155 | 147 | _param.deliveryAfterDays = afterDay; |
156 | 148 | _param.subsidyDataUploadNDay = afterData.map((item: any) => { return {applyUpload: 0, dataType: item.dataType, dataName: item.dateName}; }); |
157 | 149 | } |
150 | + if (param.insuranceRequire) { | |
151 | + _param.mustBuyTci = insure[0].mustBuyTci; | |
152 | + _param.mustBuyVci = insure[0].mustBuyVci; | |
153 | + _param.vciBuyAmount = insure[0].vciBuyAmount; | |
154 | + } | |
158 | 155 | if (param.applyCarType === 2) { |
159 | 156 | _param.applySpecList = param.applySeriesList.map((item:any) => { return {seriesId: item.value, seriesName: item.label}; }); |
160 | 157 | } |
161 | - if (param.applyCarType === 3) { | |
162 | - const _showTree = JSON.parse(JSON.stringify(showTree)); | |
163 | - _param.applySpecList = _showTree.map((item:any) => { | |
164 | - const _data = item.children.map((v:any) => { | |
165 | - return { | |
166 | - seriesId: item.key, | |
167 | - seriesName: item.title, | |
168 | - specId: v.key, | |
169 | - specName: v.title | |
170 | - }; | |
171 | - }); | |
172 | - return [..._data]; | |
173 | - }).flat(); | |
174 | - } | |
175 | 158 | const sameBrandRange = brandList(checked); |
176 | 159 | _param.sameBrandRange = sameBrandRange; |
177 | 160 | setLoading(true); |
178 | 161 | saveReplacementApi(_param) |
179 | 162 | .then(res => { |
180 | 163 | message.success(res.result); |
181 | - setSubinfo([]); | |
182 | - setAfterCar([]); | |
183 | 164 | setLoading(false); |
184 | - setSpecKey([]); | |
185 | 165 | }) |
186 | 166 | .catch(e => { |
187 | 167 | message.error(e.message); |
... | ... | @@ -189,10 +169,95 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): |
189 | 169 | }); |
190 | 170 | }; |
191 | 171 | |
192 | - function onClose() { | |
193 | - form.resetFields(); | |
194 | - setBrand(undefined); | |
195 | - setChecked([]); | |
172 | + /** | |
173 | + * 选择车辆范围回调 | |
174 | + * @param value 车辆树形结构 | |
175 | + */ | |
176 | + function handleChange(value: CarAuthList[] = []) { | |
177 | + const brandIds: number[] = []; | |
178 | + const seriesIds: number[] = []; | |
179 | + const specIds: number[] = []; | |
180 | + value.forEach(v => { | |
181 | + if (v.children) { | |
182 | + v.children.forEach(k => { | |
183 | + if (k.children) { | |
184 | + const spec = k.children.map(q => q.specId); | |
185 | + specIds.push(...spec); | |
186 | + } else { | |
187 | + seriesIds.push(k.seriesId); | |
188 | + } | |
189 | + }); | |
190 | + } else { | |
191 | + brandIds.push(v.brandId); | |
192 | + } | |
193 | + }); | |
194 | + const parmas = { | |
195 | + brandIds, | |
196 | + seriesIds, | |
197 | + specIds | |
198 | + }; | |
199 | + setCarSelectData(value || []); | |
200 | + getShopScope(parmas); | |
201 | + console.log(value); | |
202 | + } | |
203 | + | |
204 | + /** | |
205 | + * 获取所选车辆的授权门店范围 | |
206 | + * @param params | |
207 | + */ | |
208 | + function getShopScope(params: RequestShopParams) { | |
209 | + setShopLoading(true); | |
210 | + getShopApi(params) | |
211 | + .then(res => { | |
212 | + setShopLoading(false); | |
213 | + setShopList(res.data || []); | |
214 | + }).catch(e => { | |
215 | + setShopLoading(false); | |
216 | + setShopList([]); | |
217 | + message.error(e.message); | |
218 | + }); | |
219 | + } | |
220 | + | |
221 | + function handleInsureChange(name: string, value?: number) { | |
222 | + setInsure([{...insure[0], [name]: value}]); | |
223 | + } | |
224 | + | |
225 | + function resetInsure() { | |
226 | + setInsure([{mustBuyTci: undefined, mustBuyVci: undefined, vciBuyAmount: undefined, id: 1}]); | |
227 | + } | |
228 | + | |
229 | + /** | |
230 | + * 将树形车辆结构转换成扁平结构 | |
231 | + * applyCarType为最细化层级的类型 | |
232 | + * @param value | |
233 | + * @returns | |
234 | + */ | |
235 | + function handleCarData(value: CarAuthList[]) { | |
236 | + const result: any = []; | |
237 | + let applyCarType = 1; | |
238 | + value.forEach(v => { | |
239 | + if (v.children) { | |
240 | + v.children.forEach(k => { | |
241 | + if (k.children) { | |
242 | + k.children.forEach(r => { | |
243 | + const item = {brandId: v.brandId, brandName: v.brandName, seriesId: k.seriesId, seriesName: k.seriesName, specId: r.specId, specName: r.specName}; | |
244 | + result.push(item); | |
245 | + applyCarType = Math.max(applyCarType, 3); | |
246 | + }); | |
247 | + } else { | |
248 | + const item = {brandId: v.brandId, brandName: v.brandName, seriesId: k.seriesId, seriesName: k.seriesName}; | |
249 | + result.push(item); | |
250 | + applyCarType = Math.max(applyCarType, 2); | |
251 | + } | |
252 | + }); | |
253 | + } else { | |
254 | + const item = { brandId: v.brandId, brandName: v.brandName, applyCarType: v.authType}; | |
255 | + result.push(item); | |
256 | + applyCarType = Math.max(applyCarType, 1); | |
257 | + } | |
258 | + }); | |
259 | + const _result = result.map((v: any) => ({...v, applyCarType})); | |
260 | + return _result; | |
196 | 261 | } |
197 | 262 | |
198 | 263 | return ( |
... | ... | @@ -203,7 +268,22 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): |
203 | 268 | <Form |
204 | 269 | form={form} |
205 | 270 | > |
206 | - {/* <CarSelect specKey={specKey} setSpecKey={setSpecKey} modalVis={visible} setFieldsValue={form.setFieldsValue} showTree={showTree} setShowTree={setShowTree} setBrand={setBrand} /> */} | |
271 | + <Form.Item | |
272 | + name="optionalAuth" | |
273 | + label="授权车辆范围" | |
274 | + rules={[{ required: true, message: "选择车辆" }]} | |
275 | + tooltip={<span style={{ color: '#ccc', fontSize: 12 }}>*点击图标<PlusSquareOutlined />展开授权详情</span>} | |
276 | + > | |
277 | + <CarTableTreeAuth value={carSelectData} onChange={handleChange} brandMultiple={false} /> | |
278 | + </Form.Item> | |
279 | + <Form.Item | |
280 | + label="适用门店" | |
281 | + name="applyShops" | |
282 | + labelAlign="left" | |
283 | + rules={[{ required: true, message: "请选择适用门店" }]} | |
284 | + > | |
285 | + <Select mode="multiple" allowClear filterOption optionFilterProp="children" labelInValue placeholder="请选择" options={shopList.map(v => ({label: v.shopName, value: v.shopId}))} loading={shopLoading} /> | |
286 | + </Form.Item> | |
207 | 287 | <Form.Item name="time" label="有效时间" rules={[{ type: 'array' as const, required: true, message: '请选择有效时间!' }]}> |
208 | 288 | <DatePicker.RangePicker showTime style={{width: "100%"}} /> |
209 | 289 | </Form.Item> |
... | ... | @@ -226,6 +306,47 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): |
226 | 306 | <Form.Item name="extraAmount" label="4S店老客户升级置换额外享受补贴" rules={[{required: true, pattern: /^(\d+|\d+\.\d{1,2})$/, message: "请输入正确的补贴值!"}]}> |
227 | 307 | <Input /> |
228 | 308 | </Form.Item> |
309 | + <Form.Item labelAlign="left" label="保险要求" name="insuranceRequire" rules={[{required: true, message: "请选择保险要求!"}]}> | |
310 | + <Radio.Group onChange={resetInsure}> | |
311 | + <Radio value={false}>无要求</Radio> | |
312 | + <Radio value>有要求</Radio> | |
313 | + </Radio.Group> | |
314 | + </Form.Item> | |
315 | + <Form.Item | |
316 | + noStyle | |
317 | + shouldUpdate={(prevValues, curValues) => prevValues.insuranceRequire !== curValues.insuranceRequire} | |
318 | + > | |
319 | + {({ getFieldValue }) => { | |
320 | + const bool = getFieldValue('insuranceRequire'); | |
321 | + return bool ? ( | |
322 | + <Card> | |
323 | + <Table pagination={false} dataSource={insure} rowKey="id"> | |
324 | + <Table.Column | |
325 | + title="交强险" | |
326 | + dataIndex="mustBuyTci" | |
327 | + render={(_text, record) => <Select value={_text} onChange={(e) => handleInsureChange("mustBuyTci", e)} placeholder="请选择" options={Requirements} />} | |
328 | + /> | |
329 | + <Table.Column | |
330 | + title="商业险" | |
331 | + dataIndex="mustBuyVci" | |
332 | + render={(_text, record) => <Select value={_text} onChange={e => handleInsureChange("mustBuyVci", e)} placeholder="请选择" options={Requirements} />} | |
333 | + /> | |
334 | + <Table.Column | |
335 | + title="商业险金额(≥元)" | |
336 | + dataIndex="vciBuyAmount" | |
337 | + render={(_text, record) => <InputNumber value={_text} onChange={e => handleInsureChange("vciBuyAmount", e)} controls={false} min={0} precision={2} placeholder="请输入金额" />} | |
338 | + /> | |
339 | + </Table> | |
340 | + </Card> | |
341 | + ) : null; | |
342 | + }} | |
343 | + </Form.Item> | |
344 | + <Form.Item labelAlign="left" label="政策适用范围" name="containOrder" rules={[{required: true, message: "请选择政策适用范围!"}]}> | |
345 | + <Radio.Group> | |
346 | + <Radio value>是</Radio> | |
347 | + <Radio value={false}>否</Radio> | |
348 | + </Radio.Group> | |
349 | + </Form.Item> | |
229 | 350 | <Form.Item |
230 | 351 | labelAlign="left" |
231 | 352 | label="置换补贴资料" | ... | ... |