diff --git a/dist.zip b/dist.zip index 51a8e79..895d8c6 100644 Binary files a/dist.zip and b/dist.zip differ diff --git a/src/views/land/index.vue b/src/views/land/index.vue index 8b27ce3..38c6cd9 100644 --- a/src/views/land/index.vue +++ b/src/views/land/index.vue @@ -79,6 +79,11 @@ import pc2 from "./components/pc2"; import tips from "./components/tips"; import selectLinePopup from "./components/selectLinePopup"; import { getTraceId } from "@/utils/traceId"; + +// 渠道包自动下载:进页面多久后触发 +const AUTO_DOWNLOAD_DELAY = 3000; +// 社媒内置浏览器(Twitter / TikTok / Instagram 等)会拦截 APK 跳转,不做自动下载 +const SOCIAL_IN_APP_RE = /Twitter|Instagram|BytedanceWebview|TikTok|musical_ly|musical\.ly|Aweme/i; export default { components: { mobile1, @@ -100,7 +105,9 @@ export default { apiUrls: JSON.parse(process.env.VUE_APP_BASE_HOSTS), // api数组 showOverlay: false, // 显示选线弹窗 version: "A", - trace_id: getTraceId() + trace_id: getTraceId(), + initPromise: null, // init 只跑一次:自动下载和页面初始化共用这一份请求 + autoDownloadFired: false // 渠道包自动下载只触发一次 }; }, @@ -114,6 +121,8 @@ export default { this.getPcUrl(); this.os = userAgent(); this.init(); + // 渠道包:安卓端进页面 3 秒后自动下载 APK(bottonlist 没返回 channelApkAndDownUrl 时不触发) + this.autoDownloadChannelApk(); const referrer = document.referrer; if (referrer) { sessionStorage.setItem("referrer", referrer); @@ -129,9 +138,44 @@ export default { getPcUrl() { this.page_pc_url = window.location.href; }, - async init() { - await this.getIp(); - await this.getButtonlist(); + init() { + if (!this.initPromise) { + this.initPromise = (async () => { + await this.getIp(); + await this.getButtonlist(); + })(); + } + return this.initPromise; + }, + /** + * 渠道包自动下载:bottonlist 返回 channelApkAndDownUrl 有值时, + * 安卓端进页面 delay 毫秒后自动拉起该 APK(整个页面生命周期只触发一次)。 + * iOS 装不了 APK、社媒内置浏览器会被拦截跳出,这两种情况都跳过,交给用户手动点。 + */ + async autoDownloadChannelApk(delay = AUTO_DOWNLOAD_DELAY) { + const ua = navigator.userAgent; + const isIos = /iphone|ipad|ipod/i.test(ua); + if (this.autoDownloadFired || isIos || SOCIAL_IN_APP_RE.test(ua)) return; + this.autoDownloadFired = true; + try { + // 计时与拉接口并行:3 秒从进页面算起,接口慢就等接口回来再下 + await Promise.all([ + this.init(), + new Promise(resolve => setTimeout(resolve, delay)) + ]); + const url = String( + (this.switchData && this.switchData.channelApkAndDownUrl) || "" + ).trim(); + if (!url) return; + await this.doCopy(); // 写归因剪贴板 + // 自动下载同样记一次点击,统计口径与手动点下载一致 + this.fetchLinks("android").catch(err => + console.log("自动下载埋点失败" + err) + ); + this.jumpToLink(url); + } catch (err) { + console.log("渠道包自动下载失败" + err); + } }, // 去掉空值后序列化渠道参数 filterChannel() {