/** * 收藏夹管理 Composable * 提供收藏文件的添加、删除、排序等功能 */ import { ref, watch } from 'vue' import { STORAGE_KEYS } from '@/utils/constants' import type { FavoriteFile, FileItem, DraggingState } from '@/types/file-system' export function useFavorites() { // 收藏列表 const favorites = ref([]) // 拖拽状态 const draggingState = ref({ isDragging: false, draggedIndex: -1, pressedIndex: -1 }) /** * 从 localStorage 加载收藏列表 */ const loadFavorites = () => { try { const stored = localStorage.getItem(STORAGE_KEYS.FAVORITE_FILES) if (stored) { favorites.value = JSON.parse(stored) } } catch (error) { console.error('加载收藏列表失败:', error) } } /** * 保存收藏列表到 localStorage */ const saveFavorites = () => { try { localStorage.setItem(STORAGE_KEYS.FAVORITE_FILES, JSON.stringify(favorites.value)) } catch (error) { console.error('保存收藏列表失败:', error) } } /** * 添加收藏 */ const addFavorite = (file: FileItem) => { // 检查是否已存在 const exists = favorites.value.some(fav => fav.path === file.path) if (exists) { return false } favorites.value.push({ ...file, addedAt: Date.now() } as FavoriteFile) saveFavorites() return true } /** * 标准化路径用于比较(处理正斜杠/反斜杠不一致) */ const normalizePath = (path: string): string => { return path.replace(/\\/g, '/').toLowerCase() } /** * 删除收藏 */ const removeFavorite = (path: string) => { const normalizedPath = normalizePath(path) const index = favorites.value.findIndex(fav => normalizePath(fav.path) === normalizedPath) if (index !== -1) { favorites.value.splice(index, 1) saveFavorites() } } /** * 切换收藏状态 */ const toggleFavorite = (file: FileItem) => { const exists = isFavorite(file.path) if (exists) { removeFavorite(file.path) return false } else { addFavorite(file) return true } } /** * 检查是否已收藏 */ const isFavorite = (path: string): boolean => { const normalizedPath = normalizePath(path) return favorites.value.some(fav => normalizePath(fav.path) === normalizedPath) } /** * 长按开始 */ const onLongPressStart = (event: MouseEvent | TouchEvent, index: number) => { const isMouse = event instanceof MouseEvent const isTouch = event instanceof TouchEvent // 只支持鼠标左键或触摸 if (isMouse && event.button !== 0) return if (!isMouse && !isTouch) return draggingState.value.pressedIndex = index draggingState.value.draggedIndex = index } /** * 长按取消 */ const onLongPressCancel = () => { if (!draggingState.value.isDragging) { draggingState.value.pressedIndex = -1 draggingState.value.draggedIndex = -1 } } /** * 拖拽开始 */ const onDragStart = (event: DragEvent, index: number) => { draggingState.value.isDragging = true draggingState.value.draggedIndex = index // 设置拖拽数据 if (event.dataTransfer) { event.dataTransfer.effectAllowed = 'move' event.dataTransfer.setData('text/plain', index.toString()) } } /** * 拖拽经过 */ const onDragOver = (event: DragEvent) => { event.preventDefault() if (event.dataTransfer) { event.dataTransfer.dropEffect = 'move' } } /** * 放置 */ const onDrop = (event: DragEvent, targetIndex: number) => { event.preventDefault() const fromIndex = draggingState.value.draggedIndex const toIndex = targetIndex if (fromIndex === toIndex || fromIndex === -1) { resetDragging() return } // 移动元素 const item = favorites.value.splice(fromIndex, 1)[0] favorites.value.splice(toIndex, 0, item) saveFavorites() resetDragging() } /** * 拖拽结束 */ const onDragEnd = () => { resetDragging() } /** * 重置拖拽状态 */ const resetDragging = () => { draggingState.value.isDragging = false draggingState.value.draggedIndex = -1 draggingState.value.pressedIndex = -1 } /** * 重新排序 */ const reorder = (fromIndex: number, toIndex: number) => { if (fromIndex === toIndex) return const item = favorites.value.splice(fromIndex, 1)[0] favorites.value.splice(toIndex, 0, item) saveFavorites() } // 组件挂载时加载收藏列表 loadFavorites() return { // 状态 favorites, draggingState, // 方法 addFavorite, removeFavorite, toggleFavorite, isFavorite, // 拖拽方法 onLongPressStart, onLongPressCancel, onDragStart, onDragOver, onDrop, onDragEnd, reorder, // 工具方法 loadFavorites, saveFavorites, resetDragging } }