增加内置浏览器打开引导

This commit is contained in:
yml
2026-06-15 00:55:12 +08:00
parent 4a0d615926
commit 2a8c1e5c37
3 changed files with 200 additions and 0 deletions
+1
View File
@@ -61,6 +61,7 @@ declare module 'vue' {
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
InAppBrowserPrompt: typeof import('./src/components/InAppBrowserPrompt.vue')['default']
MobileBottomNav: typeof import('./src/components/MobileBottomNav.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
+2
View File
@@ -3,6 +3,7 @@ import { RouterView } from 'vue-router'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import InAppBrowserPrompt from './components/InAppBrowserPrompt.vue'
import AdminLayout from './layouts/AdminLayout.vue'
import AppLayout from './layouts/AppLayout.vue'
@@ -24,4 +25,5 @@ const layout = computed(() => {
<AppLayout v-else>
<RouterView />
</AppLayout>
<InAppBrowserPrompt />
</template>
@@ -0,0 +1,197 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
const promptStorageKey = 'hfb_in_app_browser_prompt_seen'
const visible = ref(false)
const browserName = ref('')
function detectInAppBrowser(userAgent: string) {
const ua = userAgent.toLowerCase()
if (ua.includes('micromessenger')) return 'wechat'
if (/\bqq\//i.test(userAgent) || ua.includes('mqqbrowser')) return 'qq'
return ''
}
function storageGet(key: string) {
try {
return window.sessionStorage.getItem(key)
} catch {
return null
}
}
function storageSet(key: string, value: string) {
try {
window.sessionStorage.setItem(key, value)
} catch {
// sessionStorage 不可用时只影响“本次会话只提醒一次”,不阻断页面使用。
}
}
function closePrompt() {
storageSet(promptStorageKey, '1')
visible.value = false
}
onMounted(() => {
const browser = detectInAppBrowser(window.navigator.userAgent)
if (!browser || storageGet(promptStorageKey) === '1') return
browserName.value = browser === 'wechat' ? '微信' : 'QQ'
visible.value = true
})
</script>
<template>
<Teleport to="body">
<div v-if="visible" class="in-app-browser-mask" role="presentation">
<section
class="in-app-browser-dialog"
role="dialog"
aria-modal="true"
aria-labelledby="in-app-browser-title"
>
<div class="prompt-icon" aria-hidden="true">
<van-icon name="guide-o" :size="30" />
</div>
<div class="prompt-copy">
<p class="prompt-kicker">当前为{{ browserName }}内置浏览器</p>
<h2 id="in-app-browser-title">建议在系统浏览器打开</h2>
<p class="prompt-desc">部分支付跳转和上传能力在内置浏览器里可能受限</p>
<div class="prompt-tip">
<span class="prompt-tip-line">点击右上角 <strong>···</strong></span>
<span>选择在浏览器打开</span>
</div>
</div>
<button class="prompt-action" type="button" @click="closePrompt">我知道了</button>
</section>
</div>
</Teleport>
</template>
<style scoped>
.in-app-browser-mask {
position: fixed;
inset: 0;
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
background: rgb(15 23 42 / 48%);
backdrop-filter: blur(1.5px);
}
.in-app-browser-dialog {
width: min(78vw, 320px);
min-width: 250px;
overflow: hidden;
border: 1px solid rgb(255 255 255 / 68%);
border-radius: 18px;
background: #fff;
box-shadow: 0 18px 48px rgb(15 23 42 / 24%);
color: #1f2937;
text-align: center;
}
.prompt-icon {
display: grid;
width: 50px;
height: 50px;
margin: 22px auto 12px;
place-items: center;
border-radius: 16px;
background: linear-gradient(135deg, #fff4ec, #ffe1d0);
color: #d85b12;
}
.prompt-copy {
padding: 0 22px;
}
.prompt-kicker {
margin: 0;
color: #d85b12;
font-size: 12px;
font-weight: 700;
line-height: 1.4;
}
.in-app-browser-dialog h2 {
margin: 6px 0 0;
font-size: 18px;
font-weight: 800;
line-height: 1.4;
}
.prompt-desc {
margin: 9px 0 0;
color: #6b7280;
font-size: 13px;
line-height: 1.55;
}
.prompt-tip {
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 3px;
max-width: 100%;
margin: 14px 0 18px;
padding: 8px 13px;
border-radius: 12px;
background: #f6f8fb;
color: #4b5563;
font-size: 12px;
line-height: 1.35;
}
.prompt-tip strong {
display: inline-block;
color: #111827;
font-size: 15px;
letter-spacing: 1px;
line-height: 1;
transform: translateY(-1px);
}
.prompt-tip-line {
display: inline-flex;
align-items: center;
gap: 5px;
}
.prompt-action {
width: 100%;
min-height: 48px;
border: 0;
background: linear-gradient(135deg, #ff7a1a, #ef5b00);
color: #fff;
font: inherit;
font-size: 15px;
font-weight: 700;
cursor: pointer;
}
.prompt-action:active {
filter: brightness(0.96);
}
@media (max-width: 360px) {
.in-app-browser-mask {
padding: 18px;
}
.in-app-browser-dialog {
width: calc(100vw - 36px);
min-width: 0;
}
.prompt-copy {
padding: 0 20px;
}
.prompt-tip {
width: 100%;
}
}
</style>