diff --git a/frontend/src/components/CustomDialog.vue b/frontend/src/components/CustomDialog.vue index b862f5b..c3a28c9 100644 --- a/frontend/src/components/CustomDialog.vue +++ b/frontend/src/components/CustomDialog.vue @@ -11,8 +11,8 @@ ref="promptInput" />
- - + +
diff --git a/frontend/src/components/RecipeDetailOverlay.vue b/frontend/src/components/RecipeDetailOverlay.vue index 0fdb13b..9515255 100644 --- a/frontend/src/components/RecipeDetailOverlay.vue +++ b/frontend/src/components/RecipeDetailOverlay.vue @@ -36,12 +36,6 @@ >English - -
- - 上传你的专属二维码,生成属于自己的配方卡片 -
-
@@ -361,6 +355,7 @@ import { useAuthStore } from '../stores/auth' import { useUiStore } from '../stores/ui' import { useDiaryStore } from '../stores/diary' import { api } from '../composables/useApi' +import { showConfirm } from '../composables/useDialog' import { oilEn, recipeNameEn } from '../composables/useOilTranslation' // TagPicker replaced with inline tag editing @@ -481,6 +476,14 @@ async function loadBrand() { } catch { brand.value = {} } + // Show upload prompt if user hasn't set up brand assets yet + if (showBrandHint.value) { + const ok = await showConfirm( + '上传你的专属二维码,让配方卡片更专业 ✨', + { okText: '去上传', cancelText: '取消' } + ) + if (ok) goUploadQr() + } } // Whether to show the brand/QR upload hint (show to all users who haven't set up brand assets) diff --git a/frontend/src/composables/useDialog.js b/frontend/src/composables/useDialog.js index 1a43287..07688af 100644 --- a/frontend/src/composables/useDialog.js +++ b/frontend/src/composables/useDialog.js @@ -5,6 +5,8 @@ export const dialogState = reactive({ type: 'alert', // 'alert', 'confirm', 'prompt' message: '', defaultValue: '', + okText: '', + cancelText: '', resolve: null }) @@ -13,15 +15,19 @@ export function showAlert(msg) { dialogState.visible = true dialogState.type = 'alert' dialogState.message = msg + dialogState.okText = '' + dialogState.cancelText = '' dialogState.resolve = resolve }) } -export function showConfirm(msg) { +export function showConfirm(msg, opts = {}) { return new Promise(resolve => { dialogState.visible = true dialogState.type = 'confirm' dialogState.message = msg + dialogState.okText = opts.okText || '' + dialogState.cancelText = opts.cancelText || '' dialogState.resolve = resolve }) } diff --git a/frontend/src/views/MyDiary.vue b/frontend/src/views/MyDiary.vue index cbe657e..95a5c60 100644 --- a/frontend/src/views/MyDiary.vue +++ b/frontend/src/views/MyDiary.vue @@ -107,6 +107,11 @@
+ +
+ 📋 上传完成后可返回配方卡片 + +

🏷️ 品牌设置

@@ -232,6 +237,7 @@ const router = useRouter() const activeTab = ref('brand') const pasteText = ref('') const selectedDiaryId = ref(null) +const returnRecipeId = ref(null) const selectedDiary = ref(null) const newEntryText = ref('') @@ -266,8 +272,16 @@ onMounted(async () => { await diaryStore.loadDiary() displayName.value = auth.user.display_name || '' await loadBrandSettings() + returnRecipeId.value = localStorage.getItem('oil_return_recipe_id') || null }) +function goBackToRecipe() { + if (returnRecipeId.value) { + localStorage.removeItem('oil_return_recipe_id') + router.push('/?openRecipe=' + encodeURIComponent(returnRecipeId.value)) + } +} + function selectDiary(d) { const id = d._id || d.id selectedDiaryId.value = id @@ -755,6 +769,39 @@ async function applyBusiness() { border-color: #7ec6a4; } +/* Return banner */ +.return-banner { + display: flex; + align-items: center; + justify-content: space-between; + background: #f0faf5; + border: 1.5px solid #7ec6a4; + border-radius: 12px; + padding: 10px 14px; + margin-bottom: 14px; + font-size: 13px; + color: #3e7d5a; + gap: 10px; +} + +.btn-return { + background: linear-gradient(135deg, #7ec6a4 0%, #4a9d7e 100%); + color: #fff; + border: none; + border-radius: 8px; + padding: 6px 14px; + font-size: 12px; + cursor: pointer; + font-family: inherit; + font-weight: 500; + white-space: nowrap; + flex-shrink: 0; +} + +.btn-return:hover { + opacity: 0.9; +} + /* Brand */ .form-group { margin-bottom: 14px;