三级目录的增删改查

34 阅读5分钟
import { connect, Dispatch } from 'dva';
import styles from './index.less';
import { useEffect, useState } from 'react';
import { Space, Checkbox, Popover, Button, Modal } from 'antd';
import { UNVIcon, UNVMessageBox } from 'UNV-DESIGN';
import AddOne from './AddOne';
import { set } from 'lodash';

interface Props {
  dispatch: Dispatch;
  regions: any[];
}
const RegionSetting = (props: Props) => {
  const { dispatch, regions } = props;

  // 是否显示添加区域
  const [showAdd, setShowAdd] = useState<boolean>(false);

  // 当前选择的一级区域
  const [currentFirst, setCurrentFirst] = useState<any>('');

  // 当前选择的二级区域
  const [currentSecond, setCurrentSecond] = useState<any>('');

  // 当前选择的三级区域
  const [currentThird, setCurrentThird] = useState<any>('');

  // 二级列表
  const [seconds, setSeconds] = useState<any[]>([]);

  // 三级列表
  const [thirds, setThirds] = useState<any[]>([]);

  // 当前勾选的一级区域
  const [selectOne, setSelectOne] = useState<any[]>([]);

  // 当前勾选的二级区域
  const [selectTwo, setSelectTwo] = useState<any[]>([]);

  // 当前勾选的三级区域
  const [selectThree, setSelectThree] = useState<any[]>([]);

  // 当前编辑的区域
  const [currentEdit, setCurrentEdit] = useState<any>({});

  // 当前要添加的目录等级
  const [addLevel, setAddLevel] = useState<number>(1);

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

  useEffect(() => {
    // 一级缪璐
    setCurrentFirst(currentFirst ? currentFirst : regions[0]?.id);
    let newSecondList: Array<any> = [];
    // 二级目录相关
    if (currentFirst) {
      const tempObj = regions.find((item: any) => item.id === currentFirst);
      if (tempObj.children && tempObj.children.length > 0) {
        setSeconds(tempObj.children);
        setCurrentSecond(tempObj.children[0]?.id);
      } else {
        setSeconds([]);
      }
      newSecondList = tempObj.children || [];
    } else {
      setSeconds(regions[0]?.children || []);
      setCurrentSecond(regions[0]?.children[0]?.id);
      newSecondList = regions[0]?.children || [];
    }
    // 三级目录相关
    if (currentSecond) {
      const tempObj =
        (newSecondList.length > 0 &&
          newSecondList.find((item: any) => item.id === currentSecond)) ||
        {};
      setThirds(tempObj.children || []);
    } else {
      const tempObj = newSecondList[0] || {};
      setThirds(tempObj.children || []);
    }
  }, [regions]);

  /**
   * 勾选区域
   * @param e 组件属性
   * @param item 当前勾选项
   * @param type 类型
   */
  const _checkRegion = (e: any, item: any, type: number) => {
    e.stopPropagation();
    switch (type) {
      case 1:
        if (e.target.checked) {
          setSelectOne([...selectOne, item.id]);
        } else {
          setSelectOne(selectOne.filter((id: any) => id !== item.id));
        }
        break;
      case 2:
        if (e.target.checked) {
          setSelectTwo([...selectTwo, item.id]);
        } else {
          setSelectTwo(selectTwo.filter((id: any) => id !== item.id));
        }
        break;
      case 3:
        if (e.target.checked) {
          setSelectThree([...selectThree, item.id]);
        } else {
          setSelectThree(selectThree.filter((id: any) => id !== item.id));
        }
        break;
      default:
        break;
    }
  };

  /**
   * 删除区域
   * @param type 类型
   */
  const _delRegion = (type: number) => {
    Modal.confirm({
      title: intl.formatMessage({
        id: 'Are you sure you want to delete it?'
      }),
      cancelText: intl.formatMessage({ id: 'Cancel' }),
      okText: intl.formatMessage({ id: 'OK' }),
      onOk: () => {
        switch (type) {
          case 1:
            _delAction(selectOne);
            break;
          case 2:
            _delAction(selectTwo);
            break;
          case 3:
            _delAction(selectThree);
            break;
          default:
            break;
        }
      }
    });
  };

  /**
   * 获取区域
   */
  const _getRegion = () => {
    dispatch({
      type: 'newRegion/getRegion'
    });
  };

  /**
   * 删除区域
   * @param ids 区域id
   */
  const _delAction = (ids: any[]) => {
    dispatch({
      type: 'newRegion/delRegion',
      payload: [...ids],
      callback: () => {
        _getRegion();
      }
    });
  };

  /**
   * 提交区域信息
   * @param data
   */
  const onSubmit = (res: any) => {
    let method = 'newRegion/addRegion';
    if (currentEdit.id) {
      method = 'newRegion/editRegion';
    }
    let newRes = { ...res, level: addLevel };
    switch (addLevel) {
      case 1:
        newRes.parentId = undefined;
        break;
      case 2:
        newRes.parentId = currentFirst;
        break;
      case 3:
        newRes.parentId = currentSecond;
        break;
      default:
        break;
    }
    dispatch({
      type: method,
      payload: {
        ...newRes
      },
      callback: () => {
        _getRegion();
        setShowAdd(false);
      }
    });
  };

  /**
   * 选择一级目录
   * @param item
   */
  const _selectOneLevel = (item: any) => {
    setCurrentFirst(item.id);
    const newSecond = item.children || [];
    setCurrentSecond(newSecond[0]?.id || {});
    setSeconds(newSecond);
    const newThird = newSecond[0]?.children || [];
    setThirds(newThird);
    setSelectTwo([]);
    setSelectThree([]);
  };

  /**
   * 选择二级目录
   * @param item
   */
  const _selectTwoLevel = (item: any) => {
    setCurrentSecond(item.id);
    setThirds(item.children || []);
    setSelectThree([]);
  };

  /**
   * 编辑区域
   * @param item 当前编辑的区域
   */
  const _editRegion = (item: any, type: number) => {
    switch (type) {
      case 1:
        setCurrentFirst(item.id);
        break;
      case 2:
        setCurrentSecond(item.id);
        break;
      case 3:
        setCurrentThird(item.id);
        break;
      default:
        break;
    }
    setCurrentEdit(item);
    setShowAdd(true);
  };

  /**
   * 移动区域
   * @param item 当前移动的区域
   * @param type 移动方向
   * @param level 移动级别
   */
  const _moveRegion = (item: any, type: string, level: number) => {
    let index = 0;
    let target: any = {};
    switch (level) {
      case 1:
        index = regions.findIndex((item: any) => item.id === item.id);
        if (type === 'up') {
          target = regions[index - 1];
        } else {
          target = regions[index + 1];
        }
        _moveAction(item.id, target.id, type);
        break;
      case 2:
        index = regions.findIndex((item: any) => item.id === item.id);
        if (type === 'up') {
          target = seconds[index - 1];
        } else {
          target = seconds[index + 1];
        }
        _moveAction(item.id, target.id, type);
        break;
      case 3:
        index = regions.findIndex((item: any) => item.id === item.id);
        if (type === 'up') {
          target = thirds[index - 1];
        } else {
          target = thirds[index + 1];
        }
        _moveAction(item.id, target.id, type);
        break;
      default:
        break;
    }
  };

  /**
   * 移动区域
   * @param id 当前移动的区域id
   * @param target 目标区域id
   * @param type 移动方向
   */
  const _moveAction = (id: number, target: number, type: string) => {
    dispatch({
      type: 'newRegion/moveRegion',
      payload: {
        id,
        target,
        type
      },
      callback: () => {
        _getRegion();
      }
    });
  };

  return (
    <div className={styles.regionSetting}>
      <div className={styles.regionSetting_title}>
        {intl.formatMessage({ id: 'National and regional allocation' })}
      </div>
      <div className={styles.regionSetting_content}>
        <div className={styles.regionSetting_first}>
          <div className={styles.regionSetting_first_header}>
            <div className={styles.regionSetting_header_font}>
              {intl.formatMessage({ id: 'District' })}
            </div>
            <Space>
              <UNVIcon
                icon="addIcon"
                onClick={() => {
                  setCurrentEdit({});
                  setAddLevel(1);
                  setShowAdd(true);
                }}
              />
              <UNVIcon
                icon="deleteIcon"
                onClick={() => _delRegion(1)}
                style={{ marginTop: '3px' }}
                disabled={selectOne.length < 1}
              />
            </Space>
          </div>
          <div className={styles.regionSetting_first_list}>
            {Array.isArray(regions) &&
              regions.length > 0 &&
              regions.map((item: any, index: number) => {
                return (
                  <div
                    key={item.id}
                    className={styles.regionSetting_first_listOne}
                    onClick={() => _selectOneLevel(item)}
                    data-index={currentFirst === item.id}
                  >
                    <Space>
                      <Checkbox
                        onChange={(e) => _checkRegion(e, item, 1)}
                        checked={selectOne.includes(item.id)}
                      />
                      <div className={styles.regionSetting_first_listOneFont}>
                        {item.fullName}
                      </div>
                    </Space>
                    <Popover
                      placement="bottom"
                      overlayClassName={styles.popovers}
                      content={
                        <>
                          <div
                            onClick={() => _editRegion(item, 1)}
                            className={styles.popovers_item}
                          >
                            {intl.formatMessage({ id: 'Edit' })}
                          </div>
                          {/* <div
                            onClick={() => _delRegion(item)}
                            className={styles.popovers_item}
                          >
                            {intl.formatMessage({ id: 'Delete' })}
                          </div> */}
                          <div
                            onClick={() => _moveRegion(item, 'up', 1)}
                            data-index={index === 0}
                            className={styles.popovers_itemMove}
                          >
                            {intl.formatMessage({ id: 'Up' })}
                          </div>
                          <div
                            onClick={() => _moveRegion(item, 'down', 1)}
                            className={styles.popovers_itemMove}
                            data-index={index === regions.length - 1}
                            data-index1={'down'}
                          >
                            {intl.formatMessage({ id: 'Down' })}
                          </div>
                        </>
                      }
                    >
                      <UNVIcon
                        icon="moreAIcon"
                        className={styles.regionSetting_first_listOneIcon}
                      />
                    </Popover>
                  </div>
                );
              })}
          </div>
        </div>
        <div className={styles.regionSetting_first}>
          <div className={styles.regionSetting_first_header}>
            <div className={styles.regionSetting_header_font}>
              {intl.formatMessage({ id: 'Country' })}
            </div>
            <Space>
              <UNVIcon
                icon="addIcon"
                onClick={() => {
                  setCurrentEdit({});
                  setAddLevel(2);
                  if (currentFirst) {
                    setShowAdd(true);
                  } else {
                    UNVMessageBox.info(
                      intl.formatMessage({
                        id: 'Please select first level category'
                      })
                    );
                  }
                }}
              />
              <UNVIcon
                icon="deleteIcon"
                onClick={() => _delRegion(1)}
                style={{ marginTop: '3px' }}
                disabled={selectTwo.length < 1}
              />
            </Space>
          </div>
          <div className={styles.regionSetting_first_list}>
            {Array.isArray(seconds) &&
              seconds.length > 0 &&
              seconds.map((item: any, index: number) => {
                return (
                  <div
                    key={item.id}
                    className={styles.regionSetting_first_listOne}
                    onClick={() => _selectTwoLevel(item)}
                    data-index={currentSecond === item.id}
                  >
                    <Space>
                      <Checkbox
                        onChange={(e) => _checkRegion(e, item, 2)}
                        checked={selectTwo.includes(item.id)}
                      />
                      <div className={styles.regionSetting_first_listOneFont}>
                        {item.fullName}
                      </div>
                    </Space>
                    <Popover
                      placement="bottom"
                      overlayClassName={styles.popovers}
                      content={
                        <>
                          <div
                            onClick={() => _editRegion(item, 2)}
                            className={styles.popovers_item}
                          >
                            {intl.formatMessage({ id: 'Edit' })}
                          </div>
                          {/* <div
                            onClick={() => _delRegion(item)}
                            className={styles.popovers_item}
                          >
                            {intl.formatMessage({ id: 'Delete' })}
                          </div> */}
                          <div
                            onClick={() => _moveRegion(item, 'up', 2)}
                            data-index={index === 0}
                            className={styles.popovers_itemMove}
                          >
                            {intl.formatMessage({ id: 'Up' })}
                          </div>
                          <div
                            onClick={() => _moveRegion(item, 'down', 2)}
                            className={styles.popovers_itemMove}
                            data-index={index === seconds.length - 1}
                            data-index1={'down'}
                          >
                            {intl.formatMessage({ id: 'Down' })}
                          </div>
                        </>
                      }
                    >
                      <UNVIcon
                        icon="moreAIcon"
                        className={styles.regionSetting_first_listOneIcon}
                      />
                    </Popover>
                  </div>
                );
              })}
          </div>
        </div>
        <div className={styles.regionSetting_first}>
          <div className={styles.regionSetting_first_header}>
            <div className={styles.regionSetting_header_font}>
              {intl.formatMessage({ id: 'Region' })}
            </div>
            <Space>
              <UNVIcon
                icon="addIcon"
                onClick={() => {
                  setCurrentEdit({});
                  setAddLevel(3);
                  if (currentSecond) {
                    setShowAdd(true);
                  } else {
                    UNVMessageBox.info(
                      intl.formatMessage({
                        id: 'Please select the secondary category first'
                      })
                    );
                  }
                }}
              />
              <UNVIcon
                icon="deleteIcon"
                onClick={() => _delRegion(1)}
                style={{ marginTop: '3px' }}
                disabled={selectThree.length < 1}
              />
            </Space>
          </div>
          <div className={styles.regionSetting_first_list}>
            {Array.isArray(thirds) &&
              thirds.length > 0 &&
              thirds.map((item: any, index: number) => {
                return (
                  <div
                    key={item.id}
                    className={styles.regionSetting_first_listOne}
                    onClick={() => {
                      setCurrentThird(item.id);
                    }}
                    data-index={currentThird === item.id}
                  >
                    <Space>
                      <Checkbox
                        onChange={(e) => _checkRegion(e, item, 3)}
                        checked={selectThree.includes(item.id)}
                      />
                      <div className={styles.regionSetting_first_listOneFont}>
                        {item.fullName}
                      </div>
                    </Space>
                    <Popover
                      placement="bottom"
                      overlayClassName={styles.popovers}
                      content={
                        <>
                          <div
                            onClick={() => _editRegion(item, 3)}
                            className={styles.popovers_item}
                          >
                            {intl.formatMessage({ id: 'Edit' })}
                          </div>
                          {/* <div
                            onClick={() => _delRegion(item)}
                            className={styles.popovers_item}
                          >
                            {intl.formatMessage({ id: 'Delete' })}
                          </div> */}
                          <div
                            onClick={() => _moveRegion(item, 'up', 2)}
                            data-index={index === 0}
                            className={styles.popovers_itemMove}
                          >
                            {intl.formatMessage({ id: 'Up' })}
                          </div>
                          <div
                            onClick={() => _moveRegion(item, 'down', 3)}
                            className={styles.popovers_itemMove}
                            data-index={index === thirds.length - 1}
                            data-index1={'down'}
                          >
                            {intl.formatMessage({ id: 'Down' })}
                          </div>
                        </>
                      }
                    >
                      <UNVIcon
                        icon="moreAIcon"
                        className={styles.regionSetting_first_listOneIcon}
                      />
                    </Popover>
                  </div>
                );
              })}
          </div>
        </div>
      </div>
      {showAdd && (
        <AddOne
          onSubmit={onSubmit}
          onCancel={() => setShowAdd(false)}
          currentEdit={currentEdit}
        />
      )}
    </div>
  );
};

export default connect(({ newRegion, loading }: any) => {
  const { regions } = newRegion;
  return {
    regions,
    loading: loading.effects['regions/getRegion']
  };
})(RegionSetting);

css样式

.regionSetting {
  padding: 10px;
  border-radius: 8px;
  background-color: white;
  height: 100%;
  width: 100%;

  .regionSetting_title {
    height: 30px;
    line-height: 22px;
    padding-left: 10px;
    border-bottom: 1px solid rgb(234, 234, 234);
    font-size: 14px;
    color: rgba(0, 0, 0, 0.5);
  }

  .regionSetting_content {
    display: flex;
    height: calc(100% - 30px);

    .regionSetting_first {
      width: 260px;
      padding: 0 10px 0 10px;
      border-right: 2px solid rgb(234, 234, 234);

      .regionSetting_first_header {
        display: flex;
        justify-content: space-between;
        height: 40px;
        border-bottom: 1px solid rgb(234, 234, 234);
        font-weight: 700;
        font-style: normal;
        font-size: 16px;
        color: rgba(0, 0, 0, 0.5);

        .regionSetting_header_font {
          padding: 10px 0 0 10px;
        }
      }

      .regionSetting_first_list {
        height: calc(100% - 42px);
        overflow-y: auto;

        .regionSetting_first_listOne {
          display: flex;
          justify-content: space-between;
          height: 40px;
          padding-left: 10px;
          cursor: pointer;

          &[data-index=true] {
            background-color: rgb(237, 248, 255);
            color: #0183CC;
          }

          .regionSetting_first_listOneFont {
            width: 164px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
          }

          .regionSetting_first_listOneIcon {
            margin-top: 6px;
            visibility: hidden;
          }

          &:hover {
            .regionSetting_first_listOneIcon {
              visibility: visible;
            }
          }
        }
      }
    }
  }
}

.popovers {
  .popovers_item {
    border-bottom: 1px solid rgb(226, 226, 226);
    cursor: pointer;
    margin-bottom: 4px
  }

  .popovers_itemMove {
    border-bottom: 1px solid rgb(226, 226, 226);
    cursor: pointer;

    &[data-index=true] {
      pointer-events: none;
      color: rgba(0, 0, 0, 0.25);
      cursor: not-allowed;
    }

    &[data-index1='down'] {
      border-bottom: none;
    }
  }
}