QR upload: replace inline hint with dialog, add back button in brand page
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 3s
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 12s
Test / e2e-test (push) Failing after 1m21s
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 3s
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 12s
Test / e2e-test (push) Failing after 1m21s
- Replace the inline brand-upload-hint bar in RecipeDetailOverlay with a confirm dialog (「去上传」/「取消」) that pops up when the card opens - Extend useDialog/CustomDialog to support custom ok/cancel button text - Add a 「← 返回配方卡片」banner in MyDiary brand tab when navigated from a recipe card, allowing return without uploading Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,8 +11,8 @@
|
|||||||
ref="promptInput"
|
ref="promptInput"
|
||||||
/>
|
/>
|
||||||
<div class="dialog-btn-row">
|
<div class="dialog-btn-row">
|
||||||
<button v-if="dialogState.type !== 'alert'" class="dialog-btn-outline" @click="cancel">取消</button>
|
<button v-if="dialogState.type !== 'alert'" class="dialog-btn-outline" @click="cancel">{{ dialogState.cancelText || '取消' }}</button>
|
||||||
<button class="dialog-btn-primary" @click="ok">确定</button>
|
<button class="dialog-btn-primary" @click="ok">{{ dialogState.okText || '确定' }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -36,12 +36,6 @@
|
|||||||
>English</button>
|
>English</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- QR / brand upload hint -->
|
|
||||||
<div v-if="showBrandHint" class="brand-upload-hint">
|
|
||||||
<span class="hint-icon">✨</span>
|
|
||||||
<span>上传你的专属二维码,生成属于自己的配方卡片</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card image (rendered by html2canvas) -->
|
<!-- Card image (rendered by html2canvas) -->
|
||||||
<div v-show="!cardImageUrl" ref="cardRef" class="export-card">
|
<div v-show="!cardImageUrl" ref="cardRef" class="export-card">
|
||||||
<!-- Brand overlay layers -->
|
<!-- Brand overlay layers -->
|
||||||
@@ -361,6 +355,7 @@ import { useAuthStore } from '../stores/auth'
|
|||||||
import { useUiStore } from '../stores/ui'
|
import { useUiStore } from '../stores/ui'
|
||||||
import { useDiaryStore } from '../stores/diary'
|
import { useDiaryStore } from '../stores/diary'
|
||||||
import { api } from '../composables/useApi'
|
import { api } from '../composables/useApi'
|
||||||
|
import { showConfirm } from '../composables/useDialog'
|
||||||
import { oilEn, recipeNameEn } from '../composables/useOilTranslation'
|
import { oilEn, recipeNameEn } from '../composables/useOilTranslation'
|
||||||
// TagPicker replaced with inline tag editing
|
// TagPicker replaced with inline tag editing
|
||||||
|
|
||||||
@@ -481,6 +476,14 @@ async function loadBrand() {
|
|||||||
} catch {
|
} catch {
|
||||||
brand.value = {}
|
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)
|
// Whether to show the brand/QR upload hint (show to all users who haven't set up brand assets)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ export const dialogState = reactive({
|
|||||||
type: 'alert', // 'alert', 'confirm', 'prompt'
|
type: 'alert', // 'alert', 'confirm', 'prompt'
|
||||||
message: '',
|
message: '',
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
|
okText: '',
|
||||||
|
cancelText: '',
|
||||||
resolve: null
|
resolve: null
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -13,15 +15,19 @@ export function showAlert(msg) {
|
|||||||
dialogState.visible = true
|
dialogState.visible = true
|
||||||
dialogState.type = 'alert'
|
dialogState.type = 'alert'
|
||||||
dialogState.message = msg
|
dialogState.message = msg
|
||||||
|
dialogState.okText = ''
|
||||||
|
dialogState.cancelText = ''
|
||||||
dialogState.resolve = resolve
|
dialogState.resolve = resolve
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showConfirm(msg) {
|
export function showConfirm(msg, opts = {}) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
dialogState.visible = true
|
dialogState.visible = true
|
||||||
dialogState.type = 'confirm'
|
dialogState.type = 'confirm'
|
||||||
dialogState.message = msg
|
dialogState.message = msg
|
||||||
|
dialogState.okText = opts.okText || ''
|
||||||
|
dialogState.cancelText = opts.cancelText || ''
|
||||||
dialogState.resolve = resolve
|
dialogState.resolve = resolve
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,11 @@
|
|||||||
|
|
||||||
<!-- Brand Tab -->
|
<!-- Brand Tab -->
|
||||||
<div v-if="activeTab === 'brand'" class="tab-content">
|
<div v-if="activeTab === 'brand'" class="tab-content">
|
||||||
|
<!-- Back to recipe card (when navigated from a recipe) -->
|
||||||
|
<div v-if="returnRecipeId" class="return-banner">
|
||||||
|
<span>📋 上传完成后可返回配方卡片</span>
|
||||||
|
<button class="btn-return" @click="goBackToRecipe">← 返回配方卡片</button>
|
||||||
|
</div>
|
||||||
<div class="section-card">
|
<div class="section-card">
|
||||||
<h4>🏷️ 品牌设置</h4>
|
<h4>🏷️ 品牌设置</h4>
|
||||||
|
|
||||||
@@ -232,6 +237,7 @@ const router = useRouter()
|
|||||||
const activeTab = ref('brand')
|
const activeTab = ref('brand')
|
||||||
const pasteText = ref('')
|
const pasteText = ref('')
|
||||||
const selectedDiaryId = ref(null)
|
const selectedDiaryId = ref(null)
|
||||||
|
const returnRecipeId = ref(null)
|
||||||
const selectedDiary = ref(null)
|
const selectedDiary = ref(null)
|
||||||
const newEntryText = ref('')
|
const newEntryText = ref('')
|
||||||
|
|
||||||
@@ -266,8 +272,16 @@ onMounted(async () => {
|
|||||||
await diaryStore.loadDiary()
|
await diaryStore.loadDiary()
|
||||||
displayName.value = auth.user.display_name || ''
|
displayName.value = auth.user.display_name || ''
|
||||||
await loadBrandSettings()
|
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) {
|
function selectDiary(d) {
|
||||||
const id = d._id || d.id
|
const id = d._id || d.id
|
||||||
selectedDiaryId.value = id
|
selectedDiaryId.value = id
|
||||||
@@ -755,6 +769,39 @@ async function applyBusiness() {
|
|||||||
border-color: #7ec6a4;
|
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 */
|
/* Brand */
|
||||||
.form-group {
|
.form-group {
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
|
|||||||
Reference in New Issue
Block a user