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 对数据进行更高级的处理,包括数据转换、聚合分析以及可视化展示。 数据转换 数据转换…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...