当前位置: 首页 > article >正文

Ant Design Vue 表格复杂数据合并单元格

Ant Design Vue 表格复杂数据合并单元格

官方合并效果

在这里插入图片描述

官方示例

表头只支持列合并,使用 column 里的 colSpan 进行设置。
表格支持行/列合并,使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时,设置的表格不会渲染。

<template><a-table :columns="columns" :data-source="data" bordered><template slot="name" slot-scope="text"><a>{{ text }}</a></template></a-table>
</template>
<script>
// In the fifth row, other columns are merged into first column
// by setting it's colSpan to be 0
const renderContent = (value, row, index) => {const obj = {children: value,attrs: {},};if (index === 4) {obj.attrs.colSpan = 0;}return obj;
};const data = [{key: '1',name: 'John Brown',age: 32,tel: '0571-22098909',phone: 18889898989,address: 'New York No. 1 Lake Park',},{key: '2',name: 'Jim Green',tel: '0571-22098333',phone: 18889898888,age: 42,address: 'London No. 1 Lake Park',},{key: '3',name: 'Joe Black',age: 32,tel: '0575-22098909',phone: 18900010002,address: 'Sidney No. 1 Lake Park',},{key: '4',name: 'Jim Red',age: 18,tel: '0575-22098909',phone: 18900010002,address: 'London No. 2 Lake Park',},{key: '5',name: 'Jake White',age: 18,tel: '0575-22098909',phone: 18900010002,address: 'Dublin No. 2 Lake Park',},
];export default {data() {const columns = [{title: 'Name',dataIndex: 'name',customRender: (text, row, index) => {if (index < 4) {return <a href="javascript:;">{text}</a>;}return {children: <a href="javascript:;">{text}</a>,attrs: {colSpan: 5,},};},},{title: 'Age',dataIndex: 'age',customRender: renderContent,},{title: 'Home phone',colSpan: 2,dataIndex: 'tel',customRender: (value, row, index) => {const obj = {children: value,attrs: {},};if (index === 2) {obj.attrs.rowSpan = 2;}// These two are merged into above cellif (index === 3) {obj.attrs.rowSpan = 0;}if (index === 4) {obj.attrs.colSpan = 0;}return obj;},},{title: 'Phone',colSpan: 0,dataIndex: 'phone',customRender: renderContent,},{title: 'Address',dataIndex: 'address',customRender: renderContent,},];return {data,columns,};},
};
</script>

实际项目中实现效果

在这里插入图片描述

实现原理

分层说明

  1. 数据预处理

    • 使用prepareData方法按markId字段分组
    • 组内数据按mergeIs字段排序(值为"是"的排在前)
  2. 双层级合并机制

    • 主合并层:相同markId的"名称"列合并
    • 次级合并层:在相同markId组内,连续mergeIs === '是’的"数量"列合并
  3. 合并标识管理

    • 通过rowSpan属性控制行合并数
    • rowSpan=0表示该单元格被合并
    • originalIndex记录原始位置用于合并定位
  4. 动态计数器机制

    • primarySpan跟踪名称列合并跨度
    • secondarySpan跟踪数量列合并跨度
    • 遇到分组边界或状态变化时重置计数器
{markId: "分组标识",  // 用于主合并层级mergeIs: "是/否",   // 用于次级合并层级name: "显示内容",    // 名称列数据num: "数值"         // 数量列数据
}

数据流向示意图

分组排序
原始数据
预处理模块
结构优化数据
合并处理器
可合并数据集
表格渲染

表格组件配置

<template><section class="console-section-box"><div class="con"><a-table:columns="columns":data-source="tableData":showHeader="true":loading="tableLoading":pagination="pagination":bordered="true":rowKey="(record, index) => {return index;}":scroll="{ x: true }"></a-table></div><a-back-top /></section>
</template>

合并逻辑

<script>
import { mockData } from '~/mock/index.js';
const productColumn = [{title: '名称',dataIndex: 'name',customRender: (value, row, index) => {const { rowSpan, originalIndex } = row.nameCellObj || { rowSpan: 1, originalIndex: index };const obj = {children: value,attrs: {}};if (index === originalIndex) {obj.attrs.rowSpan = rowSpan;obj.attrs.colSpan = 1;}return obj;},align: 'center',width: 90},{title: '类型',dataIndex: 'type',align: 'center',width: 100},{title: '数量',dataIndex: 'num',key: 'num',customRender: (value, row, index) => {const { rowSpan, originalIndex } = row.numCellObj || { rowSpan: 1, originalIndex: index };const obj = {children: value,attrs: {}};if (index === originalIndex) {obj.attrs.rowSpan = rowSpan;obj.attrs.colSpan = 1;}return obj;},align: 'center',width: 90}
];
export default {name: '',data() {return {tableLoading: false,tableData: [],pagination: {current: 1, // 当前页码pageSize: 10000, // 每页显示条数total: 0,showTotal: total => `共有 ${total} 条数据` //分页中显示总的数据},columns: productColumn,};},async mounted() {await this.fetchData();},methods: {async fetchData() {this.tableLoading = true;try {const res = await this.XXXX();if (res.code === 0) {this.tableData = mockData;this.pagination.total = res.data.length;this.handleCellMerge(this.tableData);}} catch (error) {console.error('Error fetching data:', error);}this.tableLoading = false;},// 根据数据合并单元格handleCellMerge(arr) {if (!arr?.length) return;const processor = {currentMarkId: null,currentMergeIs: null,primarySpan: 1,secondarySpan: 1,// 初始化单元格状态initialize(row, index) {row.nameCellObj = { rowSpan: 1, originalIndex: index };row.numCellObj = { rowSpan: 1, originalIndex: index };},// 主合并逻辑processPrimary(index, rows) {if (rows[index].markId === this.currentMarkId) {this.primarySpan++;rows[index - this.primarySpan + 1].nameCellObj.rowSpan = this.primarySpan;rows[index].nameCellObj.rowSpan = 0;return true;}this.currentMarkId = rows[index].markId;this.primarySpan = 1;return false;},// 次级合并逻辑processSecondary(index, rows) {if (rows[index].mergeIs === this.currentMergeIs && this.currentMergeIs === '是') {this.secondarySpan++;rows[index - this.secondarySpan + 1].numCellObj.rowSpan = this.secondarySpan;rows[index].numCellObj.rowSpan = 0;return true;}this.currentMergeIs = rows[index].mergeIs;this.secondarySpan = 1;return false;}};const sortedData = this.prepareData(arr);processor.currentMarkId = sortedData[0].markId;processor.currentMergeIs = sortedData[0].mergeIs;// 单次遍历处理所有合并逻辑sortedData.forEach((item, index) => {processor.initialize(item, index);if (index === 0) return;if (processor.processPrimary(index, sortedData)) {processor.processSecondary(index, sortedData);} else {processor.currentMergeIs = item.mergeIs;}});arr.splice(0, arr.length, ...sortedData);},// 分组排序方法prepareData(originData) {// 使用Map提高分组性能const groups = new Map();for (const item of originData) {const group = groups.get(item.markId) || [];group.push(item);groups.set(item.markId, group);}// 预计算排序权重避免重复计算return Array.from(groups.values()).flatMap(group => group.sort((a, b) => (b.mergeIs === '是') - (a.mergeIs === '是')));}}
};
</script>

mock数据

mock/index.js

export const mockData = [{name: '数据A',num: '9999999',type: 'AAA',mergeIs: '是',markId: 'ITEM_001'},{name: '数据A',num: '9999999',type: 'BBB',mergeIs: '是',markId: 'ITEM_001'},{name: '数据A',num: '9999999',type: 'CCC',mergeIs: '否',markId: 'ITEM_001'},{name: '数据A',num: '9999999',type: 'DDD',mergeIs: '否',markId: 'ITEM_001'},{name: '数据A',num: '9999999',type: 'EEE',mergeIs: '否',markId: 'ITEM_001'},{name: '数据B',num: '600',type: 'AAA',mergeIs: '是',markId: 'ITEM_002'},{name: '数据B',num: '9999999',type: 'BBB',mergeIs: '否',markId: 'ITEM_002'},{name: '数据B',num: '600',type: 'CCC',mergeIs: '是',markId: 'ITEM_002'},{name: '数据B',num: '9999999',type: 'DDD',mergeIs: '否',markId: 'ITEM_002'},{name: '数据B',num: '9999999',type: 'EEE',mergeIs: '否',markId: 'ITEM_002'},{name: '数据C',num: '9999999',type: 'AAA',mergeIs: '否',markId: 'ITEM_003'},{name: '数据C',num: '9999999',type: 'BBB',mergeIs: '否',markId: 'ITEM_003'},{name: '数据C',num: '9999999',type: 'CCC',mergeIs: '否',markId: 'ITEM_003'},{name: '数据C',num: '9999999',type: 'DDD',mergeIs: '否',markId: 'ITEM_003'},{name: '数据C',num: '9999999',type: 'EEE',mergeIs: '否',markId: 'ITEM_003'}
];

5. 样式

<style lang="scss" scoped>
.con {min-height: calc(100vh - 160px);padding: 24px;border-radius: 8px;background-color: #fff;
}
.project-info-box {display: flex;flex-direction: column;width: 100%;height: 100%;padding-bottom: 20px;
}
.project-info {width: 100%;height: 60px;line-height: 60px;display: flex;justify-content: space-between;p {margin: 0;}
}
</style>

相关文章:

Ant Design Vue 表格复杂数据合并单元格

Ant Design Vue 表格复杂数据合并单元格 官方合并效果 官方示例 表头只支持列合并&#xff0c;使用 column 里的 colSpan 进行设置。 表格支持行/列合并&#xff0c;使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时&#xff0c;设置的表格不会渲染。 <temp…...

Fiddler为什么可以看到一次HTTP请求数据?

1、作为代理服务器 Fiddler作为代理服务器&#xff0c;拦截了设备与互联网服务器之间的所有HTTP和HTTPS流量。当客户端&#xff08;如浏览器&#xff09;发送请求时&#xff0c;请求先到达Fiddler&#xff0c;然后由Fiddler转发到目标服务器&#xff1b;服务器的响应也会返回给…...

第十九讲 | XGBoost 与集成学习:精准高效的地学建模新范式

&#x1f7e8; 一、为什么要学习集成学习&#xff1f; 集成学习&#xff08;Ensemble Learning&#xff09; 是一种将多个弱学习器&#xff08;如决策树&#xff09;组合成一个强学习器的策略。它在地理学、生态学、遥感分类等领域表现尤为突出。 &#x1f4cc; 应用优势&#…...

基于 GoFrame 框架的电子邮件发送实践:优势、特色与经验分享

1. 引言 如果你是一位有1-2年Go开发经验的后端开发者&#xff0c;可能已经熟悉了Go语言在性能和并发上的天然优势&#xff0c;也曾在项目中遇到过邮件发送的需求——无论是用户注册时的激活邮件、系统异常时的通知&#xff0c;还是营销活动中的批量促销邮件&#xff0c;邮件功…...

ECharts 如何实现柱状图悬停时,整个背景区域均可触发点击事件

1. 前言 ECharts 柱状图的点击事件默认仅响应柱子本身的点击&#xff0c;本文旨在实现整个背景区域均可触发点击事件 2. 实现思路 核心&#xff1a;全局监听 坐标判断 数据转换 通过 getZr() 监听整个画布点击&#xff0c;结合像素坐标判断是否在图表区域内‌通过 containPi…...

金融简单介绍及金融诈骗防范

在当今社会&#xff0c;金融学如同一股无形却强大的力量&#xff0c;深刻影响着我们生活的方方面面。无论是个人的日常收支、投资理财&#xff0c;还是国家的宏观经济调控&#xff0c;都与金融学紧密相连。​ 一、金融学的概念​ 金融学&#xff0c;简单来说&#xff0c;是研…...

cursor+高德MCP:制作一份旅游攻略

高德开放平台 | 高德地图API (amap.com) 1.注册成为开发者 2.进入控制台选择应用管理----->我的应用 3.新建应用 4.点击添加Key 5.在高德开发平台找到MCP的文档 6.按照快速接入的步骤&#xff0c;进行操作 一定要按照最新版的cursor, 如果之前已经安装旧的版本卸载掉重新安…...

软件版本命名规范Semantic Versioning

​语义化版本控制&#xff08;Semantic Versioning&#xff0c;简称 SemVer&#xff09;是一种广泛采用的版本号管理规范&#xff0c;旨在通过版本号传达软件更新的性质和影响&#xff0c;帮助开发者和用户理解每次发布的变更内容 &#x1f522; 版本号结构 语义化版本号通常采…...

Uniapp: 大纲

目录 一、基础巩固1.1、Uniapp:下拉选择框ba-tree-picker1.2、Uniapp&#xff1a;确认框1.3、Uniapp&#xff1a;消息提示1.4、Uniapp&#xff1a;获取当前定位坐标 二、项目配置2.1、Uniapp&#xff1a;修改端口号2.2、Uniapp&#xff1a;本地存储 一、基础巩固 1.1、Uniapp:…...

Kubernetes控制平面组件:API Server Webhook 授权机制 详解

云原生学习路线导航页&#xff08;持续更新中&#xff09; kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计&#xff08;一&#xff09;Kubernetes架构原则和对象设计&#xff08;二&#xff09;Kubernetes架构原则和对象设计&#xff08;三&#xff09;Kubernetes控…...

【KWDB 创作者计划】_产品技术解读_1

【KWDB 创作者计划】_产品技术解读_1 一、存储引擎:高性能混合存储架构1. 存储模型设计2. 存储压缩与编码3. 持久化策略二、KWDB 组件源码解析1. 核心模块分层架构2. 关键组件源码剖析三、KWDB 特性代码通读1. 实时分析能力(Real-Time OLAP)2. 混合负载隔离(HTAP)3. 智能索…...

Python Cookbook-6.2 定义常量

任务 你需要定义一些模块级别的变量(比如命名的常量)&#xff0c;而且客户代码无法将其重新绑定。 解决方案 你可以把任何对象当做模块一样安装。将下列代码存为一个模块const.py&#xff0c;并放入你的Python的sys.path 指定的目录中: class _const(object):class ConstEr…...

【Python爬虫】简单案例介绍2

本文继续接着我的上一篇博客【Python爬虫】简单案例介绍1-CSDN博客 目录 跨页 3.2 环境准备 跨页 当对单个页面的结构有了清晰的认识并成功提取数据后&#xff0c;接下来就需要考虑页面之间的跨页问题。此时我们便迎来了下一个关键任务&#xff1a;如何实现跨页爬取&#xf…...

【神经网络】python实现神经网络(四)——误差反向传播的基础理论

一.反向传播 本章将介绍能够高效计算权重参数的梯度的方法——误差反向传播法,这里简单介绍一下什么是反向传播,加入有个函数y = f(x),那么它的反向传播为图下这个样子: 反向传播的计算顺序是,将输入信号E乘以节点的局部导数,然后将结果传递给下一个节点。这里所…...

【SQL】COUNT... FILTER 的适用场景

【SQL】COUNT... FILTER 的适用场景 一、引言二、FILTER 基础学习2.1 语法解析2.2 适用范围2.2.1 主流数据库支持情况 2.3 技术优势2.3.1 性能优化2.3.2 等阶写法对比 2.4 适用场景2.4.1 多维统计报表2.4.2 动态数据过滤2.4.3 复杂条件处理 三、总结 一、引言 今天参加业务评审…...

I/O进程(全)

I/O 一、标准IO 1.概念 在C库中定义的一组用于输入输出的函数 2.特点 (1).通过缓冲机制减少系统调用&#xff0c;提高效率 (2.)围绕流进行操作&#xff0c;流用FILE *来描述(3).标准IO默认打开了三个流&#xff0c;stdin&#xff08;标准输入&#xff09;、stdout&#xff08;标…...

vue2使用ezuikit-js播放萤石视频

需求&#xff1a;需要在大屏上播放萤石视频&#xff0c;用到官方的ezuikit-js插件实现&#xff0c;并实现视频播放切换功能。有个问题至今没有解决&#xff0c;就是萤石视频的宽高是固定的&#xff0c;不会根据大屏缩放进行自适应。我这边做了简单的刷新自适应。 1.下载ezuikit…...

什么是Lodash

一、什么是lodash 在 JavaScript 开发中&#xff0c;Lodash 是一个非常受欢迎的实用工具库&#xff0c;旨在提供高效、模块化的实用函数&#xff0c;帮助开发者更轻松地处理数组、对象、字符串等常见数据结构。它是对 JavaScript 原生方法的增强和优化&#xff0c;它在开发中提…...

【笔试强训day19】

目录 第一题&#xff1a;小易的升级之路 描述 输入描述&#xff1a; 输出描述&#xff1a; 输入&#xff1a; 输出&#xff1a; 第二题&#xff1a;礼物的最大价值 描述 输入&#xff1a; 返回值&#xff1a; 备注&#xff1a; 第三题&#xff1a;对称之美 题目描述…...

STM32电机库 电机控制特性

ST MC FW库提供FOC和六步法两种电机控制方式。这使得它能够驱动永磁同步电机 (PMSM) 和无刷直流电机 (BLDC)。FOC 更适合 PMSM,而六步法更适合 BLDC 电机。该固件可以驱动内嵌式PMSM 和标贴式PMSM。 ST Motor Control 固件库提供以下功能: FOC SVPWM 生成: 可配置的 PW…...

【Linux】42.网络基础(2.4)

文章目录 2.3 TCP协议2.3.10 拥塞控制2.3.11 延迟应答2.3.12 捎带应答2.3.13 面向字节流2.3.14 粘包问题2.3.15 TCP异常情况2.3.16 TCP小结2.3.17 基于TCP应用层协议 2.3 TCP协议 2.3.10 拥塞控制 虽然TCP有了滑动窗口这个大杀器, 能够高效可靠的发送大量的数据. 但是如果在刚…...

SPI接口DAC设备驱动与应用程序开发

本文章相关专栏往期内容&#xff0c;SPI子系统专栏&#xff1a; SPI通信协议与Linux设备驱动框架解析SPI传输与驱动框架的实现spidev.c&#xff1a;SPI设备驱动的核心实现逻辑 PCI/PCIe子系统专栏&#xff1a; 专栏地址&#xff1a;PCI/PCIe子系统PCIe设备MSI/MSI-X中断源码分析…...

第十六届蓝桥杯大赛软件赛省赛 Python 大学 B 组 满分题解

题面链接Htlang/2025lqb_python_b 个人觉得今年这套题整体比往年要简单许多&#xff0c;但是G题想简单了出大问题&#xff0c;预估50101015120860&#xff0c;道阻且长&#xff0c;再接再厉 代码仅供学习参考&#xff0c;满分为赛后洛谷中的测评&#xff0c;蓝桥杯官方测评待…...

数据库的种类及常见类型

一&#xff0c;数据库的种类 最常见的数据库类型分为两种&#xff0c;关系型数据库和非关系型数据库。 二&#xff0c;关系型数据库介绍 生产环境主流的关系型数据库有 Oracle、SQL Server、MySQL/MariaDB等。 关系型数据库在存储数据时实际就是采用的一张二维表&#xff0…...

vue文件预览docx-preview

1、在项目中引入插件docx-preview npm i docx-preview 此插件依赖jszip&#xff0c;所以还要下载jszip&#xff1a;npm i jszip 2、点击在线预览按钮请求接口获取文件流 const blob new Blob([resp.data]) const url URL.createObjectURL(blob);//浏览器本地存储不能直接…...

旧版 VMware 虚拟机迁移至 KVM 平台-案例2

项目背景 需将一台旧版 VMware 虚拟机&#xff08;VMDK 格式&#xff09;迁移至 KVM 虚拟化平台&#xff0c;具体要求如下&#xff1a; 格式转换&#xff1a;将 VMDK 转换为 QCOW2 格式。磁盘扩容&#xff1a;将原 40GB 磁盘扩展至 60GB。密码重置&#xff1a;修改 aiden 用户…...

若依代码生成器原理velocity模板引擎(自用)

1.源码分析 代码生成器:导入表结构(预览、编辑、删除、同步)、生成前后端代码 代码生成器表结构说明&#xff1a; 若依提供了两张核心表来存储导入的业务表信息&#xff1a; gen_table&#xff1a;存储业务表的基本信息 &#xff0c;它对应于配置代码基本信息和生成信息的页…...

OpenCV直方图均衡化全面解析:从灰度到彩色图像的增强技术

目录 一、直方图均衡化基础&#xff1a;原理与核心思想 二、彩色图像的直方图均衡化&#xff1a;挑战与解决方案 三、进阶技巧与注意事项 四、应用场景与典型案 一、直方图均衡化基础&#xff1a;原理与核心思想 1. 直方图的本质与作用 直方图是图像像素强度分布的统计图表…...

【Pandas】pandas DataFrame keys

Pandas2.2 DataFrame Indexing, iteration 方法描述DataFrame.head([n])用于返回 DataFrame 的前几行DataFrame.at快速访问和修改 DataFrame 中单个值的方法DataFrame.iat快速访问和修改 DataFrame 中单个值的方法DataFrame.loc用于基于标签&#xff08;行标签和列标签&#…...

Web前端之Vue+Element实现表格动态复杂的合并行功能、localeCompare、forEach、table、push、sort、Map

MENU 效果图公共数据数据未排序时&#xff08;需要合并的行数据未处于相邻位置&#xff09;固定合并行方法&#xff08;写死&#xff09;动态合并行&#xff0c;行数计算方法当太合并行&#xff0c;合并方法方法&#xff08;函数&#xff09;执行 效果图 公共数据 Html <e…...