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 | import React, { useEffect, useState } from 'react'; | 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 | import {saveReplacementApi, ApplyData} from '@/pages/order3/CarPurchaseSubsidy/ReplacementSubsidy/api'; | 3 | import {saveReplacementApi, ApplyData} from '@/pages/order3/CarPurchaseSubsidy/ReplacementSubsidy/api'; |
5 | import { getAllBrandApi, getSeriesApi } from "@/common/api"; | 4 | import { getAllBrandApi, getSeriesApi } from "@/common/api"; |
6 | import useInitial from '@/hooks/useInitail'; | 5 | import useInitial from '@/hooks/useInitail'; |
7 | import NewDataModal from '@/pages/order3/Common/NewDataModal/index'; | 6 | import NewDataModal from '@/pages/order3/Common/NewDataModal/index'; |
8 | import moment from 'moment'; | 7 | import moment from 'moment'; |
9 | import { PageHeaderWrapper } from '@ant-design/pro-layout'; | 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 | import { isNil } from 'lodash'; | 13 | import { isNil } from 'lodash'; |
11 | 14 | ||
12 | interface DataNode { | 15 | interface DataNode { |
@@ -15,22 +18,21 @@ interface DataNode { | @@ -15,22 +18,21 @@ interface DataNode { | ||
15 | isLeaf?: boolean; | 18 | isLeaf?: boolean; |
16 | children?: DataNode[]; | 19 | children?: DataNode[]; |
17 | } | 20 | } |
21 | +const Requirements = [{value: true, label: '必买'}, {value: false, label: '非必买'}]; | ||
18 | 22 | ||
19 | export default function ApplyModal() { | 23 | export default function ApplyModal() { |
20 | const [form] = Form.useForm(); | 24 | const [form] = Form.useForm(); |
21 | const [loading, setLoading] = useState<boolean>(false); | 25 | const [loading, setLoading] = useState<boolean>(false); |
22 | - const [showTree, setShowTree] = useState<any[]>([]); | ||
23 | const {data} = useInitial(getAllBrandApi, [], {}); | 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 | const [treeData, setTreeData] = useState<any>([]); | 27 | const [treeData, setTreeData] = useState<any>([]); |
28 | const [checked, setChecked] = useState<any[]>([]); | 28 | const [checked, setChecked] = useState<any[]>([]); |
29 | - const [specKey, setSpecKey] = useState<any[]>([]); | ||
30 | - const [brand, setBrand] = useState<any>(); | ||
31 | const [beforeData, setBeforeData] = useState<ApplyData[]>([]); // 前置资料 | 29 | const [beforeData, setBeforeData] = useState<ApplyData[]>([]); // 前置资料 |
32 | const [afterData, setAfterData] = useState<ApplyData[]>([]); // 后置资料 | 30 | const [afterData, setAfterData] = useState<ApplyData[]>([]); // 后置资料 |
33 | const [afterDay, setAfterDay] = useState<number>(); // 后置资料上传天数 | 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 | useEffect(() => { | 37 | useEffect(() => { |
36 | if (data.length) { | 38 | if (data.length) { |
@@ -49,18 +51,6 @@ export default function ApplyModal() { | @@ -49,18 +51,6 @@ export default function ApplyModal() { | ||
49 | } | 51 | } |
50 | }, [checked.length]); | 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 | const onCheck = (value:any) => { | 54 | const onCheck = (value:any) => { |
65 | setChecked(value); | 55 | setChecked(value); |
66 | }; | 56 | }; |
@@ -116,11 +106,7 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | @@ -116,11 +106,7 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | ||
116 | setTreeData((origin:any) => updateTreeData(origin, key, _childrenNode)); | 106 | setTreeData((origin:any) => updateTreeData(origin, key, _childrenNode)); |
117 | }; | 107 | }; |
118 | const handleCancel = () => { | 108 | const handleCancel = () => { |
119 | - setSpecKey([]); | ||
120 | - setSubinfo([]); | ||
121 | - setAfterCar([]); | ||
122 | setChecked([]); | 109 | setChecked([]); |
123 | - setHidden(true); | ||
124 | setChecked([]); | 110 | setChecked([]); |
125 | }; | 111 | }; |
126 | const onFinsh = async () => { | 112 | const onFinsh = async () => { |
@@ -137,6 +123,9 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | @@ -137,6 +123,9 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | ||
137 | applyShops: param.applyShops.map((item:any) => { return {shopId: item.value, shopName: item.label}; }), // 门店列表 | 123 | applyShops: param.applyShops.map((item:any) => { return {shopId: item.value, shopName: item.label}; }), // 门店列表 |
138 | subsidyDataUploadApply: beforeData.map((v:any) => { return {applyUpload: 1, dataType: v.dataType, dataName: v.dataName}; }), // 申请时上传资料 | 124 | subsidyDataUploadApply: beforeData.map((v:any) => { return {applyUpload: 1, dataType: v.dataType, dataName: v.dataName}; }), // 申请时上传资料 |
139 | subsidyType: 2, | 125 | subsidyType: 2, |
126 | + applyCarList: handleCarData(param.optionalAuth), | ||
127 | + containOrder: param.containOrder, | ||
128 | + insuranceRequire: param.insuranceRequire | ||
140 | }; | 129 | }; |
141 | if (checked.length === 0) { | 130 | if (checked.length === 0) { |
142 | message.error("请选择本品牌范围!"); | 131 | message.error("请选择本品牌范围!"); |
@@ -144,44 +133,35 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | @@ -144,44 +133,35 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | ||
144 | } else if (!isNil(afterDay) && afterData.length === 0) { | 133 | } else if (!isNil(afterDay) && afterData.length === 0) { |
145 | message.error("请勾选交车后N天内上传的资料!"); | 134 | message.error("请勾选交车后N天内上传的资料!"); |
146 | return; | 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 | return; | 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 | return; | 144 | return; |
153 | } | 145 | } |
154 | if (!isNil(afterDay)) { | 146 | if (!isNil(afterDay)) { |
155 | _param.deliveryAfterDays = afterDay; | 147 | _param.deliveryAfterDays = afterDay; |
156 | _param.subsidyDataUploadNDay = afterData.map((item: any) => { return {applyUpload: 0, dataType: item.dataType, dataName: item.dateName}; }); | 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 | if (param.applyCarType === 2) { | 155 | if (param.applyCarType === 2) { |
159 | _param.applySpecList = param.applySeriesList.map((item:any) => { return {seriesId: item.value, seriesName: item.label}; }); | 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 | const sameBrandRange = brandList(checked); | 158 | const sameBrandRange = brandList(checked); |
176 | _param.sameBrandRange = sameBrandRange; | 159 | _param.sameBrandRange = sameBrandRange; |
177 | setLoading(true); | 160 | setLoading(true); |
178 | saveReplacementApi(_param) | 161 | saveReplacementApi(_param) |
179 | .then(res => { | 162 | .then(res => { |
180 | message.success(res.result); | 163 | message.success(res.result); |
181 | - setSubinfo([]); | ||
182 | - setAfterCar([]); | ||
183 | setLoading(false); | 164 | setLoading(false); |
184 | - setSpecKey([]); | ||
185 | }) | 165 | }) |
186 | .catch(e => { | 166 | .catch(e => { |
187 | message.error(e.message); | 167 | message.error(e.message); |
@@ -189,10 +169,95 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | @@ -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 | return ( | 263 | return ( |
@@ -203,7 +268,22 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | @@ -203,7 +268,22 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | ||
203 | <Form | 268 | <Form |
204 | form={form} | 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 | <Form.Item name="time" label="有效时间" rules={[{ type: 'array' as const, required: true, message: '请选择有效时间!' }]}> | 287 | <Form.Item name="time" label="有效时间" rules={[{ type: 'array' as const, required: true, message: '请选择有效时间!' }]}> |
208 | <DatePicker.RangePicker showTime style={{width: "100%"}} /> | 288 | <DatePicker.RangePicker showTime style={{width: "100%"}} /> |
209 | </Form.Item> | 289 | </Form.Item> |
@@ -226,6 +306,47 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | @@ -226,6 +306,47 @@ function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): | ||
226 | <Form.Item name="extraAmount" label="4S店老客户升级置换额外享受补贴" rules={[{required: true, pattern: /^(\d+|\d+\.\d{1,2})$/, message: "请输入正确的补贴值!"}]}> | 306 | <Form.Item name="extraAmount" label="4S店老客户升级置换额外享受补贴" rules={[{required: true, pattern: /^(\d+|\d+\.\d{1,2})$/, message: "请输入正确的补贴值!"}]}> |
227 | <Input /> | 307 | <Input /> |
228 | </Form.Item> | 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 | <Form.Item | 350 | <Form.Item |
230 | labelAlign="left" | 351 | labelAlign="left" |
231 | label="置换补贴资料" | 352 | label="置换补贴资料" |