## 通讯录组件

## 代码演示

```tsx
import React, { useCallback, useState } from 'react';
import { Button, SelectPeople } from 'ui-component-5e';
import { UserNode } from './index';
import { mockData } from './mockData';
import './indexMd.less';
import './index.less';

const ESelectPeople: React.FC = () => {
  const [selectedIds, setSelectedIds] = useState([]);
  const [pcVisible, setPcVisible] = useState(false);
  const [mobileVisible, setMobileVisible] = useState(false);
  const multi = true;
  const onHandleClick = useCallback(() => {
    setPcVisible(true);
    setMobileVisible(false);
  }, []);
  const onHandleMobileClick = useCallback(() => {
    setMobileVisible(true);
    setPcVisible(false);
  }, []);
  const onConfirm = () => {
    setPcVisible(false);
    setSelectedIds([]);
  };
  const onCancel = () => {
    setPcVisible(false);
  };
  const handleSelect = (selected: boolean, value: number, type?: 'department' | 'userName') => {
    console.log(selected, value, type)
    if (multi) {
      setSelectedIds((preState) =>
        selected
          ? preState.concat(value)
          : preState.filter((id) => id !== value),
      );
    } else {
      setSelectedIds([value]);
    }
  };
  const renderNode = (
    itemNode: UserNode,
    type: 'departmentName' | 'userName',
  ) => {
    const departNode = () => (
      <div className="contact-title">{`部门${itemNode.id}`}</div>
    );
    const userNode = () => (
      <div className="contact-user">
        <img className="contact-avatar" src={itemNode.avatar} />
        <div className="contact-title">{itemNode.wxUserId}</div>
      </div>
    );
    return <span>{type === 'departmentName' ? departNode() : userNode()}</span>;
  };

  return (
    <>
      <Button onClick={onHandleClick}>打开web通讯录</Button>
      <Button onClick={onHandleMobileClick}>打开mobile通讯录</Button>
      {pcVisible && (
        <div className="select-people-box">
          <SelectPeople
            data={mockData}
            handleSelect={handleSelect}
            isPcClient
            multi={multi}
            onCancel={onCancel}
            onConfirm={onConfirm}
            renderNode={renderNode}
            selectedIds={selectedIds}
            title="选择通讯录"
          />
        </div>
      )}
      {mobileVisible && (
        <div className="select-people-mobile-box">
          <SelectPeople
            data={mockData}
            handleSelect={handleSelect}
            multi={multi}
            onCancel={onCancel}
            onConfirm={onConfirm}
            renderNode={renderNode}
            selectedIds={selectedIds}
            title="选择通讯录"
          />
        </div>
      )}
    </>
  );
};
export default () => <ESelectPeople />;
```

---

## API

TreePeople props

| 参数         | 说明                                     | 类型                                                         | 默认值 |
| ------------ | ---------------------------------------- | ------------------------------------------------------------ | ------ |
| isPcClient   | 是否客户端                               | boolean                                                      | false  |
| title        | 通讯录名称(只有移动端才显示 title)       | string                                                       | \-     |
| renderNode   | 自定义渲染节点                           | (nodeData,type: 'departmentName' ｜ 'userName') => ReactNode | \-     |
| footer       | 自定义底部按钮                           | ReactNode                                                    | \-     |
| onConfirm    | 点击确定回调                             | function(e)                                                  | \-     |
| onCancel     | 点击取消回调                             | function(e)                                                  | \-     |
| data         | treeNodes 数据(value 在整个树范围内唯一) | array<{value, title, children,departInfoList}>               | \-     |
| multi        | 支持点选多个节点                         | boolean                                                      | false  |
| selectedIds  | 选中的树节点数组                         | number[]                                                     | [ ]    |
| handleSelect | 点击选中的回调                           | function                                                     | \-     |
| levelPadding | 层级节点外边距                           | number                                                       | 24     |

---

## FAQ

##### 为什么首节点是展开状态？

业务需要，最顶层部门展开当前部门下的人员列表信息以及子部门节点

##### 为什么移动端演示的通讯录组件底部按钮位置不对？

因为 position:fixed 相对浏览器窗口定位，当我们在移动端使用通讯录组件作为页面时，底部按钮位置固定在手机屏幕底部，而在演示的通讯录组件时，底部按钮自然固定在浏览器底部
