diff --git a/components/apolloTable/component/DragFixed.less b/components/apolloTable/component/DragFixed.less new file mode 100644 index 0000000000000000000000000000000000000000..5e5fc66e40ea0e230da79c74abb54b7a3d6d581a --- /dev/null +++ b/components/apolloTable/component/DragFixed.less @@ -0,0 +1,24 @@ +@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; +} diff --git a/components/apolloTable/component/DragFixed.tsx b/components/apolloTable/component/DragFixed.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3d941be2045d2909475e4a013dc59cadf96db296 --- /dev/null +++ b/components/apolloTable/component/DragFixed.tsx @@ -0,0 +1,162 @@ +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 ( +
+ { + e.stopPropagation(); + }} + /> + } + onResizeStart={onResizeStartHandle} + onResize={onResizeHandle} + onResizeStop={onResizeStopHandle} + draggableOpts={{ enableUserSelectHack: false }} + /> +
+ ); +}; +export default DragFixed; diff --git a/components/apolloTable/component/Table.tsx b/components/apolloTable/component/Table.tsx index 1c5483ef52e4da562049d8f73a69cf8a333c8a37..108ba41310d67e0f53d94ff9dd4e64266a10d66e 100644 --- a/components/apolloTable/component/Table.tsx +++ b/components/apolloTable/component/Table.tsx @@ -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 { }, ); }; + // 拖拽自定义固定列前置动作 + 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 { 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 { style={{ paddingRight: this.props.onScroll ? paddingRight : 0, }} + id="tableContainer" ref={(dom) => { this.tableContainer = dom; }} @@ -537,6 +559,16 @@ export default class AirTable extends Component { } )} +
{({ width, height }: any) => { @@ -716,12 +748,14 @@ export default class AirTable extends Component {
{ this.widthHandleWrapper = dom; }} >
{ this.widthHandle = dom; }} diff --git a/components/apolloTable/component/interface.tsx b/components/apolloTable/component/interface.tsx index 7a21526472ec5217e270cbf750de8796adab433f..6c81e65db113228294cf07873313ae9de8deb5c9 100644 --- a/components/apolloTable/component/interface.tsx +++ b/components/apolloTable/component/interface.tsx @@ -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[];