Private
Public Access
1
0
Files
u-desk/frontend/src/composables/useNavigation.js
绝尘 f54bf1c28d 重构:Wails v3 迁移 + 前端目录规范化 + Sidebar滚动优化
- web/ → frontend/ 目录重命名(Wails v3 标准结构)
- main.go: Middleware 修复 custom.js 404 + DevTools 延迟启动
- Sidebar: 收藏夹内部独立滚动 + 帮助区块固定底部
- useFavorites.ts: longPressTimer const→let 修复 TypeError
- App.vue: Arco Tabs padding-top 覆盖
- build: config.yml / Taskfile.yml 对齐官方模板,devtools build tag
- 新增 v3 bindings、vite.config.js、跨平台构建配置

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 11:03:53 +08:00

274 lines
6.2 KiB
JavaScript

/**
* 导航和路径管理 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<string>} 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<Array<string>>}
*/
const navHistory = ref([])
/**
* 当前在历史栈中的位置
* @type {Ref<number>}
*/
const navIndex = ref(-1)
/**
* 是否正在导航(防止重复记录)
* @type {Ref<boolean>}
*/
const isNavigating = ref(false)
/**
* 路径历史记录(用于下拉列表)
* @type {Ref<Array<string>>}
*/
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<boolean>} 是否成功
*/
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<boolean>} 是否成功
*/
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<boolean>} 是否成功
*/
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<Array<string>>} navHistory - 导航历史栈
* @property {Ref<number>} navIndex - 当前在历史栈中的位置
* @property {Ref<boolean>} isNavigating - 是否正在导航
* @property {Ref<Array<string>>} pathHistory - 路径历史记录(下拉列表)
* @property {ComputedRef<boolean>} canGoBack - 是否可以后退
* @property {ComputedRef<boolean>} 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 - 加载路径历史记录
*/