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编…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
