treebox.tsx 5.52 KB
import { Input, Popover, Tree } from 'antd';
import React from 'react';
import { FC, ReactElement, useEffect, useState } from 'react';
import type { OptionField } from '../type';
import {QxBaseIcon} from '@qx/common';
import './style.less';

interface QxFieldPopoverProp {
  data: OptionField[];
  widgets?: string[]; //需要展示的widgets
  exclude?: string[]; //排除的字段
  width?: string; //pop 宽度
  trigger?: 'click' | 'hover' | undefined;
  onSelect?: (field: OptionField) => void;
  disabled?: boolean;
  hiddenAfterTrigger?: boolean;
  popFooter?: ReactElement;
}

type FieldsCheckboxGroupProps = {
  fields: OptionField[];
  values?: string[];
  onChange: (selectedKey: string, selectedItem: OptionField, isChecked: boolean) => void;
};

const ParametersTreeGroup: FC<FieldsCheckboxGroupProps> = (props) => {
  const { fields, values, onChange } = props;

  const [keyword, setKey] = useState('');

  const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
  const [expandedKeys, setExpandedKeys] = useState<any>([]);
  const [checkedKeys, setCheckedKeys] = useState<any>([]);

  const [treeData, setTreeData] = useState<any[]>([]);

  useEffect(() => {
    if (keyword) {
      // eslint-disable-next-line @typescript-eslint/no-use-before-define
      const keyTree = loop(fields);
      setTreeData(keyTree);
    } else {
      setExpandedKeys([]);
      setTreeData(fields || []);
    }
  }, [fields, keyword]);

  useEffect(() => {
    if (values && values?.length > 0) {
      setCheckedKeys({
        checked: values,
        halfChecked: [],
      });
    } else {
      setCheckedKeys({
        checked: [],
        halfChecked: [],
      });
    }
  }, [values]);

  const onExpand = (expandedKeysValue: React.Key[]) => {
    console.log('onExpand', expandedKeysValue);
    // if not set autoExpandParent to false, if children expanded, parent can not collapse.
    // or, you can remove all expanded children keys.
    setExpandedKeys(expandedKeysValue);
    setAutoExpandParent(false);
  };

  const onCheck = (checkedKeysValue: any, Item: any) => {
    console.log('onCheck', checkedKeysValue, Item, checkedKeysValue?.checked);
    setCheckedKeys(checkedKeysValue);
    const chooseId = Item?.node?.id;
    if (chooseId) {
      onChange(chooseId, Item?.node, Item?.checked);
    }
  };

  // const onSelect = (selectedKeysValue: React.Key[], info: any) => {
  //   console.log('onSelect', info);
  //   setSelectedKeys(selectedKeysValue);
  // };

  const KeysArr: any[] = [];
  const loop = (data: any): any =>
    data.map((item: any) => {
      const strTitle = item.title as string;
      const index = strTitle.indexOf(keyword);
      const beforeStr = strTitle.substring(0, index);
      const afterStr = strTitle.slice(index + keyword.length);
      const title =
        index > -1 ? (
          <span>
            {beforeStr}
            <span style={{ color: 'red' }} className="site-tree-search-value">
              {keyword}
            </span>
            {afterStr}
          </span>
        ) : (
          <span>{strTitle}</span>
        );
      if (item.child) {
        KeysArr.push(item.id);
        return { ...item, title, id: item.id, child: loop(item.child) };
      }
      setExpandedKeys(KeysArr);
      return {
        ...item,
        title,
        id: item.id,
      };
    });

  //   const onChange = (newValue: string[]) => {
  //     console.log('onChange ', value);
  //     setValue(newValue);
  //   };

  return (
    <div style={{ padding: '10px', maxHeight: '200px', overflow: 'auto' }}>
      <Input
        className={'qx-selector-sub-search'}
        placeholder={'请输入参数名称搜索'}
        allowClear
        prefix={<QxBaseIcon type={'icon-app-search-line'} />}
        onChange={(e) => {
          setKey(e.target.value.trim());
        }}
      />
      <Tree
        checkable
        onExpand={onExpand}
        expandedKeys={expandedKeys}
        autoExpandParent={autoExpandParent}
        fieldNames={{
          title: 'title',
          key: 'id',
          children: 'child',
        }}
        checkStrictly={true}
        onCheck={onCheck}
        checkedKeys={checkedKeys}
        // onSelect={onSelect}
        // selectedKeys={selectedKeys}
        treeData={treeData || []}
      />
    </div>
  );
};

interface QxTreeParameterPopoverProp extends QxFieldPopoverProp {
  onChange: (selectedKey: string, selectedItem: OptionField, isChecked: boolean) => void;
  values?: string[];
  children?: any;
}

const QxTreeParameterPopover: React.FC<QxTreeParameterPopoverProp> = (props) => {
  const [fields, setFields] = useState<OptionField[]>([]);
  const [visible, setVisible] = useState<boolean>(false);
  // @ts-ignore
  const excludeFields = (list?: OptionField[]) => {
    // @ts-ignore
    return list?.filter((item?: any) => {
      if (item.children && item.children.length === 0) {
        return false;
      }
      const allow = true;
      return allow;
    });
  };
  useEffect(() => {
    // console.log(props.data);
    if (props.data) {
      const _fields = excludeFields(props?.data);
      setFields(_fields || []);
    }
  }, [props.data]);

  return (
    <Popover
      overlayClassName={'qx-fields-popover'}
      content={
        <ParametersTreeGroup fields={fields} onChange={props.onChange} values={props.values} />
      }
      placement={'bottomRight'}
      trigger={props.disabled ? undefined : props.trigger || 'hover'}
      open={visible}
      onOpenChange={(v) => {
        setVisible(v);
      }}
    >
      {props?.children}
    </Popover>
  );
};

export default QxTreeParameterPopover;