Merge branch 'dev' into feature/qr-upload-hint
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / e2e-test (push) Has been cancelled
Test / build-check (push) Has been cancelled
Test / unit-test (push) Has been cancelled
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 14s
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / e2e-test (push) Has been cancelled
Test / build-check (push) Has been cancelled
Test / unit-test (push) Has been cancelled
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 14s
# Conflicts: # frontend/src/components/RecipeDetailOverlay.vue
This commit is contained in:
@@ -119,7 +119,7 @@ async function submit() {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.35);
|
||||
z-index: 5000;
|
||||
z-index: 6000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@@ -36,6 +36,17 @@
|
||||
>English</button>
|
||||
</div>
|
||||
|
||||
<!-- Volume selector -->
|
||||
<div class="volume-controls card-volume-controls">
|
||||
<button
|
||||
v-for="(drops, ml) in VOLUME_DROPS"
|
||||
:key="ml"
|
||||
class="volume-btn"
|
||||
:class="{ active: selectedCardVolume === ml }"
|
||||
@click="onCardVolumeChange(ml)"
|
||||
>{{ ml === '单次' ? '单次' : ml + 'ml' }}</button>
|
||||
</div>
|
||||
|
||||
<!-- QR / brand upload hint -->
|
||||
<div v-if="showBrandHint" class="brand-upload-hint">
|
||||
<span class="hint-icon">✨</span>
|
||||
@@ -382,6 +393,7 @@ const viewMode = ref('card')
|
||||
const cardRef = ref(null)
|
||||
const cardImageUrl = ref(null)
|
||||
const cardLang = ref('zh')
|
||||
const selectedCardVolume = ref('单次')
|
||||
const showTranslationEditor = ref(false)
|
||||
const customRecipeNameEn = ref('')
|
||||
const customOilNameEn = ref({})
|
||||
@@ -547,9 +559,20 @@ function copyText() {
|
||||
})
|
||||
}
|
||||
|
||||
function applyTranslation() {
|
||||
// translations stored in customOilNameEn / customRecipeNameEn
|
||||
async function applyTranslation() {
|
||||
showTranslationEditor.value = false
|
||||
// Persist en_name to backend
|
||||
if (recipe.value._id && customRecipeNameEn.value) {
|
||||
try {
|
||||
await api.put(`/api/recipes/${recipe.value._id}`, {
|
||||
en_name: customRecipeNameEn.value,
|
||||
version: recipe.value._version,
|
||||
})
|
||||
ui.showToast('翻译已保存')
|
||||
} catch (e) {
|
||||
ui.showToast('翻译保存失败')
|
||||
}
|
||||
}
|
||||
cardImageUrl.value = null
|
||||
nextTick(() => generateCardImage())
|
||||
}
|
||||
@@ -564,7 +587,7 @@ function getCardOilName(name) {
|
||||
|
||||
function getCardRecipeName() {
|
||||
if (cardLang.value === 'en') {
|
||||
return customRecipeNameEn.value || recipeNameEn(recipe.value.name)
|
||||
return customRecipeNameEn.value || recipe.value.en_name || recipeNameEn(recipe.value.name)
|
||||
}
|
||||
return recipe.value.name
|
||||
}
|
||||
@@ -669,7 +692,7 @@ onMounted(() => {
|
||||
editTags.value = [...(r.tags || [])]
|
||||
editIngredients.value = (r.ingredients || []).map(i => ({ oil: i.oil, drops: i.drops }))
|
||||
// Init translation defaults
|
||||
customRecipeNameEn.value = recipeNameEn(r.name)
|
||||
customRecipeNameEn.value = r.en_name || recipeNameEn(r.name)
|
||||
const enMap = {}
|
||||
;(r.ingredients || []).forEach(ing => {
|
||||
enMap[ing.oil] = oilEn(ing.oil) || ing.oil
|
||||
|
||||
@@ -16,6 +16,7 @@ export const useRecipesStore = defineStore('recipes', () => {
|
||||
_owner_name: r._owner_name ?? r.owner_name ?? '',
|
||||
_version: r._version ?? r.version ?? 1,
|
||||
name: r.name,
|
||||
en_name: r.en_name ?? '',
|
||||
note: r.note ?? '',
|
||||
tags: r.tags ?? [],
|
||||
ingredients: (r.ingredients ?? []).map((ing) => ({
|
||||
|
||||
Reference in New Issue
Block a user