基于ant-design-vue3多功能操作表格,表头序号为动态添加记录按钮,鼠标在表格记录行,当前行序号显示删除按钮

由于项目需要,并考虑到尽可能让空间利用率高,因此定制开发一个表格组件,组件功能主要是在序号表头位置为添加按钮,点击按钮,新增一行表格数据;表格数据删除不同于以往表格在操作栏定义删除按钮,该组件删除按钮在表格每行记录数据序号位置处,每当鼠标停留在当前记录行时,显示删除按钮。效果图如下所示:
在这里插入图片描述
鼠标在表格记录行外效果图:
在这里插入图片描述
1.实现代码

表头json数据
export const mergeHeaderSchema: BasicColumn[] = [{title: 'ID',dataIndex: 'index',key: 'index',align: 'center',},{title: '权属',key: 'ownership',dataIndex: 'ownership',align: 'center',width: '12%',},{title: '起源',key: 'origin',dataIndex: 'origin',align: 'center',width: '12%',},{title: '商品林',dataIndex: 'name1',align: 'center',children: [{title: '合计',key: 'total',dataIndex: 'total',align: 'center',width: '8%',},{title: '主伐',key: 'no',edit: true,dataIndex: 'name3',align: 'center',},{title: '抚育采伐',key: 'address',dataIndex: 'name4',align: 'center',},{title: '低产林改造',key: 'no',dataIndex: 'name5',align: 'center',},{title: '其他采伐',key: 'no',dataIndex: 'name6',align: 'center',},],},{title: '公益林',dataIndex: 'name7',align: 'center',children: [{title: '合计',key: 'total',dataIndex: 'total',align: 'center',width: '8%',},{title: '更新采伐',key: 'no',dataIndex: 'name9',align: 'center',},{title: '抚育采伐',key: 'address',dataIndex: 'name10',align: 'center',},{title: '低效林改造',key: 'no',dataIndex: 'name11',align: 'center',},{title: '其他采伐',key: 'no',dataIndex: 'name12',align: 'center',},],},
];<template><a-spin :spinning="confirmLoading"><a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"><a-row><a-col :span="12"><a-form-item label="规划"><a-select v-model:value="formData.period"><a-select-option :value="135">135</a-select-option><a-select-option :value="145">145</a-select-option></a-select></a-form-item></a-col><a-col :span="12"><a-form-item label="年份"><a-select v-model:value="formData.period"><a-select-option :value="2024">2024</a-select-option><a-select-option :value="2023">2023</a-select-option></a-select></a-form-item></a-col><a-col :span="12"><a-form-item label="年文号"><a-select v-model:value="formData.period"><a-select-option :value="1">1</a-select-option><a-select-option :value="2">2</a-select-option></a-select></a-form-item></a-col><a-col :span="12"><a-form-item label="编限单位"><Cascader v-bind="attrs" :value="state" :options="options" /></a-form-item></a-col><!--   重点代码       --><a-col :span="24"><a-table bordered :columns="mergeHeaderSchema" :data-source="data" class="plus-common-table" :customRow="rowClick" :pagination="false"><!--   重点代码,插槽定义,表头序号为动态添加记录按钮       --><template #headerCell="{ column }"><template v-if="column.dataIndex === 'index'"><Icon icon="ant-design:plus-circle-outlined" class="plus-add" @click="handleAddClick" /></template><template v-else-if="column.dataIndex === 'ownership' || column.dataIndex === 'origin'"><div class="table-required"><span>{{ column.title }}(</span><span class="required-star">*</span><span>)</span></div></template></template><!--   重点代码,插槽定义,鼠标在表格记录行,当前行序号显示删除按钮      --><template #bodyCell="{ record, index, column }"><template v-if="column.dataIndex === 'index'"><div class="table-index">{{ index + 1 }}</div><Icon v-if="showDeleteBtn[index]" icon="ant-design:close-circle" class="plus-delete-btn" @click="handleDeleteClick(record)" /></template><template v-else-if="column.dataIndex === 'ownership'"><a-select v-model:value="formData.period" class="table-select"><a-select-option :value="2024">2024</a-select-option><a-select-option :value="2023">2023</a-select-option></a-select></template><template v-else-if="column.dataIndex === 'origin'"><a-select v-model:value="formData.period" class="table-select"><a-select-option :value="2024">2024</a-select-option><a-select-option :value="2023">2023</a-select-option></a-select></template><template v-else-if="column.dataIndex === 'total'"><div class="table-total">{{ record.total }}</div></template><template v-else><a-input @blur="handleEditFinish(record, column)" @input="handleInput($event, column)" /></template></template></a-table></a-col></a-row></a-form></a-spin>
</template><script lang="ts" setup>import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted, onUnmounted } from 'vue';import { defHttp } from '/@/utils/http/axios';import { useMessage } from '/@/hooks/web/useMessage';import { getValueType } from '/@/utils';import { saveOrUpdate } from '../Quota.api';import { Cascader, Form, message } from 'ant-design-vue';import { BasicTable, useTable } from '@/components/Table';import { mergeHeaderSchema } from '../Quota.data';let timerId: any;const handleInput = (event, column) => {const regex = /^(\d+(\.\d*)?)$/;const valid = regex.test(event.target.value);if (!valid) {message.error('【' + column.title + '】格式有误,请输入数字');}};const props = defineProps({formDisabled: { type: Boolean, default: false },formData: { type: Object, default: () => {} },formBpm: { type: Boolean, default: true },});const formRef = ref();const showDeleteBtn = ref([false, false, false, false, false]);const useForm = Form.useForm;const emit = defineEmits(['register', 'ok']);const formData = reactive<Record<string, any>>({id: '',businessCode: '',period: '',referenceCode: '',year: undefined,ownership: '',type: '',origin: '',province: '',city: '',county: '',delFlag: undefined,town: '',village: '',limitingUnit: '',status: '',});const { createMessage } = useMessage();const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });const confirmLoading = ref<boolean>(false);//表单验证const validatorRules = {};const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: true });const attrs = reactive<Record<string, any>>({});const state = ref();const [registerTable] = useTable({title: '多级表头示例',// api: demoListApi,columns: mergeHeaderSchema,});const data = ref<Record<string, any>>([]);const options = [{value: 'zhejiang',label: 'Zhejiang',children: [{value: 'hangzhou',label: 'Hangzhou',children: [{value: 'xihu',label: 'West Lake',},],},],},{value: 'jiangsu',label: 'Jiangsu',children: [{value: 'nanjing',label: 'Nanjing',children: [{value: 'zhonghuamen',label: 'Zhong Hua Men',},],},],},];// 表单禁用const disabled = computed(() => {if (props.formBpm === true) {if (props.formData.disabled === false) {return false;} else {return true;}}return props.formDisabled;});function handleAddClick() {data.value.push({ index: Date.now(), total: 200 });}function handleDeleteClick(record) {data.value = data.value.filter((item) => item.index !== record.index);}function rowClick(record, index) {return {// onClick: (event) => {//   console.info(record, index);// },// onMouseenter: (event) => {//   // 清除之前的定时器(如果存在)//   clearTimeout(timerId);//   // 设置一个新的定时器,等待一段时间后执行//   timerId = setTimeout(() => {//     // 鼠标停止移动后的操作//     console.log('Mouse has stopped moving over the element');//     showDeleteBtn.value[index] = true;//   }, 200);// },onMouseleave: (event) => {showDeleteBtn.value.forEach((item, index) => {showDeleteBtn.value[index] = false;});// 清除定时器clearTimeout(timerId);// showDeleteBtn.value[index] = false;},onMousemove: (event) => {// 如果鼠标在元素内移动,清除之前的定时器并重新设置clearTimeout(timerId);timerId = setTimeout(() => {showDeleteBtn.value[index] = true;// ... 同样的操作}, 50);// showDeleteBtn.value[index] = false;},};}// 在组件卸载前移除事件监听器(可选,但建议这样做以避免内存泄漏)onUnmounted(() => {// 清除定时器clearTimeout(timerId);// 如果需要,可以在这里移除其他事件监听器});function handleEditFinish(record, column) {}/*** 新增*/function add() {edit({});}/*** 编辑*/function edit(record) {nextTick(() => {resetFields();//赋值Object.assign(formData, record);});}/*** 提交数据*/async function submitForm() {// 触发表单验证await validate();confirmLoading.value = true;const isUpdate = ref<boolean>(false);//时间格式化let model = formData;if (model.id) {isUpdate.value = true;}//循环数据for (let data in model) {//如果该数据是数组并且是字符串类型if (model[data] instanceof Array) {let valueType = getValueType(formRef.value.getProps, data);//如果是字符串类型的需要变成以逗号分割的字符串if (valueType === 'string') {model[data] = model[data].join(',');}}}await saveOrUpdate(model, isUpdate.value).then((res) => {if (res.success) {createMessage.success(res.message);emit('ok');} else {createMessage.warning(res.message);}}).finally(() => {confirmLoading.value = false;});}defineExpose({add,edit,submitForm,});
</script><style lang="less" scoped>.antd-modal-form {height: 500px !important;overflow-y: auto;padding: 14px;}::v-deep(.ant-table-content) {.table-required {display: flex;align-items: center;justify-content: center; /* 水平居中 */display: -webkit-flex;}.required-star {color: red;font-size: 20px;}.ant-table-cell .plus-add {font-size: 30px !important;color: #1890ff;}.ant-table-cell {padding: 0;margin: 0;height: 35px;}.table-select {margin: 0;padding: 0;width: 100%;}.ant-input {border: 0;height: 100%;padding: 5px;}.table-total {height: 100%;display: flex;align-items: center;justify-content: center; /* 水平居中 */background-color: lightgray;}.plus-delete-btn {font-size: 30px !important;color: white;background-color: #f56c6c;position: absolute;border-radius: 15px;top: 50%; /* 将元素的顶部移动到父元素的中心 */left: 50%; /* 将元素的左边移动到父元素的中心 */transform: translate(-50%, -50%); /* 使用转换移动元素自身的50%宽度和高度,使其真正居中 */}.table-index {width: 100% !important;height: 100% !important;display: flex;align-items: center;justify-content: center; /* 水平居中 *///text-align: center;}}.element {/* 初始样式 */background-color: lightblue;padding: 10px;cursor: pointer;}.element:hover {/* 鼠标悬停时的样式 */background-color: lightgreen;}
</style>

2.重点代码标识
表头序号为动态添加记录按钮
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.相关大数据学习demo地址:
https://github.com/carteryh/big-data

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

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

相关文章

问题解决|如何优雅展示层级或关联数据?

一、8种可用图表类型及配套教程 &#xff08;一&#xff09;包珠图 &#xff08;1&#xff09;功能介绍 包珠图&#xff08;Circular Packing&#xff09;&#xff0c;是一类较特殊的分类树状图&#xff0c;以气泡之间的包含关系展示层级关系&#xff0c;以气泡面积&#xf…

Spring事件机制

文章目录 一、Spring事件二、实现Spring事件1、自定义事件2、事件监听器2.1 实现ApplicationListener接口2.2 EventListener2.3 TransactionalEventListener 3、事件发布4、异步使用 三、EventBus1、事件模式2、EventBus三要素3、同步事件3.1 定义事件类3.2 定义事件监听3.3 测…

解析西门子PLC的String和WString

西门子PLC有两种字符串类型&#xff0c;String与WString String 用于存放英文数字标点符号等ASCII字符&#xff0c;每个字符占用一个字节 WString宽字符串用于存放中文、英文、数字等Unicode字符&#xff0c;每个字符占用两个字节 之前我搞过一篇解析String的 关于使用TCP-…

Kotlin 的优势:现代编程语言的卓越选择

文章目录 简洁与优雅的语法空安全特性函数式编程&#xff0c;支持高阶函数、lambdaKotlin 内联函数与 Java 的互操作性强大的类型推断协程支持lazy 委托object 单例模式区间表达式现代的开发工具支持 本文首发地址 https://h89.cn/archives/301.html 最新更新地址 https://gite…

包装类和泛型

&#x1f389;欢迎大家收看&#xff0c;请多多支持&#x1f339; &#x1f970;关注小哇&#xff0c;和我一起成长&#x1f680;个人主页&#x1f680; 包装类&#x1f319; Java中每个基本数据类型都对应了一个包装类&#xff0c; 除了int的包装类是Integer&#xff0c;char…

微信小程序开发 快速学习 这篇就够了

目录 一、配置篇 &#xff08;1&#xff09;官网链接&#xff1a; &#xff08;2&#xff09;项目分析 &#xff08;3&#xff09;调试器 &#xff08;4&#xff09;预览体验 &#xff08;5&#xff09;配置文件 &#xff08;6&#xff09;配置pages &#xff08;7&…

【开发问题记录】启动某个微服务时无法连接到seata(seata启动或配置异常)

问题记录 一、问题描述1.1 问题复现1.1.1 将Linux中的部分微服务启动1.1.2 在本地启动当时出错的服务 1.2 解决思路1.2.1 Nacos中seata相关的信息1.2.2 Linux中seata相关的信息 二、问题解决2.1 seata的配置错误2.1.1 Nacos中seata的配置问题2.1.2 命名空间问题的发现 2.2 网络…

Matlab编程资源库(10)离散傅立叶变换

一、离散傅立叶变换算法简要 给定一个N点的离散信号序列x(n)&#xff0c;其中n表示时刻&#xff0c;n 0, 1, 2, ..., N-1。 定义离散傅立叶变换的频域序列X(k)&#xff0c;其中k表示频率&#xff0c;k 0, 1, 2, ..., N-1。 通过以下公式计算每个频率对应的复数值&#xff…

生鲜云订单零售系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;商品分类管理&#xff0c;商品信息管理&#xff0c;订单评价管理&#xff0c;订单管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;商品信息&#…

[Unity] ShaderGraph实现镜头加速线/残血效果 URP

效果如下所示&#xff1a;残血状态时&#xff0c;画面会压暗角&#xff0c;并出现速度线营造紧迫感。 使用到的素材如下&#xff0c;换别的当然也可以。[这是张白色的png放射图&#xff0c;并非皇帝的新图hhh] 这个效果的实现逻辑&#xff0c;其实就是利用time向圆心做透明度的…

2024经济师考试报名『注册流程』图解!

⏰报名时间&#xff1a;8月12日—9月11日 ☑️报名注册流程 1、经济师考试报名注册网站&#xff1a;中国人事考试网. 2、点击考生登录栏目中的【新用户注册】按钮&#xff0c;进行注册。 3、进入用户注册界面&#xff0c;填写注册信息。 4、填写完毕确认无误后点击【提交】&…

Unity UGUI 之 Mask

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 本文在发布时间选用unity 2022.3.8稳定版本&#xff0c;请注意分别 1.什么是遮罩 遮罩是一…

深度解读大语言模型中的Transformer架构

一、Transformer的诞生背景 传统的循环神经网络&#xff08;RNN&#xff09;和长短期记忆网络&#xff08;LSTM&#xff09;在处理自然语言时存在诸多局限性。RNN 由于其递归的结构&#xff0c;在处理长序列时容易出现梯度消失和梯度爆炸的问题。这导致模型难以捕捉长距离的依…

学习react-登录状态验证

1.创建三个页面LoginPage, HomePage,NotFoundPage用于Router 创建LoginPage.tsx用于做登录页面 // LoginPage.tsx const LoginPage (props:LoginProp) > {const navigate useNavigate();return( <h1 onClick{ ()>{navigate("/");}}>Hello Login, {pr…

02 Go语言操作MySQL基础教程_20240729 课程笔记

概述 如果您没有Golang的基础&#xff0c;应该学习如下前置课程。 Golang零基础入门Golang面向对象编程Go Web 基础Go语言开发REST API接口_20240728 基础不好的同学每节课的代码最好配合视频进行阅读和学习&#xff0c;如果基础比较扎实&#xff0c;则阅读本教程巩固一下相…

微信小游戏之 三消(一)

首先设定一下 单个 方块 cell 类&#xff1a; 类定义和属性 init 方法 用于初始化方块&#xff0c;接收游戏实例、数据、宽度、道具类型和位置。 onWarning 方法 设置警告精灵的帧&#xff0c;并播放闪烁动作&#xff0c;用于显示方块的警告状态。 grow 方法 根据传入的方向…

21.发布确认模式-高级

问题 生产环境中由于一些不明原因&#xff0c;导致rabbitmq重启&#xff0c;在重启的期间生产者消息投递失败&#xff0c;导致消息丢失&#xff0c;需要手动处理恢复。那么如何才能进行rabbitmq的消息可靠性投递&#xff1f;特别是在极端的情况&#xff0c;rabbitmq集群不可用…

文件操作相关的精讲

目录&#xff1a; 思维导图 一. 文件定义 二. 文件的打开和关闭 三. 文件的顺序读写操作 四. 文件的随机读写操作 五. 文本文件和二进制文件 六. 文件读取结束的判断 七.文件缓冲区 思维导图&#xff1a; 一. 文件定义 1.文件定义 C语言中&#xff0c;文件是指一组相…

Vue3可媲美Element Plus Tree组件实战之移除节点

Element Plus Tree自定义节点内容示例中介绍了移除节点的用法&#xff0c;个人觉得作为提供给用户API&#xff0c;应该遵循迪米特法则&#xff0c;把功能实现的细节封装在组件内部&#xff0c;而提供给用户最简单的操作方式&#xff0c;同时在此基础上支持用户的扩展。 因此&a…

接口测试支持IDEA插件一键同步API、新增思维导图快速评审测试用例,MeterSphere开源持续测试工具v3.1.0版本发布

2024年7月29日&#xff0c;MeterSphere开源持续测试工具正式发布v3.1.0版本。 在这一版本中&#xff0c;接口测试方面&#xff0c;支持通过IDEA插件一键同步API至MeterSphere&#xff1b;测试管理方面&#xff0c;“测试用例”模块新增通过思维导图模式快捷评审测试用例。在“…