|
@ -2,18 +2,20 @@ |
|
|
<q-tr |
|
|
<q-tr |
|
|
ref="trRef" |
|
|
ref="trRef" |
|
|
:class="row[table.selectedField] ? 'selected ' : ''" |
|
|
:class="row[table.selectedField] ? 'selected ' : ''" |
|
|
|
|
|
:draggable=" |
|
|
|
|
|
(typeof gridProps.draggable === 'boolean' && gridProps.draggable) || (typeof gridProps.draggable === 'string' && gridProps.draggable === 'local') |
|
|
|
|
|
? true |
|
|
|
|
|
: false |
|
|
|
|
|
" |
|
|
@click.stop.prevent="click($event, row, row.rowIndex)" |
|
|
@click.stop.prevent="click($event, row, row.rowIndex)" |
|
|
@dblclick.stop.prevent="dbClick($event, row, row.rowIndex)" |
|
|
@dblclick.stop.prevent="dbClick($event, row, row.rowIndex)" |
|
|
> |
|
|
|
|
|
<q-td |
|
|
|
|
|
class="nowrap text-nowrap" |
|
|
|
|
|
:draggable="gridProps.draggable" |
|
|
|
|
|
@dragenter="onDragEnter($event, row)" |
|
|
@dragenter="onDragEnter($event, row)" |
|
|
@dragleave="onDragLeave($event, row)" |
|
|
@dragleave="onDragLeave($event, row)" |
|
|
@dragover="onDragOver($event, row)" |
|
|
@dragover="onDragOver($event, row)" |
|
|
@drop="onDrop($event, row)" |
|
|
@drop="onDrop($event, row)" |
|
|
@dragstart="onDragStart($event, row)" |
|
|
@dragstart="onDragStart($event, row)" |
|
|
> |
|
|
> |
|
|
|
|
|
<q-td class="nowrap text-nowrap"> |
|
|
<div ref="tdDivRef" class="flex flex-nowrap items-center h-full w-full" style="flex-wrap: nowrap"> |
|
|
<div ref="tdDivRef" class="flex flex-nowrap items-center h-full w-full" style="flex-wrap: nowrap"> |
|
|
<!--层级占位符--> |
|
|
<!--层级占位符--> |
|
|
<span :style="`width:${24 * props.level}px;`"></span> |
|
|
<span :style="`width:${24 * props.level}px;`"></span> |
|
@ -58,12 +60,6 @@ |
|
|
:class="col.__thClass + ' ' + col.classes" |
|
|
:class="col.__thClass + ' ' + col.classes" |
|
|
:title="col.classes?.indexOf('truncate') > -1 && col.value && typeof col.value !== 'object' ? col.value : ''" |
|
|
:title="col.classes?.indexOf('truncate') > -1 && col.value && typeof col.value !== 'object' ? col.value : ''" |
|
|
:style="col.style" |
|
|
:style="col.style" |
|
|
:draggable="gridProps.draggable" |
|
|
|
|
|
@dragenter="onDragEnter($event, row)" |
|
|
|
|
|
@dragleave="onDragLeave($event, row)" |
|
|
|
|
|
@dragover="onDragOver($event, row)" |
|
|
|
|
|
@drop="onDrop($event, row)" |
|
|
|
|
|
@dragstart="onDragStart($event, row)" |
|
|
|
|
|
> |
|
|
> |
|
|
<template v-if="col.value && typeof col.value === 'object' && col.value.componentType && col.value.bindModelValue"> |
|
|
<template v-if="col.value && typeof col.value === 'object' && col.value.componentType && col.value.bindModelValue"> |
|
|
<component :is="col.value.componentType" v-bind="col.value.attrs" v-model="getRow(table.rows, row[props.rowKey], false)[col.name]"></component> |
|
|
<component :is="col.value.componentType" v-bind="col.value.attrs" v-model="getRow(table.rows, row[props.rowKey], false)[col.name]"></component> |
|
@ -90,11 +86,12 @@ |
|
|
:grid="props.grid" |
|
|
:grid="props.grid" |
|
|
:grid-row-click="props.gridRowClick" |
|
|
:grid-row-click="props.gridRowClick" |
|
|
:grid-row-db-click="gridRowDbClick" |
|
|
:grid-row-db-click="gridRowDbClick" |
|
|
|
|
|
:after-row-draggable="props.afterRowDraggable" |
|
|
></TreeGridRow> |
|
|
></TreeGridRow> |
|
|
</template> |
|
|
</template> |
|
|
</template> |
|
|
</template> |
|
|
<script setup lang="ts"> |
|
|
<script setup lang="ts"> |
|
|
import { ref, reactive, computed, watch, inject, toRwa } from 'vue'; |
|
|
import { ref, reactive, computed, watch, inject, toRaw, nextTick } from 'vue'; |
|
|
import { Tools } from '@/platform'; |
|
|
import { Tools } from '@/platform'; |
|
|
|
|
|
|
|
|
const trRef = ref(); |
|
|
const trRef = ref(); |
|
@ -140,6 +137,10 @@ const props = defineProps({ |
|
|
type: Function, |
|
|
type: Function, |
|
|
default: () => {}, |
|
|
default: () => {}, |
|
|
}, |
|
|
}, |
|
|
|
|
|
afterRowDraggable: { |
|
|
|
|
|
type: Function, |
|
|
|
|
|
default: () => {}, |
|
|
|
|
|
}, |
|
|
}); |
|
|
}); |
|
|
const table = inject('table'); |
|
|
const table = inject('table'); |
|
|
|
|
|
|
|
@ -433,11 +434,26 @@ const dragRecordsContains = (dataRow) => { |
|
|
); |
|
|
); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 根据传入节点判断该节点是否为所在层级的最后一个节点 |
|
|
|
|
|
const isLastNode = (dataRow) => { |
|
|
|
|
|
if (Tools.isEmpty(dataRow[props.gridProps.foreignKey])) { |
|
|
|
|
|
if (table.rows[table.rows.length - 1][props.gridProps.primaryKey] === dataRow[props.gridProps.primaryKey]) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
const parent = getRow(table.rows, dataRow[props.gridProps.foreignKey], true); |
|
|
|
|
|
if (parent.children[parent.children.length - 1][props.gridProps.primaryKey] === dataRow[props.gridProps.primaryKey]) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// 拖拽至可放置区域触发 |
|
|
// 拖拽至可放置区域触发 |
|
|
const onDragEnter = (e, dataRow) => { |
|
|
const onDragEnter = (e, dataRow) => { |
|
|
if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { |
|
|
if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { |
|
|
addDragTopStyle(e); |
|
|
addDragTopStyle(e); |
|
|
} else if (e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { |
|
|
} else if (isLastNode(dataRow) && e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { |
|
|
addDragBottomStyle(e); |
|
|
addDragBottomStyle(e); |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
@ -467,7 +483,7 @@ const onDragOver = (e, dataRow) => { |
|
|
if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { |
|
|
if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { |
|
|
removeDragBottomStyle(e); |
|
|
removeDragBottomStyle(e); |
|
|
addDragTopStyle(e); |
|
|
addDragTopStyle(e); |
|
|
} else if (e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { |
|
|
} else if (isLastNode(dataRow) && e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { |
|
|
removeDragTopStyle(e); |
|
|
removeDragTopStyle(e); |
|
|
addDragBottomStyle(e); |
|
|
addDragBottomStyle(e); |
|
|
} |
|
|
} |
|
@ -482,58 +498,86 @@ const onDragOver = (e, dataRow) => { |
|
|
|
|
|
|
|
|
// 删除表格中的数据 |
|
|
// 删除表格中的数据 |
|
|
const removeRecord = (arr, removeData) => { |
|
|
const removeRecord = (arr, removeData) => { |
|
|
|
|
|
let index = 0; |
|
|
for (let i = 0; i < arr.length; i++) { |
|
|
for (let i = 0; i < arr.length; i++) { |
|
|
if (arr[i][props.rowKey] === removeData[props.rowKey]) { |
|
|
if (arr[i][props.rowKey] === removeData[props.rowKey]) { |
|
|
arr.splice(i, 1); |
|
|
arr.splice(i, 1); |
|
|
|
|
|
index = i; |
|
|
break; |
|
|
break; |
|
|
} else if (arr[i].children && arr[i].children.length > 0) { |
|
|
} else if (arr[i].children && arr[i].children.length > 0) { |
|
|
removeRecord(arr[i].children, removeData); |
|
|
const a = removeRecord(arr[i].children, removeData); |
|
|
|
|
|
if (a > 0) { |
|
|
|
|
|
index = a; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return index; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 待更新的排序数据 |
|
|
|
|
|
const updateOrderData = <any>[]; |
|
|
|
|
|
|
|
|
// 设置排序号 |
|
|
// 设置排序号 |
|
|
const setOrder = (arr) => { |
|
|
const setOrder = (arr) => { |
|
|
arr.forEach((item, index) => { |
|
|
arr.forEach((item, index) => { |
|
|
item[props.gridProps.orderBy] = index + 1; |
|
|
item[props.gridProps.orderBy] = index + 1; |
|
|
|
|
|
// 添加至待更新集合中 |
|
|
|
|
|
updateOrderData.push(toRaw(item)); |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// 增加并重新设置父属性 |
|
|
// 增加并重新设置父属性 |
|
|
const addRecord = (arr, addData, targetData, targetIndex) => { |
|
|
const addRecord = (e, arr, addData, targetData, dragIndex, targetIndex) => { |
|
|
for (let i = 0; i < arr.length; i++) { |
|
|
for (let i = 0; i < arr.length; i++) { |
|
|
if (arr[i][props.gridProps.primaryKey] === targetData[props.gridProps.foreignKey]) { |
|
|
if (arr[i][props.gridProps.primaryKey] === targetData[props.gridProps.foreignKey]) { |
|
|
|
|
|
if ( |
|
|
|
|
|
e.offsetY <= gridTrMiddleHeightComputed.value && |
|
|
|
|
|
isTrue(dragIndex, targetIndex) && |
|
|
|
|
|
addData[props.gridProps.foreignKey] === targetData[props.gridProps.foreignKey] |
|
|
|
|
|
) { |
|
|
|
|
|
arr[i].children.splice(targetIndex - 1, 0, addData); |
|
|
|
|
|
} else if (e.offsetY > gridTrMiddleHeightComputed.value && addData[props.gridProps.foreignKey] !== targetData[props.gridProps.foreignKey]) { |
|
|
|
|
|
arr[i].children.splice(arr[i].children.length, 0, addData); |
|
|
|
|
|
} else { |
|
|
|
|
|
arr[i].children.splice(targetIndex, 0, addData); |
|
|
|
|
|
} |
|
|
// 修改父 |
|
|
// 修改父 |
|
|
addData[props.gridProps.foreignKey] = arr[i][props.gridProps.primaryKey]; |
|
|
addData[props.gridProps.foreignKey] = arr[i][props.gridProps.primaryKey]; |
|
|
arr[i].children.splice(targetIndex + 1, 0, addData); |
|
|
|
|
|
// 重新设置排序号 |
|
|
// 重新设置排序号 |
|
|
setOrder(arr[i].children); |
|
|
setOrder(arr[i].children); |
|
|
break; |
|
|
break; |
|
|
} else if (arr[i].children && arr[i].children.length > 0) { |
|
|
} else if (arr[i].children && arr[i].children.length > 0) { |
|
|
addRecord(arr[i].children, addData, targetData, targetIndex); |
|
|
addRecord(e, arr[i].children, addData, targetData, dragIndex, targetIndex); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const isTrue = (dragIndex, targetIndex) => { |
|
|
|
|
|
if (dragIndex < targetIndex) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// 数据处理 |
|
|
// 数据处理 |
|
|
const resetOrderDataHandler = (e, dragRecords, targetData, targetIndex) => { |
|
|
const resetOrderDataHandler = (e, dragRecords, targetData, targetIndex) => { |
|
|
// 1、从表格数据中将拖拽数据删除 |
|
|
// 1、从表格数据中将拖拽数据删除 |
|
|
dragRecords.forEach((item) => { |
|
|
dragRecords.forEach((item) => { |
|
|
removeRecord(table.rows, item); |
|
|
const itemIndex = removeRecord(table.rows, item); |
|
|
|
|
|
|
|
|
// 2、表格数据中根据目标位置添加数据 |
|
|
// 2、表格数据中根据目标位置添加数据 |
|
|
if (Tools.isEmpty(targetData[props.gridProps.foreignKey])) { |
|
|
if (Tools.isEmpty(targetData[props.gridProps.foreignKey])) { |
|
|
if (e.offsetY <= gridTrMiddleHeightComputed.value) { |
|
|
// 3、修正位置,当拖拽至行的上半部分,且拖拽对象跟目标对象处于同级,且下标小于目标时,使用splice添加到指定下标时需将下标-1(扣除自身所占的1个下标) |
|
|
item[props.gridProps.foreignKey] = null; |
|
|
if (e.offsetY <= gridTrMiddleHeightComputed.value && Tools.isEmpty(item[props.gridProps.foreignKey]) && isTrue(itemIndex, targetIndex)) { |
|
|
table.rows.splice(targetIndex, 0, item); |
|
|
table.rows.splice(targetIndex - 1, 0, item); |
|
|
setOrder(table.rows); |
|
|
|
|
|
} else { |
|
|
} else { |
|
|
|
|
|
table.rows.splice(targetIndex, 0, item); |
|
|
|
|
|
} |
|
|
item[props.gridProps.foreignKey] = null; |
|
|
item[props.gridProps.foreignKey] = null; |
|
|
table.rows.splice(targetIndex + 1, 0, item); |
|
|
|
|
|
setOrder(table.rows); |
|
|
setOrder(table.rows); |
|
|
} |
|
|
// 根目录下顺序变化,直接将根目录下所有数据放到待更新集合中 |
|
|
|
|
|
updateOrderData.push(...toRaw(table.rows)); |
|
|
} else { |
|
|
} else { |
|
|
addRecord(table.rows, item, targetData, targetIndex); |
|
|
addRecord(e, table.rows, item, targetData, itemIndex, targetIndex); |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
@ -563,9 +607,17 @@ const onDrop = (e, dataRow) => { |
|
|
) { |
|
|
) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
// 每次放置时清空待更新集合 |
|
|
|
|
|
updateOrderData.splice(0, updateOrderData.length); |
|
|
// 将拖动的数据及其子节点放到目标数据位置,并将目标数据父节点下的子节点重新排序。 |
|
|
// 将拖动的数据及其子节点放到目标数据位置,并将目标数据父节点下的子节点重新排序。 |
|
|
resetOrder(e, table.dragRecords, table.rows, dataRow); |
|
|
resetOrder(e, table.dragRecords, table.rows, dataRow); |
|
|
// emit('afterRowDraggable'); |
|
|
|
|
|
|
|
|
// 请求后端更新排序 |
|
|
|
|
|
if (typeof props.gridProps.draggable === 'boolean' && props.gridProps.draggable && updateOrderData?.length > 0) { |
|
|
|
|
|
props.grid.updates(updateOrderData); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
props.afterRowDraggable(updateOrderData); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const click = (evt, row, rowIndex) => { |
|
|
const click = (evt, row, rowIndex) => { |
|
|