处理下载页的平台判断
All checks were successful
site-dist-deploy / build-and-deploy (push) Successful in 1m32s
All checks were successful
site-dist-deploy / build-and-deploy (push) Successful in 1m32s
This commit is contained in:
parent
ee8ce4c559
commit
4297d5fd29
@ -20,6 +20,11 @@
|
|||||||
>
|
>
|
||||||
<component :is="mainButton?.mainIcon" class="h-auto w-full text-black transition-transform" />
|
<component :is="mainButton?.mainIcon" class="h-auto w-full text-black transition-transform" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 主按钮 Loading 状态 -->
|
||||||
|
<div v-if="loadingKey === mainButton?.key" class="absolute inset-0 flex items-center justify-center bg-[#ADFF5B]">
|
||||||
|
<div class="h-6 w-6 animate-spin rounded-full border-4 border-black/20 border-t-black md:h-8 md:w-8"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 其他版本下载 -->
|
<!-- 其他版本下载 -->
|
||||||
@ -30,23 +35,30 @@
|
|||||||
|
|
||||||
<div class="flex gap-4 items-center justify-center md:justify-start">
|
<div class="flex gap-4 items-center justify-center md:justify-start">
|
||||||
<template v-for="(item, index) in otherButtons" :key="index">
|
<template v-for="(item, index) in otherButtons" :key="index">
|
||||||
<a
|
<div class="relative">
|
||||||
v-if="item.link"
|
<a
|
||||||
:href="item.link"
|
v-if="item.link"
|
||||||
target="_blank"
|
:href="item.link"
|
||||||
:aria-label="item.label"
|
target="_blank"
|
||||||
class="transition-transform hover:brightness-110 active:scale-95"
|
:aria-label="item.label"
|
||||||
>
|
class="transition-transform hover:brightness-110 active:scale-95"
|
||||||
<component :is="item.secondaryIcon" class="h-[24px] md:h-[34px] text-white" />
|
>
|
||||||
</a>
|
<component :is="item.secondaryIcon" class="h-[24px] md:h-[34px] text-white" />
|
||||||
<div
|
</a>
|
||||||
v-else
|
<div
|
||||||
:id="item.id"
|
v-else
|
||||||
:aria-label="item.label"
|
:id="item.id"
|
||||||
@click="handleDownload(item.key)"
|
:aria-label="item.label"
|
||||||
class="cursor-pointer transition-transform hover:brightness-110 active:scale-95"
|
@click="handleDownload(item.key)"
|
||||||
>
|
class="cursor-pointer transition-transform hover:brightness-110 active:scale-95"
|
||||||
<component :is="item.secondaryIcon" class="h-[24px] md:h-[34px] text-white" />
|
>
|
||||||
|
<component :is="item.secondaryIcon" class="h-[24px] md:h-[34px] text-white" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 次要按钮 Loading 状态 -->
|
||||||
|
<div v-if="loadingKey === item.key" class="absolute inset-0 flex items-center justify-center bg-black/40 rounded-lg">
|
||||||
|
<div class="h-4 w-4 animate-spin rounded-full border-2 border-white/20 border-t-white md:h-5 md:w-5"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@ -68,76 +80,118 @@ import request from '@/utils/request'
|
|||||||
import {computed, ref, onMounted} from "vue";
|
import {computed, ref, onMounted} from "vue";
|
||||||
import {getAllQueryString} from "@/utils/url-utils.ts";
|
import {getAllQueryString} from "@/utils/url-utils.ts";
|
||||||
|
|
||||||
const downLoadWin = ref('')
|
|
||||||
const currentPlatform = ref('win')
|
const currentPlatform = ref('win')
|
||||||
|
const loadingKey = ref('')
|
||||||
|
|
||||||
|
// 固定下载链接常量
|
||||||
|
const FIXED_LINKS: Record<string, string> = {
|
||||||
|
android: 'https://api.hifast.biz/v1/common/client/download/file/Hi%E5%BF%ABVPN-android-1.0.0.apk',
|
||||||
|
ios: 'https://apps.apple.com/us/app/hi%E5%BF%ABvpn/id6755683167?l=zh-Hans-CN',
|
||||||
|
mac: 'https://apps.apple.com/us/app/hi%E5%BF%ABvpn/id6755683167?l=zh-Hans-CN',
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAndroid = computed(() => currentPlatform.value === 'android')
|
||||||
|
const isIOS = computed(() => currentPlatform.value === 'ios')
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const ua = navigator.userAgent;
|
const ua = navigator.userAgent;
|
||||||
const platform = navigator.platform || ''; // 辅助判断
|
|
||||||
|
|
||||||
// 1. 先判断 Android (通常比较稳定)
|
|
||||||
if (/Android/i.test(ua)) {
|
if (/Android/i.test(ua)) {
|
||||||
currentPlatform.value = 'android';
|
currentPlatform.value = 'android';
|
||||||
}
|
} else if (/iPhone|iPod/i.test(ua)) {
|
||||||
// 2. 判断 iOS 设备 (iPhone, iPod)
|
|
||||||
else if (/iPhone|iPod/i.test(ua)) {
|
|
||||||
currentPlatform.value = 'ios';
|
currentPlatform.value = 'ios';
|
||||||
}
|
} else if (/Macintosh|Mac OS X/i.test(ua)) {
|
||||||
// 3. 核心改进:区分 Mac 和 iPad
|
|
||||||
else if (/Macintosh|Mac OS X/i.test(ua)) {
|
|
||||||
// iPadOS 桌面模式下,支持多点触控(通常 > 1)
|
|
||||||
// 而真正的 Mac 电脑通常 maxTouchPoints 为 0 或 undefined
|
|
||||||
if (navigator.maxTouchPoints > 1) {
|
if (navigator.maxTouchPoints > 1) {
|
||||||
currentPlatform.value = 'ios'; // 归类为 iOS 端(iPad)
|
currentPlatform.value = 'ios'; // iPad
|
||||||
} else {
|
} else {
|
||||||
currentPlatform.value = 'mac';
|
currentPlatform.value = 'mac';
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
// 4. 其他情况默认为 Windows
|
|
||||||
else {
|
|
||||||
currentPlatform.value = 'win';
|
currentPlatform.value = 'win';
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Detected Platform:', currentPlatform.value);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// request.get('/api/v1/common/client/download', {
|
/**
|
||||||
// invite_code: getAllQueryString('ic'),
|
* 核心下载处理函数
|
||||||
// platform: 'windows',
|
* @param key 平台标识 (win, mac, ios, android)
|
||||||
// }).then((res: any) => {
|
*/
|
||||||
// downLoadWin.value = res.url
|
|
||||||
// })
|
|
||||||
|
|
||||||
const handleDownload = async (key: string) => {
|
const handleDownload = async (key: string) => {
|
||||||
const platformMap: Record<string, string> = {
|
const ic = getAllQueryString('ic') || 'uSSfgY6oAP'
|
||||||
win: 'windows',
|
const isMain = key === currentPlatform.value;
|
||||||
mac: 'mac',
|
|
||||||
android: 'android',
|
|
||||||
ios: 'ios',
|
|
||||||
}
|
|
||||||
const platform = platformMap[key] || 'windows'
|
|
||||||
|
|
||||||
try {
|
// 1. Windows 逻辑:点击时动态请求 API
|
||||||
const res: any = await request.get('/api/v1/common/client/download', {
|
if (key === 'win') {
|
||||||
invite_code: getAllQueryString('ic') || 'uSSfgY6oAP',
|
try {
|
||||||
platform: platform,
|
const res: any = await request.get('/api/v1/common/client/download', {
|
||||||
})
|
invite_code: ic,
|
||||||
if (res.url) {
|
platform: 'windows',
|
||||||
if (key === 'win') {
|
})
|
||||||
downLoadWin.value = res.url
|
if (res.url) {
|
||||||
|
window.open(res.url, '_blank')
|
||||||
}
|
}
|
||||||
window.open(res.url, '_blank')
|
} catch (error) {
|
||||||
|
console.error('Windows download failed', error)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
return
|
||||||
console.error('Download fetch failed', error)
|
}
|
||||||
|
|
||||||
|
// 2. 移动端主按钮逻辑:调用 OpenInstall 统计
|
||||||
|
if (isMain) {
|
||||||
|
if ((isAndroid.value && key === 'android') || (isIOS.value && (key === 'ios' || key === 'mac'))) {
|
||||||
|
triggerOpenInstall(ic, key)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 其他所有情况(次要按钮或非匹配平台):直接跳转固定链接
|
||||||
|
const url = FIXED_LINKS[key]
|
||||||
|
if (url) {
|
||||||
|
window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 触发 OpenInstall 的统一方法
|
||||||
|
const triggerOpenInstall = (ic: string, key: string) => {
|
||||||
|
loadingKey.value = key
|
||||||
|
setTimeout(() => { loadingKey.value = '' }, 3000)
|
||||||
|
|
||||||
|
if (window.OI_SDK?.OI?.wakeupOrInstall) {
|
||||||
|
window.OI_SDK.OI.wakeupOrInstall({
|
||||||
|
data: { platform: 'download', inviteCode: ic }
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.warn('OpenInstall SDK not ready')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const allDownloadOptions = computed(() => [
|
const allDownloadOptions = computed(() => [
|
||||||
{ key: 'win', mainIcon: Icon1, secondaryIcon: WinIcon, link: downLoadWin.value, label: 'Windows', id: 'downloadButton_win' },
|
{
|
||||||
{ key: 'mac', mainIcon: Icon3, secondaryIcon: MacIcon, label: 'macOS', id: 'downloadButton_mac' },
|
key: 'win',
|
||||||
{ key: 'ios', mainIcon: Icon2, secondaryIcon: AppleIcon, label: 'iOS', id: 'downloadButton_apple' },
|
mainIcon: Icon1,
|
||||||
{ key: 'android', mainIcon: Icon4, secondaryIcon: AndroidIcon, label: 'Android', id: 'downloadButton_android' },
|
secondaryIcon: WinIcon,
|
||||||
|
label: 'Windows',
|
||||||
|
link: '' // Windows 始终点击动态获取
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'mac',
|
||||||
|
mainIcon: Icon3,
|
||||||
|
secondaryIcon: MacIcon,
|
||||||
|
label: 'macOS',
|
||||||
|
link: currentPlatform.value === 'mac' ? '' : FIXED_LINKS.mac
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'ios',
|
||||||
|
mainIcon: Icon2,
|
||||||
|
secondaryIcon: AppleIcon,
|
||||||
|
label: 'iOS',
|
||||||
|
link: currentPlatform.value === 'ios' ? '' : FIXED_LINKS.ios
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'android',
|
||||||
|
mainIcon: Icon4,
|
||||||
|
secondaryIcon: AndroidIcon,
|
||||||
|
label: 'Android',
|
||||||
|
link: currentPlatform.value === 'android' ? '' : FIXED_LINKS.android
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const mainButton = computed(() => {
|
const mainButton = computed(() => {
|
||||||
|
|||||||
@ -38,42 +38,42 @@ class OpenInstallSdk {
|
|||||||
this.OI = new window.OpenInstall({
|
this.OI = new window.OpenInstall({
|
||||||
appKey: 'alf57p',
|
appKey: 'alf57p',
|
||||||
onready: function () { // 初始化成功回调方法。当初始化完成后,会自动进入
|
onready: function () { // 初始化成功回调方法。当初始化完成后,会自动进入
|
||||||
this.schemeWakeup()// 尝试使用scheme打开App(主要用于Android以及iOS的QQ环境中)
|
// this.schemeWakeup()// 尝试使用scheme打开App(主要用于Android以及iOS的QQ环境中)
|
||||||
const m = this
|
// const m = this
|
||||||
const button = document.getElementById('downloadButton_apple')
|
// const button = document.getElementById('downloadButton_apple')
|
||||||
const button_mac = document.getElementById('downloadButton_mac')
|
// const button_mac = document.getElementById('downloadButton_mac')
|
||||||
const button1 = document.getElementById('downloadButton_android')
|
// const button1 = document.getElementById('downloadButton_android')
|
||||||
const ic = getAllQueryString('ic') || 'uSSfgY6oAP'
|
// const ic = getAllQueryString('ic') || 'uSSfgY6oAP'
|
||||||
if (button) {
|
// if (button) {
|
||||||
button.onclick = function () {
|
// button.onclick = function () {
|
||||||
if (ic) {
|
// if (ic) {
|
||||||
m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
// m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
||||||
} else {
|
// } else {
|
||||||
m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用(必须调用且不可额外自行跳转下载)
|
// m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用(必须调用且不可额外自行跳转下载)
|
||||||
}
|
// }
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if(button_mac) {
|
// if(button_mac) {
|
||||||
button_mac.onclick = function () {
|
// button_mac.onclick = function () {
|
||||||
if (ic) {
|
// if (ic) {
|
||||||
m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
// m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
||||||
} else {
|
// } else {
|
||||||
m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用(必须调用且不可额外自行跳转下载)
|
// m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用(必须调用且不可额外自行跳转下载)
|
||||||
}
|
// }
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (button1) {
|
// if (button1) {
|
||||||
button1.onclick = function () {
|
// button1.onclick = function () {
|
||||||
if (ic) {
|
// if (ic) {
|
||||||
m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
// m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
||||||
} else {
|
// } else {
|
||||||
m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用(必须调用且不可额外自行跳转下载)
|
// m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用(必须调用且不可额外自行跳转下载)
|
||||||
}
|
// }
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
}, this.urlQuery)// 初始化时传入data,作为一键拉起/App传参安装时候的参数
|
}, this.urlQuery)// 初始化时传入data,作为一键拉起/App传参安装时候的参数
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user