From d629b360a0398c9c8715c77a0133d0437cd56e24 Mon Sep 17 00:00:00 2001 From: speakeloudest Date: Thu, 2 Apr 2026 07:27:16 +0300 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0adjust=20web=20sdk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 16 ++++ src/main.ts | 3 +- src/pages/Home/components/DownloadButton.vue | 51 ++++++---- src/utils/adjust.ts | 98 ++++++++++++++++++++ tsconfig.app.json | 6 +- 6 files changed, 153 insertions(+), 22 deletions(-) create mode 100644 src/utils/adjust.ts diff --git a/package.json b/package.json index 71e91a5..60503b6 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "@adjustcom/adjust-web-sdk": "^5.8.2", "@tailwindcss/vite": "^4.1.18", "axios": "^1.13.2", "clsx": "^2.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2959cbd..601ad55 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@adjustcom/adjust-web-sdk': + specifier: ^5.8.2 + version: 5.8.2 '@tailwindcss/vite': 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)) @@ -72,6 +75,9 @@ importers: packages: + '@adjustcom/adjust-web-sdk@5.8.2': + resolution: {integrity: sha512-6ov2EKKuPQi7i+0CdtsGZ7REIE8jRlg++muAjqpR4ySLjOXTgxVSmWjsTBohxnTVDDL2OGEMfXFUG6ZIhyvl9Q==} + '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -85,6 +91,10 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + '@babel/types@7.28.6': resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} engines: {node: '>=6.9.0'} @@ -1094,6 +1104,10 @@ packages: snapshots: + '@adjustcom/adjust-web-sdk@5.8.2': + dependencies: + '@babel/runtime': 7.29.2 + '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.28.5': {} @@ -1102,6 +1116,8 @@ snapshots: dependencies: '@babel/types': 7.28.6 + '@babel/runtime@7.29.2': {} + '@babel/types@7.28.6': dependencies: '@babel/helper-string-parser': 7.27.1 diff --git a/src/main.ts b/src/main.ts index 94336c5..83193db 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,7 @@ import { createApp } from 'vue' import './styles/index.css' import App from './App.vue' -import '@/utils/openinstall.ts' +import '@/utils/openinstall' +import '@/utils/adjust' createApp(App).mount('#app') diff --git a/src/pages/Home/components/DownloadButton.vue b/src/pages/Home/components/DownloadButton.vue index 10a684a..07d73ab 100644 --- a/src/pages/Home/components/DownloadButton.vue +++ b/src/pages/Home/components/DownloadButton.vue @@ -8,6 +8,7 @@ target="_blank" :aria-label="mainButton.label" class="flex h-full w-full items-center justify-center transition-transform hover:brightness-110 active:scale-95" + @click.prevent="handleDownload(mainButton)" > @@ -16,6 +17,7 @@ :id="mainButton?.id" :aria-label="mainButton?.label" class="flex h-full w-full cursor-pointer items-center justify-center transition-transform hover:brightness-110 active:scale-95" + @click="handleDownload(mainButton)" > @@ -35,6 +37,7 @@ target="_blank" :aria-label="item.label" class="transition-transform hover:brightness-110 active:scale-95" + @click.prevent="handleDownload(item)" > @@ -43,6 +46,7 @@ :id="item.id" :aria-label="item.label" class="cursor-pointer transition-transform hover:brightness-110 active:scale-95" + @click="handleDownload(item)" > @@ -64,10 +68,9 @@ import AndroidIcon from './AndroidIcon.svg?component' import request from '@/utils/request' 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') onMounted(() => { @@ -100,30 +103,38 @@ onMounted(() => { console.log('Detected Platform:', currentPlatform.value); }); -// request.get('/api/v1/common/client/download', { -// invite_code: getAllQueryString('ic'), -// platform: 'mac', -// }).then((res: any) => { -// downLoadMac.value = res.url -// }) +const handleDownload = (item: any) => { + console.log('Downloading:', item.label, item.link); + // 记录点击事件(通过 key 自动映射令牌) + AdjustUtil.trackEvent(item.key); -request.get('/api/v1/common/client/download', { - invite_code: getAllQueryString('ic'), - platform: 'windows', -}).then((res: any) => { - downLoadWin.value = res.url -}) + if (item.key === 'win') { + // Windows 平台:点击时请求下载地址 + request.get('/api/v1/common/client/download', { + invite_code: getAllQueryString('ic'), + 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 ic = getAllQueryString('ic') 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' return [ - { key: 'win', mainIcon: Icon1, secondaryIcon: WinIcon, link: downLoadWin.value, label: 'Windows', id: 'downloadButton_win' }, - { key: 'mac', mainIcon: Icon3, secondaryIcon: MacIcon, label: 'macOS', link: `https://hifastvpn.go.link?adj_t=1xf6e7ru&inviteCode=${ic}` }, - { key: 'ios', mainIcon: Icon2, secondaryIcon: AppleIcon, label: 'iOS', link: `https://hifastvpn.go.link?adj_t=1xf6e7ru&inviteCode=${ic}` }, + { key: 'win', mainIcon: Icon1, secondaryIcon: WinIcon, link: '', label: 'Windows', id: 'downloadButton_win' }, + { key: 'mac', mainIcon: Icon3, secondaryIcon: MacIcon, label: 'macOS', link: AdjustUtil.getDecoratedLink() }, + { key: 'ios', mainIcon: Icon2, secondaryIcon: AppleIcon, label: 'iOS', link: AdjustUtil.getDecoratedLink() }, { key: 'android', mainIcon: Icon4, secondaryIcon: AndroidIcon, label: 'Android', link: androidLink }, ] }) diff --git a/src/utils/adjust.ts b/src/utils/adjust.ts new file mode 100644 index 0000000..a8a4b56 --- /dev/null +++ b/src/utils/adjust.ts @@ -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 Token(6位令牌) + */ + public trackEvent(eventNameOrToken: string) { + if (this.isInitialized) { + // 优先从映射表中查找令牌,找不到则视为直接传入的令牌 + const token = (AdjustUtil.EVENT_TOKENS as any)[eventNameOrToken] || eventNameOrToken + Adjust.trackEvent({ eventToken: token }) + } + } +} + +export default AdjustUtil.getInstance() diff --git a/tsconfig.app.json b/tsconfig.app.json index 8d16e42..8adf728 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -10,7 +10,11 @@ "noUnusedParameters": true, "erasableSyntaxOnly": true, "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true + "noUncheckedSideEffectImports": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } }, "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] }