树结构

26 阅读2分钟

image.png

image.png

import { Modal, Row, Col, Input, Tree, Icon } from 'antd';
import { FormattedMessage } from 'umi-plugin-react/locale';
import styles from './style.less';

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

class MenSearch extends React.Component {
        constructor(props) {
                super(props);
                this.state = {
                        MenList: {},
                        autoExpandParent: true,
                        checkedKeys: [],
                        expandedKeys: [],
                        selectedItems: [],
                        isSelectionDisabled: false,
                };
        }
        // 展开收缩树节点
        onExpand = expandedKeys => {
                console.log('onExpand', expandedKeys);
                this.setState({
                        expandedKeys,
                        autoExpandParent: false,
                });
        };
        // 选中树节点
        onCheck = checkedKeys => {
                console.log('onCheck', checkedKeys);
                // 获取选中一整条的数据
                const newSelectedItems = this.getSelectedItems(checkedKeys, this.props.menuData);
                // 获取数据中不能选择的父节点
                const titlesWithChildren = this.props.menuData
                        .filter(item => item.children)
                        .map(item => item.title);
                // 过滤掉不用选择的父节点
                const filteredSelectedItems = newSelectedItems.filter(
                        item => !titlesWithChildren.includes(item.title),
                );
                console.log('Filtered Selected Items:', filteredSelectedItems);
                // 获取取消选中的项
                const previouslySelectedItems = this.state.selectedItems.map(item => item.id);
                const uncheckedKeys = previouslySelectedItems.filter(item => !checkedKeys.includes(item));
                // 找到取消选中的具体项
                const removedItems = uncheckedKeys.map(items =>
                        this.state.selectedItems.find(item => item.id === items),
                );
                console.log('Removed Items:', removedItems);
                // 合并已选中的项和新选中的项,并移除取消选中的项
                const combinedItems = [
                        ...this.state.selectedItems.filter(item => !removedItems.includes(item)),
                        ...filteredSelectedItems,
                ];
                // 过滤重复项
                const uniqueSelectedItems = Array.from(new Set(combinedItems.map(item => item.id))).map(id =>
                        combinedItems.find(item => item.id === id),
                );
                // 超过4条数据,禁用选择
                const isSelectionDisabled = uniqueSelectedItems.length >= 4 ? true : false;
                if (uniqueSelectedItems.length > 4) {
                        console.log('超过4条数据,禁用选择');
                        const firstFourItems = uniqueSelectedItems.slice(0, 4);
                        // 取消多余的选择项
                        let newCheckedKeys = firstFourItems.map(item => item.id);
                        this.setState({
                                checkedKeys: newCheckedKeys,
                                selectedItems: firstFourItems,
                                isSelectionDisabled,
                        });
                        return;
                }
                this.setState({
                        checkedKeys,
                        selectedItems: uniqueSelectedItems,
                        isSelectionDisabled,
                });
        };
        getSelectedItems = (keys, data) => {
                let result = [];
                keys.forEach(key => {
                        const item = this.findItemByKey(key, data);
                        if (item) {
                                result.push(item);
                        }
                });
                return result;
        };

        findItemByKey = (key, data) => {
                for (let item of data) {
                        if (item.id === key) {
                                return item;
                        }
                        if (item.children) {
                                const found = this.findItemByKey(key, item.children);
                                if (found) {
                                        return found;
                                }
                        }
                }
                return null;
        };
        // 递归渲染树节点
        renderTreeNodes = data => {
                if (!data || !Array.isArray(data)) return null;

                return data.map(item => {
                        if (!item) return null;

                        // // 父节点添加禁用样式
                        // const disabled = item.children?.length > 0;

                        return (
                                <TreeNode key={item.id} title={item.title} dataRef={item}>
                                        {item.children && this.renderTreeNodes(item.children)}
                                </TreeNode>
                        );
                });
        };
        // 关闭和保存菜单设置
        onMenSearch = id => {
                this.props.handleMenSearch(id);
                console.log(this.props);
        };
        // 删除选中菜单
        setDelete = item => {
                const { selectedItems } = this.state;
                // 删除右边的菜单
                const newSelectedItems = selectedItems.filter(selectedItem => selectedItem.id !== item.id);
                // 删除左边选中的菜单
                let newCheckedKeys = newSelectedItems.map(item => item.id);
                // 超过4条数据禁用选择
                const isSelectionDisabled = newSelectedItems.length >= 4 ? true : false;
                this.setState({
                        selectedItems: newSelectedItems,
                        checkedKeys: newCheckedKeys,
                        isSelectionDisabled,
                });
        };

        render() {
                const { checkedKeys, selectedItems, isSelectionDisabled } = this.state;
                const { MenSearchShow, menuData } = this.props;
                return (
                        <div>
                                <Modal
                                        width={960}
                                        visible={MenSearchShow}
                                        closable={false}
                                        cancelText="关闭"
                                        okText="保存设置"
                                        onOk={() => this.onMenSearch('save')}
                                        onCancel={() => this.onMenSearch('close')}
                                >
                                        <Row>
                                                <Col span={12}>
                                                        <div className={styles.MenSearch}>
                                                                <div className={styles.top}>
                                                                        <span className={styles.title}>所有菜单</span>
                                                                        <Search
                                                                                style={{
                                                                                        width: 220,
                                                                                        marginLeft: '15px',
                                                                                        border: '1px solid #dcdfe6',
                                                                                        borderRadius: '5px',
                                                                                }}
                                                                                placeholder="请输入查询菜单名称"
                                                                                onChange={e => this.handleSearch(e.target.value)}
                                                                        />
                                                                </div>
                                                                <div className={styles.Mentree}>
                                                                        <Tree
                                                                                disabled={isSelectionDisabled}
                                                                                checkable
                                                                                onExpand={this.onExpand}
                                                                                expandedKeys={this.state.expandedKeys}
                                                                                autoExpandParent={this.state.autoExpandParent}
                                                                                onCheck={this.onCheck}
                                                                                checkedKeys={this.state.checkedKeys}
                                                                        >
                                                                                {this.renderTreeNodes(menuData)}
                                                                        </Tree>
                                                                </div>
                                                        </div>
                                                </Col>
                                                <Col span={12}>
                                                        <div className={styles.MenMenSearch}>
                                                                <div className={styles.top}>
                                                                        <span className={styles.title}>已选菜单</span>
                                                                        <div>
                                                                                <span className={styles.title}>已选:{checkedKeys.length}</span>
                                                                                <span className={styles.title}>可选:{5}</span>
                                                                        </div>
                                                                </div>
                                                                <div className={`${styles['Mentree']}`}>
                                                                        {selectedItems.map((item, index) => (
                                                                                <div key={index} className={`${styles['treeList']}`}>
                                                                                        {/* <FormattedMessage id={`menu.${item}`} /> */}
                                                                                        <p>{item.title}</p>
                                                                                        <Icon
                                                                                                type="delete"
                                                                                                onClick={() => {
                                                                                                        this.setDelete(item);
                                                                                                }}
                                                                                        />
                                                                                </div>
                                                                        ))}
                                                                </div>
                                                        </div>
                                                </Col>
                                        </Row>
                                </Modal>
                        </div>
                );
        }

        handleSearch = value => {
                // 实现搜索逻辑
                console.log('搜索内容:', value);
        };
}

export default MenSearch;