diff --git a/examples/views/table/TableTest2.vue b/examples/views/table/TableTest2.vue
index 6a82c9484b..9513cb9822 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}"
@@ -40,8 +41,8 @@
-
-
+
+
{
}, 100)
})
+const disabledColumnMethod = ({ column }: any) => {
+ return column.field === 'sex11'
+}
+
+const disabledRowMethod = ({ row }: any) => {
+ return row.id === 10002
+}
+
const rowDragstartEvent = (params: any) => {
console.log(params)
}
diff --git a/package.json b/package.json
index 7ddc354186..b54ef22d8e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "vxe-table",
- "version": "4.9.27",
+ "version": "4.9.28",
"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": "^4.3.32"
+ "vxe-pc-ui": "^4.3.33"
},
"devDependencies": {
"@types/resize-observer-browser": "^0.1.11",
diff --git a/packages/table/module/keyboard/hook.ts b/packages/table/module/keyboard/hook.ts
index 3fe59b1eeb..fcdcc2ba6d 100644
--- a/packages/table/module/keyboard/hook.ts
+++ b/packages/table/module/keyboard/hook.ts
@@ -1,7 +1,7 @@
import XEUtils from 'xe-utils'
import { VxeUI } from '../../../ui'
import { getRefElem } from '../../src/util'
-import { browse, hasClass, getAbsolutePos, addClass, removeClass, getEventTargetNode } from '../../../ui/src/dom'
+import { browse, hasClass, getAbsolutePos, addClass, removeClass } from '../../../ui/src/dom'
import type { TableKeyboardPrivateMethods } from '../../../../types'
@@ -373,36 +373,7 @@ hooks.add('tableKeyboardModule', {
$xeTable.handleSelected(params, evnt)
})
},
- /**
- * 表头单元格按下事件
- */
- triggerHeaderCellMousedownEvent (evnt, params) {
- const { mouseConfig } = props
- const mouseOpts = computeMouseOpts.value
- if (mouseConfig && mouseOpts.area && $xeTable.handleHeaderCellAreaEvent) {
- const cell = evnt.currentTarget
- const triggerSort = getEventTargetNode(evnt, cell, 'vxe-cell--sort').flag
- const triggerFilter = getEventTargetNode(evnt, cell, 'vxe-cell--filter').flag
- $xeTable.handleHeaderCellAreaEvent(evnt, Object.assign({ cell, triggerSort, triggerFilter }, params))
- }
- $xeTable.focus()
- if ($xeTable.closeMenu) {
- $xeTable.closeMenu()
- }
- },
- /**
- * 单元格按下事件
- */
- triggerCellMousedownEvent (evnt, params) {
- const cell = evnt.currentTarget
- params.cell = cell
- handleCellMousedownEvent(evnt, params)
- $xeTable.focus()
- $xeTable.closeFilter()
- if ($xeTable.closeMenu) {
- $xeTable.closeMenu()
- }
- }
+ handleCellMousedownEvent
}
return keyboardMethods
diff --git a/packages/table/src/body.ts b/packages/table/src/body.ts
index 0e1f83be02..e3efc48027 100644
--- a/packages/table/src/body.ts
+++ b/packages/table/src/body.ts
@@ -36,7 +36,7 @@ export default defineComponent({
const { xID, props: tableProps, context: tableContext, reactData: tableReactData, internalData: tableInternalData } = $xeTable
const { refTableBody, refTableHeader, refTableFooter, refTableLeftBody, refTableRightBody, refScrollXHandleElem, refScrollYHandleElem } = $xeTable.getRefMaps()
- const { computeEditOpts, computeMouseOpts, computeAreaOpts, computeSYOpts, computeEmptyOpts, computeKeyboardOpts, computeTooltipOpts, computeRadioOpts, computeExpandOpts, computeTreeOpts, computeCheckboxOpts, computeCellOpts, computeValidOpts, computeRowOpts, computeColumnOpts } = $xeTable.getComputeMaps()
+ const { computeEditOpts, computeMouseOpts, computeAreaOpts, computeSYOpts, computeEmptyOpts, computeKeyboardOpts, computeTooltipOpts, computeRadioOpts, computeExpandOpts, computeTreeOpts, computeCheckboxOpts, computeCellOpts, computeValidOpts, computeRowOpts, computeColumnOpts, computeRowDragOpts } = $xeTable.getComputeMaps()
const refElem = ref() as Ref
const refBodyTable = ref() as Ref
@@ -140,6 +140,8 @@ export default defineComponent({
const editOpts = computeEditOpts.value
const tooltipOpts = computeTooltipOpts.value
const rowOpts = computeRowOpts.value
+ const rowDragOpts = computeRowDragOpts.value
+ const { disabledMethod: dragDisabledMethod } = rowDragOpts
const sYOpts = computeSYOpts.value
const columnOpts = computeColumnOpts.value
const mouseOpts = computeMouseOpts.value
@@ -195,6 +197,14 @@ export default defineComponent({
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 || tooltipConfig) {
tdOns.onMouseenter = (evnt: MouseEvent) => {
@@ -223,7 +233,7 @@ export default defineComponent({
}
}
// 按下事件处理
- if (checkboxOpts.range || mouseConfig) {
+ if (isColDragCell || checkboxOpts.range || mouseConfig) {
tdOns.onMousedown = (evnt: MouseEvent) => {
$xeTable.triggerCellMousedownEvent(evnt, params)
}
@@ -367,6 +377,8 @@ export default defineComponent({
'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 aa73304888..edf7522363 100644
--- a/packages/table/src/cell.ts
+++ b/packages/table/src/cell.ts
@@ -50,20 +50,24 @@ function renderCellDragIcon (params: VxeTableDefines.CellRenderBodyParams) {
const { dragConfig } = tableProps
const { computeRowDragOpts } = $table.getComputeMaps()
const rowDragOpts = computeRowDragOpts.value
- 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.onMousedown = (evnt: MouseEvent) => {
+ if (!isDisabled) {
+ $table.handleCellDragMousedownEvent(evnt, params)
+ }
+ }
+ ons.onMouseup = $table.handleCellDragMouseupEvent
+ }
return h('span', {
key: 'dg',
class: ['vxe-cell--drag-handle', {
'is--disabled': isDisabled
}],
- onMousedown (evnt) {
- if (!isDisabled) {
- $table.handleCellDragMousedownEvent(evnt, params)
- }
- },
- onMouseup: $table.handleCellDragMouseupEvent
+ ...ons
}, [
h('i', {
class: icon || (dragConfig ? dragConfig.rowIcon : '') || getIcon().TABLE_DRAG_ROW
@@ -103,21 +107,25 @@ function renderHeaderCellDragIcon (params: VxeTableDefines.CellRenderHeaderParam
const { computeColumnOpts, computeColumnDragOpts } = $table.getComputeMaps()
const columnOpts = computeColumnOpts.value
const columnDragOpts = computeColumnDragOpts.value
- 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.onMousedown = (evnt: MouseEvent) => {
+ if (!isDisabled) {
+ $table.handleHeaderCellDragMousedownEvent(evnt, params)
+ }
+ }
+ ons.onMouseup = $table.handleHeaderCellDragMouseupEvent
+ }
return h('span', {
key: 'dg',
class: ['vxe-cell--drag-handle', {
'is--disabled': isDisabled
}],
- onMousedown (evnt) {
- if (!isDisabled) {
- $table.handleHeaderCellDragMousedownEvent(evnt, params)
- }
- },
- onMouseup: $table.handleHeaderCellDragMouseupEvent
+ ...ons
}, [
h('i', {
class: icon || getIcon().TABLE_DRAG_COLUMN
diff --git a/packages/table/src/header.ts b/packages/table/src/header.ts
index 2b6d11de7f..8746090bdb 100644
--- a/packages/table/src/header.ts
+++ b/packages/table/src/header.ts
@@ -27,7 +27,7 @@ export default defineComponent({
const { xID, props: tableProps, reactData: tableReactData, internalData: tableInternalData } = $xeTable
const { refElem: tableRefElem, refTableBody, refLeftContainer, refRightContainer, refCellResizeBar, refCellResizeTip } = $xeTable.getRefMaps()
- const { computeColumnOpts, computeResizableOpts } = $xeTable.getComputeMaps()
+ const { computeColumnOpts, computeColumnDragOpts, computeResizableOpts } = $xeTable.getComputeMaps()
const headerColumn = ref([] as VxeTableDefines.ColumnInfo[][])
@@ -169,6 +169,8 @@ export default defineComponent({
const { resizable: allResizable, border, columnKey, headerCellClassName, headerCellStyle, showHeaderOverflow: allColumnHeaderOverflow, headerAlign: allHeaderAlign, align: allAlign, mouseConfig } = tableProps
const { currentColumn, scrollXLoad, overflowX, scrollbarWidth } = tableReactData
const columnOpts = computeColumnOpts.value
+ const columnDragOpts = computeColumnDragOpts.value
+ const { disabledMethod: dragDisabledMethod } = columnDragOpts
return cols.map((column, $columnIndex) => {
const { type, showHeaderOverflow, headerAlign, align, headerClassName, editRender, cellRender } = column
const colid = column.id
@@ -186,6 +188,11 @@ export default defineComponent({
const columnIndex = $xeTable.getColumnIndex(column)
const _columnIndex = $xeTable.getVTColumnIndex(column)
const params: VxeTableDefines.CellRenderHeaderParams = { $table: $xeTable, $grid: $xeTable.xegrid, $rowIndex, column, columnIndex, $columnIndex, _columnIndex, fixed: fixedType, type: renderType, isHidden: fixedHiddenColumn, hasFilter }
+ const thAttrs: Record = {
+ colid,
+ colspan: column.colSpan > 1 ? column.colSpan : null,
+ rowspan: column.rowSpan > 1 ? column.rowSpan : null
+ }
const thOns: any = {
onClick: (evnt: MouseEvent) => $xeTable.triggerHeaderCellClickEvent(evnt, params),
onDblclick: (evnt: MouseEvent) => $xeTable.triggerHeaderCellDblclickEvent(evnt, params)
@@ -194,15 +201,23 @@ export default defineComponent({
if (scrollXLoad && !hasEllipsis) {
showEllipsis = hasEllipsis = true
}
+ const isColDragCell = columnOpts.drag && columnDragOpts.trigger === 'cell'
+ let isDisabledDrag = false
+ if (isColDragCell) {
+ isDisabledDrag = !!(dragDisabledMethod && dragDisabledMethod(params))
+ }
// 按下事件处理
- if (mouseConfig) {
+ if (mouseConfig || isColDragCell) {
thOns.onMousedown = (evnt: MouseEvent) => $xeTable.triggerHeaderCellMousedownEvent(evnt, params)
}
- // 拖拽行事件
+ // 拖拽列事件
if (columnOpts.drag) {
thOns.onDragstart = $xeTable.handleHeaderCellDragDragstartEvent
thOns.onDragend = $xeTable.handleHeaderCellDragDragendEvent
thOns.onDragover = $xeTable.handleHeaderCellDragDragoverEvent
+ if (isColDragCell) {
+ thOns.onMouseup = $xeTable.handleHeaderCellDragMouseupEvent
+ }
}
return h('th', {
class: ['vxe-header--column', colid, {
@@ -216,15 +231,14 @@ export default defineComponent({
'is--sortable': column.sortable,
'col--filter': !!column.filters,
'is--filter-active': hasFilter,
+ 'is--drag-disabled': isDisabledDrag,
'col--current': currentColumn === column
},
headerClassName ? (XEUtils.isFunction(headerClassName) ? headerClassName(params) : headerClassName) : '',
headerCellClassName ? (XEUtils.isFunction(headerCellClassName) ? headerCellClassName(params) : headerCellClassName) : ''
],
- colid,
- colspan: column.colSpan > 1 ? column.colSpan : null,
- rowspan: column.rowSpan > 1 ? column.rowSpan : null,
style: headerCellStyle ? (XEUtils.isFunction(headerCellStyle) ? headerCellStyle(params) : headerCellStyle) : null,
+ ...thAttrs,
...thOns,
key: columnKey || columnOpts.useKey || columnOpts.drag || isColGroup ? colid : $columnIndex
}, [
diff --git a/packages/table/src/table.ts b/packages/table/src/table.ts
index 45c8e642a4..0c7f369b3e 100644
--- a/packages/table/src/table.ts
+++ b/packages/table/src/table.ts
@@ -7168,6 +7168,74 @@ export default defineComponent({
$xeTable.handleColumnSortEvent(evnt, column)
}
},
+ /**
+ * 表头单元格按下事件
+ */
+ triggerHeaderCellMousedownEvent (evnt, params) {
+ const { mouseConfig } = props
+ const mouseOpts = computeMouseOpts.value
+ const columnOpts = computeColumnOpts.value
+ const columnDragOpts = computeColumnDragOpts.value
+ const { trigger, disabledMethod } = columnDragOpts
+ const cell = evnt.currentTarget as HTMLDivElement
+ 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, params) {
+ const { column } = params
+ const { type, treeNode } = column
+ const isRadioType = type === 'radio'
+ const isCheckboxType = type === 'checkbox'
+ const isExpandType = type === 'expand'
+ const rowOpts = computeRowOpts.value
+ const rowDragOpts = computeRowDragOpts.value
+ 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()
+ }
+ },
/**
* 行拖拽
*/
@@ -7393,15 +7461,15 @@ export default defineComponent({
}
},
handleCellDragMousedownEvent (evnt, params) {
+ evnt.stopPropagation()
const { dragConfig } = props
const rowDragOpts = computeRowDragOpts.value
- 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
clearRowDropOrigin()
if (dStartMethod && !dStartMethod(params)) {
trEl.draggable = false
@@ -7641,11 +7709,12 @@ export default defineComponent({
}
},
handleHeaderCellDragMousedownEvent (evnt, params) {
+ evnt.stopPropagation()
const columnDragOpts = computeColumnDragOpts.value
- 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()
if (dragStartMethod && !dragStartMethod(params)) {
@@ -8183,6 +8252,7 @@ export default defineComponent({
const resizableOpts = computeResizableOpts.value
const isArea = mouseConfig && mouseOpts.area
const tableStyle = computeTableStyle.value
+ const columnDragOpts = computeColumnDragOpts.value
return h('div', {
ref: refElem,
class: ['vxe-table', 'vxe-table--render-default', `tid_${xID}`, `border--${tableBorder}`, {
@@ -8199,6 +8269,7 @@ export default defineComponent({
'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,
@@ -8754,7 +8825,7 @@ export default defineComponent({
if (props.editRules && !$xeTable.validate) {
errLog('vxe.error.reqModule', ['Validator'])
}
- if ((checkboxOpts.range || props.keyboardConfig || props.mouseConfig) && !$xeTable.triggerCellMousedownEvent) {
+ if ((checkboxOpts.range || props.keyboardConfig || props.mouseConfig) && !$xeTable.handleCellMousedownEvent) {
errLog('vxe.error.reqModule', ['Keyboard'])
}
if ((props.printConfig || props.importConfig || props.exportConfig) && !$xeTable.exportData) {
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;