Commit 66a718df authored by zhangwenshuai's avatar zhangwenshuai

增加自定义固定列

parent 62249dc2
@import '../common';
.leftFixedHandleWrap {
position: absolute;
bottom: 0;
width: 2px;
z-index: 4;
background: transparent;
&.hovered {
background: #aaa;
}
}
.leftFixedHandle {
cursor: grab;
transform: translate(-50%, -50%);
border-radius: 10px;
width: 6px;
height: 26px;
background: #2d7ff9;
position: fixed;
z-index: 4;
opacity: 0;
transition: opacity ease 100ms;
}
import React from 'react';
import { ResizableBox } from 'react-resizable';
import styles from './DragFixed.less';
const DragFixed = (props: any) => {
const { initLeft, initTop, onResizeStart, tableWidth, showColumns, columnWidth, columns, onResizeStop } = props;
// 表格
const container: any = document.querySelector('#tableContainer');
// 滑块wrap
const handleWrap: any = document.querySelector('#leftFixedHandleWrap');
// 滑块
const handle: any = document.querySelector('#leftFixedHandle');
// 分割线wrap
const dividerWrap: any = document.querySelector('#dividerWrap');
// 分割线
const divider: any = document.querySelector('#divider');
const onMouseEnterWrap = (e: any) => {
// 滑块wrap添加hovered样式
handleWrap.classList.add(styles.hovered);
// 滑块初始化位置,显示
handle.style.top = `${e.clientY}px`;
handle.style.opacity = 1;
};
const onMouseMoveWrap = (e: any) => {
// 滑块位置跟随鼠标上下移动
handle.style.top = `${e.clientY}px`;
};
const onMouseLeaveWrap = (e: any) => {
const originLeft = container.getBoundingClientRect().x || 0;
// 当前固定列宽度为分割线的left
const handleWrapLeft: string = handleWrap.style.left;
// 样式转数值
const handleWrapLeftNum: string = handleWrapLeft.slice(0, -2);
console.log('x',e.clientX - originLeft)
console.log('left',handleWrapLeftNum)
if (
e.clientX - originLeft < Number(handleWrapLeftNum) - 10 ||
e.clientX - originLeft > Number(handleWrapLeftNum) + 12
) {
// 滑块wrap移除hovered样式
handleWrap.classList.remove(styles.hovered);
// 滑块隐藏
handle.style.opacity = 0;
}
};
const onResizeStartHandle = (e: any) => {
if (typeof onResizeStart === 'function') {
onResizeStart();
}
const originLeft = container.getBoundingClientRect().x || 0;
handleWrap.style.top = 0;
handleWrap.style.left = `${e.x - originLeft}px`;
};
const onResizeHandle = (e: any) => {
const originLeft = container.getBoundingClientRect().x || 0;
let inTableLeft = e.x - originLeft;
// left不能超过表格一半宽度
if (inTableLeft > tableWidth / 2) {
inTableLeft = tableWidth / 2;
}
let fixedWidth = 0;
let index = 0;
// 计算固定列宽度及索引
for (let i = 0; i < showColumns.length; i++) {
fixedWidth += showColumns[i].width || columnWidth;
if (fixedWidth > inTableLeft) {
index = i;
break;
}
}
let leftHandleLeft = 0;
if (inTableLeft > fixedWidth - (showColumns[index].width || columnWidth) / 2) {
// left位于当前列中间偏右
leftHandleLeft = fixedWidth;
} else {
// left位于当前列中间偏左
leftHandleLeft = fixedWidth - (showColumns[index].width || columnWidth);
}
// 拖动时显示分割线
dividerWrap.style.display = 'block';
// 分割线取列的边侧位置
divider.style.left = `${leftHandleLeft}px`;
// 拖动线取鼠标位置
handleWrap.style.left = `${inTableLeft}px`;
};
const onResizeStopHandle = () => {
// 当前固定列宽度为分割线的left
const fixedWidth: string = divider.style.left;
// 样式转数值
const fixedWidthNum: string = fixedWidth.slice(0, -2);
// 分隔线wrap隐藏
dividerWrap.style.display = 'none';
// 滑块wrap移除hovered样式
handleWrap.classList.remove(styles.hovered);
handleWrap.style.left = fixedWidth;
// 滑块隐藏
handle.style.opacity = 0;
let leftFixedWidth = 0;
const fixedCol: any = {};
// 计算获取固定列
for (let i = 0; i < showColumns.length; i++) {
leftFixedWidth += showColumns[i].width || columnWidth;
if (leftFixedWidth <= Number(fixedWidthNum)) {
fixedCol[showColumns[i].columnName] = 1;
} else {
break;
}
}
const newColumns: any = [];
// 为固定列增加fixed属性
columns.map((item: any) => {
if (fixedCol[item.columnName] === 1) {
item.fixed = 'left';
} else {
if (item.fixed === 'left') {
item.fixed = '';
}
}
newColumns.push(item);
});
if (typeof onResizeStop === 'function') {
onResizeStop({ columns: newColumns });
}
};
return (
<div
id="leftFixedHandleWrap"
className={styles.leftFixedHandleWrap}
style={{
left: `${initLeft}px`,
top: `${initTop}px`,
}}
onMouseEnter={onMouseEnterWrap}
onMouseMove={onMouseMoveWrap}
// onMouseLeave={onMouseLeaveWrap}
>
<ResizableBox
handle={
<span
id="leftFixedHandle"
className={styles.leftFixedHandle}
onClick={(e) => {
e.stopPropagation();
}}
/>
}
onResizeStart={onResizeStartHandle}
onResize={onResizeHandle}
onResizeStop={onResizeStopHandle}
draggableOpts={{ enableUserSelectHack: false }}
/>
</div>
);
};
export default DragFixed;
......@@ -10,6 +10,7 @@ import styles from './Table.less';
import { TableProps, TableState, ColumnProps, RowProps } from './interface';
import Column from './Column';
import Cell from './Cell';
import LeftDragFixed from './DragFixed';
import { getMergeClassName, getMergeStyle } from '../utils/utils';
import { Consumer } from './context';
......@@ -261,6 +262,26 @@ export default class AirTable extends Component<TableProps, TableState> {
},
);
};
// 拖拽自定义固定列前置动作
onResizeStartLeftDragFixed = () => {
// 拖动开始,将表格滚动回最左端
if (this.grid3 && this.grid4) {
this.grid3.scrollToPosition({ scrollLeft: 0 });
this.grid4.scrollToPosition({ scrollLeft: 0 });
}
};
// 拖拽自定义固定列后置动作
onResizeStopLeftDragFixed = ({ columns }) => {
this.setState(
{
columns,
},
() => {
this.grid1 && this.grid1.recomputeGridSize();
this.grid2 && this.grid2.recomputeGridSize();
},
);
};
// 渲染表头
renderHeaderCell = (
......@@ -414,7 +435,7 @@ export default class AirTable extends Component<TableProps, TableState> {
render() {
const { loading, noDataPlaceholder, loadComp } = this.props;
const { columns, dataSource, tableWidth = 0, tableHeight = 0 } = this.state;
const { overscanColumnCount, overscanRowCount, rowHeight, headerHeight } = this.config;
const { overscanColumnCount, overscanRowCount, rowHeight, headerHeight, columnWidth } = this.config;
const scrollbarWidth = scrollbarSize() || 0;
const showColumns = this.memoizeColumns(columns);
const leftColumns = this.memoizeLeftColumns(columns);
......@@ -458,6 +479,7 @@ export default class AirTable extends Component<TableProps, TableState> {
style={{
paddingRight: this.props.onScroll ? paddingRight : 0,
}}
id="tableContainer"
ref={(dom) => {
this.tableContainer = dom;
}}
......@@ -537,6 +559,16 @@ export default class AirTable extends Component<TableProps, TableState> {
}
</div>
)}
<LeftDragFixed
initLeft={leftWidth}
initTop={headerHeight}
tableWidth={tableWidth}
showColumns={showColumns}
columnWidth={columnWidth}
columns={columns}
onResizeStart={this.onResizeStartLeftDragFixed}
onResizeStop={this.onResizeStopLeftDragFixed}
/>
<div className={styles.centerContainer}>
<AutoSizer onResize={this.onResize}>
{({ width, height }: any) => {
......@@ -716,12 +748,14 @@ export default class AirTable extends Component<TableProps, TableState> {
</div>
<div
className={styles.widthHandleWrapper}
id="dividerWrap"
ref={(dom) => {
this.widthHandleWrapper = dom;
}}
>
<div
className={styles.widthHandle}
id="divider"
ref={(dom) => {
this.widthHandle = dom;
}}
......
......@@ -50,29 +50,32 @@ export interface LoadConfigProps {
}
export interface TableProps extends LoadConfigProps {
columns: ColumnProps[];
dataSource: RowProps[];
rowClassName?: string | Function;
rowStyle?: Object | Function;
columns: ColumnProps[];// 列配置
dataSource: RowProps[];// 数据源
rowClassName?: string | Function;// 行class
rowStyle?: Object | Function;// 行style
rowRenderer?: Function;
bordered?: boolean;
height?: number;
width?: number;
emitChangeCell?: Function;
bordered?: boolean;// 是否显示边框
height?: number;// 表格高度
width?: number;// 表格宽度
emitChangeCell?: Function;// 单元格修改回调
sortConfig?: any;
paginationConfig?: any;
showIndex?: boolean;
showExpand?: any;
emptyPlaceholder?: string;
cellEditable?: boolean;
rowHeight?: number;
headerHeight?: number;
columnWidth?: number;
loading?: boolean;
rowSelection?: any;
noDataPlaceholder?: any;
contentMenu?: any;
loadComp?: any;
paginationConfig?: any;// 分页配置
showIndex?: boolean;// 是否显示序号
showExpand?: any;// 是否显示展开详情图标
emptyPlaceholder?: string;// 数据为空时默认显示
cellEditable?: boolean;// 单元格是否可编辑
rowHeight?: number;// 初始化行高
headerHeight?: number;// 初始化表头高度
columnWidth?: number;// 初始化单元格宽度
loading?: boolean;// 是否加载中
rowSelection?: any;// 复选配置
noDataPlaceholder?: any;// 无数据时显示文案
contentMenu?: any;// 右键菜单
loadComp?: any;// 加载动画组件
canFixed?: boolean;// 是否可以拖拽自定义固定列
canSorted?: boolean;// 是否可以拖拽自定义列排序
canResized?: boolean;// 是否可以拖拽自定义列伸缩
}
export interface TableState {
columns: ColumnProps[];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment