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

vue3+ts+elementui-表格根据相同值合并

代码

 <div style="height: auto; overflow: auto"><el-table ref="dataTableRef" v-loading="loading" :data="pageData" highlight-current-row border@selection-change="handleSelectionChange" :span-method="objectSpanMethod" :row-style="tableRowStyle"><el-table-column type="selection" width="55" align="center" /><!-- <el-table-column key="id" label="id" prop="id" align="center" /> --><el-table-column key="roomName" label="房间名称" prop="roomName" align="center" /><el-table-column key="categoryName" label="所属分类" prop="categoryName" align="center" /><el-table-column key="deviceName" label="设备名称" prop="deviceName" align="center" /></el-table><pagination v-if="total > 0" v-model:total="total" v-model:page="queryParams.pageNum"v-model:limit="queryParams.pageSize" @pagination="handleQuery()" style="float: right;" /></div>

js 


interface User {id: stringroomName: stringdeviceName: stringcategoryName: string
}
interface SpanMethodProps {row: Usercolumn: TableColumnCtx<User>rowIndex: numbercolumnIndex: number
}
const objectSpanMethod = ({ row, column, rowIndex }) => {if (column.property === 'roomName') {const currentRoom = row.roomName;let prevRoom = rowIndex === 0 ? null : pageData.value[rowIndex - 1].roomName;if (rowIndex === 0 || currentRoom !== prevRoom) {let count = 1;for (let i = rowIndex + 1; i < pageData.value.length; i++) {if (pageData.value[i].roomName === currentRoom) {count++;} else {break;}}return { rowspan: count, colspan: 1 };} else {return { rowspan: 0, colspan: 0 };}}if (column.property === 'categoryName') {const currentCategory = row.categoryName;let prevCategory = rowIndex === 0 ? null : pageData.value[rowIndex - 1].categoryName;if (rowIndex === 0 || currentCategory !== prevCategory) {let count = 1;for (let i = rowIndex + 1; i < pageData.value.length; i++) {if (pageData.value[i].categoryName === currentCategory) {count++;} else {break;}}return { rowspan: count, colspan: 1 };} else {return { rowspan: 0, colspan: 0 };}}return { rowspan: 1, colspan: 1 };
}
// 定义合并信息的类型
type SpanInfo = {rowspan: numbercolspan: number
}// 用于存储 roomName 和 categoryName 的合并信息
const roomNameSpanMap: Map<number, SpanInfo> = new Map() // key 是 rowIndex
const categoryNameSpanMap: Map<number, SpanInfo> = new Map()// 计算合并信息的方法
const calculateSpans = (data: User[]) => {let roomNameCount = 1let categoryNameCount = 1let prevRoomName = data[0]?.roomNamelet prevCategoryName = data[0]?.categoryName// 第一行默认 rowspan 为后续相同项的数量roomNameSpanMap.set(0, { rowspan: 1, colspan: 1 })categoryNameSpanMap.set(0, { rowspan: 1, colspan: 1 })for (let i = 1; i < data.length; i++) {const current = data[i]const prev = data[i - 1]// 处理 roomNameif (current.roomName === prev.roomName) {roomNameCount++// 当前行不显示,rowspan 设为 0roomNameSpanMap.set(i, { rowspan: 0, colspan: 0 })} else {// 新的 roomName,设置 rowspan 为累计的数量roomNameSpanMap.set(i - 1, { rowspan: roomNameCount, colspan: 1 })roomNameCount = 1 // 重置计数roomNameSpanMap.set(i, { rowspan: 1, colspan: 1 }) // 当前行可能是新的开始}// 处理 categoryNameif (current.categoryName === prev.categoryName) {categoryNameCount++categoryNameSpanMap.set(i, { rowspan: 0, colspan: 0 })} else {categoryNameSpanMap.set(i - 1, { rowspan: categoryNameCount, colspan: 1 })categoryNameCount = 1categoryNameSpanMap.set(i, { rowspan: 1, colspan: 1 })}prevRoomName = current.roomNameprevCategoryName = current.categoryName}// 处理最后一行的 rowspanroomNameSpanMap.set(data.length - 1, { rowspan: roomNameCount, colspan: 1 })categoryNameSpanMap.set(data.length - 1, { rowspan: categoryNameCount, colspan: 1 })
}
const tableRowStyle = ({ row, rowIndex }) => {return {height: '40px','vertical-align': 'middle'}
}

style 

// 表格
/* 确保表格行高一致,避免合并后行高错乱 */
:deep(.el-table .el-table__row) {/* 不要设置height/min-height/line-height,自动撑开 */vertical-align: middle !important;
}:deep(.el-table__cell) {vertical-align: middle !important;
}/* 确保表格容器有足够的空间 */
:deep(.table-container) {height: auto;/* 自动高度 */overflow: auto;/* 如果内容超出,显示滚动条 */
}

http://www.lryc.cn/news/590849.html

相关文章:

  • Linux之Zabbix分布式监控篇(二)
  • 算法竞赛备赛——【图论】求最短路径——Floyd算法
  • 【华为机试】122. 买卖股票的最佳时机 II
  • React 学习(4)
  • 研发知识系统选型实战:从 Notion 到 Gitee Wiki 的迭代经验
  • STM32 DMA通信详解
  • 求解偏微分方程的傅里叶积分解
  • ThreadLocal使用详解-从源码层面分析
  • Python 网络爬虫 —— requests 库和网页源代码
  • 智能体开发工具链全景图:IDE、调试器与监控平台
  • Fair-code介绍(Fair code)(一套新型软件模型:旨在“开源”“商业可持续性”中找到平衡)
  • Windows 11清理C盘方法大全:磁盘清理/禁用休眠/系统还原点/优化大师使用教程
  • Android默认背光亮度配置说明
  • 纯前端html实现图片坐标与尺寸(XY坐标及宽高)获取
  • SegNet:一种用于图像分割的深度卷积编码器解码器架构
  • RocketMQ 高可用集群架构与一致性机制解析
  • 【3D目标检测】Livox Tele-15采集的.lvx数据转.bag再转.pcd
  • 鲍威尔去留风波的AI量化解析:基于多模态数据驱动的金融市场脉冲响应研究
  • 达梦数据守护集群搭建(1主1实时备库1同步备库1异步备库)
  • 时序数据库选型指南 —— 为什么选择 Apache IoTDB?
  • javaweb学习开发代码_HTML-CSS-JS
  • Java面试(基础篇) - 第二篇!
  • slot=“trigger“ 覆盖了组件内部的 ref=“trigger“【详细来龙去脉版 5min】
  • Web开发 01
  • Python的“__name__“属性
  • visual freebasic教程-菜单栏
  • 视频码率是什么?视频流分辨率 2688x1520_25fps采用 h264格式压缩,其码率为
  • 线上协同办公时代:以开源AI大模型等工具培养网感,拥抱职业变革
  • Vim多列打开不同文件操作指南
  • Dijkstra 算法求解多种操作