120 lines
3.2 KiB
JavaScript
120 lines
3.2 KiB
JavaScript
import { Tree, Tag, Divider, Button, Space } from 'antd'
|
||
import { useState, useEffect } from 'react'
|
||
import './TreeFilterPanel.css'
|
||
|
||
/**
|
||
* 树形筛选面板组件
|
||
* @param {Object} props
|
||
* @param {Array} props.treeData - 树形数据
|
||
* @param {string} props.selectedKey - 当前选中的节点ID
|
||
* @param {string} props.tempSelectedKey - 临时选中的节点ID(确认前)
|
||
* @param {string} props.treeTitle - 树标题
|
||
* @param {Function} props.onSelect - 选择变化回调
|
||
* @param {Function} props.onConfirm - 确认筛选
|
||
* @param {Function} props.onClear - 清除筛选
|
||
* @param {string} props.placeholder - 占位提示文本
|
||
*/
|
||
function TreeFilterPanel({
|
||
treeData,
|
||
selectedKey,
|
||
tempSelectedKey,
|
||
treeTitle = '分组筛选',
|
||
onSelect,
|
||
onConfirm,
|
||
onClear,
|
||
placeholder = '请选择分组进行筛选',
|
||
}) {
|
||
// 获取所有节点的key用于默认展开
|
||
const getAllKeys = (nodes) => {
|
||
let keys = []
|
||
const traverse = (node) => {
|
||
keys.push(node.key)
|
||
if (node.children) {
|
||
node.children.forEach(traverse)
|
||
}
|
||
}
|
||
nodes.forEach(traverse)
|
||
return keys
|
||
}
|
||
|
||
const [expandedKeys, setExpandedKeys] = useState([])
|
||
|
||
// 初始化时展开所有节点
|
||
useEffect(() => {
|
||
if (treeData && treeData.length > 0) {
|
||
setExpandedKeys(getAllKeys(treeData))
|
||
}
|
||
}, [treeData])
|
||
|
||
// 查找节点名称
|
||
const findNodeName = (nodes, id) => {
|
||
for (const node of nodes) {
|
||
if (node.key === id) return node.title
|
||
if (node.children) {
|
||
const found = findNodeName(node.children, id)
|
||
if (found) return found
|
||
}
|
||
}
|
||
return ''
|
||
}
|
||
|
||
const handleTreeSelect = (selectedKeys) => {
|
||
const key = selectedKeys[0] || null
|
||
onSelect?.(key)
|
||
}
|
||
|
||
const handleExpand = (keys) => {
|
||
setExpandedKeys(keys)
|
||
}
|
||
|
||
return (
|
||
<div className="tree-filter-panel">
|
||
{/* 已选择的筛选条件 */}
|
||
<div className="tree-filter-selected">
|
||
{tempSelectedKey ? (
|
||
<div className="tree-filter-tag">
|
||
<span className="tree-filter-label">已选择分组:</span>
|
||
<Tag color="blue" closable onClose={() => onSelect?.(null)}>
|
||
{findNodeName(treeData, tempSelectedKey)}
|
||
</Tag>
|
||
</div>
|
||
) : (
|
||
<div className="tree-filter-placeholder">
|
||
<span>{placeholder}</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<Divider style={{ margin: '12px 0' }} />
|
||
|
||
{/* 树形选择器 */}
|
||
<div className="tree-filter-container">
|
||
<div className="tree-filter-header">{treeTitle}</div>
|
||
<Tree
|
||
treeData={treeData}
|
||
expandedKeys={expandedKeys}
|
||
onExpand={handleExpand}
|
||
onSelect={handleTreeSelect}
|
||
selectedKeys={tempSelectedKey ? [tempSelectedKey] : []}
|
||
/>
|
||
</div>
|
||
|
||
<Divider style={{ margin: '12px 0' }} />
|
||
|
||
{/* 操作按钮 */}
|
||
<div className="tree-filter-actions">
|
||
<Space>
|
||
<Button size="small" onClick={onClear}>
|
||
清除筛选
|
||
</Button>
|
||
<Button size="small" type="primary" onClick={onConfirm}>
|
||
确定
|
||
</Button>
|
||
</Space>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default TreeFilterPanel
|