Update FileManager.vue

This commit is contained in:
Baobhan Sith
2025-04-18 20:12:48 +08:00
parent 8c304bcbf4
commit 26180ca8c0
@@ -400,60 +400,68 @@ const SCROLL_SPEED = 10; // px per interval,基础滚动速度
const handleDragOver = (event: DragEvent) => { const handleDragOver = (event: DragEvent) => {
event.preventDefault(); event.preventDefault();
const isExternalFileDrag = event.dataTransfer?.types.includes('Files') ?? false; const isExternalFileDrag = event.dataTransfer?.types.includes('Files') ?? false;
const isInternalDrag = !!draggedItem.value; const isInternalDrag = !!draggedItem.value; // Check if an internal item is being dragged
// --- Determine Drop Effect ---
let effect: 'copy' | 'move' | 'none' = 'none'; let effect: 'copy' | 'move' | 'none' = 'none';
let currentTargetFilename: string | null = null; let currentTargetFilename: string | null = null;
let highlightContainer = false; // Flag to control container highlighting
const targetElement = event.target as HTMLElement; const targetElement = event.target as HTMLElement;
const targetRow = targetElement.closest('tr.file-row'); // Find closest row (folder or file) const targetRow = targetElement.closest('tr.file-row');
// Safely access dataset only if targetRow is an HTMLElement
const targetFilename = (targetRow instanceof HTMLElement) ? targetRow.dataset.filename : undefined; const targetFilename = (targetRow instanceof HTMLElement) ? targetRow.dataset.filename : undefined;
const targetIsFolder = targetRow?.classList.contains('folder-row'); const targetIsFolder = targetRow?.classList.contains('folder-row');
if (props.wsDeps.isConnected.value && isExternalFileDrag) { if (props.wsDeps.isConnected.value) {
// External Drag (Upload) if (isExternalFileDrag) {
if (targetIsFolder && targetFilename && targetFilename !== '..') { // External Drag (Upload)
effect = 'copy'; // Allow dropping into subfolders effect = 'copy'; // Always allow copy for external files
currentTargetFilename = targetFilename; highlightContainer = true; // Highlight the container
} else if (!targetRow) {
effect = 'copy'; // Allow dropping into the main container area (current path)
currentTargetFilename = null; // No specific target row
} else {
effect = 'none'; // Don't allow dropping external files onto file rows or '..'
currentTargetFilename = null;
}
isDraggingOver.value = (effect === 'copy'); // Set general drag-over state if allowed
} else if (isInternalDrag && draggedItem.value) { // Determine the specific target folder for potential drop and row highlighting
// Internal Drag (Move) if (targetIsFolder && targetFilename && targetFilename !== '..') {
if (targetIsFolder && targetFilename && targetFilename !== draggedItem.value.filename) { currentTargetFilename = targetFilename; // Target is a subfolder row
// Allow dropping onto any folder row (including '..') except itself } else {
effect = 'move'; currentTargetFilename = null; // Target is the current directory (or invalid row)
currentTargetFilename = targetFilename; }
} else {
effect = 'none';
currentTargetFilename = null;
}
isDraggingOver.value = false; // Don't use general drag-over for internal moves
} else if (isInternalDrag && draggedItem.value) {
// Internal Drag (Move)
highlightContainer = false; // Do not highlight the container for internal moves
if (targetIsFolder && targetFilename && targetFilename !== draggedItem.value.filename) {
// Allow dropping onto any folder row (including '..') except itself
effect = 'move';
currentTargetFilename = targetFilename; // Target is the specific folder row
} else {
// Invalid target for internal move
effect = 'none';
currentTargetFilename = null;
}
} else {
// Other drag types
effect = 'none';
currentTargetFilename = null;
highlightContainer = false;
}
} else { } else {
// Other drag types or not connected // Not connected
effect = 'none'; effect = 'none';
currentTargetFilename = null; currentTargetFilename = null;
isDraggingOver.value = false; highlightContainer = false;
} }
// --- Apply Drop Effect and Target Highlighting --- // --- Apply Drop Effect and Target Highlighting ---
if (event.dataTransfer) { if (event.dataTransfer) {
event.dataTransfer.dropEffect = effect; event.dataTransfer.dropEffect = effect;
} }
isDraggingOver.value = highlightContainer; // Control container highlight based on flag
dragOverTarget.value = currentTargetFilename; // Set specific row target for highlighting dragOverTarget.value = currentTargetFilename; // Set specific row target for highlighting
// --- 处理自动滚动 --- // --- 处理自动滚动 ---
const container = fileListContainerRef.value; const container = fileListContainerRef.value;
if (container && (isExternalFileDrag || draggedItem.value)) { // 仅在有效拖拽时处理滚动 // 仅在有效拖拽 (外部文件或内部文件) 且效果不是 'none' 时处理滚动
if (container && (isExternalFileDrag || isInternalDrag) && effect !== 'none') {
const rect = container.getBoundingClientRect(); const rect = container.getBoundingClientRect();
const mouseY = event.clientY - rect.top; // 鼠标在容器内的 Y 坐标 const mouseY = event.clientY - rect.top; // 鼠标在容器内的 Y 坐标
@@ -489,7 +497,7 @@ const handleDragOver = (event: DragEvent) => {
} }
} }
} else { } else {
// 如果拖拽无效或容器不存在,确保停止滚动 // 如果拖拽无效、效果为 'none' 或容器不存在,确保停止滚动
if (scrollIntervalId.value !== null) { if (scrollIntervalId.value !== null) {
clearInterval(scrollIntervalId.value); clearInterval(scrollIntervalId.value);
scrollIntervalId.value = null; scrollIntervalId.value = null;
@@ -615,14 +623,30 @@ const handleDragLeaveRow = (targetItem: FileListItem) => {
const handleDropOnRow = (targetItem: FileListItem, event: DragEvent) => { const handleDropOnRow = (targetItem: FileListItem, event: DragEvent) => {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); // 阻止事件冒泡到父容器的 drop 处理 // 检查是否是外部文件拖拽
const files = event.dataTransfer?.files;
if (files && files.length > 0) {
// 如果是外部文件拖拽,不阻止冒泡,让父容器的 handleDrop 处理上传
console.log(`[FileManager ${props.sessionId}] External file drop detected on row, letting parent handle.`);
// 不需要清除 draggedItem.value,因为外部拖拽时它应该为 null
// dragOverTarget.value = null; // 清除悬停状态 (父容器 handleDrop 会处理)
return;
}
// --- 以下是处理内部文件移动的逻辑 ---
event.stopPropagation(); // 仅在处理内部移动时阻止冒泡
const sourceItem = draggedItem.value; const sourceItem = draggedItem.value;
dragOverTarget.value = null; // 清除悬停状态 dragOverTarget.value = null; // 清除悬停状态
// 验证拖放操作的有效性 (与之前相同) // 验证内部拖放操作的有效性
// 注意:这里的 !sourceItem 检查现在只会在非外部文件拖拽时发生,
// 如果 sourceItem 仍然是 null,说明不是有效的内部拖拽。
if (!sourceItem || sourceItem.filename === '..' || (targetItem.filename !== '..' && !targetItem.attrs.isDirectory) || sourceItem.filename === targetItem.filename) { if (!sourceItem || sourceItem.filename === '..' || (targetItem.filename !== '..' && !targetItem.attrs.isDirectory) || sourceItem.filename === targetItem.filename) {
console.log(`[FileManager ${props.sessionId}] Drop on row ignored: Invalid target or source. Source: ${sourceItem?.filename}, Target: ${targetItem.filename}`); console.log(`[FileManager ${props.sessionId}] Internal drop on row ignored: Invalid target or source. Source: ${sourceItem?.filename}, Target: ${targetItem.filename}`);
draggedItem.value = null; // 如果 sourceItem 存在但无效,才需要清除
if (sourceItem) {
draggedItem.value = null;
}
return; return;
} }
@@ -1682,3 +1706,4 @@ td:nth-child(5) { /* Modified */
</style> </style>