index.tsx 5.96 KB
import React, { useEffect, useState, useRef } from 'react';
import { Form, Input, InputNumber, Select, Tooltip } from 'antd';
import * as commonUtils from "@/utils/utils";
import type { SelectProps } from 'antd';
import type { PropsType, FormItemTypeKey, StateType } from './type';

const FormItemTypeEvent = (props: PropsType) => {
  const addState: any = {};
  const { showConfig } = props;
  const { sName = "", bNotEmpty } = showConfig;

  const [state, setState] = useState<StateType>({
    searchValue: "",
  });
  addState.state = state;
  const onSaveState0 = (value: StateType) => {
    setState(pre => ({ ...pre, ...value }))
  }
  addState.onSaveState0 = onSaveState0;

  const antdRef = useRef<any>(null);
  addState.antdRef = antdRef;

  useEffect(() => {
    antdRef.current?.focus();
  }, [])

  const formItemProps = (): any => {
    return {
      style: { margin: 0 },
      name: sName,
      rules: [{ required: bNotEmpty, message: <Tooltip title="此字段必填!"><div>必填</div></Tooltip> }]
    }
  }
  addState.formItemProps = formItemProps;

  const dropDownRef = useRef<any>(null);
  const getDropDownData = ({ searchValue = '', pageNum = 1 } = { searchValue: '', pageNum: 1 }) => {
    const { formId, name, record, } = props;
    const { dropDownData: dropDownDataOld = [], totalPageCount } = state;
    if (totalPageCount && pageNum > totalPageCount) return;
    const tempId = commonUtils.createSid();
    dropDownRef.current = tempId;
    props.getSqlDropDownData(formId, name, showConfig, record, searchValue, pageNum).then((result: any = {}) => {
      if (dropDownRef.current !== tempId) return;
      const {
        currentPageNo: pageNum, totalPageCount, totalCount, conditonValues, dropDownData = [],
      } = result;
      onSaveState0({
        pageNum,
        totalPageCount,
        totalCount,
        // conditonValues,
        dropDownData: [...(pageNum === 1 ? [] : dropDownDataOld), ...dropDownData],
      })
    });
  }
  addState.getDropDownData = getDropDownData;

  return {
    ...props,
    ...addState,
  }
}

const FormItemType: React.FC<PropsType> = (baseProps): React.ReactElement => {
  const props = FormItemTypeEvent(baseProps);
  const { showConfig } = props;
  const { sName = "", bNotEmpty } = showConfig;
  const firstDataIndex = sName.charAt(0) as FormItemTypeKey;
  const FormItemJson: Record<FormItemTypeKey, JSX.Element> = {
    "s": <FormItemInput {...props} />,
    "i": <FormItemInputNumber {...props} />,
    "d": <FormItemInputNumber {...props} />,
    "t": <FormItemDatePicker {...props} />,
    "b": <FormItemInputCheckbox {...props} />,
  }

  return FormItemJson[firstDataIndex];
}

// 文本框
const FormItemInput: React.FC<PropsType> = (props): React.ReactElement => {
  const { showConfig } = props;

  const { sDropDownType } = showConfig;
  if (["sql", "const"].includes(sDropDownType)) {
    return <FormItemInputSelect {...props} />
  }

  return <Form.Item
    {...props.formItemProps()}
  >
    <Input ref={props.antdRef} onPressEnter={props.onSave} onBlur={props.onSave} />
  </Form.Item>
}

// 下拉框
const FormItemInputSelect: React.FC<PropsType> = (props): React.ReactElement => {
  const { name, showConfig, record, state } = props;
  const { dropDownData = [] } = state;
  const { sName, sDropDownType } = showConfig;
  const [fieldNames, setFieldNames] = useState<any>(null);
  const timer = useRef<any>(null);
  // 获取下拉数据
  useEffect(() => {
    const { dropDownData, showDropDown } = showConfig;
    if (sDropDownType === "sql") {
      props.getDropDownData();
      return;
    }
    const data = dropDownData || (typeof showDropDown === 'object') ? showDropDown : commonUtils.objectToArr(commonUtils.convertStrToObj(showDropDown));
    if (!data?.length) return;

    props.onSaveState0({
      dropDownData: data,
    })

  }, [])

  useEffect(() => {
    if (!dropDownData.length) return;
    const data0 = dropDownData[0];
    setFieldNames({
      label: Object.keys(data0)[0],
      value: data0.sSlaveId ? 'sSlaveId' : 'sId',
    })
  }, [!!dropDownData.length])

  const handlePopupScroll = (e: React.UIEvent<HTMLDivElement>) => {
    // e.persist();
    const { dropDownData } = showConfig;
    const target = e.target as HTMLDivElement;
    const { scrollTop, offsetHeight, scrollHeight } = target;
    if (Math.ceil(scrollTop + offsetHeight) >= scrollHeight && sDropDownType === 'sql' && commonUtils.isEmptyArr(dropDownData)) {
      const {
        pageNum, searchPageNum, searchTotalPageCount, searchValue, totalPageCount,
      } = state;
      const nextPageNum = pageNum + 1;
      const nextSearchPageNum = searchPageNum + 1;
      props.getDropDownData({ searchValue, pageNum: searchValue === '' ? nextPageNum : nextSearchPageNum });
    }
  };

  const selectProps: SelectProps = {
    filterOption: sDropDownType !== "sql",
    showSearch: true,
    fieldNames,
    options: dropDownData,
    onChange: (value: any) => {
      props.onChange(name, sName, { [sName]: dropDownData.find((item: any) => item[fieldNames.value] === value)[fieldNames.label] }, record.sId, dropDownData)
    },
    onSearch: (value: string) => {
      if (sDropDownType !== 'sql' || showConfig.dropDownData) return;
      clearTimeout(timer.current);
      timer.current = setTimeout(() => {
        props.getDropDownData({ searchValue: value, pageNum: 1 });
      }, 500);
    },
    onPopupScroll: handlePopupScroll
  }

  return <Form.Item
    {...props.formItemProps()}
  >
    <Select {...selectProps} />
  </Form.Item>
}

// 数字框
const FormItemInputNumber: React.FC<PropsType> = (props): React.ReactElement => {
  return <Form.Item
    {...props.formItemProps()}
  >
    <InputNumber ref={props.antdRef} onPressEnter={props.onSave} onBlur={props.onSave} />
  </Form.Item>
}

// 日期框
const FormItemDatePicker: React.FC<PropsType> = (props): React.ReactElement => {
  return <FormItemInput {...props} />
}

// 复选框
const FormItemInputCheckbox: React.FC<PropsType> = (props): React.ReactElement => {
  return <FormItemInput {...props} />
}


export default FormItemType;