2021-03-16 树结构拼接数据 然后选择

import React, { Component } from 'react'
import { Tree, Modal, Input, Icon, Form, message, Menu, Dropdown } from 'antd'
import { removeGenericEmpty } from '@/libs/util'
import {
queryAllOrganization,
queryMember,
getMemberGroup,
getMemberByGroup
} from '@/api'
import './orgAGroupModal.scss'

const { TreeNode } = Tree
const { Search } = Input

function updateTreeData(list, key, children) {
return list.map((node) => {
if (node.key === key) {
return {
...node,
children: node.children ? node.children.concat(children) : children
}
}
if (node.children) {
return {
...node,
children: updateTreeData(node.children, key, children)
}
}

return node

})
}

function formatOrgData(ary) {
if (!ary) return
const newTree = ary.map((item) => ({
...item,
title: ${item.name} ${ item.numberOfMember ?{item.numberOfMember})` : '' }`, key: item.parent ? `p{item.id}` : item.id,
value: +item.id,
children: formatOrgData(item.children)
}))
return newTree
}

function formatGroupData(ary) {
if (!ary) return
const newTree = ary.map((item) => ({
...item,
title: ${item.name} ${ item.numberOfMember ?{item.numberOfMember})` : '' }`, key: item.number ? `g{item.id}` : item.id,
children: formatGroupData(item.children)
}))
return newTree
}

interface Iprops {
visible: boolean
transfer: any
title: string
closeOrgAGroupModal: any
}

interface Istate {
expandedOrgKeys: string[]
autoOrgExpandParent: boolean
checkedOrgKeys: any[]
selectedOrgKeys: string[]
listType: number
firstSelectedOrgKey: string
orgData: any
groupsData: {
id: string | number
name: string
number?: string
numberOfMember?: number
remarks?: string
sortNumber?: number
updateTime?: string
}[]
groupRightAry: any[]
autoGroupExpandParent: boolean
expandedGroupKeys: string[]
checkedGroupKeys: any[]
selectedGroupKeys: string[]
firstSelectedGroupKey: string
personAry: any[]
}

class OrgAGroupModal extends Component<Iprops, Istate> {
constructor(props) {
super(props)
this.state = {
orgData: [],
expandedOrgKeys: ['1'],
firstSelectedOrgKey: '', // 第一次点击节点,防止重复点击
checkedOrgKeys: [], // 左侧的keys
selectedOrgKeys: [],
autoOrgExpandParent: true,
listType: 1, // 1 组织列表 2 人员分组
groupRightAry: [],
groupsData: [{ id: '', name: '' }],
autoGroupExpandParent: true,
expandedGroupKeys: ['1'],
checkedGroupKeys: [],
selectedGroupKeys: [],
firstSelectedGroupKey: '',
personAry: []
}
}

componentDidMount() {
this.fetchOrg()
this.fetchMemberGroup()
}

// 展开树节点
onOrgExpand = (expandedKeys, e) => {
this.setState({
expandedOrgKeys: expandedKeys,
autoOrgExpandParent: false
})
}

onOrgCheck = (checkedKeys, e) => {
const { personAry } = this.state
const orgPersonAry = e.checkedNodes
.filter((item, index) => !item.key.startsWith('p'))
.map((item) => ({
title: item.props.title,
key: item.key
}))

this.setState({
  checkedOrgKeys: checkedKeys,
  personAry: [...personAry, ...orgPersonAry]
})

}

// p 代表组织
onOrgSelect = (selectedKeys, e) => {
const { orgData, firstSelectedOrgKey } = this.state
const selectedKey = selectedKeys[0]
if (!selectedKey.startsWith('p') || selectedKey === firstSelectedOrgKey)
return
// 查找的时候位置节点的id需要去掉p
queryMember({ department: selectedKey.slice(1) }).then((res) => {
const processedTree = updateTreeData(
orgData,
selectedKey,
formatOrgData(res.data.records)
)
this.setState({
orgData: processedTree,
firstSelectedOrgKey: selectedKey
})
})
}

renderTreeNodes = (data) => {
return data.map((item) => {
if (item && item.children) {
return (
<TreeNode title={${item.title}} key={item.key} dataRef={item}>
{this.renderTreeNodes(item.children)}
</TreeNode>
)
}
return <TreeNode key={item.key} {...item} />
})
}

// 搜索组织列表
onOrgSearch = (value?: string) => {
this.fetchOrg(value)
}

// 删除选择的人员或位置
deleteCheckedNode = (key) => {
const { personAry } = this.state
const newPersonAry = personAry.filter((item) => item !== key)
this.setState({
personAry: newPersonAry
})
}

// 获取位置列表
fetchOrg = (name?: string) => {
queryAllOrganization(removeGenericEmpty({ name }), null, {}).then((res) => {
const { organization } = res.data
const orgAry = []
if (organization) {
// @ts-ignore
orgAry.push(organization)
}
this.setState({
orgData: formatOrgData(orgAry)
})
})
}

// 分组 --------------------------------
// 搜索分组列表
onGroupSearch = (value?: string) => {
this.fetchMemberGroup(value)
}

// 获取人员分组
fetchMemberGroup = (name?: string) => {
getMemberGroup({ name }).then((res) => {
if (res.data) {
const { records } = res.data
this.setState({ groupsData: formatGroupData(records) })
}
})
}

// 展开树节点
onGroupExpand = (expandedKeys, e) => {
this.setState({
expandedGroupKeys: expandedKeys,
autoGroupExpandParent: false
})
}

onGroupCheck = (checkedKeys, e) => {
const { personAry } = this.state
const groupPersonAry = e.checkedNodes
.filter((item, index) => !item.key.startsWith('g'))
.map((item) => ({
title: item.props.title,
key: item.key
}))
this.setState({
personAry: [...personAry, ...groupPersonAry],
checkedGroupKeys: checkedKeys
})
}

// 点击节点出现人员
onGroupSelect = (selectedKeys, e) => {
// 人员的key加上D区分位置的key
const { groupsData, firstSelectedGroupKey } = this.state
const selectedKey = selectedKeys[0]
if (!selectedKey.startsWith('g') || selectedKey === firstSelectedGroupKey)
return
getMemberByGroup({ memberGroupId: selectedKey.slice(1) }).then((res) => {
const processedTree = updateTreeData(
groupsData,
selectedKey,
formatGroupData(res.data.records)
)
this.setState({
groupsData: processedTree,
firstSelectedGroupKey: selectedKey
})
})
}

// 公共
closeOrgSelectTree = () => {
this.props.closeOrgAGroupModal()
}

handleSubmit = () => {
const { personAry } = this.state
if (personAry.length > 0) {
const personIdList = personAry.map((item) => item.key)
this.props.transfer({
personIdList
})
} else {
message.warning('请选择人员')
}
}

render() {
const { visible, title } = this.props
const {
orgData,
selectedOrgKeys,
expandedOrgKeys,
autoOrgExpandParent,
groupRightAry,
checkedOrgKeys,
listType,
groupsData,
autoGroupExpandParent,
expandedGroupKeys,
checkedGroupKeys,
selectedGroupKeys,
personAry
} = this.state

const menu = (
  <Menu>
    <Menu.Item>
      <a
        target="_blank"
        rel="noopener noreferrer"
        onClick={() => {
          this.setState({ listType: 1 })
        }}
      >
        组织列表
      </a>
    </Menu.Item>
    <Menu.Item>
      <a
        target="_blank"
        rel="noopener noreferrer"
        onClick={() => {
          this.setState({ listType: 2 })
        }}
      >
        人员分组
      </a>
    </Menu.Item>
  </Menu>
)
return (
  <>
    <Modal
      title="添加人员"
      visible={visible}
      maskClosable={false}
      width={855}
      destroyOnClose
      onOk={this.handleSubmit}
      onCancel={this.closeOrgSelectTree}
    >
      <div className="box-wrapper">
        <div>
          <Dropdown overlay={menu}>
            <a
              style={{ color: '#666' }}
              onClick={(e) => e.preventDefault()}
            >
              {listType === 1 ? '组织机构' : '人员分组'}{' '}
              <Icon type="down" />
            </a>
          </Dropdown>
          {listType === 1 ? (
            <div className="small-box">
              <Search
                style={{ marginBottom: 8 }}
                placeholder="请输入关键字查找"
                onSearch={this.onOrgSearch}
              />
              <Tree
                checkable
                onExpand={this.onOrgExpand}
                defaultExpandAll
                expandedKeys={expandedOrgKeys}
                autoExpandParent={autoOrgExpandParent}
                onCheck={this.onOrgCheck}
                checkedKeys={checkedOrgKeys}
                onSelect={this.onOrgSelect}
                selectedKeys={selectedOrgKeys}
              >
                {this.renderTreeNodes(orgData)}
              </Tree>
            </div>
          ) : null}
          {listType === 2 ? (
            <div className="small-box">
              <Search
                style={{ marginBottom: 8 }}
                placeholder="请输入关键字查找"
                onSearch={this.onGroupSearch}
              />
              <Tree
                checkable
                onExpand={this.onGroupExpand}
                defaultExpandAll
                expandedKeys={expandedGroupKeys}
                autoExpandParent={autoGroupExpandParent}
                onCheck={this.onGroupCheck}
                checkedKeys={checkedGroupKeys}
                onSelect={this.onGroupSelect}
                selectedKeys={selectedGroupKeys}
              >
                {this.renderTreeNodes(groupsData)}
              </Tree>
            </div>
          ) : null}
        </div>
        <div>
          <div>
            已选择人员{' '}
            <span style={{ color: '#ccc', marginLeft: 12 }}>
              <Icon type="control" />{' '}
              <span className="detail-color">{personAry.length}</span>个人员
            </span>
          </div>
          <div className="small-box right">
            {personAry.map((item, index) => (
              <div key={item.id} className="flex-between">
                <span>{item.title}</span>
                <Icon
                  type="close"
                  className="close-icon"
                  onClick={() => {
                    this.deleteCheckedNode(item.key)
                  }}
                />
              </div>
            ))}
          </div>
        </div>
      </div>
    </Modal>
  </>
)

}
}
export default Form.create()(OrgAGroupModal)

css

.box-wrapper {
display: flex;
justify-content: space-around;
.small-box {
width: 380px;
height: 363px;
margin-top: 6px;
margin-bottom: 6px;
border: 1px solid #d9d9d9;
padding: 12px;
overflow: auto;
}
.right {
padding: 16px 30px;
.flex-between {
display: flex;
justify-content: space-between;
line-height: 28px;
.close-icon {
color: #999;
cursor: pointer;
&:hover {
color: #333
}
}
}
}
}

用法

<OrgAGroupModal
// @ts-ignore
title="添加人员"
visible={orgTreeVisible}
closeOrgAGroupModal={this.closeOrgTree}
transfer={this.receiveOrgTreeData}
/>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容