先上成品示意图:

几个关键步骤:

一 定义数据结构:

export const data = [{key: 'row1',beforeUpdateLevel: '等级1',level_1: '保',level_2: '升',level_3: '升',level_4: '未设置',level: 1, // 表示当前行变更前为等级1},{key: 'row2',beforeUpdateLevel: '等级2',level_1: '降',level_2: '保',level_3: '升',level_4: '升',level: 2,},{key: 'row3',beforeUpdateLevel: '等级3',level_1: '降',level_2: '未设置',level_3: '未设置',level_4: '升',level: 3,},{key: 'row4',beforeUpdateLevel: '等级4',level_1: '降',level_2: '未设置',level_3: '未设置',level_4: '未设置',level: 4,},
];

二 实现表头分组:

利用column--->title属性 实现表头对角线分组" data-link-title="antd Table-->column--->title属性 实现表头对角线分组">antd Table-->column--->title属性 实现表头对角线分组

const columns = [// 利用title可以返回ReactNode属性  和 css 实现分组{title: (<div className={styler.headerCell}><div className={styler.afer}>变更后等级</div><div className={styler.before}>变更前等级</div></div>),dataIndex: 'beforeUpdateLevel',key: 'beforeUpdateLevel',// 固定分组这一栏的宽度width: 220,align: 'center',},{title: '等级1',dataIndex: 'level_1',align: 'center',key: 'level_1',},{title: '等级2',dataIndex: 'level_2',align: 'center',key: 'level_2',},{title: '等级3',dataIndex: 'level_3',align: 'center',key: 'level_3',},{title: '等级4',dataIndex: 'level_4',align: 'center',key: 'level_4',},];

css 实现画对角线:

.headerCell {// 画三角形border-top: 43px rgb(250 250 250) solid;/*上边框宽度等于表格第一行行高*/width: 0px;/*让容器宽度为0*/height: 0px;/*让容器高度为0*/border-left: 237px #f8fbff solid;/*左边框宽度等于表格第一行第一格宽度*/position: relative;.afer {position: absolute;top: -36px;left: -70px;width: 60px;color: #666666;}.before {position: absolute;top: -24px;left: -226px;width: 60px;color: #666666;}// 伪元素画分割线&::after {content: '';position: absolute;width: 1px;height: 237px;top: -140px;left: -120px;background-color: rgb(239 239 239);display: block;transform: rotate(-80deg);}}

注意:

固定分组表头的宽度,否则响应式可能会引起表头斜线错位等问题

三:添加单元格点击事件  设置选中状态

利用onCell属性为单元格添加点击事件

 // 设置第一个单元格为默认选中const [active, setActive] = useState('row1_level_1');const newColums = columns.map((col, index) => {return {...col,onCell: (record) => ({record,dataIndex: col.dataIndex,title: col.title,onClick: () => cellHandleClick(record, col),}),};});const cellHandleClick = (record, col) => {const { key } = record;const { dataIndex } = col;// 利用record和col的组合keysetActive(`${key}_${dataIndex}`);
};

四:完整代码

import React, { useState, useEffect } from 'react';
import { Popover, Table, Tag } from 'antd';
import { data } from './data';
import classNames from 'classnames';
import DownPopover from './DownPopover';
import StayPopover from './StayPopover';
import UpPopover from './UpPopover';
import styler from './index.less';
import { history } from 'umi';export default function ViewFlow({ onCellClick }) {const [active, setActive] = useState('row1_level_1');const SettingCell = ({title,dataIndex,children,record,...restProps}) => {let childNode = children;const [show, setShow] = useState(false);useEffect(() => {}, [show]);const handleOver = () => {setShow(true);};const handleOut = () => {setShow(false);};const SettingBtn = (<divclassName={styler.settingBtn}onClick={() => handleGoSetting(record, dataIndex)}>去设置</div>);const renderText = (record, dataIndex) => {const { level } = record;const [_, currentLevel] = dataIndex.split('_');const text = record?.[dataIndex];switch (text) {case '未设置':return show ? SettingBtn : <div className={styler.base}>{text}</div>;case '保':return (<Itemtext={text}level={level}currentLevel={currentLevel}color="#3880FF"background="rgba(56, 128, 255, 0.05)"/>);case '降':return (<Itemtext={text}level={level}currentLevel={currentLevel}color="#FF3D00"background="rgba(255, 61, 0, 0.05)"/>);case '升':return (<Itemtext={text}level={level}currentLevel={currentLevel}color="#24B488"background="rgba(36, 180, 136, 0.05)"/>);default:return text;}};childNode = renderText(record, dataIndex);const key = `${record?.key}_${dataIndex}`;return (<tdonMouseOut={handleOut}onMouseOver={handleOver}{...restProps}className={classNames({ active: key === active },{ firstColumnClass: dataIndex === 'beforeUpdateLevel' },)}>{childNode}</td>);};const ItemMap = {升: UpPopover,降: DownPopover,保: StayPopover,};const Item = ({ color, background, text, level, currentLevel }) => {const Content = ItemMap[text];return (<Popovercontent={<Content level={level} currentLevel={currentLevel} />}placement="bottomRight"><div className={styler.text}><div style={{ color, background }}>{text}</div></div></Popover>);};const handleGoSetting = (record, dataIndex) => {const { level } = record;const [, levelNum] = dataIndex.split('_');};const cellHandleClick = (record, col) => {const { key } = record;const { dataIndex } = col;setActive(`${key}_${dataIndex}`);};const columns = [{title: (<div className={styler.headerCell}><div className={styler.afer}>变更后等级</div><div className={styler.before}>变更前等级</div></div>),dataIndex: 'beforeUpdateLevel',key: 'beforeUpdateLevel',width: 220,align: 'center',},{title: '等级1',dataIndex: 'level_1',align: 'center',key: 'level_1',},{title: '等级2',dataIndex: 'level_2',align: 'center',key: 'level_2',},{title: '等级3',dataIndex: 'level_3',align: 'center',key: 'level_3',},{title: '等级4',dataIndex: 'level_4',align: 'center',key: 'level_4',},];const newColums = columns.map((col, index) => {return {...col,onCell: (record) => ({record,dataIndex: col.dataIndex,title: col.title,onClick: () => cellHandleClick(record, col),}),};});const components = {body: {cell: SettingCell,},};return (<div className={styler.content}><Tablecomponents={components}columns={newColums}bordereddataSource={data}pagination={false}/></div>);
}

data.js

export const data = [{key: 'row1',beforeUpdateLevel: '等级1',level_1: '保',level_2: '升',level_3: '升',level_4: '未设置',level: 1, // 表示当前行变更前为等级1},{key: 'row2',beforeUpdateLevel: '等级2',level_1: '降',level_2: '保',level_3: '升',level_4: '升',level: 2,},{key: 'row3',beforeUpdateLevel: '等级3',level_1: '降',level_2: '未设置',level_3: '未设置',level_4: '升',level: 3,},{key: 'row4',beforeUpdateLevel: '等级4',level_1: '降',level_2: '未设置',level_3: '未设置',level_4: '未设置',level: 4,},
];

index.less

.content {.base {padding: 5px 0px;color: #c8c8c8;width: 60px;display: inline-block;}.settingBtn {box-sizing: border-box;display: inline-block;background: rgba(56, 128, 255, 0.1);border: 1px solid rgba(56, 128, 255, 0.5);padding: 4px;width: 60px;border-radius: 2px;color: #3880ff;}.text {box-sizing: border-box;width: 60px;padding: 4px 0;display: inline-flex;justify-content: center;align-items: center;div {width: 20px;height: 20px;border-radius: 50%;background: rgba(56, 128, 255, 0.05);}}.headerCell {// 画三角形border-top: 43px rgb(250 250 250) solid;/*上边框宽度等于表格第一行行高*/width: 0px;/*让容器宽度为0*/height: 0px;/*让容器高度为0*/border-left: 237px #f8fbff solid;/*左边框宽度等于表格第一行第一格宽度*/position: relative;.afer {position: absolute;top: -36px;left: -70px;width: 60px;color: #666666;}.before {position: absolute;top: -24px;left: -226px;width: 60px;color: #666666;}// 伪元素画分割线&::after {content: '';position: absolute;width: 1px;height: 237px;top: -140px;left: -120px;background-color: rgb(239 239 239);display: block;transform: rotate(-80deg);}}:global {.firstColumnClass {background: #f8fbff;}.active {background: linear-gradient(0deg,rgba(56, 128, 255, 0.05),rgba(56, 128, 255, 0.05));// border: 1px solid #3880ff;// border-right: 1px solid #3880ff !important ;// box-sizing: border-box;box-shadow: 0px 0px 2px #3880ff inset;}.ant-table-thead {height: 30px;}.ant-table-tbody > tr > td {padding: 8px 0px;}.ant-table.ant-table-bordered> .ant-table-container> .ant-table-content> table> thead> tr> th {padding: 0;}// .ant-table-tbody > tr > td :first-child {//   background: #f8fbff;//   &:hover {//     background: #f8fbff;//   }// }background: #f8fbff;// .ant-table-tbody > tr > td:nth-child(2) {//   background: #bae7ff;// }.ant-table-tbody > tr > td:hover {cursor: pointer;background: linear-gradient(0deg,rgba(56, 128, 255, 0.05),rgba(56, 128, 255, 0.05));}}
}

DownPopver.jsx

import React from 'react';
import { Popover, Space, Tag, Typography } from 'antd';
export default function DownPopover({ level, currentLevel }) {return (<Space size={10} direction="vertical"><Tag color="#FF3D00">降级</Tag><><Typography.Text type="secondary">变更前等级:<Typography.Text>等级{`${level}`}</Typography.Text></Typography.Text><Typography.Text type="secondary">变更后等级:<Typography.Text>等级{`${currentLevel}`}</Typography.Text></Typography.Text></></Space>);
}

StayPopover.jsx

import React from 'react';
import { Popover, Space, Tag, Typography } from 'antd';
export default function StayPopover({ level, currentLevel }) {return (<Space size={10} direction="vertical"><Tag color="#599CFF">保级</Tag><><Typography.Text type="secondary">保级等级:<Typography.Text>等级{`${currentLevel}`}</Typography.Text></Typography.Text></></Space>);
}

UpPopover.jsx

import React from 'react';
import { Popover, Space, Tag, Typography } from 'antd';
export default function UpPopover({ level, currentLevel }) {return (<Space size={10} direction="vertical"><Tag color="#24B488">升级</Tag><><Typography.Text type="secondary">变更前等级:<Typography.Text>等级{`${level}`}</Typography.Text></Typography.Text><Typography.Text type="secondary">变更后等级:<Typography.Text>等级{`${currentLevel}`}</Typography.Text></Typography.Text><Typography.Text type="secondary">状态:<Typography.Text>启用</Typography.Text></Typography.Text></></Space>);
}

React antd Table 实现单元格点击 表头斜线分组等功能相关推荐

  1. vue中用table_Vue中table合并单元格用法

    地名 结果 人名 性别 {{item.name}} 已完成 未完成 {{item.groups[0].name}} {{item.groups[0].sex}} {{item.groups[son]. ...

  2. 解决element-ui中表格行点击事件和表格单元格点击事件冲突的问题

    element-ui中如果同时设置了表格行点击事件和表格单元格点击事件的化,当点击单元格的时候会因为事件冒泡触发表格行点击事件,这不是我们需要的 要解决这种事件冲突的问题,只需要在单元格的点击事件上加 ...

  3. html table 合并单元格 分页,Word表格跨页,合并单元格后,希望跨页的每一页都显示合并单元格的内容(有图)...

    回答: 一.使用Excel开始菜单中的合并功能 Excel表格中合并单元格有很多中形式,比如:合并居中.合并单元格.按行合并.跨列居中.合并相同单元格和合并内容.接下来看看具体操作步骤吧! 步骤:选中 ...

  4. itext隐藏table的单元格边框

    隐藏table的单元格边框 PdfPCell的方法disableBorderSide(1); 参数为int型. 其中具体参数: //隐藏上边框 // cell.disableBorderSide(1) ...

  5. 表格合并行的方法和单元格点击事件

    el-table部分 <el-table max-height="100%" @cell-click="cellClick":data="dat ...

  6. Table合并单元格,表格居中,内容居中显示

    例如:新建一张四行四列的表格,第一行的四列合并,第二.三.四行的第一列合并在一起居中显示 <%@ page language="java" contentType=" ...

  7. element plus的table合并单元格

    element的table合并单元格 就element+中的el-table中的span-method方法的使用和遇到的一些问题 如果想要将后一列挨着的单元格合并,return 1,2,但是得将后一个 ...

  8. Layui table表格单元格合并问题

    Layui table表格单元格合并 人丑话不多, 直接上方法: /*** * @param fieldName 要合并列的field属性值* @param index 表格的索引值 从1开始* @d ...

  9. js实现 table合并单元格

    ** table合并单元格 function uniteTdCells(tableId){var table = document.getElementById(tableId);for (let i ...

最新文章

  1. 阿里巴巴Druid,轻松实现MySQL数据库加密!
  2. go语言笔记——map map 默认是无序的,不管是按照 key 还是按照 value 默认都不排序...
  3. boost::lockfree::detail::tagged_ptr用法的测试程序
  4. shell脚本实现无密码交互的SSH自动登陆
  5. linux mysql 最小安装,Linux最小化安装之安装mysql
  6. 交流伺服系统设计指南_交流设计
  7. 测试驱动开发 测试前移_为什么测试驱动的开发有用?
  8. C++设计模式之二 AbstractFactory模式
  9. 【Java】计算符号函数的值
  10. linux安装mysql5.7.29_linux 之centos7搭建mysql5.7.29的详细过程
  11. 阿里云的RDS 查看binlog日志的方法
  12. 【Elasticsearch】zen discovery集群发现机制
  13. UML与软件建模 第五次作业
  14. DDoS booter滥用 DTLS 服务器放大攻击
  15. list转有序map
  16. Unity 随机生成中文名字
  17. PKU ACM 1008 玛雅历
  18. 【VOLTE】【SRVCC】【2】 VOLTE SRVCC(SRVCC TO 3GPP2/CDMA1X)
  19. GDAL综合整理--7:GDAL实用工具简介
  20. 这个春天,邀你一起探寻AI与青春的碰撞之力

热门文章

  1. FTP服务器配置实例(匿名用户、本地用户、虚拟用户)
  2. 如何查看linux上的ftp服务器配置,ftp服务器配置:如何在Linux上搭建FTP服务器?
  3. 决策易|营销管理,让流向数据说话!
  4. [Asp.net]web.config customErrors 如何设置?
  5. Excel VBA解析JSON数据
  6. 面试常问集锦——线上排查部分
  7. vue canvas 方法无效_3 分钟,教会你如何用 Vue 实现 Google 搜索中灭霸的无限手套...
  8. MapReduce编程
  9. 使用PyQt5写一个桌面程序
  10. 【Java】一文秒懂http请求获取FlexManager某设备分组监控点