diff --git a/src/components/PresetManager.vue b/src/components/PresetManager.vue index b9db6e8..f34333c 100644 --- a/src/components/PresetManager.vue +++ b/src/components/PresetManager.vue @@ -90,7 +90,9 @@ const filteredPresets = computed(() => { } // Filter by Folder - if (selectedFolderId.value) { + if (selectedFolderId.value === 'favorites') { + presets = presets.filter(p => p.isFavorite); + } else if (selectedFolderId.value) { presets = presets.filter(p => p.folderId === selectedFolderId.value); } else if (selectedFolderId.value === '') { // Uncategorized @@ -137,6 +139,7 @@ const flattenedFolders = computed(() => { const allPresetsCount = computed(() => (store.extendedPresets || []).length); const uncategorizedCount = computed(() => (store.extendedPresets || []).filter(p => !p.folderId).length); +const favoritesCount = computed(() => (store.extendedPresets || []).filter(p => p.isFavorite).length); // Actions function handleFolderSelect(id: string | null) { @@ -262,6 +265,13 @@ function deletePreset(preset: ExtendedPreset) { } } +function toggleFavorite(preset: ExtendedPreset) { + store.updateExtendedPreset(preset.id, { isFavorite: !preset.isFavorite }); + if (!preset.isFavorite) { + showNotification(`已添加到收藏`, 'success'); + } +} + async function copyPresetContent(preset: ExtendedPreset) { try { await navigator.clipboard.writeText(preset.content); @@ -327,9 +337,11 @@ const shareLoading = ref(false); const shareResultCode = ref(''); const shareImportCode = ref(''); const shareSinglePreset = ref(null); +const shareFolder = ref(null); -function openShareDialog(preset?: ExtendedPreset) { +function openShareDialog(preset?: ExtendedPreset, folder?: PresetFolder) { shareSinglePreset.value = preset || null; + shareFolder.value = folder || null; shareTab.value = 'create'; shareResultCode.value = ''; shareImportCode.value = ''; @@ -340,6 +352,10 @@ function handleShare(preset: ExtendedPreset) { openShareDialog(preset); } +function handleShareFolder(folder: PresetFolder) { + openShareDialog(undefined, folder); +} + async function generateShareCode() { shareLoading.value = true; try { @@ -349,6 +365,33 @@ async function generateShareCode() { if (shareSinglePreset.value) { data = shareSinglePreset.value; type = 'single'; + } else if (shareFolder.value) { + // Find all presets in this folder and its subfolders? + // User likely just wants this folder and its direct contents, OR the whole tree. + // Simplest is recursive export of folder + subfolders + presets inside them. + + const folderIds = new Set(); + const foldersToExport: PresetFolder[] = []; + + const collectFolders = (id: string) => { + const folder = store.presetFolders.find(f => f.id === id); + if (folder) { + folderIds.add(id); + foldersToExport.push(folder); + // Find subfolders + store.presetFolders.filter(f => f.parentId === id).forEach(f => collectFolders(f.id)); + } + }; + + collectFolders(shareFolder.value.id); + + const presetsToExport = store.extendedPresets.filter(p => p.folderId && folderIds.has(p.folderId)); + + data = { + presetFolders: foldersToExport, + extendedPresets: presetsToExport + }; + type = 'folder'; } else { const jsonString = store.exportPresetsToJson(); try { @@ -594,6 +637,7 @@ function closeShareDialog() { shareResultCode.value = ''; shareImportCode.value = ''; shareSinglePreset.value = null; + shareFolder.value = null; } // Helpers @@ -648,12 +692,14 @@ onMounted(() => { :expanded-ids="expandedFolderIds" :all-count="allPresetsCount" :uncategorized-count="uncategorizedCount" + :favorites-count="favoritesCount" @update:selected-folder-id="handleFolderSelect" @toggle-expand="handleToggleExpand" @create-folder="createFolder()" @create-sub-folder="createFolder" @edit-folder="editFolder" @delete-folder="deleteFolder" + @share-folder="handleShareFolder" /> @@ -721,14 +767,15 @@ onMounted(() => {
+ :presets="filteredPresets" + :search-query="searchQuery" + @apply="applyPreset" + @edit="editPreset" + @delete="deletePreset" + @copy="copyPresetContent" + @share="handleShare" + @toggle-favorite="toggleFavorite" + />
@@ -867,6 +914,9 @@ onMounted(() => {

正在分享预设: {{ shareSinglePreset.name }}

+

+ 正在分享文件夹: {{ shareFolder.name }} +

正在分享: 所有预设数据

diff --git a/src/components/preset/FolderTreeItem.vue b/src/components/preset/FolderTreeItem.vue index 1a06136..b3bd0f5 100644 --- a/src/components/preset/FolderTreeItem.vue +++ b/src/components/preset/FolderTreeItem.vue @@ -21,6 +21,7 @@ const emit = defineEmits<{ (e: 'create-sub', parentId: string): void; (e: 'edit', folder: PresetFolder): void; (e: 'delete', folder: PresetFolder): void; + (e: 'share', folder: PresetFolder): void; }>(); const isExpanded = computed(() => props.expandedIds.has(props.folder.id)); @@ -85,6 +86,15 @@ const showActions = ref(false);
+
diff --git a/src/components/preset/PresetList.vue b/src/components/preset/PresetList.vue index 31fd777..f48730e 100644 --- a/src/components/preset/PresetList.vue +++ b/src/components/preset/PresetList.vue @@ -13,6 +13,7 @@ const emit = defineEmits<{ (e: 'delete', preset: ExtendedPreset): void; (e: 'copy', preset: ExtendedPreset): void; (e: 'share', preset: ExtendedPreset): void; + (e: 'toggle-favorite', preset: ExtendedPreset): void; }>(); function getTypeIcon(type: PresetType) { @@ -61,6 +62,11 @@ function formatDate(dateStr: string) {

{{ preset.name }}

+
+ + diff --git a/src/types.ts b/src/types.ts index e7146f4..b2a8deb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -86,6 +86,7 @@ export interface ExtendedPreset { updatedAt: string; isPublic?: boolean; author?: string; + isFavorite?: boolean; } // 预设文件夹