【原创】vue-element-admin-plus完成编辑页面中嵌套列表功能

news2025/7/12 9:38:55

前言

vue-element-admin-plus对于复杂业务的支持程度确实不怎么样,我这里就遇到了编辑页面中还要嵌套列表的真实案例,比如字典,主字典嵌套子信息,类似于一个树状结构。目前vue-element-admin-plus给出的例子是无法满足这个需求的。

修改Write

修改Edit和修改Write都是可以实现的,毕竟程序员只有不想做,哪有做不出来的道理。但是按照各司其职来说,修改components中的Write更好,毕竟同为内部编辑。

引入表格

由于只有新增完了主字典,才能新增其子内容,因此这里表格显示条件是只有编辑的情况才显示,新增的情况不显示。另外要加上标题和按钮,用于新增和删除子内容。

<template>
  <Form :rules="rules" @register="formRegister" :schema="schema" />

  <div v-if="props.editType === 'edit'">
    <ElText type="primary" size="large" style="width: 100%">字典所属数据</ElText>
    <div style="display: block; margin-top: 20px">
      <ElButton type="primary" @click="addChild">新增</ElButton>
      <ElButton type="danger" @click="delChildList">删除</ElButton>
    </div>
    <ElTable :data="dictData" stripe style="width: 100%" @selection-change="selectionChange">
      <ElTableColumn type="selection" />
      <ElTableColumn label="字典值" prop="name" />
      <ElTableColumn label="字典码" prop="code" />
      <ElTableColumn label="字典说明" prop="remark" />
      <ElTableColumn label="操作">
        <template #default="slot">
          <ElButton type="primary" size="small" @click="editChild(slot.row)">编辑</ElButton>
          <ElButton type="danger" size="small" @click="delChildRow(slot.row)">删除</ElButton>
        </template>
      </ElTableColumn>
    </ElTable>
  </div>
</template>

注意了,在这里template标签中引入的ElTable必须是大驼峰格式的,不能是小写且用-号连接的

props.editType是从Edit页面传进来的。

const props = defineProps({
  currentRow: {
    type: Object as PropType<Nullable<DictDetailVo>>,
    default: () => null
  },
  editType: {
    type: String,
    default: 'add'
  },
  editId: {
    type: Number,
    default: -1
  }
})

dictData需要自行定义,是一个ref引用的数组。

const dictData = ref<Array<DictDetailVo>>([])

addChild和delChildList是点击按钮时调用,这个放后面再说

列表中的editChild和delChildRow也是点击按钮时调用,放后面再说

准备子数据接口

由于我们需要对子列表进行操作,因此还需要这个列表的增删改查接口。

export const dictAddApi = (data: DictEditBo): Promise<IResponse<number>> => {
  return request.post({ url: '/dict/add.adw', data })
}

export const dictUpdateApi = (data: DictEditBo): Promise<IResponse<any>> => {
  return request.post({ url: '/dict/update.adw', data })
}

export const dictDeleteApi = (data: BaseDeleteBo): Promise<IResponse<any>> => {
  return request.post({ url: '/dict/delete.adw', data })
}

export const dictChildrenApi = (data: DictSearchBo): Promise<IResponse<number>> => {
  return request.post({ url: '/dict/children.adw', data })
}

直接查询子数据接口:

const childrenSearch: DictSearchBo = {
  parentId: props.editId
}
const refreshChildren = () => {
  dictChildrenApi(childrenSearch).then((res) => {
    dictData.value = res.d as unknown as Array<DictDetailVo>
  })
}
refreshChildren()

进入页面时就需要调用refreshChildren接口了,入参需要将parentId传入,通过Edit页面传进来

新增、编辑对话框

在Write页面内部新增和编辑子列表就不要再跳转新的页面了,这里我使用ElDialog搞定,当然这里写的也必须是大驼峰形式的ElDialog,不能使用小写用-号拼接的,不然会识别不了。

  <ElDialog v-model="showEditDictChildDialog" title="编辑字典项">
    <div>
      <ElInput v-model="editDictDetail.name" placeholder="字典值" style="margin-bottom: 20px" />
      <ElInput v-model="editDictDetail.code" placeholder="字典码" style="margin-bottom: 20px" />
      <ElInput v-model="editDictDetail.remark" placeholder="字典说明" />
    </div>
    <template #footer>
      <ElButton @click="showEditDictChildDialog = false">取消</ElButton>
      <ElButton type="primary" @click="handleSaveEdit">保存</ElButton>
    </template>
  </ElDialog>

其中showEditDictChildDialog是ref引用的布尔类型对象,用于显示和隐藏对话框。

const showEditDictChildDialog = ref(false)

editDictDetail就是新增和编辑用的对象,使用ref引用。

const editDictDetail = ref<DictEditBo>({
  id: 0,
  name: '',
  parentId: '',
  code: '',
  remark: ''
})

handleSaveEdit由保存按钮调用

const handleSaveEdit = () => {
  showEditDictChildDialog.value = false
  if (!editDictDetail.value.id) {
    dictAddApi(editDictDetail.value).then(() => {
      refreshChildren()
    })
  } else {
    dictUpdateApi(editDictDetail.value).then(() => {
      refreshChildren()
    })
  }
}

关闭弹窗后,如果编辑的对象不存在id,则调用新增接口,否则调用编辑接口。

剩余方法

剩余的方法就是addChild、delChildList、editChild、delChildRow和selectionChange了。

addChild和editChild很像,其中add需要将弹窗内的数据重置,防止新增的数据还是之前的,其次就是弹出编辑弹窗了

const editChild = (row: DictDetailVo) => {
  showEditDictChildDialog.value = true
  editDictDetail.value = { ...row }
}

const addChild = () => {
  // 重置新增对象
  editDictDetail.value = {
    id: undefined,
    name: '',
    parentId: props.editId,
    code: '',
    remark: ''
  }
  showEditDictChildDialog.value = true
}

两个删除方法也差不多,最多是弹出一个模态框用于提示删除警告,外加调用删除接口。

 由于我写的后端删除接口只有传入id列表的,因此及时是删除单行,也被我作为列表传入了

const delChildRow = (row: DictDetailVo) => {
  ElMessageBox.confirm('是否要删除这条数据?', '删除警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    const nowDate = Date.now()

    const deleteBo: BaseDeleteBo = {
      ids: [row.id],
      rt: nowDate
    }
    dictDeleteApi(deleteBo).then(() => {
      refreshChildren()
    })
  })
}

const delChildList = () => {
  ElMessageBox.confirm('是否要删除这些数据?', '删除警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    const nowDate = Date.now()

    const rowIds = selectList.value.map((row) => {
      return row.id
    })
    const deleteBo: BaseDeleteBo = {
      ids: rowIds,
      rt: nowDate
    }
    dictDeleteApi(deleteBo).then(() => {
      refreshChildren()
    })
  })
}

完成效果

修改Page

修改Table

给的默认例子的Page是无法做成树状图的,这里需要对Table标签进行修改,增加tree-props和row-key

    <Table
      v-model:pageSize="pageInfo.pageSize"
      v-model:currentPage="pageInfo.currentPage"
      :columns="allSchemas.tableColumns"
      :data="dataList"
      :loading="loading"
      :stripe="true"
      :pagination="{
        total: pageInfo.totalCount
      }"
      @register="pageView.tableRegister"
      :tree-props="treeProps"
      row-key="id"
    />

tree-props用于指定树状图的子列表的字段名称

const treeProps = {
  children: 'children'
}

指定子列表的字段名为children,也就是说如果这个字段中存在一个列表,那就可以展开了。

row-key用于指定列表唯一值,防止展开混乱。

后端需要保证其传来的子列表字段也必须为children,否则树状列表不生效。

完成效果

完成效果如下,可以做到字典列表无限嵌套 

编辑页面也能够嵌套列表了

结语

本篇文章给大家展示了在vue-element-plus-admin中如何在编辑页面嵌套子列表,给大家提供一个编辑思路。当然这里只是一个介绍思路的demo,并不是完整代码,如果真的要完整实现这个功能,还需要后端的协助,当然这里的前后端都我一个人开发就对了,哈哈😎

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

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

相关文章

DeepSeek教unity------MessagePack-02

内置支持类型&#xff1a; 对象序列化 MessagePack for C# 可以序列化你自己定义的公共类或结构体类型。默认情况下&#xff0c;可序列化的类型必须用 [MessagePackObject] 属性进行注解&#xff0c;成员需要用 [Key] 属性进行注解。键可以是索引&#xff08;整数&#xff09;…

H5应用抓包及调试技巧

由于图片和格式解析问题&#xff0c;可前往 阅读原文 在现代移动互联网时代&#xff0c;H5 应用以其跨平台、轻量化、快速迭代的特性&#xff0c;成为移动开发的重要一环。然而&#xff0c;随着功能的复杂化和用户体验要求的提升&#xff0c;H5应用的调试也面临着诸多挑战&…

自学Java-面向对象高级(final、单例类、枚举类、抽象类、接口)

自学Java-面向对象高级&#xff08;final、单例类、枚举类、抽象类、接口&#xff09; 一、final关键字1、认识final关键字2、final修饰变量的注意3、常量 二、单例类&#xff08;设计模式&#xff09;1、设计模式的概念2、单例设计模式3、单例类有很多形式4、懒汉式单例类5、小…

docker下部署kong+consul+konga 报错问题处理

前言&#xff1a; 由于在docker下部署一些项目比较特殊&#xff0c;特别是网络这一块&#xff0c;如果没有搞清楚&#xff0c;是很容易出问题的。 先上docker-compose 编排 这里的docker-compose for kong可以在 kong-compose 获取代码 version: 3.9x-kong-config:&kong…

网络优化工作流程

DT路测 移动测试&#xff08;Drive Test&#xff09; CQT 定点测试&#xff08;通信质量测试&#xff09; DT 测试不能体现实际话务质量&#xff1a;回音、串音等网络问题不能通过 DT 测试发现&#xff0c;因此 CQT 拨打测试是 DT 测试很好的补充&#xff0c;也是目前室内外测…

React入门 - 0.React简介

React入门 - React简介 A Brief Introduction to React By JacksonML 1. 关于React React是一个知名的Web框架。众所周知&#xff0c;jQuery, Angular, Vue等框架都曾闪亮登场&#xff0c;并且&#xff0c;都仍然在全球市场占有一席之地。React这个颇有担当的新锐&#xff0…

SpringCloud系列教程:微服务的未来(二十四)Direct交换机、Topic交换机、声明队列交换机

前言 在现代消息队列系统中&#xff0c;交换机是实现消息传递和路由的核心组件。本文将重点探讨三种常见的交换机类型&#xff1a;Direct交换机、Topic交换机和声明队列交换机。通过对这三种交换机的详细分析&#xff0c;我们将学习它们的工作原理、应用场景以及如何在实际项目…

Sojson高级加密技术科普

1. 引言 什么是Sojson&#xff1f; Sojson是一款用于JavaScript代码加密与混淆的工具&#xff0c;它能够有效保护前端代码的知识产权&#xff0c;避免开发者的心血被随意窃取。 为什么需要代码加密&#xff1f; 在当今的互联网环境下&#xff0c;代码被轻易复制、篡改或逆向…

mysql多主集群 galera cluster for mysql 8安装配置启动重启集群

[TOC] 一、安装mysql 1、安装 系统环境&#xff1a; Ubuntu 18.04 64位 MySQL 8.0.19 下载MySQL APT安装配置包 首先访问 https://dev.mysql.com/downloads/repo/apt/ 获取配置包下载地址 wget https://dev.mysql.com/get/mysql-apt-config_0.8.14-1_all.deb sudo dpkg -i mysq…

mybatis 入门案例

前言 我们清楚 mybatis 是一个持久层框架&#xff0c;可以非常便捷的操作数据库。如最常见的对数据进行增删改查操作。 项目准备 1 在mybatis 数据库 创建 user 用户表 并插入以下两条数据 以下是一个user.sql 脚本文件如何使用 脚本文件可以参照MySQL数据库的备份与还原_控…

Python使用Flask结合DeepSeek开发

一、背景 我之前关于DeepSeek使用ollama部署的文章大家可以把DeepSeek大模型部署起来。那么ollama还提供了可以调用对应部署模型的API接口。我们可以基于这些接口&#xff0c;做自己的二次开发。使用pythonflaskollama就可以进行模型对话调用。并且前端采用SSE的技术&#xff0…

前端常见面试题-2025

vue4.0 Vue.js 4.0 是在 2021 年 9 月发布。Vue.js 4.0 是 Vue.js 的一个重要版本&#xff0c;引入了许多新特性和改进&#xff0c;旨在提升开发者的体验和性能。以下是一些关键的更新和新特性&#xff1a; Composition API 重构&#xff1a;Vue 3 引入了 Composition API 作为…

大模型开发实战篇7:语音识别-语音转文字

语音识别大模型&#xff0c;是人工智能领域的一项重要技术&#xff0c;它能够将人类的语音转换为文本。近年来&#xff0c;随着深度学习技术的不断发展&#xff0c;语音识别大模型取得了显著的进展&#xff0c;并在各个领域得到了广泛应用。 主流语音识别大模型 目前&#xf…

QML 部件获得焦点触发的全局槽函数 onActiveFocusItemChanged

在qml的window窗口中&#xff0c;假如添加里许多其他部件&#xff0c;当这些部件改变时&#xff0c;会有一个全局部件焦点改变槽函数触发&#xff0c;就是 onActiveFocusItemChanged 可以通过此槽函数就可以知道当前焦点在哪一个部件上&#xff0c;也可以做一些自动化测试等&…

如何用ClassFinal加密JAR保护知识产权!

0.前言 凌晨三点的办公室&#xff0c;咖啡杯底凝着褐色的残渍&#xff0c;键盘上跳跃的手指突然停滞。张工程师盯着屏幕上的反编译窗口&#xff0c;自己耗时三个月开发的规则引擎此刻像被解剖的标本般赤裸裸摊开——这正是上周交付给客户的jar包。当.class文件以伪代码形式暴露…

轨迹优化 | 基于LBFGS优化器的无约束路径平滑(附ROS C++仿真)

目录 0 专栏介绍1 LBFGS优化器1.1 拟牛顿法框架1.2 LBFGS-Lite库 2 基于LBFGS的轨迹优化3 ROS C仿真 0 专栏介绍 &#x1f525;课设、毕设、创新竞赛必备&#xff01;&#x1f525;本专栏涉及更高阶的运动规划算法轨迹优化实战&#xff0c;包括&#xff1a;曲线生成、碰撞检测…

Vue2到Vue3:无痛升级之路

为什么要从 Vue2 升级到 Vue3 Vue 3 带来了众多令人瞩目的改进和新特性&#xff0c;这些优势使得升级到 Vue 3 对项目的长期发展具有重要意义。 性能显著提升&#xff1a;Vue 3 采用了基于 Proxy 的响应式系统&#xff0c;相比 Vue 2 使用的 Object.defineProperty&#xff0c…

第28篇 基于ARM A9处理器用C语言实现中断<四>

Q&#xff1a;可以改变上一期实验工程里红色LED计数的速率吗&#xff1f; A&#xff1a;在按键中断服务程序中使HPS Timer 0停止计数&#xff0c;修改定时器中使用的预设计数值&#xff0c;然后重启定时器&#xff1b;所有的修改都是在按键中断服务程序中完成。主程序和其他…

时间序列分析(四)——差分运算、延迟算子、AR(p)模型

此前篇章&#xff1a; 时间序列分析&#xff08;一&#xff09;——基础概念篇 时间序列分析&#xff08;二&#xff09;——平稳性检验 时间序列分析&#xff08;三&#xff09;——白噪声检验 一、差分运算 差分运算的定义&#xff1a;差分运算是一种将非平稳时间序列转换…

《深度学习》——调整学习率和保存使用最优模型

调整学习率 在使用 PyTorch 进行深度学习训练时&#xff0c;调整学习率是一个重要的技巧&#xff0c;合适的学习率调整策略可以帮助模型更好地收敛。 PyTorch 提供了多种调整学习率的方法&#xff0c;下面将详细介绍几种常见的学习率调整策略及实例代码&#xff1a; torch.opt…