diff --git a/examples/views/table/TableTest2.vue b/examples/views/table/TableTest2.vue
index 243a81f6eb..3abc4b6b1f 100644
--- a/examples/views/table/TableTest2.vue
+++ b/examples/views/table/TableTest2.vue
@@ -13,8 +13,9 @@
ref="tableRef"
id="bbbbb"
:row-config="{useKey: true,drag:true}"
+ :row-drag-config="{trigger:'row',disabledMethod:disabledRowMethod}"
:column-config="{useKey: true,drag: true}"
- :column-drag-config="{isCrossDrag:true,isToChildDrag:true,isSelfToChildDrag:true}"
+ :column-drag-config="{isCrossDrag:true,isToChildDrag:true,isSelfToChildDrag:true,trigger:'default',disabledMethod:disabledColumnMethod}"
:custom-config="customConfig"
:loading="demo1.loading"
:import-config="{modes: importModes}"
@@ -38,10 +39,10 @@
-
-
+
+
-
+
item.value === cellValue)
return item ? item.label : ''
diff --git a/package.json b/package.json
index c73481cc92..214ed40e54 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "vxe-table",
- "version": "3.11.31",
+ "version": "3.11.32",
"description": "一个基于 vue 的 PC 端表格组件,支持增删改查、虚拟树、拖拽排序,懒加载、快捷菜单、数据校验、树形结构、打印、导入导出、自定义模板、渲染器、JSON 配置式...",
"scripts": {
"update": "npm install --legacy-peer-deps",
@@ -28,7 +28,7 @@
"style": "lib/style.css",
"typings": "types/index.d.ts",
"dependencies": {
- "vxe-pc-ui": "^3.3.35"
+ "vxe-pc-ui": "^3.3.36"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.25.7",
diff --git a/packages/table/module/keyboard/mixin.ts b/packages/table/module/keyboard/mixin.ts
index 21e9a29b65..ec38b87a3e 100644
--- a/packages/table/module/keyboard/mixin.ts
+++ b/packages/table/module/keyboard/mixin.ts
@@ -1,5 +1,5 @@
import XEUtils from 'xe-utils'
-import { browse, hasClass, getAbsolutePos, addClass, removeClass, getEventTargetNode } from '../../../ui/src/dom'
+import { browse, hasClass, getAbsolutePos, addClass, removeClass } from '../../../ui/src/dom'
function getTargetOffset (target: any, container: any) {
let offsetTop = 0
@@ -186,31 +186,6 @@ export default {
this.handleSelected(params, evnt)
})
},
- /**
- * 表头单元格按下事件
- */
- triggerHeaderCellMousedownEvent (evnt: any, params: any) {
- const { mouseConfig, mouseOpts } = this
- if (mouseConfig && mouseOpts.area && this.handleHeaderCellAreaEvent) {
- const cell = evnt.currentTarget
- const triggerSort = getEventTargetNode(evnt, cell, 'vxe-cell--sort').flag
- const triggerFilter = getEventTargetNode(evnt, cell, 'vxe-cell--filter').flag
- this.handleHeaderCellAreaEvent(evnt, Object.assign({ cell, triggerSort, triggerFilter }, params))
- }
- this.focus()
- this.closeMenu()
- },
- /**
- * 单元格按下事件
- */
- triggerCellMousedownEvent (evnt: any, params: any) {
- const cell = evnt.currentTarget
- params.cell = cell
- this.handleCellMousedownEvent(evnt, params)
- this.focus()
- this.closeFilter()
- this.closeMenu()
- },
handleCellMousedownEvent (evnt: any, params: any) {
const { editConfig, editOpts, handleSelected, checkboxConfig, checkboxOpts, mouseConfig, mouseOpts } = this
if (mouseConfig && mouseOpts.area && this.handleMousedownCellAreaEvent) {
diff --git a/packages/table/src/body.ts b/packages/table/src/body.ts
index b326baab7e..89ae7af7e3 100644
--- a/packages/table/src/body.ts
+++ b/packages/table/src/body.ts
@@ -93,6 +93,8 @@ function renderColumn (h: any, _vm: any, $xetable: any, seq: any, rowid: any, fi
areaOpts,
validErrorMaps
} = $xetable
+ const rowDragOpts = $xetable.computeRowDragOpts
+ const { disabledMethod: dragDisabledMethod } = rowDragOpts
const { selectCellToRow } = areaOpts
const cellOpts = $xetable.computeCellOpts
const { type, cellRender, editRender, align, showOverflow, className, treeNode, slots } = column
@@ -126,6 +128,14 @@ function renderColumn (h: any, _vm: any, $xetable: any, seq: any, rowid: any, fi
const bindMouseleave = tableListeners['cell-mouseleave']
const triggerDblclick = (editRender && editConfig && editOpts.trigger === 'dblclick')
const params = { $table: $xetable, $grid: $xetable.$xegrid, isEdit: false, seq, rowid, row, rowIndex, $rowIndex, _rowIndex, column, columnIndex, $columnIndex, _columnIndex, fixed: fixedType, type: renderType, isHidden: fixedHiddenColumn, level: rowLevel, visibleData: afterFullData, data: tableData, items }
+ let isColDragCell = false
+ let isDisabledDrag = false
+ if (rowOpts.drag) {
+ isColDragCell = rowDragOpts.trigger === 'row' || (column.dragSort && rowDragOpts.trigger === 'cell')
+ }
+ if (isColDragCell) {
+ isDisabledDrag = !!(dragDisabledMethod && dragDisabledMethod(params))
+ }
// hover 进入事件
if (showTitle || showTooltip || showAllTip || bindMouseenter || tooltipConfig) {
tdOns.mouseenter = (evnt: any) => {
@@ -158,7 +168,7 @@ function renderColumn (h: any, _vm: any, $xetable: any, seq: any, rowid: any, fi
}
}
// 按下事件处理
- if (checkboxOpts.range || mouseConfig) {
+ if (isColDragCell || checkboxOpts.range || mouseConfig) {
tdOns.mousedown = (evnt: any) => {
$xetable.triggerCellMousedownEvent(evnt, params)
}
@@ -314,6 +324,8 @@ function renderColumn (h: any, _vm: any, $xetable: any, seq: any, rowid: any, fi
'col--edit': isEdit,
'col--ellipsis': hasEllipsis,
'fixed--hidden': fixedHiddenColumn,
+ 'is--drag-cell': isColDragCell,
+ 'is--drag-disabled': isDisabledDrag,
'col--dirty': isDirty,
'col--active': editConfig && isEdit && (actived.row === row && (actived.column === column || editOpts.mode === 'row')),
'col--valid-error': !!errorValidItem,
diff --git a/packages/table/src/cell.ts b/packages/table/src/cell.ts
index 3d5c01fede..a29c24cc5c 100644
--- a/packages/table/src/cell.ts
+++ b/packages/table/src/cell.ts
@@ -53,22 +53,24 @@ function renderCellDragIcon (h: CreateElement, params: any) {
const tableProps = $table
const { dragConfig } = tableProps
const rowDragOpts = $table.computeRowDragOpts
- const { icon, disabledMethod } = rowDragOpts
+ const { icon, trigger, disabledMethod } = rowDragOpts
const rDisabledMethod = disabledMethod || (dragConfig ? dragConfig.rowDisabledMethod : null)
const isDisabled = rDisabledMethod && rDisabledMethod(params)
+ const ons: Record = {}
+ if (trigger !== 'cell') {
+ ons.mousedown = (evnt: MouseEvent) => {
+ if (!isDisabled) {
+ $table.handleCellDragMousedownEvent(evnt, params)
+ }
+ }
+ ons.mouseup = $table.handleCellDragMouseupEvent
+ }
return h('span', {
key: 'dg',
class: ['vxe-cell--drag-handle', {
'is--disabled': isDisabled
}],
- on: {
- mousedown (evnt: DragEvent) {
- if (!isDisabled) {
- $table.handleCellDragMousedownEvent(evnt, params)
- }
- },
- mouseup: $table.handleCellDragMouseupEvent
- }
+ on: ons
}, [
h('i', {
class: icon || (dragConfig ? dragConfig.rowIcon : '') || getIcon().TABLE_DRAG_ROW
@@ -106,23 +108,25 @@ function renderHeaderCellDragIcon (h: CreateElement, params: VxeTableDefines.Cel
const { $table, column } = params
const columnOpts = $table.computeColumnOpts
const columnDragOpts = $table.computeColumnDragOpts
- const { showIcon, icon, isCrossDrag, visibleMethod, disabledMethod } = columnDragOpts
- const isDisabled = disabledMethod && disabledMethod(params)
+ const { showIcon, icon, trigger, isCrossDrag, visibleMethod, disabledMethod } = columnDragOpts
if (columnOpts.drag && showIcon && (!visibleMethod || visibleMethod(params))) {
if (!column.fixed && (isCrossDrag || !column.parentId)) {
+ const isDisabled = disabledMethod && disabledMethod(params)
+ const ons: Record = {}
+ if (trigger !== 'cell') {
+ ons.mousedown = (evnt: MouseEvent) => {
+ if (!isDisabled) {
+ $table.handleHeaderCellDragMousedownEvent(evnt, params)
+ }
+ }
+ ons.mouseup = $table.handleHeaderCellDragMouseupEvent
+ }
return h('span', {
key: 'dg',
class: ['vxe-cell--drag-handle', {
'is--disabled': isDisabled
}],
- on: {
- mousedown (evnt: MouseEvent) {
- if (!isDisabled) {
- $table.handleHeaderCellDragMousedownEvent(evnt, params)
- }
- },
- mouseup: $table.handleHeaderCellDragMouseupEvent
- }
+ on: ons
}, [
h('i', {
class: icon || getIcon().TABLE_DRAG_COLUMN
diff --git a/packages/table/src/header.ts b/packages/table/src/header.ts
index 17559feef4..e4de97f0ca 100644
--- a/packages/table/src/header.ts
+++ b/packages/table/src/header.ts
@@ -12,9 +12,14 @@ const { renderer } = VxeUI
const cellType = 'header'
const renderRows = (h: CreateElement, _vm: any, cols: VxeTableDefines.ColumnInfo[], $rowIndex: number) => {
- const { $parent: $xetable, fixedType } = _vm
- const { $listeners: tableListeners, resizable: allResizable, border, columnKey, headerCellClassName, headerCellStyle, showHeaderOverflow: allColumnHeaderOverflow, headerAlign: allHeaderAlign, align: allAlign, highlightCurrentColumn, currentColumn, scrollXLoad, overflowX, scrollbarWidth, sortOpts, mouseConfig, columnOpts } = $xetable
+ const $xeTable = _vm.$parent
+ const $xeGrid = $xeTable.xegrid
+ const { fixedType } = _vm
+
+ const { resizable: allResizable, border, columnKey, headerCellClassName, headerCellStyle, showHeaderOverflow: allColumnHeaderOverflow, headerAlign: allHeaderAlign, align: allAlign, currentColumn, scrollXLoad, overflowX, scrollbarWidth, mouseConfig, columnOpts } = $xeTable
+ const columnDragOpts = $xeTable.computeColumnDragOpts
+ const { disabledMethod: dragDisabledMethod } = columnDragOpts
return cols.map((column: any, $columnIndex: any) => {
const { type, showHeaderOverflow, headerAlign, align, headerClassName, editRender, cellRender } = column
// const { enabled } = tooltipOpts
@@ -29,30 +34,40 @@ const renderRows = (h: CreateElement, _vm: any, cols: VxeTableDefines.ColumnInfo
const showTitle = headOverflow === 'title'
const showTooltip = headOverflow === true || headOverflow === 'tooltip'
let hasEllipsis = showTitle || showTooltip || showEllipsis
- const thOns: any = {}
const hasFilter = column.filters && column.filters.some((item: any) => item.checked)
- const columnIndex = $xetable.getColumnIndex(column)
- const _columnIndex = $xetable.getVTColumnIndex(column)
- const params = { $table: $xetable, $grid: $xetable.xegrid, $rowIndex, column, columnIndex, $columnIndex, _columnIndex, fixed: fixedType, type: cellType, isHidden: fixedHiddenColumn, hasFilter }
+ const columnIndex = $xeTable.getColumnIndex(column)
+ const _columnIndex = $xeTable.getVTColumnIndex(column)
+ const params = { $table: $xeTable, $grid: $xeGrid, $rowIndex, column, columnIndex, $columnIndex, _columnIndex, fixed: fixedType, type: cellType, isHidden: fixedHiddenColumn, hasFilter }
+ const thAttrs: Record = {
+ colid,
+ colspan: column.colSpan > 1 ? column.colSpan : null,
+ rowspan: column.rowSpan > 1 ? column.rowSpan : null
+ }
+ const thOns: any = {
+ click: (evnt: MouseEvent) => $xeTable.triggerHeaderCellClickEvent(evnt, params),
+ dblclick: (evnt: MouseEvent) => $xeTable.triggerHeaderCellDblclickEvent(evnt, params)
+ }
// 虚拟滚动不支持动态高度
if (scrollXLoad && !hasEllipsis) {
showEllipsis = hasEllipsis = true
}
- if (columnOpts.isCurrent || highlightCurrentColumn || tableListeners['header-cell-click'] || sortOpts.trigger === 'cell') {
- thOns.click = (evnt: any) => $xetable.triggerHeaderCellClickEvent(evnt, params)
- }
- if (tableListeners['header-cell-dblclick']) {
- thOns.dblclick = (evnt: any) => $xetable.triggerHeaderCellDblclickEvent(evnt, params)
+ const isColDragCell = columnOpts.drag && columnDragOpts.trigger === 'cell'
+ let isDisabledDrag = false
+ if (isColDragCell) {
+ isDisabledDrag = !!(dragDisabledMethod && dragDisabledMethod(params))
}
// 按下事件处理
- if (mouseConfig) {
- thOns.mousedown = (evnt: any) => $xetable.triggerHeaderCellMousedownEvent(evnt, params)
+ if (mouseConfig || isColDragCell) {
+ thOns.mousedown = (evnt: any) => $xeTable.triggerHeaderCellMousedownEvent(evnt, params)
}
- // 拖拽行事件
+ // 拖拽列事件
if (columnOpts.drag) {
- thOns.dragstart = $xetable.handleHeaderCellDragDragstartEvent
- thOns.dragend = $xetable.handleHeaderCellDragDragendEvent
- thOns.dragover = $xetable.handleHeaderCellDragDragoverEvent
+ thOns.dragstart = $xeTable.handleHeaderCellDragDragstartEvent
+ thOns.dragend = $xeTable.handleHeaderCellDragDragendEvent
+ thOns.dragover = $xeTable.handleHeaderCellDragDragoverEvent
+ if (isColDragCell) {
+ thOns.mouseup = $xeTable.handleHeaderCellDragMouseupEvent
+ }
}
return h('th', {
class: ['vxe-header--column', colid, {
@@ -66,13 +81,10 @@ const renderRows = (h: CreateElement, _vm: any, cols: VxeTableDefines.ColumnInfo
'is--sortable': column.sortable,
'col--filter': !!column.filters,
'is--filter-active': hasFilter,
+ 'is--drag-disabled': isDisabledDrag,
'col--current': currentColumn === column
}, getClass(headerClassName, params), getClass(headerCellClassName, params)],
- attrs: {
- colid,
- colspan: column.colSpan > 1 ? column.colSpan : null,
- rowspan: column.rowSpan > 1 ? column.rowSpan : null
- },
+ attrs: thAttrs,
style: headerCellStyle ? (XEUtils.isFunction(headerCellStyle) ? headerCellStyle(params) : headerCellStyle) : null,
on: thOns,
key: columnKey || columnOpts.useKey || columnOpts.drag || isColGroup ? colid : $columnIndex
diff --git a/packages/table/src/methods.ts b/packages/table/src/methods.ts
index 0399949da5..2c68c5696d 100644
--- a/packages/table/src/methods.ts
+++ b/packages/table/src/methods.ts
@@ -5156,6 +5156,79 @@ const Methods = {
$xeTable.handleColumnSortEvent(evnt, column)
}
},
+ /**
+ * 表头单元格按下事件
+ */
+ triggerHeaderCellMousedownEvent (evnt: any, params: any) {
+ const $xeTable = this
+ const props = $xeTable
+
+ const { mouseConfig } = props
+ const mouseOpts = $xeTable.computeMouseOpts
+ const columnOpts = $xeTable.computeColumnOpts
+ const columnDragOpts = $xeTable.computeColumnDragOpts
+ const { trigger, disabledMethod } = columnDragOpts
+ const cell = evnt.currentTarget
+ const triggerInput = cell && cell.tagName && cell.tagName.toLowerCase() === 'input'
+ const triggerCheckbox = getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag
+ const triggerSort = getEventTargetNode(evnt, cell, 'vxe-cell--sort').flag
+ const triggerFilter = getEventTargetNode(evnt, cell, 'vxe-cell--filter').flag
+ let triggerDrag = false
+ if (!(triggerInput || triggerCheckbox || triggerSort || triggerFilter)) {
+ if (columnOpts.drag && trigger === 'cell' && !(disabledMethod && disabledMethod(params))) {
+ triggerDrag = true
+ $xeTable.handleHeaderCellDragMousedownEvent(evnt, params)
+ }
+ }
+ if (!triggerDrag && mouseConfig && mouseOpts.area && $xeTable.handleHeaderCellAreaEvent) {
+ $xeTable.handleHeaderCellAreaEvent(evnt, Object.assign({ cell, triggerSort, triggerFilter }, params))
+ }
+ $xeTable.focus()
+ if ($xeTable.closeMenu) {
+ $xeTable.closeMenu()
+ }
+ },
+ /**
+ * 单元格按下事件
+ */
+ triggerCellMousedownEvent (evnt: any, params: any) {
+ const $xeTable = this
+
+ const { column } = params
+ const { type, treeNode } = column
+ const isRadioType = type === 'radio'
+ const isCheckboxType = type === 'checkbox'
+ const isExpandType = type === 'expand'
+ const rowOpts = $xeTable.computeRowOpts
+ const rowDragOpts = $xeTable.computeRowDragOpts
+ const { trigger, disabledMethod } = rowDragOpts
+ const cell = evnt.currentTarget
+ params.cell = cell
+ const triggerInput = cell && cell.tagName && cell.tagName.toLowerCase() === 'input'
+ const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag
+ const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag
+ const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-tree--btn-wrapper').flag
+ const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag
+ let isColDragCell = false
+ if (rowOpts.drag) {
+ isColDragCell = trigger === 'row' || (column.dragSort && trigger === 'cell')
+ }
+ let triggerDrag = false
+ if (!(triggerInput || triggerRadio || triggerCheckbox || triggerTreeNode || triggerExpandNode)) {
+ if (isColDragCell && !(disabledMethod && disabledMethod(params))) {
+ triggerDrag = true
+ $xeTable.handleCellDragMousedownEvent(evnt, params)
+ }
+ }
+ if (!triggerDrag && $xeTable.handleCellMousedownEvent) {
+ $xeTable.handleCellMousedownEvent(evnt, params)
+ }
+ $xeTable.focus()
+ $xeTable.closeFilter()
+ if ($xeTable.closeMenu) {
+ $xeTable.closeMenu()
+ }
+ },
/**
* 行拖拽
*/
@@ -5395,12 +5468,13 @@ const Methods = {
const props = $xeTable
const reactData = $xeTable
+ evnt.stopPropagation()
const { dragConfig } = props
const rowDragOpts = $xeTable.computeRowDragOpts
- const { dragStartMethod } = rowDragOpts
+ const { trigger, dragStartMethod } = rowDragOpts
const { row } = params
const dragEl = evnt.currentTarget as HTMLElement
- const tdEl = dragEl.parentElement?.parentElement as HTMLElement
+ const tdEl = trigger === 'cell' || trigger === 'row' ? dragEl : dragEl.parentElement?.parentElement as HTMLElement
const trEl = tdEl.parentElement as HTMLElement
const dStartMethod = dragStartMethod || (dragConfig ? dragConfig.dragStartMethod : null)
reactData.isDragRowMove = false
@@ -5652,11 +5726,12 @@ const Methods = {
const $xeTable = this
const reactData = $xeTable
+ evnt.stopPropagation()
const columnDragOpts = $xeTable.computeColumnDragOpts
- const { dragStartMethod } = columnDragOpts
+ const { trigger, dragStartMethod } = columnDragOpts
const { column } = params
const dragEl = evnt.currentTarget as HTMLElement
- const thEl = dragEl.parentElement?.parentElement as HTMLElement
+ const thEl = trigger === 'cell' ? dragEl : dragEl.parentElement?.parentElement as HTMLElement
reactData.isDragColMove = false
clearColDropOrigin($xeTable)
if (dragStartMethod && !dragStartMethod(params)) {
diff --git a/packages/table/src/table.ts b/packages/table/src/table.ts
index d10b047c54..42c152faa8 100644
--- a/packages/table/src/table.ts
+++ b/packages/table/src/table.ts
@@ -1072,7 +1072,7 @@ export default {
if (this.editRules && !this._validate) {
errLog('vxe.error.reqModule', ['Validator'])
}
- if ((this.checkboxOpts.range || this.keyboardConfig || this.mouseConfig) && !this.triggerCellMousedownEvent) {
+ if ((this.checkboxOpts.range || this.keyboardConfig || this.mouseConfig) && !this.handleCellMousedownEvent) {
errLog('vxe.error.reqModule', ['Keyboard'])
}
if ((this.printConfig || this.importConfig || this.exportConfig) && !this._exportData) {
@@ -1253,6 +1253,7 @@ export default {
const virtualScrollBars = $xeTable.computeVirtualScrollBars
const isArea = mouseConfig && mouseOpts.area
const tableStyle = $xeTable.computeTableStyle
+ const columnDragOpts = $xeTable.computeColumnDragOpts
return h('div', {
ref: 'refElem',
class: ['vxe-table', 'vxe-table--render-default', `tid_${tId}`, vSize ? `size--${vSize}` : '', `border--${tableBorder}`, {
@@ -1268,6 +1269,7 @@ export default {
'column--highlight': columnOpts.isHover || highlightHoverColumn,
'checkbox--range': checkboxOpts.range,
'column--calc': isCalcColumn,
+ 'col--drag-cell': columnOpts.drag && columnDragOpts.trigger === 'cell',
'is--header': showHeader,
'is--footer': showFooter,
'is--group': isGroup,
diff --git a/styles/components/table.scss b/styles/components/table.scss
index 7d68c429e9..c02d5d5fc0 100644
--- a/styles/components/table.scss
+++ b/styles/components/table.scss
@@ -677,6 +677,24 @@
}
}
}
+ &.col--drag-cell {
+ .vxe-header--column {
+ user-select: none;
+ &:not(.is--drag-disabled) {
+ cursor: grab;
+ &:active {
+ cursor: grabbing;
+ }
+ &:hover {
+ color: var(--vxe-ui-font-primary-color);
+ }
+ }
+ &.is--drag-disabled {
+ color: var(--vxe-ui-input-disabled-color);
+ cursor: not-allowed;
+ }
+ }
+ }
&.column--highlight {
.vxe-header--column {
&:not(.col--seq) {
@@ -1368,6 +1386,24 @@
}
}
}
+ .vxe-body--column {
+ &.is--drag-cell {
+ user-select: none;
+ &:not(.is--drag-disabled) {
+ cursor: grab;
+ &:active {
+ cursor: grabbing;
+ }
+ &:hover {
+ color: var(--vxe-ui-font-primary-color);
+ }
+ }
+ &.is--drag-disabled {
+ color: var(--vxe-ui-input-disabled-color);
+ cursor: not-allowed;
+ }
+ }
+ }
.vxe-body--row-list-move {
transition-property: transform;
transition-duration: 0.35s;