@ant-design/icons#CaretDownFilled TypeScript Examples

The following examples show how to use @ant-design/icons#CaretDownFilled. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From dashboard with Apache License 2.0 4 votes vote down vote up
DepartmentSelectionModal: React.FC<DepartmentSelectionProps> = (props) => {
  const {visible, setVisible, defaultCheckedDepartments, onFinish, allDepartments} = props;
  const [departments, setDepartments] = useState<DepartmentOption[]>([]);
  const [departmentNodes, setDepartmentNodes] = useState<TreeNode[]>([]); // 一维的节点
  const [departmentTree, setDepartmentTree] = useState<TreeNode[]>([]); // 多维的树节点
  const [selectedDepartments, setSelectedDepartments] = useState<DepartmentOption[]>(
    _.filter<DepartmentOption>(defaultCheckedDepartments) || [],
  );
  const [keyword, setKeyword] = useState<string>('');
  const [checkAll, setCheckAll] = useState<boolean>(false);
  const [expandAll, setExpandAll] = useState<boolean>(false);
  const [checkedNodeKeys, setCheckedNodeKeys] = useState<string[]>([]);
  const [expandedNodeKeys, setExpandedNodeKeys] = useState<string[]>(['1']);
  const allDepartmentMap = _.keyBy(allDepartments, 'ext_id');

  const onCheckAllChange = (e: CheckboxChangeEvent) => {
    let items: DepartmentOption[];
    if (e.target.checked) {
      items = _.uniqWith<DepartmentOption>(
        [...departments, ...selectedDepartments],
        (a, b) => a.ext_id === b.ext_id,
      );
    } else {
      items = _.differenceWith(selectedDepartments, departments, (a, b) => a.ext_id === b.ext_id);
    }
    setSelectedDepartments(items);
    setCheckAll(e.target.checked);
  };

  const onNodesCheck = (checked: { checked: string[]; halfChecked: string[] }) => {
    const checkedExtDepartmentIDs: number[] = [];
    let selectedExtDepartmentIDs = selectedDepartments.map((item) => item.ext_id);
    let checkedKeys = [...checked.checked];

    // 找出本次uncheck的key,根据这些key的ext_id去删除相关checkedKey
    const uncheckedKeys = _.difference(checkedNodeKeys, checkedKeys);
    _.forEach<string>(uncheckedKeys, (key: string) => {
      // @ts-ignore
      checkedKeys = checkedKeys.filter<string>((checkedKey) => {
        return !checkedKey.includes(key);
      });
    });

    // 记录当前所有checked的key
    checkedKeys.forEach((key) => {
      checkedExtDepartmentIDs.push(Number(key));
      selectedExtDepartmentIDs.push(Number(key));
    });

    // 计算需要删除的extDepartmentID
    // @ts-ignore
    const shouldDeleteExtDepartmentIDs = _.difference(
      _.map(departments, 'ext_id'),
      checkedExtDepartmentIDs,
    );
    selectedExtDepartmentIDs = _.difference(
      _.uniq(selectedExtDepartmentIDs),
      _.uniq(shouldDeleteExtDepartmentIDs),
    );

    const items = selectedExtDepartmentIDs.map((selectedExtDepartmentID) => {
      return allDepartmentMap[selectedExtDepartmentID];
    });

    setCheckAll(departments.length === items.length);
    setSelectedDepartments(items);
  };

  const nodeRender = (node: DataNode): ReactNode => {
    return (
      <>
        <FolderFilled
          style={{
            color: '#47a7ff',
            fontSize: 20,
            marginRight: 6,
            verticalAlign: -6,
          }}
        />
        {node.title}
      </>
    );
  };

  useEffect(() => {
    setSelectedDepartments(_.filter<DepartmentOption>(defaultCheckedDepartments) || []);
    setKeyword('');
  }, [defaultCheckedDepartments, visible]);

  // 监听选中部门变化,计算checked的树节点
  useEffect(() => {
    const allDepartmentNodeKeys = _.map(departmentNodes, 'key');
    // 计算当前选中的部门,命中的key
    const matchedKeys: string[] = [];
    allDepartmentNodeKeys.forEach((key: string) => {
      selectedDepartments.forEach((department) => {
        if (key === `${department.ext_id}`) {
          matchedKeys.push(key);
        }
      });
    });
    setCheckedNodeKeys(matchedKeys);
  }, [selectedDepartments]);

  // 关键词变化的时候
  useEffect(() => {
    let filteredDepartments: DepartmentOption[] = [];

    allDepartments.forEach((item) => {
      if (keyword.trim() === '' || item.label.includes(keyword.trim())) {
        filteredDepartments.push(item);
      }
    })

    // 把搜索结果的父级节点放进结果集,方便构造树
    const pushParentDepartment = (item: DepartmentOption) => {
      if (item.ext_parent_id === 0) {
        filteredDepartments.push(item);
        return;
      }
      const parent = allDepartmentMap[item.ext_parent_id];
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      filteredDepartments.push(parent);
      pushParentDepartment(parent);
    };

    filteredDepartments.forEach((item) => {
      pushParentDepartment(item);
    })

    filteredDepartments = _.uniq<DepartmentOption>(filteredDepartments);
    setDepartments(filteredDepartments);

    const {nodes, tree} = buildDepartmentTree(filteredDepartments);

    // 这里同步更新node节点和选中key值
    let checkedKeys: string[] = [];
    nodes.forEach((node) => {
      selectedDepartments.forEach((department) => {
        if (node.key === `${department.ext_id}`) {
          checkedKeys.push(node.key);
        }
      });
    });
    checkedKeys = _.uniq<string>(checkedKeys);
    setCheckedNodeKeys(checkedKeys);

    setCheckAll(false);
    setDepartmentNodes(nodes);
    setDepartmentTree(tree);
  }, [allDepartments, keyword]);

  // @ts-ignore
  return (
    <Modal
      width={665}
      className={'dialog from-item-label-100w'}
      visible={visible}
      zIndex={1001}
      onCancel={() => setVisible(false)}
      onOk={() => {
        if (onFinish) {
          onFinish(selectedDepartments);
        }
        setVisible(false);
      }}
    >
      <h2 className="dialog-title"> 选择部门 </h2>
      <div className={styles.addDepartmentDialogContent}>
        <div className={styles.container}>
          <div className={styles.left}>
            <p className={styles.toolTop} style={{marginBottom: 0}}>
              <Search
                className={styles.searchInput}
                enterButton={'搜索'}
                prefix={<SearchOutlined/>}
                placeholder="请输入部门名称"
                allowClear
                value={keyword}
                onChange={(e) => {
                  setKeyword(e.target.value);
                }}
              />
            </p>
            <p style={{marginBottom: 0}}>
              <Checkbox checked={checkAll} onChange={onCheckAllChange}>
                全部部门({departments.length}):
              </Checkbox>
              <Button
                type={'link'}
                onClick={() => {
                  const currentStatus = !expandAll;
                  if (currentStatus) {
                    setExpandedNodeKeys(_.map(departmentNodes, 'key'));
                  } else {
                    setExpandedNodeKeys(['0']);
                  }
                  setExpandAll(currentStatus);
                }}
                style={{marginRight: 30}}
              >
                {!expandAll ? '展开全部' : '收起全部'}
              </Button>
            </p>
            <div className={styles.allDepartment}>
              {departmentTree.length === 0 && <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
              <Tree
                className={styles.departmentTree}
                autoExpandParent={false}
                checkStrictly={true}
                checkedKeys={checkedNodeKeys}
                defaultExpandedKeys={checkedNodeKeys}
                expandedKeys={expandedNodeKeys}
                // @ts-ignore
                onExpand={(expandedKeys: string[]) => {
                  setExpandedNodeKeys(expandedKeys);
                }}
                height={300}
                switcherIcon={<CaretDownFilled style={{color: '#47a7ff'}}/>}
                checkable={true}
                multiple={true}
                treeData={departmentTree}
                // @ts-ignore
                onCheck={onNodesCheck}
                titleRender={nodeRender}
              />
            </div>
          </div>
          <div className={styles.right}>
            <p>
              已选部门({selectedDepartments.length}):
              <Button
                type={'link'}
                onClick={() => {
                  setSelectedDepartments([]);
                  setCheckAll(false);
                }}
              >
                清空
              </Button>
            </p>
            <ul className={styles.allDepartmentList}>
              {selectedDepartments.map((department) => {
                if (!department) {
                  return <></>
                }

                return (
                  <li
                    key={department.ext_id}
                    onClick={() => {
                      setSelectedDepartments(
                        selectedDepartments.filter((item) => item.ext_id !== department.ext_id),
                      );
                    }}
                  >
                    <div className={styles.avatarAndName}>
                      <div className="flex-col align-left">
                        <FolderFilled
                          style={{
                            color: '#47a7ff',
                            fontSize: 20,
                            marginRight: 6,
                            verticalAlign: -6,
                          }}
                        />
                        {department.name}
                      </div>
                    </div>
                    <CloseOutlined/>
                  </li>
                );
              })}
            </ul>
          </div>
        </div>
      </div>
    </Modal>
  );
}
Example #2
Source File: index.tsx    From dashboard with Apache License 2.0 4 votes vote down vote up
StaffTreeSelectionModal: React.FC<StaffSelectionProps> = (props) => {
  const { visible, setVisible, defaultCheckedStaffs, onFinish, allStaffs } = props;
  const [staffs, setStaffs] = useState<StaffOption[]>([]);
  const [staffNodes, setStaffNodes] = useState<TreeNode[]>([]); // 一维的节点
  const [staffTree, setStaffTree] = useState<TreeNode[]>([]); // 多维的树节点
  const [selectedStaffs, setSelectedStaffs] = useState<StaffOption[]>(defaultCheckedStaffs || []);
  const [keyword, setKeyword] = useState<string>('');
  const [checkAll, setCheckAll] = useState<boolean>(false);
  const [expandAll, setExpandAll] = useState<boolean>(false);
  const [checkedNodeKeys, setCheckedNodeKeys] = useState<string[]>([]);
  const [expandedNodeKeys, setExpandedNodeKeys] = useState<string[]>([rootNode]);
  const allStaffMap = _.keyBy(allStaffs, 'ext_id');

  const onCheckAllChange = (e: CheckboxChangeEvent) => {
    let items: StaffOption[];
    if (e.target.checked) {
      items = _.uniqWith<StaffOption>(
        [...staffs, ...selectedStaffs],
        (a, b) => a.ext_id === b.ext_id,
      );
    } else {
      // @ts-ignore
      items = _.differenceWith<StaffParam>(selectedStaffs, staffs, (a, b) => a.ext_id === b.ext_id);
    }
    setSelectedStaffs(items);
    setCheckAll(e.target.checked);
  };

  const onNodesCheck = (checked: string[]) => {
    const checkedExtStaffIDs: string[] = [];
    let selectedExtStaffIDs = _.map(selectedStaffs, 'ext_id');
    let checkedKeys = [...checked];

    // 找出本次uncheck的key,根据这些key的ext_id去删除相关checkedKey
    const uncheckedKeys = _.difference(checkedNodeKeys, checkedKeys);
    _.forEach<string>(uncheckedKeys, (key: string) => {
      const [, , nodeID] = key.split(separator);
      // eslint-disable-next-line no-param-reassign
      // @ts-ignore
      checkedKeys = checkedKeys.filter<string>((checkedKey) => {
        return !checkedKey.includes(`${separator}${nodeID}`);
      });
    });

    // 记录当前所有checked的key
    checkedKeys.forEach((key) => {
      const [nodeType, , nodeID] = key.split(separator);
      if (nodeType === 'node') {
        checkedExtStaffIDs.push(nodeID);
        selectedExtStaffIDs.push(nodeID);
      }
    });

    // 计算需要删除的extStaffID
    // @ts-ignore
    const shouldDeleteExtStaffIDs = _.difference(_.map(staffs, 'ext_id'), checkedExtStaffIDs);
    selectedExtStaffIDs = _.difference(
      _.uniq(selectedExtStaffIDs),
      _.uniq(shouldDeleteExtStaffIDs),
    );

    const items = selectedExtStaffIDs.map((selectedExtStaffID) => {
      return allStaffMap[selectedExtStaffID];
    });

    setCheckAll(staffs.length === items.length);
    setSelectedStaffs(items);
  };

  const nodeRender = (node: DataNode): ReactNode => {
    const [nodeType, , extStaffID] = node.key.toString().split(separator);
    if (nodeType === 'node') {
      const staff = allStaffMap[extStaffID];
      if (staff) {
        return (
          <div className={styles.staffTitleNode}>
            <img src={FormatWeWorkAvatar(staff?.avatar_url, 60)} className={styles.avatar} />
            <div className={styles.text}>
              <span className={styles.title}>{staff?.name}</span>
              <em
                style={{
                  color: RoleColorMap[staff?.role_type],
                  borderColor: RoleColorMap[staff?.role_type],
                }}
              >
                {RoleMap[staff?.role_type] || '普通员工'}
              </em>
            </div>
          </div>
        );
      }
    }
    return (
      <>
        <FolderFilled
          style={{
            color: '#47a7ff',
            fontSize: 20,
            marginRight: 6,
            verticalAlign: -3,
          }}
        />
        {node.title}
      </>
    );
  };

  useEffect(() => {
    setSelectedStaffs(defaultCheckedStaffs || []);
    setKeyword('');
  }, [defaultCheckedStaffs, visible]);

  // 监听选中员工变化,计算checked的树节点
  useEffect(() => {
    const allStaffNodeKeys = _.map(staffNodes, 'key');
    // 计算当前选中的员工,命中的key
    const matchedKeys: string[] = [];
    allStaffNodeKeys.forEach((key: string) => {
      selectedStaffs.forEach((staff) => {
        if (key.includes(`${separator}${staff?.ext_id}`)) {
          matchedKeys.push(key);
        }
      });
    });
    setCheckedNodeKeys(matchedKeys);
  }, [selectedStaffs, staffNodes]);

  // 关键词变化的时候
  useEffect(() => {
    const filteredStaffs = allStaffs.filter((item) => {
      // 搜索部门名称
      let isDepartmentMatch = false;
      item?.departments?.forEach((department) => {
        if (department.name.includes(keyword)) {
          isDepartmentMatch = true;
        }
      });
      return keyword === '' || isDepartmentMatch || item.label.includes(keyword);
    });
    setStaffs(filteredStaffs);
    const { nodes, tree } = buildStaffTree(filteredStaffs);

    // 这里同步更新node节点和选中key值
    let checkedKeys: string[] = [];
    nodes.forEach((node) => {
      selectedStaffs.forEach((staff) => {
        if (node.nodeKey.includes(`${separator}${staff?.ext_id}`)) {
          checkedKeys.push(node.key);
        }
      });
    });
    checkedKeys = _.uniq<string>(checkedKeys);
    setCheckedNodeKeys(checkedKeys);

    setCheckAll(false);
    setStaffNodes(nodes);
    setStaffTree(tree);
  }, [allStaffs, keyword]);

  // @ts-ignore
  return (
    <Modal
      width={665}
      className={'dialog from-item-label-100w'}
      visible={visible}
      zIndex={1001}
      onCancel={() => setVisible(false)}
      onOk={() => {
        if (onFinish) {
          onFinish(selectedStaffs);
        }
        setVisible(false);
      }}
    >
      <h2 className='dialog-title'> 选择员工 </h2>
      <div className={styles.addStaffDialogContent}>
        <div className={styles.container}>
          <div className={styles.left}>
            <p className={styles.toolTop} style={{ marginBottom: 0 }}>
              <Search
                className={styles.searchInput}
                enterButton={'搜索'}
                prefix={<SearchOutlined />}
                placeholder='请输入员工昵称'
                allowClear
                value={keyword}
                onChange={(e) => {
                  setKeyword(e.target.value);
                }}
              />
            </p>
            <p style={{ marginBottom: 0 }}>
              <Checkbox checked={checkAll} onChange={onCheckAllChange}>
                全部成员({staffs.length}):
              </Checkbox>
              <Button
                type={'link'}
                onClick={() => {
                  const currentStatus = !expandAll;
                  if (currentStatus) {
                    setExpandedNodeKeys(
                      _.map(
                        staffNodes.filter((staffNode) => staffNode.type === 'group'),
                        'key',
                      ),
                    );
                  } else {
                    setExpandedNodeKeys([rootNode]);
                  }
                  setExpandAll(currentStatus);
                }}
                style={{ marginRight: 30 }}
              >
                {!expandAll ? '展开部门' : '收起部门'}
              </Button>
            </p>
            <div className={styles.allStaff}>
              {staffTree.length === 0 && <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
              <Tree
                className={styles.staffTree}
                autoExpandParent={true}
                checkedKeys={checkedNodeKeys}
                defaultExpandedKeys={checkedNodeKeys}
                expandedKeys={expandedNodeKeys}
                // @ts-ignore
                onExpand={(expandedKeys: string[]) => {
                  setExpandedNodeKeys(expandedKeys);
                }}
                height={300}
                switcherIcon={<CaretDownFilled style={{ color: '#47a7ff' }} />}
                checkable={true}
                multiple={true}
                treeData={staffTree}
                // @ts-ignore
                onCheck={onNodesCheck}
                titleRender={nodeRender}
              />
            </div>
          </div>
          <div className={styles.right}>
            <p>
              已选成员({selectedStaffs.length}):
              <Button
                type={'link'}
                onClick={() => {
                  setSelectedStaffs([]);
                  setCheckAll(false);
                }}
              >
                清空
              </Button>
            </p>
            <ul className={styles.allStaffList}>
              {selectedStaffs.map((staff) => {
                if (!staff?.ext_id) {
                  return '';
                }

                return (
                  <li
                    key={staff?.ext_id}
                    onClick={() => {
                      setSelectedStaffs(
                        selectedStaffs.filter((item) => item?.ext_id !== staff?.ext_id),
                      );
                    }}
                  >
                    <div className={styles.avatarAndName}>
                      <img src={staff?.avatar_url} className={styles.avatar} />
                      <div className='flex-col align-left'>
                        <span>{staff?.name}</span>
                      </div>
                    </div>
                    <CloseOutlined />
                  </li>
                );
              })}
            </ul>
          </div>
        </div>
      </div>
    </Modal>
  );
}
Example #3
Source File: DepartmentTree.tsx    From dashboard with Apache License 2.0 4 votes vote down vote up
DepartMentTreeComp = ({ callback }: { callback: (selectedkey: string) => void }) => {
  const [allDepartments, setAllDepartments] = useState<DepartmentList.Item[]>([]);
  const [departments, setDepartments] = useState<DepartmentOption[]>([]);
  const [departmentNodes, setDepartmentNodes] = useState<TreeNode[]>([]); // 一维的节点
  const [departmentTree, setDepartmentTree] = useState<TreeNode[]>([]); // 多维的树节点
  const [selectedDepartments, setSelectedDepartments] = useState<DepartmentOption[]>([]);
  const [keyword] = useState<string>('');
  const [expandAll, setExpandAll] = useState<boolean>(false);
  const [checkedNodeKeys, setCheckedNodeKeys] = useState<string[]>([]);
  const [expandedNodeKeys, setExpandedNodeKeys] = useState<string[]>(['1']);
  const allDepartmentMap = _.keyBy(allDepartments, 'ext_id');

  useEffect(() => {
    QueryDepartmentList({ page_size: 5000 })
      .then((res: any) => {
        if (res?.code === 0 && res?.data && res?.data.items) {
          setAllDepartments(res?.data.items);
          setExpandedNodeKeys(['1']);
        }
      })
      .catch((err) => {
        message.error(err);
      });
  }, []);

  const onNodesCheck = (checked: { checked: string[]; halfChecked: string[] }) => {
    const checkedExtDepartmentIDs: number[] = [];
    let selectedExtDepartmentIDs = selectedDepartments.map((item) => item.ext_id);
    let checkedKeys = [...checked.checked];

    // 找出本次uncheck的key,根据这些key的ext_id去删除相关checkedKey
    const uncheckedKeys = _.difference(checkedNodeKeys, checkedKeys);
    _.forEach<string>(uncheckedKeys, (key: string) => {
      // @ts-ignore
      checkedKeys = checkedKeys.filter<string>((checkedKey) => {
        return !checkedKey.includes(key);
      });
    });

    // 记录当前所有checkedkey
    checkedKeys.forEach((key) => {
      checkedExtDepartmentIDs.push(Number(key));
      selectedExtDepartmentIDs.push(Number(key));
    });

    // 计算需要删除的extDepartmentID
    // @ts-ignore
    const shouldDeleteExtDepartmentIDs = _.difference(
      _.map(departments, 'ext_id'),
      checkedExtDepartmentIDs,
    );
    selectedExtDepartmentIDs = _.difference(
      _.uniq(selectedExtDepartmentIDs),
      _.uniq(shouldDeleteExtDepartmentIDs),
    );

    const items = selectedExtDepartmentIDs.map((selectedExtDepartmentID) => {
      return allDepartmentMap[selectedExtDepartmentID];
    });

    // @ts-ignore
    setSelectedDepartments(items);
  };

  const nodeRender = (node: DataNode): ReactNode => {
    return (
      <div
        onClick={() => {
          // eslint-disable-next-line @typescript-eslint/no-unused-expressions
          callback && callback(String(node.key))
        }}
        style={{ padding: '4px 6px', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow:'ellipsis'}}
      >
        <FolderFilled
          style={{
            color: '#47a7ff',
            fontSize: 20,
            marginRight: 6,
            verticalAlign: -6,
          }}
        />
        <span>
          {/* node.title */}
          {
            // @ts-ignore
            node.title.length>14? <span>{node.title.slice(0,13)}...</span>:<span>{node.title}</span>
          }
          ({node.staff_num})
        </span>
      </div>
    );
  };
  // 监听选中部门变化,计算checked的树节点
  useEffect(() => {
    const allDepartmentNodeKeys = _.map(departmentNodes, 'key');
    // 计算当前选中的部门,命中的key
    const matchedKeys: string[] = [];
    allDepartmentNodeKeys.forEach((key: string) => {
      selectedDepartments.forEach((department) => {
        if (key === `${department.ext_id}`) {
          matchedKeys.push(key);
        }
      });
    });
    setCheckedNodeKeys(matchedKeys);
  }, [selectedDepartments]);

  // 关键词变化的时候
  useEffect(() => {
    const filteredDepartments = allDepartments.filter((item) => {
      return keyword === '' || item.label.includes(keyword);
    });
    // @ts-ignore
    setDepartments(filteredDepartments);
    const { nodes, tree } = buildDepartmentTree(filteredDepartments);
    // 这里同步更新node节点和选中keylet checkedKeys: string[] = [];
    nodes.forEach((node) => {
      selectedDepartments.forEach((department) => {
        if (node.key === `${department.ext_id}`) {
          checkedKeys.push(node.key);
        }
      });
    });
    checkedKeys = _.uniq<string>(checkedKeys);
    setCheckedNodeKeys(checkedKeys);
    setDepartmentNodes(nodes);
    setDepartmentTree(tree);
  }, [allDepartments, keyword]);

  return (
    <div >
      <div className={styles.header}>
        <span className={styles.departmentTitle}>部门信息</span>
        <a
          type={'link'}
          onClick={() => {
            const currentStatus = !expandAll;
            if (currentStatus) {
              setExpandedNodeKeys(_.map(departmentNodes, 'key'));
            } else {
              setExpandedNodeKeys(['0']);
            }
            setExpandAll(currentStatus);
          }}
        >
          {!expandAll ? '展开全部' : '收起全部'}
        </a>
      </div>
      <div className={styles.treeContainer}>
        <Tree
          autoExpandParent={false}
          checkStrictly={true}
          checkedKeys={checkedNodeKeys}
          expandedKeys={expandedNodeKeys}
          // @ts-ignore
          onExpand={(expandedKeys: string[]) => {
            setExpandedNodeKeys(expandedKeys);
          }}
          height={300}
          switcherIcon={<CaretDownFilled style={{ color: '#47a7ff' }} />}
          multiple={true}
          treeData={departmentTree}
          // @ts-ignore
          onCheck={onNodesCheck}
          titleRender={nodeRender}
        />
      </div>
    </div>
  );
}