react antd table 自定义表头功能实现

react antd table 自定义表头功能

Ⅰ- 壹 - 功能展示和使用需求

需求描述

基于antd table 实现

自定义 table 的表头 内容 排序 宽度和顺序等 , 可根据自己的需求自己扩展

github:https://github.com/whqgo/ReactAntdTableCustomHeader

功能展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Ⅱ - 贰 - 封装思路

在这里插入图片描述

TaskareaTableColumns: 主要对 弹框内容的封装

app.tsx:使用的方式 和对表头数据的描述

json.ts: 数据文件 主要用于模拟的数据

设计思路

用对象数组描述表格 然后进行解析读取处理 , 这是最原始的数据,

const [taskareaTableColumnsData, setTaskareaTableColumnsData] = useState({isShow: false, //控制显示隐藏type: 'taskarea',fields: fixedFields, // 当前字段的 模型数据  , 目的是为了 对字段的控制, 业务需要, // 用于修改 和默认columns: [// {//     serial: '', // //     lable: '', //表头的名称 多个用 /  隔开//     lableRename: '', //表头的 重命名名称 优先级高于lable //     value: [], // 要读取数据的字段key要读取数据的字段key 和 lable 关系对应//     expression:'',// 表达式,fields存在的才能做计算//     width: '',//宽度//     defaultSortOrder: '',// 数据 的 排序方式//     style:'',//样式//     visible:'',//可视//     noRender:true,// 是否 重写 render//... 和 antd table columns 配置一样// }{key: 'workDispatchOrdersProcessN.paiGongDanHao',id: '1', //serial: '1',// lable: ['工序名称', '派工单号'], //表头的名称 多个用 /  隔开lableRename: '工序/单号', //表头的 重命名名称 优先级高于lable title: '工序/单号', //表头的最终 重命名名称 优先级高于lable value: ['workDispatchOrdersProcessN', 'paiGongDanHao'], // 要读取数据的字段key 和 lable 关系对应expression: '',// 表达式,fields存在的才能做计算width: '',//宽度visible: true,//可视defaultSortOrder: '',// 数据 的 排序方式 styleType: 'def',//样式风格  def 默认文本  number 数字样式style: {},//样式align: 'center',//表头居中},{key: 'yxfw',id: '22', // serial: '22', // // lable: ['物品名称'], //表头的名称 多个用 /  隔开lableRename: '规格', //表头的 重命名名称 优先级高于lable title: '规格',value: ['yxfw'], // 要读取数据的字段keyexpression: '',// 表达式,fields存在的才能做计算width: '',//宽度defaultSortOrder: '',// 数据 的 排序方式visible: true,//可视styleType: 'def',//样式风格  def 默认文本  number 数字样式style: { flex: 3 },//样式align: 'center',//表头居中},{title: '操作',key: 'action',serial: '000000',id: 'aaa111bbb222ccc333',noRender: true,// 是否 重写 renderalign: 'center',//表头居中visible: true,//可视width: '300px',render: (_: any, record: any) => {return <div className='operation-item-content-taskarea'><div style={{ 'justifyContent': 'space-evenly', flex: '1' }}><div className='operation-badge-taskarea1'><div style={{}}><Button type="primary" onClick={() => {console.log("操作====按钮触发", record);}} size={'large'}>按钮</Button></div></div></div></div>},},],severalRows: 3// 控制合并行数})

我们可以在 useEffect进行动态控制 这里我们对 tableColumns 中的数据进行了二次处理 目的是在 这里就能获取到我当前的表头原始的数据,去控制最终要显示的数据处理,例如他的表头 文字 title,我需要根据两个值去判最终的结果,render中是根据我需求去做的处理

  useEffect(() => {if (!taskareaTableColumnsData?.columns) returnif (workDispatchOrdersData?.length) {setTableColumns(() => (taskareaTableColumnsData.columns.reduce((preData: any, curData: any) => {// 判断是否可视if (curData.visible) {return curData.noRender ? [...preData, curData] : [...preData, {...curData,title: (record: any) => {let titleStr = curData?.lableRename || (taskareaTableColumnsData.fields.filter((f: any) => curData.value.includes(f.c))).map((f1: any) => f1.n).join('/')return <div>{titleStr}</div>},width: curData.width ? !isNaN(curData.width) ? curData.width + 'px' : curData.width : '',render: (_: any, record: any, index: any) => {return (<div className='operation-item-content-taskarea'><div>{(() => {switch (curData.styleType) {case 'def':return curData?.value?.map((cITem: any, i: number) => {return <div key={i}> {record[cITem]}</div>})case 'number':let socketMessageWSDataFind = null// 获取字段 模型的属性 let filterModels = fixedFields.filter((f: any) => curData?.value.includes(f.c))// 判断是不是 自定义的模型 需要特殊处理let customDefinitionFind: any = filterModels.find((f: any) => f.sourceDataType == "customDefinition")return <div style={{ justifyContent: 'start' }}>{/* <div className='operation-badge-taskarea'>{`${item['dmvl'] || 0}/${item['jiHuaShengChanShuLiang']}`}</div> */}{/*  没有推送的时候 查询模型   实际生产数量/计划生产数量 */}<div className='operation-badge-taskarea'>{curData?.expression ? eval(curData.expression) : curData?.value?.reduce((preValData: any, curValData: any) => {// return preValData + (record[curValData] ? (record[curValData]) : '')return [...preValData, record[curValData] || 0]}, []).join('/')}{/* 审核中 样式样式处理  */}{customDefinitionFind && <div className={customDefinitionFind?.className}>{eval(customDefinitionFind?.expression) || ''}</div>}</div></div>default:return curData?.value?.map((cITem: any, i: number) => {return <div key={i}> {record[cITem]}</div>})}})()}</div></div>)},onCell: (record: any, index: number) => {const cIndex = taskareaTableColumnsData.columns.findIndex(cItem => cItem.id === curData.id)if (curData.styleType === 'def' && cIndex + 1 <= taskareaTableColumnsData.severalRows) {try {if (index) { // 不是第一条const preD = workDispatchOrdersData[index - 1], nextD = workDispatchOrdersData[index];if (!preD || !nextD) return {}let preV = '', nextV = '';curData.value.map((item: string) => {preV += preD[item]nextV += nextD[item]})if (preV === nextV) { // 上一条和当前条相等,不渲染return { rowSpan: 0 }}}if (index !== workDispatchOrdersData.length - 1) { // 不是最后一条let unlikeIndex = workDispatchOrdersData.length - index; // 默认全部相等for (let i = index; i < workDispatchOrdersData.length; i++) {const nextD = workDispatchOrdersData[i + 1], currentD = workDispatchOrdersData[i];if (!nextD) break;let currentV = '', nextV = '';curData.value.map((item: string) => {currentV += currentD[item]nextV += nextD[item]})if (i !== workDispatchOrdersData.length - 1 && nextV !== currentV) { // 当前条和下一条不相等,就是需要合并的数unlikeIndex = i - index + 1break;}}return { rowSpan: unlikeIndex }}} catch (err) { console.log(err); }}return {}}}]} else {return preData}}, [])))}}, [workDispatchOrdersData, taskareaTableColumnsData.columns])

在弹框中 TaskareaTableColumns这个组件,就是把taskareaTableColumnsData.columns 中的配置当成数据去处理的,然后对他的内容做了自定义处理,详情看代码

github:https://github.com/whqgo/ReactAntdTableCustomHeader

Ⅲ - 叁 - 主要代码

APP.tsx使用

import { useEffect, useState } from 'react'
import './App.css'
import { Button, Checkbox, Input, InputNumber, Modal, Select, Space, Table } from 'antd';
import TaskareaTableColumns from './TaskareaTableColumns';
import { cloneDeep } from 'lodash'
import { fixedFields, MNData } from './json'
function App() {const [taskareaTableColumnsData, setTaskareaTableColumnsData] = useState({isShow: false, //控制显示隐藏type: 'taskarea',fields: fixedFields, // 当前字段的 模型数据  , 目的是为了 对字段的控制, 业务需要, // 用于修改 和默认columns: [// {//     serial: '', // //     lable: '', //表头的名称 多个用 /  隔开//     lableRename: '', //表头的 重命名名称 优先级高于lable //     value: [], // 要读取数据的字段key要读取数据的字段key 和 lable 关系对应//     expression:'',// 表达式,fields存在的才能做计算//     width: '',//宽度//     defaultSortOrder: '',// 数据 的 排序方式//     style:'',//样式//     visible:'',//可视//     noRender:true,// 是否 重写 render//... 和 antd table columns 配置一样// }{key: 'workDispatchOrdersProcessN.paiGongDanHao',id: '1', //serial: '1',// lable: ['工序名称', '派工单号'], //表头的名称 多个用 /  隔开lableRename: '工序/单号', //表头的 重命名名称 优先级高于lable title: '工序/单号', //表头的最终 重命名名称 优先级高于lable value: ['workDispatchOrdersProcessN', 'paiGongDanHao'], // 要读取数据的字段key 和 lable 关系对应expression: '',// 表达式,fields存在的才能做计算width: '',//宽度visible: true,//可视defaultSortOrder: '',// 数据 的 排序方式 styleType: 'def',//样式风格  def 默认文本  number 数字样式style: {},//样式align: 'center',//表头居中},{key: 'workDispatchOrdersItemN',id: '2', // serial: '2', // // lable: ['物品名称'], //表头的名称 多个用 /  隔开lableRename: '物品', //表头的 重命名名称 优先级高于lable title: '物品',value: ['workDispatchOrdersItemN'], // 要读取数据的字段keyexpression: '',// 表达式,fields存在的才能做计算width: '',//宽度defaultSortOrder: '',// 数据 的 排序方式visible: true,//可视styleType: 'def',//样式风格  def 默认文本  number 数字样式style: { flex: 3 },//样式align: 'center',//表头居中},{key: 'yxfw',id: '22', // serial: '22', // // lable: ['物品名称'], //表头的名称 多个用 /  隔开lableRename: '规格', //表头的 重命名名称 优先级高于lable title: '规格',value: ['yxfw'], // 要读取数据的字段keyexpression: '',// 表达式,fields存在的才能做计算width: '',//宽度defaultSortOrder: '',// 数据 的 排序方式visible: true,//可视styleType: 'def',//样式风格  def 默认文本  number 数字样式style: { flex: 3 },//样式align: 'center',//表头居中},{key: 'oiwo',id: '222', // serial: '222', // // lable: ['物品名称'], //表头的名称 多个用 /  隔开lableRename: '库存代码', //表头的 重命名名称 优先级高于lable title: '库存代码',value: ['oiwo'], // 要读取数据的字段keyexpression: '',// 表达式,fields存在的才能做计算width: '',//宽度defaultSortOrder: '',// 数据 的 排序方式visible: true,//可视styleType: 'def',//样式风格  def 默认文本  number 数字样式style: { flex: 3 },//样式align: 'center',//表头居中},{key: 'cqsw',id: '2222', // serial: '2222', // // lable: ['物品名称'], //表头的名称 多个用 /  隔开lableRename: '客户简称', //表头的 重命名名称 优先级高于lable title: '客户简称',value: ['cqsw'], // 要读取数据的字段keyexpression: '',// 表达式,fields存在的才能做计算width: '',//宽度defaultSortOrder: '',// 数据 的 排序方式visible: true,//可视styleType: 'def',//样式风格  def 默认文本  number 数字样式style: { flex: 3 },//样式align: 'center',//表头居中},{key: 'frbz.sene',id: '3',serial: '3',// lable: ['主设备名称'], //表头的名称 多个用 /  隔开lableRename: '主设备/设备部位', //表头的 重命名名称 优先级高于lable title: '主设备',value: ['frbz', 'sene'], // 要读取数据的字段keyexpression: '',// 表达式,fields存在的才能做计算width: '',//宽度defaultSortOrder: '',// 数据 的 排序方式visible: true,//可视styleType: 'def',//样式风格  def 默认文本  number 数字样式style: {},//样式align: 'center',//表头居中},{key: 'dmvl.jiHuaShengChanShuLiang.mvit',id: '4',serial: '4',lable: ['实际生产数量', '计划生产数量', '审核中'], //表头的名称 多个用 /  隔开lableRename: '实际生产数量/计划生产数量', //表头的 重命名名称 优先级高于lable title: '实际生产数量/计划生产数量',value: ['dmvl', 'jiHuaShengChanShuLiang', 'mvit'], // 要读取数据的字段keyexpression: "`${socketMessageWSDataFind ? (socketMessageWSDataFind['dmvl'] || record['dmvl'] || 0) : record['dmvl'] || 0}/${record['jiHuaShengChanShuLiang'] || 0}`",// 表达式,fields存在的才能做计算width: '',//宽度defaultSortOrder: '',// 数据 的 排序方式visible: true,//可视styleType: 'number',//样式风格  def 默认文本  number 数字样式style: { textAlign: 'start', flex: 3 },//样式\align: 'center',//表头居中},// {//     key: 'dmvl.jiHuaShengChanShuLiang',//     id: '5',//     serial: '5',//     lable: ['实际生产数量', '计划生产数量'], //表头的名称 多个用 /  隔开//     lableRename: '实际生产数量12/计划生产数量333', //表头的 重命名名称 优先级高于lable //     value: ['dmvl', 'jiHuaShengChanShuLiang'], // 要读取数据的字段key//     expression: "",// 表达式,fields存在的才能做计算//     width: '',//宽度//     defaultSortOrder: '',// 数据 的 排序方式//     visible: true,//可视//     styleType: 'number',//样式风格  def 默认文本  number 数字样式//     style: { textAlign: 'start', flex: 3 },//样式\//     align: 'center',//表头居中// },{title: '操作',key: 'action',serial: '000000',id: 'aaa111bbb222ccc333',noRender: true,// 是否 重写 renderalign: 'center',//表头居中visible: true,//可视width: '300px',render: (_: any, record: any) => {return <div className='operation-item-content-taskarea'><div style={{ 'justifyContent': 'space-evenly', flex: '1' }}><div className='operation-badge-taskarea1'><div style={{}}><Button type="primary" onClick={() => {console.log("操作====按钮触发", record);}} size={'large'}>按钮</Button></div></div></div></div>},},],severalRows: 3// 控制合并行数})// 最终的 columnsconst [tableColumns, setTableColumns] = useState<any>([])const taskareaTableColumnsFillData = (FillDatType: any, tableColumnsFillData: any) => {// console.log(tableColumnsFillData, "===tableColumnsFillData===");// console.log(FillDatType, "===isShow===");// console.log(taskareaTableColumnsData, "===isShow===");if (FillDatType) {setTaskareaTableColumnsData((taskareaTableColumnsData: any) => {let _taskareaTableColumnsData = cloneDeep(taskareaTableColumnsData)_taskareaTableColumnsData.isShow = false_taskareaTableColumnsData.columns = [...tableColumnsFillData.tableData, _taskareaTableColumnsData.columns[_taskareaTableColumnsData.columns?.length - 1]]_taskareaTableColumnsData.severalRows = tableColumnsFillData.severalRowsreturn _taskareaTableColumnsData})} else {setTaskareaTableColumnsData((taskareaTableColumnsData: any) => ({ ...taskareaTableColumnsData, isShow: false }))}}const [workDispatchOrdersData, setWorkDispatchOrdersData] = useState<any>([])//数据// 初始化数据const getInit = async () => {setWorkDispatchOrdersData(() => MNData)}useEffect(() => {if (!taskareaTableColumnsData?.columns) return// console.log(taskareaTableColumnsData.columns, "====taskareaTableColumnsData.columns===");// console.log(workDispatchOrdersData, "====taskareaTableColumnsData.columns===");if (workDispatchOrdersData?.length) {setTableColumns(() => (taskareaTableColumnsData.columns.reduce((preData: any, curData: any) => {// 判断是否可视if (curData.visible) {return curData.noRender ? [...preData, curData] : [...preData, {...curData,title: (record: any) => {let titleStr = curData?.lableRename || (taskareaTableColumnsData.fields.filter((f: any) => curData.value.includes(f.c))).map((f1: any) => f1.n).join('/')return <div>{titleStr}</div>},width: curData.width ? !isNaN(curData.width) ? curData.width + 'px' : curData.width : '',render: (_: any, record: any, index: any) => {// console.log(_, record, index);// console.log(curData)return (<div className='operation-item-content-taskarea'><div>{(() => {switch (curData.styleType) {case 'def':return curData?.value?.map((cITem: any, i: number) => {return <div key={i}> {record[cITem]}</div>})case 'number':let socketMessageWSDataFind = null// 获取字段 模型的属性 let filterModels = fixedFields.filter((f: any) => curData?.value.includes(f.c))// 判断是不是 自定义的模型 需要特殊处理let customDefinitionFind: any = filterModels.find((f: any) => f.sourceDataType == "customDefinition")return <div style={{ justifyContent: 'start' }}>{/* <div className='operation-badge-taskarea'>{`${item['dmvl'] || 0}/${item['jiHuaShengChanShuLiang']}`}</div> */}{/*  没有推送的时候 查询模型   实际生产数量/计划生产数量 */}<div className='operation-badge-taskarea'>{curData?.expression ? eval(curData.expression) : curData?.value?.reduce((preValData: any, curValData: any) => {// return preValData + (record[curValData] ? (record[curValData]) : '')return [...preValData, record[curValData] || 0]}, []).join('/')}{/* 审核中 样式样式处理  */}{customDefinitionFind && <div className={customDefinitionFind?.className}>{eval(customDefinitionFind?.expression) || ''}</div>}</div></div>default:return curData?.value?.map((cITem: any, i: number) => {return <div key={i}> {record[cITem]}</div>})}})()}</div></div>)},onCell: (record: any, index: number) => {const cIndex = taskareaTableColumnsData.columns.findIndex(cItem => cItem.id === curData.id)if (curData.styleType === 'def' && cIndex + 1 <= taskareaTableColumnsData.severalRows) {try {if (index) { // 不是第一条const preD = workDispatchOrdersData[index - 1], nextD = workDispatchOrdersData[index];if (!preD || !nextD) return {}let preV = '', nextV = '';curData.value.map((item: string) => {preV += preD[item]nextV += nextD[item]})if (preV === nextV) { // 上一条和当前条相等,不渲染return { rowSpan: 0 }}}if (index !== workDispatchOrdersData.length - 1) { // 不是最后一条let unlikeIndex = workDispatchOrdersData.length - index; // 默认全部相等for (let i = index; i < workDispatchOrdersData.length; i++) {const nextD = workDispatchOrdersData[i + 1], currentD = workDispatchOrdersData[i];if (!nextD) break;let currentV = '', nextV = '';curData.value.map((item: string) => {currentV += currentD[item]nextV += nextD[item]})if (i !== workDispatchOrdersData.length - 1 && nextV !== currentV) { // 当前条和下一条不相等,就是需要合并的数unlikeIndex = i - index + 1break;}}return { rowSpan: unlikeIndex }}} catch (err) { console.log(err); }}return {}}}]} else {return preData}}, [])))}}, [workDispatchOrdersData, taskareaTableColumnsData.columns])useEffect(() => {getInit()}, [])return (<div className="App">{taskareaTableColumnsData.isShow && <TaskareaTableColumns data={taskareaTableColumnsData} fillData={taskareaTableColumnsFillData} />}<div><Button onClick={() => {setTaskareaTableColumnsData((data) => ({ ...data, isShow: true }))}}> 设置表头</Button></div>{tableColumns && <Tableborderedcolumns={tableColumns as any}className='taskarea-table-css'dataSource={workDispatchOrdersData}pagination={false}rowKey='id'/>}</div>)
}export default App

TaskareaTableColumns 封装

import React, { useState, useEffect, Fragment, useRef, useCallback } from 'react';
import './index.css';
import { Button, Checkbox, Input, InputNumber, Modal, Select, Space, Table } from 'antd';import update from 'immutability-helper';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';import { cloneDeep } from 'lodash';interface DraggableBodyRowProps extends React.HTMLAttributes<HTMLTableRowElement> {index: number;moveRow: (dragIndex: number, hoverIndex: number) => void;
}const DraggableBodyRowType = 'DraggableBodyRow';const DraggableBodyRow = ({index,moveRow,className,style,...restProps
}: DraggableBodyRowProps) => {const ref = useRef<HTMLTableRowElement>(null);const [{ isOver, dropClassName }, drop] = useDrop({accept: DraggableBodyRowType,collect: monitor => {const { index: dragIndex } = monitor.getItem() || {};if (dragIndex === index) {return {};}return {isOver: monitor.isOver(),dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',};},drop: (item: { index: number }) => {moveRow(item.index, index);},});const [, drag] = useDrag({type: DraggableBodyRowType,item: { index },collect: monitor => ({isDragging: monitor.isDragging(),}),});drop(drag(ref));return (<trref={ref}className={`${className}${isOver ? dropClassName : ''}`}style={{ cursor: 'move', ...style }}{...restProps}/>);
};const index: any = (props: any) => {const { fillData, type, model, data } = props;const [state, setState] = useState<any>({modalWidth: '60%',modalHeight: '55vh',});const [dataSource, setDataSource] = useState<any[]>([]);const [severalRows, setSeveralRows] = useState<any>()useEffect(() => {console.log(data.severalRows);setSeveralRows(data.severalRows)}, [data.severalRows])// 新增一条const addTableRow = () => {setDataSource((dataSource: any) => {let _dataSource = cloneDeep(dataSource)_dataSource.push({id: Date.now(),serial: _dataSource.length + 1,lable: null,visible: true,align: 'center',//表头居中})return _dataSource})}// 最终的 columnsconst [tableColumns, setTableColumns] = useState<any>([{title: '序号',key: 'index',dataIndex: 'index',width: '60px',render: (_: any, __: any, index: number) => index + 1, // 使用 index + 1 作为序号值},{title: '字段名称',dataIndex: 'value',key: 'value',noRender: true,styleType: 'multipleSelect',},{title: '显示名称',dataIndex: 'lableRename',key: 'lableRename',noRender: true,styleType: 'input',},{title: '可视',dataIndex: 'visible',key: 'visible',styleType: 'checkbox',noRender: true,},{title: '宽度',dataIndex: 'width',key: 'width',styleType: 'input',noRender: true,},// {//     title: '排序',//     dataIndex: 'defaultSortOrder',//     key: 'defaultSortOrder',//     styleType: 'select',//     noRender: true,// },{title: '操作',key: 'option',width: 100,render: (_: any, record: any) => (<Space><Button type="primary" onClick={() => {// 删除setDataSource((dataSource: any) => {let _dataSource = cloneDeep(dataSource)let recindex = _dataSource.findIndex((f: any) => f.id == record.id)_dataSource.splice(recindex, 1)return _dataSource})}} danger>删除</Button></Space>),},])const moveRow = useCallback((dragIndex: number, hoverIndex: number) => {const dragRow = dataSource[dragIndex];setDataSource(update(dataSource, {$splice: [[dragIndex, 1],[hoverIndex, 0, dragRow],],}),);},[dataSource],);const onOK = async (type: any) => {if (type) {// console.log('%c [ 工作台设置提交 tableColumns] 日志', 'font-size:13px; background:#26A08F; color:#fff;', tableColumns);// console.log('%c [ 工作台设置提交 dataSource] 日志', 'font-size:13px; background:#26A08F; color:#fff;', dataSource);if (fillData) fillData(1, { tableData: cloneDeep(dataSource), severalRows })} else {if (fillData) fillData(0)}}const h = () => {if (!data) returnswitch (data.type) {case "taskarea":return (<><div>前<InputNumber style={{ margin: '0 5px 10px' }} min={1} value={severalRows} onChange={(val) => setSeveralRows(parseInt(val))} />列数值相同的时候,进行单元格合并</div>{/*  这里必须加个key 不然会报错, 社区给的解决方案就是这样的 */}<DndProvider key={Math.random()} backend={HTML5Backend}><Tablecolumns={tableColumns}dataSource={dataSource}pagination={false}components={{body: {row: DraggableBodyRow,},}}onRow={(_, index) => {const attr = {index,moveRow,};return attr as React.HTMLAttributes<any>;}}/></DndProvider></>)default:return <></>}}const getInit = async () => {// console.log(data, "===getInit===");// 过滤掉 操作let newList = data.columns.filter((f: any) => f.id != 'aaa111bbb222ccc333')setDataSource(() => newList)// 配置 table columnssetTableColumns(() => (tableColumns.reduce((preData: any, curData: any) => {return !curData.noRender ? [...preData, curData] : [...preData, {...curData,render: (_: any, record: any, index: any) => {// console.log(_, record, index);// console.log(curData)return <Fragment>{(() => {switch (curData.styleType) {case 'input':return <Input value={record[curData.dataIndex]} onChange={(e) => {setDataSource((dataSource: any) => {let _dataSource = cloneDeep(dataSource)let recordfind = _dataSource.find((f: any) => f.id === record.id)recordfind[curData.dataIndex] = e.target.valuereturn _dataSource})}} placeholder={'请输入'}></Input>case 'checkbox':return <Checkbox onChange={(e) => {setDataSource((dataSource: any) => {let _dataSource = cloneDeep(dataSource)let recordfind = _dataSource.find((f: any) => f.id === record.id)recordfind[curData.dataIndex] = e.target.checkedreturn _dataSource})}} checked={record[curData.dataIndex]}></Checkbox>case 'multipleSelect':return <Selectmode="multiple"allowClearstyle={{ width: '100%' }}defaultValue={record[curData.dataIndex] || []}onChange={(value: any) => {// console.log('%c [multipleSelect value ] 日志', 'font-size:13px; background:#26A08F; color:#fff;', value);// 修改setDataSource((dataSource: any) => {let _dataSource = cloneDeep(dataSource)let recordfind = _dataSource.find((f: any) => f.id === record.id)recordfind[curData.dataIndex] = value// 判断是不是数值类型 赋值样式  目前let numberStyle = ['decimal']let isnumberStyle = data.fields.filter((f: any) => value.includes(f.c)).find((f2: any) => numberStyle.includes(f2.t))if (isnumberStyle) {recordfind.styleType = 'def'} else {recordfind.styleType = 'number'}return _dataSource})}}options={data.fields.map((item: any) => {return {value: item.c,label: item.n,}})}/>case 'select':return <SelectdefaultValue={record[curData.dataIndex] || ''}style={{ width: 120 }}allowClearonChange={(value: any) => {// 修改setDataSource((dataSource: any) => {let _dataSource = cloneDeep(dataSource)let recordfind = _dataSource.find((f: any) => f.id === record.id)recordfind[curData.dataIndex] = valuereturn _dataSource})}}options={[{value: '',label: '无',},{value: 'descend',label: '降序',},{value: 'ascend',label: '升序',},]}/>default:return <div>暂无内容</div>}})()}</Fragment>}}]}, [])))}useEffect(() => {if (!data) returngetInit()}, [])useEffect(() => {// console.log(dataSource, "===dataSource===监听修改");}, [dataSource])return (<><Modalwidth={state.modalWidth}style={{ top: 50 }}destroyOnClose={true}centered={false}title={(() => {return '设置列表'})()}open={data?.isShow}// onOk={onOK}// onCancel={() => setIsShow(false)}footer={(() => {let footer = [<Button key="quxiao3" onClick={() => onOK(0)} size={'large'}>取消</Button>,<Button key="xinzengyitiao" type="primary" onClick={() => addTableRow()} size={'large'}>新增一条</Button>,<Button key="submit" type="primary" onClick={() => onOK(1)} size={'large'}>确定</Button>]return footer})()}maskClosable={false}className="TaskareaTableColumnsCss"closable={false}bodyStyle={{height: state.modalHeight,position: 'relative',display: 'flex',overflow: 'auto',}}><div style={{ width: '100%' }}>{(data?.isShow) && h()}</div></Modal></>);
};
export default index

github:https://github.com/whqgo/ReactAntdTableCustomHeader

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3015476.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

2024年4月17日华为春招实习试题【三题】-题目+题解+在线评测,2024.4.17,华为机试

2024年4月17日华为春招实习试题【三题】-题目题解在线评测 &#x1f52e;题目一描述&#xff1a;扑克牌消消乐输入描述输出描述样例一样例二Limitation解题思路一&#xff1a;模拟&#xff0c;遇到连续3张相同牌号的卡牌&#xff0c;直接删除解题思路二&#xff1a;栈解题思路三…

软考网络工程师 第六章 第二部分 第二节 IP分片与计算

IP定义 IP报文最大65535字节&#xff0c;而以太网MTU为1500字节。 相当于货轮能载重65535&#xff0c;而火车载重1500&#xff0c;那么必须把货轮上的货物分装给多个火车运输 例题精选解析 以太网主机发送一个IP分组&#xff0c;长度3000字节&#xff0c;头长度为标准长度&a…

【北京迅为】《iTOP-3588开发板源码编译手册》-第三章 编译 Linux源码包

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

C语言 函数概述

好 接下来 我们来讲函数 构建C程序的最佳方式 就是模块化程序设计 C语言中 最基本的程序模块被称为 函数 所以 这个知识点的重要性不言而喻 这里 我们讲个故事 诸葛亮六出祁山时 为了逼司马懿出战 派人送给力司马懿一件女人衣服 司马懿只是为使者 诸葛亮的饮食起居 使者感叹…

AI论文速读 |2024[IJCAI]TrajCL: 稳健轨迹表示:通过因果学习隔离环境混杂因素

题目&#xff1a; Towards Robust Trajectory Representations: Isolating Environmental Confounders with Causal Learning 作者&#xff1a;Kang Luo, Yuanshao Zhu, Wei Chen, Kun Wang(王琨), Zhengyang Zhou(周正阳), Sijie Ruan(阮思捷), Yuxuan Liang(梁宇轩) 机构&a…

leetcode-字符串的排列-100

题目要求 思路 1.因为只涉及到字符&#xff0c;因此可以进行排序 2.创建临时字符串&#xff0c;当临时字符串temp的长度等于str的长度&#xff0c;作为判出条件。 3.创建一个标记的数组&#xff0c;每次在temp中插入一个字符&#xff0c;便在对应的数组下标设置为1&#xff0c…

国家电网某地电力公司网络硬件综合监控运维项目

国家电网某地电力公司是国家电网有限公司的子公司&#xff0c;负责当地电网规划、建设、运营和供电服务&#xff0c;下属多家地市供电企业和检修公司、信息通信公司等业务支撑实施机构。 项目现状 随着公司信息化建设加速&#xff0c;其信息内网中存在大量物理服务器、存储设备…

美团KV存储squirrel和Celler学习

文章目录 美团在KV存储squirrel优化和改进在水平方向1、对Gossip协议进行优化 在垂直扩展方面1、forkless RDB数据复制优化2、使用多线程&#xff0c;充分利用机器的多核能力 在高可用方面 美团持久化kv存储celler优化和改进水平扩展优化1、使用bulkload进行数据导入2、线程模型…

linux启动常见问题

一、忘记root密码 日常生活中&#xff0c;我们会接触到很多账号和密码&#xff0c;而这些账号和密码我们不能都很好的记忆&#xff0c;对于linux也是一样的&#xff0c;如果root密码忘记了怎么办&#xff1f;岂不是都无法登陆使用Linux了&#xff1f;现在我就教各位&#xff0c…

一文了解CRM系统帮助中心:从认识到搭建

客户关系管理&#xff08;CRM&#xff09;系统是企业的一个重要部分。而CRM系统帮助中心为用户提供了便捷的支持服务&#xff0c;提升了用户体验&#xff0c;减少了企业运营成本。本文将从认识到搭建&#xff0c;带你全面了解CRM系统帮助中心。 一、认识CRM系统帮助中心 CRM系统…

智慧交通系统:未来出行,从这里开始

随着城市化进程的加快&#xff0c;交通拥堵、事故频发、停车难等问题日益凸显&#xff0c;传统交通管理模式已难以满足现代社会的需求。智慧交通系统作为解决这些问题的关键&#xff0c;通过集成创新技术&#xff0c;实现交通管理的智能化、信息化&#xff0c;提高交通系统的运…

流量分析利器arkime的学习之路(三)---结合Suricata攻击检测

1、基础 Arkime安装部分参考《流量分析利器arkime的学习之路&#xff08;一&#xff09;—安装部署》 在此基础上安装suricata软件并配置。 2、安装suricata yum install suricate 可能依赖的文件包括libyaml&#xff0c;PyYAML&#xff0c;这些可能在之前安装arkime或者其他…

教程分享:如何为跨境电商、外贸、国际展会制作二维码?

不论是做跨境电商、在全球做产品推广&#xff0c;还是国外的餐厅运营、参加国际展会&#xff0c;或者是做创意户外广告、制作个性化的个人名片、有趣的产品包装……只要是在国外使用二维码&#xff0c;你都可以在QR Tiger去制作您需要的二维码&#xff01; 一、认识QR Tiger 二…

RVM(相关向量机)、CNN_RVM(卷积神经网络结合相关向量机)、RVM-Adaboost(相关向量机结合Adaboost)

当我们谈到RVM&#xff08;Relevance Vector Machine&#xff0c;相关向量机&#xff09;、CNN_RVM&#xff08;卷积神经网络结合相关向量机&#xff09;以及RVM-Adaboost&#xff08;相关向量机结合AdaBoost算法&#xff09;时&#xff0c;每种模型都有其独特的原理和结构。以…

[开发|鸿蒙] 鸿蒙OS开发环境搭建(笔记,持续更新)

搭建开发环境流程&#xff1a; https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/installation_process-0000001071425528-V2 鸿蒙DevEco Studio 3.1.1 Release仅支持windows和mac系统 运行环境要求 为保证DevEco Studio正常运行&#xff0c;建议电脑配置…

idea修改maven项目名称及子模块名称

一、修改目录名称 shift F6修改目录&#xff0c;选择“rename module and dictionary”。![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/43efd9c6af6e43ad9656455db94b37a2.png)二、修改子项目pom的 三、修改父项目pom的 四、刷新maven项目

消费金融平台公司如何做大做强自营产品

本文来自于2019年的某次内部分享沟通会&#xff0c;部分敏感内容已做删减。

Facebook之道:探索社交媒体领域的未来

随着科技的不断发展&#xff0c;社交媒体已经成为我们日常生活中不可或缺的一部分。而在这个领域中&#xff0c;Facebook一直是引领者和领头羊。然而&#xff0c;随着时间的推移&#xff0c;社交媒体领域正在发生着翻天覆地的变化&#xff0c;而Facebook又将何去何从&#xff1…

Meta的Ray-Bans将是最好的AI伴侣眼镜

早在2023年&#xff0c;当我第一次尝试雷朋眼镜时&#xff0c;我就带着智能眼镜自拍。但那个时候&#xff0c;很少有人意识到它是一副智能眼镜。 现在2024年雷明这种眼镜兼作蓝牙耳机&#xff0c;与iOS或安卓系统配对&#xff0c;并与一个专门的元视图应用程序同步。眼镜臂底部…

Scanner中next()、nextInt()、nextLine()、hasNext()、hasNextInt()的使用方法及注意事项

目录 1、next()、nextInt()、nextLine()的使用方法及区分 2、循环时如何使用hasNext方法 3、用hasNextInt()作为判断下一个输入是否为数字需要配合next()方法使用 1、next()、nextInt()、nextLine()的使用方法及区分 三者简单定义 next()&#xff1a;此方法遇见第一个有效字符…