Private
Public Access
1
0
Files
u-desk/frontend/src/components/FileSystem/composables/usePathNavigation.ts
绝尘 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

248 lines
5.5 KiB
TypeScript

/**
* 路径导航 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<void>
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<PathHistory>({
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 }