/** * 路径导航 Composable * 提供路径输入、历史记录、前进/后退等功能 */ import { ref, watch, computed } from 'vue' import { STORAGE_KEYS } from '@/utils/constants' import { normalizePathSeparators } from '@/utils/fileUtils' import type { PathHistory } from '@/types/file-system' export interface UsePathNavigationOptions { onListDirectory?: (path: string) => Promise initialPath?: string } /** * 从 localStorage 恢复上次的路径 */ const restoreLastPath = (): string | null => { try { const lastPath = localStorage.getItem(STORAGE_KEYS.FILESYSTEM.FILE_PATH) if (lastPath) { // 规范化旧路径(可能包含反斜杠) return normalizePathSeparators(lastPath) } return lastPath } catch (error) { console.error('恢复路径失败:', error) return null } } /** * 保存路径到 localStorage */ const saveLastPath = (path: string) => { try { localStorage.setItem(STORAGE_KEYS.FILESYSTEM.FILE_PATH, path) } catch (error) { console.error('保存路径失败:', error) } } export function usePathNavigation(options: UsePathNavigationOptions = {}) { const { onListDirectory, initialPath = '' } = options // 尝试恢复上次的路径,如果没有则使用初始路径 const savedPath = restoreLastPath() const filePath = ref(savedPath || initialPath) // 历史记录 const history = ref({ paths: [], currentIndex: -1 }) /** * 导航到指定路径(带错误处理) */ const navigate = async (path: string) => { if (!path || path === filePath.value) return try { // 路径规范化(处理反斜杠并统一为正斜杠) const normalizedPath = normalizePathSeparators(path) filePath.value = normalizedPath // 添加到历史记录 addToHistory(normalizedPath) // 触发目录列出 if (onListDirectory) { await onListDirectory(normalizedPath) } } catch (error) { console.error('导航失败:', error) throw error } } /** * 添加到历史记录 */ const addToHistory = (path: string) => { const { paths, currentIndex } = history.value // 如果当前不在历史记录末尾,删除当前位置之后的所有记录 if (currentIndex < paths.length - 1) { history.value.paths = paths.slice(0, currentIndex + 1) } // 避免重复添加相同路径 const lastPath = history.value.paths[history.value.paths.length - 1] if (lastPath !== path) { history.value.paths.push(path) history.value.currentIndex = history.value.paths.length - 1 } } /** * 后退(带错误处理) */ const back = async () => { const { paths, currentIndex } = history.value if (currentIndex <= 0) return try { const newIndex = currentIndex - 1 history.value.currentIndex = newIndex filePath.value = paths[newIndex] if (onListDirectory) { await onListDirectory(paths[newIndex]) } } catch (error) { console.error('后退失败:', error) throw error } } /** * 前进(带错误处理) */ const forward = async () => { const { paths, currentIndex } = history.value if (currentIndex >= paths.length - 1) return try { const newIndex = currentIndex + 1 history.value.currentIndex = newIndex filePath.value = paths[newIndex] if (onListDirectory) { await onListDirectory(paths[newIndex]) } } catch (error) { console.error('前进失败:', error) throw error } } /** * 路径输入选择 */ const onPathSelect = (value: string) => { navigate(value) } /** * 路径输入回车 */ const onPathEnter = (value: string) => { navigate(value) } /** * 浏览目录(双击或回车) */ const browseDirectory = async (path: string) => { await navigate(path) } /** * 获取父目录路径 */ const getParentPath = (path: string): string => { const separator = path.includes('\\') ? '\\' : '/' const lastSeparator = path.lastIndexOf(separator) return lastSeparator > 0 ? path.substring(0, lastSeparator) : path } /** * 上级目录 */ const goUp = async () => { const parentPath = getParentPath(filePath.value) if (parentPath !== filePath.value) { await navigate(parentPath) } } /** * 路径规范化(统一为正斜杠) */ const normalizePath = (path: string): string => { return normalizePathSeparators(path) } /** * 判断是否可以后退 */ const canGoBack = computed(() => { return history.value.currentIndex > 0 }) /** * 判断是否可以前进 */ const canGoForward = computed(() => { return history.value.currentIndex < history.value.paths.length - 1 }) /** * 获取历史记录列表(用于自动完成) */ const getPathHistory = computed(() => { return history.value.paths.slice().reverse() // 最新的在前 }) // 监听路径变化,自动保存到 localStorage watch(filePath, (newPath) => { if (newPath) { saveLastPath(newPath) } }) return { // 状态 filePath, history, // 导航方法 navigate, back, forward, goUp, browseDirectory, // 事件处理 onPathSelect, onPathEnter, // 工具方法 getParentPath, normalizePath, // 计算属性 canGoBack, canGoForward, getPathHistory } } // 导出类型(用于外部使用) export type { PathHistory }