/** * 导航和路径管理 composable * * @module composables/useNavigation * @description 封装文件系统的导航历史、路径操作等逻辑 */ import { ref, computed } from 'vue' import { Message } from '@arco-design/web-vue' /** * 路径历史 localStorage 键 */ const STORAGE_KEY_PATH_HISTORY = 'app-filesystem-path-history' /** * 导航管理 composable * @param {Object} options - 配置选项 * @param {Ref} options.filePath - 当前路径 ref * @param {Function} options.onListDirectory - 列出目录的函数 * @param {Function} options.onExitZipMode - 退出 ZIP 模式的函数 * @returns {UseNavigationReturn} 导航操作 API */ export function useNavigation(options = {}) { const { filePath, onListDirectory, onExitZipMode, } = options // ========== 导航历史记录(支持后退/前进) ========== /** * 导航历史栈 * @type {Ref>} */ const navHistory = ref([]) /** * 当前在历史栈中的位置 * @type {Ref} */ const navIndex = ref(-1) /** * 是否正在导航(防止重复记录) * @type {Ref} */ const isNavigating = ref(false) /** * 路径历史记录(用于下拉列表) * @type {Ref>} */ const pathHistory = ref([]) // ========== 计算属性 ========== /** * 是否可以后退 */ const canGoBack = computed(() => navIndex.value > 0) /** * 是否可以前进 */ const canGoForward = computed(() => navIndex.value < navHistory.value.length - 1) // ========== 导航操作 ========== /** * 添加到路径历史记录 * @param {string} path - 路径 */ const addToHistory = (path) => { if (!path || path === filePath.value) return // 去重:如果路径已在历史中,先删除 const index = pathHistory.value.indexOf(path) if (index > -1) { pathHistory.value.splice(index, 1) } // 添加到开头 pathHistory.value.unshift(path) // 限制历史记录数量 if (pathHistory.value.length > 50) { pathHistory.value = pathHistory.value.slice(0, 50) } // 持久化 try { localStorage.setItem(STORAGE_KEY_PATH_HISTORY, JSON.stringify(pathHistory.value)) } catch (e) { // 忽略 localStorage 错误 } } /** * 推送到导航历史栈 * @param {string} path - 路径 */ const pushNav = (path) => { if (isNavigating.value) { return } // 如果当前位置不在历史末尾,删除后续历史 if (navIndex.value < navHistory.value.length - 1) { navHistory.value = navHistory.value.slice(0, navIndex.value + 1) } // 添加到历史 navHistory.value.push(path) navIndex.value = navHistory.value.length - 1 // 同时添加到路径历史 addToHistory(path) } /** * 后退 * @returns {Promise} 是否成功 */ const goBack = async () => { if (!canGoBack.value) { return false } isNavigating.value = true try { navIndex.value-- const path = navHistory.value[navIndex.value] await onListDirectory(path) return true } catch (error) { Message.error(`后退失败: ${error.message || error}`) return false } finally { isNavigating.value = false } } /** * 前进 * @returns {Promise} 是否成功 */ const goForward = async () => { if (!canGoForward.value) { return false } isNavigating.value = true try { navIndex.value++ const path = navHistory.value[navIndex.value] await onListDirectory(path) return true } catch (error) { Message.error(`前进失败: ${error.message || error}`) return false } finally { isNavigating.value = false } } // ========== 路径操作 ========== /** * 路径选择(从下拉列表) * @param {string} value - 选中的路径 */ const onPathSelect = (value) => { if (value && value !== filePath.value) { goToPath(value) } } /** * 路径输入框回车事件 */ const onPathEnter = () => { const path = filePath.value?.trim() if (path) { goToPath(path) } } /** * 跳转到指定路径 * @param {string} path - 目标路径 * @returns {Promise} 是否成功 */ const goToPath = async (path) => { if (!path) { return false } // 退出 ZIP 模式 if (onExitZipMode) { onExitZipMode() } return await onListDirectory(path) } /** * 浏览目录(打开系统文件选择对话框) */ const browseDirectory = async () => { Message.info('请手动输入目录路径') } // ========== 初始化 ========== /** * 加载路径历史记录 */ const loadPathHistory = () => { try { const saved = localStorage.getItem(STORAGE_KEY_PATH_HISTORY) if (saved) { pathHistory.value = JSON.parse(saved) } } catch (e) { console.warn('[useNavigation] 加载路径历史失败:', e) } } // 初始化 loadPathHistory() return { // 状态 navHistory, navIndex, isNavigating, pathHistory, canGoBack, canGoForward, // 方法 addToHistory, pushNav, goBack, goForward, onPathSelect, onPathEnter, goToPath, browseDirectory, loadPathHistory, } } /** * @typedef {Object} UseNavigationReturn * @property {Ref>} navHistory - 导航历史栈 * @property {Ref} navIndex - 当前在历史栈中的位置 * @property {Ref} isNavigating - 是否正在导航 * @property {Ref>} pathHistory - 路径历史记录(下拉列表) * @property {ComputedRef} canGoBack - 是否可以后退 * @property {ComputedRef} canGoForward - 是否可以前进 * @property {Function} addToHistory - 添加到路径历史记录 * @property {Function} pushNav - 推送到导航历史栈 * @property {Function} goBack - 后退 * @property {Function} goForward - 前进 * @property {Function} onPathSelect - 路径选择 * @property {Function} onPathEnter - 路径输入框回车事件 * @property {Function} goToPath - 跳转到指定路径 * @property {Function} browseDirectory - 浏览目录 * @property {Function} loadPathHistory - 加载路径历史记录 */