八、Vben框架动态生成可编辑Table
开发过程中产品经理提出了一些奇怪的需求,让人很摸不着头脑,一问就是客户的需求就是这样,那么我们开发只能想各种办法啦。
最近就提出了两个需求,
第一个是需要在日期选择的时候根据时间选择的不同让底下table中增加两个时间中间的日期,底下是实现后的效果。

第二个是动态添加工序模块,里面的内容不止包含了tabs,table,还有form等组件和新增行,删除行等操作,这个操作就比较骚气了,非常难实现。

好了,有句话怎么说来着,“烧不死的鸟就是凤凰”,只有无畏前行,才能涅槃重生,最终还是实现了。下面就给大家细细讲解。
先看一下文件的组成,update.vue文件是主页面,updateSon.vue文件是底下的工序文件作为他的子页面。

第一个需求实现方案:
1.首先要分析获取他的时间区间
//当时间改变的时候触发handleChangeDate方法
<template #date="{ model, field }"><RangePickerv-model:value="model[field]"valueFormat="YYYY-MM-DD"format="YYYY-MM-DD"style="{width: '100%';}"@change="handleChangeDate"/></template>//在script里写方法,使用provide依赖注入一下,方便子组件无限级使用。// 选择周期const dateList = ref([]);function handleChangeDate(e) {setFieldsValue({ demandPlanningCycleStart: e[0], demandPlanningCycleEnd: e[1] });dateList.value = enumerateDaysBetweenDates(e[0], e[1]);}provide('dateList', dateList);//处理时间函数,return时间区间function enumerateDaysBetweenDates(startDate, endDate) {// 假定你已经保证了startDate 小于endDate,且二者不相等let daysList = [];let SDate = moment(startDate);let EDate = moment(endDate);daysList.push(SDate.format('MM-DD'));while (SDate.add(1, 'days').isBefore(EDate)) {// 注意这里add方法处理后SDate对象已经改变。daysList.push(SDate.format('MM-DD'));}daysList.push(EDate.format('MM-DD'));return daysList;}
2.在就是在updateSon.vue页面里面获取到dateList,并且把他加进Table的columns里面。
//在BasicTable里面循环增加tamplate
//ifDetail是在详情展示的时候是他不被编辑<template #[`planDay${idx+1}`]="{ record }" v-for="(val, idx) in dateList" :key="idx"><InputNumber:precision="2"@blur="handleDataInsert"placeholder="请输入":disabled="ifDetail"v-model:value="record[`planDay${idx + 1}`]"/>
</template>//获取到dateList的值const dateList: any = inject('dateList');//在watch监听的时候监听这个值,然后将新出现的日期插入columns里面
//item.demandPlanDetailList.tableMethods.getColumns()获取到了最新的columns
//columns为watch(dateList,(newVal, oldVal) => {purchasePlan.value.forEach((item) => {const columns1: any = [];const tableColumns = item.demandPlanDetailList.tableMethods.getColumns();if (newVal.length) {newVal.forEach((date, index) => {columns1.push({title: date,width: 140,slots: { customRender: `planDay${index + 1}` },dataIndex: `planDay${index + 1}`,});});columns1.push({title: '合计',width: 140,slots: { customRender: 'planDayDemandSum' },dataIndex: 'planDayDemandSum',});}if (oldVal.length) {
//删除原先插入的tableColumns.splice(11, oldVal.length + 1);}
//增加最新的进去tableColumns.splice(11, 0, ...columns1);item.plannedOutputDetail.tableMethods.setColumns(columns);item.demandPlanDetailList.tableMethods.setColumns(tableColumns);});},{ deep: true },);
第二个需求实现方案
- 首先我们应该默认一个值传给子组件,用于展示
//当然也需要provide依赖注入一下,方便子组件无限级使用。
const purchasePlan = ref([]);provide('purchasePlan', purchasePlan);//默认新增数据,最重要的是无论schemas和table里面的columns都要使用cloneDeep解除他们的深度绑定,才能重复使用。const addData = (datalist) => {const [registerForm, formMethods] = useForm({baseColProps: {span: 8,},layout: 'vertical',labelWidth: 140,schemas: cloneDeep(UpdateFormStaticSchema()),showActionButtonGroup: false,});const [registerPlanTable, tablePlanMethods] = useTable({...});const [registerTable, tableMethods] = useTable({...});const [registerOtherTable, tableOtherMethods] = useTable({...});const [registerPriceTable, tablePriceMethods] = useTable({...});datalist.push({activeKey: 0,form: {form: registerForm,formMethods: formMethods,},plannedOutputDetail: {table: registerPlanTable,tableMethods: tablePlanMethods,},demandPlanDetailList: {table: registerTable,tableMethods: tableMethods,},otherCostDetailList: {table: registerOtherTable,tableMethods: tableOtherMethods,},operation: {table: registerPriceTable,tableMethods: tablePriceMethods,},});};
2.我们要明确当点击添加工序的时候,这个table名称肯定不能写死,那么就要把他赋值出来
//按钮触发方法
//purchasePlan为原需要展示几个工序,从外面获取,默认是1个
<a-buttonstyle="margin-right: 15px"type="primary"@click="addPurchasePlanListBtn(purchasePlan)">添加工序
</a-button>//获取数据
const purchasePlan: any = inject('purchasePlan');//最重要的是这步,让他的所有的方法和form和table增加到purchasePlan中const addPurchasePlanListBtn = (datalist) => {const [registerForm, formMethods] = useForm({...});const [registerTable, tableMethods] = useTable({...});const [registerPlanTable, tablePlanMethods] = useTable({...});const [registerOtherTable, tableOtherMethods] = useTable({...});const [registerPriceTable, tablePriceMethods] = useTable({...});datalist.push({activeKey: 0,form: {form: registerForm,formMethods: formMethods,},plannedOutputDetail: {table: registerPlanTable,tableMethods: tablePlanMethods,},demandPlanDetailList: {table: registerTable,tableMethods: tableMethods,},otherCostDetailList: {table: registerOtherTable,tableMethods: tableOtherMethods,},operation: {table: registerPriceTable,tableMethods: tablePriceMethods,},});};
实现到这一步了,大家也就明白了,他是如何增加了的吧,在每次增加的时候都会创建上面的所有的table和form。
好了,今天的分享到此结束,大家如果还有什么不明白的,可以给留言哦。我会一一给大家解答。
相关文章:
八、Vben框架动态生成可编辑Table
开发过程中产品经理提出了一些奇怪的需求,让人很摸不着头脑,一问就是客户的需求就是这样,那么我们开发只能想各种办法啦。 最近就提出了两个需求, 第一个是需要在日期选择的时候根据时间选择的不同让底下table中增加两个时间中间的…...
浅谈ERP数据的重要性
影响一个ERP项目的因素有很多,数据无疑是其中很重要的一项,正所谓“正确的诊断源于准确的信息,准确的信息基于可靠的采集”,当我们抓住数据这个根基,大处着眼,小处着手的时候,我们距离ERP成功的日子就不会太…...
【RabbitMQ笔记06】消息队列RabbitMQ七种模式之Topics主题模式
这篇文章,主要介绍消息队列RabbitMQ七种模式之Topics主题模式。 目录 一、消息队列 1.1、主题模式(Topics) 1.2、案例代码 (1)引入依赖 (2)编写生产者 (3)编写消费…...
ChatGPT似乎有的时候并不能搞懂Java的动态分派,你懂了吗?
目录 碎碎念 ChatGPT 中出现的问题 那么正确答案应该是什么呢? 分派的相关知识点总结: 分派是什么? 静态分派与动态分派: Java语言是静态多分派,动态单分派的; 静态分派:静态重载多分派…...
【C++初阶】vector的模拟实现
大家好我是沐曦希💕 文章目录一、前言二、无参构造&析构三、基础接口1.empty和clear2.size和capacity3.[]和iterator四、reserve和resize五、尾插尾删六、其他构造1.迭代器区间构造2.拷贝构造七、memcpy问题八、完整代码一、前言 在模拟实现容器时候࿰…...
微信小程序、小游戏的流量主一般可以赚多少钱?
本篇文章主要科普小程序、小游戏流量主一般赚钱的实际情况,通过在下长期运营的经验汇总而成。 日期:2023年2月26日 作者:任聪聪 小程序、小程序满1000用户后即可开通流量主,但实际上很多人并没有传说中的那种日赚几千的流量收入的…...
jni-Demo-基于linux(c++ java)
跑一个jni 的最简单的Demo需要提前准备 VsCode 编译器、win10下,vscode中集成linux操作系统、c编译器(gcc、g),java编译器(jdk1.8)参考:https://mangocool.com/1653030123842.htmlJniDemo类&…...
指针的进阶——(1)
本次讲解重点: 1、字符指针 2、数组指针 3、指针数组 4、数组传参和指针传参 5、函数指针 关于指针这个知识点的主题,我们在前面已经初级阶段已经对指针有了大致的理解和应用了。我们知道了指针的概念: 1、指针就是地址,但口…...
电商平台的促销活动如何抵御大流量的ddos攻击
每一次活动大促带来的迅猛流量,对技术人而言都是一次严峻考验。如果在活动期间遭受黑产恶意 DDoS 攻击,无疑是雪上加霜。电商的特性是业务常态下通常不会遭受大流量 DDoS 攻击,且对延迟敏感,因此只需要在活动期间按需使用 DDoS 防…...
代码随想录-48-104. 二叉树的最大深度
目录前言题目1.层序迭代思路2. 本题思路分析:3. 算法实现4. pop函数的算法复杂度5. 算法坑点前言 在本科毕设结束后,我开始刷卡哥的“代码随想录”,每天一节。自己的总结笔记均会放在“算法刷题-代码随想录”该专栏下。 代码随想录此题链接 …...
【Vue3源码】第六章 computed的实现
【Vue3源码】第六章 computed的实现 上一章节我们实现了 ref 及其它配套的isRef、unRef 和 proxyRefs API。这一章开始实现computed计算属性。 认识computed 接受一个 getter 函数,返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。…...
Java基础之注解
3.注解 3.1概述【理解】 概述 对我们的程序进行标注和解释 注解和注释的区别 注释: 给程序员看的注解: 给编译器看的 使用注解进行配置配置的优势 代码更加简洁,方便 3.2自定义注解【理解】 格式 public interface 注解名称 { public 属性类型 属性名() default 默认值…...
三、线性表
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 提示:这里可以添加本文要记录的大概内容: 自学JAVA数据结构笔记,跟学视频为:黑马程序员Java数据结构与java算法全套教程…...
C++统计方形
统计方形 内存限制:256 MB 时间限制:1 S 题目描述 有一个n*m方格的棋盘,求其方格包含多少正方形、长方形(此处长方形不包含正方形) 输入格式 输入存在多组测试数据。每组测试数据输入两个整数n,m,数字不超…...
Tina_Linux配网开发指南
OpenRemoved_Tina_Linux_配网_开发指南 1 概述 1.1 编写目的 介绍Allwinner 平台上基于wifimanager-v2.0 的WiFi 配网方式,包括softap(WiFi ap 模式热点配网),soundwave(声波配网),BLE(蓝牙低功耗配网)。 1.2 适用范围 • allwinner 软件平台tina v5.0 版本及以…...
高频面试题|RabbitMQ如何防止消息的重复消费?
一. 前言最近有很多小伙伴开始找工作,在面试时,面试官经常会问我们这样一个题目:RabbitMQ如何防止重复消费?有很多小伙伴这个时候都在想,消息怎么还会重复消费呢???.......所以他们在面试后就跑来问壹哥,针对这个比…...
黑盒测试用例设计方法-边界值分析法
目录 一、边界值定义 二、边界值的考虑 三、边界值的优化 四、边界值的设计用例的步骤 五、案例 六、边界值的类型 一、边界值定义 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下…...
项目风险管理中不可忽视的5个关键点
1、风险意识非常重要 项目经理必须要有风险意识,并不是项目计划做好就万事大吉,而是需要对项目风险进行预判,时刻保持风险意识,及时发现和处理项目风险。 项目风险管理关键:风险意识 2、建立组织风险资产库 寻…...
Linux->进程地址空间
目录 前言: 1. 程序地址空间回顾 2. 进程空间是什么 3. 进程地址空间与内存 4. 进程地址空间和内存的关联 5. 为什么要有进程地址空间 前言: 我们在平时学习的过程当中总是听到栈、堆、代码段等等储存空间,但是这些东西到底是什么&…...
【奶奶看了也不会】AI绘画 Mac安装stable-diffusion-webui绘制AI妹子保姆级教程
1.作品图 2.准备工作 目前网上能搜到的stable-diffusion-webui的安装教程都是Window和Mac M1芯片的,而对于因特尔芯片的文章少之又少,这就导致我们还在用老Intel 芯片的Mac本,看着别人生成美女图片只能眼馋。所以小卷这周末折腾了一天&#…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
