From d9ceacbf227fabf2a8967d1ee2234c47cb1d1303 Mon Sep 17 00:00:00 2001 From: Baobhan Sith <80159437+Heavrnl@users.noreply.github.com> Date: Tue, 13 May 2025 20:37:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BA=E7=A7=BB=E5=8A=A8=E7=AB=AF?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6=E5=A4=9A=E9=80=89=E6=8C=89?= =?UTF-8?q?=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/src/components/FileManager.vue | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/FileManager.vue b/packages/frontend/src/components/FileManager.vue index afd176f..cc9a7ed 100644 --- a/packages/frontend/src/components/FileManager.vue +++ b/packages/frontend/src/components/FileManager.vue @@ -117,6 +117,7 @@ const sortDirection = ref<'asc' | 'desc'>('asc'); // const isFetchingInitialPath = ref(false); // 通过 isLoading 和 !initialLoadDone 推断 const isEditingPath = ref(false); const searchQuery = ref(''); // 搜索查询 ref +const isMultiSelectMode = ref(false); // 多选模式状态 (主要用于移动端) const isSearchActive = ref(false); // 控制搜索框激活状态 const searchInputRef = ref(null); // 搜索输入框 ref const pathInputRef = ref(null); @@ -249,6 +250,15 @@ const handleItemAction = (item: FileListItem) => { // 修改:使用 currentSftpManager.value.loadDirectory currentSftpManager.value.loadDirectory(newPath); } else if (item.attrs.isFile) { + // 在移动端多选模式下,不打开文件而是选择它 + if (props.isMobile && isMultiSelectMode.value) { + if (selectedItems.value.has(item.filename)) { + selectedItems.value.delete(item.filename); + } else { + selectedItems.value.add(item.filename); + } + return; + } // 修改:使用 currentSftpManager.value 的 currentPath 和 joinPath const filePath = currentSftpManager.value.joinPath(currentSftpManager.value.currentPath.value, item.filename); const fileInfo: FileInfo = { name: item.filename, fullPath: filePath }; @@ -270,11 +280,20 @@ const handleItemAction = (item: FileListItem) => { } }; +// 切换多选模式 (主要用于移动端) +const toggleMultiSelectMode = () => { + isMultiSelectMode.value = !isMultiSelectMode.value; + if (!isMultiSelectMode.value) { + clearSelection(); // 退出多选模式时清空选择 + } + console.log(`[FileManager ${props.sessionId}-${props.instanceId}] Multi-select mode: ${isMultiSelectMode.value ? 'enabled' : 'disabled'}`); +}; + // 实例化选择 Composable (需要 filteredFileList 和 handleItemAction) const { selectedItems, // 使用 Composable 返回的 selectedItems lastClickedIndex, // 获取 lastClickedIndex 以传递给 ContextMenu - handleItemClick, // 使用 Composable 返回的 handleItemClick + handleItemClick: originalHandleItemClick, // 使用 Composable 返回的 handleItemClick clearSelection, // 获取清空选择的方法 } = useFileManagerSelection({ // 传递当前显示的列表 (已排序和过滤) @@ -282,6 +301,19 @@ const { onItemAction: handleItemAction, // 传递动作回调 }); +// 自定义 handleItemClick 函数以支持移动端多选模式 +const handleItemClick = (event: MouseEvent, item: FileListItem, forceMultiSelect = false) => { + if (props.isMobile && (isMultiSelectMode.value || forceMultiSelect)) { + if (selectedItems.value.has(item.filename)) { + selectedItems.value.delete(item.filename); + } else { + selectedItems.value.add(item.filename); + } + return; + } + originalHandleItemClick(event, item); +}; + // --- 操作模态框辅助函数 --- const openActionModal = ( @@ -1378,6 +1410,20 @@ const handleOpenEditorClick = () => { {{ t('fileManager.actions.upload') }} + + +