antd table合并复杂单元格、分组合并行、分组合并列、动态渲染列、嵌套表头
项目里遇到个需求,涉及到比较复杂的单元格合并 、嵌套表头、分组合并行、合并列等,并且数据列还是动态的,效果图如下:
可以分组设置【显示列】例如:当前组为【合同约定】,显示列为【合同节点】和【节点金额】
我们按【数据源】进行分组后,把第一组编号为【0001】的单元行合并 ,然后再插入一行【小计】,根据显示的【列数】决定合并几个【单元格】,比如我们的需求可以设置为当【合同节点】与【金额】全部显示时,显示【小计】的信息,再进行单元格合并
我们的数据源如下:
动态列数据:
const mockRowData = [// {// name: '合同约定',// key: 'agree',// handle: 'lt',// handleValue: 2312313,// color: '#FF811A',// enable: true,// checked: true,// // disabled: true,// checkable: false,// hidden: true,// children: [{name: '合同节点',key: 'contractNodes',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: true,checked: true,type: 1,},{name: '金额',key: 'Money',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: true,checked: true,type: 1,},{name: '节点比例',key: 'NodeRatio',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: false,checked: true,type: 1,},{name: '付款条件',key: 'paymentTerms',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: true,checked: true,type: 1,},// ],// },// {// name: '确认收入',// key: 'confirmIncome',// handle: 'lt',// handleValue: 2312313,// color: '#FF811A',// enable: false,// checked: true,// // disabled: true,// checkable: false,// hidden: true,// children: [{name: '成果提交日期',key: 'submissionDate',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: false,checked: true,type: 2,},{name: '证明文件日期',key: 'fileDate',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: true,checked: true,type: 2,},{name: '确认收入',key: 'Income',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: false,checked: true,type: 2,},{name: '确认比例',key: 'confirmationRatio',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: false,checked: true,type: 2,},// ],// },// {// name: '收款',// key: 'receivePayment',// handle: 'lt',// handleValue: 2312313,// color: '#FF811A',// enable: false,// checked: true,// // disabled: true,// checkable: false,// hidden: true,// children: [{name: '到账日期',key: 'DateofReceipt',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: false,checked: true,type: 3,},{name: '金额',key: 'Money1',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: true,checked: true,type: 3,},{name: '确认比例',key: 'confirmationRatio1',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: false,checked: true,type: 3,},// ],// },{name: '应收款',key: 'receivables',handle: 'lt',handleValue: 2312313,color: '#FF811A',enable: false,checked: true,children: [],type: 4,},
];
数据源:
const mockTableData = {group1: [{group: 'group1',id: 1,name: '第一建筑设计院',order: '0001',type: '外部承包',isConsortium: '是',nameSquare:'XXXXX有限公司公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称',cstatus: '执行中',money: '60,0000,0000',value1: 12345,contractNodes: 12345,Money: 12345,NodeRatio: 12345,paymentTerms: 12345,confirmIncome: 12345,submissionDate: 12345,fileDate: 12345,Income: 12345,confirmationRatio: 12345,Money1: 879,DateofReceipt: '2024-10-25',confirmationRatio1: '20%',receivables: '',agree: '',receivePayment: '200,0000,0000',},{group: 'group1',id: 2,name: '第二建筑设计院',order: '0001',type: '外部承包',isConsortium: '是',nameSquare:'XXXXX有限公司公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称',cstatus: '执行中',money: '60,0000,0000',value1: 1234124,contractNodes: 1234124,Money: 1234124,NodeRatio: 1234124,paymentTerms: 1234124,confirmIncome: 1234124,submissionDate: 1234124,fileDate: 1234124,Income: 1234124,confirmationRatio: 1234124,Money1: 879,DateofReceipt: '2024-10-25',confirmationRatio1: '20%',receivables: '',agree: '',receivePayment: '200,0000,0000',},{group: 'group1',id: 3,name: '第三建筑设计院',order: '0001',type: '外部承包',isConsortium: '是',nameSquare:'XXXXX有限公司公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称',cstatus: '执行中',money: '60,0000,0000',value1: 54321,contractNodes: 54321,Money: 54321,NodeRatio: 54321,paymentTerms: 54321,confirmIncome: 54321,submissionDate: 54321,fileDate: 54321,Income: 54321,confirmationRatio: 54321,Money1: 879,DateofReceipt: '2024-10-25',confirmationRatio1: '20%',receivables: '',agree: '',receivePayment: '200,0000,0000',},],group2: [{group: 'group2',id: 4,name: '第一建筑设计院',order: '0002',type: '外部承包',isConsortium: '是',nameSquare:'XXXXX有限公司公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称',cstatus: '执行中',money: '60,0000,0000',value1: 12345,contractNodes: 12345,Money: 12345,NodeRatio: 12345,paymentTerms: 12345,confirmIncome: 12345,submissionDate: 12345,fileDate: 12345,Income: 12345,confirmationRatio: 12345,Money1: 879,DateofReceipt: '2024-10-25',confirmationRatio1: '20%',receivables: '',agree: '',receivePayment: '200,0000,0000',},{group: 'group2',id: 5,name: '第二建筑设计院',order: '0002',type: '外部承包',isConsortium: '是',nameSquare:'XXXXX有限公司公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称',cstatus: '执行中',money: '60,0000,0000',value1: 1234124,contractNodes: 1234124,Money: 1234124,NodeRatio: 1234124,paymentTerms: 1234124,confirmIncome: 1234124,submissionDate: 1234124,fileDate: 1234124,Income: 1234124,confirmationRatio: 1234124,Money1: 879,DateofReceipt: '2024-10-25',confirmationRatio1: '20%',receivables: '',agree: '',receivePayment: '200,0000,0000',},{group: 'group2',id: 6,name: '第三建筑设计院',order: '0002',type: '外部承包',isConsortium: '是',nameSquare:'XXXXX有限公司公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称公司名称',cstatus: '执行中',money: '60,0000,0000',value1: 54321,contractNodes: 54321,Money: 54321,NodeRatio: 54321,paymentTerms: 54321,confirmIncome: 54321,submissionDate: 54321,fileDate: 54321,Income: 54321,confirmationRatio: 54321,Money1: 879,DateofReceipt: '2024-10-25',confirmationRatio1: '20%',receivables: '',agree: '',receivePayment: '200,0000,0000',},],
};
那接下来咱们就先看如何显示【动态列】吧~
1.显示动态列
const columns = useCallback(() => {if (rowData && rowData.length) {console.log(rowData);const list = [// 先写入非动态列{title: '合同编号',dataIndex: 'order',width: 50,render: (text) => {return (<divclassName="ellipsis-item"title={text}style={{ width: '100px' }}>{text}</div>);},onCell: mergeRow,},// 循环动态列,{title: '收款',className: 'type3Column',children: [...flattenData(rowData, 0).filter((item) => item.checked).filter((item) => item.type === 3).map((item) => {return {title: (<div className="ellipsis-item" title={item.name}>{item.name}</div>),dataIndex: item.key,className: 'type3Column',width: 100,render: (text) => {return (<divstyle={{background: getColumnColor(item.enable,text,item.handle,item.handleValue,item.color,),}}className="value-item">{text}</div>);},};}),],},];console.log('list', list);return list;}}, [rowData]);
2.合并列
思路
我们的列是动态变换的,所以合并的列数也是动态合并的,那我们就需要在每次变化的时候再去判断需要合并几列
1.先将【原始数据源】分组处理,计算每组的【小计】金额 ,然后写入【表格数据源】里
2.循环动态列,将列也分别写入三个数组里
3.判断我们【每组】【动态列】中是否符合我们的需求,是否要显示【小计】信息,设置【要合并的列】为1
4.如果存在,判断本组有无其他列显示,有的话【要合并的列数+1】
处理列数&计算要合并的列数
const handleColumnData = (row) => {console.log('row=======', row);let type1list = [];// 分组列1let type2list = []; // 分组列2let type3list = []; // 分组列3let haveAgreeTotal = false; // 分组列1是否有【小计】let haveIncomeTotal = false; // 分组列1是否有【小计】let haveReciveTotal = false; // 分组列1是否有【小计】let AgreeColspan = 0; // 分组列1要合并的列数let IncomeColspan = 0; // 分组列1要合并的列数let ReciveColspan = 0; // 分组列1要合并的列数row.forEach((item) => {if (item.type === 1) {type1list.push(item.key);} else if (item.type === 2) {type2list.push(item.key);} else if (item.type === 3) {type3list.push(item.key);}});// console.log('type1', type1list)// console.log('type2', type2list)// console.log('type3', type3list)if (type1list.length > 0) {// 如果同时存在【合同节点】和【金额】字段,显示小计if (type1list.includes('contractNodes') &&type1list.includes('Money')) {haveAgreeTotal = true;AgreeColspan = 1;if (type1list.includes('NodeRatio')) {AgreeColspan += 1;}if (type1list.includes('paymentTerms')) {AgreeColspan += 1;}}}if (type2list.length > 0) {// 如果同时存在【成果提交日期】和【确认收入】字段,显示小计if (type2list.includes('submissionDate') &&type2list.includes('Income')) {haveIncomeTotal = true;IncomeColspan = 1;if (type2list.includes('fileDate')) {IncomeColspan += 1;}if (type2list.includes('confirmationRatio')) {IncomeColspan += 1;}}}if (type3list.length > 0) {// 如果同时存在【到账日期】和【金额】字段,显示小计if (type3list.includes('DateofReceipt') &&type3list.includes('Money1')) {haveReciveTotal = true;ReciveColspan = 1;if (type3list.includes('confirmationRatio1')) {ReciveColspan += 1;}}}// console.log('haveAgreeTotal, haveIncomeTotal, haveReciveTotal', haveAgreeTotal, haveIncomeTotal, haveReciveTotal)// console.log('AgreeColspan, IncomeColspan, ReciveColspan', AgreeColspan, IncomeColspan, ReciveColspan)return {haveAgreeTotal,haveIncomeTotal,haveReciveTotal,AgreeColspan,IncomeColspan,ReciveColspan,};};
useEffect(() => {// setTableData(mockTableData)let source = formatData(mockTableData, rowData);setDataSource(source);}, []);
根据需求写入【小计】行
const formatData = (data, rowData) => {let obj = handleColumnData(rowData);let resTableData = [];const {haveAgreeTotal,haveIncomeTotal,haveReciveTotal,AgreeColspan,IncomeColspan,ReciveColspan,} = obj;// 是否有任意一组列存在小计,存在则写入新一行// 循环列表,把数据分组写入// 写入小计行,根据列标识写入要合并的列数// 渲染时判断标识行,写入列数,其余为0if (haveAgreeTotal || haveIncomeTotal || haveReciveTotal) {Object.keys(data).forEach((key) => {let group = data[key];let nodeSum = 0;let IncomeSum = 0;let Money1Sum = 0;group.forEach((item) => {resTableData.push(item);nodeSum += item.NodeRatio;IncomeSum += item.Income;Money1Sum += item.Money1;});let totalRecord = {group: key,id: '',order: '',type: '',isConsortium: '',nameSquare: '',cstatus: '',money: '',value1: '',confirmIncome: '',receivables: '',agree: '',receivePayment: '',};if (haveAgreeTotal) {totalRecord.contractNodes = '小计';totalRecord.Money = nodeSum;totalRecord.NodeRatio = nodeSum;totalRecord.paymentTerms = nodeSum;totalRecord.AgreeColspan = AgreeColspan;}if (haveIncomeTotal) {totalRecord.submissionDate = '小计';totalRecord.Income = IncomeSum;totalRecord.fileDate = IncomeSum;totalRecord.confirmationRatio = IncomeSum;totalRecord.IncomeColspan = IncomeColspan;}if (haveReciveTotal) {totalRecord.DateofReceipt = '小计';totalRecord.Money1 = Money1Sum;totalRecord.confirmationRatio1 = Money1Sum;totalRecord.ReciveColspan = ReciveColspan;}// console.log('recordtotal', totalRecord)resTableData.push(totalRecord);});} else {Object.keys(data).forEach((key) => {let group = data[key];group.forEach((item) => {resTableData.push(item);});});}
return resTableData};
渲染表格
此处我们要注意的是!当前合并单元格行数、列数设置好后,我们要把【被合并的行列】都设置为0!!并且【其他的行和列】的合并数也要都为0!不然表格会出现错位问题!
我们把cloumns列设置
{title: '合同约定',className: 'type1Column',children: [...flattenData(rowData, 0).filter((item) => item.checked).filter((item) => item.type === 1).map((item) => {return {title: (<div className="ellipsis-item" title={item.name}>{item.name}</div>),dataIndex: item.key,className: 'type1Column',width: 100,render: (text, record, index) => {if (record.AgreeColspan) { // 判断是否是小计行if (item.key === 'Money') {return {children: handleNode(item, text, 'total_back_pink'),props: { colSpan: record.AgreeColspan }, // 合并"小计"行从第二列开始的所有列};} else if (item.key === 'contractNodes') {return {children: handleNode(item, text, 'total_back_pink'),props: { colSpan: 1 }, // "小计"列不合并};} else {return {children: handleNode(item, text, 'total_back_pink'),props: { colSpan: 0 }, // 当前组其他列设置为0,不会出现表格错位情况};}} else {return {children: handleNode(item, text),props: { colSpan: 1 }, // 非"小计"行全部不合并};}},};}),],},
这样就实现了【分组合并列】、【动态渲染列】啦!
2.合并行
思路
循环【数据源】,从第一行开始判断,如果【当前行】与【下一行】是同一组,那【rowSpan】 + 1,【被合并的行】记得要设置为0哦
const formatData = (data, rowData) => {// 处理要合并的列...// 处理要合并的行let processedData = [...resTableData];let prevFinishNum;let currentIndexForSameProperty;for (let i = 0; i < processedData.length; i++) {const currentItem = processedData[i];if (i === 0 || currentItem.group !== prevFinishNum) {// 新的组开始,重置计数器,并将上一组最后一项的rowSpan设置好if (prevFinishNum !== undefined &¤tIndexForSameProperty !== undefined) {processedData[currentIndexForSameProperty].rowSpan =i - currentIndexForSameProperty;}currentIndexForSameProperty = i;currentItem.rowSpan = 1;currentItem.opcaty = '0'; // 标识是不是被合并的行} else {// 相同组内,累加rowSpanprocessedData[currentIndexForSameProperty].rowSpan += 1;currentItem.opcaty = '1'; // 标识是被合并的行}prevFinishNum = currentItem.group;}// 处理数组的最后一项if (currentIndexForSameProperty !== undefined &¤tIndexForSameProperty < processedData.length - 1) {processedData[currentIndexForSameProperty].rowSpan =processedData.length - currentIndexForSameProperty;}return processedData;}
这样就实现了【合并行】啦!
3.嵌套表头
这个在 antd官网 都有,就是给columns设置children就行了,咱们在上面【渲染动态列】的代码里也有提到 ~
相关文章:

antd table合并复杂单元格、分组合并行、分组合并列、动态渲染列、嵌套表头
项目里遇到个需求,涉及到比较复杂的单元格合并 、嵌套表头、分组合并行、合并列等,并且数据列还是动态的,效果图如下: 可以分组设置【显示列】例如:当前组为【合同约定】,显示列为【合同节点】和【节点金额…...

一键安装与配置Stable Diffusion,轻松实现AI绘画
随着技术的迭代,目前 Stable Diffusion 已经能够生成非常艺术化的图片了,完全有赶超人类的架势,已经有不少工作被这类服务替代,比如制作一个 logo 图片,画一张虚拟老婆照片,画质堪比相机。 最新 Stable Di…...

模板和静态文件
模板和静态文件 1、templates模板2、静态文件2.1、static目录2.2、引用静态文件 1、templates模板 "templates"目录用于存放模板文件,通常是用于动态生成页面的文件。 在app01目录下创建templates文件夹,html文件均保存在templates中 在urls.p…...
Android Studio 打包aar丢失远程依赖问题解决
之前打包,使用的com.kezong.fat-aar,embed(‘XXXX’)的方式,可以使三方依赖打包在aar包里,在项目里直接使用 升级了Gradle:7.5后,打包就打包不起来了,一直报错ÿ…...

Chromium 搜索引擎功能浅析c++
地址栏输入:chrome://settings/searchEngines 可以看到 有百度等数据源,那么如何调整其顺序呢,此数据又存储在哪里呢? 1、浏览器初始化搜索引擎数据来源在 components\search_engines\prepopulated_engines.json // Copyright …...

DDoS攻击快速增长,如何在抗ddos防护中获得主动?
当下DDoS攻击规模不断突破上限。前段时间,中国首款3A《黑神话:悟空》也在一夜之内遭受到28万次攻击DDoS攻击,严重影响到全球玩家的游戏体验。Gcore发布的数据也显示了 DDoS攻击令人担忧的趋势,尤其是峰值攻击已增加到了令人震惊的…...
MongoDB 死锁 锁定问题
要查看 MongoDB 是否出现“锁死” (也就是所谓的 锁定问题,通常指长时间的锁定导致数据库操作无法正常进行),可以通过以下几种方法来检测数据库的锁定状态和锁定相关信息。 1. 使用 db.currentOp() 检查活动操作 MongoDB 提供了 db.currentOp() 命令来查…...

鸿蒙--商品列表
这里主要利用的是 List 组件 相关概念 Scroll:可滚动的容器组件,当子组件的布局尺寸超过父组件的视口时,内容可以滚动。List:列表包...

【Fargo】5:根据网络带宽动态调整发送速率
根据网络带宽动态调整发送速率 原理:这个简单实现的原理是 改变包的发送速率就可以改变发送码率了。例如1秒发1000个1KB 的包,带宽8Mbps,如果带宽是4Mbps,那么1秒发500个就够了。D:\XTRANS\thunderbolt\ayame\zhb-bifrost\player-only\worker\src\fargo\zhb_uv_udp_sender.…...
入门C语言:从原码、反码、补码到位运算
入门C语言:从原码、反码、补码到位运算 C语言作为一门底层编程语言,离不开对计算机硬件的深入理解。掌握整数的二进制表示法和位运算是深入学习C语言的基础。对于大一新生来说,理解原码、反码、补码与位运算这几个概念,将帮助你更…...

18770 差值最大
### 思路 为了找到两个数x和y使得x - y的值最大,并且x在y的右侧,我们可以使用以下方法: 1. 从右向左遍历数组,记录当前遍历到的最大值max_right。 2. 对于每个元素a[i],计算max_right - a[i],并更新最大差…...

【Flutter】合并多个流Stream
1.说明 无意间发现了一个好用的库rxdart,它为 Dart 的 Stream 添加了额外的功能。 2.功能 (1)合并多个流Stream 借助Rx.combineLatest2()合并两个流stream1和stream2。 注意:如果dart文件中同时使用了getx,需要隐…...
【SQL学习笔记】
Pycharm社区版的页面中无database选项? 1、进入Setting-Pluggins窗口,输入database navigator 2、安装后,重启即可 MySQL 的架构共分为两层:Server 层和存储引擎层 1、Server 层负责建⽴连接、分析和执⾏ SQL 2、存储引擎层负…...
contact form 7设置方法与详细步骤
Contact Form 7(CF7)是WordPress中非常流行的表单插件,用于创建和管理网站上的联系表单。以下是Contact Form 7的设置方法与详细步骤: 一、安装Contact Form 7插件 从WordPress后台安装: 登录WordPress后台,进入“插件”菜单下…...

第170天:应急响应-战中溯源反制对抗上线CSGoby蚁剑Sqlmap等安全工具
目录 案例一:溯源反制-Webshell工具-Antsword 案例二:溯源反制-SQL注入工具-SQLMAP 案例三:溯源反制-漏洞扫描工具-Goby 案例四:溯源反制-远程控制工具-CobaltStrike 反制Server,爆破密码(通用&#x…...
5-容器管理工具Docker
├──5-容器管理工具Docker | ├──1-容器管理工具Docker | | ├──1-应用部署容器化演进之路 | | ├──2-容器技术涉及Linux内核关键技术 | | ├──3-Docker生态架构及部署 | | ├──4-使用容器运行Nginx及docker命令介绍 | | ├──5-容器镜像介…...

OCR+PDF解析配套前端工具开源详解!
目录 一、项目简介 TextIn为相关领域的前端开发提供了优秀的范本。 目前项目已在Github上开源! 二、性能特色 三、安装使用 安装依赖启动项目脚本命令项目结构 四、效果展示 面对日常生活和工作中常见的OCR识别、PDF解析、翻译、校对等场景,配套的…...

【操作系统】引导(Boot)电脑的奇妙开机过程
🌹😊🌹博客主页:【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见:【C语言专项】 目录 什么是操作系统的引导? 操作系统的引导(开机过程) Windows操作系…...

国产云桌面迁移对接信创AD域控方案
在前文《替换AD域时,网络准入场景如何迁移对接国产身份域管?》中,根据 AD 在企业中的应用程度,我们将企业分为了轻度、中度及深度三类微软 AD 用户。 轻度AD用户:仅部分应用对接 AD 。替换 AD 时,可能会直接…...

ESP32—C3实现DS18B20(温度传感器)检测温度(Arduino IED )
1源代码(DS18B20) #include <OneWire.h> // 引入OneWire库,用于与单总线设备通信 #include <DallasTemperature.h> // 引入DallasTemperature库,用于读取DS18B20温度传感器数据// 定义连接到DS18B20数据引脚的GPIO编…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...