/* eslint-disable react-hooks/exhaustive-deps */
import React, { useState, useRef, memo, createElement, useEffect, useMemo } from 'react';
import {
  ProForm,
  ProFormDependency,
  ProFormSelect,
  ProFormText,
  ProFormMoney,
  ProFormTextArea,
  ProFormDigit,
  ProFormDigitRange,
  ProFormDatePicker,
  ProFormDateTimePicker,
  ProFormDateRangePicker,
  ProFormDateTimeRangePicker,
  ProFormTimePicker,
  ProFormTreeSelect,
  ProFormCheckbox,
  ProFormRadio,
  ProFormCascader,
  ProFormSwitch,
  ProFormRate,
  ProFormSlider,
  ProFormUploadDragger,
  ProFormUploadButton,
  ProFormList,
  ProCard,
  CheckCard,
  ProFormFieldSet,
} from '@ant-design/pro-components';
import ImgCrop from 'antd-img-crop';
import { doFetch } from '@/utils/doFetch';
import moment from 'moment';
import { useAsyncEffect, useRequest } from 'ahooks';
import * as Antd from 'antd';
import { PlusOutlined, DownOutlined, CloseOutlined, RedoOutlined } from '@ant-design/icons';
import BraftEditor from 'braft-editor';
import EditTable from './EditTable';
import EditorItem from './EditorItem';
import Diyrule from './Diyrule';
import defaultSetting from '../../../config/defaultSettings';
import Expandables from './Expandable';
const {
  Image,
  Form,
  Upload,
  Col,
  Pagination,
  Avatar,
  Dropdown,
  Menu,
  Tabs,
  message,
  AutoComplete,
  Row,
} = Antd;
const AntdCheckBox = Antd.Checkbox;

const FormItems = {
  Input,
  Password,
  Money,
  Textarea,
  Digit,
  DigitRange,
  Date,
  Time,
  DateTime,
  DateWeek,
  DateMonth,
  DateQuarter,
  DateYear,
  DateRange,
  TimeRange,
  DateTimeRange,
  Select,
  TreeSelect,
  Checkbox,
  Radio,
  Switch,
  Cascader,
  Rate,
  Slider,
  UploadBtn,
  UploadImage,
  UploadDragger,
  Editor,
  Diyrules,
  FormList,
  FormSelectList,
  CheckboxItem,
  RadioItem,
  MyAutoComplete,
  Expandable,
};
function upperCase(str) {
  const newStr = str.slice(0, 1).toUpperCase() + str.slice(1);
  return newStr;
}
// tree遍历
function treeForeach(tree, func) {
  tree.forEach((data) => {
    func(data);
    data.children && treeForeach(data.children, func); // 遍历子树
  });
}

let FormRender = memo(({ fields = [], name, curindex, formRef }) => {
  return (
    <>
      {fields
        .filter((it) => it.hideInForm !== true)
        .map((item, index) => {
          let key = item?.valueType ? upperCase(item?.valueType) : 'Input';
          let { hideInForm } = item;
          if (hideInForm && Object.keys(hideInForm)) {
            return (
              <ProFormDependency name={Object.keys(hideInForm)}>
                {(params) => {
                  let ifs = true;
                  let res = Object.keys(hideInForm).map((its) => {
                    if (Array.isArray(hideInForm[its])) {
                      return !hideInForm[its].includes(params[its]);
                    } else {
                      let vals = hideInForm[its].reverse; //取反 即不存在当前数组中的
                      return vals.indexOf(params[its]) != -1;
                    }
                  });
                  ifs = res.includes(false);
                  if (ifs) {
                    return (
                      <Col {...item.colProps}>
                        {curindex == 0 ? (
                          <p>
                            <label htmlFor="">{item.title}</label>
                            <p style={{ padding: '6px 0 0 0', margin: 0 }}>
                              <b style={{ color: 'red' }}>!</b> 需满足条件才可以填写{item.title}
                            </p>
                          </p>
                        ) : (
                          <p style={{ padding: '4px 0 0 0', margin: 0 }}>
                            <b style={{ color: 'red' }}>!</b> 需满足条件才可以填写{item.title}
                          </p>
                        )}
                      </Col>
                    );
                  } else {
                    return (
                      <>
                        {createElement(FormItems[key], {
                          item: item,
                          colProps: item.colProps,
                          key: item?.dataIndex,
                          name: name,
                          formRef,
                          curindex,
                        })}
                      </>
                    );
                  }
                }}
              </ProFormDependency>
            );
          } else {
            return (
              <>
                {createElement(FormItems[key], {
                  item: item,
                  colProps: item.colProps,
                  key: item?.dataIndex,
                  name: name,
                  formRef,
                  curindex,
                })}
              </>
            );
          }
        })}
    </>
  );
});

// colProps 默认删格
function Input({ item, colProps }) {
  let keys = item?.key ?? item?.dataIndex ?? '';
  const defaultrule =
    keys.indexOf('phone') != -1
      ? {
          pattern: /^(((\d{3,4}-)?[0-9]{7,8})|(1(3|4|5|6|7|8|9)\d{9}))$/,
          message: item.title + '格式不正确',
        }
      : keys.indexOf('mail') != -1
      ? {
          pattern: /^[a-z0-9A-Z]+[- | a-z0-9A-Z . _]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-z]{2,}$/,
          message: '邮箱格式不正确',
        }
      : {};

  return (
    <>
      <ProFormText
        fieldProps={item?.fieldProps}
        formItemProps={{
          ...item.formItemProps,
          rules: [defaultrule, ...(item?.formItemProps?.rules ?? [])],
        }} //手机号邮箱自带验证
        name={keys}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
      />
    </>
  );
}

function MyAutoComplete({ item, colProps, formRef }) {
  const [options, setoptions] = useState([]);
  const [username, setusername] = useState();
  const { data, run, runAsync } = useRequest(
    async () => {
      let res = await doFetch({
        url: '/auth/sysUser/queryLikeIotUsername',
        params: { username },
      });
      return res?.data?.dataList;
    },
    {
      manual: true,
      debounceWait: 300,
    },
  );
  useEffect(() => {
    runAsync()
      .then((data) => {
        const options = data?.map((it) => ({
          ...it,
          label: `${it?.username}-${it?.fullName}`,
          value: `${it?.username}-${it?.fullName}`,
        }));
        setoptions(options);
      })
      .catch((error) => {
        console.log(error);
      });
  }, [username]);
  let col = item.colProps ?? colProps;
  let curkey = item?.key ?? item?.dataIndex;
  return (
    <Col span={12}>
      <ProForm.Item name={curkey} label={item.title} {...item.formItemProps}>
        <AutoComplete
          formRef={formRef}
          allowClear={true}
          style={{ width: '100%' }}
          disabled={item?.disabled}
          colProps={item.colProps ?? colProps}
          onSearch={(e) => {
            setusername(e);
          }}
          options={options}
          onSelect={item?.onSelect}
          {...item?.fieldProps}
        />
      </ProForm.Item>
      {/* createElement(children,{props:value,onChange}) */}
    </Col>
  );
}

//pwd
function Password({ item, colProps }) {
  return (
    <>
      <ProFormText.Password
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
      />
    </>
  );
}
//money
function Money({ item, colProps }) {
  return (
    <>
      <ProFormMoney
        locale="zh-CN"
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
        min={item.min}
        max={item.max}
      />
    </>
  );
}

//textarea
function Textarea({ item, colProps }) {
  return (
    <>
      <ProFormTextArea
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? { span: 24 }}
        label={item.title}
        placeholder={`请输入${item.title}`}
      />
    </>
  );
}

//digit
function Digit({ item, colProps }) {
  return (
    <>
      <ProFormDigit
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
        min={item.min}
        max={item.max}
        fieldProps={{ precision: item.precision ?? 2, ...(item?.fieldProps ?? {}) }}
      />
    </>
  );
}

//digitrange
function DigitRange({ item, colProps }) {
  return (
    <>
      <ProFormDigitRange
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={['请输入最小值', '请输入最大值']}
        min={item.min}
        max={item.max}
        fieldProps={{ precision: item.precision ?? 0, ...(item?.fieldProps ?? {}) }}
      />
    </>
  );
}

//Date
function Date({ item, colProps }) {
  return (
    <>
      <ProFormDatePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}

function DateWeek({ item, colProps }) {
  const weekFormat = 'YYYY-MM-DD';
  const customWeekStartEndFormat = (value) =>
    `${moment(value).startOf('week').format(weekFormat)} ~ ${moment(value)
      .endOf('week')
      .format(weekFormat)}`;
  return (
    <>
      <ProFormDatePicker
        fieldProps={{ ...item?.fieldProps, picker: 'week', format: customWeekStartEndFormat }}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//DateMonth
function DateMonth({ item, colProps }) {
  return (
    <>
      <ProFormDatePicker
        fieldProps={{ ...item?.fieldProps, picker: 'month', format: 'YYYY-MM' }}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//DateQuarter
function DateQuarter({ item, colProps }) {
  const quarterFormat = 'YYYY-MM-DD';
  const customWeekStartEndFormat = (value) =>
    `${moment(value).startOf('quarter').format(quarterFormat)} ~ ${moment(value)
      .endOf('quarter')
      .format(quarterFormat)}`;
  return (
    <>
      <ProFormDatePicker
        fieldProps={{ ...item?.fieldProps, picker: 'quarter', format: customWeekStartEndFormat }}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//DateYear
function DateYear({ item, colProps }) {
  return (
    <>
      <ProFormDatePicker
        fieldProps={{ ...item?.fieldProps, picker: 'year', format: 'YYYY' }}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}

//dateTime
function DateTime({ item, colProps }) {
  return (
    <>
      <ProFormDateTimePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//DateRange
function DateRange({ item, colProps }) {
  return (
    <>
      <ProFormDateRangePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={['请选择开始日期', '请选择结束日期']}
        width="100%"
      />
    </>
  );
}
//dateTimeRange
function DateTimeRange({ item, colProps }) {
  return (
    <>
      <ProFormDateTimeRangePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={['请选择开始时间', '请选择结束时间']}
        width="100%"
      />
    </>
  );
}
//Time
function Time({ item, colProps }) {
  return (
    <>
      <ProFormTimePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//TimeRange
function TimeRange({ item, colProps }) {
  return (
    <>
      <ProFormTimePicker.RangePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={['请选择开始时间', '请选择结束时间']}
        width="100%"
      />
    </>
  );
}

function LinkSelect({ item, colProps, formRef, name, curindex }) {
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}, //获取linkParams下声明的key
    extraParams = curoption?.extraParams ?? {};
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item?.key ?? item?.dataIndex;
          return (
            <ProFormSelect
              convertValue={(value) => {
                return item?.fieldProps?.mode == 'multiple' ? (!value ? [] : null) : null;
              }}
              fieldProps={item?.fieldProps}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              request={async (parse) => {
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key] ? key : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: { ...result, ...extraParams },
                });
                if (name) {
                  let curvals = formRef?.current?.getFieldValue(name);
                  curvals = curvals.map((it, i) => {
                    if (i == curindex) {
                      it[curkey] = null;
                    }
                    return it;
                  });
                  formRef?.current?.setFieldsValue({ [name]: curvals });
                } else {
                  let curval = formRef?.current?.getFieldValue(curkey),
                    ifclean;
                  if (Array.isArray(curval)) {
                    ifclean = res?.data?.dataList
                      ?.map((it) => it.value)
                      .filter?.((it) => {
                        return curval?.includes(it);
                      });
                  } else {
                    ifclean = res?.data?.dataList.filter((it) => it.value == curval)?.[0]?.value;
                  }
                  //console.log(
                  //   curval,
                  //   res?.data?.dataList?.map((it) => it.value),
                  //   curkey,
                  // );

                  formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                }
                return res?.data?.dataList ?? [];
              }}
              showSearch
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkSelect({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async (params) => {
        let list = await doFetch({ url: curoption?.path, params: curoption?.params });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormSelect
        fieldProps={item.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        showSearch
        {...options}
      />
    </>
  );
}

//Select 高阶组建
function Select(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkSelect {...props} />;
  } else {
    return <NolinkSelect {...props} />;
  }
}

function LinkTreeSelect({ item, colProps, formRef, name, curindex }) {
  let prevparse = useRef();
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}, //获取linkParams下声明的key
    extraParams = curoption?.extraParams ?? {};
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item?.key ?? item?.dataIndex;
          return (
            <ProFormTreeSelect
              fieldProps={{
                ...item?.fieldProps,
                fieldNames: { label: 'title', value: 'key', children: 'children' },
                showSearch: false,
              }}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              request={async (parse) => {
                delete parse.keyWords;
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key] ? key : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: { ...result, ...extraParams },
                });

                if (prevparse.current !== JSON.stringify(parse)) {
                  if (name) {
                    let curvals = formRef?.current?.getFieldValue(name);
                    curvals = curvals.map((it, i) => {
                      if (i == curindex) {
                        it[curkey] = null;
                      }
                      return it;
                    });
                    formRef?.current?.setFieldsValue({ [name]: curvals });
                  } else {
                    let curval = formRef?.current?.getFieldValue(curkey),
                      ifclean;
                    //树结构所有value提取到数组
                    let allvalue = [];
                    treeForeach(res?.data?.dataList, (node) => {
                      allvalue.push(node?.key);
                    });

                    //过滤存在的value
                    if (Array.isArray(curval)) {
                      ifclean = allvalue?.filter?.((it) => {
                        return curval?.includes(it);
                      });
                    } else {
                      ifclean = allvalue?.filter?.((it) => it == curval)?.[0];
                    }

                    formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                  }
                }
                prevparse.current = JSON.stringify(parse);
                return res?.data?.dataList ?? [];
              }}
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkTreeSelect({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async (params) => {
        let list = await doFetch({ url: curoption?.path, params: curoption?.params });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormTreeSelect
        fieldProps={{
          ...item?.fieldProps,
          allowClear: true,
          fieldNames: { label: 'title', value: 'key', children: 'children' },
          showSearch: true,
        }}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        {...options}
      />
    </>
  );
}

//TreeSelect 高阶组建
function TreeSelect(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkTreeSelect {...props} />;
  } else {
    return <NolinkTreeSelect {...props} />;
  }
}

function CheckboxItem({ item, colProps }) {
  return (
    <>
      <ProFormCheckbox
        fieldProps={item.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
      />
    </>
  );
}

function LinkCheckbox({ item, colProps, formRef, name, curindex }) {
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}, //获取linkParams下声明的key
    extraParams = curoption?.extraParams ?? {};
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item?.key ?? item?.dataIndex;
          return (
            <ProFormCheckbox.Group
              fieldProps={item?.fieldProps}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              request={async (parse) => {
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key] ? key : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: { ...result, ...extraParams },
                });
                if (name) {
                  let curvals = formRef?.current?.getFieldValue(name);
                  curvals = curvals.map((it, i) => {
                    if (i == curindex) {
                      it[curkey] = null;
                    }
                    return it;
                  });
                  formRef?.current?.setFieldsValue({ [name]: curvals });
                } else {
                  let curval = formRef?.current?.getFieldValue(curkey),
                    ifclean;
                  if (Array.isArray(curval)) {
                    ifclean = res?.data?.dataList
                      ?.map((it) => it.value)
                      .filter?.((it) => {
                        return curval?.includes(it);
                      });
                  } else {
                    ifclean = res?.data?.dataList.filter((it) => it.value == curval)?.[0]?.value;
                  }
                  formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                }
                return res?.data?.dataList ?? [];
              }}
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkCheckbox({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async (params) => {
        let list = await doFetch({ url: curoption?.path, params: curoption?.params });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormCheckbox.Group
        fieldProps={item.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        {...options}
      />
    </>
  );
}

//Checkbox 高阶组建
function Checkbox(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkCheckbox {...props} />;
  } else {
    return <NolinkCheckbox {...props} />;
  }
}

function RadioItem({ item, colProps }) {
  return (
    <>
      <ProFormRadio
        fieldProps={item.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
      />
    </>
  );
}

function LinkRadio({ item, colProps, formRef, name, curindex }) {
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}, //获取linkParams下声明的key
    extraParams = curoption?.extraParams ?? {};
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item?.key ?? item?.dataIndex;
          return (
            <ProFormRadio.Group
              fieldProps={item?.fieldProps}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              request={async (parse) => {
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key] ? key : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: { ...result, ...extraParams },
                });
                if (name) {
                  let curvals = formRef?.current?.getFieldValue(name);
                  curvals = curvals.map((it, i) => {
                    if (i == curindex) {
                      it[curkey] = null;
                    }
                    return it;
                  });
                  formRef?.current?.setFieldsValue({ [name]: curvals });
                } else {
                  let curval = formRef?.current?.getFieldValue(curkey),
                    ifclean;
                  if (Array.isArray(curval)) {
                    ifclean = res?.data?.dataList
                      ?.map((it) => it.value)
                      .filter?.((it) => {
                        return curval?.includes(it);
                      });
                  } else {
                    ifclean = res?.data?.dataList.filter((it) => it.value == curval)?.[0]?.value;
                  }
                  formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                }
                return res?.data?.dataList ?? [];
              }}
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkRadio({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async (params) => {
        let list = await doFetch({ url: curoption?.path, params: curoption?.params });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormRadio.Group
        fieldProps={item.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        {...options}
      />
    </>
  );
}

//Radio 高阶组建
function Radio(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkRadio {...props} />;
  } else {
    return <NolinkRadio {...props} />;
  }
}

function LinkCascader({ item, colProps, formRef, name, curindex }) {
  let prevparse = useRef();
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}, //获取linkParams下声明的key
    extraParams = curoption?.extraParams ?? {};
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item?.key ?? item?.dataIndex;
          return (
            <ProFormCascader
              fieldProps={{
                ...item?.fieldProps,
                fieldNames: { label: 'title', value: 'key', children: 'children' },
                showSearch: false,
              }}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              request={async (parse) => {
                delete parse.keyWords;
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key] ? key : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: { ...result, ...extraParams },
                });
                if (prevparse.current !== JSON.stringify(parse)) {
                  if (name) {
                    let curvals = formRef?.current?.getFieldValue(name);
                    curvals = curvals.map((it, i) => {
                      if (i == curindex) {
                        it[curkey] = null;
                      }
                      return it;
                    });
                    formRef?.current?.setFieldsValue({ [name]: curvals });
                  } else {
                    let curval = formRef?.current?.getFieldValue(curkey),
                      ifclean;
                    if (Array.isArray(curval)) {
                      ifclean = res?.data?.dataList
                        ?.map((it) => it.value)
                        .filter?.((it) => {
                          return curval?.includes(it);
                        });
                    } else {
                      ifclean = res?.data?.dataList.filter((it) => it.value == curval)?.[0]?.value;
                    }
                    formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                  }
                }
                prevparse.current = JSON.stringify(parse);
                return res?.data?.dataList ?? [];
              }}
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkCascader({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async (params) => {
        let list = await doFetch({ url: curoption?.path, params: curoption?.params });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormCascader
        fieldProps={{
          ...item?.fieldProps,
          fieldNames: { label: 'title', value: 'key', children: 'children' },
          showSearch: true,
        }}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        {...options}
      />
    </>
  );
}

//Cascader 高阶组建
function Cascader(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkCascader {...props} />;
  } else {
    return <NolinkCascader {...props} />;
  }
}

//switch
function Switch({ item, colProps }) {
  return (
    <>
      <ProFormSwitch
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
      />
    </>
  );
}

//Rate
function Rate({ item, colProps }) {
  return (
    <>
      <ProFormRate
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
      />
    </>
  );
}

//Slider
function Slider({ item, colProps }) {
  return (
    <>
      <ProFormSlider
        {...item?.fieldProps}
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
      />
    </>
  );
}

//uploadbtn
function UploadBtn({ item, colProps }) {
  let token = `Bearer ${localStorage.getItem('TOKENES')}`;
  return (
    <>
      <ProFormUploadButton
        fieldProps={{
          ...item?.fieldProps,
          action: defaultSetting.proxypath + '/base/sysAttachment/uploadFile',
          headers: { Authorization: token },
          onPreview: (file) => {
            let url = '';
            if (file.response) {
              url = file.response.data.dataList[0].url;
            } else if (file.url) {
              url = file.url;
            } else {
              url = file.thumbUrl;
            }
            window.open(url);
          },
        }}
        transform={(value) => {
          const key = item?.key ?? item?.dataIndex;
          const transvalue = value?.map((it) => {
            if (it.response) {
              return it?.response?.data?.dataList[0];
            } else {
              return it;
            }
          });
          return {
            [key]: transvalue,
          };
        }}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        title={`上传${item.title}`}
        max={item.max}
      />
    </>
  );
}

function UploadImg({ value, onChange, fieldProps }) {
  let token = `Bearer ${localStorage.getItem('TOKENES')}`;
  const [image, setImage] = useState({});
  function beforeUpload(file) {
    const isJpgOrPng =
      file.type === 'image/jpg' || file.type === 'image/jpeg' || file.type === 'image/png';
    if (!isJpgOrPng) {
      message.error('只能上传.jpg/.jpeg/.png图片!');
      return;
    }
    return true;
  }

  // maxCount 最大数量
  const defaultconfig = {
    name: 'file',
    action: defaultSetting.proxypath + '/base/sysAttachment/uploadFile',
    accept: '.jpg,.png,.jpeg',
    listType: 'picture-card',
    beforeUpload: beforeUpload,
    defaultFileList: value,
    headers: { Authorization: token },
    onChange(info) {
      let {
        file: { name, status, response },
        fileList,
        event,
      } = info;
      if (status == 'error') {
        message.error(`${info.file.name} 上传失败`);
      } else if (status === 'done') {
        const transfile = fileList.map((it) => {
          return it?.response ? it?.response?.data?.dataList[0] : it;
        });
        onChange(transfile);
      }
    },
    onRemove(file) {
      let uid = file?.response?.data?.dataList[0]?.uid ?? file?.uid;
      let newvalue = value?.filter((it) => it.uid != uid);
      onChange(newvalue);
    },
    onPreview(file) {
      let url = '';
      if (file.response) {
        url = file.response.data.dataList[0].url;
      } else if (file.url) {
        url = file.url;
      } else {
        url = file.thumbUrl;
      }
      setImage({
        url,
        visible: true,
      });
    },
  };

  const uploadButton = (
    <div>
      <PlusOutlined />
      <div style={{ marginTop: 8 }}>上传图片</div>
    </div>
  );
  //console.log(value?.length, fieldProps.limit);
  return (
    <>
      <Image
        src={image.url}
        width={0}
        height={0}
        preview={{
          visible: image?.visible,
          onVisibleChange: (e) => {
            if (image?.visible) {
              setImage((s) => ({
                ...s,
                visible: false,
              }));
            }
          },
        }}
      />
      {fieldProps?.crop ? (
        <ImgCrop
          rotate
          grid
          quality={1}
          shape={fieldProps?.crop?.shape ?? 'rect'} //裁切区域形状，'rect' 或 'round'
          aspect={fieldProps?.crop?.aspect ?? 1 / 1} //裁切区域宽高比，width / height
        >
          <Upload {...defaultconfig}>
            {!value ? uploadButton : value?.length < fieldProps.limit ? uploadButton : null}
          </Upload>
        </ImgCrop>
      ) : (
        <Upload {...defaultconfig}>
          {!value ? uploadButton : value?.length < fieldProps.limit ? uploadButton : null}
        </Upload>
      )}
    </>
  );
}

//upload Image
function UploadImage({ item, colProps }) {
  let col = item.colProps ?? colProps;
  return (
    <Col {...col}>
      <Form.Item name={item?.key ?? item?.dataIndex} label={item.title} {...item.formItemProps}>
        <UploadImg fieldProps={{ ...item?.fieldProps }} />
      </Form.Item>
    </Col>
  );
}

// uploadDragger
function UploadDragger({ item, colProps }) {
  let token = `Bearer ${localStorage.getItem('TOKENES')}`;
  return (
    <>
      <ProFormUploadDragger
        fieldProps={{
          ...item?.fieldProps,
          action: defaultSetting.proxypath + '/base/sysAttachment/uploadFile',
          headers: { Authorization: token },
          onPreview: (file) => {
            let url = '';
            if (file.response) {
              url = file.response.data.dataList[0].url;
            } else if (file.url) {
              url = file.url;
            } else {
              url = file.thumbUrl;
            }
            window.open(url);
          },
        }}
        transform={(value) => {
          const key = item?.key ?? item?.dataIndex;
          const transvalue = value?.map((it) => {
            if (it.response) {
              return it?.response?.data?.dataList[0];
            } else {
              return it;
            }
          });
          return {
            [key]: transvalue,
          };
        }}
        formItemProps={item.formItemProps}
        name={item?.key ?? item?.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
      />
    </>
  );
}

// editor
function Editor({ item, colProps, formRef }) {
  let col = item.colProps ?? colProps;
  let curkey = item?.key ?? item?.dataIndex;
  return (
    <Col {...col}>
      <ProForm.Item
        // convertValue={(value) => {
        //   return BraftEditor.createEditorState(value);
        // }}
        transform={(value) => {
          return {
            [curkey]: value && value?.toHTML?.(),
          };
        }}
        name={curkey}
        label={item.title}
        {...item.formItemProps}
      >
        <EditorItem
          serverURL={defaultSetting.proxypath + '/base/sysAttachment/uploadFile'}
          item={item}
          params={item.params}
          formRef={formRef}
          curkey={curkey}
        />
      </ProForm.Item>
    </Col>
  );
}

// editor
function Diyrules({ item, colProps, formRef }) {
  let col = item.colProps ?? colProps;
  let curkey = item?.key ?? item?.dataIndex;
  return (
    <Col {...col}>
      <ProForm.Item
        convertValue={(value) => {
          if (value?.other) return value;
          let nrList = {
            other: { increaseList: [] },
            value: [],
          };
          value?.forEach?.((it) => {
            if (it?.noRuleCode == 'increasing_order') {
              nrList.other = it;
            } else {
              nrList.value.push(it);
            }
          });
          return nrList;
        }}
        name={curkey}
        label={item.title}
        {...item.formItemProps}
      >
        <Diyrule />
      </ProForm.Item>
    </Col>
  );
}

function Expandable({ item, colProps }) {
  let col = item.colProps ?? colProps;
  let curkey = item?.key ?? item?.dataIndex;
  return (
    <Col {...col} style={{ marginBottom: 16 }}>
      <ProForm.Item name={curkey} label={item.title} {...item.formItemProps}>
        <Expandables item={item} key={item} />
      </ProForm.Item>
    </Col>
  );
}

function FormList({ item, colProps, formRef }) {
  let col = item.colProps ?? colProps;
  let fields = item.columns;

  return (
    <Col {...col}>
      <ProFormList
        name={item?.key ?? item?.dataIndex}
        label={item.title}
        min={item.min ?? 0}
        max={item.max ?? 100}
        itemContainerRender={(doms) => {
          return <ProForm.Group>{doms}</ProForm.Group>;
        }}
        alwaysShowItemLabel={false}
        copyIconProps={false}
      >
        {(f, index, action) => {
          return (
            <FormRender
              fields={fields}
              action={action}
              curindex={index}
              formRef={formRef}
              name={item?.key ?? item?.dataIndex}
            />
          );
        }}
      </ProFormList>
    </Col>
  );
}

const Todo = ({ actionRef, value = [], item, params, rowKey, chooses, onChange }) => {
  return (
    <>
      <EditTable
        // loading={false}
        actionRef={actionRef}
        defaultValue={value} //调用接口合并初始值
        path={item.path}
        extraparams={params ?? {}}
        rowKey={rowKey}
        key={value}
        columns={item.columns}
        resizeable={false}
        alwaysShowAlert={false}
        tableAlertRender={false}
        tableAlertOptionRender={false}
        rowClassName={(record, index) => {
          if (chooses.includes(record[rowKey])) {
            return 'lightblue';
          } else {
            return '';
          }
        }}
        rowSelection={{
          ...item.rowSelection,
          columnWidth: 44,
          preserveSelectedRowKeys: true,
          selectedRowKeys: value && value?.map((it) => it[rowKey]),
          onChange: (selectedKeys, selectedRows) => {
            // console.log('row', selectedRows, 'selectkey:', selectedKeys);
            // console.log('value:', value);
            const rowkeylist = value ? value?.map((it) => it[rowKey]) : [];
            // console.log('rowkeyList:', rowkeylist);
            const newValue = selectedRows?.map((its) => {
              if (rowkeylist.includes(its[rowKey])) {
                return value.filter((it) => it[rowKey] == its[rowKey])[0];
              } else {
                return its;
              }
            });
            // console.log('newValue:', newValue);
            onChange(newValue);
          },
        }}
        editable={{
          onValuesChange: (record, recordList) => {
            const newValue = value?.map((its) => {
              if (its[rowKey] == record[rowKey]) {
                return record;
              } else {
                return its;
              }
            });
            // console.log('edit-newvalue:', newValue);
            onChange(newValue);
          },
        }}
      />
    </>
  );
};

const Done = ({ actionRef, value, item, params, rowKey, chooses, onChange }) => {
  return (
    <EditTable
      value={value}
      rowKey={rowKey}
      columns={item.columns}
      resizeable={false}
      alwaysShowAlert={false}
      tableAlertRender={false}
      tableAlertOptionRender={false}
      rowClassName={(record, index) => {
        if (chooses.includes(record[rowKey])) {
          return 'lightblue';
        } else {
          return '';
        }
      }}
      rowSelection={{
        ...item.rowSelection,
        columnWidth: 44,
        preserveSelectedRowKeys: true,
        selectedRowKeys: value && value?.map((it) => it[rowKey]),
        onChange: (selectedKeys, selectedRows) => {
          const rowkeylist = value ? value?.map((it) => it[rowKey]) : [];
          const newValue = selectedRows?.map((its) => {
            if (rowkeylist.includes(its[rowKey])) {
              return value.filter((it) => it[rowKey] == its[rowKey])[0];
            } else {
              return its;
            }
          });
          onChange(newValue);
        },
      }}
      editable={{
        onValuesChange: (record, recordList) => {
          const newValue = value?.map((its) => {
            if (its[rowKey] == record[rowKey]) {
              return record;
            } else {
              return its;
            }
          });
          onChange(newValue);
        },
      }}
    />
  );
};

function TableSelect({ item, value, onChange, params = {} }) {
  const rowKey = item?.rowKey ?? 'id';
  const [chooses, setchooses] = useState([]); //mark 标记
  const [activetab, setactivetab] = useState(1);
  let actionRef = useRef();

  const menu = (selectedRows) => (
    <Menu
      style={{ width: 160 }}
      items={
        selectedRows.length > 0
          ? selectedRows.map((it) => ({
              key: it[rowKey],
              label: (
                <div
                  className="spread"
                  onClick={(e) => {
                    e.stopPropagation();
                    let key = it[rowKey];
                    setchooses((s) => {
                      let news = [...s];
                      if (s.includes(key)) {
                        news = news.filter((it) => {
                          return it != key;
                        });
                      } else {
                        news.push(key);
                      }
                      return news;
                    });
                  }}
                >
                  <span
                    style={{
                      color: chooses.includes(it[rowKey]) ? '#1890ff' : '#333333',
                      transition: 'all 0.4s',
                      userSelect: 'none',
                    }}
                  >
                    {it[item.rowName]}
                  </span>
                  <CloseOutlined
                    onClick={(e) => {
                      e.stopPropagation();
                      let newvalue = value.filter((its) => its[rowKey] != it[rowKey]);
                      onChange(newvalue);
                      setchooses((s) => {
                        let news = [...s];
                        news = news.filter((its) => {
                          return its != it[rowKey];
                        });
                        return news;
                      });
                    }}
                  />
                </div>
              ),
            }))
          : [
              {
                key: -1,
                label: '请先选择',
              },
            ]
      }
    />
  );

  const propes = {
    actionRef,
    value,
    item,
    params,
    rowKey,
    chooses,
    onChange,
  };
  return (
    <div className="selecttable">
      <Tabs
        destroyInactiveTabPane={true}
        tabBarExtraContent={
          <div className="center">
            <Dropdown overlay={menu(value ?? [])}>
              <a>
                已选择{value?.length ?? 0}项 <DownOutlined />
              </a>
            </Dropdown>
            <div
              className="center"
              style={{ color: 'red', cursor: 'pointer', margin: '0 6px 0 16px' }}
              onClick={() => {
                onChange([]);
                setchooses([]);
              }}
            >
              <RedoOutlined rotate={-90} />
              清空
            </div>
          </div>
        }
        onChange={setactivetab}
        items={[
          { label: '数据选择', key: 1 },
          { label: `选择结果${value?.length ?? 0}项`, key: 2 },
        ]}
      />
      {activetab == 1 && <Todo {...propes} />}
      {activetab == 2 && <Done {...propes} />}
    </div>
  );
}

function LinkSelectList({ item, colProps, formRef, name, curindex }) {
  let col = item.colProps ?? colProps;
  let curlinkparams = item?.linkParams ?? {}; //获取linkParams下声明的key
  return (
    <Col {...col}>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item?.key ?? item?.dataIndex;
          let result = {};
          for (let key in curlinkparams) {
            let reversekey = !curlinkparams[key] ? key : curlinkparams[key];
            result[reversekey] = params[key];
          }
          return (
            <Form.Item name={curkey} label={item.title} {...item.formItemProps}>
              <TableSelect item={item} params={result} />
            </Form.Item>
          );
        }}
      </ProFormDependency>
    </Col>
  );
}

function NolinkSelectList({ item, colProps, formRef }) {
  let col = item.colProps ?? colProps;
  let curkey = item?.key ?? item?.dataIndex; //获取key
  return (
    <Col {...col}>
      <Form.Item name={curkey} label={item.title} {...item.formItemProps}>
        <TableSelect item={item} params={item.params} />
      </Form.Item>
    </Col>
  );
}

function FormSelectList(props) {
  let ifs = props?.item?.linkParams;
  if (ifs) {
    return <LinkSelectList {...props} />;
  } else {
    return <NolinkSelectList {...props} />;
  }
}

export default FormItems;
