This commit is contained in:
parent
3313b95ab1
commit
6c296dbaaf
@ -73,9 +73,18 @@
|
||||
<div class="mx-auto h-[101px] w-[247px] md:h-[202px] md:w-[494px]">
|
||||
<div
|
||||
@click="handleDownload('ios')"
|
||||
class="block h-full w-full cursor-pointer transition-transform active:scale-95"
|
||||
class="relative block h-full w-full cursor-pointer transition-transform active:scale-95"
|
||||
>
|
||||
<img src="./Group%20100.png" class="h-full w-full" alt="下载" />
|
||||
<!-- Loading Overlay -->
|
||||
<div
|
||||
v-if="isLoadingIos"
|
||||
class="absolute inset-0 flex items-center justify-center rounded-[20px] bg-black/40"
|
||||
>
|
||||
<div
|
||||
class="h-8 w-8 animate-spin rounded-full border-4 border-[#ADFF5B] border-t-transparent md:h-12 md:w-12"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -109,11 +118,21 @@
|
||||
<template v-for="client in otherClients" :key="client.type">
|
||||
<div
|
||||
@click="handleDownload(client.type)"
|
||||
class="cursor-pointer transition-transform hover:brightness-110 active:scale-95"
|
||||
class="relative cursor-pointer transition-transform hover:brightness-110 active:scale-95"
|
||||
>
|
||||
<MacosIcon v-if="client.type === 'mac'" />
|
||||
<WindowsIcon v-if="client.type === 'window'" />
|
||||
<AndroidIcon v-if="client.type === 'android'" />
|
||||
|
||||
<!-- Loading Overlay for Android -->
|
||||
<div
|
||||
v-if="client.type === 'android' && isLoadingAndroid"
|
||||
class="absolute inset-0 flex items-center justify-center rounded-lg bg-black/40"
|
||||
>
|
||||
<div
|
||||
class="h-6 w-6 animate-spin rounded-full border-2 border-[#ADFF5B] border-t-transparent"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@ -132,6 +151,7 @@ import WindowsIcon from './windows.svg?component'
|
||||
import AndroidIcon from './android.svg?component'
|
||||
import request from '@/utils/request'
|
||||
import { getAllQueryString } from '@/utils/url-utils.ts'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
||||
import DownloadMethodList from './DownloadMethodList/DownloadMethodList.vue'
|
||||
import FAQAccordion from './FAQAccordion/index.vue'
|
||||
@ -147,13 +167,46 @@ const handleDownload = async (key: string) => {
|
||||
const platform = platformMap[key] || 'windows'
|
||||
const ic = getAllQueryString('ic') || sessionStorage.getItem('ic') || 'uSSfg1Y1vt'
|
||||
|
||||
if (platform === 'ios') {
|
||||
if (window.OI_SDK && window.OI_SDK.OI) {
|
||||
window.OI_SDK.OI.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
||||
// 设备环境检测
|
||||
const ua = navigator.userAgent
|
||||
const isAndroidDevice = /Android/i.test(ua)
|
||||
const isIosDevice =
|
||||
/iPhone|iPod|iPad/i.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
|
||||
const isMobileDevice = isAndroidDevice || isIosDevice
|
||||
|
||||
// 1. 安卓下载逻辑
|
||||
if (key === 'android') {
|
||||
if (isAndroidDevice) {
|
||||
isLoadingAndroid.value = true
|
||||
await triggerOpenInstall(ic)
|
||||
isLoadingAndroid.value = false
|
||||
return
|
||||
} else {
|
||||
window.open(
|
||||
'https://api.hifast.biz/v1/common/client/download/file/Hi%E5%BF%ABVPN-android-1.0.0.apk',
|
||||
'_blank',
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 2. iOS/Mac 下载逻辑
|
||||
if (key === 'ios' || key === 'mac') {
|
||||
if (isMobileDevice) {
|
||||
if (key === 'ios') isLoadingIos.value = true
|
||||
await triggerOpenInstall(ic)
|
||||
isLoadingIos.value = false
|
||||
return
|
||||
} else {
|
||||
window.open(
|
||||
'https://apps.apple.com/us/app/hi%E5%BF%ABvpn/id6755683167?l=zh-Hans-CN',
|
||||
'_blank',
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 原有逻辑 (如 Windows)
|
||||
try {
|
||||
const res: any = await request.get('/api/v1/common/client/download', {
|
||||
invite_code: ic,
|
||||
@ -167,7 +220,27 @@ const handleDownload = async (key: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 提取 OpenInstall 触发逻辑
|
||||
const triggerOpenInstall = async (ic: string) => {
|
||||
if (!(window as any).OI_SDK?.isReady && (window as any).OI_SDK_PROMISE) {
|
||||
try {
|
||||
await Promise.race([
|
||||
(window as any).OI_SDK_PROMISE,
|
||||
new Promise((_, reject) => setTimeout(() => reject(new Error('OpenInstall timeout')), 3000)),
|
||||
])
|
||||
} catch (e) {
|
||||
console.warn('OpenInstall readiness wait failed or timeout:', e)
|
||||
}
|
||||
}
|
||||
|
||||
if ((window as any).OI_SDK && (window as any).OI_SDK.OI) {
|
||||
;(window as any).OI_SDK.OI.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
||||
}
|
||||
}
|
||||
|
||||
const activeIndex = ref(0)
|
||||
const isLoadingIos = ref(false)
|
||||
const isLoadingAndroid = ref(false)
|
||||
|
||||
const otherClients = computed(() => {
|
||||
return [
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
v-else
|
||||
:id="mainButton?.id"
|
||||
:aria-label="mainButton?.label"
|
||||
@click="mainButton.key === 'win' ? handleDownload(mainButton.key) : null"
|
||||
@click="handleDownload(mainButton.key)"
|
||||
class="flex h-full w-full cursor-pointer items-center justify-center transition-transform hover:brightness-110 active:scale-95"
|
||||
>
|
||||
<component
|
||||
@ -68,7 +68,7 @@
|
||||
v-else
|
||||
:id="item.id"
|
||||
:aria-label="item.label"
|
||||
@click="item.key === 'win' ? handleDownload(item.key) : null"
|
||||
@click="handleDownload(item.key)"
|
||||
class="cursor-pointer transition-transform hover:brightness-110 active:scale-95"
|
||||
>
|
||||
<component :is="item.secondaryIcon" class="h-[24px] text-white md:h-[34px]" />
|
||||
@ -142,10 +142,47 @@ const handleDownload = async (key: string) => {
|
||||
ios: 'ios',
|
||||
}
|
||||
const platform = platformMap[key] || 'windows'
|
||||
const ic = getAllQueryString('ic') || sessionStorage.getItem('ic') || 'uSSfg1Y1vt'
|
||||
|
||||
// 设备环境检测
|
||||
const ua = navigator.userAgent
|
||||
const isAndroidDevice = /Android/i.test(ua)
|
||||
const isIosDevice =
|
||||
/iPhone|iPod|iPad/i.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
|
||||
const isMobileDevice = isAndroidDevice || isIosDevice
|
||||
|
||||
// 1. 安卓下载逻辑
|
||||
if (key === 'android') {
|
||||
if (isAndroidDevice) {
|
||||
await triggerOpenInstall(ic)
|
||||
return
|
||||
} else {
|
||||
window.open(
|
||||
'https://api.hifast.biz/v1/common/client/download/file/Hi%E5%BF%ABVPN-android-1.0.0.apk',
|
||||
'_blank',
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 2. iOS/Mac 下载逻辑
|
||||
if (key === 'ios' || key === 'mac') {
|
||||
if (isMobileDevice) {
|
||||
await triggerOpenInstall(ic)
|
||||
return
|
||||
} else {
|
||||
window.open(
|
||||
'https://apps.apple.com/us/app/hi%E5%BF%ABvpn/id6755683167?l=zh-Hans-CN',
|
||||
'_blank',
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 原有逻辑 (如 Windows)
|
||||
try {
|
||||
const res: any = await request.get('/api/v1/common/client/download', {
|
||||
invite_code: getAllQueryString('ic') || sessionStorage.getItem('ic') || 'uSSfg1Y1vt',
|
||||
invite_code: ic,
|
||||
platform: platform,
|
||||
})
|
||||
if (res.url) {
|
||||
@ -159,6 +196,24 @@ const handleDownload = async (key: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 提取 OpenInstall 触发逻辑
|
||||
const triggerOpenInstall = async (ic: string) => {
|
||||
if (!(window as any).OI_SDK?.isReady && (window as any).OI_SDK_PROMISE) {
|
||||
try {
|
||||
await Promise.race([
|
||||
(window as any).OI_SDK_PROMISE,
|
||||
new Promise((_, reject) => setTimeout(() => reject(new Error('OpenInstall timeout')), 3000)),
|
||||
])
|
||||
} catch (e) {
|
||||
console.warn('OpenInstall readiness wait failed or timeout:', e)
|
||||
}
|
||||
}
|
||||
|
||||
if ((window as any).OI_SDK && (window as any).OI_SDK.OI) {
|
||||
;(window as any).OI_SDK.OI.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
||||
}
|
||||
}
|
||||
|
||||
const allDownloadOptions = computed(() => [
|
||||
{
|
||||
key: 'win',
|
||||
|
||||
@ -11,8 +11,13 @@ script.charset = 'UTF-8'
|
||||
script.src = 'https://web.cdn.openinstall.io/openinstall.js'
|
||||
document.head.appendChild(script)
|
||||
|
||||
let resolveReady: (sdk: OpenInstallSdk) => void
|
||||
window.OI_SDK_PROMISE = new Promise((resolve) => {
|
||||
resolveReady = resolve
|
||||
})
|
||||
|
||||
script.addEventListener('load', () => {
|
||||
window.OI_SDK = new OpenInstallSdk()
|
||||
window.OI_SDK = new OpenInstallSdk(resolveReady)
|
||||
})
|
||||
|
||||
class OpenInstallSdk {
|
||||
@ -20,7 +25,9 @@ class OpenInstallSdk {
|
||||
|
||||
public OI: Record<string, any> // openinstall 实例
|
||||
|
||||
constructor() {
|
||||
public isReady = false
|
||||
|
||||
constructor(private onReadyCallback?: (sdk: OpenInstallSdk) => void) {
|
||||
this.OI = {}
|
||||
this.urlQuery = window.OpenInstall.parseUrlParams()
|
||||
const id = getAllQueryString('id')
|
||||
@ -34,47 +41,39 @@ class OpenInstallSdk {
|
||||
}
|
||||
|
||||
async init() {
|
||||
const self = this
|
||||
try {
|
||||
this.OI = new window.OpenInstall(
|
||||
{
|
||||
appKey: 'alf57p',
|
||||
onready: function () {
|
||||
// 初始化成功回调方法。当初始化完成后,会自动进入
|
||||
this.schemeWakeup() // 尝试使用scheme打开App(主要用于Android以及iOS的QQ环境中)
|
||||
// 注意:此时的 this 是 OpenInstall 的原始实例对象 (m)
|
||||
const m = this
|
||||
m.schemeWakeup() // 尝试使用scheme打开App(主要用于Android以及iOS的QQ环境中)
|
||||
|
||||
const button = document.getElementById('downloadButton_apple')
|
||||
const button_mac = document.getElementById('downloadButton_mac')
|
||||
const button1 = document.getElementById('downloadButton_android')
|
||||
const ic = getAllQueryString('ic') || 'uSSfg1Y1vt'
|
||||
if (button) {
|
||||
button.onclick = function () {
|
||||
if (ic) {
|
||||
m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
||||
} else {
|
||||
m.wakeupOrInstall() // 此方法为scheme、Universal Link唤醒以及引导下载的作用(必须调用且不可额外自行跳转下载)
|
||||
}
|
||||
return false
|
||||
|
||||
const clickHandler = function () {
|
||||
if (ic) {
|
||||
m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } })
|
||||
} else {
|
||||
m.wakeupOrInstall()
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
if (button) button.onclick = clickHandler
|
||||
if (button_mac) button_mac.onclick = clickHandler
|
||||
if (button1) button1.onclick = clickHandler
|
||||
|
||||
// 标记就绪并触发 Promise
|
||||
self.isReady = true
|
||||
if (self.onReadyCallback) {
|
||||
self.onReadyCallback(self)
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user