From b69abe0fdb5743d0b4d3a207f5e85579e78432c3 Mon Sep 17 00:00:00 2001 From: Hera Zhao Date: Thu, 9 Apr 2026 17:04:00 +0000 Subject: [PATCH] =?UTF-8?q?rewrite:=20=E8=8B=B1=E6=96=87=E5=90=8D=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E8=AF=BB=E5=86=99=20oils.en=5Fname=EF=BC=8C=E4=B8=89?= =?UTF-8?q?=E5=A4=84=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 核心设计: oils.en_name (DB) 是唯一数据源 读取链路 (全部统一): - 精油价目: getEnglishName → oilsMeta.enName → oilEn() - 配方卡片: getCardOilName → oilsMeta.enName → oilEn() - 翻译编辑器: openTranslationEditor → oilsMeta.enName 写入链路 (全部写同一个字段): - 精油价目编辑: saveEditOil → oilsStore.saveOil → oils.en_name → loadOils - 配方卡翻译: applyTranslation → oilsStore.saveOil → oils.en_name → loadOils - 配方名翻译: applyTranslation → PUT /api/recipes/{id} → recipes.en_name → loadRecipes 保存后: - await Promise.all([loadOils(), loadRecipes()]) 刷新所有数据 - 下次任何地方渲染都读到最新值 - customOilNameEn 只在编辑器打开期间有效,关闭后丢弃 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/components/RecipeDetailOverlay.vue | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/RecipeDetailOverlay.vue b/frontend/src/components/RecipeDetailOverlay.vue index 0d9a40a..d6ad844 100644 --- a/frontend/src/components/RecipeDetailOverlay.vue +++ b/frontend/src/components/RecipeDetailOverlay.vue @@ -596,41 +596,41 @@ function copyText() { } function openTranslationEditor() { - // Pre-populate with existing English names from DB/translation table + // Pre-populate from single source of truth: oilsMeta.enName (DB) const map = {} for (const ing of cardIngredients.value) { - const existing = oilsStore.oilsMeta[ing.oil]?.enName || oilEn(ing.oil) - if (existing) map[ing.oil] = existing + map[ing.oil] = getOilEnglish(ing.oil) } customOilNameEn.value = map - customRecipeNameEn.value = recipe.value.en_name || recipeNameEn(recipe.value.name) + customRecipeNameEn.value = recipe.value.en_name || '' showTranslationEditor.value = true } async function applyTranslation() { showTranslationEditor.value = false let saved = 0 + let failed = 0 - // 1. Save recipe English name (no version check — only updating en_name) - if (recipe.value._id && customRecipeNameEn.value) { + // 1. Save recipe English name to recipes table + if (recipe.value._id && customRecipeNameEn.value.trim()) { try { await api.put(`/api/recipes/${recipe.value._id}`, { - en_name: customRecipeNameEn.value, + en_name: customRecipeNameEn.value.trim(), }) - recipe.value.en_name = customRecipeNameEn.value saved++ } catch (e) { console.error('Save recipe en_name failed:', e) + failed++ } } - // 2. Save each oil's English name to oils table (syncs with oil reference page) - let failed = 0 + // 2. Save each oil's English name to oils table + // This is THE single source of truth — both oil reference page and recipe card read from here for (const [oilName, enName] of Object.entries(customOilNameEn.value)) { if (!enName?.trim()) continue const meta = oilsStore.oilsMeta[oilName] if (!meta) continue - if (meta.enName === enName.trim()) continue + if (meta.enName === enName.trim()) continue // no change try { await oilsStore.saveOil(oilName, meta.bottlePrice, meta.dropCount, meta.retailPrice, enName.trim()) saved++ @@ -640,25 +640,38 @@ async function applyTranslation() { } } + // 3. Reload ALL data — this updates oilsMeta.enName and recipe.en_name + // So the next render reads fresh data from the single source + await Promise.all([ + oilsStore.loadOils(), + recipesStore.loadRecipes(), + ]) + if (saved > 0) { ui.showToast(`翻译已保存(${saved}项)` + (failed > 0 ? `,${failed}项失败` : '')) - // Reload data so next open shows updated names - recipesStore.loadRecipes() - oilsStore.loadOils() } else if (failed > 0) { ui.showToast(`保存失败 ${failed} 项`) } else { ui.showToast('没有修改') } + // Regenerate card image with updated names from store cardImageUrl.value = null nextTick(() => generateCardImage()) } // Override translation getters for card rendering +function getOilEnglish(name) { + return oilsStore.oilsMeta[name]?.enName || oilEn(name) || '' +} + function getCardOilName(name) { if (cardLang.value === 'en') { - return customOilNameEn.value[name] || oilsStore.oilsMeta[name]?.enName || oilEn(name) || name + // During editing, use customOilNameEn; otherwise read from store (single source of truth) + if (showTranslationEditor.value && customOilNameEn.value[name]) { + return customOilNameEn.value[name] + } + return getOilEnglish(name) || name } return name }