diff --git a/frontend/src/views/RecipeManager.vue b/frontend/src/views/RecipeManager.vue index 3a00be8..ad6fce4 100644 --- a/frontend/src/views/RecipeManager.vue +++ b/frontend/src/views/RecipeManager.vue @@ -65,6 +65,31 @@ + +
+
+ + {{ tag }} + × + +
+
+ + {{ tag }} +
+
+ + +
+
+ + +
+
@@ -550,6 +575,43 @@ function clearSelection() { showBatchMenu.value = false } +function addBatchTag() { + const tag = batchNewTag.value.trim() + if (tag && !batchTagsSelected.value.includes(tag)) { + batchTagsSelected.value.push(tag) + } + batchNewTag.value = '' +} + +async function applyBatchTags() { + const tags = batchTagsSelected.value + if (!tags.length) { ui.showToast('请选择至少一个标签'); return } + const pubIds = [...selectedIds] + const diaryIds = [...selectedDiaryIds] + for (const tagName of tags) { + for (const id of pubIds) { + const recipe = recipeStore.recipes.find(r => r._id === id) + if (recipe && !recipe.tags.includes(tagName)) { + recipe.tags.push(tagName) + await recipeStore.saveRecipe(recipe) + } + } + for (const id of diaryIds) { + const d = diaryStore.userDiary.find(r => r.id === id) + if (d) { + const dtags = [...(d.tags || [])] + if (!dtags.includes(tagName)) { + dtags.push(tagName) + await diaryStore.updateDiary(id, { ...d, tags: dtags }) + } + } + } + } + showBatchTagPicker.value = false + ui.showToast(`已为 ${pubIds.length + diaryIds.length} 个配方添加 ${tags.length} 个标签`) + clearSelection() +} + function doBatch(action) { showBatchMenu.value = false executeBatchAction(action) @@ -601,26 +663,10 @@ async function executeBatchAction(action) { } ui.showToast(`已删除 ${totalCount} 个配方`) } else if (action === 'tag') { - const tagName = await showPrompt('输入要添加的标签:') - if (!tagName) return - for (const id of pubIds) { - const recipe = recipeStore.recipes.find(r => r._id === id) - if (recipe && !recipe.tags.includes(tagName)) { - recipe.tags.push(tagName) - await recipeStore.saveRecipe(recipe) - } - } - for (const id of diaryIds) { - const d = diaryStore.userDiary.find(r => r.id === id) - if (d) { - const tags = [...(d.tags || [])] - if (!tags.includes(tagName)) { - tags.push(tagName) - await diaryStore.updateDiary(id, { ...d, tags }) - } - } - } - ui.showToast(`已为 ${totalCount} 个配方添加标签`) + batchTagsSelected.value = [] + batchNewTag.value = '' + showBatchTagPicker.value = true + return // don't clear selection yet } else if (action === 'share_public') { const ok = await showConfirm(`将 ${diaryIds.length} 个配方分享到公共配方库?`) if (!ok) return @@ -976,6 +1022,9 @@ async function saveAllParsed() { const sharedCount = ref({ adopted: 0, total: 0 }) const previewRecipeIndex = ref(null) const showBatchMenu = ref(false) +const showBatchTagPicker = ref(false) +const batchTagsSelected = ref([]) +const batchNewTag = ref('') const totalSelected = computed(() => selectedIds.size + selectedDiaryIds.size) const isMyAllSelected = computed(() => myFilteredRecipes.value.length > 0 && selectedDiaryIds.size === myFilteredRecipes.value.length) const isPubAllSelected = computed(() => publicFilteredRecipes.value.length > 0 && selectedIds.size === publicFilteredRecipes.value.length) @@ -1641,6 +1690,9 @@ watch(() => recipeStore.recipes, () => { .batch-menu-btn:hover { border-color: #7ec6a4; color: #4a9d7e; } .batch-delete { color: #c0392b; border-color: #e8b4b0; } .batch-delete:hover { background: #fdf0ee; border-color: #c0392b; } +.batch-tag-picker { + padding: 12px; background: #f8faf8; border: 1.5px solid #d4e8d4; border-radius: 10px; margin-bottom: 10px; +} .mini-select { width: 18px; height: 18px; border: 1.5px solid #d4cfc7; border-radius: 4px; background: #fff; color: transparent; font-size: 11px; cursor: pointer;