zdppy+vue3+antd 实现表格单元格编辑功能
初步实现
<template><a-button class="editable-add-btn" style="margin-bottom: 8px" @click="handleAdd">Add</a-button><a-table bordered :data-source="dataSource" :columns="columns"><template #bodyCell="{ column, text, record }"><!--make the name column editable--><template v-if="column.dataIndex === 'name'"><div class="editable-cell"><div v-if="editableData[record.key]" class="editable-cell-input-wrapper"><a-input v-model:value="editableData[record.key].name" @pressEnter="save(record.key)"/><check-outlined class="editable-cell-icon-check" @click="save(record.key)"/></div><div v-else class="editable-cell-text-wrapper">{{ text || ' ' }}<edit-outlined class="editable-cell-icon" @click="edit(record.key)"/></div></div></template><!--Action column--><template v-else-if="column.dataIndex === 'operation'"><a-popconfirmv-if="dataSource.length"title="Sure to delete?"@confirm="onDelete(record.key)"><a>Delete</a></a-popconfirm></template></template></a-table>
</template>
<script setup>
import {computed, reactive, ref} from 'vue';
import {CheckOutlined, EditOutlined} from "@ant-design/icons-vue";
import {cloneDeep} from 'lodash-es';const columns = [{title: 'name',dataIndex: 'name',width: '30%',},{title: 'age',dataIndex: 'age',},{title: 'address',dataIndex: 'address',},{title: 'operation',dataIndex: 'operation',},
];
const dataSource = ref([{key: '0',name: 'Edward King 0',age: 32,address: 'London, Park Lane no. 0',},{key: '1',name: 'Edward King 1',age: 32,address: 'London, Park Lane no. 1',},
]);
const count = computed(() => dataSource.value.length + 1);
const editableData = reactive({});// make the row editable
const edit = key => {editableData[key] = cloneDeep(dataSource.value.filter(item => key === item.key)[0]);
};// save the edit result
const save = key => {Object.assign(dataSource.value.filter(item => key === item.key)[0], editableData[key]);delete editableData[key];
};// delete the row
const onDelete = key => {dataSource.value = dataSource.value.filter(item => item.key !== key);
};// add a row to data source
const handleAdd = () => {const newData = {key: `${count.value}`,name: `Edward King ${count.value}`,age: 32,address: `London, Park Lane no. ${count.value}`,};dataSource.value.push(newData);
};
</script>
<style lang="less" scoped>
.editable-cell {position: relative;.editable-cell-input-wrapper,.editable-cell-text-wrapper {padding-right: 24px;}.editable-cell-text-wrapper {padding: 5px 24px 5px 5px;}.editable-cell-icon,.editable-cell-icon-check {position: absolute;right: 0;width: 20px;cursor: pointer;}.editable-cell-icon {margin-top: 4px;display: none;}.editable-cell-icon-check {line-height: 28px;}.editable-cell-icon:hover,.editable-cell-icon-check:hover {color: #108ee9;}.editable-add-btn {margin-bottom: 8px;}
}.editable-cell:hover .editable-cell-icon {display: inline-block;
}
</style>
渲染后端接口数据
<script setup>
import {computed, onMounted, reactive, ref} from 'vue';
import {CheckOutlined, EditOutlined} from "@ant-design/icons-vue";
import {cloneDeep} from 'lodash-es';
import axios from "axios";const columns = [{name: '姓名',dataIndex: 'name',key: 'name',},{name: '性别',dataIndex: 'gender',key: 'gender',},{title: '年龄',dataIndex: 'age',key: 'age',},{title: '电话',dataIndex: 'phone',key: 'phone',},{title: '邮箱',key: 'email',dataIndex: 'email',},{title: '薪资',key: 'salary',dataIndex: 'salary',},{title: '操作',key: 'action',},
];const dataSource = ref([]);onMounted(() => {axios.get("http://127.0.0.1:8889/zdppy_amuserdetail").then((response) => {console.log("response.data", response.data);dataSource.value = response.data.data.results;})
})const count = computed(() => dataSource.value.length + 1);
const editableData = reactive({});// make the row editable
const edit = id => {console.log("edit", editableData, id)editableData[id] = cloneDeep(dataSource.value.filter(item => id === item.id)[0]);
};// save the edit result
const save = id => {Object.assign(dataSource.value.filter(item => id === item.id)[0], editableData[id]);delete editableData[id];
};// add a row to data source
const handleAdd = () => {const newData = {key: `${count.value}`,name: `Edward King ${count.value}`,age: 32,address: `London, Park Lane no. ${count.value}`,};dataSource.value.push(newData);
};
</script><template><a-button class="editable-add-btn" style="margin-bottom: 8px" @click="handleAdd">Add</a-button><a-tablebordered:data-source="dataSource":columns="columns":row-key="record => record.id"><template #headerCell="{ column }"><template v-if="column.key === 'name'"><span>{{ column.name }}</span></template><template v-else-if="column.key === 'gender'"><span>{{ column.name }}</span></template></template><template #bodyCell="{ column, text, record }"><!--make the name column editable--><template v-if="column.dataIndex === 'name'"><div class="editable-cell"><div v-if="editableData[record.id]" class="editable-cell-input-wrapper"><a-input v-model:value="editableData[record.id].name" @pressEnter="save(record.id)"/><check-outlined class="editable-cell-icon-check" @click="save(record.id)"/></div><div v-else class="editable-cell-text-wrapper">{{ text || ' ' }}<edit-outlined class="editable-cell-icon" @click="edit(record.id)"/></div></div></template><!--Action column--><template v-else-if="column.key === 'action'"><a-space wrap><a-button size="small" type="primary" block>编辑</a-button><a-button size="small" block>详情</a-button><a-button size="small" danger block>删除</a-button></a-space></template></template></a-table>
</template>
<style lang="less" scoped>
.editable-cell {position: relative;.editable-cell-input-wrapper,.editable-cell-text-wrapper {padding-right: 24px;}.editable-cell-text-wrapper {padding: 5px 24px 5px 5px;}.editable-cell-icon,.editable-cell-icon-check {position: absolute;right: 0;width: 20px;cursor: pointer;}.editable-cell-icon {margin-top: 4px;display: none;}.editable-cell-icon-check {line-height: 28px;}.editable-cell-icon:hover,.editable-cell-icon-check:hover {color: #108ee9;}.editable-add-btn {margin-bottom: 8px;}
}.editable-cell:hover .editable-cell-icon {display: inline-block;
}
</style>
将修改的数据保存到数据库
<script setup>
import {computed, onMounted, reactive, ref} from 'vue';
import {CheckOutlined, EditOutlined} from "@ant-design/icons-vue";
import {cloneDeep} from 'lodash-es';
import axios from "axios";const columns = [{name: '姓名',dataIndex: 'name',key: 'name',},{name: '性别',dataIndex: 'gender',key: 'gender',},{title: '年龄',dataIndex: 'age',key: 'age',},{title: '电话',dataIndex: 'phone',key: 'phone',},{title: '邮箱',key: 'email',dataIndex: 'email',},{title: '薪资',key: 'salary',dataIndex: 'salary',},{title: '操作',key: 'action',},
];const dataSource = ref([]);onMounted(() => {axios.get("http://127.0.0.1:8889/zdppy_amuserdetail").then((response) => {console.log("response.data", response.data);dataSource.value = response.data.data.results;})
})const count = computed(() => dataSource.value.length + 1);
const editableData = reactive({});// make the row editable
const edit = id => {console.log("edit", editableData, id)editableData[id] = cloneDeep(dataSource.value.filter(item => id === item.id)[0]);
};// save the edit result
const save = id => {const data = editableData[id]console.log("updated data", data)// backend updateaxios({method: "put",url: "http://127.0.0.1:8889/zdppy_amuserdetail/" + id,contentType: "application/json",data,}).then(resp => {console.log("update", resp.data);})// frontedn updateObject.assign(dataSource.value.filter(item => id === item.id)[0], editableData[id]);delete editableData[id];
};// add a row to data source
const handleAdd = () => {const newData = {key: `${count.value}`,name: `Edward King ${count.value}`,age: 32,address: `London, Park Lane no. ${count.value}`,};dataSource.value.push(newData);
};
</script><template><a-button class="editable-add-btn" style="margin-bottom: 8px" @click="handleAdd">Add</a-button><a-tablebordered:data-source="dataSource":columns="columns":row-key="record => record.id"><template #headerCell="{ column }"><template v-if="column.key === 'name'"><span>{{ column.name }}</span></template><template v-else-if="column.key === 'gender'"><span>{{ column.name }}</span></template></template><template #bodyCell="{ column, text, record }"><!--make the name column editable--><template v-if="column.dataIndex === 'name'"><div class="editable-cell"><div v-if="editableData[record.id]" class="editable-cell-input-wrapper"><a-input v-model:value="editableData[record.id].name" @pressEnter="save(record.id)"/><check-outlined class="editable-cell-icon-check" @click="save(record.id)"/></div><div v-else class="editable-cell-text-wrapper">{{ text || ' ' }}<edit-outlined class="editable-cell-icon" @click="edit(record.id)"/></div></div></template><!--Action column--><template v-else-if="column.key === 'action'"><a-space wrap><a-button size="small" type="primary" block>编辑</a-button><a-button size="small" block>详情</a-button><a-button size="small" danger block>删除</a-button></a-space></template></template></a-table>
</template>
<style lang="less" scoped>
.editable-cell {position: relative;.editable-cell-input-wrapper,.editable-cell-text-wrapper {padding-right: 24px;}.editable-cell-text-wrapper {padding: 5px 24px 5px 5px;}.editable-cell-icon,.editable-cell-icon-check {position: absolute;right: 0;width: 20px;cursor: pointer;}.editable-cell-icon {margin-top: 4px;display: none;}.editable-cell-icon-check {line-height: 28px;}.editable-cell-icon:hover,.editable-cell-icon-check:hover {color: #108ee9;}.editable-add-btn {margin-bottom: 8px;}
}.editable-cell:hover .editable-cell-icon {display: inline-block;
}
</style>
相关文章:
zdppy+vue3+antd 实现表格单元格编辑功能
初步实现 <template><a-button class"editable-add-btn" style"margin-bottom: 8px" click"handleAdd">Add</a-button><a-table bordered :data-source"dataSource" :columns"columns"><templa…...
elasticsearch索引怎么设计
Primary Shard(主分片) Primary Shard(主分片)是索引数据存储的基本单位,承担着数据写入和查询的职责。以下是关于Primary Shard的一些关键点: 1. 数据分布:每个索引在创建时会被分成多个主分…...
React 中 useState 和 useReducer 的联系和区别
文章目录 使用场景使用 useState使用 useReducer 联系区别用法状态更新逻辑适用场景可读性和可维护性 使用场景 使用 useState 状态逻辑简单。只涉及少量的状态更新。需要快速和简单的状态管理。 使用 useReducer 状态逻辑复杂。涉及多个子状态或多种状态更新逻辑。需要更好…...
Linux 定时任务详解:全面掌握 cron 和 at 命令
Linux 定时任务详解:全面掌握 cron 和 at 命令 Linux 系统中定时任务的管理对于运维和开发人员来说都是至关重要的。通过定时任务,可以在特定时间自动执行脚本或命令,提高系统自动化程度。本文将详细介绍 Linux 中常用的定时任务管理工具 cr…...

力扣考研经典题 反转链表
核心思想 头插法: 不断的将cur指针所指向的节点放到头节点之前,然后头节点指向cur节点,因为最后返回的是head.next 。 解题思路 1.如果头节点是空的,或者是只有一个节点,只需要返回head节点即可。 if (head null …...
opencv 设置超时时间
经常爬视频数据,然后用opencv做成图片 因此设置超时时间很重要 cap.set(cv2.CAP_PROP_FPS, timeout_ms) for idx, row in data.iterrows(): if idx < 400: continue try: # 打开视频文件 timeout_ms 5000 cap cv2.VideoCapture(row[PLAY_URL]) cap.set(cv2.C…...
2024年7月6日随笔
期末考试全部结束了,这个月是真累啊,一堆事,好在都熬过来了,上次参加的那个码题杯自己居然进国赛了,我看了一下职业赛道和本科赛道的题,本科赛道的感觉要难上不少,比赛时间是一周后,…...
Ubuntu 打开或关闭界面
设置开机默认关闭图形界面 1. 设置系统默认启动到多用户目标(命令行界面): o 使用以下命令将系统默认启动目标设置为多用户目标(这会关闭图形界面): sudo systemctl set-default multi-use…...

使用京东云主机搭建幻兽帕鲁游戏联机服务器全流程,0基础教程
使用京东云服务器搭建幻兽帕鲁Palworld游戏联机服务器教程,非常简单,京东云推出幻兽帕鲁镜像系统,镜像直接选择幻兽帕鲁镜像即可一键自动部署,不需要手动操作,真正的新手0基础部署幻兽帕鲁,阿腾云整理基于京…...

Python和MATLAB微机电健康推导算法和系统模拟优化设计
🎯要点 🎯惯性测量身体活动特征推导健康状态算法 | 🎯卷积网络算法学习惯性测量数据估计六自由度姿态 | 🎯全球导航卫星系统模拟,及惯性测量动态测斜仪算法、动态倾斜算法、融合算法 | 🎯微机电系统加速度…...

IT之家最新科技热点 | 小米 AI 研究院开创多模态通用模型
人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…...

黑色矩形块检测数据集VOC+YOLO格式2000张1类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2000 标注数量(xml文件个数):2000 标注数量(txt文件个数):2000 标注…...

Linux内存管理--系列文章柒——硬件架构
一、引子 之前文章讲解的是系统的虚拟内存,本章讲述这些硬件的架构和系统怎样统一管理这些硬件的。 二、物理内存模型 物理内存模型描述了计算机系统中的物理内存如何由操作系统组织和管理。它定义了物理内存如何划分为单元,如何寻址这些单元以及如何…...
QQ音乐Android一面凉经
最近面试了不少公司, 近期告一段落, 整理一下各家的面试问题, 打算陆续发布出来, 供有缘人参考。今天给大家带来的是QQ音乐Android一面凉经。 面试岗位: QQ音乐Android开发工程师面试时长: 50min(提问40min 反问10min)代码考核: 无 面试问题(40min) 自我介绍 工作经历, 重点…...

浅谈进程隐藏技术
前言 在之前几篇文章已经学习了解了几种钩取的方法 浅谈调试模式钩取浅谈热补丁浅谈内联钩取原理与实现导入地址表钩取技术 这篇文章就利用钩取方式完成进程隐藏的效果。 进程遍历方法 在实现进程隐藏时,首先需要明确遍历进程的方法。 CreateToolhelp32Snapsh…...
【C++】Google Test(gtest)单元测试
文章目录 Google Test(gtest)单元测试使用示例更多用法测试夹具 Google Test(gtest)单元测试 单元测试是一种软件测试方法,它旨在将应用程序的各个部分(通常是方法或函数)分离出来并独立测试&a…...

水箱高低水位浮球液位开关
水箱高低水位浮球液位开关概述 水箱高低水位浮球液位开关是一种用于监测和控制水箱中液位的自动化设备,它能够在水箱液位达到预设的高低限制时,输出开关信号,以控制水泵或电磁阀的开闭,从而维持水箱液位在一个安全的范围内。这类设…...

Autoware内容学习与初步探索(一)
0. 简介 之前作者主要是基于ROS2,CyberRT还有AutoSar等中间件完成搭建的。有一说一,这种从头开发当然有从头开发的好处,但是如果说绝大多数的公司还是基于现成的Apollo以及Autoware来完成的。这些现成的框架中也有很多非常好的方法。目前作者…...

【手写数据库内核组件】01 解析树的结构,不同类型的数据结构组多层的链表树,抽象类型统一引用格式
不同类型的链表 专栏内容: postgresql使用入门基础手写数据库toadb并发编程 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 文章目录 不同类型…...
Pandas 进阶 —— 数据转换、聚合与可视化
引言 在数据分析的旅程中,Pandas 库提供了从数据转换到聚合再到可视化的全面解决方案。上篇我们掌握了数据的导入和清洗,本篇我们将探索如何通过 Pandas 对数据进行更高级的处理,包括数据转换、聚合分析以及可视化展示。 数据转换 数据转换…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...