org-setter.tsx 6.65 KB
import React, { useEffect, useRef, useState } from 'react';
import { Menu, Popover, Tag } from 'antd';
import OrgSelectorDialog from '../../qx-org-selector/src/dialog';
import { ParamValueType } from '../../qx-filter-condition/filter';
import { getOrgIdAndNameMap } from '../service';
import { request } from '@qx/common';
import { CloseOutlined } from '@ant-design/icons';

interface OrgSetterProps {
  value: any[];
  onChange: (val: any, type: ParamValueType, isDelete?: boolean) => void;
  disabled: boolean;
  style?: any;
  max?: number;
  options?: { value: string; key: string }[];
  modalClassName?: string | undefined; // 弹框类名自定义 用于自定义以及覆盖样式
}

/**
 * 用户选择
 *
 * @param value
 * @param onChange
 * @param disabled
 * @param style
 * @param max
 * @constructor
 */
export const OrgSetter: React.FC<OrgSetterProps> = ({
  value,
  onChange,
  disabled = false,
  style,
  max = 1,
  ...props
}) => {
  const [valueType, setValueType] = useState(ParamValueType.MANUAL);
  const [valueMap, setValueMap] = useState({});
  const [tempMap, setTempMap] = useState({});
  const [varMap, setVarMap] = useState({});
  const selectRef = useRef();
  const [selectedUser, setSelectedUser] = useState<any[]>([]);

  useEffect(() => {
    const _map = { ...tempMap };
    const _varMap = { ...varMap };
    (props.options || []).forEach((item) => {
      _map[item.key] = item.value;
      _varMap[item.key] = item.value;
    });
    setVarMap(_varMap);
    setTempMap(_map);
  }, [props.options]);

  useEffect(() => {
    const _valueMap = {};
    const manualValues: string[] = [];
    const waitCodes: string[] = [];
    const fieldValues: string[] = [];

    (value || []).forEach((item) => {
      if (item.type === ParamValueType.MANUAL) {
        manualValues.push(item.value);
        setValueType(ParamValueType.MANUAL);
      } else if (item.type === ParamValueType.FIELD) {
        fieldValues.push(item.value);
        setValueType(ParamValueType.FIELD);
      } else if (item.type === ParamValueType.OPERATOR) {
        _valueMap[item.value] = tempMap[item.value];
        setValueType(ParamValueType.OPERATOR);
      }
    });

    manualValues.forEach((item) => {
      if (tempMap[item]) {
        _valueMap[item] = tempMap[item];
      } else {
        waitCodes.push(item);
      }
    });
    //field 目前只能选一个
    // @ts-ignore
    if (typeof props.getName === 'function' && fieldValues.length > 0) {
      // _valueMap[fieldValues.join(',')] = props.getName(fieldValues) || fieldValues.join(',');
      fieldValues.map((_val, index) => {
        _valueMap[fieldValues[index]] =
          // @ts-ignore
          props.getName([fieldValues[index]]) || fieldValues.join(',');
      });
    }
    if (waitCodes.length > 0) {
      getOrgIdAndNameMap(waitCodes)
        .then((res) => {
          Object.keys(res || {}).forEach((key) => {
            _valueMap[key] = res[key];
          });
          setValueMap(_valueMap);
          setTempMap({ ...tempMap, ..._valueMap });
          const _data = [];
          Object.keys(_valueMap).forEach((id: string) => {
            _data.push({ id, name: _valueMap[id] });
          });
          setSelectedUser(_data);
        })
        .catch(() => {
          waitCodes.forEach((item) => {
            _valueMap[item] = item;
          });
          setValueMap(_valueMap);
        });
    } else {
      if (JSON.stringify(_valueMap) !== JSON.stringify(valueMap)) {
        setValueMap(_valueMap);
      }
    }
  }, [value, JSON.stringify(tempMap)]);

  const [visible, setSelectUserShow] = useState(false);
  const [popVisible, setPopVisible] = useState(false);

  const addOrgItem = (ids: string[], items: any[]) => {
    const _valueMap = {};
    items.forEach((item) => {
      _valueMap[item.code] = item.name;
    });
    setTempMap({ ...tempMap, ..._valueMap });
    setValueMap(_valueMap);

    onChange(ids, ParamValueType.MANUAL);
  };

  /**
   * 部门选择完成
   * @param userIds
   * @param userObj
   */
  const onSelectedUserOk = (ids: string[], Objs: any[]) => {
    addOrgItem(ids, Objs);
    setSelectUserShow(false);
  };

  const removeItem = (e: any, id: string) => {
    const _value: string[] = [];
    value.forEach((item) => {
      if (item.value !== id) {
        _value.push(item.value);
      }
    });
    onChange(_value, valueType, true);
  };

  const selectDom = (
    <div
      style={{
        width:
          selectRef &&
          selectRef.current &&
          // @ts-ignore
          (selectRef.current.clientWidth || '200') + 'px',
      }}
    >
      <Menu
        mode="inline"
        className={'qx-fields-pop-content'}
        selectedKeys={[]}
        onClick={({ key }) => {
          if (key === 'custom') {
            setSelectUserShow(true);
          } else {
            onChange([key], ParamValueType.OPERATOR);
          }
          setPopVisible(false);
        }}
      >
        <Menu.Item key="custom" onClick={() => !disabled}>
          指定部门
        </Menu.Item>
        <Menu.Divider />
        {(props.options || []).map((item) => {
          return <Menu.Item key={item.key}>{item.value}</Menu.Item>;
        })}
      </Menu>
    </div>
  );

  const handlePopVisibleChange = (v) => {
    setPopVisible(v);
  };

  return (
    <>
      <Popover
        content={selectDom}
        overlayClassName={'qx-pop-select'}
        getPopupContainer={(triggerNode) => triggerNode}
        arrowContent={false}
        open={popVisible}
        onOpenChange={handlePopVisibleChange}
        placement="bottom"
        trigger={disabled ? undefined : 'click'}
      >
        <div
          style={style || {}}
          ref={selectRef}
          className={`select sel-user-show ant-input btn-text ${
            disabled ? 'ant-input-disabled' : ''
          }`}
        >
          {Object.keys(valueMap || {}).length === 0 && (
            <span className={'ant-select-selection-placeholder'}>请选择</span>
          )}
          {valueMap &&
            Object.keys(valueMap).map((id: string) => (
              <Tag
                key={`${id}`}
                closeIcon={<CloseOutlined />}
                closable
                onClose={(e) => removeItem(e, id)}
                onClick={(e) => e.stopPropagation()}
              >
                {valueMap[id]}
              </Tag>
            ))}
        </div>
      </Popover>

      <OrgSelectorDialog
        request={request}
        title={'选择部门'}
        key={visible + ''}
        visible={visible}
        checkStrictly
        selectedData={selectedUser}
        max={max}
        onOk={onSelectedUserOk}
        onCancel={() => setSelectUserShow(false)}
        modalClassName={props?.modalClassName || ''}
      />
    </>
  );
};