树形结构-CRUD接口

先看一下效果:整体的效果
   

新增效果 --默认值是 default

 修改效果 -

大致效果如上

---------------------------------------------------------------------------------------------------------------------------------
下面讲解代码如何实现的
 根据你使用的UI的框架中的树结构---形成相应的数据结构(递归形式)-如果后端给你分好了(感谢他)
这个是给我的是一个  数组包裹的对象形式 进行递归
这个我写在--一个通用的 js 导出形式  这边我需要是的是两种类型 所以分了一下(效果图上的是第一个)  
解释一下:data:后端给你的数据
                  parentId是 从0 或者 -1 开始 看你的需求 我这边是 -1

                   show:我这是区分我要的是那种类型         

递归形式走的

export function buildTree(data, parentId, show) {
  const result = [];
  data?.filter(item => item.parentId === parentId)
    .forEach(items => {
      const children = buildTree(data, items.id, show);
      let node = ''
      if (!show) {
        node = {
          value: `${items.categoryName}`,
          key: `${items.id}`,
          defaultValue: `${items.categoryName}`,
          isEditable: false,
          parentId: `${items.parentId}`,
          children: children.length ? children : undefined,
        };
      } else {
        node = {
          value: `${items.id}`,
          title: `${items.categoryName}`,
          children: children.length ? children : undefined,
        };
      }

      result.push(node);
    });
  return result;
}

 这边都是实现的代码了-------可以详细看下  ---谢谢  -如果不懂-请评论


import { DownOutlined, EditOutlined, PlusOutlined, MinusOutlined, CloseOutlined, CheckOutlined } from '@ant-design/icons';
import { Input, Tree, message } from 'antd';
import React, { useEffect, useState } from 'react';
import moment from 'moment';
import { GetclubGoodsCategoryList, PostclubGoodsCategoryRemove, PostclubGoodsCategorySave, PostclubGoodsCategoryUpdate } from '@/services/commodity';
import { buildTree } from '@/utils/utils';

const { TreeNode } = Tree;
// 三张图
import reduce from '@/assets/icon/reduce.png';
import addIng from '@/assets/icon/addIng.png';
import editIng from '@/assets/icon/editIng.png';
function TreeData({ onNodeClick }) {

    // 佛祖保佑,不会报错

    const [selectedNode, setSelectedNode] = useState(null);

    // const treeData = buildTree(data1, 0);
    const expandedKeyArr = ["0"];

    const [data, setData] = useState();
    const [listObj, setListObj] = useState({});
    let isMounted = true;
    const getDate = async () => {
        try {
//获取最初的数据  ------------接口
            let res = await GetclubGoodsCategoryList();
            if (isMounted && res && res.code == "200") {
                const treeData = buildTree(res.data, 0);
                setData(treeData);
            }
        } catch (error) {
            console.error("Error fetching data: ", error);
        }
    };
    useEffect(() => {

        getDate();
        return () => {
            isMounted = false;
        };
    }, []);


    const [expandedKeys, setExpandedKeys] = useState(expandedKeyArr);

    // 修改---树结构 有值---接口
    const onChangeUpdate = async () => {
        if (Object.keys(listObj).length > 0) {
            let res = await PostclubGoodsCategoryUpdate({
                categoryName: listObj.value,
                // parentId: listObj.key,
                id: listObj.key,

            });
            if (res && res.code == "200") {
                message.success("修改成功");
//重新获取树形结构
                getDate();
            }
        }

    }

    const onExpand = (expandedKeys) => {
        setExpandedKeys(expandedKeys);
    };
    const handleNodeClick = (node) => {
        setSelectedNode(node);

        // 进行暴露---作为一个组件调用你所点击的值对象
        onNodeClick(node);
    };

    const renderTreeNodes = (data, depth = 0) => {
        return data?.map((item) => {
            const title = item.isEditable ? (
                <div style={{
                    display: 'flex',
                    justifyContent: 'space-between',
                    alignItems: 'center',
                }}>

                        {/*  输入框显示 和   一个对号  一个 叉号

*/}

                    <Input placeholder="输入名称" defaultValue={item.defaultValue}
                        onChange={(e) => onChange(e, item)} />

                    <CheckOutlined style={{
                        margin: '0 4px',
                    }} onClick={() => onSave(item)} />
                    <CloseOutlined onClick={() => onClose(item.parentKey, item.defaultValue)} />
                </div>
            ) : (
                <div onClick={() => handleNodeClick(item)}
                    style={{
                        display: 'flex',
                        justifyContent: 'space-between',
                        alignItems: 'center',
                    }}
                >
                    <div
                        style={{
                            whiteSpace: 'nowrap'
                        }}
                    >{item.value}</div>
                    <div
                        style={{
                            display: 'flex',
                            flexWrap: 'nowrap',
                            alignItems: 'center',
                        }}
                    >
                        {/* <EditOutlined onClick={() => onEdit(item.key)} />
                        <PlusOutlined onClick={() => onAdd(item.key)} />
                        {item.parentKey !== "0" && (
                            <MinusOutlined onClick={() => onDelete(item.key)} />
                        )} */}

                        {/* 两层之上就没有图标l 
                        效果上的左边字 右边图片 

*/}
                        {
                            item.value &&
                            <>
                                <img style={{ margin: '0 4px' }} width='15px' onClick={() => onEdit(item.key)} height='15px' src={editIng} alt="" />
                                {
                                    depth < 2 && <img width='15px' onClick={() => onAdd(item.key)} height='15px' src={addIng} alt="" />
                                }

                                <img style={{ margin: '0 4px' }} onClick={() => onDelete(item.key)} width='15px' height='15px' src={reduce} alt="" />
                            </>

                        }
                    </div>
                </div>
            );

            if (item.children) {
                return (
                    <TreeNode title={title} key={item.key}>
                        {renderTreeNodes(item.children, depth + 1)}
                    </TreeNode>
                );
            }

            return <TreeNode title={title} key={item.key} />;
        });
    };

    const onAdd = (key) => {
        if (expandedKeys.indexOf(key) === -1) {
            expandedKeys.push(key);
        }
        setExpandedKeys(expandedKeys.slice());
        addNode(key, data);
        setData([...data]);
    };

    const onEdit = (key) => {
        editNode(key, data);
        setData([...data]);
    };

    const editNode = (key, data) =>
        data.forEach((item) => {
            if (item.key === key) {
                item.isEditable = true;
            } else {
                item.isEditable = false;
            }
            item.value = item.defaultValue;
            if (item.children) {
                editNode(key, item.children);
            }
        });

    const getRandomNumber = (min = 1, max = 10000) => {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    };

    const addNode = (key, data) =>
        data.forEach((item) => {
            if (item.key === key) {
                if (item.children) {
                    item.children.push({
                        value: "default",
                        key: getRandomNumber(),
                        parentKey: key,
                        isEditable: false,
                        showAdd: true
                    });
                } else {
                    item.children = [
                        {
                            value: "default",
                            key: getRandomNumber(),
                            parentKey: key,
                            isEditable: false,
                            showAdd: true
                        },
                    ];
                }
                return;
            }
            if (item.children) {
                addNode(key, item.children);
            }
        });

    const onChange = (e, key) => {
        changeNode(key.parentKey ? key : key, e.target.value, data);
        setData([...data]);

    };

    const changeNode = (key, value, data) =>

        data.forEach((item) => {

            if (item.parentKey || item.key == key.key) {

                item.value = value;
            }
            if (item.children) {
                changeNode(key, value, item.children);
            }
        });

    // 保存---数据新增---接口
    const onSaveObj = async () => {

        let res = await PostclubGoodsCategorySave({
            categoryName: listObj.value,
            parentId: listObj.parentKey,
        })
        if (res && res.code === 200) {
            message.success('新增成功')
            getDate();
        } else {
            message.error('新增失败')
        }
    };

    useEffect(() => {

        if (listObj.showAdd) {

            onSaveObj();
        } else {
            onChangeUpdate()
        }


    }, [listObj])
    const onSave = (key) => {

        if (key.value == undefined) {
            message.error('请输入分类名称')
            return
        }
        setListObj(key)
        saveNode(key, data);
        setData([...data]);

    };


    const saveNode = (key, data) =>
        data.forEach((item) => {
            if (item.parentKey === key) {
                item.defaultValue = item.value;
            }
            if (item.children) {
                saveNode(key, item.children);
            }
            item.isEditable = false;
        });

    const onClose = (key, defaultValue) => {
        closeNode(key, defaultValue, data);
        setData([...data]);
    };

    const closeNode = (key, defaultValue, data) =>
        data.forEach((item, index) => {
            item.isEditable = false;
            if (item.parentKey === key) {
                data.splice(index, 1);
                item.value = defaultValue;
            }
            if (item.children) {
                closeNode(key, defaultValue, item.children);
            }
        });

    const onDelete = (key) => {
        deleteNode(key, data);
        setData([...data]);
    };
    //删除节点---接口
    const deleteIds = async (key) => {
        let data = await PostclubGoodsCategoryRemove({
            ids: key,
        })
        if (data && data.code === 200) {
            message.success('删除成功')
            getDate();
        }
    }
    const deleteNode = (key, data) =>
        data.forEach((item, index) => {
            if (item.key === key) {
                if (!item.showAdd) {
                    deleteIds(key);
                }


                data.splice(index, 1);

                return;
            } else {
                if (item.children) {
                    deleteNode(key, item.children);
                }
            }
        });

    return (
        <div style={{
            position: 'relative',
            left: '-14px'
        }}>
            <Tree onExpand={onExpand} expandedKeys={expandedKeys}>
                {renderTreeNodes(data)}
            </Tree>

        </div>
    );
}

export default TreeData;


 

相关推荐

  1. wpf 树形结构

    2024-06-06 04:14:06       10 阅读
  2. 数据结构树形结构

    2024-06-06 04:14:06       12 阅读
  3. 【MyBatis-Plus】内置接口的使用之CRUD

    2024-06-06 04:14:06       36 阅读
  4. C# 常见的数据结构如何在CRUD时选择

    2024-06-06 04:14:06       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-06 04:14:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-06 04:14:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-06 04:14:06       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-06 04:14:06       20 阅读

热门阅读

  1. flink 状态

    2024-06-06 04:14:06       6 阅读
  2. 0开篇-介绍

    2024-06-06 04:14:06       9 阅读
  3. 在RT-Thread下为MPU手搓以太网MAC驱动-3

    2024-06-06 04:14:06       7 阅读
  4. oracle sql--计算某一日期到当前日期的间隔天数

    2024-06-06 04:14:06       10 阅读
  5. docker mqqt 安装

    2024-06-06 04:14:06       7 阅读
  6. USB - ACK、NAK和STALL的含义

    2024-06-06 04:14:06       16 阅读
  7. conda环境里安装ffmpeg

    2024-06-06 04:14:06       9 阅读
  8. 在本地局域网的 Ubuntu 16.04 主机安装 GitLab 服务

    2024-06-06 04:14:06       11 阅读
  9. 正则表达式 0.1v

    2024-06-06 04:14:06       9 阅读
  10. WHAT - 容器化系列(二)- docker

    2024-06-06 04:14:06       11 阅读
  11. Shell正则表达式与文本处理器

    2024-06-06 04:14:06       6 阅读