bee-table
Version:
Table ui component for react
1,250 lines (1,200 loc) • 93.2 kB
JavaScript
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import TableRow from './TableRow';
import TableHeader from './TableHeader';
import { measureScrollbar, debounce, warningOnce ,getMaxColChildrenLength } from './lib/utils';
import shallowequal from 'shallowequal';
import ColumnManager from './ColumnManager';
import createStore from './createStore';
import Loading from 'bee-loading';
import Icon from 'bee-icon';
import { Event,EventUtil,closest,myBrowser} from "./lib/utils";
import { arrayMoveTo } from "./lib/util";
import i18n from "./lib/i18n";
import { getComponentLocale } from "bee-locale/build/tool";
import ResizeObserver from 'resize-observer-polyfill';
import DragResizerLine from "./DragResizerLine";
import DragRowLine from "./DragRowLine";
const prefix = 'u';
const propTypes = {
data: PropTypes.array,
expandIconAsCell: PropTypes.bool,
defaultExpandAllRows: PropTypes.bool,
expandedRowKeys: PropTypes.array,
defaultExpandedRowKeys: PropTypes.array,
useFixedHeader: PropTypes.bool,
columns: PropTypes.array,
clsPrefix: PropTypes.string,
bodyStyle: PropTypes.object,
style: PropTypes.object,
//特殊的渲染规则的key值
rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
rowClassName: PropTypes.func,
//column的主键,和 column.key 作用相同
columnKey: PropTypes.string,
expandedRowClassName: PropTypes.func,
childrenColumnName: PropTypes.string,
onExpand: PropTypes.func,
onRowHover:PropTypes.func,
onExpandedRowsChange: PropTypes.func,
indentSize: PropTypes.number,
onRowClick: PropTypes.func,
onRowDoubleClick: PropTypes.func,
expandIconColumnIndex: PropTypes.number,
//是否显示表头
showHeader: PropTypes.bool,
title: PropTypes.func,
footer: PropTypes.func,
emptyText: PropTypes.func,
scroll: PropTypes.object,
rowRef: PropTypes.func,
getBodyWrapper: PropTypes.func,
children: PropTypes.node,
draggable: PropTypes.bool,
minColumnWidth: PropTypes.number,
filterable: PropTypes.bool,
filterDelay: PropTypes.number,
onFilterChange: PropTypes.func,
onFilterClear: PropTypes.func,
syncHover: PropTypes.bool,
tabIndex:PropTypes.string,
hoverContent:PropTypes.func,
size: PropTypes.oneOf(['sm', 'md', 'lg']),
rowDraggAble: PropTypes.bool,
hideDragHandle: PropTypes.bool, // 隐藏行拖拽把手
onDropRow: PropTypes.func,
onDragRowStart: PropTypes.func,
onBodyScroll: PropTypes.func,
bodyDisplayInRow: PropTypes.bool, // 表格内容超出列宽度时进行换行 or 以...形式展现
headerDisplayInRow: PropTypes.bool, // 表头内容超出列宽度时进行换行 or 以...形式展现
showRowNum: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]), // 表格是否自动生成序号,格式为{base:number || 0,defaultKey:string || '_index',defaultName:string || '序号'}
onPaste:PropTypes.func,
onBodyMouseLeave: PropTypes.func,
originWidth: PropTypes.number,
scrollTop: PropTypes.number,
lazyLoad: PropTypes.bool,
ignoreScrollYChange: PropTypes.func,
onResize: PropTypes.func,
bordered: PropTypes.bool,
onDragStart: PropTypes.func,
onDragEnter: PropTypes.func,
onDragOver: PropTypes.func,
onDrop: PropTypes.func,
onDragEnd: PropTypes.func,
onMouseDown: PropTypes.func,
onMouseMove: PropTypes.func,
onMouseUp: PropTypes.func,
dragborder: PropTypes.bool,
onDropBorder: PropTypes.func,
onDraggingBorder: PropTypes.func,
dragborderKey: PropTypes.string,
headerHeight: PropTypes.string,
afterDragColWidth: PropTypes.number,
headerScroll: PropTypes.func,
headerEventNoStop: PropTypes.bool,
onCopy: PropTypes.func,
resetScroll: PropTypes.func,
footerScroll: PropTypes.func,
hideHeaderScroll: PropTypes.func,
locale: PropTypes.string,
getCellClassName: PropTypes.string,
useDragHandle: PropTypes.func,
expandedRowRender: PropTypes.any,
expandRowByClick: PropTypes.func,
haveExpandIcon: PropTypes.any,
expandedIcon: PropTypes.any,
collapsedIcon: PropTypes.any,
height: PropTypes.number,
showSum: PropTypes.bool,
heightConsistent: PropTypes.bool,
syncFixedRowHeight: PropTypes.bool,
setRowHeight: PropTypes.func,
setRowParentIndex: PropTypes.func,
handleScrollY: PropTypes.func,
handleScrollX: PropTypes.func,
onKeyTab: PropTypes.func,
onKeyUp: PropTypes.func,
onKeyDown: PropTypes.func,
onTableKeyDown: PropTypes.func,
focusable: PropTypes.bool,
loading: PropTypes.bool,
};
const defaultProps = {
data: [],
useFixedHeader: true,
expandIconAsCell: false,
defaultExpandAllRows: false,
defaultExpandedRowKeys: [],
columnKey: 'key',
rowKey: 'key',
rowClassName: () => '',
expandedRowClassName: () => '',
onExpand() { },
onExpandedRowsChange() { },
onRowClick() { },
// onRowDoubleClick() { },
clsPrefix: prefix+'-table',
bodyStyle: {},
style: {},
childrenColumnName: 'children',
indentSize: 15,
expandIconColumnIndex: 0,
showHeader: true,
scroll: {},
rowRef: () => null,
getBodyWrapper: body => body,
// emptyText: () => <div><Icon type="uf-nodata" className="table-nodata"></Icon><span>{locale["no_data"]}</span></div>,
columns:[],
minColumnWidth: 80,
locale:{},
syncHover: true,
// setRowHeight:()=>{},
setRowParentIndex:()=>{},
tabIndex:'0',
heightConsistent:false,
size: 'md',
rowDraggAble:false,
hideDragHandle:false,
onDropRow: ()=>{},
onDragRowStart: ()=>{},
onBodyScroll: ()=>{},
bodyDisplayInRow: true,
headerDisplayInRow: true,
headerHeight:null,
showRowNum: false,
onPaste:()=>{},
originWidth:null//做什么用??
};
const expandIconCellWidth = Number(43);
const tableUUID = ()=> "_table_uid_"+new Date().getTime()
let browserInfo = {};
class Table extends Component {
constructor(props) {
super(props);
browserInfo = myBrowser();
let expandedRowKeys = [];
let rows = [...props.data];
const showDragHandle = !props.hideDragHandle && props.rowDraggAble;
this.columnManager = new ColumnManager(props.columns, props.children, props.originWidth, showDragHandle, props.showRowNum); // 加入props.showRowNum参数
this.store = createStore({ currentHoverKey: null });
this.firstDid = true;
this.scrollYChanged = false;
if (props.defaultExpandAllRows) {
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
expandedRowKeys.push(this.getRowKey(row, i));
rows = rows.concat(row[props.childrenColumnName] || []);
}
} else {
expandedRowKeys = props.expandedRowKeys || props.defaultExpandedRowKeys;
}
this.state = {
expandedRowKeys,
data: props.data,
currentHoverKey: null,
scrollPosition: 'left',
fixedColumnsHeadRowsHeight: null,
fixedColumnsBodyRowsHeight: [],
fixedColumnsExpandedRowsHeight: {}, //扩展行的高度
}
this.onExpandedRowsChange = this.onExpandedRowsChange.bind(this);
this.onExpanded = this.onExpanded.bind(this);
this.onRowDestroy = this.onRowDestroy.bind(this);
this.getRowKey = this.getRowKey.bind(this);
this.getExpandedRows = this.getExpandedRows.bind(this);
this.getHeader = this.getHeader.bind(this);
this.getHeaderRows = this.getHeaderRows.bind(this);
this.getExpandedRow = this.getExpandedRow.bind(this);
this.getRowsByData = this.getRowsByData.bind(this);
this.getRows = this.getRows.bind(this);
this.getColGroup = this.getColGroup.bind(this);
this.getLeftFixedTable = this.getLeftFixedTable.bind(this);
this.getRightFixedTable = this.getRightFixedTable.bind(this);
this.getTable = this.getTable.bind(this);
this.getTitle = this.getTitle.bind(this);
this.getFooter = this.getFooter.bind(this);
this.getEmptyText = this.getEmptyText.bind(this);
this.syncFixedTableRowHeight = this.syncFixedTableRowHeight.bind(this);
this.resetScrollX = this.resetScrollX.bind(this);
this.findExpandedRow = this.findExpandedRow.bind(this);
this.isRowExpanded = this.isRowExpanded.bind(this);
// this.detectScrollTarget = this.detectScrollTarget.bind(this);
this.handleBodyScroll = this.handleBodyScroll.bind(this);
this.handleRowHover = this.handleRowHover.bind(this);
this.computeTableWidth = this.computeTableWidth.bind(this);
this.onBodyMouseLeave = this.onBodyMouseLeave.bind(this);
this.tableUid = tableUUID();
this.contentTable = null;
this.leftColumnsLength //左侧固定列的长度
this.centerColumnsLength //非固定列的长度// this.columnsChildrenList = [];//复杂表头、所有叶子节点
this.dataChanged = false; // 数据是否改变
//同步行高时使用的缓存
this.fixedColumnsBodyRowsHeightCache = null;
this.fixedColumnsExpandedRowsHeightCache = null;
}
componentWillMount() {
this.centerColumnsLength = this.columnManager.centerColumns().length
this.leftColumnsLength = this.columnManager.leftColumns().length
}
componentDidMount() {
// this.getTableUID();
EventUtil.addHandler(this.contentTable,'keydown',this.onKeyDown);
EventUtil.addHandler(this.contentTable,'focus',this.onFocus);
setTimeout(this.resetScrollX, 300);
//含有纵向滚动条
// if(this.props.scroll.y){
// this.scrollbarWidth = measureScrollbar(`.u-table`);
// }
this.scrollbarWidth = measureScrollbar(`.${this.props.clsPrefix}`);//dom装载后获取浏览器下的滚动条宽度
//后续也放在recevice里面
if (!this.props.originWidth) {
this.computeTableWidth();
}
let {useFixedHeader,scroll={}} = this.props;
if (this.columnManager.isAnyColumnsFixed()) {
this.syncFixedTableRowHeight();//同步固定列的内容行高度
const targetNode = this.contentTable
if (targetNode) {
this.resizeObserver = new ResizeObserver(() => {
this.resize()
});
this.resizeObserver.observe(targetNode)
}
}
if(scroll.y){//固定列头存在则执行head和body的宽度
this.syncFixedTableScrollWidth();//同步固定列的滚动宽度
}
}
componentWillReceiveProps(nextProps) {
let { hideDragHandle, rowDraggAble, showRowNum ,clsPrefix} = this.props;
// 清除同步行高时使用的缓存
this.fixedColumnsBodyRowsHeightCache = null;
this.fixedColumnsExpandedRowsHeightCache = null;
if ('data' in nextProps) {
this.setState({
data: nextProps.data,
});
}
if ('defaultExpandAllRows' in nextProps) {
const { defaultExpandAllRows, data, expandedRowKeys, childrenColumnName = 'children'} = nextProps;
if (defaultExpandAllRows && !expandedRowKeys) {
let _expandedRowKeys = [];
let rows = [...(data || [])];
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
_expandedRowKeys.push(this.getRowKey(row, i));
rows = rows.concat(row[childrenColumnName] || []);
}
this.setState({
expandedRowKeys: _expandedRowKeys
})
} else if (!defaultExpandAllRows && !expandedRowKeys) {
this.expandedRowKeys = []
}
}
if ('expandedRowKeys' in nextProps) {
this.setState({
expandedRowKeys: nextProps.expandedRowKeys,
});
}
if (nextProps.columns && !shallowequal(nextProps.columns,this.props.columns)) {
this.columnManager.reset(nextProps.columns, null, showRowNum, !hideDragHandle && rowDraggAble); // 加入this.props.showRowNum参数
if(nextProps.columns.length !== this.props.columns.length && this.bodyTable){
this.scrollTop = this.bodyTable.scrollTop;
}
} else if (nextProps.children !== this.props.children) {
this.columnManager.reset(null, nextProps.children, showRowNum, !hideDragHandle && rowDraggAble); // 加入this.props.showRowNum参数
}
//适配lazyload
if(nextProps.scrollTop > -1){
// this.bodyTable.scrollTop = nextProps.scrollTop;
this.scrollTop = nextProps.scrollTop;
}
// fix:模态框中使用table,计算的滚动条宽度为0的bug
// fix:表格首次渲染时 display:none,再显示时,未重新计算,导致表行出现错位的bug
// if(this.scrollbarWidth<=0 && this.props.scroll.y){
// this.scrollbarWidth = measureScrollbar(`.${clsPrefix}`);
// }
if (!nextProps.originWidth) {
this.computeTableWidth();
this.firstDid = true;//避免重复update
}
if(nextProps.resetScroll){
this.resetScrollX();
}
// console.log('this.scrollTop**********',this.scrollTop);
}
componentDidUpdate(prevProps, prevState) {
// todo: IE 大数据渲染,行高不固定,且设置了 heightConsistent={true} 时,滚动加载操作会导致 ie11 浏览器崩溃
// https://github.com/tinper-bee/bee-table/commit/bd2092cdbaad236ff89477304e58dea93325bf09
let {useFixedHeader,scroll = {}} = this.props;
if(this.columnManager.isAnyColumnsFixed()) {
debounce(this.syncFixedTableRowHeight(),200);//同步固定列内容行的高度
}
if(scroll.y){//固定列头存在则执行head和body的宽度
debounce(this.syncFixedTableScrollWidth(),200);//同步固定列的滚动宽度
}
//适应模态框中表格、以及父容器宽度变化的情况
if (typeof (this.props.scroll.x) !== 'number' && this.contentTable.getBoundingClientRect().width !== this.contentDomWidth && this.firstDid) {
this.computeTableWidth();
this.firstDid = false;//避免重复update
}
if(this.scrollTop > -1){
this.fixedLeftBodyInner && ( this.fixedLeftBodyInner.scrollTop = this.scrollTop);
this.fixedRightBodyInner && ( this.fixedRightBodyInner.scrollTop = this.scrollTop);
this.bodyTable.scrollTop = this.scrollTop;
this.scrollTop = -1;
}
// 当表格没有数据时,重置滚动条位置,造成grid里面的表头列无法操作
// if (prevProps.data.length === 0 || this.props.data.length === 0 ) {
// this.resetScrollX();
// }
// 当懒加载手动设置的scroll.y发生变化时,滚动条回到顶部
const prevScrollY = prevProps.scroll.y
const currentScrollY = this.props.scroll.y
if (prevScrollY && currentScrollY && (prevScrollY !== currentScrollY) && this.props.lazyLoad && !this.props.ignoreScrollYChange) {
this.bodyTable.scrollTop = 0
} else if (this.props.ignoreScrollYChange && currentScrollY && prevScrollY) {
if (prevScrollY !== currentScrollY) {
this.scrollYChanged = true
const bodyScrollTop = this.bodyTable.scrollTop
if (bodyScrollTop === 0) { // 在顶部的时候,滚动条不用动
this.bodyTable.scrollTop = 0;
} else {
const distance = bodyScrollTop + currentScrollY - prevScrollY;
if (distance < 0) {
this.bodyTable.scrollTop = 0;
} else {
const { scrollHeight, scrollTop } = this.bodyTable
const bottomDistance = Math.abs(scrollHeight - scrollTop - prevScrollY) // 在最底部的时候也不用滚动滚动条
if (bottomDistance < 5) { // 有些dom计算不是十分精确,设置一个值来缓冲一下
this.bodyTable.scrollTop = scrollTop + prevScrollY - currentScrollY
} else {
this.bodyTable.scrollTop = distance;
}
}
}
} else if (this.scrollYChanged) {
this.bodyTable.scrollTop += 1
this.scrollYChanged = false
}
}
// 是否传入 scroll中的y属性,如果传入判断是否是整数,如果是则进行比较 。bodyTable 的clientHeight进行判断
// this.isShowScrollY();
// gx为了解决底部滚动条显示的问题
// if (this.bodyTable) {
// const currentOverflowX = window.getComputedStyle(this.bodyTable).overflowX;
// if (this.props.scroll.x && currentOverflowX !== 'scroll') {
// // 此处应该对比一下实际的
// if (this.computeWidth > this.contentDomWidth) {
// this.bodyTable.style.overflowX = 'scroll';
// }
// }
// }
// let scrollContainerWidth = window.getComputedStyle(this.bodyTableOuter.querySelector('.scroll-container')).width; // scroll-container层元素的宽度
// let scrollContainerTableWidth = this.bodyTableOuter.querySelector('.table-bordered').style.width; // scroll-container内层table元素的宽度
// // 有左右固定列时,scroll-container因为有竖直滚动条,使得scroll-container实际宽度(不包括滚动条的宽度)小于内部table宽度出现水平方向滚动条,导致滚动到底部不对齐
// if ((parseFloat(scrollContainerWidth) >= parseFloat(scrollContainerTableWidth)) && (this.columnManager.leftLeafColumns().length > 0 || this.columnManager.rightLeafColumns().length > 0)) {
// this.bodyTable.style.overflowX = 'hidden';
// } else {
// this.bodyTable.style.overflowX = 'auto';
// }
// if (this.bodyTableOuter) { // 隐藏几个不需要真正滚动的父元素的滚动条
// this.bodyTableOuter.style.overflowY = 'hidden'
// }
// if (this.fixedColumnsBodyLeftOuter) {
// this.fixedColumnsBodyLeftOuter.style.overflowY = 'hidden'
// }
// if (this.fixedColumnsBodyRightOuter) {
// this.fixedColumnsBodyRightOuter.style.overflowY = 'hidden'
// }
}
componentWillUnmount() {
// 移除绑定事件,避免内存泄漏
this.contentTable = null;
EventUtil.removeHandler(this.contentTable,'keydown',this.onKeyDown);
EventUtil.removeHandler(this.contentTable,'focus',this.onFocus);
if (this.resizeObserver) {
this.resizeObserver.disconnect()
}
}
resize = ()=>{
let debounceFunc = ()=>{
this.syncFixedTableRowHeight();
this.computeTableWidth();
typeof this.props.onResize =='function' && this.props.onResize();
};
debounce(debounceFunc(), 150);
let renderFlag = this.state.renderFlag;
this.setState({
renderFlag: !renderFlag
});
}
/*
getTableUID =()=>{
let uid = "_table_uid_"+new Date().getTime();
this.tableUid = uid;
let div = document.createElement("div");
div.className = "u-table-drag-hidden-cont";
div.id = uid;
this.contentTable.appendChild(div);
}
*/
//计算表格宽度 --- 这块有必要?待确认 待废除 zzj
computeTableWidth() {
let {expandIconAsCell} = this.props;
//如果用户传了scroll.x按用户传的为主
let setWidthParam = this.props.scroll.x
if (typeof (setWidthParam) == 'number') {
let numSetWidthParam = parseInt(setWidthParam);
this.contentWidth = numSetWidthParam;
} else {
// this.preContentDomWidth = this.contentDomWidth;
//计算总表格宽度、根据表格宽度和各列的宽度和比较,重置最后一列
this.contentDomWidth = this.contentTable.getBoundingClientRect().width//表格容器宽度
this.contentWidth = this.contentDomWidth;//默认与容器宽度一样
}
const computeObj = this.columnManager.getColumnWidth(this.contentWidth);
const expandColWidth = expandIconAsCell ? expandIconCellWidth : 0;
let lastShowIndex = computeObj.lastShowIndex;
this.computeWidth = computeObj.computeWidth + expandColWidth;
this.domWidthDiff = this.contentDomWidth - this.computeWidth;
if (typeof (setWidthParam) == 'string' && setWidthParam.indexOf('%')) {
this.contentWidth = this.contentWidth * parseInt(setWidthParam) / 100;
this.domWidthDiff = this.contentDomWidth - this.contentWidth;
}
if (this.computeWidth < this.contentWidth) {
let contentWidthDiff = this.scrollbarWidth?this.contentWidth - this.computeWidth-this.scrollbarWidth:this.contentWidth - this.computeWidth;
//bordered的表格需要减去边框的差值1
if(this.props.bordered){
contentWidthDiff = contentWidthDiff-1;
}
this.setState({ contentWidthDiff, lastShowIndex });
} else {
this.contentWidth = this.computeWidth;
this.setState({ contentWidthDiff: 0, lastShowIndex });//重新渲染,为了显示滚动条
}
}
/*
//根据内容动态的判断是否显示纵向滚动条
isShowScrollY(){
const props = this.props;
const y = props.scroll && props.scroll.y;
if(y){
const bodyH = this.bodyTable.clientHeight;
const bodyContentH = this.bodyTable.querySelector('table').clientHeight;
const rightBodyTable = this.fixedRightBodyInner;
// const leftBodyTable = this.fixedLeftBodyInner;
const overflowy = bodyContentH <= bodyH ? 'auto':'scroll';
this.bodyTable.style.overflowY = overflowy;
this.headTable.style.overflowY = overflowy;
rightBodyTable && (rightBodyTable.style.overflowY = overflowy);
}
}
*/
//同步固定列情况下部分区域滚动条出现引起的错位问题
syncFixedTableScrollWidth = ()=>{
const {clsPrefix} = this.props;
let tableDom = this.contentTable;
let tableContentDom = tableDom.querySelector(`.${clsPrefix}-content`);
let tableFixedRight = tableDom.querySelector(`.${clsPrefix}-fixed-right`);
let centerBodyDom = tableDom.querySelector(`.${clsPrefix}-scroll .${clsPrefix}-body`);
let centerHeadDom = tableDom.querySelector(`.${clsPrefix}-scroll .${clsPrefix}-header`);//固定列头的情况下
if(!centerHeadDom)centerHeadDom = tableDom.querySelector(`.${clsPrefix}-scroll .${clsPrefix}-thead`);//未固定列头的情况下
//注意精准匹配,以确保行展开表格嵌套表格时正确匹配
let centerHeadTableDom = tableDom.querySelector(`.${clsPrefix}-scroll .${clsPrefix}-header > table[data-for-table='${this.tableUid}']`);
let centerBodyTableDom = tableDom.querySelector(`.${clsPrefix}-scroll .${clsPrefix}-body > table[data-for-table='${this.tableUid}']`);
let bodyInnerDoms = tableDom.querySelectorAll(`.${clsPrefix}-body-outer .${clsPrefix}-body-inner`);
// if(!this.scrollbarWidth)this.scrollbarWidth=measureScrollbar();
let scrollbarWidth = this.scrollbarWidth;
let hasCenterScrollY = centerBodyTableDom.getBoundingClientRect().height>centerBodyDom.getBoundingClientRect().height?true:false;//中间区域是否存在垂直滚动条
// let hasCenterScrollX = centerBodyTableDom.getBoundingClientRect().width>centerBodyDom.getBoundingClientRect().width?true:false;//中间区域存在水平滚动条
let hasCenterScrollX = centerBodyDom.scrollWidth>(centerBodyDom.clientWidth+1)?true:false;//中间区域存在水平滚动条
//console.log("AAA---->syncFixedTableScrollWidth-->hasCenterScrollX"+hasCenterScrollX+"-->hasCenterScrollY"+hasCenterScrollY+"--->scrollbarWidth"+scrollbarWidth)
//解决存在右侧固定列,中间区域垂直滚动条需要隐藏显示的问题
if(hasCenterScrollY&&this.columnManager.isAnyColumnsRightFixed()){
//非Chrome内核浏览器中间区域会出现多余垂直滚动条需要隐藏
if(browserInfo.browserType=='Chrome'){
centerBodyDom.style.marginRight = 0;
}else{
centerBodyDom.style.marginRight = (-scrollbarWidth)+"px";
}
if(browserInfo.osType=='Mac'&&browserInfo.browserType=='FF'){//解决mac的ff下右侧固定列存在,中间区域右侧被遮挡的问题
centerBodyTableDom.style.paddingRight = scrollbarWidth+"px";
}
}else{
centerBodyDom.style.marginRight = 0;
}
if(centerHeadDom)centerHeadDom.style.marginRight = centerBodyDom.style.marginRight;
//解决中间区域存在水平滚动条,左右固定区域无法跟其对齐的问题
if(bodyInnerDoms&&bodyInnerDoms.length){
[].forEach.call(bodyInnerDoms,(bodyInnerDom)=>{
if(hasCenterScrollX) {
if(browserInfo.browserType=='Chrome'){//mac下验证
if(hasCenterScrollX){
bodyInnerDom.style.overflowX = 'scroll';
}else{
bodyInnerDom.style.overflowX = 'hidden';
}
}else{
if(browserInfo.osType=='Win'&&browserInfo.browserType=='FF') {
bodyInnerDom.style.overflowX = 'hidden';//win的firefox下,中间x滚动出现时,左右固定列x滚动条隐藏通过paddingBottom填充占位
}else{
bodyInnerDom.style.overflowX = 'scroll';//确保中间x滚动出现时,左右固定列x滚动条正确显示占位
}
}
// bodyInnerDom.style.paddingBottom = browserInfo.browserType=='Chrome'?0:`${scrollbarWidth}px`;//chrome下左右固定列底部不需要填充占位,firefox需要占位,
if(browserInfo.osType=='Win'&&browserInfo.browserType=='FF'){
bodyInnerDom.style.paddingBottom = `${scrollbarWidth}px`;//win的firefox不需显示x滚动条但需要填充占位
}else{
bodyInnerDom.style.paddingBottom = 0;//firefox升级89.0.2后不需要占位了
}
}else {
bodyInnerDom.style.overflowX = 'hidden';//确保中间x滚动不出现时,左右固定列x滚动条不显示
bodyInnerDom.style.paddingBottom = 0;
}
});
}
//解决中间存在水平滚动条头部区域无法对齐的问题
if(centerHeadTableDom){
let paddingWidth = 0;
if(hasCenterScrollY && hasCenterScrollX || hasCenterScrollY && !tableFixedRight)paddingWidth=paddingWidth+scrollbarWidth;
centerHeadTableDom.style.paddingRight=`${paddingWidth}px`;
}
//为表格追加是否存在滚动条的样式标识
if(tableContentDom){
if(hasCenterScrollX){
if(!tableContentDom.classList.contains('has-scroll-x'))tableContentDom.classList.add('has-scroll-x');
}else{
tableContentDom.classList.remove('has-scroll-x');
}
if(hasCenterScrollY){
if(!tableContentDom.classList.contains('has-scroll-y'))tableContentDom.classList.add('has-scroll-y');
}else{
tableContentDom.classList.remove('has-scroll-y');
}
//中间区域有垂直滚动条
if(hasCenterScrollY){
if(this.headTable){//中间区域有垂直滚动条,则头部也需要显示头部滚动条
this.headTable.style.overflowY='scroll';
if(this.columnManager.isAnyColumnsRightFixed()){
//右侧固定列存在时需要头部Y滚动条占位
}else{
if(browserInfo.osType=='Win'&&browserInfo.browserType=='FF'){ // 解决win下FF的头部右上角多于滚动条显示问题
this.headTable.style.overflowY='hidden';
this.headTable.style.paddingRight = `${scrollbarWidth}px`;
}
}
}
}else{
if(this.headTable)this.headTable.style.overflowY='hidden';//中间区域无垂直滚动条,则头部也不需要显示头部滚动条
}
}
}
onExpandedRowsChange(expandedRowKeys) {
if (!this.props.expandedRowKeys) {
this.setState({ expandedRowKeys });
}
this.props.onExpandedRowsChange(expandedRowKeys);
}
onExpanded(expanded, record, index, e) {
if (e) {
e.preventDefault();
e.stopPropagation();
}
const info = this.findExpandedRow(record);
if (typeof info !== 'undefined' && !expanded) {
this.onRowDestroy(record, index, true);
} else if (!info && expanded) {
const expandedRows = this.getExpandedRows().concat();
expandedRows.push(this.getRowKey(record, index));
this.onExpandedRowsChange(expandedRows);
}
this.props.onExpand(expanded, record,index);
}
onRowDestroy(record, rowIndex, isExpandOperation) {
const expandedRows = this.getExpandedRows().concat();
const rowKey = this.getRowKey(record, rowIndex);
let index = -1;
expandedRows.forEach((r, i) => {
if (r === rowKey) {
index = i;
}
});
if (index !== -1) {
expandedRows.splice(index, 1);
}
//
if(this.currentHoverKey == rowKey && this.hoverDom){
this.hoverDom.style.display = 'none';
}
// todo:如果是TableRow组件卸载触发的该方法,需要加判断,解决懒加载时,持续触发onExpandedRowsChange的问题
if(isExpandOperation){
this.onExpandedRowsChange(expandedRows);
} else {
const info = this.findExpandedRow(record);
if(typeof info === 'undefined'){
this.onExpandedRowsChange(expandedRows);
}
}
}
getRowKey(record, index) {
const rowKey = this.props.rowKey;
const key = (typeof rowKey === 'function') ?
rowKey(record, index) : record[rowKey];
warningOnce(
key !== undefined,
'Each record in table should have a unique `key` prop,' +
'or set `rowKey` to an unique primary key.'
);
return key;
}
getExpandedRows() {
return this.props.expandedRowKeys || this.state.expandedRowKeys;
}
getHeader(columns, fixed, leftFixedWidth, rightFixedWidth) {
const { filterDelay, onFilterChange, onFilterClear, filterable, showHeader, expandIconAsCell, clsPrefix, onDragStart, onDragEnter, onDragOver, onDrop,onDragEnd, draggable,
onMouseDown, onMouseMove, onMouseUp, dragborder, dragborderKey, minColumnWidth, headerHeight,afterDragColWidth,headerScroll ,bordered,onDropBorder,onDraggingBorder, bodyDisplayInRow, headerEventNoStop, onCopy} = this.props;
let columnsChildrenList = []; //复杂表头拖拽,重新render表头前,将其置空
const rows = this.getHeaderRows({columns,columnsChildrenList});
if (expandIconAsCell) {
let hasLeftFixed = this.columnManager.isAnyColumnsLeftFixed();
if((hasLeftFixed && fixed =='left') //存在左侧固定列则展开图标独立到左侧区域
||(!hasLeftFixed && !fixed) //不存在左侧固定列则展开图标独立到中间区域
){
rows[0].unshift({
key: `${prefix}-table-expandIconAsCell`,
className: `${clsPrefix}-expand-icon-th`,
title: '',
rowSpan: rows.length,
width: expandIconCellWidth
});
columnsChildrenList.unshift({
className: `${prefix}-table-expand-icon-column`,
key: "expand-icon"
})
}
}
if(fixed){
columnsChildrenList = columnsChildrenList.filter((col)=>col.fixed==fixed);//只获取对应的固定列
}else{
columnsChildrenList = columnsChildrenList.filter((col)=>!col.fixed);//只获取非固定的列
}
// const trStyle = headerHeight&&!fixed ? { height: headerHeight } : (fixed ? this.getHeaderRowStyle(columns, rows) : null);
const trStyle = this.getHeaderRowStyle(columns, rows);//确保固定列和非固定列表头行高一致
let drop = draggable ? { onDragStart, onDragOver, onDrop,onDragEnd, onDragEnter, draggable } : {};
let dragBorder = dragborder ? { onMouseDown:this.onDragBorderMouseDown, onMouseMove, onMouseUp, dragborder, dragborderKey,onDropBorder,onDraggingBorder } : {};
return showHeader ? (
<TableHeader
{...drop}
{...dragBorder}
columnManager={this.columnManager}
columnsChildrenList={columnsChildrenList}
locale={this.props.locale}
minColumnWidth={minColumnWidth}
contentWidthDiff={!fixed?this.state.contentWidthDiff:0}
// contentWidth={this.contentWidth}
clsPrefix={clsPrefix}
rows={rows}
contentTable={this.contentTable}
rowStyle={trStyle}
fixed={fixed}
filterable={filterable}
onFilterChange={onFilterChange}
onFilterClear={onFilterClear}
filterDelay={filterDelay}
afterDragColWidth = {afterDragColWidth}
contentDomWidth={this.contentDomWidth}
scrollbarWidth = {this.scrollbarWidth}
headerScroll = {headerScroll}
bordered = {bordered}
tableUid = {this.tableUid}
leftFixedWidth = {leftFixedWidth}
rightFixedWidth = {rightFixedWidth}
bodyDisplayInRow = {bodyDisplayInRow}
eventNoStop = {headerEventNoStop}
onCopy = {onCopy}
/>
) : null;
}
getHeaderRows(options) {
let {columns, currentRow = 0, rows,columnsChildrenList} = options;
const { columnKey } = this.props;
// let { contentWidthDiff = 0, lastShowIndex = -1 } = this.state;
let filterCol = [];
rows = rows || [];
rows[currentRow] = rows[currentRow] || [];
// let centerShowColCount = 0;
columns.forEach((column,i) => {
if (!column.key) {
column.key = column[columnKey];
}
if (column.rowSpan && rows.length < column.rowSpan) {
while (rows.length < column.rowSpan) {
rows.push([]);
}
}
let width = column.width;
if (typeof (width) == 'string' && width.indexOf('%') > -1 && this.contentWidth) {
width = Math.ceil(this.contentWidth * parseInt(width) / 100);
} else if (width) {
width = parseInt(width);
}
// if (!column.fixed && column.ifshow) {
// centerShowColCount++;//非固定列显示的个数
// if(lastShowIndex+1 == centerShowColCount && width){//对最后一列进行补全宽度
// width = width + contentWidthDiff;
// }
// }
const cell = {
key: column.key,
className: column.className || '',
children: column.title,
drgHover: column.drgHover,
fixed: column.fixed,
width: width,
dataIndex:column.dataIndex,
textAlign:column.textAlign,
titleAlign: column.titleAlign, // 标题水平对齐方式
required: column.required, // 标题是否展示必填标志
dragborder: column.dragborder || '', // 禁止某列拖动
};
if (column.onHeadCellClick) {
cell.onClick = column.onHeadCellClick;
}
if (column.children) {
this.getHeaderRows({columns:column.children,currentRow: currentRow + 1, rows,columnsChildrenList});
} else {
columnsChildrenList&&columnsChildrenList.push(column); //复杂表头拖拽,所有叶子节点
}
if ('colSpan' in column) {
cell.colSpan = column.colSpan;
}
if ('rowSpan' in column) {
cell.rowSpan = column.rowSpan;
}
if (cell.colSpan !== 0) {
rows[currentRow].push(cell);
}
//判断是否启用过滤
if (this.props.filterable) {
//组装Filter需要的Col
filterCol.push({
key: column.key,
children: "过滤渲染",
width: column.width,
fixed: column.fixed, // fixed
filtertype: column.filterType,//下拉的类型 包括['text','dropdown','date','daterange','number']
dataIndex: column.dataIndex,//field
datasource: this.props.data,//需要单独拿到数据处理
format: column.format,//设置日期的格式
filterdropdown: column.filterDropdown,//是否显示 show hide
filterdropdownauto: column.filterDropdownAuto,//是否自定义数据
filterdropdowndata: column.filterDropdownData,//自定义数据格式
filterdropdownfocus: column.filterDropdownFocus,//焦点触发函数回调
filterdropdowntype: column.filterDropdownType,//下拉的类型分为 String,Number 默认是String
filterdropdownincludekeys: column.filterDropdownIncludeKeys,//下拉条件按照指定的keys去显示
filterinputnumberoptions: column.filterInputNumberOptions//设置数值框内的详细属性
});
}
});
if (this.props.filterable) {
rows.push(filterCol);
}
return rows.filter(row => row.length > 0);
}
getExpandedRow(key, content, visible, className, fixed, record, index) {
const { clsPrefix, expandIconAsCell,onPaste, getCellClassName } = this.props;
let colCount;
if (fixed === 'left') {
colCount = this.columnManager.leftLeafColumns().length;
} else if (fixed === 'right') {
colCount = this.columnManager.rightLeafColumns().length;
} else {
colCount = this.columnManager.centerColumns().length; //计算非固定列的个数,fix: 嵌套表格场景,右侧列断开的问题
}
let hasLeftFixed = this.columnManager.isAnyColumnsLeftFixed();
let expandedRowHeight = this.state.fixedColumnsExpandedRowsHeight[key] || 'auto';
function contentContainer() {
if (content && content.props && content.props.style) {
return (
<div style={{ height: content.props.style.height }}></div>
)
} else {
return ' '
}
}
const columns = [{
key: 'extra-row',
render: () => ({
props: {
colSpan: colCount,
},
children: !fixed ? content : contentContainer(),
}),
}];
if (expandIconAsCell) {
if((hasLeftFixed && fixed=='left')
||(!hasLeftFixed&&!fixed)){
columns.unshift({
key: 'expand-icon-placeholder',
className:'expand-icon-placeholder',
render: () => null,
});
}
}
return (
<TableRow
record={record}
index={index}
tableUid = {this.tableUid}
onPaste={onPaste}
columns={columns}
visible={visible}
className={className}
key={`${key}-extra-row`}
hoverKey={key}
clsPrefix={`${clsPrefix}-expanded-row`}
indent={1}
expandIconAsCell={false}
expandable={false}
store={this.store}
dragborderKey={this.props.dragborderKey}
rowDraggAble={this.props.rowDraggAble}
useDragHandle={this.props.useDragHandle}
height={expandedRowHeight}
getCellClassName = {getCellClassName}
setRowHeight={this.props.setRowHeight}
isExpandedRow={true}
/>
);
}
//列宽度拖拽-鼠标按下的事件
onDragBorderMouseDown = (event)=>{
const {minColumnWidth} = this.props;
let dragGapDom = Event.getTarget(event);
let currentDom = dragGapDom.parentElement;
let columnKey = currentDom.getAttribute('data-col-key');
let columnFixed = currentDom.getAttribute('data-th-fixed');
let columnWidth = currentDom.getAttribute('data-th-width');
let columnIndex = currentDom.getAttribute('data-col-index');
let currentInfo = {columnKey,columnFixed,columnWidth,columnIndex};
let tableRect = this.contentTable.getBoundingClientRect();//表格
let dragGapRect = dragGapDom.getBoundingClientRect();//当前的伸缩label
//向上查找th元素
function getParentThElement(element){
let _tagName = element.tagName.toLowerCase();
if(element.getAttribute('data-filter-type') === 'filterContext')return null;
if(_tagName === 'i')return null;
if(_tagName != 'th'){
return getParentThElement(element.parentElement);
}else{
return element;
}
}
let thDom = getParentThElement(currentDom);
let resizerDefaultWidth = thDom.getBoundingClientRect().width;
let resizerLineHeight = tableRect.height;
let resizerLineLeft = dragGapRect.right-tableRect.left-parseInt(dragGapRect.width/2)-1;
let column = this.columnManager.leafColumns().find((col)=>col.key?col.key==columnKey:col.dataIndex==columnKey);
this.setState({
resizerVisible: true,
resizerLineHeight,
resizerLineLeft,
resizerDefaultWidth,
resizerMinWidth:column.minWidth||minColumnWidth,
dataSource: currentInfo,
});
this.resizerLine.start(event);
}
//列宽度拖拽-鼠标松开的事件
onDragBorderMouseUp=(event,moveX, info)=> {
const {minColumnWidth,onDropBorder} = this.props;
let target = Event.getTarget(event);
let {columnKey,columnFixed,columnWidth,columnIndex} = info;
let column = this.columnManager.leafColumns().find((col)=>col.key?col.key==columnKey:col.dataIndex==columnKey);
let oldWidth = ColumnManager.DefaultColumnWidth;
//原宽度
if (typeof (column.width) == 'string' && column.width.indexOf('%') > -1 ) {//百分比情况
oldWidth = parseInt(columnWidth);
}else if(column.width){//非百分比情况
oldWidth = parseInt(column.width);
}
let newWidth = oldWidth+moveX;//拖动后的宽度
newWidth = newWidth<minColumnWidth?minColumnWidth:newWidth;//限制最小宽度
this.columnManager.clearCache();//注意:先清除缓存
let changeColumn = this.columnManager.findColumn(column.key||column.dataIndex);
if(!changeColumn){
console.error('拖拽列宽度未找到列定义:'+(column.key||column.dataIndex),column);
return;
}
changeColumn.width = newWidth;
this.computeTableWidth();//注意:重新计算需要补充的列宽度
// let newWidthDiff = newWidth-oldWidth;//计算新旧宽度的实际变化距离, 负数为缩小,正数为放大
// console.log("AAA---onDragBorderMouseUp-->最终距离"+moveX+'---表宽度--'+this.contentWidth+'---实际变化距离---'+newWidthDiff,this.columnManager.columns)
this.setState({
resizerVisible: false,
fixedColumnsHeadRowsHeight: null,
fixedColumnsBodyRowsHeight: [],
fixedColumnsExpandedRowsHeight: {}, // 扩展行的高度
});
typeof onDropBorder=='function' && onDropBorder(event, newWidth,column,this.columnManager.columns);
}
//列宽度拖拽-取消事件
onDragBorderCancel = (event,moveX,info)=>{
this.setState({ resizerVisible: false});
}
//列宽度拖拽-鼠标移动的事件
onDragBorderMouseMove = (event,moveX,info)=>{
const {minColumnWidth,onDraggingBorder} = this.props;
let {columnKey,columnFixed,columnWidth,columnIndex} = info;
let column = this.columnManager.leafColumns().find((col)=>col.key?col.key==columnKey:col.dataIndex==columnKey);
let oldWidth = ColumnManager.DefaultColumnWidth;//原宽度
//原宽度
if (typeof (column.width) == 'string' && column.width.indexOf('%') > -1 ) {//百分比情况
oldWidth = parseInt(columnWidth);
}else if(column.width){//非百分比情况
oldWidth = parseInt(column.width);
}
let newWidth = oldWidth+moveX;//拖动后的宽度
newWidth = newWidth<minColumnWidth?minColumnWidth:newWidth;//限制最小宽度
typeof onDraggingBorder=='function' && onDraggingBorder(event, newWidth,column,this.columnManager.columns);
// console.log("AAA---onDragBorderMouseMove-->移动距离"+moveX)
}
/**
* 行拖拽开始时触发
* @param currentKey 当前拖拽目标的key
*/
_onRowDragStart = (options) => {
let {dragStartKey} = options;
let {lazyLoad,onRowDragStart} = this.props;
if(lazyLoad){
onRowDragStart && onRowDragStart(options);//直接传递给bigDataX触发
}else{
let {data} = this.state,currentIndex,record;
data.forEach((da,i)=>{
// tr 的唯一标识通过 data.key 或 rowKey 两种方式传进来
let trKey = da.key ? da.key : this.getRowKey(da, i);
if(trKey == dragStartKey){
currentIndex = i;
record = da;
}
});
this.props.onDragRowStart && this.props.onDragRowStart(record,currentIndex);
}
}
/**
* 行拖拽结束时触发
*/
_onRowDragDrop = (options)=>{
let {lazyLoad,onRowDragDrop} = this.props;
if(lazyLoad){
onRowDragDrop && onRowDragDrop(options);//直接传递给bigDataX触发
}else{
let {dragTargetKey,dragTargetIndex,dropTargetKey,dropTargetIndex} = options;
let {data} = this.state,record;
for(let i=0;i<data.length;i++){
let da = data[i];
// tr 的唯一标识通过 data.key 或 rowKey 两种方式传进来
let trKey = da.key ? da.key : this.getRowKey(da, i);
if(trKey == dragTargetKey){
record = da;break; //匹配到后则退出减少性能开销
}
}
if (dragTargetIndex > -1) {
data = arrayMoveTo(data,dragTargetIndex,dropTargetIndex);
this.props.onDropRow && this.props.onDropRow(data,record,dropTargetIndex);
this.setState({data});
} else {
this.props.onDropRow && this.props.onDropRow(data,record,dropTargetIndex);
}
}
// console.log("AAAA---->行拖拽结束:"+currentKey,targetKey);
}
/**
*
*
* @param {*} data
* @param {*} visible
* @param {*} indent 层级
* @param {*} columns
* @param {*} fixed
* @param {number} [rootIndex=-1] 祖级节点
* @returns
* @memberof Table
*/
getRowsByData(data, visible, indent, columns, fixed,rootIndex=-1) {
const props = this.props;
const childrenColumnName = props.childrenColumnName;
const expandedRowRender = props.expandedRowRender;
const expandRowByClick = props.expandRowByClick;
const onPaste = props.onPaste;
const anyColumnsFixed = this.columnManager.isAnyColumnsFixed();
const hasLeftFixed = this.columnManager.isAnyColumnsLeftFixed();
const { fixedColumnsBodyRowsHeight } = this.state;
let rst = [];
let height;
const rowClassName = props.rowClassName;
const rowRef = props.rowRef;
const expandedRowClassName = props.expandedRowClassName;
const needIndentSpaced = props.data.some(record => record[childrenColumnName]);
const onRowClick = props.onRowClick;
const onRowDoubleClick = props.onRowDoubleClick;
//const expandIconAsCell = fixed !== 'right' ? props.expandIconAsCell : false;
const expandIconColumnIndex = props.expandIconColumnIndex
if(props.lazyLoad && props.lazyLoad.preHeight && indent == 0){
// console.log("AAA--->lazyLoad--first->"+props.lazyLoad.preHeight);
rst.push(
<TableRow onPaste={onPaste} height={props.lazyLoad.preHeight} columns={[]} className='table_lazyload_row_first' key={'table_lazyload_row_first'} store={this.store} visible = {true}/>
)
}
let leafColumns;
if (fixed === 'left') {
leafColumns = this.columnManager.leftLeafColumns();
} else if (fixed === 'right') {
leafColumns = this.columnManager.rightLeafColumns();
} else {
leafColumns = this.columnManager.leafColumns();
}
const lazyCurrentIndex = props.lazyLoad && props.lazyLoad.startIndex ?props.lazyLoad.startIndex :0;
const lazyParentIndex = props.lazyLoad && props.lazyLoad.startParentIndex ?props.lazyLoad.startParentIndex :0;
const lazyEndIndex = props.lazyLoad && props.lazyLoad.endIndex ?props.lazyLoad.endIndex :-1;
const lazyLoadEnable = (props.lazyLoad && props.lazyLoad.startIndex>-1 && props.lazyLoad.endIndex >-1);
for (let i = 0; i < data.length; i++) {
let isHiddenExpandIcon;
const record = data[i];
const key = this.getRowKey(record, i);
// 兼容 NCC 以前的业务逻辑,支持外部通过 record 中的 isleaf 字段,判断是否为叶子节点
// record['_isLeaf'] = typeof record['isleaf'] === 'boolean' ? record['isleaf'] : record['_isLeaf'];
if(typeof record['isleaf'] === 'boolean' ){
record['_isLeaf'] = record['isleaf']; //如果isleaf存在并且为boolean的情况下才生成_isLeaf,否则无需生成
}
// _isLeaf 字段是在 bigData 里添加的,只有层级树大数据场景需要该字段
// _isLeaf 有三种取值情况:true / false / null。(Table内部字段)
const _isLeaf = typeof record['_isLeaf'] === 'boolean' ? record['_isLeaf'] : null;
const childrenColumn = _isLeaf ? false : record[childrenColumnName];
const isRowExpanded = this.isRowExpanded(record, i);
let expandedRowContent;
let expandedContentHeight = 0;
//fixedIndex一般是跟index是一个值的,只有是树结构时,会讲子节点的值也累计上
let fixedIndex = i;
//判断是否是tree结构
if (this.treeType) {
fixedIndex = this.treeRowIndex;
}
if (expandedRowRender && isRowExpanded) {
expandedRowContent = expandedRowRender(record, fixedIndex+lazyCurrentIndex, indent);
expandedContentHeight = parseInt(expandedRowContent.props && expandedRowContent.props.style && expandedRowContent.props.style.height?expandedRowContent.props.style.height:0);
}
//只有当使用expandedRowRender参数的时候才去识别isHiddenExpandIcon(隐藏行展开的icon)
if (expandedRowRender && typeof props.haveExpandIcon == 'function') {
isHiddenExpandIcon = props.haveExpandIcon(record, i);
}
if(props.bodyDisplayInRow){//内容显示不换行,即显示为"..."
if(anyColumnsFixed){//存在固定列则强制同步行高度,以确保行不会错位
height = props.height ? props.height : fixedColumnsBodyRowsHeight[fixedIndex];
}else{ //不存在固定列,则按指定高度呈现行
height = props.height || 40;
}
}else{//内容自适应行高
if(anyColumnsFixed){//存在固定列则强制同步行高度,以确保行不会错位
height = fixedColumnsBodyRowsHeight[fixedIndex];
}else{
//不存在固定列,则按内容高度自行呈现
}
}
// if (props.bodyDisplayInRow && props.height) {
// height = props.height
// } else if(fixed || props.heightConsistent) {
// height = fixedColumnsBodyRowsHeight[fixedIndex];
// }
let className = rowClassName(record, fixedIndex+lazyCurrentIndex, indent);
//合计代码如果是最后一行并且有合计功能时,最后一行为合计列
if(i == data.length -1 && props.showSum){
className = className + ' sumrow';
}
let paramRootIndex = rootIndex;
//小于0说明为第一层节点,她的子孙节点要保存自己的根节点
if(paramRootIndex<0){
paramRootIndex = i+lazyParentIndex;
}
let index = i;
if(rootIndex ==-1){
index = i+lazyParentIndex
}
if(lazyLoadEnable && this.treeType && (record.index <lazyCurrentIndex || record.index > lazyEndIndex)){
// 大数据表格下,如果是树表,父节点如果已经不在区域范围则无需渲染dom,解决快速向上滚动父级树节点闪现的问题
fixedIndex--;
this.treeRowIndex--;
}else{
rst.push(
<TableRow
onPaste={onPaste}
indent={indent}
indentSize={props.indentSize}
needIndentSpaced={needIndentSpaced}
className={`${className}`}
record={record}
hasLeftFixed={hasLeftFixed}
expandIconAsCell={props.expandIconAsCell}
onDestroy={this.onRowDestroy}
index={index}
visible={visible}
expandRowByClick={expandRowByClick}
onExpand={this.onExpanded}
expandable={expandedRowRender || ((childrenColumn && childrenColumn.length > 0) ? true : _isLeaf === false)}
expanded={isRowExpanded}
clsPrefix={`${props.clsPrefix}-row`}
childrenColumnName={childrenColumnName}
columns={leafColumns}
expandIconColumnIndex={expandIconColumnIndex}
onRowClick={onRowClick}
onRowDoubleClick={onRowDoubleClick}
height={height}
isHiddenExpandIcon={isHiddenExpandIcon}
onHover={this.handleRowHover}
key={"table_row_"+key}
hoverKey={key}
ref={rowRef}
store={this.store}
fixed={fixed}
expandedContentHeight={expandedContentHeight}
setRowHeight={props.setRowHeight}
setRowParentIndex={props.setRowParentIndex}
treeType={childrenColumn||this.treeType?true:false}
fixedIndex={fixedIndex+lazyCurrentIndex}
rootIndex = {rootIndex}
syncHover = {props.syncHover}
bodyDisplayInRow = {props.bodyDisplayInRow}
rowDraggAble={props.rowDraggAble}
useDragHandle={props.useDragHandle}
contentTable={this.contentTable}
tableUid = {this.tableUid}
expandedIcon={props.expandedIcon}
collapsedIcon={props.collapsedIcon}
lazyStartIndex = {lazyCurrentIndex}
lazyEndIndex = {lazyEndIndex}
centerColumnsLength={this.centerColumnsLength}
leftColumnsLength={this.leftColumnsLength}
expandIconCellWidth={expandIconCellWidth}
getCellClassName = {props.getCellClassName}
/>
);
}
this.treeRowIndex++;
const subVisible = visible && isRowExpanded;
if (expandedRowContent && isRowExpanded) {
rst.push(this.getExpandedRow(
key, expandedRowContent, subVisible, expandedRowClassName(record, i, indent), fixed, record, index
));
}
if (childrenColumn) {
this.isTreeType = true; //增加该标志位,为了兼容老版本,不修改以前的 `this.treeType` 的相关逻辑
this.treeType = true;//证明是tree表形式visible = {true}
rst = rst.concat(this.getRowsByData(
childrenColumn, subVisible, indent + 1, columns, fixed,paramRootIndex
));
}
}
if(props.lazyLoad && props.lazyLoad.sufHeight && indent == 0){
//console.log("AAA--->lazyLoad---last-->"+props.lazyLoad.su