Private
Public Access
1
0
Files
u-desk/web/src/composables/useFavoriteFiles.js
绝尘 eb2cbad17b 优化:代码质量提升,修复重复逻辑和语法高亮支持
- 简化计算属性,删除重复代码
- 优化文件扩展名获取逻辑
- 新增文件工具函数库 fileHelpers.js
- 增强 CodeEditor 语法高亮(支持 30+ 语言)
- 修复 Office 文档文件服务器访问权限
- 添加特殊文件名支持(Dockerfile、Makefile 等)
2026-01-30 02:29:51 +08:00

321 lines
8.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 收藏夹管理 composable
*
* @module composables/useFavoriteFiles
* @description 封装收藏夹的增删改查逻辑,支持持久化存储
*/
import { ref, onMounted } from 'vue'
import { Message } from '@arco-design/web-vue'
import { useLocalStorage } from './useLocalStorage'
/**
* 收藏夹 composable
* @param {string} storageKey - localStorage 键名
* @param {Object} [options] - 配置选项
* @param {number} [options.maxLength=50] - 最大收藏数量
* @param {Function} [options.onAdd] - 添加收藏回调
* @param {Function} [options.onRemove] - 移除收藏回调
* @returns {UseFavoriteFilesReturn} 收藏夹操作API
*
* @example
* const {
* favoriteFiles,
* isFavorite,
* toggleFavorite,
* removeFavorite,
* clearAll
* } = useFavoriteFiles('app-favorites')
*
* // 在模板中使用
* <a-button @click="toggleFavorite(file)">
* <icon-star-fill v-if="isFavorite(file.path)" />
* <icon-star v-else />
* </a-button>
*/
export function useFavoriteFiles(storageKey, options = {}) {
const {
maxLength = 50,
onAdd = () => {},
onRemove = () => {},
} = options
// 使用 localStorage composable 管理收藏列表
const { storedValue: favoriteFiles, load, save } = useLocalStorage(
storageKey,
[]
)
/**
* 判断文件/目录是否已收藏
* @param {string} path - 文件/目录路径
* @returns {boolean} 是否已收藏
*/
const isFavorite = (path) => {
if (!path || !Array.isArray(favoriteFiles.value)) {
return false
}
return favoriteFiles.value.some(fav => fav.path === path)
}
/**
* 排序收藏列表(按创建时间倒序,最新的在上面)
*/
const sortFavorites = () => {
if (!Array.isArray(favoriteFiles.value)) {
return
}
favoriteFiles.value.sort((a, b) => {
const timeA = a.created_at || 0
const timeB = b.created_at || 0
return timeB - timeA // 倒序:最新的在上面
})
}
/**
* 切换收藏状态
* @param {Object} item - 文件/目录信息
* @param {string} item.path - 路径
* @param {string} item.name - 名称
* @param {boolean} item.is_dir - 是否为目录
* @returns {boolean} 操作后是否为收藏状态
*/
const toggleFavorite = (item) => {
if (!item || !item.path) {
Message.warning('无效的文件信息')
return false
}
const index = favoriteFiles.value.findIndex(fav => fav.path === item.path)
if (index > -1) {
// 已收藏,执行取消收藏
favoriteFiles.value.splice(index, 1)
save(favoriteFiles.value) // 直接保存,不重新排序
onRemove(item)
Message.info(`已取消收藏: ${item.name}`)
return false
} else {
// 未收藏,执行添加收藏
if (favoriteFiles.value.length >= maxLength) {
Message.warning(`收藏夹已满,最多只能收藏 ${maxLength}`)
return false
}
favoriteFiles.value.push({
path: item.path,
name: item.name,
is_dir: item.is_dir || false,
created_at: Date.now(), // 添加时间戳(用于 getSortedFavorites
})
save(favoriteFiles.value) // 直接保存,不重新排序(新项目添加到末尾)
onAdd(item)
Message.success(`已收藏: ${item.name}`)
return true
}
}
/**
* 移除收藏
* @param {string} path - 文件/目录路径
* @returns {boolean} 是否成功移除
*/
const removeFavorite = (path) => {
if (!path) {
Message.warning('请提供有效的路径')
return false
}
const index = favoriteFiles.value.findIndex(fav => fav.path === path)
if (index === -1) {
Message.warning('该路径不在收藏夹中')
return false
}
const item = favoriteFiles.value[index]
favoriteFiles.value.splice(index, 1)
save(favoriteFiles.value) // 直接保存,不重新排序
onRemove(item)
Message.info(`已取消收藏: ${item.name}`)
return true
}
/**
* 打开收藏的文件/目录
* @param {string} path - 文件/目录路径
* @param {Function} onOpen - 打开回调函数
* @returns {Promise<boolean>} 是否成功打开
*/
const openFavorite = async (path, onOpen) => {
if (!path || !onOpen) {
return false
}
const item = favoriteFiles.value.find(fav => fav.path === path)
if (!item) {
Message.warning('收藏项不存在')
return false
}
return await onOpen(item)
}
/**
* 清空所有收藏
* @param {boolean} [confirm=true] - 是否需要确认
* @returns {boolean} 是否成功清空
*/
const clearAll = (confirm = true) => {
const executeClear = () => {
const count = favoriteFiles.value.length
favoriteFiles.value = []
save([])
Message.success(`已清空 ${count} 个收藏项`)
return true
}
if (!confirm) {
return executeClear()
}
// 使用原生 confirm简单场景
if (window.confirm(`确定要清空所有 ${favoriteFiles.value.length} 个收藏项吗?`)) {
return executeClear()
}
return false
}
/**
* 获取收藏列表(按创建时间排序)
* @param {string} [order='desc'] - 排序方式:'asc'或'desc'
* @returns {Array} 排序后的收藏列表
*/
const getSortedFavorites = (order = 'desc') => {
const sorted = [...favoriteFiles.value]
sorted.sort((a, b) => {
const timeA = a.created_at || 0
const timeB = b.created_at || 0
return order === 'desc' ? timeB - timeA : timeA - timeB
})
return sorted
}
/**
* 按名称搜索收藏
* @param {string} keyword - 搜索关键词
* @returns {Array} 匹配的收藏列表
*/
const searchFavorites = (keyword) => {
if (!keyword || !keyword.trim()) {
return favoriteFiles.value
}
const lowerKeyword = keyword.toLowerCase().trim()
return favoriteFiles.value.filter(fav =>
fav.name.toLowerCase().includes(lowerKeyword) ||
fav.path.toLowerCase().includes(lowerKeyword)
)
}
/**
* 重新排序收藏列表(拖拽排序)
* @param {number} fromIndex - 源索引
* @param {number} toIndex - 目标索引
* @returns {boolean} 是否成功重排序
*/
const reorderFavorites = (fromIndex, toIndex) => {
if (!Array.isArray(favoriteFiles.value)) {
return false
}
if (fromIndex < 0 || fromIndex >= favoriteFiles.value.length ||
toIndex < 0 || toIndex >= favoriteFiles.value.length) {
return false
}
if (fromIndex === toIndex) {
return false
}
// 移动数组元素
const [movedItem] = favoriteFiles.value.splice(fromIndex, 1)
favoriteFiles.value.splice(toIndex, 0, movedItem)
// 保存新顺序
save(favoriteFiles.value)
return true
}
// 组件挂载时加载数据(不自动排序,保持用户拖拽的顺序)
onMounted(() => {
load()
})
return {
// 状态
favoriteFiles,
// 方法
isFavorite,
toggleFavorite,
removeFavorite,
openFavorite,
clearAll,
getSortedFavorites,
searchFavorites,
sortFavorites,
reorderFavorites,
load,
save,
}
}
/**
* @typedef {Object} UseFavoriteFilesReturn
* @property {Ref<Array>} favoriteFiles - 收藏列表(自动按时间倒序排列)
* @property {Function} isFavorite - 判断是否已收藏
* @property {Function} toggleFavorite - 切换收藏状态
* @property {Function} removeFavorite - 移除收藏
* @property {Function} openFavorite - 打开收藏项
* @property {Function} clearAll - 清空所有收藏
* @property {Function} getSortedFavorites - 获取排序后的列表
* @property {Function} searchFavorites - 搜索收藏
* @property {Function} sortFavorites - 手动排序收藏列表
* @property {Function} reorderFavorites - 拖拽重新排序
* @property {Function} load - 手动加载数据
* @property {Function} save - 手动保存数据
*/
/**
* 创建多个收藏夹管理实例
* @param {Object} config - 配置对象
* @returns {Object} 收藏夹管理实例集合
*
* @example
* const {
* filesystemFavs,
* deviceTestFavs
* } = createMultipleFavorites({
* filesystem: 'app-filesystem-favorites',
* deviceTest: 'app-device-test-favorites'
* })
*/
export function createMultipleFavorites(config) {
const result = {}
Object.keys(config).forEach(key => {
result[key] = useFavoriteFiles(config[key])
})
return result
}