增加adjust web sdk
All checks were successful
site-dist-deploy / build-and-deploy (push) Successful in 1m36s

This commit is contained in:
speakeloudest 2026-04-02 07:27:16 +03:00
parent 681ad15228
commit d629b360a0
6 changed files with 153 additions and 22 deletions

View File

@ -10,6 +10,7 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@adjustcom/adjust-web-sdk": "^5.8.2",
"@tailwindcss/vite": "^4.1.18", "@tailwindcss/vite": "^4.1.18",
"axios": "^1.13.2", "axios": "^1.13.2",
"clsx": "^2.1.1", "clsx": "^2.1.1",

16
pnpm-lock.yaml generated
View File

@ -8,6 +8,9 @@ importers:
.: .:
dependencies: dependencies:
'@adjustcom/adjust-web-sdk':
specifier: ^5.8.2
version: 5.8.2
'@tailwindcss/vite': '@tailwindcss/vite':
specifier: ^4.1.18 specifier: ^4.1.18
version: 4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)) version: 4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2))
@ -72,6 +75,9 @@ importers:
packages: packages:
'@adjustcom/adjust-web-sdk@5.8.2':
resolution: {integrity: sha512-6ov2EKKuPQi7i+0CdtsGZ7REIE8jRlg++muAjqpR4ySLjOXTgxVSmWjsTBohxnTVDDL2OGEMfXFUG6ZIhyvl9Q==}
'@babel/helper-string-parser@7.27.1': '@babel/helper-string-parser@7.27.1':
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -85,6 +91,10 @@ packages:
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
hasBin: true hasBin: true
'@babel/runtime@7.29.2':
resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==}
engines: {node: '>=6.9.0'}
'@babel/types@7.28.6': '@babel/types@7.28.6':
resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -1094,6 +1104,10 @@ packages:
snapshots: snapshots:
'@adjustcom/adjust-web-sdk@5.8.2':
dependencies:
'@babel/runtime': 7.29.2
'@babel/helper-string-parser@7.27.1': {} '@babel/helper-string-parser@7.27.1': {}
'@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-identifier@7.28.5': {}
@ -1102,6 +1116,8 @@ snapshots:
dependencies: dependencies:
'@babel/types': 7.28.6 '@babel/types': 7.28.6
'@babel/runtime@7.29.2': {}
'@babel/types@7.28.6': '@babel/types@7.28.6':
dependencies: dependencies:
'@babel/helper-string-parser': 7.27.1 '@babel/helper-string-parser': 7.27.1

View File

@ -1,6 +1,7 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import './styles/index.css' import './styles/index.css'
import App from './App.vue' import App from './App.vue'
import '@/utils/openinstall.ts' import '@/utils/openinstall'
import '@/utils/adjust'
createApp(App).mount('#app') createApp(App).mount('#app')

View File

@ -8,6 +8,7 @@
target="_blank" target="_blank"
:aria-label="mainButton.label" :aria-label="mainButton.label"
class="flex h-full w-full items-center justify-center transition-transform hover:brightness-110 active:scale-95" class="flex h-full w-full items-center justify-center transition-transform hover:brightness-110 active:scale-95"
@click.prevent="handleDownload(mainButton)"
> >
<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" />
</a> </a>
@ -16,6 +17,7 @@
:id="mainButton?.id" :id="mainButton?.id"
:aria-label="mainButton?.label" :aria-label="mainButton?.label"
class="flex h-full w-full cursor-pointer items-center justify-center transition-transform hover:brightness-110 active:scale-95" class="flex h-full w-full cursor-pointer items-center justify-center transition-transform hover:brightness-110 active:scale-95"
@click="handleDownload(mainButton)"
> >
<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>
@ -35,6 +37,7 @@
target="_blank" target="_blank"
:aria-label="item.label" :aria-label="item.label"
class="transition-transform hover:brightness-110 active:scale-95" class="transition-transform hover:brightness-110 active:scale-95"
@click.prevent="handleDownload(item)"
> >
<component :is="item.secondaryIcon" class="h-[24px] md:h-[34px] text-white" /> <component :is="item.secondaryIcon" class="h-[24px] md:h-[34px] text-white" />
</a> </a>
@ -43,6 +46,7 @@
:id="item.id" :id="item.id"
:aria-label="item.label" :aria-label="item.label"
class="cursor-pointer transition-transform hover:brightness-110 active:scale-95" class="cursor-pointer transition-transform hover:brightness-110 active:scale-95"
@click="handleDownload(item)"
> >
<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> </div>
@ -64,10 +68,9 @@ import AndroidIcon from './AndroidIcon.svg?component'
import request from '@/utils/request' import request from '@/utils/request'
import {computed, ref, onMounted} from "vue"; import {computed, ref, onMounted} from "vue";
import {getAllQueryString} from "@/utils/url-utils"; import {getAllQueryString} from "../../../utils/url-utils";
import AdjustUtil from "../../../utils/adjust";
const downLoadWin = ref('')
const downLoadMac = ref('')
const currentPlatform = ref('win') const currentPlatform = ref('win')
onMounted(() => { onMounted(() => {
@ -100,30 +103,38 @@ onMounted(() => {
console.log('Detected Platform:', currentPlatform.value); console.log('Detected Platform:', currentPlatform.value);
}); });
// request.get('/api/v1/common/client/download', { const handleDownload = (item: any) => {
// invite_code: getAllQueryString('ic'), console.log('Downloading:', item.label, item.link);
// platform: 'mac', // key
// }).then((res: any) => { AdjustUtil.trackEvent(item.key);
// downLoadMac.value = res.url
// })
request.get('/api/v1/common/client/download', { if (item.key === 'win') {
invite_code: getAllQueryString('ic'), // Windows
platform: 'windows', request.get('/api/v1/common/client/download', {
}).then((res: any) => { invite_code: getAllQueryString('ic'),
downLoadWin.value = res.url platform: 'windows',
}) }).then((res: any) => {
if (res.url) {
window.open(res.url, '_blank');
}
}).catch((err: any) => {
console.error('Failed to fetch windows download link:', err);
});
} else if (item.link) {
//
window.open(item.link, '_blank');
}
};
const allDownloadOptions = computed(() => { const allDownloadOptions = computed(() => {
const ic = getAllQueryString('ic')
const androidLink = currentPlatform.value === 'android' const androidLink = currentPlatform.value === 'android'
? `https://hifastvpn.go.link?adj_t=1xf6e7ru&inviteCode=${ic}` ? AdjustUtil.getDecoratedLink()
: 'https://api.hifast.biz/v1/common/client/download/file/Hi%E5%BF%ABVPN-android-1.0.0.apk' : 'https://api.hifast.biz/v1/common/client/download/file/Hi%E5%BF%ABVPN-android-1.0.0.apk'
return [ return [
{ key: 'win', mainIcon: Icon1, secondaryIcon: WinIcon, link: downLoadWin.value, label: 'Windows', id: 'downloadButton_win' }, { key: 'win', mainIcon: Icon1, secondaryIcon: WinIcon, link: '', label: 'Windows', id: 'downloadButton_win' },
{ key: 'mac', mainIcon: Icon3, secondaryIcon: MacIcon, label: 'macOS', link: `https://hifastvpn.go.link?adj_t=1xf6e7ru&inviteCode=${ic}` }, { key: 'mac', mainIcon: Icon3, secondaryIcon: MacIcon, label: 'macOS', link: AdjustUtil.getDecoratedLink() },
{ key: 'ios', mainIcon: Icon2, secondaryIcon: AppleIcon, label: 'iOS', link: `https://hifastvpn.go.link?adj_t=1xf6e7ru&inviteCode=${ic}` }, { key: 'ios', mainIcon: Icon2, secondaryIcon: AppleIcon, label: 'iOS', link: AdjustUtil.getDecoratedLink() },
{ key: 'android', mainIcon: Icon4, secondaryIcon: AndroidIcon, label: 'Android', link: androidLink }, { key: 'android', mainIcon: Icon4, secondaryIcon: AndroidIcon, label: 'Android', link: androidLink },
] ]
}) })

98
src/utils/adjust.ts Normal file
View File

@ -0,0 +1,98 @@
import Adjust from '@adjustcom/adjust-web-sdk'
import { getAllQueryString } from '@/utils/url-utils'
/**
* Adjust Web SDK
* SDK
*/
class AdjustUtil {
private static instance: AdjustUtil
private isInitialized: boolean = false
private appToken: string = 'vnxcjw75xyww'
private environment: 'production' | 'sandbox' = 'production'
// Adjust 事件令牌映射表(请在此处替换为真实的 6 位令牌)
public static readonly EVENT_TOKENS = {
win: 'c6rntd',
mac: 'c6rntd',
ios: 'c6rntd',
android: 'c6rntd',
}
private constructor() {
this.init()
}
public static getInstance(): AdjustUtil {
if (!AdjustUtil.instance) {
AdjustUtil.instance = new AdjustUtil()
}
return AdjustUtil.instance
}
private init() {
try {
if (!this.isInitialized) {
Adjust.initSdk({
appToken: this.appToken,
environment: this.environment,
logLevel: 'verbose'
})
this.isInitialized = true
console.log('Adjust SDK Initialized (NPM)')
// 获取并设置 inviteCode 作为全局参数
const ic = getAllQueryString('ic')
if (ic) {
Adjust.addGlobalCallbackParameters([
{ key: 'inviteCode', value: ic }
])
console.log('Adjust Global Parameter Set: inviteCode =', ic)
}
}
} catch (e) {
console.error('Adjust SDK Initialization Error:', e)
}
}
/**
* Adjust URL
* @param baseUrl Adjust 'https://hifastvpn.go.link'
* @param defaultAdjT adj_t '1xf6e7ru'
*/
public getDecoratedLink(baseUrl: string = 'https://hifastvpn.go.link', defaultAdjT: string = '1xf6e7ru'): string {
const currentParams = new URLSearchParams(window.location.search || window.location.hash.split('?')[1] || '')
const baseParams = new URLSearchParams()
// 设置默认 adj_t
baseParams.set('adj_t', defaultAdjT)
// 将当前页面的参数合并进来(当前页面的参数优先级更高,可覆盖默认的 adj_t
currentParams.forEach((value, key) => {
if (key === 'ic') {
// 特殊处理URL 上的 ic 映射为 Adjust 链接上的 inviteCode
baseParams.set('inviteCode', value)
} else {
baseParams.set(key, value)
}
})
const finalQuery = baseParams.toString()
return `${baseUrl}${baseUrl.includes('?') ? '&' : '?'}${finalQuery}`
}
/**
*
* @param eventNameOrToken win/ios等 Adjust Event Token6
*/
public trackEvent(eventNameOrToken: string) {
if (this.isInitialized) {
// 优先从映射表中查找令牌,找不到则视为直接传入的令牌
const token = (AdjustUtil.EVENT_TOKENS as any)[eventNameOrToken] || eventNameOrToken
Adjust.trackEvent({ eventToken: token })
}
}
}
export default AdjustUtil.getInstance()

View File

@ -10,7 +10,11 @@
"noUnusedParameters": true, "noUnusedParameters": true,
"erasableSyntaxOnly": true, "erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true "noUncheckedSideEffectImports": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}, },
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
} }