192 lines
5.8 KiB
JavaScript
192 lines
5.8 KiB
JavaScript
import React, { useState,useMemo,useEffect } from 'react';
|
|
import { Input, Transfer, Button,Tree } from "antd"
|
|
import {RedoOutlined } from '@ant-design/icons';
|
|
const { Search } = Input;
|
|
export default function PersonForm({treeList,deptList,callback,onCancel,selectPerson}) {
|
|
const [searchValue, setSearchValue] = useState('');
|
|
const [expandedKeys, setExpandedKeys] = useState([treeList[0].key]);
|
|
const [autoExpandParent, setAutoExpandParent] = useState(true);
|
|
const [treeData, setTreeData] = useState(treeList)
|
|
|
|
// 处理搜索时树形数据高亮
|
|
const loop = (data) =>
|
|
data.map((item) => {
|
|
const index = item.title.indexOf(searchValue);
|
|
const beforeStr = item.title.substr(0, index);
|
|
const afterStr = item.title.substr(index + searchValue.length);
|
|
const title =
|
|
index > -1 ? (
|
|
<span>
|
|
{beforeStr}
|
|
<span style={{color:"#ff8c64"}}>{searchValue}</span>
|
|
{afterStr}
|
|
</span>
|
|
) : (
|
|
<span>{item.title}</span>
|
|
);
|
|
if (item.children) {
|
|
return { title, key: item.key || item.value, children: loop(item.children) };
|
|
}
|
|
|
|
return {
|
|
title,
|
|
key: item.key || item.value,
|
|
};
|
|
})
|
|
const getParentKey =(key, tree) => {
|
|
let parentKey
|
|
for (let i = 0; i < tree.length; i++) {
|
|
const node = tree[i];
|
|
if (node.children) {
|
|
if (node.children.some((item) => item.value === key)) {
|
|
parentKey = node.value;
|
|
} else if (getParentKey(key, node.children)) {
|
|
parentKey = getParentKey(key, node.children);
|
|
}
|
|
}
|
|
}
|
|
return parentKey;
|
|
}
|
|
|
|
|
|
// 将树形节点改为一维数组
|
|
const generateList = (data, dataList) => {
|
|
for (let i = 0; i < data.length; i++) {
|
|
const node = data[i];
|
|
const { key, title,value } = node;
|
|
dataList.push({ key:key||value, title, });
|
|
if (node.children) {
|
|
generateList(node.children, dataList);
|
|
}
|
|
}
|
|
return dataList
|
|
}
|
|
|
|
// 树节点展开/收缩
|
|
const onExpand = (expandedKeys) => {
|
|
setExpandedKeys(expandedKeys)
|
|
setAutoExpandParent(false)
|
|
}
|
|
|
|
|
|
|
|
// 搜索框回调
|
|
const onInputChange = (e) => {
|
|
let { value } = e.target
|
|
value = String(value).trim()
|
|
const dataList = generateList(treeData, [])
|
|
let expandedKeys = dataList
|
|
.map((item) => {
|
|
if (item.title.indexOf(value) > -1) {
|
|
return getParentKey(item.key, treeData)
|
|
}
|
|
return null;
|
|
})
|
|
.filter((item, i, self) => item && self.indexOf(item) === i)
|
|
setExpandedKeys(expandedKeys)
|
|
setAutoExpandParent(true)
|
|
setSearchValue(value)
|
|
}
|
|
|
|
const customRender = (record) => {
|
|
let name;
|
|
if (record?.dept?.deptName) {
|
|
name = record.dept.deptName
|
|
} else {
|
|
name = deptList.find(item => item.deptId == record.parentId)?.deptName
|
|
}
|
|
return <span>{record.title}<span>{ name ? `【${name}】` :''}</span></span>;
|
|
}
|
|
|
|
// 穿梭框处理
|
|
const isChecked = (selectedKeys, eventKey) => selectedKeys.includes(eventKey);
|
|
const generateTree = (treeNodes = [], checkedKeys = []) =>
|
|
treeNodes.map(({ children, ...props }) => ({
|
|
...props,
|
|
disabled: checkedKeys.includes(props.key),
|
|
children: generateTree(children, checkedKeys),
|
|
}));
|
|
const TreeTransfer = ({ dataSource, targetKeys, ...restProps }) => {
|
|
|
|
const transferDataSource = [];
|
|
function flatten(list = []) {
|
|
list.forEach((item) => {
|
|
item.key = item.key ||item.value
|
|
transferDataSource.push(item);
|
|
flatten(item.children);
|
|
});
|
|
}
|
|
flatten(dataSource);
|
|
return (
|
|
<Transfer
|
|
{...restProps}
|
|
targetKeys={targetKeys}
|
|
dataSource={transferDataSource}
|
|
className="tree-transfer"
|
|
render={customRender}
|
|
showSelectAll={false}
|
|
>
|
|
{({ direction, onItemSelect, selectedKeys }) => {
|
|
if (direction === 'left') {
|
|
const checkedKeys = [...selectedKeys, ...targetKeys];
|
|
return (
|
|
<Tree
|
|
blockNode
|
|
checkable
|
|
checkStrictly
|
|
onExpand={onExpand}
|
|
expandedKeys={expandedKeys}
|
|
autoExpandParent={autoExpandParent}
|
|
height={300}
|
|
checkedKeys={checkedKeys}
|
|
treeData={loop(treeData)}
|
|
onCheck={(val, { node: { key },checkedNodes }) => {
|
|
onItemSelect(key, !isChecked(checkedKeys, key));
|
|
}}
|
|
onSelect={(_, { node: { key } }) => {
|
|
onItemSelect(key, !isChecked(checkedKeys, key));
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
}}
|
|
</Transfer>
|
|
);
|
|
};
|
|
|
|
|
|
const [targetKeys, setTargetKeys] = useState([]);
|
|
const onChange = (keys,direction) => {
|
|
setTargetKeys(keys);
|
|
};
|
|
useEffect(() => {
|
|
setTargetKeys(selectPerson)
|
|
}, [selectPerson])
|
|
|
|
|
|
return (
|
|
<>
|
|
<Input.Group compact>
|
|
<Search
|
|
addonBefore="用户名称"
|
|
placeholder="请输入用户名称"
|
|
allowClear
|
|
onChange={onInputChange}
|
|
style={{
|
|
width: "95.3%",
|
|
}}
|
|
/>
|
|
<Button icon={<RedoOutlined style={{color:"#8d8d8d"}} />}></Button>
|
|
</Input.Group>
|
|
|
|
<div className='transfer-content' style={{marginTop:20}}>
|
|
<TreeTransfer dataSource={treeData} targetKeys={targetKeys} onChange={onChange} />
|
|
</div>
|
|
<div style={{ display: 'flex', justifyContent: 'flex-end',columnGap:10,marginTop:10 }}>
|
|
<Button onClick={onCancel}>取消</Button>
|
|
<Button type="primary" onClick={() => callback(targetKeys)}>确认</Button>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|