当前位置: 首页 > news >正文

树形结构-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',}}><divstyle={{whiteSpace: 'nowrap'}}>{item.value}</div><divstyle={{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;


 

相关文章:

树形结构-CRUD接口

先看一下效果&#xff1a;整体的效果 新增效果 --默认值是 default 修改效果 - 大致效果如上 --------------------------------------------------------------------------------------------------------------------------------- 下面讲解代码如何实现的 根据你使用…...

【Qt知识】Qt窗口坐标系

Qt的窗口坐标体系遵循标准的计算机图形坐标系统规则 Qt窗口坐标体系特点 坐标原点&#xff1a;窗口坐标体系的原点位于窗口的左上角&#xff0c;即坐标(0, 0)位置。 轴方向&#xff1a; X轴&#xff1a;向右为正方向&#xff0c;随着X坐标值的增加&#xff0c;元素在窗口中从…...

SAP Build引言

前言 SAP Build 似乎是一个整合了很多低代码或无代码产品的平台&#xff0c;最早的时候应该都是各自分开的几个产品&#xff0c;近年合并到一块上了SAP Build平台 现在看官网的介绍应该是有三四个产品被集成进来了&#xff0c;分别是SAP IRPA&#xff0c;SAP Workflow&#xf…...

2024上海国际钢丝绳及吊索具展览会

2024上海国际钢丝绳及吊索具展览会 2024 Shanghai International Wire Rope and Hanger Exhibition 时间&#xff1a;2024年12月18日--20日 地点&#xff1a;上海新国际博览中心 详询主办方陆先生 I38&#xff08;前三位&#xff09; I82I&#xff08;中间四位&#xff…...

记一次mysql索引优化

生产日志告警出现一条慢 sql 告警, 通过 sql 监控平台拿到 这条sql 语句是 : SELECTid,report_id,report_detail_id,item_code,report_type,photo FROM**** 表 WHEREdel_flag 0 AND (report_type 1 AND report_detail_id IN ( 1742 )) 之后用 explain 分析这条 sql 的命中…...

【Javascript系列】Terser通过调用API来实现代码的压缩和优化功能

Terser通过调用API来实现代码的压缩和优化功能 起源通过API来调用API调用过程中的一个隐含的技术点 - 异步调用和Promise对象官方文档中的一个有点容易忽略和混淆的地方关于Promise 起源 书接 上回&#xff0c;对Terser的功能做了一个初步的探索。在官方的主页上&#xff0c;有…...

嵌入式期末复习

一、选择题&#xff08;20&#xff09; 二、判断题&#xff08;10&#xff09; 三、填空题&#xff08;10&#xff09; 主机-目标机的文件传输方式主要有串口传输方式、网络传输方式、USB接口传输方式、JTAG接口传输方式、移动存储设备方式。常用的远程调试技术主要有 插桩/st…...

生信算法7 - 核酸序列Fasta和蛋白PDB文件读写与检索

python 3.9实现以下算法。 1. 简单的写文件和读文件 # 写 file1 open(count.txt,w) file1.write(this is a test) file1.close()# 读 file2 open(my_file) print(file2.read())2. 将列表内容写入文本文件 # 生成100-500数字列表 data [i * 100 for i in range(1, 6)] pri…...

【Python】Python异步编程

Python 异步编程 异步编程 异步编程是一种编程范式&#xff0c;通过非阻塞的方式执行任务&#xff0c;允许程序在等待某些操作&#xff08;如I/O操作、网络请求、数据库查询等&#xff09;完成时&#xff0c;继续执行其他任务。这与同步编程&#xff08;或阻塞编程&#xff09…...

pytorch笔记:自动混合精度(AMP)

1 理论部分 1.1 FP16 VS FP32 FP32具有八个指数位和23个小数位&#xff0c;而FP16具有五个指数位和十个小数位Tensor内核支持混合精度数学&#xff0c;即输入为半精度&#xff08;FP16&#xff09;&#xff0c;输出为全精度&#xff08;FP32&#xff09; 1.1.1 使用FP16的优缺…...

R语言ggplot2包绘制世界地图

数据和代码获取&#xff1a;请查看主页个人信息&#xff01;&#xff01;&#xff01; 1. 数据读取与处理 首先&#xff0c;从CSV文件中读取数据&#xff0c;并计算各国每日收入的平均签证成本。 library(tidyverse) ​ df <- read_csv("df.csv") %>% group_…...

【Linux】Linux的权限_1

文章目录 三、权限1. shell外壳2. Linux的用户3. Linux权限管理文件访问者的分类文件类型和访问权限 未完待续 三、权限 1. shell外壳 为什么要使用shell外壳 由于用户不擅长直接与操作系统直接接触和操作系统的易用程度、安全性考虑&#xff0c;用户不能直接访问操作系统。 什…...

日语_远程办公常用日语单词

基本词汇 リモートワーク&#xff08;Rimōto Wāku&#xff09;&#xff1a;远程工作テレワーク&#xff08;Terewāku&#xff09;&#xff1a;远程工作&#xff08;Telework&#xff09;在宅勤務&#xff08;ざいたくきんむ&#xff0c;Zaitaku Kinmu&#xff09;&#xff…...

MTK 平台项目security boot 开启/关闭 及 系统签名流程

以 https://online.mediatek.com/FAQ#/SW/FAQ26691 为基础做如下记录以做备忘&#xff1a; How to Enable/Disable Secure Boot for Security 3.0: 1、 How to Enable Path Enable Preloader /vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/{…...

JDBC连接MySQL

目录 1.数据库编程的必备条件 2.Java的数据库编程JDBC 3.JDBC的工作原理 4.第三方库connector的下载和导包 5.JDBC的使用 使用步骤 &#xff08;1&#xff09;创建数据源对象DataSource &#xff08;2&#xff09;给对象设置必要的属性 &#xff08;3&#xff09;和数据…...

【Qt】【模型视图架构】 在项目视图中启用拖放

文章目录 1. 在便捷类中启用拖放2. 在模型/视图类中启用拖放 模型/视图框架支持Qt的拖放应用。 列表、表格和树中的项目可以在视图中被拖拽&#xff0c;数据作为MIME编码的数据被导入和导出。标准视图可以自动支持内部的拖放。 默认视图的拖放功能并没有被启用&#xff0c;如果…...

B端产品无爆款,说有的都是忽悠和外行!

前言&#xff1a;网上经常有人讲运营&#xff0c;把C端那一套硬搬到B端&#xff0c;讲的自我陶醉&#xff0c;稍微有点常识的人就知道不能这么玩。 一、什么是B端和C端 B端&#xff08;Business-to-Business&#xff09;是指面向企业客户的市场和产品。B端产品或服务主要是为…...

腾讯云的身份证核验,找不到这个类

文件上传功能在许多Web应用程序中是非常常见的需求之一。然而&#xff0c;由于文件上传存在安全风险&#xff0c;保护用户上传的文件的安全性&#xff0c;以及防止黑客利用上传功能进行攻击是非常重要的。在本文中&#xff0c;我们将讨论一些常见的安全漏洞&#xff0c;并提供一…...

vue3 vue-draggable-next 实现拖拽穿梭框效果

一、vue3 vue-draggable-next 实现拖拽穿梭框效果 <template> <div> <h2>列表 1</h2> <draggable v-model"list1" group"items" tag"transition-group" end"onDragEnd"> <div v-for"(item…...

FreeRTOS【16】直达任务通知使用

1.开发背景 直达任务通知&#xff0c;FreeRTOS 的线程任务提供的接口&#xff0c;可以用作线程唤醒&#xff0c;或者是传递数据&#xff0c;因为是基于线程本身的操作&#xff0c;是轻量级&#xff0c;速度响应更快&#xff0c;适合小内存芯片使用。 事实上本人使用得比较少&am…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

解析“道作为序位生成器”的核心原理

解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制&#xff0c;重点解析"道作为序位生成器"的核心原理与实现框架&#xff1a; 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...