input.tsx 5.56 KB
import React, { useEffect, useImperativeHandle, useState } from 'react';

import { Checkbox, Input, Tag } from 'antd';
import { ApartmentOutlined } from '@ant-design/icons';
import './style.less';
import OrgSelectorDialog from './dialog';

export type QxOrgSelectorProps = {
  onChange?: (data: string | string[], infos?: BaseOrg[]) => void;
  onMounted?: () => void;
  defaultValue?: any;
  disabled?: boolean;
  multiple?: boolean;
  readOnly?: boolean;
  name?: string;
  max?: number;
  request: any;
  value?: string | string[];
  defaultData?: any;
  data?: []; //请求body参数
  cRef?: any;
};

type BaseOrg = {
  id: string;
  name: string;
};
/**
 * 表单设计器(XRender)
 * @constructor
 */
const QxOrgSelector: React.FC<QxOrgSelectorProps> = (props) => {
  const [selectOrgs, setSelectOrgs] = useState([]);
  const [visible, setVisible] = useState(false);
  const [value, setValue] = useState<string | string[]>();

  useEffect(() => {
    setValue(props.defaultValue);
    if (props?.onMounted) {
      props?.onMounted();
    }
  }, []);

  useEffect(() => {
    setValue(props.value);
    //如果value
    if (!props.value) {
      setSelectOrgs([]);
    }
  }, [props.value]);

  useImperativeHandle(props.cRef, function () {
    return {
      // 暴露给父组件
      clear: () => {
        setSelectOrgs([]);
        setValue(undefined);
      },
      /*  //方法触发增加部门
      addOrgs: (orgs: BaseOrg[]) => {
        const addIds: string[] = selectOrgs.map(org => org.id);
        const waits = orgs.filter((org) => {
          return org.id && !addIds.includes(org.id);
        });
        setSelectOrgs([...selectOrgs, ...waits]);
      },*/
      //设置部门
      setOrgs: (orgs: BaseOrg[]) => {
        if (JSON.stringify(orgs) === JSON.stringify(selectOrgs)) {
          return;
        }
        setSelectOrgs(orgs);
        const ids = orgs.map((user) => user.id);
        if (JSON.stringify(ids) === JSON.stringify(value)) {
          return;
        }
        props.onChange(ids, orgs);
      },
    };
  });

  //TODO 默认值待优化
  useEffect(() => {
    let _orgs = [];
    let ids;
    if (props.defaultData) {
      if (props.multiple || Array.isArray(props.defaultData)) {
        _orgs = props.defaultData;
        ids = [];
        props.defaultData.map((item) => {
          ids.push(item.id);
        });
      } else {
        _orgs = [props.defaultData];
        ids = props.defaultData.id;
      }
    }
    setSelectOrgs(_orgs);

    if (ids && ids.length > 0 && !props.value) {
      props.onChange(ids, _orgs);
    }
  }, [JSON.stringify(props.defaultData)]);

  // getUserList()
  const handleOk = (keys: any[], data: any[]) => {
    let _value: [] | string = keys;
    if (!props.multiple && keys && keys.length > 0) {
      // @ts-ignore
      _value = keys[0];
    }
    setValue(_value);

    setSelectOrgs(data);
    setVisible(false);
    if (props.onChange) {
      props.onChange(_value, data);
    }
  };

  const handleCancel = () => {
    setVisible(false);
  };

  const handleRemove = (index: number) => {
    let _value: string | string[] = '';
    let _selected = [];
    if (props.multiple) {
      // @ts-ignore
      _value = [...value];
      _selected = [...selectOrgs];
      _value.splice(index, 1);
      _selected.splice(index, 1);
    }

    setValue(_value);
    setSelectOrgs(_selected);

    if (props.onChange) {
      props.onChange(_value, _selected);
    }
  };

  return (
    <>
      {props.name ? (
        props.multiple && typeof value !== 'string' ? (
          <Checkbox.Group name={props.name} value={value} style={{ display: 'none' }} />
        ) : (
          <Input style={{ display: 'none' }} value={value} />
        )
      ) : null}
      <div
        className={
          'qx-org-selector ant-input ' +
          `${props.readOnly ? 'qx-org-selector--readonly' : 'qx-org-selector--edit'}`
        }
        style={{ minHeight: '32px', paddingTop: 3, paddingBottom: 3 }}
        onClick={() => setVisible(true)}
      >
        {props.readOnly ? null : (
          <ApartmentOutlined
            style={{
              paddingRight: '5px',
              paddingLeft: 4,
              paddingTop: 6,
              verticalAlign: 'top',
              color: '#999',
            }}
          />
        )}
        {selectOrgs.map(
          (org: { title?: string; key?: string; name?: string; id?: string }, index: number) => (
            <Tag
              closable={!props.readOnly}
              color={'blue'}
              key={org.key || org.id}
              onClose={() => handleRemove(index)}
              style={{
                maxWidth: `calc(100% - ${!props.readOnly && index === 0 ? 32 : 8}px)`,
              }}
            >
              <span
                style={{
                  display: 'inline-block',
                  maxWidth: `calc(100% - ${!props.readOnly ? 15 : 0}px)`,
                  textOverflow: 'ellipsis',
                  overflow: 'hidden',
                  height: 20,
                  // lineHeight: '20px',
                }}
                title={org.title || org.name}
              >
                {org.title || org.name}
              </span>
            </Tag>
          ),
        )}
      </div>
      {props.readOnly ? null : (
        <OrgSelectorDialog
          key={visible + ''}
          visible={visible}
          multiple
          checkStrictly
          selectedData={selectOrgs}
          data={props.data}
          max={props.max}
          request={props.request}
          onOk={handleOk}
          onCancel={handleCancel}
        />
      )}
    </>
  );
};

export default QxOrgSelector;