原生html vue3使用element plus 的树tree上移下移案例源码

上效果 

html源码

<!DOCTYPE html>
<html lang="en">
<!--
* @Name: mallSalesReports.html
* @Description:
* @Author Lani
* @date 2024-02-28 18:32:36
-->
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>商品类别</title><script src="../js/vue3.3.8/vue.global.js"></script><script src="../js/elementPlus/index.full.js"></script><link rel="stylesheet" href="../js/elementPlus/index.css"><style>.el-header {height: 88px;background-color: #fff;z-index: 2;}#main-body .el-main {padding: 0;z-index: 1;}.el-aside {display: flex;justify-content: center;align-items: center;}.el-tree .el-tree-node__content {height: 50px !important;border-top: 1px solid #aaa;}.tree {border-bottom: 1px solid #aaa;border-left: 1px solid #aaa;border-right: 1px solid #aaa;/*width: 600px;*/}.custom-tree-node1 {display: flex;flex: 1;align-items: center;justify-content: space-between;font-size: 14px;padding: 8px;height: 50px;}</style>
</head>
<body>
<div id="app" class="common-layout" v-cloak><el-affix :offset="0"><el-row :gutter="0" style="border-bottom: 0px solid #d0d0d0;margin:0 20px;padding: 15px 0;background-color: #fff;"><el-col :span="22"><div class="flex-r"><h4 class="menu-title-color fw7 fz22">商品销售报表</h4></div></el-col><el-col :span="2" style="text-align: end"><el-button type="primary" size="large" @click="handleAddTopLevelNode">新增一级目录</el-button></el-col></el-row></el-affix><el-container><el-main id="main-body"><el-treeref="menutree":allow-drop="allowDrop" :allow-drag="allowDrag":data="treeData" draggable:expand-on-click-node="false"default-expand-all node-key="id"class="tree"><template #default="{ node, data }"><div class="custom-tree-node1"><div><el-input v-if="data.isEdit" v-model="data.DICT_VALUE" maxlength="12" show-word-limit></el-input><el-text v-else="!node.isEdit">{{ data.DICT_VALUE }}</el-text></div><div style="margin-left: 40px;"><el-button type="text" size="small" v-if="data.up"@click="handleMoveUp(node, data, 'up')">上移<i class="el-icon-top"></i></el-button><el-buttontype="text" size="small" v-if="data.down"@click="handleMoveDown(node, data, 'down')">下移<i class="el-icon-bottom"></i></el-button><el-button @click="append(node,data)" type="primary" v-if="data.subNode"> 添加子级</el-button><el-button style="margin-left: 18px" @click="edit(node, data)">{{ data.operateBtnText }}</el-button><el-button style="margin-left: 18px" @click="remove(node, data)" v-if="data.delete"> 删除</el-button></div></div></template></el-tree></el-main></el-container>
</div>
</body>
<script type="module">import zhCn from "../js/elementPlus/locale/zh-cn.mjs";const {createApp, ref, reactive, watch, toRaw, toRefs, shallowRef} = Vueconst _app = createApp({setup() {const categoryInfo = reactive({maxLevel: 2,//类别层级最大2treeData: [{ //默认保留第一个节点数不能为空label: '全部商品',DICT_VALUE: '全部商品',up: false, down: true, subNode: true, delete: false, operateBtnText: '修改',id: 1,children: [{label: 'Level two 1-1',DICT_VALUE: 'Level two 1-1',id: 2,up: false, down: true, subNode: true, delete: true, operateBtnText: '修改',},],},{ //默认保留第一个节点数不能为空label: '花吃了那女孩',DICT_VALUE: '花吃了那女孩',up: false, down: true, subNode: true, delete: false, operateBtnText: '修改',id: 1,children: [{label: 'Level two 1-1',DICT_VALUE: 'Level two 1-1',id: 2,up: false, down: true, subNode: true, delete: true, operateBtnText: '修改',},],},],id: 1})const payStatus = ref('')const num = ref(20)const timer = ref(null);const clickCount = ref(0);const locale = ref('')const searchKeywords = ref('')/** 判断结点拖拽* */const allowDrop = (draggingNode, dropNode, type) => {// console.log('|--正在拖拽draggingNode,type', draggingNode, type)// console.log('|--dropNode', dropNode)if (type == 'inner') return false //只能同级拖拽if (draggingNode.level > categoryInfo.maxLevel) return falsereturn true//允许拖拽}const allowDrag = (draggingNode) => {return !draggingNode.data.label.includes('Level three 3-1-1')}const toast = (message, type = 'warning', fn = null) => {ElementPlus.ElMessage({message,type, fn})}/** 插入:$refs.menutree.insertBefore* 删除:$refs.menutree.remove* */const handleMoveUp = (node) => {  // 上移的原理就是现在选中节点上方复制一个一模一样的节点,然后删掉原来那个const {$treeNodeId, ...newData} = node.dataconsole.log('|--选中结点', node.data, vm.$refs.menutree, $treeNodeId, newData, node.previousSibling.data.$treeNodeId)if (vm.$refs.menutree) vm.$refs.menutree.insertBefore(newData, node.previousSibling)// if (vm.$refs.menutree) vm.$refs.menutree.insertBefore(newData, node.previousSibling.data.$treeNodeId)if (vm.$refs.menutree) vm.$refs.menutree.remove(node)saveCategoryRequest()}const handleMoveDown = (node) => {  // 下移的原理就是现在选中节点下方复制一个一模一样的节点,然后删掉原来那个const {$treeNodeId, ...newData} = node.dataif (vm.$refs.menutree) vm.$refs.menutree.insertAfter(newData, node.nextSibling)// if (vm.$refs.menutree) vm.$refs.menutree.insertAfter(newData, node.nextSibling.data.$treeNodeId)if (vm.$refs.menutree) vm.$refs.menutree.remove(node)saveCategoryRequest()}/** node: 当前节点,* data: 当前节点* */const append = (node, data) => {//给当前节点,添加一个子节点console.log('|--添加', node, data)if (node.level >= categoryInfo.maxLevel) {toast(`级别最大只能为${categoryInfo.maxLevel}`)return}categoryInfo.id = categoryInfo.id + 1const newChild = {label: '二级类别 ',id: categoryInfo.id,children: [],up: data.children.length > 0 ? true : false,down: false,subNode: false,delete: true,isEdit: true,operateBtnText: '保存',/*API字段*/"DICT_SEQ": 0,DICT_VALUE: '二级类别 ',}if (!data.children) {data.children = []}data.children.push(newChild)data.items = JSON.parse(JSON.stringify(data.children))if (data.children.length > 1) {data.children[data.children.length - 2].down = true}}const handleAddTopLevelNode = () => { //添加一级类别categoryInfo.id = categoryInfo.id + 1let newTopLevelNode = {id: categoryInfo.id,label: '一级类别 ',up: true, down: false, subNode: true, delete: true, isEdit: true, operateBtnText: '保存',children: [],items: [],"DICT_SEQ": 0,DICT_VALUE: '一级类别 ',}categoryInfo.treeData.push(newTopLevelNode)if (categoryInfo.treeData.length > 1) {categoryInfo.treeData[categoryInfo.treeData.length - 2].down = true}}/** isAPI: true:用于请求掊口,删除不用字段, false 用于ui渲染增加一些字段* */const refreshTree = (data, isAPI = false) => {for (let i = 0; i < data.length; i++) {// data[i].id = data[i].DICT_SEQif (isAPI && data[i]) { // 上传修改try {delete data[i].labeldelete data[i].updelete data[i].downdelete data[i].subNodedelete data[i].deletedelete data[i].isEditdelete data[i].operateBtnTextdata[i].items = JSON.parse(JSON.stringify(data[i].children))  //同步itemsif ((!data[i].children) || (data[i].children.length <= 0)) continuedata[i].items = refreshTree(data[i].items, isAPI)delete data[i].children} catch (e) {}continue}//渲染uidata[i].label = data[i].DICT_VALUEdata[i].up = (i != 0)data[i].down = (i != (data.length - 1))data[i].subNode = truedata[i].delete = truedata[i].isEdit = falsecategoryInfo.id = categoryInfo.id + 1data[i].id = categoryInfo.iddata[i].operateBtnText = '修改'data[i].children = []if ((!data[i].items) || (data[i].items.length <= 0)) continuedata[i].children = refreshTree(data[i].items, isAPI)// console.log(data[i].children)}return data}const saveCategoryRequest = async () => {console.log('|-http 请求-')toast('Http请求')}return {...toRefs(categoryInfo),num,locale, searchKeywords,clickCount, timer,headerCellStyle: {borderTop: '2px solid #d0d0d0', background: '#f5f5f5', color: '#333', fontWeight: 500},// 方法allowDrag, allowDrop,toast, append, handleMoveDown, handleMoveUp,//移除节点remove: (node, data) => {console.log("|--del", node, data, node.data.$treeNodeId)const {$treeNodeId} = node.dataconsole.log('|--', $treeNodeId, vm.$refs.menutree)// returnif (categoryInfo.treeData.length <= 1) {toast('至少保留一个结点')return;}if (!vm.$refs.menutree) returnconsole.log('|--remove')// vm.$refs.menutree.remove($treeNodeId)vm.$refs.menutree.remove(node) //OK// vm.$refs.menutree.remove(data)saveCategoryRequest()/* const parent = node.parent;const children = parent.data.children || parent.data;const index = children.findIndex((d) => d.id === data.id);children.splice(index, 1);*/}, //移除节点edit: (node, data) => {let btnText = '保存'if (data.isEdit) {saveCategoryRequest()btnText = '修改'}data.isEdit = !data.isEditdata.operateBtnText = btnText},handleAddTopLevelNode,payStatusItemSelectedEvent: (item, index) => {payStatus.value = item.item},refreshTree, saveCategoryRequest,menuMoveF: (node, data, type) => { //上移,下移 结点,指针console.log('|--node', node)// 将变动之前的node备份let copyNode = {...node};console.log(copyNode)copyNode.previousSibling = {...node.previousSibling};copyNode.nextSibling = {...node.nextSibling};console.log('|--copyNode 复制节点--|', copyNode)let nodeData = {};if (node.previousSibling) { //上移vm.$refs.menutree.remove(node.data);// 删除原先的node// 拿到copy的node   // nodeData = CircularJSON.parse(nodeData = copyNode// 复制该node到指定位置(参数:1. 要增加的节点的 data 2. 要增加的节点的后一个节点的 data、key 或者 node)/*  vm.$refs.menutree.insertBefore(nodeData.data,nodeData.previousSibling.data);  */vm.$refs.menutree.insertBefore(nodeData.data,nodeData.previousSibling.data);window.sessionStorage.removeItem("menuNode");} else {toast("该菜单已经是当前层最上级");}returnif (type === "up") {  // 上移if (node.previousSibling) {vm.$refs.menutree.remove(node.data);// 删除原先的node// 拿到copy的node   // nodeData = CircularJSON.parse(nodeData = copyNode// 复制该node到指定位置(参数:1. 要增加的节点的 data 2. 要增加的节点的后一个节点的 data、key 或者 node)vm.$refs.menutree.insertBefore(nodeData.data,nodeData.previousSibling.data);window.sessionStorage.removeItem("menuNode");} else {toast("该菜单已经是当前层最上级");}} else {  // 下移if (node.nextSibling) {vm.$refs.menutree.remove(node.data);nodeData = CircularJSON.parse(window.sessionStorage.getItem("menuNode"));// 参数:1. 要增加的节点的 data 2. 要增加的节点的前一个节点的 data、key 或者 nodevm.$refs.menutree.insertAfter(nodeData.data,nodeData.nextSibling.data);window.sessionStorage.removeItem("menuNode");} else {toast("该菜单已经是当前层最下级");}}}}},async mounted() {},})_app.use(ElementPlus, {locale: zhCn})const vm = _app.mount('#app')
</script></html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/756730.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker入门(五)—— 小练习,docker安装nginx、elasticsearch

练习 docker 安装 nginx # 搜素镜像 [rootiZbp15293q8kgzhur7n6kvZ home]# docker search nginx NAME DESCRIPTION STARS OFFICIAL nginx …

【Postrsql】postgresql的介绍、安装和使用

介绍 1.基本信息 PostgreSQL是一个功能强大的开源关系型数据库系统。经过长达15年以上的积极开发和不断改进&#xff0c;PostgreSQL已在可靠性、稳定性、数据一致性等获得了业内极高的声誉。目前PostgreSQL可以运行在所有主流操作系统上&#xff0c;包括Linux、Unix和Windows…

html5cssjs代码 024 响应式布局示例

html5&css&js代码 024 响应式布局示例 一、代码二、解释 该HTML代码重点在于构建一个带有响应式设计的两栏布局网页&#xff0c;包含页头、导航条、主要内容区&#xff08;左右两列&#xff09;和底部区域&#xff0c;并运用CSS样式设置页面元素的布局、颜色、字体、间…

【Node.js从基础到高级运用】十五、单元测试与集成测试

引言 在Node.js开发过程中&#xff0c;测试是确保代码质量和功能正确性的关键步骤。单元测试和集成测试是最常见的测试类型。下面我们将使用Jest框架来进行测试。 单元测试 单元测试是指对软件中的最小可测试单元进行检查和验证。在Node.js中&#xff0c;这通常指的是函数或者…

HarmonyOS开发:超详细介绍如何开源静态共享包,实现远程依赖

前言 当我们开发了一个独立的功能&#xff0c;想让他人进行使用&#xff0c;一般的方式就是开源出去&#xff0c;有源码的方式&#xff0c;也有文件包的形式&#xff0c;当然了也有远程依赖的方式&#xff0c;比如在Android中&#xff0c;我们可以提供源码&#xff0c;也可以打…

SQLiteC/C++接口详细介绍sqlite3_stmt类(一)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍sqlite3_stmt类简介 下一篇&#xff1a;SQLiteC/C接口详细介绍sqlite3_stmt类&#xff08;二&#xff09; ​ 序言&#xff1a; 本文开始了SQLite的第二个类的详细介绍…

Qt 容器类控件

Group Box 使用 QGroupBox 实现一个带有标题的分组框可以把其他的控件放到里面作为一组&#xff0c;这样看起来能更好看一点. 核心属性 属性说明title分组框的标题alignment分组框内部内容的对齐方式flat是否是 “扁平” 模式checkable是否可选择. 设为 true&#xff0c;则在…

鸿蒙Harmony应用开发—ArkTS-高级组件:@ohos.advertising.AdComponent (非全屏广告展示组件))

本模块提供展示非全屏广告的能力。 说明&#xff1a; 本模块首批接口从API Version 11开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import { AdComponent } from ohos.advertising.AdComponent; AdComponent AdComponent(ads: Ar…

webpack5零基础入门-12搭建开发服务器

1.目的 每次写完代码都需要手动输入指令才能编译代码&#xff0c;太麻烦了&#xff0c;我们希望一切自动化 2.安装相关包 npm install --save-dev webpack-dev-server 3.添加配置 在webpack.config.js中添加devServer相关配置 /**开发服务器 */devServer: {host: localhos…

华为中心AP 配置入侵防御实验

配置入侵防御示例 组网图形 图1 入侵防御组网图 组网需求配置思路操作步骤中心AP的配置文件 组网需求 如图1所示&#xff0c;某企业部署了WLAN网络&#xff0c;内网用户可以访问Internet的Web服务器。现需要在中心AP上配置入侵防御功能&#xff0c;具体要求如下&#xff1a; 保…

Bert的一些理解

Bert的一些理解 Masked Language Model (MLM)Next Sentence Prediction (NSP)总结 参考链接1 参考链接2 BERT 模型的训练数据集通常是以预训练任务的形式来构建的&#xff0c;其中包括两个主要任务&#xff1a;Masked Language Model (MLM) 和 Next Sentence Prediction (NSP)。…

GPT-4与Claude3、Gemini、Sora:AI领域的技术创新与突破

【最新增加Claude3、Gemini、Sora、GPTs讲解及AI领域中的集中大模型的最新技术】 2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚…

【PG数据库】CentOS 7 安装 PostgreSQL 14

1 CentOS 7 安装 PostgreSQL 14 1.1下载离线安装包 下载方式&#xff1a;利用离线下载方式在虚拟机中安装PostgreSQL 14 下载链接&#xff1a; https://yum.postgresql.org/14/redhat/rhel-7-x86_64/repoview/postgresqldbserver14.group.html 依次进入下载&#xff1a; 1.…

深度访谈:OpenAI缘何要进军光量子领域

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨王珩 编译/排版丨沛贤 深度好文&#xff1a;2000字丨12分钟阅读 据报道&#xff0c;人工智能巨头最近为其团队增添了一位新成员&#xff1a;Ben Bartlett&#xff0c;他是PsiQuantum的前…

【QT+QGIS跨平台编译】之八十四:【QGIS_Gui跨平台编译】—【错误处理:未实例化QgsMapLayer - QgsHighlight】

文章目录 一、未实例化QgsMapLayer二、错误处理 一、未实例化QgsMapLayer 报错信息&#xff1a; 二、错误处理 第31行修改为&#xff1a; #include "qgsmaplayer.h"

HarmonyOS NEXT应用开发之多文件下载监听案例

介绍 多文件下载监听在应用开发中是一个非常常见的需求。本示例将介绍如何使用request上传下载模块实现多文件下载监听&#xff0c;如监听每个文件下载任务的进度&#xff0c;任务暂停&#xff0c;下载完成等下载情况。每个应用最多支持创建10个未完成的任务&#xff0c;相关规…

GB28181视频汇聚EasyCVR平台接入海康Ehome设备,设备在线但是视频无法播放是什么原因?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

云原生相关知识

一、kubernetes 1 概述 Kubernetes&#xff08;也称 k8s 或 “kube”&#xff09;是一 个​​开源​​的容器编排平台&#xff0c;可以自动完成在部署、管理和扩展容器化应用过程中涉及的许多手动操作。 我们常说的编排的英文单词为 “Orchestration”&#xff0c;它常被解释…

苹果意将Gemini引入iPhone;英伟达发布新AI GPU;Grok正式开源

苹果正在谈判将 Gemini 引入 iPhone Mark Gurman 报道&#xff0c;苹果正在谈判将 Google 的生成式 AI 大模型 Gemini 引入 iPhone。 知情人士透露&#xff0c;两家公司正在积极谈判&#xff0c;让苹果获得 Gemini 授权&#xff0c;为今年 iPhone 软件的一些新功能提供动力。苹…

vim | vim多标签之间的跳转

比如有两个标签&#xff1a; 按 Ctrl o 会直接跳转到上一次打开的文件&#xff0c;这样可能不够直观&#xff0c;可以用 :ls 进行查看buff&#xff0c;如下&#xff1a; 可以看到 %a 的是当前正在编辑的 # 是按 Ctrl o 会跳转到的 当然也可以用 这种命令进行跳转&#xff1…