core.tsx 7.23 KB
import * as React from 'react';
import { useCallback, useEffect, useImperativeHandle, useState } from 'react';
import { Checkbox, Empty, Input, Spin } from 'antd';
import { getPositions } from './service';
import { cloneDeep } from 'lodash-es';
import {QxBaseIcon} from '@qx/common';
import Menu from 'antd/es/menu';

type PosCoreProps = {
  cRef?: any;
  multiple?: boolean;
  placeholder?: string;
  params?: any;
  onSelect?: (selectedKeys: string[], selectedData: PosModel[]) => void;
  request: any;
};

export interface PosModel {
  id: string;
  name: string;
  category?: boolean;
  positionList?: PosModel[];
  visible?: boolean;
}

const PosCore: React.FC<PosCoreProps> = (props) => {
  const [loading, setLoading] = useState<boolean>(true); //请求loading

  const [data, setData] = useState<PosModel[]>([]); //存储原始数据
  const [expandedKeys, setExpandedKeys] = useState<string[]>();

  const [keywords, setKeywords] = useState<string>('');

  const [selectedData, setSelectedData] = useState<PosModel[]>([]);
  const [selectedKeys, setSelectedKeys] = useState<string[]>();

  const requestData = useCallback(() => {
    setLoading(true);
    getPositions(props.request, props.params || {})
      .then((res: PosModel[]) => {
        if (res) {
          const _extendKeys: string[] = [];
          let _selectKey = '';
          res.map((item) => {
            if (!_selectKey && item.positionList && item.positionList.length > 0) {
              _selectKey = item.positionList[0].id;
            }
            _extendKeys.push(item.id);
          });
          if (_selectKey && !props.multiple) {
            setSelectedKeys([_selectKey]);
          }
          setExpandedKeys(_extendKeys);

          setData(res);

          setLoading(false);
        }
      })
      .catch(() => {
        setLoading(false);
      });
  }, []);

  useEffect(() => {
    requestData();
  }, [requestData]);

  useEffect(() => {
    const onSelect = props.onSelect ? props.onSelect : () => {};
    if (selectedKeys) {
      onSelect(selectedKeys, selectedData);
    }
  }, [props.onSelect, selectedKeys, selectedData]);

  const handleSelect = (selectData: { selectedKeys: string[] }) => {
    //单选走这里
    if (!props.multiple) {
      setSelectedKeys(selectData.selectedKeys);
    }
  };
  useImperativeHandle(props.cRef, () => ({
    // 暴露给父组件
    remove: (index: number) => {
      let _selectedKeys: string[] = [];
      let _selectedData: PosModel[] = [];
      if (selectedKeys && selectedKeys.length > 0) {
        _selectedKeys = [...selectedKeys];
        _selectedData = [...selectedData];
        _selectedKeys.splice(index, 1);
        _selectedData.splice(index, 1);
        setSelectedData(_selectedData);
        setSelectedKeys(_selectedKeys);
      }
    },
    emptySelect: () => {
      setSelectedData([]);
      setSelectedKeys([]);
    },
  }));
  const handleMultiSelect = (checked: boolean, item: PosModel) => {
    let _selectedKeys: string[] = [];
    let _selectedData: PosModel[] = [];
    if (selectedKeys) {
      _selectedKeys = [...selectedKeys];
      _selectedData = [...selectedData];
    }
    //console.log(checked, item.id, _selectedKeys);

    if (checked) {
      _selectedKeys.push(item.id);
      _selectedData.push(item);
    } else {
      const index = _selectedKeys.indexOf(item.id);
      if (index > -1) {
        _selectedKeys.splice(index, 1);
        _selectedData.splice(index, 1);
      }
    }

    setSelectedData(_selectedData);
    setSelectedKeys(_selectedKeys);
    /*
        if (props.onSelect) {
          props.onSelect(_selectedKeys, _selectedData);
        }*/
  };
  //多选走这里
  const filter = (word: string) => {
    setKeywords(word);
    const traverse = function (node: PosModel) {
      const childNodes = node.positionList || [];

      childNodes.forEach((child) => {
        child.visible = child.name.indexOf(word) > -1;

        traverse(child);
      });

      if (!node.visible && childNodes.length) {
        node.visible = childNodes.some((child) => child.visible);
      }
    };

    if (data) {
      const _data = cloneDeep(data);
      _data.forEach((item) => {
        traverse(item);
      });
      setData(_data);
    }
  };

  const handleSearch = (e: React.KeyboardEvent<HTMLInputElement>) => {
    e.stopPropagation();
    // @ts-ignore
    filter(e.target.value.trim());
  };
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // @ts-ignore
    if (e.type === 'click' && e.target.value === '' && data) {
      //如果是清空
      filter('');
    }
  };
  const renderText = (text: string) => {
    let title = <> {text}</>;
    if (keywords) {
      const index = text.indexOf(keywords);
      if (index > -1) {
        title = (
          <>
            {text.substr(0, index)}
            <span className={'qx-keywords-highlight'}>{keywords}</span>
            {text.substr(index + keywords.length)}
          </>
        );
      }
    }
    return title;
  };

  return (
    <div className={'qx-search-menus__wrap'}>
      <Input
        className={'qx-selector-sub-search'}
        placeholder={props.placeholder || '请输入岗位名称,按回车键搜索'}
        allowClear
        prefix={<QxBaseIcon type={'icon-app-search-line'} />}
        onChange={(e) => {
          handleChange(e);
        }}
        onPressEnter={(e) => {
          handleSearch(e);
        }}
      />
      <div className="qx-search-menus">
        {expandedKeys ? (
          <Menu
            mode={'inline'}
            onSelect={handleSelect}
            selectedKeys={props.multiple ? [] : selectedKeys}
            multiple={!!props.multiple}
            defaultOpenKeys={expandedKeys}
          >
            {data.map((item: PosModel) => {
              if (typeof item.visible === 'boolean' && !item.visible) {
                return null;
              }
              if (item.positionList) {
                return (
                  <Menu.SubMenu key={item.id} title={item.name}>
                    {item.positionList.map((child) => {
                      return typeof child.visible === 'boolean' && !child.visible ? null : (
                        <Menu.Item key={child.id}>
                          {props.multiple ? (
                            <Checkbox
                              checked={selectedKeys && selectedKeys.indexOf(child.id) > -1}
                              onChange={(e) => {
                                handleMultiSelect(e.target.checked, child);
                              }}
                            >
                              {renderText(child.name)}
                            </Checkbox>
                          ) : (
                            renderText(child.name)
                          )}
                        </Menu.Item>
                      );
                    })}
                  </Menu.SubMenu>
                );
              }
              return null;
            })}
          </Menu>
        ) : null}
        <Spin
          spinning={loading}
          style={{ width: '100%', marginTop: '40px' }}
          // indicator={<LoadingOutlined style={{ fontSize: 24, marginTop: '40px' }} spin />}
        />
        {!loading && data.length === 0 ? <Empty style={{ paddingTop: '30px' }} /> : null}
      </div>
    </div>
  );
};

export default PosCore;