index.tsx 14.7 KB
import React, { useEffect, useState } from 'react';
import { Table, Button, Form, Space, DatePicker, Tree, Input, message, Card, Row, Col, Radio, Select, InputNumber} from 'antd';
import {saveReplacementApi, ApplyData} from '@/pages/order3/CarPurchaseSubsidy/ReplacementSubsidy/api';
import { getAllBrandApi, getSeriesApi } from "@/common/api";
import useInitial from '@/hooks/useInitail';
import NewDataModal from '@/pages/order3/Common/NewDataModal/index';
import moment from 'moment';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import CarTableTreeAuth from '@/components/CarTableTreeAuth';
import { PlusSquareOutlined } from '@ant-design/icons';
import { CarAuthList } from '@/components/CarTableTreeAuth/entity';
import { getShopApi, ShopVo, RequestShopParams } from '@/pages/order3/Common/api';
import { isNil } from 'lodash';

interface DataNode {
  title: string;
  key: string;
  isLeaf?: boolean;
  children?: DataNode[];
}
const Requirements = [{value: true, label: '必买'}, {value: false, label: '非必买'}];

export default function ApplyModal() {
  const [form] = Form.useForm();
  const [loading, setLoading] = useState<boolean>(false);
  const {data} = useInitial(getAllBrandApi, [], {});
  const [treeData, setTreeData] = useState<any>([]);
  const [checked, setChecked] = useState<any[]>([]);
  const [beforeData, setBeforeData] = useState<ApplyData[]>([]); // 前置资料
  const [afterData, setAfterData] = useState<ApplyData[]>([]); // 后置资料
  const [afterDay, setAfterDay] = useState<number>(); // 后置资料上传天数
  const [shopList, setShopList] = useState<ShopVo[]>([]);
  const [shopLoading, setShopLoading] = useState<boolean>(false);
  const [carSelectData, setCarSelectData] = useState<CarAuthList[]>([]);
  const [insure, setInsure] = useState<any>([{mustBuyTci: undefined, mustBuyVci: undefined, vciBuyAmount: undefined, id: 1}]);

  useEffect(() => {
    if (data.length) {
      const _data = data.map((v:any) => {
        return { title: v.name, key: `${v.id}${v.initial}` };
      });
      setTreeData(_data);
    }
  }, [data.length]);

  useEffect(() => {
    if (checked.length) {
      form.setFieldsValue({sameBrandRange: checked});
    } else {
      form.setFieldsValue({sameBrandRange: undefined});
    }
  }, [checked.length]);

const onCheck = (value:any) => {
  setChecked(value);
};

const brandList = (value:any[]) => {
  const _data: any[] = JSON.parse(JSON.stringify(treeData));
  const parent = _data.filter(v => value.includes(v.key));
  const children = _data.filter(v => !value.includes(v.key));
  let childrenNode: any[] = [];
  children.map(k => {
    if (k.children && k.children.length>0) {
      k.children.map((v:any) => {
        if (value.includes(v.key)) {
          const node = {brandId: parseInt(k.key, 10), brandName: k.title, seriesId: v.key, seriesName: v.title};
          childrenNode.push(node);
        }
        return v;
      });
    }
    return k;
  });
  parent.map(k => {
    if (value.includes(k.key)) {
      childrenNode.push({brandId: parseInt(k.key, 10), brandName: k.title});
    }
    return k;
  });
  return childrenNode;
};
function updateTreeData(list: DataNode[], key: React.Key, children: DataNode[]): DataNode[] {
  return list.map(node => {
    if (node.key === key) {
      return {
        ...node,
        children,
      };
    }
    // if (node.children) {
    //   return {
    //     ...node,
    //     children: updateTreeData(node.children, key, children),
    //   };
    // }
    return node;
  });
}
  const onLoadData = async ({key, children} : any) => {
    if (children) {
      return;
    }
    const {data: childrenNode} = await getSeriesApi(parseInt(key, 10));
    const _childrenNode = (childrenNode || []).map((v:any) => { return {key: v.id, title: v.name, isLeaf: true}; });
    setTreeData((origin:any) => updateTreeData(origin, key, _childrenNode));
  };
  const handleCancel = () => {
    setChecked([]);
    setChecked([]);
  };
  const onFinsh = async () => {
    const param = await form.validateFields();
    const _param: any = {
      beginTime: (+moment(param.time[0], "YYYY-MM-DD HH:mm:ss").unix())*1000, // 开始时间
      endTime: (+moment(param.time[1], "YYYY-MM-DD HH:mm:ss").unix())*1000, // 结束时间
      brandId: param.brand.value, // 品牌id
      brandName: param.brand.label, // 品牌名称
      applyCarType: param.applyCarType, // 适用车辆范围
      sameBrandAmount: +param.sameBrandAmount, // 本品牌补贴金额
      diffBrandAmount: +param.diffBrandAmount, // 非本品牌补贴金额
      extraAmount: +param.extraAmount, // 4S店老客户升级置换额外享受补贴
      applyShops: param.applyShops.map((item:any) => { return {shopId: item.value, shopName: item.label}; }), // 门店列表
      subsidyDataUploadApply: beforeData.map((v:any) => { return {applyUpload: 1, dataType: v.dataType, dataName: v.dataName}; }), // 申请时上传资料
      subsidyType: 2,
      applyCarList: handleCarData(param.optionalAuth),
      containOrder: param.containOrder,
      insuranceRequire: param.insuranceRequire
    };
    if (checked.length === 0) {
      message.error("请选择本品牌范围!");
      return;
    } else if (!isNil(afterDay) && afterData.length === 0) {
      message.error("请勾选交车后N天内上传的资料!");
      return;
    } else if (param.insuranceRequire && isNil(insure[0].mustBuyTci)) {
      message.error("请选择是否购买交强险!");
      return;
    } else if (param.insuranceRequire && isNil(insure[0].mustBuyVci)) {
      message.error("请选择商是否购买商业险购!");
      return;
    } else if (param.insuranceRequire && isNil(insure[0].vciBuyAmount)) {
      message.error("请选择输入商业险金额!");
      return;
    }
    if (!isNil(afterDay)) {
      _param.deliveryAfterDays = afterDay;
      _param.subsidyDataUploadNDay = afterData.map((item: any) => { return {applyUpload: 0, dataType: item.dataType, dataName: item.dateName}; });
    }
    if (param.insuranceRequire) {
      _param.mustBuyTci = insure[0].mustBuyTci;
      _param.mustBuyVci = insure[0].mustBuyVci;
      _param.vciBuyAmount = insure[0].vciBuyAmount;
    }
    if (param.applyCarType === 2) {
      _param.applySpecList = param.applySeriesList.map((item:any) => { return {seriesId: item.value, seriesName: item.label}; });
    }
    const sameBrandRange = brandList(checked);
    _param.sameBrandRange = sameBrandRange;
    setLoading(true);
    saveReplacementApi(_param)
    .then(res => {
      message.success(res.result);
      setLoading(false);
    })
    .catch(e => {
      message.error(e.message);
      setLoading(false);
    });
  };

    /**
   * 选择车辆范围回调
   * @param value 车辆树形结构
   */
  function handleChange(value: CarAuthList[] = []) {
    const brandIds: number[] = [];
    const seriesIds: number[] = [];
    const specIds: number[] = [];
    value.forEach(v => {
      if (v.children) {
        v.children.forEach(k => {
          if (k.children) {
            const spec = k.children.map(q => q.specId);
            specIds.push(...spec);
          } else {
            seriesIds.push(k.seriesId);
          }
        });
      } else {
        brandIds.push(v.brandId);
      }
    });
    const parmas = {
      brandIds,
      seriesIds,
      specIds
    };
    setCarSelectData(value || []);
    getShopScope(parmas);
    console.log(value);
  }

  /**
   * 获取所选车辆的授权门店范围
   * @param params 
   */
  function getShopScope(params: RequestShopParams) {
    setShopLoading(true);
    getShopApi(params)
    .then(res => {
      setShopLoading(false);
      setShopList(res.data || []);
    }).catch(e => {
      setShopLoading(false);
      setShopList([]);
      message.error(e.message);
    });
  }

  function handleInsureChange(name: string, value?: number) {
    setInsure([{...insure[0], [name]: value}]);
  }

  function resetInsure() {
    setInsure([{mustBuyTci: undefined, mustBuyVci: undefined, vciBuyAmount: undefined, id: 1}]);
  }

  /**
   * 将树形车辆结构转换成扁平结构
   * applyCarType为最细化层级的类型
   * @param value 
   * @returns 
   */
  function handleCarData(value: CarAuthList[]) {
    const result: any = [];
    let applyCarType = 1;
    value.forEach(v => {
      if (v.children) {
        v.children.forEach(k => {
          if (k.children) {
            k.children.forEach(r => {
              const item = {brandId: v.brandId, brandName: v.brandName, seriesId: k.seriesId, seriesName: k.seriesName, specId: r.specId, specName: r.specName};
              result.push(item);
              applyCarType = Math.max(applyCarType, 3);
            });
          } else {
            const item = {brandId: v.brandId, brandName: v.brandName, seriesId: k.seriesId, seriesName: k.seriesName};
            result.push(item);
            applyCarType = Math.max(applyCarType, 2);
          }
        });
      } else {
        const item = { brandId: v.brandId, brandName: v.brandName, applyCarType: v.authType};
        result.push(item);
        applyCarType = Math.max(applyCarType, 1);
      }
    });
    const _result = result.map((v: any) => ({...v, applyCarType}));
    return _result;
  }

  return (
    <PageHeaderWrapper title="置换补贴">
      <Card>
        <Row justify="center">
          <Col span={16}>
            <Form
              form={form}
            >
              <Form.Item
                name="optionalAuth"
                label="授权车辆范围"
                rules={[{ required: true, message: "选择车辆" }]}
                tooltip={<span style={{ color: '#ccc', fontSize: 12 }}>*点击图标<PlusSquareOutlined />展开授权详情</span>}
              >
                <CarTableTreeAuth value={carSelectData} onChange={handleChange} brandMultiple={false} />
              </Form.Item>
              <Form.Item
                label="适用门店"
                name="applyShops"
                labelAlign="left"
                rules={[{ required: true, message: "请选择适用门店" }]}
              >
                <Select mode="multiple" allowClear filterOption optionFilterProp="children" labelInValue placeholder="请选择" options={shopList.map(v => ({label: v.shopName, value: v.shopId}))} loading={shopLoading} />
              </Form.Item>
              <Form.Item name="time" label="有效时间" rules={[{ type: 'array' as const, required: true, message: '请选择有效时间!' }]}>
                <DatePicker.RangePicker showTime style={{width: "100%"}} />
              </Form.Item>
              <Form.Item name="sameBrandAmount" label="补贴金额(本品牌)" rules={[{required: true, pattern: /^(\d+|\d+\.\d{1,2})$/, message: "请输入正确的本品牌补贴金额!"}]}>
                <Input placeholder="请输入本品牌补贴金额" suffix="元" />
              </Form.Item>
              <Form.Item name="diffBrandAmount" label="补贴金额(非本品牌)" rules={[{required: true, pattern: /^(\d+|\d+\.\d{1,2})$/, message: "请输入正确的非本品牌补贴金额!"}]}>
                <Input placeholder="请输入非本品牌补贴金额" suffix="元" />
              </Form.Item>
              <Form.Item name="sameBrandRange" label="本品牌范围" rules={[{required: true, message: "请选择本品牌范围!"}]}>
                <Tree
                  height={330}
                  checkable
                  onCheck={(value) => onCheck(value)}
                  checkedKeys={checked || []}
                  loadData={onLoadData}
                  treeData={treeData}
                />
              </Form.Item>
              <Form.Item name="extraAmount" label="4S店老客户升级置换额外享受补贴" rules={[{required: true, pattern: /^(\d+|\d+\.\d{1,2})$/, message: "请输入正确的补贴值!"}]}>
                <Input />
              </Form.Item>
              <Form.Item labelAlign="left" label="保险要求" name="insuranceRequire" rules={[{required: true, message: "请选择保险要求!"}]}>
                <Radio.Group onChange={resetInsure}>
                  <Radio value={false}>无要求</Radio>
                  <Radio value>有要求</Radio>
                </Radio.Group>
              </Form.Item>
              <Form.Item
                noStyle
                shouldUpdate={(prevValues, curValues) => prevValues.insuranceRequire !== curValues.insuranceRequire}
              >
                {({ getFieldValue }) => {
                const bool = getFieldValue('insuranceRequire');
                return bool ? (
                  <Card>
                    <Table pagination={false} dataSource={insure} rowKey="id">
                      <Table.Column
                        title="交强险"
                        dataIndex="mustBuyTci"
                        render={(_text, record) => <Select value={_text} onChange={(e) => handleInsureChange("mustBuyTci", e)} placeholder="请选择" options={Requirements} />}
                      />
                      <Table.Column
                        title="商业险"
                        dataIndex="mustBuyVci"
                        render={(_text, record) => <Select value={_text} onChange={e => handleInsureChange("mustBuyVci", e)} placeholder="请选择" options={Requirements} />}
                      />
                      <Table.Column
                        title="商业险金额(≥元)"
                        dataIndex="vciBuyAmount"
                        render={(_text, record) => <InputNumber value={_text} onChange={e => handleInsureChange("vciBuyAmount", e)} controls={false} min={0} precision={2} placeholder="请输入金额" />}
                      />
                    </Table>
                  </Card>
                ) : null;
              }}
              </Form.Item>
              <Form.Item labelAlign="left" label="政策适用范围" name="containOrder" rules={[{required: true, message: "请选择政策适用范围!"}]}>
                <Radio.Group>
                  <Radio value>是</Radio>
                  <Radio value={false}>否</Radio>
                </Radio.Group>
              </Form.Item>
              <Form.Item
                labelAlign="left"
                label="置换补贴资料"
                required
              />
              <NewDataModal checked={afterData} selectData={beforeData} setSelectData={setBeforeData} />
              <NewDataModal postData checked={beforeData} selectData={afterData} setSelectData={setAfterData} afterDay={afterDay} setAfterDay={setAfterDay} />
            </Form>
            <Row justify="center">
              <Space>              
                <Button key="cancel" onClick={handleCancel} style={{marginLeft: 10}}>取消</Button>
                <Button key="submit" onClick={onFinsh} type="primary" htmlType="submit" loading={loading}>确认</Button>
              </Space>
            </Row>
          </Col>
        </Row>
      </Card>
    </PageHeaderWrapper>
  );
}