一个小组件(treeSearchSelect)

150 阅读1分钟

image.png

时间紧,任务重。写的有点low,拓展性不好,但能用。
import React, {useState, useEffect} from 'react';
import {TreeSelect, Spin, Badge} from '一个基于 antd 4.18.8 封装的企业内部组件库';
import localeText from '@locale';
import {forEach} from 'lodash';
import './index.less';

const {TreeSelectSearch, TreeNode} = TreeSelect;

Index.defaultProps = {
  prefixCls: 'mc-treeSelect',
  optionLabel: ''
};

export default function Index(props) {
  const {prefixCls, onFetchData, notFoundContent,
    handleChange, renderData, defaultValue, optionLabel, hasAllOption, treeDataSimpleMode,
    treeNodeFilterProp, treeDefaultExpandedKeys} = props;
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState(null);
  const [searchValue, setSearchValue] = useState<string>('');
  const [totalNum, setTotalNum] = useState(0);
  const [allCheckedValues, setAllCheckedValues] = useState([]);
  const [newValues, setNewValues] = useState(defaultValue);

  useEffect(() => {
    const vals: string[] = hasAllOption ? ['all'] : [];
    let count = 0;
    const fn = (d) => {
      forEach(d, (item) => {
        if (item?.children?.length) {
          fn(item.children);
        } else {
          count++;
          vals.push(item.value);
        }
      });
    };
    fn(renderData);
    setTotalNum(vals.length);
    if (defaultValue.length === count) {
      setNewValues(vals);
    }
    setAllCheckedValues(vals);
    setData(renderData);
  }, [renderData, defaultValue]);

  async function focusHandler() {
    if (onFetchData) {
      setLoading(true);
      try {
        const newData = await onFetchData() || [];
        setData(newData);
      } finally {
        setLoading(false);
      }
    }
  }

  const renderTreeNode = (inputTreeData) => {
    if (inputTreeData && inputTreeData.length) {
      return inputTreeData.map((node) => {
        const {isLeaf, disabled, value, title, children, nodeStatusColor} = node || {};

        const renderTitle = nodeStatusColor ? (
          <Badge color={nodeStatusColor} text={title} />
        ) : title;
        return (
          <TreeNode
            isLeaf={isLeaf}
            disabled={!!disabled}
            checkable={!disabled}
            value={value}
            dataRef={node}
            key={value}
            title={renderTitle}
          >
            {children && children.length && renderTreeNode(children)}
          </TreeNode>
        );
      });
    }
    return null;
  };

  return (
    <div>
      <TreeSelectSearch
        className={prefixCls}
        style={{width: 220}}
        dropdownMatchSelectWidth={false}
        value={newValues}
        treeDefaultExpandedKeys={treeDefaultExpandedKeys}
        notFoundContent={loading ? <Spin size='small' /> : notFoundContent}
        onFocus={focusHandler}
        searchValue={searchValue}
        treeNodeFilterProp={treeNodeFilterProp || 'title'}
        onSearch={(val) => {
          setSearchValue(val);
        }}
        maxTagCount={0}
        treeDataSimpleMode={treeDataSimpleMode}
        maxTagPlaceholder={(val) => {
          if (data?.length <= 0) {
            return '';
          }
          if (val.length === totalNum) {
            return `${optionLabel}全部选中(${totalNum - 1})`;
          }
          return `${optionLabel}已选择(${val.length})`;
        }}
        onChange={(values, labelList, extra) => {
          if (hasAllOption) {
            if (extra?.triggerValue === 'all') {
              const temp = extra.checked ? allCheckedValues : [];
              setNewValues(temp);
              handleChange(temp);
            } else {
              const temp = values.filter((value) => value !== 'all');
              if (values.find((v) => v === 'all')) {
                handleChange(temp);
                setNewValues(temp);
              } else {
                handleChange(temp.length === totalNum - 1 ? allCheckedValues : temp);
                setNewValues(temp.length === totalNum - 1 ? allCheckedValues : temp);
              }
            }
          }
        }}
      >
        {hasAllOption && data?.length && (
          <TreeNode
            isLeaf
            checkable
            value='all'
            key='all'
            title={localeText('COMMON.TXT_SELECT_ALL')}
          />
        )}
        {data && renderTreeNode(data)}
      </TreeSelectSearch>
    </div>
  );
}

  <Form.Item
    label={localeText('STATUS_RECORD.LABEL_CATEGORY')}
    name='categories'
    initialValue={categories}
    >
    <TreeSelect
      hasAllOption
      defaultValue={categories}
      treeDefaultExpandedKeys={categories}
      renderData={categoryList}
      handleChange={(value) => {
        statusRecordStore.setCategories(value);
      }}
    />
  </Form.Item>