fix: 去重只检查目标库,跳过后继续处理下一条
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Failing after 6s
Test / e2e-test (push) Has been skipped
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Failing after 5s
PR Preview / deploy-preview (pull_request) Has been skipped
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Failing after 6s
Test / e2e-test (push) Has been skipped
Test / build-check (push) Successful in 4s
PR Preview / test (pull_request) Failing after 5s
PR Preview / deploy-preview (pull_request) Has been skipped
- checkDupName 接受 target 参数,只查目标库(公共/个人) - 提取 skipCurrentParsed/dedupOrSkip 避免代码重复 - 共享到公共库检查公共库,保存到个人检查个人 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -987,18 +987,18 @@ function toggleFormTag(tag) {
|
|||||||
* Same name + different content → show diff, prompt rename, loop until unique.
|
* Same name + different content → show diff, prompt rename, loop until unique.
|
||||||
* Returns final name or false if cancelled.
|
* Returns final name or false if cancelled.
|
||||||
*/
|
*/
|
||||||
async function checkDupName(name, ings) {
|
async function checkDupName(name, ings, target = 'diary') {
|
||||||
let currentName = name
|
let currentName = name
|
||||||
while (true) {
|
while (true) {
|
||||||
const pubDup = recipeStore.recipes.find(r => r.name === currentName)
|
const dup = target === 'public'
|
||||||
const diaryDup = diaryStore.userDiary.find(d => d.name === currentName)
|
? recipeStore.recipes.find(r => r.name === currentName)
|
||||||
const dup = pubDup || diaryDup
|
: diaryStore.userDiary.find(d => d.name === currentName)
|
||||||
if (!dup) return currentName
|
if (!dup) return currentName
|
||||||
|
|
||||||
const dupIngs = (dup.ingredients || []).filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
|
const dupIngs = (dup.ingredients || []).filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
|
||||||
const myIngs = ings.filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
|
const myIngs = ings.filter(i => i.oil).sort((a, b) => a.oil.localeCompare(b.oil))
|
||||||
const identical = dupIngs.length === myIngs.length && dupIngs.every((d, i) => d.oil === myIngs[i].oil && d.drops === myIngs[i].drops)
|
const identical = dupIngs.length === myIngs.length && dupIngs.every((d, i) => d.oil === myIngs[i].oil && d.drops === myIngs[i].drops)
|
||||||
const where = pubDup ? '公共配方库' : '我的配方'
|
const where = target === 'public' ? '公共配方库' : '我的配方'
|
||||||
|
|
||||||
if (identical) {
|
if (identical) {
|
||||||
ui.showToast(`${where}中已有一模一样的配方「${currentName}」`)
|
ui.showToast(`${where}中已有一模一样的配方「${currentName}」`)
|
||||||
@@ -1046,45 +1046,6 @@ async function saveCurrentRecipe() {
|
|||||||
tags: formTags.value,
|
tags: formTags.value,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dedup check for new recipes (not editing)
|
|
||||||
if (!editingRecipe.value) {
|
|
||||||
const result = await checkDupName(diaryPayload.name, cleanIngs)
|
|
||||||
if (result === false) {
|
|
||||||
// Skipped — but if in multi-recipe queue, load next
|
|
||||||
if (parsedCurrentIndex.value >= 0) {
|
|
||||||
const skipIdx = parsedCurrentIndex.value
|
|
||||||
// Prevent syncFormToParsed from overwriting next recipe
|
|
||||||
parsedCurrentIndex.value = -1
|
|
||||||
parsedRecipes.value.splice(skipIdx, 1)
|
|
||||||
if (parsedRecipes.value.length > 0) {
|
|
||||||
const next = Math.min(skipIdx, parsedRecipes.value.length - 1)
|
|
||||||
parsedCurrentIndex.value = next
|
|
||||||
formName.value = parsedRecipes.value[next].name
|
|
||||||
const cocoIng = parsedRecipes.value[next].ingredients.find(i => i.oil === '椰子油')
|
|
||||||
const eoIngs = parsedRecipes.value[next].ingredients.filter(i => i.oil !== '椰子油')
|
|
||||||
formIngredients.value = eoIngs.length > 0
|
|
||||||
? eoIngs.map(i => ({ ...i, _search: i.oil, _open: false }))
|
|
||||||
: [{ oil: '', drops: 1, _search: '', _open: false }]
|
|
||||||
if (cocoIng) {
|
|
||||||
formCocoRow.value = { oil: '椰子油', drops: cocoIng.drops, _search: '椰子油', _open: false }
|
|
||||||
formVolume.value = 'single'
|
|
||||||
} else {
|
|
||||||
formCocoRow.value = null
|
|
||||||
formVolume.value = ''
|
|
||||||
}
|
|
||||||
ui.showToast('已跳过,请处理下一条')
|
|
||||||
} else {
|
|
||||||
closeOverlay()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (result !== diaryPayload.name) {
|
|
||||||
formName.value = result
|
|
||||||
diaryPayload.name = result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (editingRecipe.value && editingRecipe.value._diary_id) {
|
if (editingRecipe.value && editingRecipe.value._diary_id) {
|
||||||
// Editing an existing diary recipe
|
// Editing an existing diary recipe
|
||||||
try {
|
try {
|
||||||
@@ -1126,14 +1087,15 @@ async function saveCurrentRecipe() {
|
|||||||
if (auth.canManage) {
|
if (auth.canManage) {
|
||||||
const toPublic = await showConfirm('保存到哪里?', { okText: '公共配方库', cancelText: '个人配方' })
|
const toPublic = await showConfirm('保存到哪里?', { okText: '公共配方库', cancelText: '个人配方' })
|
||||||
if (toPublic) {
|
if (toPublic) {
|
||||||
|
const finalName = await dedupOrSkip(diaryPayload.name, cleanIngs, 'public')
|
||||||
|
if (!finalName) return
|
||||||
try {
|
try {
|
||||||
const pubPayload = {
|
await recipeStore.saveRecipe({
|
||||||
name: formName.value.trim(),
|
name: finalName,
|
||||||
ingredients: cleanIngs.map(i => ({ oil_name: i.oil, drops: i.drops })),
|
ingredients: cleanIngs.map(i => ({ oil_name: i.oil, drops: i.drops })),
|
||||||
note: formNote.value,
|
note: formNote.value,
|
||||||
tags: formTags.value,
|
tags: formTags.value,
|
||||||
}
|
})
|
||||||
await recipeStore.saveRecipe(pubPayload)
|
|
||||||
ui.showToast('已添加到公共配方库')
|
ui.showToast('已添加到公共配方库')
|
||||||
if (!loadNextParsed()) closeOverlay()
|
if (!loadNextParsed()) closeOverlay()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1142,6 +1104,10 @@ async function saveCurrentRecipe() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const finalName = await dedupOrSkip(diaryPayload.name, cleanIngs, 'diary')
|
||||||
|
if (!finalName) return
|
||||||
|
diaryPayload.name = finalName
|
||||||
|
formName.value = finalName
|
||||||
try {
|
try {
|
||||||
await diaryStore.createDiary(diaryPayload)
|
await diaryStore.createDiary(diaryPayload)
|
||||||
ui.showToast('已添加到我的配方')
|
ui.showToast('已添加到我的配方')
|
||||||
@@ -1180,7 +1146,7 @@ async function saveAllParsed() {
|
|||||||
const r = parsedRecipes.value[i]
|
const r = parsedRecipes.value[i]
|
||||||
if (!r.name.trim() || r.ingredients.length === 0) continue
|
if (!r.name.trim() || r.ingredients.length === 0) continue
|
||||||
const ings = r.ingredients.map(ing => ({ oil: ing.oil, drops: ing.drops }))
|
const ings = r.ingredients.map(ing => ({ oil: ing.oil, drops: ing.drops }))
|
||||||
const finalName = await checkDupName(r.name.trim(), ings)
|
const finalName = await checkDupName(r.name.trim(), ings, toPublic ? 'public' : 'diary')
|
||||||
if (finalName === false) { skipped++; continue }
|
if (finalName === false) { skipped++; continue }
|
||||||
try {
|
try {
|
||||||
if (toPublic) {
|
if (toPublic) {
|
||||||
@@ -1202,6 +1168,48 @@ async function saveAllParsed() {
|
|||||||
closeOverlay()
|
closeOverlay()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Skip current parsed recipe and load next, or close if none left. */
|
||||||
|
function skipCurrentParsed() {
|
||||||
|
if (parsedCurrentIndex.value < 0) return
|
||||||
|
const skipIdx = parsedCurrentIndex.value
|
||||||
|
parsedCurrentIndex.value = -1
|
||||||
|
parsedRecipes.value.splice(skipIdx, 1)
|
||||||
|
if (parsedRecipes.value.length > 0) {
|
||||||
|
const next = Math.min(skipIdx, parsedRecipes.value.length - 1)
|
||||||
|
parsedCurrentIndex.value = next
|
||||||
|
const r = parsedRecipes.value[next]
|
||||||
|
formName.value = r.name
|
||||||
|
const cocoIng = r.ingredients.find(i => i.oil === '椰子油')
|
||||||
|
const eoIngs = r.ingredients.filter(i => i.oil !== '椰子油')
|
||||||
|
formIngredients.value = eoIngs.length > 0
|
||||||
|
? eoIngs.map(i => ({ ...i, _search: i.oil, _open: false }))
|
||||||
|
: [{ oil: '', drops: 1, _search: '', _open: false }]
|
||||||
|
if (cocoIng) {
|
||||||
|
formCocoRow.value = { oil: '椰子油', drops: cocoIng.drops, _search: '椰子油', _open: false }
|
||||||
|
formVolume.value = 'single'
|
||||||
|
} else {
|
||||||
|
formCocoRow.value = null
|
||||||
|
formVolume.value = ''
|
||||||
|
}
|
||||||
|
ui.showToast('已跳过,请处理下一条')
|
||||||
|
} else {
|
||||||
|
closeOverlay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run dedup check for saveCurrentRecipe. Returns final name or null if should stop.
|
||||||
|
*/
|
||||||
|
async function dedupOrSkip(name, ings, target) {
|
||||||
|
if (editingRecipe.value) return name
|
||||||
|
const result = await checkDupName(name, ings, target)
|
||||||
|
if (result === false) {
|
||||||
|
if (parsedCurrentIndex.value >= 0) skipCurrentParsed()
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
/** After saving, mark current as done and load next. Returns true if there's a next one. */
|
/** After saving, mark current as done and load next. Returns true if there's a next one. */
|
||||||
function loadNextParsed() {
|
function loadNextParsed() {
|
||||||
if (parsedCurrentIndex.value < 0 || parsedRecipes.value.length === 0) return false
|
if (parsedCurrentIndex.value < 0 || parsedRecipes.value.length === 0) return false
|
||||||
@@ -1478,7 +1486,7 @@ async function recommendApprove(recipe) {
|
|||||||
|
|
||||||
async function shareDiaryToPublic(diary) {
|
async function shareDiaryToPublic(diary) {
|
||||||
const ings = (diary.ingredients || []).map(i => ({ oil: i.oil, drops: i.drops }))
|
const ings = (diary.ingredients || []).map(i => ({ oil: i.oil, drops: i.drops }))
|
||||||
const result = await checkDupName(diary.name, ings)
|
const result = await checkDupName(diary.name, ings, 'public')
|
||||||
if (result === false) return
|
if (result === false) return
|
||||||
if (result !== diary.name) diary = { ...diary, name: result }
|
if (result !== diary.name) diary = { ...diary, name: result }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user