重构: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>
This commit is contained in:
273
frontend/src/composables/useNavigation.js
Normal file
273
frontend/src/composables/useNavigation.js
Normal file
@@ -0,0 +1,273 @@
|
||||
/**
|
||||
* 导航和路径管理 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 - 加载路径历史记录
|
||||
*/
|
||||
Reference in New Issue
Block a user