|  | @ -1,11 +1,20 @@ | 
			
		
	
		
		
			
				
					|  |  | <template> |  |  | <template> | 
			
		
	
		
		
			
				
					|  |  |   <q-tr |  |  |   <q-tr | 
			
		
	
		
		
			
				
					
					|  |  |     :class="row[table.selectedField] ? 'selected' : ''" |  |  |     ref="trRef" | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |     :class="row[table.selectedField] ? 'selected ' : ''" | 
			
		
	
		
		
			
				
					|  |  |     @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"> |  |  |     <q-td | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       <div class="flex flex-nowrap items-center" style="flex-wrap: nowrap"> |  |  |       class="nowrap text-nowrap" | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |       :draggable="gridProps.draggable" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       @dragenter="onDragEnter($event, row)" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       @dragleave="onDragLeave($event, row)" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       @dragover="onDragOver($event, row)" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       @drop="onDrop($event, row)" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       @dragstart="onDragStart($event, row)" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     > | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       <div ref="tdDivRef" class="flex flex-nowrap items-center h-full w-full" style="flex-wrap: nowrap"> | 
			
		
	
		
		
			
				
					|  |  |         <!--层级占位符--> |  |  |         <!--层级占位符--> | 
			
		
	
		
		
			
				
					|  |  |         <span :style="`width:${27 * props.level}px;`"></span> |  |  |         <span :style="`width:${27 * props.level}px;`"></span> | 
			
		
	
		
		
			
				
					|  |  |         <!--展开按钮--> |  |  |         <!--展开按钮--> | 
			
		
	
	
		
		
			
				
					|  | @ -49,6 +58,12 @@ | 
			
		
	
		
		
			
				
					|  |  |         :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> | 
			
		
	
	
		
		
			
				
					|  | @ -57,11 +72,12 @@ | 
			
		
	
		
		
			
				
					|  |  |           <component :is="col.value.componentType" v-bind="col.value.attrs"></component> |  |  |           <component :is="col.value.componentType" v-bind="col.value.attrs"></component> | 
			
		
	
		
		
			
				
					|  |  |         </template> |  |  |         </template> | 
			
		
	
		
		
			
				
					|  |  |         <template v-else> |  |  |         <template v-else> | 
			
		
	
		
		
			
				
					
					|  |  |           <span v-dompurify-html="col.value || ''"></span> |  |  |           <span v-dompurify-html="!Tools.isEmpty(col.value) ? col.value : ''"></span> | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |         </template> |  |  |         </template> | 
			
		
	
		
		
			
				
					|  |  |       </q-td> |  |  |       </q-td> | 
			
		
	
		
		
			
				
					|  |  |     </template> |  |  |     </template> | 
			
		
	
		
		
			
				
					|  |  |   </q-tr> |  |  |   </q-tr> | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   <div></div> | 
			
		
	
		
		
			
				
					|  |  |   <template v-for="child in row.children" :key="child[rowKey]"> |  |  |   <template v-for="child in row.children" :key="child[rowKey]"> | 
			
		
	
		
		
			
				
					|  |  |     <TreeGridRow |  |  |     <TreeGridRow | 
			
		
	
		
		
			
				
					|  |  |       v-if="row.expand" |  |  |       v-if="row.expand" | 
			
		
	
	
		
		
			
				
					|  | @ -76,7 +92,11 @@ | 
			
		
	
		
		
			
				
					|  |  |   </template> |  |  |   </template> | 
			
		
	
		
		
			
				
					|  |  | </template> |  |  | </template> | 
			
		
	
		
		
			
				
					|  |  | <script setup lang="ts"> |  |  | <script setup lang="ts"> | 
			
		
	
		
		
			
				
					
					|  |  | import { ref, reactive, computed, watch, inject } from 'vue'; |  |  | import { ref, reactive, computed, watch, inject, toRwa } from 'vue'; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  | import { Tools } from '@/platform'; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const trRef = ref(); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const tdDivRef = ref(); | 
			
		
	
		
		
			
				
					|  |  | const props = defineProps({ |  |  | const props = defineProps({ | 
			
		
	
		
		
			
				
					|  |  |   level: { type: Number, default: 0 }, |  |  |   level: { type: Number, default: 0 }, | 
			
		
	
		
		
			
				
					|  |  |   columnsMap: { |  |  |   columnsMap: { | 
			
		
	
	
		
		
			
				
					|  | @ -113,17 +133,51 @@ const props = defineProps({ | 
			
		
	
		
		
			
				
					|  |  | }); |  |  | }); | 
			
		
	
		
		
			
				
					|  |  | const table = inject('table'); |  |  | const table = inject('table'); | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const style = { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   icon: { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     defaultTop: { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       // 默认顶级节点图标 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       name: 'bi-folder-fill', | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       color: 'amber', | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     }, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     defaultChild: { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       // 默认子节点图标 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       name: 'note', | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       color: '', | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     }, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     drag: { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       // 拖拽时父节点图标 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       name: 'bi-folder-symlink-fill', | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       color: 'amber', | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     }, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   }, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   dragLine: { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     // 拖拽线样式 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     width: '2px', | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     style: 'dashed', | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     color: 'orange', | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   }, | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | const iconComputed = computed(() => { |  |  | const iconComputed = computed(() => { | 
			
		
	
		
		
			
				
					
					|  |  |   if (props.gridProps.treeIcon) { |  |  |   if (!Tools.isEmpty(props.row['_dragIcon_'])) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |     return { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       name: props.row['_dragIcon_'], | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       color: style.icon.drag.color, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } else if (props.gridProps.treeIcon) { | 
			
		
	
		
		
			
				
					|  |  |     return props.gridProps.treeIcon(props.row); |  |  |     return props.gridProps.treeIcon(props.row); | 
			
		
	
		
		
			
				
					|  |  |   } else { |  |  |   } else { | 
			
		
	
		
		
			
				
					|  |  |     if (props.row.children && props.row.children.length > 0) { |  |  |     if (props.row.children && props.row.children.length > 0) { | 
			
		
	
		
		
			
				
					|  |  |       return { |  |  |       return { | 
			
		
	
		
		
			
				
					
					|  |  |         name: 'folder', |  |  |         name: style.icon.defaultTop.name, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |         color: 'amber', |  |  |         color: style.icon.defaultTop.color, | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |       }; |  |  |       }; | 
			
		
	
		
		
			
				
					|  |  |     } else { |  |  |     } else { | 
			
		
	
		
		
			
				
					
					|  |  |       return 'note'; |  |  |       return { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |         name: style.icon.defaultChild.name, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         color: style.icon.defaultChild.color, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       }; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | }); |  |  | }); | 
			
		
	
	
		
		
			
				
					|  | @ -242,6 +296,268 @@ const childColsHandler = (child) => { | 
			
		
	
		
		
			
				
					|  |  |   return cols; |  |  |   return cols; | 
			
		
	
		
		
			
				
					|  |  | }; |  |  | }; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | document.addEventListener('dragstart', function (e) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (tdDivRef?.value) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     tdDivRef.value.classList.add('gridTdDiv'); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | document.addEventListener('drop', function (e) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (tdDivRef?.value) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     tdDivRef.value.classList.remove('gridTdDiv'); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 拖拽开始 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const onDragStart = (e, dataRow) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   const selecteds = props.grid.getSelectedRows(); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if ( | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     selecteds.length > 0 && | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     selecteds.findIndex((item) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       return item[props.rowKey] === dataRow[props.rowKey]; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     }) > -1 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   ) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     table.dragRecords = selecteds; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } else { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     props.grid.cleanSelected(); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     // 触发选择 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     dataRow[table.selectedField] = true; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     table.dragRecords = [dataRow]; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   e.dataTransfer.effectAllowed = 'move'; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const addDragTopStyle = (e) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (e.target?.parentNode?.children && e.target.nodeName === 'TD') { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     for (let i = 0; i < e.target.parentNode.children.length; i++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderTopWidth = style.dragLine.width; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderTopStyle = style.dragLine.style; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderTopColor = style.dragLine.color; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const removeDragTopStyle = (e) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (e.target?.parentNode?.children && e.target.nodeName === 'TD') { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     for (let i = 0; i < e.target.parentNode.children.length; i++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderTopWidth = ''; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderTopStyle = ''; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderTopColor = ''; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const addDragBottomStyle = (e) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (e.target?.parentNode?.children && e.target.nodeName === 'TD') { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     for (let i = 0; i < e.target.parentNode.children.length; i++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderBottomWidth = style.dragLine.width; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderBottomStyle = style.dragLine.style; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderBottomColor = style.dragLine.color; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const removeDragBottomStyle = (e) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (e.target?.parentNode?.children && e.target.nodeName === 'TD') { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     for (let i = 0; i < e.target.parentNode.children.length; i++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderBottomWidth = ''; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderBottomStyle = ''; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       e.target.parentNode.children[i].style.borderBottomColor = ''; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 设置拖拽目标的父节点icon图标 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const setDragIcon = (arr, key: string = '') => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   for (let i = 0; i < arr.length; i++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     if (arr[i].children && arr[i].children.length > 0) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       if (!Tools.isEmpty(key) && arr[i][props.gridProps.primaryKey] === key) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         if (Tools.isEmpty(arr[i]['_dragIcon_']) || arr[i]['_dragIcon_'] !== style.icon.drag.name) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           arr[i]['_dragIcon_'] = style.icon.drag.name; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       } else { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         arr[i]['_dragIcon_'] = ''; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       setDragIcon(arr[i].children, key); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | /** | 
			
		
	
		
		
			
				
					|  |  |  |  |  |  * 判断是否可以拖拽 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |  * @param dragRecords 拖拽的记录集 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |  * @param targetParentKey 当前鼠标所在的目标行的父节点key | 
			
		
	
		
		
			
				
					|  |  |  |  |  |  */ | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const canDrag = (dragRecords, targetParentKey) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (Tools.isEmpty(targetParentKey)) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     return true; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   // 判断拖拽的行是否为当前鼠标所在的目标行的父节点(只要存在父,一直往上找) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   let result = true; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   let parentKey = targetParentKey; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   while (!Tools.isEmpty(parentKey)) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     if ( | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       dragRecords.findIndex((item) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         return item[props.gridProps.primaryKey] === parentKey; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       }) > -1 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     ) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       result = false; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       parentKey = null; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } else { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       parentKey = getRow(table.rows, parentKey, true)[props.gridProps.foreignKey]; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   return result; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 得到表格数据行的中间高度 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const gridTrMiddleHeightComputed = computed(() => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (trRef?.value) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     return trRef.value.$el.offsetHeight / 2; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } else { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     return (table.dense || table.denseBody ? 24 : 48) / 2; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 根据传入的数据行判断是否在当前拖拽的记录集合中 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const dragRecordsContains = (dataRow) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   return ( | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     table.dragRecords.findIndex((item) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       return item[props.rowKey] === dataRow[props.rowKey]; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     }) > -1 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   ); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 拖拽至可放置区域触发 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const onDragEnter = (e, dataRow) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     addDragTopStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } else if (e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     addDragBottomStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 拖拽至不可放置区域触发 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const onDragLeave = (e, dataRow) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   removeDragTopStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   removeDragBottomStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (tdDivRef?.value) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     tdDivRef.value.classList.remove('gridTdDiv'); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | /** | 
			
		
	
		
		
			
				
					|  |  |  |  |  |  * 拖拽过程触发 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |  * @param e 拖拽的html元素 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |  * @param dataRow 当前鼠标所在的目标行数据 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |  */ | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const onDragOver = (e, dataRow) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   e.preventDefault(); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if (!canDrag(table.dragRecords, dataRow[props.gridProps.foreignKey])) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     removeDragTopStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     removeDragBottomStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     setDragIcon(table.rows); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     e.dataTransfer.dropEffect = 'none'; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } else { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     if (e.target.nodeName === 'TD' && e.offsetY <= gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       removeDragBottomStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       addDragTopStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } else if (e.target.nodeName === 'TD' && e.offsetY > gridTrMiddleHeightComputed.value && !dragRecordsContains(dataRow)) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       removeDragTopStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       addDragBottomStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     if (!Tools.isUndefinedOrNull(dataRow[props.gridProps.foreignKey])) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       setDragIcon(table.rows, dataRow[props.gridProps.foreignKey]); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } else { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       setDragIcon(table.rows); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     e.dataTransfer.dropEffect = 'move'; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 删除表格中的数据 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const removeRecord = (arr, removeData) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   for (let i = 0; i < arr.length; i++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     if (arr[i][props.rowKey] === removeData[props.rowKey]) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       arr.splice(i, 1); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       break; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } else if (arr[i].children && arr[i].children.length > 0) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       removeRecord(arr[i].children, removeData); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 设置排序号 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const setOrder = (arr) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   arr.forEach((item, index) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     item[props.gridProps.orderBy] = index + 1; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   }); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 增加并重新设置父属性 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const addRecord = (arr, addData, targetData, targetIndex) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   for (let i = 0; i < arr.length; i++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     if (arr[i][props.gridProps.primaryKey] === targetData[props.gridProps.foreignKey]) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       // 修改父 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       addData[props.gridProps.foreignKey] = arr[i][props.gridProps.primaryKey]; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       arr[i].children.splice(targetIndex + 1, 0, addData); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       // 重新设置排序号 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       setOrder(arr[i].children); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       break; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } else if (arr[i].children && arr[i].children.length > 0) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       addRecord(arr[i].children, addData, targetData, targetIndex); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 数据处理 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const resetOrderDataHandler = (e, dragRecords, targetData, targetIndex) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   // 1、从表格数据中将拖拽数据删除 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   dragRecords.forEach((item) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     removeRecord(table.rows, item); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     // 2、表格数据中根据目标位置添加数据 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     if (Tools.isEmpty(targetData[props.gridProps.foreignKey])) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       if (e.offsetY <= gridTrMiddleHeightComputed.value) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         item[props.gridProps.foreignKey] = null; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         table.rows.splice(targetIndex, 0, item); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         setOrder(table.rows); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       } else { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         item[props.gridProps.foreignKey] = null; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         table.rows.splice(targetIndex + 1, 0, item); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         setOrder(table.rows); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } else { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       addRecord(table.rows, item, targetData, targetIndex); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   }); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 重新设置树的排序 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const resetOrder = (e, dragRecords, arr, targetData) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   for (let i = 0; i < arr.length; i++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     if (arr[i][props.rowKey] === targetData[props.rowKey]) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       resetOrderDataHandler(e, dragRecords, targetData, i); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       break; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } else if (arr[i].children && arr[i].children.length > 0) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       resetOrder(e, dragRecords, arr[i].children, targetData); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | // 拖拽放置时触发 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | const onDrop = (e, dataRow) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   e.preventDefault(); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   removeDragTopStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   removeDragBottomStyle(e); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   setDragIcon(table.rows); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   if ( | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     table.dragRecords.findIndex((item) => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       return item[props.rowKey] === dataRow[props.rowKey]; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     }) > -1 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   ) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     return; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   // 将拖动的数据及其子节点放到目标数据位置,并将目标数据父节点下的子节点重新排序。 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   resetOrder(e, table.dragRecords, table.rows, dataRow); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   // emit('afterRowDraggable'); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | const click = (evt, row, rowIndex) => { |  |  | const click = (evt, row, rowIndex) => { | 
			
		
	
		
		
			
				
					|  |  |   if (!evt.ctrlKey) { |  |  |   if (!evt.ctrlKey) { | 
			
		
	
		
		
			
				
					|  |  |     props.grid.cleanSelected(); |  |  |     props.grid.cleanSelected(); | 
			
		
	
	
		
		
			
				
					|  | @ -259,3 +575,9 @@ const dbClick = (evt, row, rowIndex) => { | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | }; |  |  | }; | 
			
		
	
		
		
			
				
					|  |  | </script> |  |  | </script> | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | <style lang="css"> | 
			
		
	
		
		
			
				
					|  |  |  |  |  | .gridTdDiv { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   pointer-events: none; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | </style> | 
			
		
	
	
		
		
			
				
					|  | 
 |