UNPKG

vxe-table-select-area

Version:

一个基于 vxe-table 的可区域选中复制、粘贴的组件

1,759 lines (1,610 loc) 71.6 kB
/* eslint-disable no-unreachable */ /* eslint-disable brace-style */ // import Vue from 'vue' import {h} from 'vue' import XEUtils from 'xe-utils' import { getMouseEventClickType } from '../utils/mouse-event' import { getScrollbarWidth } from '../utils/scroll-bar' import { isEmptyValue, isBoolean, isFunction } from '../utils/index' import { KEY_CODES, MOUSE_EVENT_CLICK_TYPE } from '../utils/constant' import { clsName, getColumnByColkey, getColKeysByFixedTypeWithinColKeys, isExistNotFixedColKey, isOperationColumn, getLeftmostColKey, getRightmostColKey, getColKeysByRangeColKeys, getSelectionRangeData, getNextColKey, cellAutofill, isCellInSelectionRange, isContextmenuPanelClicked, isClearSelectionByBodyCellRightClick, getPreviewColKey, isLastColumnByColKey, isLastRowByRowKey, isExistGivenFixedColKey, getTotalWidthByColKeys } from '../common' import { onBeforeCopy, onAfterCopy, onBeforePaste, onAfterPaste, onBeforeCut, onAfterCut, onBeforeDelete, onAfterDelete } from '../common/clipboard' import { INSTANCE_METHODS, COMPS_CUSTOM_ATTRS, COLUMN_FIXED_TYPE, CURRENT_CELL_SELECTION_TYPES, EMIT_EVENTS, COMPS_NAME, AUTOFILLING_DIRECTION, CELL_SELECTION_DIRECTION } from '../common/constant' // const { render } = require('nprogress') import { isInputKeyCode } from '../utils/event-key-codes' // const vm = new Vue() // console.log(vm.$createElement); // console.log(createElement) // const h = vm.$createElement // const h = createElement export default { name: 'VxeSelection', data () { return { currentCellEl: null, isBodyCellMousedown: false, cellSelectionData: { currentCell: { rowKey: '', colKey: '', rowIndex: -1 }, normalEndCell: { rowKey: '', colKey: '', rowIndex: -1 }, autoFillEndCell: { rowKey: '', colKey: '' } }, cellSelectionRangeData: { leftColKey: '', rightColKey: '', topRowKey: '', bottomRowKey: '' }, // body indicator rowKeys bodyIndicatorRowKeys: { startRowKey: '', startRowKeyIndex: -1, endRowKey: '', endRowKeyIndex: -1 }, tableContainerRef: '$el', tableContentWrapperRef: 'tableBody', colgroups: [], cellSelectionRect: { // current cell element rect currentCellRect: { left: 0, top: 0, width: 0, height: 0 }, // normal end cell element rect normalEndCellRect: { left: 0, top: 0, width: 0, height: 0 }, // auto fill end cell element rect autoFillEndCellRect: { left: 0, top: 0, width: 0, height: 0 } }, domRect: {}, currentCellSelectionType: '', isAutofillStarting: false, isColumnResizing: false, enableStopEditing: true } }, computed: { // return row keys allRowKeys () { let result = [] const { keyField } = this.rowOpts this.rowKeyFieldName = keyField const { tableData, rowKeyFieldName } = this if (rowKeyFieldName) { result = tableData.map((x) => { return x[rowKeyFieldName] }) } // // console.log(480,tableData,rowKeyFieldName,result) return result }, /* enable cell selection 单元格编辑、剪贴板都依赖单元格选择 */ enableCellSelection () { let result = true const { cellSelectionOption, rowKeyFieldName } = this if (isEmptyValue(rowKeyFieldName)) { result = false } else if ( cellSelectionOption && isBoolean(cellSelectionOption.enable) && cellSelectionOption.enable === false ) { result = false } return result }, // show corner showCorner () { let result = true // this.cellAutofillOption = true const { cellAutofillOption } = this if (cellAutofillOption) { const { directionX, directionY } = this.cellAutofillOption if ( isBoolean(directionY) && !directionY && isBoolean(directionX) && !directionX ) { result = false } } else { result = false } // // console.log(163333,cellAutofillOption) return result } }, watch: { tableColumn: { handler (newVal) { this.$nextTick(() => { // // console.log(105,newVal) this.tableEl = this.$refs[this.tableContentWrapperRef].$refs.table this.tableColumn.forEach(e => { const obj = { field: e.field || e.id, edit: true, key: e.id, title: e.title || e.type, width: e.minWidth, _colspan: e.colSpan, _keys: e.id, _level: e.level, _realTimeWidth: e.renderWidth, _rowspan: e.rowSpan } this.colgroups.push(obj) }) }) }, immediate: false }, allRowKeys: { handler (newVal) { if (Array.isArray(newVal)) { const { currentCell } = this.cellSelectionData // 行被移除,清空单元格选中 if (currentCell.rowIndex > -1) { if (newVal.indexOf(currentCell.rowKey) === -1) { this.clearCellSelectionCurrentCell() } } } }, immediate: false }, 'cellSelectionData.currentCell': { handler: function (val) { this.setCurrentCellSelectionType() const { rowKey, colKey } = val if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) { // // console.log(138) this.setCurrentCellEl() this.setSelectionPositions({ type: 'currentCell' }) } else { this[INSTANCE_METHODS.CLEAR_CURRENT_CELL_RECT]() } this.setCellSelectionRangeData() }, deep: true, immediate: true }, 'cellSelectionData.normalEndCell': { handler: function (val) { this.setCurrentCellSelectionType() const { rowKey, colKey } = val if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) { // set normal end cell el this.setNormalEndCellEl() this.setSelectionPositions({ type: 'normalEndCell' }) } else { this[INSTANCE_METHODS.CLEAR_NORMAL_END_CELL_RECT]() } this.setCellSelectionRangeData() }, deep: true, immediate: true }, 'cellSelectionData.autoFillEndCell': { handler: function (val) { const { rowKey, colKey } = val if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) { this.setAutofillEndCellEl() this.setSelectionPositions({ type: 'autoFillEndCell' }) } else { this.clearAutofillEndCellRect() } }, deep: true, immediate: true }, isAutofillStarting: { handler (val) { if (!val) { this.setCellSelectionByAutofill() this.clearCellSelectionAutofillEndCell() } } } }, methods: { setCurrentCellSelectionType () { const { currentCell, normalEndCell } = this.cellSelectionData let result if ( isEmptyValue(currentCell.rowKey) || isEmptyValue(currentCell.colKey) ) { result = '' } else { if ( !isEmptyValue(normalEndCell.rowKey) && !isEmptyValue(normalEndCell.colKey) ) { result = CURRENT_CELL_SELECTION_TYPES.RANGE } else { result = CURRENT_CELL_SELECTION_TYPES.SINGLE } } // // console.log(261,result) this.currentCellSelectionType = result }, resetCellPositions () { // // // console.log(350) const { currentCell, normalEndCell } = this.cellSelectionData if ( !isEmptyValue(currentCell.rowKey) && !isEmptyValue(currentCell.colKey) ) { this.setSelectionPositions({ type: 'currentCell' }) } if ( !isEmptyValue(normalEndCell.rowKey) && !isEmptyValue(normalEndCell.colKey) ) { this.setSelectionPositions({ type: 'normalEndCell' }) } }, cellSelectionRangeDataChange (newData) { this.cellSelectionRangeData = Object.assign( this.cellSelectionRangeData, newData ) }, cellSelectionCornerMousedown ({ event }) { this.isAutofillStarting = true }, autofillingDirectionChange (direction) { this.autofillingDirection = direction }, cellSelectionCornerMouseup ({ event }) { this.isAutofillStarting = false }, handleCellAreaEvent: function handleCellAreaEvent (evnt, params) { // // // console.log(17,evnt,params) const { shiftKey } = evnt const { row, column } = params const rowData = row const { getRowid, cellSelectionData, cellSelectionRangeData, colgroups, allRowKeys } = this const rowKey = getRowid(rowData) const colKey = column.id // // console.log(24,this,rowKey) const { currentCell } = cellSelectionData const mouseEventClickType = getMouseEventClickType(evnt) // // console.log(47,mouseEventClickType) this.isBodyCellMousedown = true const isClearByRightClick = isClearSelectionByBodyCellRightClick({ mouseEventClickType, cellData: { rowKey, colKey }, cellSelectionData, cellSelectionRangeData, colgroups, allRowKeys }) // // // console.log(70,cellSelectionData,cellSelectionRangeData,colgroups,allRowKeys) // const isClearByRightClick = true if (isClearByRightClick) { // clear header indicator colKeys // this.clearHeaderIndicatorColKeys(); // clear body indicator colKeys this.clearBodyIndicatorRowKeys() if (shiftKey && currentCell.rowIndex > -1) { this.cellSelectionNormalEndCellChange({ rowKey, colKey }) } else { // cell selection by click this.cellSelectionByClick({ rowData, column }) this.clearCellSelectionNormalEndCell() } } }, // table click outside tableClickOutside (e) { // exclude contextmenu panel clicked if (isContextmenuPanelClicked(e)) { return false } this.isHeaderCellMousedown = false this.isBodyCellMousedown = false this.isBodyOperationColumnMousedown = false this.isAutofillStarting = false this.setIsColumnResizing(false) // clear cell selection this.clearCellSelectionCurrentCell() this.clearCellSelectionNormalEndCell() // clear indicators // this.clearHeaderIndicatorColKeys(); this.clearBodyIndicatorRowKeys() // stop editing cell // this[INSTANCE_METHODS.STOP_EDITING_CELL](); }, // clear header indicator colKeys clearHeaderIndicatorColKeys () { this.headerIndicatorColKeys.startColKey = '' this.headerIndicatorColKeys.startColKeyIndex = -1 this.headerIndicatorColKeys.endColKey = '' this.headerIndicatorColKeys.endColKeyIndex = -1 }, clearCellSelectionCurrentCell () { this.cellSelectionCurrentCellChange({ rowKey: '', colKey: '', rowIndex: -1 }) }, setIsColumnResizing (val) { this.isColumnResizing = val }, setCellSelectionRangeData () { const { currentCellSelectionType } = this const { currentCell, normalEndCell } = this.cellSelectionData let result = {} if ( currentCellSelectionType === CURRENT_CELL_SELECTION_TYPES.SINGLE ) { result = { leftColKey: currentCell.colKey, rightColKey: currentCell.colKey, topRowKey: currentCell.rowKey, bottomRowKey: currentCell.rowKey } } else if ( currentCellSelectionType === CURRENT_CELL_SELECTION_TYPES.RANGE ) { const leftmostColKey = getLeftmostColKey({ colgroups: this.colgroups, colKeys: [currentCell.colKey, normalEndCell.colKey] }) /* current cell col key is leftmost colKey 需要用 colKey 的位置进行判断,不能根据当前单元格 left 值判断(固定列时) */ if (leftmostColKey === currentCell.colKey) { result.leftColKey = currentCell.colKey result.rightColKey = normalEndCell.colKey } else { result.leftColKey = normalEndCell.colKey result.rightColKey = currentCell.colKey } if (currentCell.rowIndex < normalEndCell.rowIndex) { result.topRowKey = currentCell.rowKey result.bottomRowKey = normalEndCell.rowKey } else { result.topRowKey = normalEndCell.rowKey result.bottomRowKey = currentCell.rowKey } } else { // clear result = { leftColKey: '', rightColKey: '', topRowKey: '', bottomRowKey: '' } } // // console.log(3888888,result) this.$emit(EMIT_EVENTS.CELL_SELECTION_RANGE_DATA_CHANGE, result) }, // cell selection by click cellSelectionByClick ({ rowData, column }) { // const { rowKeyFieldName } = this; const { getRowid } = this // const rowKey = getRowKey(rowData, rowKeyFieldName); const rowKey = getRowid(rowData) // set cell selection and column to visible this[INSTANCE_METHODS.SET_CELL_SELECTION]({ rowKey, colKey: column.id, isScrollToRow: false }) // row to visible this.rowToVisible(KEY_CODES.ARROW_UP, rowKey) this.rowToVisible(KEY_CODES.ARROW_DOWN, rowKey) }, // cell selection end cell change // cellSelectionNormalEndCellChange({ rowKey, colKey }) { // this.cellSelectionData.normalEndCell.colKey = colKey; // this.cellSelectionData.normalEndCell.rowKey = rowKey; // this.cellSelectionData.normalEndCell.rowIndex = // this.allRowKeys.indexOf(rowKey); // }, setAutofillEndCellEl () { const { cellSelectionData, tableEl } = this const { rowKey, colKey } = cellSelectionData.autoFillEndCell if (tableEl) { const autoFillEndCellEl = tableEl.querySelector( `tbody tr[rowid="${rowKey}"] td[colid="${colKey}"]` ) if (autoFillEndCellEl) { this.autoFillEndCellEl = autoFillEndCellEl } } }, [INSTANCE_METHODS.SET_CELL_SELECTION] ({ rowKey, colKey, isScrollToRow = true }) { const { enableCellSelection } = this // // console.log(165,this) // if (!enableCellSelection) { // return false; // } if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) { // // console.log(171) this.cellSelectionCurrentCellChange({ rowKey, colKey }) const column = getColumnByColkey(colKey, this.colgroups) // // console.log(219,this.colgroups,column) // column to visible // this.columnToVisible(column); // row to visible if (isScrollToRow) { this[INSTANCE_METHODS.SCROLL_TO_ROW_KEY]({ rowKey }) } } }, // table scroll to rowKey position [INSTANCE_METHODS.SCROLL_TO_ROW_KEY] ({ rowKey }) { // // console.log('550滚动') if (isEmptyValue(rowKey)) { // console.warn("Row key can't be empty!"); return false } let scrollTop = 0 const { isVirtualScroll, headerTotalHeight } = this const tableContainerRef = this.$refs[this.tableContainerRef] if (isVirtualScroll) { const position = this.virtualScrollPositions.find( (x) => x.rowKey === rowKey ) if (position) { scrollTop = position.top } // fix bug #470 setTimeout(() => { scrollTo(tableContainerRef, { top: scrollTop, behavior: 'auto' }) }, 200) } else { const rowEl = this.$el.querySelector( `tbody tr[${COMPS_CUSTOM_ATTRS.BODY_ROW_KEY}="${rowKey}"]` ) scrollTop = rowEl.offsetTop - headerTotalHeight } scrollTo(tableContainerRef, { top: scrollTop, behavior: isVirtualScroll ? 'auto' : 'smooth' }) }, // clear current cell rect [INSTANCE_METHODS.CLEAR_CURRENT_CELL_RECT] () { this.currentCellEl = null this.cellSelectionRect.currentCellRect = { left: 0, top: 0, width: 0, height: 0 } }, /* * @rowToVisible * @desc row to visible * @param {number} keyCode - current keyCode * @param {any} nextRowKey - next row key */ rowToVisible (keyCode, nextRowKey) { // const tableContainerRef = this.$refs[this.tableContainerRef]; const tableContainerRef = this[this.tableContainerRef] const tableContentWrapperRef = this.$refs[this.tableContentWrapperRef].$refs.table const { isVirtualScroll, headerTotalHeight, footerTotalHeight } = this const { clientHeight: containerClientHeight, scrollTop: containerScrollTop } = tableContainerRef const nextRowEl = this.$el.querySelector( `tbody tr[${COMPS_CUSTOM_ATTRS.BODY_ROW_KEY}="${nextRowKey}"]` ) // // console.log(208,nextRowEl) if (nextRowEl) { const { offsetTop: trOffsetTop, clientHeight: trClientHeight } = nextRowEl const parentOffsetTop = tableContentWrapperRef.offsetTop // arrow up if (keyCode === KEY_CODES.ARROW_UP) { let diff = 0 if (isVirtualScroll) { diff = headerTotalHeight - (trOffsetTop - (containerScrollTop - parentOffsetTop)) } else { diff = containerScrollTop + headerTotalHeight - trOffsetTop } if (diff > 0) { tableContainerRef.scrollTop = containerScrollTop - diff } } // arrow down else if (keyCode === KEY_CODES.ARROW_DOWN) { // console.log(652) let diff = 0 if (isVirtualScroll) { diff = trOffsetTop - (containerScrollTop - parentOffsetTop) + trClientHeight + footerTotalHeight - containerClientHeight } else { diff = trOffsetTop + trClientHeight + footerTotalHeight - (containerClientHeight + containerScrollTop) } if (diff >= 0) { tableContainerRef.scrollTop = containerScrollTop + diff } } const { currentCell } = this.cellSelectionData // // console.log(258,currentCell) this.cellSelectionCurrentCellChange({ rowKey: nextRowKey, colKey: currentCell.colKey }) } }, // cell selection current cell change cellSelectionCurrentCellChange ({ rowKey, colKey }) { // // console.log(266,this.cellSelectionData) this.cellSelectionData.currentCell.colKey = colKey this.cellSelectionData.currentCell.rowKey = rowKey this.cellSelectionData.currentCell.rowIndex = this.allRowKeys.indexOf(rowKey) }, // clear cell selection normal end cell clearCellSelectionNormalEndCell () { this.cellSelectionNormalEndCellChange({ rowKey: '', colKey: '', rowIndex: -1 }) }, // cell selection end cell change cellSelectionNormalEndCellChange ({ rowKey, colKey }) { this.cellSelectionData.normalEndCell.colKey = colKey this.cellSelectionData.normalEndCell.rowKey = rowKey this.cellSelectionData.normalEndCell.rowIndex = this.allRowKeys.indexOf(rowKey) }, // cell selection auto fill cell change cellSelectionAutofillCellChange ({ rowKey, colKey }) { this.cellSelectionData.autoFillEndCell.colKey = colKey this.cellSelectionData.autoFillEndCell.rowKey = rowKey }, clearBodyIndicatorRowKeys () { this.bodyIndicatorRowKeys.startRowKey = '' this.bodyIndicatorRowKeys.startRowKeyIndex = -1 this.bodyIndicatorRowKeys.endRowKey = '' this.bodyIndicatorRowKeys.endRowKeyIndex = -1 }, // set current cell el setCurrentCellEl () { const { cellSelectionData } = this const { rowKey, colKey } = cellSelectionData.currentCell if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) { const cellEl = this.getTableCellEl({ rowKey, colKey }) if (cellEl) { this.currentCellEl = cellEl } // // console.log(448,cellEl) } }, setNormalEndCellEl () { const { cellSelectionData } = this const { rowKey, colKey } = cellSelectionData.normalEndCell if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) { const cellEl = this.getTableCellEl({ rowKey, colKey }) if (cellEl) { this.normalEndCellEl = cellEl } } }, // set selection positions setSelectionPositions ({ type }) { const { allRowKeys, tableEl, currentCellEl, normalEndCellEl, autoFillEndCellEl, cellSelectionData, virtualScrollVisibleIndexs } = this // table empty if (allRowKeys.length === 0) { return false } if (!tableEl) { return false } const { left: tableLeft, top: tableTop } = tableEl.getBoundingClientRect() let isCurrentCellOverflow = false let isNormalEndCellOverflow = false // set current cell position if (type === 'currentCell') { isCurrentCellOverflow = true if (currentCellEl) { const rect = this.getCellPosition({ cellEl: currentCellEl, tableLeft, tableTop }) this.domRect = rect if (rect) { isCurrentCellOverflow = false this.cellSelectionRect.currentCellRect = rect } } } // set nromal end cell position` if (type === 'normalEndCell') { isNormalEndCellOverflow = true if (normalEndCellEl) { const rect = this.getCellPosition({ cellEl: normalEndCellEl, tableLeft, tableTop }) // // console.log('区域>>>',this.cellSelectionRect,rect) if (rect) { isNormalEndCellOverflow = false this.cellSelectionRect.normalEndCellRect = rect } } } // current cell overflow or normal end cell overflow && is virtual scroll if ( (isCurrentCellOverflow || isNormalEndCellOverflow) && this.isVirtualScroll ) { const { currentCell, normalEndCell } = cellSelectionData // 弥补的 let mackUpColKey let mackUpRowIndex if (isCurrentCellOverflow) { mackUpColKey = currentCell.colKey mackUpRowIndex = currentCell.rowIndex } else { mackUpColKey = normalEndCell.colKey mackUpRowIndex = normalEndCell.rowIndex } let mackUpRect /* 当没有 currentCellRect 或 normalCellRect 时 进行纠正,否则只更新top值 */ if ( (isCurrentCellOverflow && !this.cellSelectionRect.currentCellRect.height) || (isNormalEndCellOverflow && !this.cellSelectionRect.normalEndCellRect.height) ) { const mackUpRectParams = { tableLeft, tableTop, colKey: mackUpColKey } // 上方超出 if (mackUpRowIndex < virtualScrollVisibleIndexs.start) { mackUpRect = this.getCellPositionByColKey({ ...mackUpRectParams, isFirstRow: true }) } // 下方超出 else if (mackUpRowIndex > virtualScrollVisibleIndexs.end) { mackUpRect = this.getCellPositionByColKey({ ...mackUpRectParams, isLastRow: true }) } } // 仅更新 top 值 else { // 上方超出 if (mackUpRowIndex < virtualScrollVisibleIndexs.start) { mackUpRect = { top: 0 } } // 下方超出 else if (mackUpRowIndex > virtualScrollVisibleIndexs.end) { mackUpRect = { top: tableEl.clientHeight } } } if (isCurrentCellOverflow) { Object.assign( this.cellSelectionRect.currentCellRect, mackUpRect ) } else { Object.assign( this.cellSelectionRect.normalEndCellRect, mackUpRect ) } } if (autoFillEndCellEl && type === 'autoFillEndCell') { const rect = this.getCellPosition({ cellEl: autoFillEndCellEl, tableLeft, tableTop }) if (rect) { this.cellSelectionRect.autoFillEndCellRect = rect } } }, // get cell position getCellPosition ({ cellEl, tableLeft, tableTop }) { // // console.log('点击单元格',cellEl,tableLeft,tableTop) // if (!this.selectionBordersVisibility) { // return false; // } const { left: cellLeft, top: cellTop, height: cellHeight, width: cellWidth } = cellEl.getBoundingClientRect() // // console.log(605,cellEl.getBoundingClientRect(),this) if (cellHeight && cellWidth) { return { left: cellLeft - tableLeft, top: cellTop - tableTop, width: cellWidth, height: cellHeight } } }, // get table el getTableCellEl ({ rowKey, colKey }) { let result = null // const { tableEl } = this; const tableEl = this.$refs[this.tableContentWrapperRef].$refs.table // // console.log(566,tableEl) if (tableEl) { result = tableEl.querySelector( `tbody tr[rowid="${rowKey}"] td[colid="${colKey}"]` ) } return result }, getSelectionCurrent ({ fixedType }) { const result = { selectionCurrent: null, autoFillArea: null } const { cellSelectionRect, colgroups, cellSelectionData } = this const { currentCellRect, normalEndCellRect } = cellSelectionRect if (!currentCellRect.width) { return result } const borders = { borderWidth: currentCellRect.width + 1, borderHeight: currentCellRect.height, topBorder: { show: true, width: 0, height: 2, top: currentCellRect.top - 1, left: currentCellRect.left - 1 }, rightBorder: { show: true, width: 2, height: 0, top: currentCellRect.top, left: currentCellRect.left + currentCellRect.width - 2 }, bottomBorder: { show: true, width: 0, height: 2, top: currentCellRect.top + currentCellRect.height - 2, left: currentCellRect.left - 1 }, leftBorder: { show: true, width: 2, height: 0, top: currentCellRect.top, left: currentCellRect.left - 1 }, corner: { show: !normalEndCellRect.width, top: 0, left: 0 } } borders.corner.top = borders.bottomBorder.top - 3 borders.corner.left = borders.rightBorder.left - 3 // cell selection single autofill if (!normalEndCellRect.width) { result.autoFillArea = this.getSelectionAutofillArea({ areaPostions: borders, fixedType }) } const totalColKeys = [cellSelectionData.currentCell.colKey] const fixedColKeys = getColKeysByFixedTypeWithinColKeys({ colKeys: totalColKeys, fixedType, colgroups }) result.selectionCurrent = this.getBorders({ ...borders, showCorner: !normalEndCellRect.width, className: 'selection-current', fixedType, totalColKeys, fixedColKeys }) // // console.log(727,result.selectionCurrent) return result }, getSelectionAutofillArea ({ areaPostions, fixedType }) { let result = null // // console.log(903) const { cellAutofillOption, cellSelectionRangeData, cellSelectionRect, cellSelectionData, isAutofillStarting, currentCellSelectionType, colgroups } = this if (!isAutofillStarting) { return result } const { currentCellRect, autoFillEndCellRect } = cellSelectionRect if (!currentCellRect.width || !autoFillEndCellRect.width) { return result } if (!areaPostions) { return result } const borders = { borderWidth: 0, borderHeight: 0, topBorder: { show: true, width: 0, height: 1, top: 0, left: 0 }, rightBorder: { show: true, width: 1, height: 0, top: 0, left: 0 }, bottomBorder: { show: true, width: 0, height: 1, top: 0, left: 0 }, leftBorder: { show: true, width: 1, height: 0, top: 0, left: 0 }, corner: { show: false, top: 0, left: 0 } } const { currentCell, autoFillEndCell } = cellSelectionData let { leftColKey, rightColKey } = cellSelectionRangeData if ( currentCellSelectionType === CURRENT_CELL_SELECTION_TYPES.SINGLE ) { leftColKey = currentCell.colKey rightColKey = currentCell.colKey } let leftmostColKey if (leftColKey !== autoFillEndCell.colKey) { leftmostColKey = getLeftmostColKey({ colgroups, colKeys: [leftColKey, autoFillEndCell.colKey] }) } let rightmostColKey if (rightColKey !== autoFillEndCell.colKey) { rightmostColKey = getRightmostColKey({ colgroups, colKeys: [rightColKey, autoFillEndCell.colKey] }) } // autofilling direction let autofillingDirection let rangeColKey1 let rangeColKey2 // auto fill end cell below if (autoFillEndCellRect.top > areaPostions.bottomBorder.top) { autofillingDirection = AUTOFILLING_DIRECTION.DOWN rangeColKey1 = leftColKey rangeColKey2 = rightColKey borders.topBorder.show = false borders.borderWidth = areaPostions.borderWidth borders.borderHeight = autoFillEndCellRect.top - areaPostions.bottomBorder.top + autoFillEndCellRect.height borders.rightBorder.top = areaPostions.bottomBorder.top borders.rightBorder.left = areaPostions.rightBorder.left if ( currentCellSelectionType === CURRENT_CELL_SELECTION_TYPES.SINGLE ) { borders.rightBorder.left++ } borders.leftBorder.top = areaPostions.bottomBorder.top borders.leftBorder.left = areaPostions.leftBorder.left borders.bottomBorder.top = autoFillEndCellRect.top + autoFillEndCellRect.height - 1 borders.bottomBorder.left = areaPostions.bottomBorder.left } // end cell above else if (autoFillEndCellRect.top < areaPostions.topBorder.top) { autofillingDirection = AUTOFILLING_DIRECTION.UP rangeColKey1 = leftColKey rangeColKey2 = rightColKey borders.bottomBorder.show = false borders.borderWidth = areaPostions.borderWidth borders.borderHeight = areaPostions.topBorder.top - autoFillEndCellRect.top borders.topBorder.top = autoFillEndCellRect.top - 1 borders.topBorder.left = areaPostions.topBorder.left borders.rightBorder.top = autoFillEndCellRect.top borders.rightBorder.left = areaPostions.rightBorder.left if ( currentCellSelectionType === CURRENT_CELL_SELECTION_TYPES.SINGLE ) { borders.rightBorder.left++ } borders.leftBorder.top = autoFillEndCellRect.top borders.leftBorder.left = areaPostions.leftBorder.left } // auto fill end cell right else if ( rightmostColKey === autoFillEndCell.colKey && !isEmptyValue(rightmostColKey) ) { autofillingDirection = AUTOFILLING_DIRECTION.RIGHT rangeColKey1 = getNextColKey({ colgroups, currentColKey: rightColKey }) rangeColKey2 = autoFillEndCell.colKey borders.leftBorder.show = false borders.borderWidth = autoFillEndCellRect.left - areaPostions.rightBorder.left + autoFillEndCellRect.width + 1 borders.borderHeight = areaPostions.borderHeight borders.topBorder.top = areaPostions.topBorder.top borders.topBorder.left = areaPostions.rightBorder.left - 1 borders.rightBorder.top = areaPostions.topBorder.top borders.rightBorder.left = autoFillEndCellRect.left + autoFillEndCellRect.width - 1 borders.bottomBorder.top = areaPostions.bottomBorder.top borders.bottomBorder.left = areaPostions.rightBorder.left - 1 } // auto fill end cell left else if ( leftmostColKey === autoFillEndCell.colKey && !isEmptyValue(leftmostColKey) ) { autofillingDirection = AUTOFILLING_DIRECTION.LEFT rangeColKey1 = getPreviewColKey({ colgroups, currentColKey: leftColKey }) rangeColKey2 = autoFillEndCell.colKey borders.rightBorder.show = false borders.borderWidth = areaPostions.leftBorder.left - autoFillEndCellRect.left + 1 borders.borderHeight = areaPostions.borderHeight borders.topBorder.top = areaPostions.topBorder.top borders.topBorder.left = autoFillEndCellRect.left borders.rightBorder.left = areaPostions.topBorder.left borders.bottomBorder.top = areaPostions.bottomBorder.top borders.bottomBorder.left = autoFillEndCellRect.left borders.leftBorder.top = areaPostions.topBorder.top borders.leftBorder.left = autoFillEndCellRect.left } else { return result } const { directionX, directionY } = cellAutofillOption if (isBoolean(directionX) && !directionX) { if ( autofillingDirection === AUTOFILLING_DIRECTION.LEFT || autofillingDirection === AUTOFILLING_DIRECTION.RIGHT ) { return false } } if (isBoolean(directionY) && !directionY) { if ( autofillingDirection === AUTOFILLING_DIRECTION.UP || autofillingDirection === AUTOFILLING_DIRECTION.DOWN ) { return false } } const totalColKeys = getColKeysByRangeColKeys({ colKey1: rangeColKey1, colKey2: rangeColKey2, colgroups }) const fixedColKeys = getColKeysByFixedTypeWithinColKeys({ colKeys: totalColKeys, fixedType, colgroups }) result = this.getBorders({ className: 'selection-autofill-area', ...borders, fixedType, totalColKeys, fixedColKeys }) if (result) { this.$emit(EMIT_EVENTS.AUTOFILLING_DIRECTION_CHANGE, autofillingDirection) // this.dispatch( // COMPS_NAME.VE_TABLE, // EMIT_EVENTS.AUTOFILLING_DIRECTION_CHANGE, // autofillingDirection, // ); } // // console.log(1095,result) return result }, cornerCellInfo () { const { allRowKeys, colgroups, cellSelectionRangeData } = this const { rightColKey, bottomRowKey } = cellSelectionRangeData let isLastColumn = false if (isLastColumnByColKey(rightColKey, colgroups)) { isLastColumn = true } else { const index = colgroups.findIndex((x) => x.key === rightColKey) // right col is right fixed and current col is not right fixed if ( colgroups[index + 1].fixed === COLUMN_FIXED_TYPE.RIGHT && colgroups[index].fixed !== COLUMN_FIXED_TYPE.RIGHT ) { isLastColumn = true } } let isLastRow = false if (isLastRowByRowKey(bottomRowKey, allRowKeys)) { isLastRow = true } return { isLastColumn, isLastRow } }, getBorders ({ borderWidth, borderHeight, topBorder, rightBorder, bottomBorder, leftBorder, corner, className, fixedType, totalColKeys, fixedColKeys }) { const { cornerCellInfo, colgroups, isFirstSelectionRow, isFirstSelectionCol, isFirstNotFixedSelectionCol, showCorner } = this const scrollYStore = this.scrollYStore const startIndex = scrollYStore.startIndex const rowHeight = scrollYStore.rowHeight const topSpaceHeight = Math.max(0, startIndex * rowHeight) let isRender = true if (fixedType) { isRender = isExistGivenFixedColKey({ fixedType, colKeys: totalColKeys, colgroups }) } // middle normal area else { isRender = isExistNotFixedColKey({ colKeys: totalColKeys, colgroups }) } if (!isRender) { return null } // fixed columns total width let fixedColsTotalWidth = 0 if (fixedColKeys.length) { fixedColsTotalWidth = getTotalWidthByColKeys({ colKeys: fixedColKeys, colgroups }) } if (fixedType) { borderWidth = fixedColsTotalWidth if (fixedType === COLUMN_FIXED_TYPE.LEFT) { borderWidth += 1 } } if (fixedType === COLUMN_FIXED_TYPE.LEFT) { if (totalColKeys.length !== fixedColKeys.length) { rightBorder.show = false corner.show = false } } if (fixedType === COLUMN_FIXED_TYPE.RIGHT) { if (totalColKeys.length !== fixedColKeys.length) { leftBorder.show = false } topBorder.left = rightBorder.left - borderWidth + 1 bottomBorder.left = rightBorder.left - borderWidth + 1 } // solved first row、first column、first not fixed column selection border hidden if (isFirstSelectionRow) { topBorder.top += 1 } if (isFirstSelectionCol) { leftBorder.left += 1 } if (isFirstNotFixedSelectionCol) { leftBorder.left += 1 } let cornerTop = corner.top let cornerLeft = corner.left let cornerBorderRightWidth = '1px' let cornerBorderBottomtWidth = '1px' if (cornerCellInfo.isLastRow) { cornerTop -= 3 cornerBorderBottomtWidth = '0px' } if (cornerCellInfo.isLastColumn) { cornerLeft -= 3 cornerBorderRightWidth = '0px' } if (!showCorner) { corner.show = false } // corner props const cornerProps = { class: clsName('selection-corner'), style: { display: corner.show ? 'block' : 'none', top: topSpaceHeight ? cornerTop + topSpaceHeight + 'px' : cornerTop + 'px', left: cornerLeft + 'px', borderWidth: `1px ${cornerBorderRightWidth} ${cornerBorderBottomtWidth} 1px` }, on: { mousedown: (e) => { this.$emit(EMIT_EVENTS.SELECTION_CORNER_MOUSEDOWN, { event: e }) // this.dispatch( // 'VxeSelecteAreaDom', // EMIT_EVENTS.SELECTION_CORNER_MOUSEDOWN, // { // event: e, // }, // ); }, mouseup: (e) => { this.$emit(EMIT_EVENTS.SELECTION_CORNER_MOUSEUP, { event: e }) // this.dispatch( // 'VxeSelecteAreaDom', // EMIT_EVENTS.SELECTION_CORNER_MOUSEUP, // { // event: e, // }, // ); } } } // // console.log(1169,topBorder,corner) return h('div', { class: clsName(className) }, [h('div', { class: clsName('selection-border'), style: { display: topBorder.show ? 'block' : 'none', width: borderWidth + 'px', height: topBorder.height + 'px', top: topSpaceHeight ? topBorder.top + topSpaceHeight + 'px' : topBorder.top + 'px', left: topBorder.left + 'px' } }), h('div', { class: clsName('selection-border'), style: { display: rightBorder.show ? 'block' : 'none', width: rightBorder.width + 'px', height: borderHeight + 'px', top: topSpaceHeight ? rightBorder.top + topSpaceHeight + 'px' : rightBorder.top + 'px', left: rightBorder.left + 'px' } }), h('div', { class: clsName('selection-border'), style: { display: bottomBorder.show ? 'block' : 'none', width: borderWidth + 'px', height: bottomBorder.height + 'px', top: topSpaceHeight ? bottomBorder.top + topSpaceHeight + 'px' : bottomBorder.top + 'px', left: bottomBorder.left + 'px' } }), h('div', { class: clsName('selection-border'), style: { display: leftBorder.show ? 'block' : 'none', width: leftBorder.width + 'px', height: borderHeight + 'px', top: topSpaceHeight ? leftBorder.top + topSpaceHeight + 'px' : leftBorder.top + 'px', left: leftBorder.left + 'px' } }), h('div', { ...cornerProps })]) }, getSelectionAreas ({ fixedType }) { // // console.log('1234选中区域',fixedType) const result = { normalArea: null, autoFillArea: null } const { currentCell, normalEndCell } = this.cellSelectionData const { cellSelectionRect, cellSelectionRangeData, colgroups } = this const { currentCellRect, normalEndCellRect } = cellSelectionRect if (!currentCellRect.width || !normalEndCellRect.width) { // // console.log(1248,cellSelectionRect) return result } const borders = { borderWidth: 0, borderHeight: 0, topBorder: { show: true, width: 0, height: 1, top: 0, left: 0 }, rightBorder: { show: true, width: 1, height: 0, top: 0, left: 0 }, bottomBorder: { show: true, width: 0, height: 1, top: 0, left: 0 }, leftBorder: { show: true, width: 1, height: 0, top: 0, left: 0 }, corner: { show: true, top: 0, left: 0 } } const leftmostColKey = getLeftmostColKey({ colgroups: this.colgroups, colKeys: [currentCell.colKey, normalEndCell.colKey] }) // end cell column key right if (leftmostColKey === currentCell.colKey) { borders.borderWidth = normalEndCellRect.left - currentCellRect.left + normalEndCellRect.width + 1 borders.topBorder.left = currentCellRect.left - 1 borders.bottomBorder.left = currentCellRect.left - 1 borders.leftBorder.left = currentCellRect.left - 1 borders.rightBorder.left = normalEndCellRect.left + normalEndCellRect.width - 1 } // end cell column key left or equal else if (leftmostColKey === normalEndCell.colKey) { borders.borderWidth = currentCellRect.left - normalEndCellRect.left + currentCellRect.width + 1 borders.topBorder.left = normalEndCellRect.left - 1 borders.rightBorder.left = currentCellRect.left + currentCellRect.width - 1 borders.bottomBorder.left = normalEndCellRect.left - 1 borders.leftBorder.left = normalEndCellRect.left - 1 } // end cell below if (normalEndCellRect.top > currentCellRect.top) { borders.borderHeight = normalEndCellRect.top - currentCellRect.top + normalEndCellRect.height borders.topBorder.top = currentCellRect.top - 1 borders.rightBorder.top = currentCellRect.top borders.bottomBorder.top = normalEndCellRect.top + normalEndCellRect.height - 1 borders.leftBorder.top = currentCellRect.top } // end cell above or equal else if (normalEndCellRect.top <= currentCellRect.top) { borders.borderHeight = currentCellRect.top - normalEndCellRect.top + currentCellRect.height borders.topBorder.top = normalEndCellRect.top - 1 borders.rightBorder.top = normalEndCellRect.top borders.bottomBorder.top = currentCellRect.top + currentCellRect.height - 1 borders.leftBorder.top = normalEndCellRect.top } borders.corner.top = borders.bottomBorder.top - 4 borders.corner.left = borders.rightBorder.left - 4 if (normalEndCellRect.width) { result.autoFillArea = this.getSelectionAutofillArea({ areaPostions: borders, fixedType }) } const { leftColKey, rightColKey } = cellSelectionRangeData const totalColKeys = getColKeysByRangeColKeys({ colKey1: leftColKey, colKey2: rightColKey, colgroups }) // // console.log(14699999,totalColKeys,leftColKey,rightColKey) const fixedColKeys = getColKeysByFixedTypeWithinColKeys({ colKeys: totalColKeys, fixedType, colgroups }) result.normalArea = this.getBorders({ ...borders, className: 'selection-normal-area', fixedType, totalColKeys, fixedColKeys }) result.normalAreaLayer = this.getAreaLayer({ ...borders, className: 'selection-normal-area-layer', fixedType, totalColKeys, fixedColKeys }) // console.log(1665,result) return result }, getAreaLayer ({ borderWidth, borderHeight, topBorder, className, fixedType, totalColKeys, fixedColKeys }) { const { colgroups } = this const scrollYStore = this.scrollYStore const startIndex = scrollYStore.startIndex const rowHeight = scrollYStore.rowHeight const topSpaceHeight = Math.max(0, startIndex * rowHeight) let isRender = true if (fixedType) { isRender = isExistGivenFixedColKey({ fixedType, colKeys: totalColKeys, colgroups }) } // middle normal area else { isRender = isExistNotFixedColKey({ colKeys: totalColKeys, colgroups }) } // // console.log(152000000000000,totalColKeys,colgroups) if (!isRender) { return null } // fixed columns total width let fixedColsTotalWidth = 0 if (fixedColKeys.length) { fixedColsTotalWidth = getTotalWidthByColKeys({ colKeys: fixedColKeys, colgroups }) } if (fixedType) { borderWidth = fixedColsTotalWidth if (fixedType === COLUMN_FIXED_TYPE.LEFT) { borderWidth += 1 } } // // console.log(1540) return h('div', { class: clsName(className), style: { top: topSpaceHeight ? topBorder.top + topSpaceHeight + 'px' : topBorder.top + 'px', left: topBorder.left + 'px', width: borderWidth + 'px', height: borderHeight + 'px' } }) }, bodyCellMouseover ({ event, params }) { const { rowKeyFieldName, isBodyCellMousedown, isAutofillStarting, isHeaderCellMousedown, isBodyOperationColumnMousedown, getRowid } = this // const rowKey = getRowKey(rowData, rowKeyFieldName); const { row, column } = params const rowKey = getRowid(row) const colKey = column.id if (isBodyCellMousedown) { // 操作列不能单元格选中 if (isOperationColumn(colKey, this.colgroups)) { return false } this.cellSelectionNormalEndCellChange({ rowKey, colKey }) } if (isBodyOperationColumnMousedown) { this.bodyIndicatorRowKeysChange({ startRowKey: this.bodyIndicatorRowKeys.startRowKey, endRowKey: rowKey }) } // 允许在body cell mouseover 里补充 header indicator 信息 if (isHeaderCellMousedown) { this.headerIndicatorColKeysChange({ startColKey: this.headerIndicatorColKeys.startColKey, endColKey: colKey }) } if (isAutofillStarting) { // 操作列不能autofilling 效果 if (isOperationColumn(colKey, this.colgroups)) {