cjd-parkball
Version:
> 中后台业务组件库,中后台就像公园,进入需要买门票(登录),所以以 Parkball(公园球) 命名,公园内必定捕获!作为一个组件库,提供使用方法文档,方便开发者的调用
248 lines (235 loc) • 7.43 kB
JavaScript
import React from 'react'
import { Tree, Input, Icon } from '../..'
import './index.scss'
const { TreeNode } = Tree
const { Search } = Input
export default class LayerTree extends React.Component {
constructor () {
super()
this.onAddItem = this.onAddItem.bind(this)
this.onTreeHover = this.onTreeHover.bind(this)
this.onTreeOut = this.onTreeOut.bind(this)
this.onTreeItemHover = this.onTreeItemHover.bind(this)
this.onTreeItemOut = this.onTreeItemOut.bind(this)
this.onTreeItemEdit = this.onTreeItemEdit.bind(this)
this.onTreeItemDel = this.onTreeItemDel.bind(this)
this.onItemIconHover = this.onItemIconHover.bind(this)
this.onSelect = this.onSelect.bind(this)
}
state = {
searchValue: '',
searchLevel: 0,
hoverActiveLevel: -1,
hoverActiveItemIndex: -1,
editItemIndex: -1,
activeEditLevel: -1,
selectedItem: '',
}
onTreeHover = (index) => {
this.setState({
hoverActiveLevel: index,
})
}
onTreeOut = (et) => {
if (et.currentTarget.contains(et.target)) {
return 0
}
this.setState({
hoverActiveLevel: -1,
})
return 1
}
onTreeItemHover = (level, index) => {
setTimeout(() => {
const { hoverActiveLevel } = this.state
if (level === hoverActiveLevel + 1) {
this.setState({
hoverActiveItemIndex: index,
})
}
}, 0)
}
onTreeItemOut = (et) => {
if (et.currentTarget.contains(et.target)) {
return 0
}
this.setState({
hoverActiveItemIndex: -1,
})
return 1
}
onItemIconHover = (et) => {
et.preventDefault()
et.stopPropagation()
}
onChange = (searchLevel, e) => {
const { value } = e.target
this.setState({
searchValue: value,
searchLevel,
})
}
onSelect = (itemKey) => {
const { onSelect } = this.props
const { selectedItem } = this.state
const { hoverActiveLevel, hoverActiveItemIndex } = this.state
const selectedItemId = `${hoverActiveLevel}-${hoverActiveItemIndex}`
if (selectedItem !== selectedItemId) {
onSelect({
key: itemKey,
level: hoverActiveLevel + 1,
index: hoverActiveItemIndex,
})
this.setState({
selectedItem: selectedItemId,
})
}
}
onAddItem = (level, value, et) => {
const { onAdd } = this.props
typeof onAdd === 'function' && onAdd({
level, value, et,
})
}
onTreeItemClick4Edit = (level, index, et) => {
et.preventDefault()
et.stopPropagation()
this.setState({
editItemIndex: index,
activeEditLevel: level,
})
}
onTreeItemEdit = (level, index, value, et) => {
et.preventDefault()
et.stopPropagation()
const { onEdit } = this.props
typeof onEdit === 'function' && onEdit({
level, index, value, et,
})
this.setState({
editItemIndex: -1,
})
}
onTreeItemDel = (level, index, et) => {
et.preventDefault()
et.stopPropagation()
const { onDel } = this.props
typeof onDel === 'function' && onDel({
level, index, et,
})
}
render () {
const indexMap = [
'一级类目',
'二级类目',
'三级类目',
'四级类目',
]
const {
layerTreeData, detailTpl, layerTreeHeight, detailWidth,
} = this.props
const {
searchValue, searchLevel, hoverActiveLevel, hoverActiveItemIndex, editItemIndex, activeEditLevel,
} = this.state
const layerTreeItemWidth = 180
const layerTreeItemMargin = 30
const layerTreeDetailWidth = detailWidth || 400
const LayerTreeWidth = ((layerTreeItemWidth + layerTreeItemMargin) * layerTreeData.length) + (detailTpl && detailTpl.tpl ? layerTreeDetailWidth : 0)
const loop = (data, sl) => {
const filteredIndex = []
const filterData = sl === searchLevel
? data.filter((i, index) => {
if (new RegExp(searchValue).test(i.key)) {
filteredIndex.push(index)
return true
}
return false
})
: data
return filterData.map((item, i) => {
const index = item.title.indexOf(searchValue)
const beforeStr = item.title.substr(0, index)
const afterStr = item.title.substr(index + searchValue.length)
const titleText = (index > -1 && sl === searchLevel)
?
(<div style={{ display: 'inline-block' }}>
{beforeStr}
<span style={{ color: '#f50' }}>
{searchValue}
</span>{afterStr}
</div>)
:
item.title
/* eslint-disable jsx-a11y/mouse-events-have-key-events */
const title = (sl === activeEditLevel && (filteredIndex[i] || i) === editItemIndex) ? (<Search
className="tree-item__edit"
placeholder=""
size="small"
enterButton="确定"
onSearch={this.onTreeItemEdit.bind(this, sl, filteredIndex[i] || i)}
/>) : (<span
className="tree-item"
onMouseOver={this.onTreeItemHover.bind(this, sl, filteredIndex[i] || i)}
onMouseOut={this.onTreeItemOut}
>
{titleText}
{sl === hoverActiveLevel + 1 && (filteredIndex[i] || i) === hoverActiveItemIndex ? <span
className="tree-item__icons"
onFocus={this.onItemIconHover}
onMouseOver={this.onItemIconHover}
>
<Icon
className="tree-item__icon"
type="edit"
onClick={this.onTreeItemClick4Edit.bind(this, sl, filteredIndex[i] || i)}
/>
{item.isDeletable ? <Icon
className="tree-item__icon"
type="delete"
onClick={this.onTreeItemDel.bind(this, sl, filteredIndex[i] || i)}
/> : ''}
</span> : ''}
</span>)
return <TreeNode key={item.key} title={title} />
})
}
return (
/* eslint-disable jsx-a11y/mouse-events-have-key-events */
<div
className="layer-tree"
style={{
width: `${LayerTreeWidth}px`,
height: `${layerTreeHeight || 300}px`,
}}
>
{layerTreeData.map((data, index) => {
if (detailTpl && detailTpl.layerLevel <= index + 1) {
return ''
}
return (<div
key={index}
className={`layer-tree__item layer-tree__item--${index}`}
onMouseOver={this.onTreeHover.bind(this, index)}
onMouseOut={this.onTreeOut}
>
<div className="layer-tree__item--title">{indexMap[index]}</div>
<Search style={{ marginBottom: 8 }} placeholder="Search" onChange={this.onChange.bind(this, index + 1)} />
<Tree
showIcon={false}
onSelect={this.onSelect}
>
{loop(data, index + 1)}
</Tree>
{index === hoverActiveLevel ? <Search
className="tree-item__add"
placeholder=""
enterButton="添加"
onSearch={this.onAddItem.bind(this, index + 1)}
/> : ''}
</div>)
})}
{detailTpl && layerTreeData.length + 1 >= detailTpl.layerLevel && detailTpl.tpl ? <div className="layer-tree__detail" style={{ width: `${layerTreeDetailWidth - 60}px` }}>{detailTpl.tpl(detailTpl.tplData)}</div> : ''}
</div>
)
}
}