diff --git a/components/apolloTable/component/DragFixed.tsx b/components/apolloTable/component/DragFixed.tsx index 6776f0ae1990236728ca6c267ce0053c81221c33..280d66a1392a173f2d79d7299e18723f27cf834e 100644 --- a/components/apolloTable/component/DragFixed.tsx +++ b/components/apolloTable/component/DragFixed.tsx @@ -90,6 +90,7 @@ const DragFixed = (props: any) => { dividerWrap.style.display = 'none'; // 滑块wrap移除hovered样式 handleWrap.classList.remove(styles.hovered); + handleWrap.style.top = `${initTop}px`; handleWrap.style.left = fixedWidth; // 滑块隐藏 handle.style.opacity = 0; diff --git a/components/apolloTable/component/DragSorted.less b/components/apolloTable/component/DragSorted.less new file mode 100644 index 0000000000000000000000000000000000000000..46728e6c17ca6e23e235461fbdc224eca2c87bae --- /dev/null +++ b/components/apolloTable/component/DragSorted.less @@ -0,0 +1,5 @@ +@import '../common'; + +.draggableDiv{ + cursor: move; +} \ No newline at end of file diff --git a/components/apolloTable/component/DragSorted.tsx b/components/apolloTable/component/DragSorted.tsx index 0fd5bc16b4aeb40fad2b0923bd63f76d1d252cd1..a29499eb149ce5d70f8ff989a85bc8ff1ff64bb4 100644 --- a/components/apolloTable/component/DragSorted.tsx +++ b/components/apolloTable/component/DragSorted.tsx @@ -1,28 +1,131 @@ import React, { useCallback } from 'react'; -import { Draggable } from 'react-beautiful-dnd'; +import classNames from 'classnames'; +import s from './DragSorted.less'; -const DragSorted = (props) => { - // using useCallback is optional - const onBeforeCapture = useCallback(() => {}, []); - const onBeforeDragStart = useCallback(() => {}, []); - const onDragStart = useCallback(() => { - debugger; +const DragSorted = (props: any) => { + const { className, style, columnConfig, onDropFinish, onScroll } = props; + // 表格 + const container: any = document.querySelector('#tableContainer'); + // 拖拽列时的影子div + const columnCopyDiv: any = document.querySelector('#columnCopyDiv'); + // 分割线wrap + const dividerWrap: any = document.querySelector('#dividerWrap'); + // 分割线 + const divider: any = document.querySelector('#divider'); + // 左侧固定列分割线 + const leftFixedHandleWrap: any = document.querySelector('#leftFixedHandleWrap'); + // ? 拖动目标事件 + // 开始拖动 + const onDragStart = useCallback((e) => { + // 表格初始位置x点 + const originLeft = container.getBoundingClientRect().x || 0; + // 拖动列矩形 + const targetRect = e.target.getBoundingClientRect(); + // 影子div显示 + columnCopyDiv.style.display = 'block'; + // 影子div初始x位置=拖动列x点-表格x点 + columnCopyDiv.style.left = `${targetRect.x - originLeft}px`; + // 影子div宽度=拖动列宽度 + columnCopyDiv.style.width = `${targetRect.width}px`; + // 鼠标x点与拖动列x点之间的距离(记录下来方便后续使用) + const detaX = e.clientX - targetRect.x; + columnCopyDiv.setAttribute('data-deta-x', detaX); + // 将拖动列信息加入拖拽事件dataTransfer中,方便后续使用 + e.dataTransfer.setData('dragColumn', JSON.stringify(columnConfig)); + // debugger + + divider.style.left = `${targetRect.x - originLeft}px`; + dividerWrap.style.display = 'block'; + }, [columnConfig.columnName]); + // 拖动中 + const onDragUpdate = useCallback((e) => { + // 拖动列矩形 + const targetRect = e.target.getBoundingClientRect(); + const tableRect = container.getBoundingClientRect(); + const detaX = columnCopyDiv.getAttribute('data-deta-x'); + const left = e.clientX - tableRect.x - detaX; + console.log('left: ', left); + // 影子div随鼠标移动 + columnCopyDiv.style.left = `${left}px`; + }, []); + // 停止拖动 + const onDragEnd = useCallback((e) => { + // 停止拖动时隐藏影子div + columnCopyDiv.style.display = 'none'; + dividerWrap.style.display = 'none'; + console.log('stop: '); }, []); - const onDragUpdate = useCallback(() => {}, []); - const onDragEnd = useCallback(() => {}, []); + // ? 投放目标事件 + // 在投放目标中移动 + const onDragOver = useCallback((e) => { + const tableRect = container.getBoundingClientRect(); + const targetRect = e.target.getBoundingClientRect(); + const columnCopyDivRect = columnCopyDiv.getBoundingClientRect(); + const leftFixedHandleWrapRect = leftFixedHandleWrap.getBoundingClientRect(); + const targetWidth = targetRect.width; + const targetX = targetRect.x; + const columnCopyDivWidth = columnCopyDivRect.width; + const columnCopyDivX = columnCopyDivRect.x; + // 影子div中间点的x坐标 + const columnCopyDivMid = columnCopyDivX + (columnCopyDivWidth / 2); + if (columnCopyDivMid > targetX && columnCopyDivMid < targetX + targetWidth) { + // 影子div中点在投放目标中 + divider.style.left = `${targetRect.x - tableRect.x}px`; + } + if (typeof onScroll === 'function') { + if (e.clientX > tableRect.right - 30) { + onScroll('right', 100); + } else if (e.clientX > tableRect.right - 100) { + onScroll('right', 10); + } else if (e.clientX < leftFixedHandleWrapRect.x + 100) { + onScroll('left', 10); + } else if (e.clientX < leftFixedHandleWrapRect.x + 30) { + onScroll('left', 100); + } + } + + // 元素默认是不能够投放,需在目标元素的dragover事件中取消默认事件 + var event = e || window.event; + event.preventDefault() + }, []); + // 在投放目标中松开鼠标 + const onDrop = useCallback((e) => { + const targetRect = e.target.getBoundingClientRect(); + const columnCopyDivRect = columnCopyDiv.getBoundingClientRect(); + const targetWidth = targetRect.width; + const targetX = targetRect.x; + const columnCopyDivWidth = columnCopyDivRect.width; + const columnCopyDivX = columnCopyDivRect.x; + // 影子div中间点的x坐标 + const columnCopyDivMid = columnCopyDivX + (columnCopyDivWidth / 2); + if (columnCopyDivMid > targetX && columnCopyDivMid < targetX + targetWidth) { + // 影子div中点在投放目标中 + try { + const dragColumn = JSON.parse(e.dataTransfer.getData('dragColumn')); + const dropColumn = columnConfig; + if (typeof onDropFinish === 'function') { + onDropFinish(dragColumn, dropColumn); + } + } catch (e) { + console.error('json解析失败') + } + } + }, [columnConfig.columnName]); + return ( - - {(provided, snapshot) => ( -
- {props.children} -
- )} -
+
+ {props.children} +
); }; export default DragSorted; diff --git a/components/apolloTable/component/Table.less b/components/apolloTable/component/Table.less index 15c9a9fa732b9eb68ad4fd61e207ad82dddfbbac..ebc698076a9be080d65f3c53591051b3a876bab5 100644 --- a/components/apolloTable/component/Table.less +++ b/components/apolloTable/component/Table.less @@ -5,6 +5,7 @@ display: flex; flex-direction: row; border: 1px solid @borderColor; + overflow: hidden; &.scroll { height: 100%; .loading { @@ -114,8 +115,9 @@ width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.4); - z-index: 20; + z-index: 4; display: none; + pointer-events: none; .widthHandle { position: absolute; cursor: ew-resize; @@ -134,3 +136,12 @@ z-index: 1; background: #ececec; } +.columnCopyDiv{ + position: absolute; + top: 0; + bottom: 0; + background: rgba(0,0,0,0.3); + z-index: 5; + pointer-events: none; + display: none; +} \ No newline at end of file diff --git a/components/apolloTable/component/Table.tsx b/components/apolloTable/component/Table.tsx index b2628d1ce791ce86c0e45fd268b0709a1d501289..2657ac4e9a5fcb6719bfe77cb0c8d1fa167c961f 100644 --- a/components/apolloTable/component/Table.tsx +++ b/components/apolloTable/component/Table.tsx @@ -2,7 +2,6 @@ import React, { Component } from 'react'; import classNames from 'classnames'; import memoizeOne from 'memoize-one'; import { Empty, Spin } from 'antd'; -import { DragDropContext, Droppable } from 'react-beautiful-dnd'; import { ScrollSync, Grid, AutoSizer } from 'react-virtualized'; import { Resizable, ResizableBox } from 'react-resizable'; import _ from 'lodash'; @@ -284,14 +283,31 @@ export default class AirTable extends Component { }, ); }; - + onScrollHor = (direction: string, step: number) => { + // 拖动超过视图范围,将表格左右滚动 + if (this.grid4) { + if (direction === 'right') { + if (this.grid4.state.scrollLeft >= this.grid4.getTotalColumnsWidth() - this.state.tableWidth - 100) { + console.log('已经到最右侧了') + return; + } + this.grid4.scrollToPosition({ scrollLeft: this.grid4.state.scrollLeft + step }); + } else { + if (this.grid4.state.scrollLeft <= 0) { + console.log('已经到最左侧了') + return; + } + this.grid4.scrollToPosition({ scrollLeft: this.grid4.state.scrollLeft - step }); + } + } + } // 渲染表头 renderHeaderCell = ( { showColumns, position }: { showColumns: ColumnProps[]; position?: string }, { columnIndex, key, style }: any, ) => { if (showColumns.length === 0) return null; - const { sortConfig, showIndex, rowSelection, dataSource } = this.props; + const { sortConfig, showIndex, rowSelection, dataSource, onDragSorted } = this.props; const { columnType = 1, columnName, @@ -303,42 +319,40 @@ export default class AirTable extends Component { requiredFlag, } = showColumns[columnIndex]; return ( -
- - { - e.stopPropagation(); - }} - /> - } - minConstraints={[100, 100]} - onResize={this.onResizeWidth} - onResizeStart={this.onResizeWidthStart} - onResizeStop={this.onResizeWidthStop.bind(this, columnName)} - draggableOpts={{ enableUserSelectHack: false }} - > - + { + e.stopPropagation(); + }} /> - - -
+ } + minConstraints={[100, 100]} + onResize={this.onResizeWidth} + onResizeStart={this.onResizeWidthStart} + onResizeStop={this.onResizeWidthStop.bind(this, columnName)} + draggableOpts={{ enableUserSelectHack: false }} + > + + + ); }; @@ -442,6 +456,8 @@ export default class AirTable extends Component { const { overscanColumnCount, overscanRowCount, rowHeight, headerHeight, columnWidth } = this.config; const scrollbarWidth = scrollbarSize() || 0; const showColumns = this.memoizeColumns(columns); + + const leftColumns = this.memoizeLeftColumns(columns); const rightColumns = this.memoizeRightColumns(columns); // 有隐藏列时,修正数据与列头不匹配问题 @@ -455,13 +471,8 @@ export default class AirTable extends Component { const rowCount = showData.length; const leftWidth = this.memoizeLeftWidth(leftColumns, showColumns); const rightWidth = this.memoizeLeftWidth(rightColumns, showColumns); - // let totalHeight: number = rowCount * rowHeight; let totalHeight: number = tableHeight - headerHeight; const { totalWidth } = this.memoizeTotalWidth(showColumns); - // if (rowCount > 0 && totalWidth > tableWidth) { - // // totalHeight = rowCount * rowHeight + scrollbarWidth; - // totalHeight = tableHeight + scrollbarWidth; - // } let realWidth = tableWidth; let paddingRight = 0; if (rowCount > 0 && rowCount * rowHeight > totalHeight) { @@ -474,344 +485,328 @@ export default class AirTable extends Component { {({ onScroll, scrollLeft, scrollTop }: any) => { return ( - - - {(provided, snapshot) => ( -
+ +
{ + this.tableContainer = dom; + }} + > + {totalWidth > tableWidth && leftCount > 0 && ( +
+ { + // 左侧表头
{ - this.tableContainer = dom; + > + { + this.grid1 = dom; + }} + className={styles.headerGrid} + columnWidth={this.getColumnWidth.bind(this, { + columns: showColumns, + showColumns: leftColumns, + })} + columnCount={leftCount} + width={leftWidth} + rowHeight={headerHeight} + rowCount={1} + height={headerHeight} + cellRenderer={this.renderHeaderCell.bind(this, { + showColumns: leftColumns, + })} + /> +
+ } + { + // 左侧固定列 +
- {totalWidth > tableWidth && leftCount > 0 && ( -
- { - // 左侧表头 -
{ + this.grid2 = dom; + }} + className={styles.sideGrid} + overscanRowCount={overscanRowCount} + cellRenderer={this.renderBodyCell.bind(this, { + showColumns: leftColumns, + showData: leftData, + position: 'left', + })} + columnWidth={this.getColumnWidth.bind(this, { + columns: showColumns, + showColumns: leftColumns, + })} + onScroll={(...arg: Array) => { + onScroll({ scrollTop: arg[0].scrollTop }); + this.onScroll(arg[0]); + }} + columnCount={leftCount} + width={leftWidth + scrollbarWidth} + rowHeight={rowHeight} + rowCount={rowCount} + height={totalHeight - scrollbarWidth} + scrollTop={scrollTop} + /> + + } + + )} + {canFixed && ( + + )} +
+ + {({ width, height }: any) => { + return ( +
+ { + // 中部表头 +
+ { + this.grid3 = dom; }} - > - { - this.grid1 = dom; - }} - className={styles.headerGrid} - columnWidth={this.getColumnWidth.bind(this, { + className={styles.headerGrid} + overscanColumnCount={ + overscanColumnCount + } + columnWidth={this.getColumnWidth.bind( + this, + { columns: showColumns, - showColumns: leftColumns, - })} - columnCount={leftCount} - width={leftWidth} - rowHeight={headerHeight} - rowCount={1} - height={headerHeight} - cellRenderer={this.renderHeaderCell.bind(this, { - showColumns: leftColumns, - })} - /> -
- } - { - // 左侧固定列 -
+ showColumns, + }, + )} + columnCount={columnCount} + width={width} + rowHeight={headerHeight} + rowCount={1} + height={headerHeight} + scrollLeft={scrollLeft} + cellRenderer={this.renderHeaderCell.bind( + this, + { + showColumns, + }, + )} + /> +
+ } + { + // 中部内容 +
+ {rowCount > 0 ? ( { - this.grid2 = dom; + this.grid4 = dom; }} - className={styles.sideGrid} - overscanRowCount={overscanRowCount} - cellRenderer={this.renderBodyCell.bind(this, { - showColumns: leftColumns, - showData: leftData, - position: 'left', - })} - columnWidth={this.getColumnWidth.bind(this, { - columns: showColumns, - showColumns: leftColumns, - })} - onScroll={(...arg: Array) => { - onScroll({ scrollTop: arg[0].scrollTop }); - this.onScroll(arg[0]); - }} - columnCount={leftCount} - width={leftWidth + scrollbarWidth} - rowHeight={rowHeight} - rowCount={rowCount} - height={totalHeight - scrollbarWidth} - scrollTop={scrollTop} - /> - - } - - )} - {canFixed && ( - - )} -
- - {({ width, height }: any) => { - return ( -
- { - // 中部表头 -
- { - this.grid3 = dom; - }} - className={styles.headerGrid} - overscanColumnCount={ - overscanColumnCount - } - columnWidth={this.getColumnWidth.bind( - this, - { - columns: showColumns, - showColumns, - }, - )} - columnCount={columnCount} - width={width} - rowHeight={headerHeight} - rowCount={1} - height={headerHeight} - scrollLeft={scrollLeft} - cellRenderer={this.renderHeaderCell.bind( - this, - { - showColumns, - }, - )} - /> -
+ className={styles.centerGrid} + overscanColumnCount={ + overscanColumnCount } - { - // 中部内容 -
- {rowCount > 0 ? ( - { - this.grid4 = dom; - }} - className={styles.centerGrid} - overscanColumnCount={ - overscanColumnCount - } - overscanRowCount={ - overscanRowCount - } - columnWidth={this.getColumnWidth.bind( - this, - { - columns: showColumns, - showColumns, - }, - )} - columnCount={columnCount} - width={realWidth} - rowHeight={rowHeight} - rowCount={rowCount} - onScroll={( - ...arg: Array - ) => { - onScroll(...arg); - this.onScroll(arg[0]); - }} - scrollTop={scrollTop} - height={totalHeight} - cellRenderer={this.renderBodyCell.bind( - this, - { - showColumns, - showData, - position: 'center', - }, - )} - /> - ) : ( - columnCount > 0 && - !loading && ( - - ) - )} - + overscanRowCount={ + overscanRowCount } - - ); - }} - - - {totalWidth > tableWidth && rightCount > 0 && ( -
- { - // 右侧表头 -
- { - this.grid5 = dom; - }} - className={styles.headerGrid} - columnWidth={this.getColumnWidth.bind(this, { - columns: showColumns, - showColumns: rightColumns, - })} - columnCount={rightCount} - width={rightWidth} - rowHeight={headerHeight} - rowCount={1} - height={headerHeight} - cellRenderer={this.renderHeaderCell.bind(this, { - showColumns: rightColumns, - position: 'right', - })} - /> -
- } - { - // 右侧固定列 -
- { - this.grid6 = dom; - }} - className={styles.sideGrid} - overscanRowCount={overscanRowCount} - cellRenderer={this.renderBodyCell.bind(this, { - showColumns: rightColumns, - showData: rightData, - position: 'right', - })} - columnWidth={this.getColumnWidth.bind(this, { - columns: showColumns, - showColumns: rightColumns, - })} - onScroll={(...arg: Array) => { - onScroll({ scrollTop: arg[0].scrollTop }); - this.onScroll(arg[0]); - }} - columnCount={rightCount} - width={rightWidth + scrollbarWidth} + columnWidth={this.getColumnWidth.bind( + this, + { + columns: showColumns, + showColumns, + }, + )} + columnCount={columnCount} + width={realWidth} rowHeight={rowHeight} rowCount={rowCount} - height={totalHeight - scrollbarWidth} + onScroll={( + ...arg: Array + ) => { + onScroll(...arg); + this.onScroll(arg[0]); + }} scrollTop={scrollTop} + height={totalHeight} + cellRenderer={this.renderBodyCell.bind( + this, + { + showColumns, + showData, + position: 'center', + }, + )} /> - - } - - )} -
-
- {loading && (loadComp ? loadComp : )} + ) : ( + columnCount > 0 && + !loading && ( + + ) + )} +
+ }
-
{ - this.widthHandleWrapper = dom; + ); + }} + +
+ {totalWidth > tableWidth && rightCount > 0 && ( +
+ { + // 右侧表头 +
+ { + this.grid5 = dom; }} - > -
{ - this.widthHandle = dom; - }} - /> -
+ className={styles.headerGrid} + columnWidth={this.getColumnWidth.bind(this, { + columns: showColumns, + showColumns: rightColumns, + })} + columnCount={rightCount} + width={rightWidth} + rowHeight={headerHeight} + rowCount={1} + height={headerHeight} + cellRenderer={this.renderHeaderCell.bind(this, { + showColumns: rightColumns, + position: 'right', + })} + /> +
+ } + { + // 右侧固定列 +
+ { + this.grid6 = dom; + }} + className={styles.sideGrid} + overscanRowCount={overscanRowCount} + cellRenderer={this.renderBodyCell.bind(this, { + showColumns: rightColumns, + showData: rightData, + position: 'right', + })} + columnWidth={this.getColumnWidth.bind(this, { + columns: showColumns, + showColumns: rightColumns, + })} + onScroll={(...arg: Array) => { + onScroll({ scrollTop: arg[0].scrollTop }); + this.onScroll(arg[0]); + }} + columnCount={rightCount} + width={rightWidth + scrollbarWidth} + rowHeight={rowHeight} + rowCount={rowCount} + height={totalHeight - scrollbarWidth} + scrollTop={scrollTop} + /> - {provided.placeholder} - - )} - - + } + + )} +
+
+ {loading && (loadComp ? loadComp : )} +
+
{ + this.widthHandleWrapper = dom; + }} + > +
{ + this.widthHandle = dom; + }} + /> +
+
+
); }} diff --git a/components/apolloTable/component/index.tsx b/components/apolloTable/component/index.tsx index b1c4c514a9917eaf415b4c4340a389c58454abc3..4afad50fa854b3b7146430a110bf93724640e03e 100644 --- a/components/apolloTable/component/index.tsx +++ b/components/apolloTable/component/index.tsx @@ -83,6 +83,7 @@ class AirTable extends React.Component { loadComp, showCondition, canFixed, + onDragSorted, } = this.props; const sortConfig = operateConfig && @@ -137,6 +138,7 @@ class AirTable extends React.Component { contentMenu={contentMenu} loadComp={loadComp} canFixed={canFixed} + onDragSorted={onDragSorted} />
diff --git a/components/apolloTable/component/interface.tsx b/components/apolloTable/component/interface.tsx index 6c81e65db113228294cf07873313ae9de8deb5c9..46fe7dc91d03caffb15cb953e393db2052a98b0e 100644 --- a/components/apolloTable/component/interface.tsx +++ b/components/apolloTable/component/interface.tsx @@ -76,6 +76,7 @@ export interface TableProps extends LoadConfigProps { canFixed?: boolean;// 是否可以拖拽自定义固定列 canSorted?: boolean;// 是否可以拖拽自定义列排序 canResized?: boolean;// 是否可以拖拽自定义列伸缩 + onDragSorted?:Function;// 拖拽更改列排序回调 } export interface TableState { columns: ColumnProps[];