处理下载页的平台判断
All checks were successful
site-dist-deploy / build-and-deploy (push) Successful in 1m32s

This commit is contained in:
speakeloudest 2026-04-20 04:24:23 +03:00
parent ee8ce4c559
commit 4297d5fd29
2 changed files with 154 additions and 100 deletions

View File

@ -20,6 +20,11 @@
>
<component :is="mainButton?.mainIcon" class="h-auto w-full text-black transition-transform" />
</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>
<!-- 其他版本下载 -->
@ -30,23 +35,30 @@
<div class="flex gap-4 items-center justify-center md:justify-start">
<template v-for="(item, index) in otherButtons" :key="index">
<a
v-if="item.link"
:href="item.link"
target="_blank"
: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>
<div
v-else
:id="item.id"
:aria-label="item.label"
@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" />
<div class="relative">
<a
v-if="item.link"
:href="item.link"
target="_blank"
: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>
<div
v-else
:id="item.id"
:aria-label="item.label"
@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" />
</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>
</template>
</div>
@ -68,76 +80,118 @@ import request from '@/utils/request'
import {computed, ref, onMounted} from "vue";
import {getAllQueryString} from "@/utils/url-utils.ts";
const downLoadWin = ref('')
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(() => {
const ua = navigator.userAgent;
const platform = navigator.platform || ''; //
// 1. Android ()
if (/Android/i.test(ua)) {
currentPlatform.value = 'android';
}
// 2. iOS (iPhone, iPod)
else if (/iPhone|iPod/i.test(ua)) {
} else if (/iPhone|iPod/i.test(ua)) {
currentPlatform.value = 'ios';
}
// 3. Mac iPad
else if (/Macintosh|Mac OS X/i.test(ua)) {
// iPadOS > 1
// Mac maxTouchPoints 0 undefined
} else if (/Macintosh|Mac OS X/i.test(ua)) {
if (navigator.maxTouchPoints > 1) {
currentPlatform.value = 'ios'; // iOS iPad
currentPlatform.value = 'ios'; // iPad
} else {
currentPlatform.value = 'mac';
}
}
// 4. Windows
else {
} else {
currentPlatform.value = 'win';
}
console.log('Detected Platform:', currentPlatform.value);
});
// request.get('/api/v1/common/client/download', {
// invite_code: getAllQueryString('ic'),
// platform: 'windows',
// }).then((res: any) => {
// downLoadWin.value = res.url
// })
/**
* 核心下载处理函数
* @param key 平台标识 (win, mac, ios, android)
*/
const handleDownload = async (key: string) => {
const platformMap: Record<string, string> = {
win: 'windows',
mac: 'mac',
android: 'android',
ios: 'ios',
}
const platform = platformMap[key] || 'windows'
const ic = getAllQueryString('ic') || 'uSSfgY6oAP'
const isMain = key === currentPlatform.value;
try {
const res: any = await request.get('/api/v1/common/client/download', {
invite_code: getAllQueryString('ic') || 'uSSfgY6oAP',
platform: platform,
})
if (res.url) {
if (key === 'win') {
downLoadWin.value = res.url
// 1. Windows API
if (key === 'win') {
try {
const res: any = await request.get('/api/v1/common/client/download', {
invite_code: ic,
platform: 'windows',
})
if (res.url) {
window.open(res.url, '_blank')
}
window.open(res.url, '_blank')
} catch (error) {
console.error('Windows download failed', error)
}
} catch (error) {
console.error('Download fetch failed', error)
return
}
// 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(() => [
{ 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: 'ios', mainIcon: Icon2, secondaryIcon: AppleIcon, label: 'iOS', id: 'downloadButton_apple' },
{ key: 'android', mainIcon: Icon4, secondaryIcon: AndroidIcon, label: 'Android', id: 'downloadButton_android' },
{
key: 'win',
mainIcon: Icon1,
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(() => {

View File

@ -38,42 +38,42 @@ class OpenInstallSdk {
this.OI = new window.OpenInstall({
appKey: 'alf57p',
onready: function () { // 初始化成功回调方法。当初始化完成后,会自动进入
this.schemeWakeup()// 尝试使用scheme打开App主要用于Android以及iOS的QQ环境中
const m = this
const button = document.getElementById('downloadButton_apple')
const button_mac = document.getElementById('downloadButton_mac')
const button1 = document.getElementById('downloadButton_android')
const ic = getAllQueryString('ic') || 'uSSfgY6oAP'
if (button) {
button.onclick = function () {
if (ic) {
m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
} else {
m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用必须调用且不可额外自行跳转下载
}
return false
}
}
if(button_mac) {
button_mac.onclick = function () {
if (ic) {
m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
} else {
m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用必须调用且不可额外自行跳转下载
}
return false
}
}
if (button1) {
button1.onclick = function () {
if (ic) {
m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
} else {
m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用必须调用且不可额外自行跳转下载
}
return false
}
}
// this.schemeWakeup()// 尝试使用scheme打开App主要用于Android以及iOS的QQ环境中
// const m = this
// const button = document.getElementById('downloadButton_apple')
// const button_mac = document.getElementById('downloadButton_mac')
// const button1 = document.getElementById('downloadButton_android')
// const ic = getAllQueryString('ic') || 'uSSfgY6oAP'
// if (button) {
// button.onclick = function () {
// if (ic) {
// m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
// } else {
// m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用必须调用且不可额外自行跳转下载
// }
// return false
// }
// }
// if(button_mac) {
// button_mac.onclick = function () {
// if (ic) {
// m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
// } else {
// m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用必须调用且不可额外自行跳转下载
// }
// return false
// }
// }
// if (button1) {
// button1.onclick = function () {
// if (ic) {
// m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
// } else {
// m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用必须调用且不可额外自行跳转下载
// }
// return false
// }
// }
},
}, this.urlQuery)// 初始化时传入data作为一键拉起/App传参安装时候的参数
} catch (e) {