自动下载添加

This commit is contained in:
谢宇宁
2026-11-13 14:27:23 +07:00
parent 4f271a1856
commit f0c2dcc987
3 changed files with 72 additions and 14 deletions
+13 -2
View File
@@ -107,8 +107,17 @@ import IosSafariOpenGuide from '~/components/mobile/IosSafariOpenGuide.vue'
import AndroidInstallTip from '~/components/mobile/AndroidInstallTip.vue'
import { TABS, TAB_CONTENTS } from './contents'
const { init, download, guide, isIos, hasIosStore, isSocialInApp, iosInstallUrl, buttonList } =
useAppDownload()
const {
init,
download,
guide,
isIos,
hasIosStore,
isSocialInApp,
iosInstallUrl,
buttonList,
autoDownloadChannelApk,
} = useAppDownload()
const groupLink = computed(() => buttonList.value.contact?.telegram || '')
const showStoreTip = ref(true)
@@ -168,6 +177,8 @@ function onTabClick() {
onMounted(() => {
init()
// 渠道包:安卓端进页面 3 秒后自动下载 APK(无 channelApkAndDownUrl 时不触发)
autoDownloadChannelApk()
startTabAutoPlay()
})
+3
View File
@@ -283,6 +283,7 @@ export function useLandingB(mode: LandingBMode) {
isSocialInApp,
guide,
init: initDownload,
autoDownloadChannelApk,
} = useAppDownload()
function closeGuide() {
@@ -573,6 +574,8 @@ export function useLandingB(mode: LandingBMode) {
setHero(0, true)
pageQrUrl.value = buildPageQrUrl()
initDownload()
// 渠道包:安卓端进页面 3 秒后自动下载 APK(无 channelApkAndDownUrl 时不触发)
autoDownloadChannelApk()
window.addEventListener('scroll', onScroll, { passive: true })
window.addEventListener('keydown', onModalKeydown)
onScroll()
+56 -12
View File
@@ -5,6 +5,7 @@
* - 点下载:bottonclick 返回 data.link(地址数组),跳 link[index];同一请求后端记点击
* - iOS 轻量版:点击直接调 h5/config 下载描述文件(不看开关);社媒内置浏览器装不了描述文件,只弹「复制到 Safari」引导
* - iOS 商店版:iosStore(packageType 2) 走 bottonclick 拿 link
* - 渠道包自动下载:bottonlist 返回 channelApkAndDownUrl 时,安卓端进页面 3 秒后自动拉起该 APK
* - 下载前把 { ...query, tid } 写入剪贴板供 App 首启归因
*
* 组件接入:
@@ -30,6 +31,8 @@ export interface ButtonList {
iosLink?: string
androidButton?: number
hasChannelApk?: boolean
// 渠道包地址:有值说明该渠道有专属 APK,安卓端进页面自动下载
channelApkAndDownUrl?: string
/** 联系方式:落地页右上角「群聊」等入口 */
contact?: { telegram?: string; paoto?: string; madou?: string }
[key: string]: unknown
@@ -44,6 +47,10 @@ const ip = ref('')
const ready = ref(false)
let initPromise: Promise<void> | null = null
// 渠道包自动下载:延迟时长(从进页面算起)+ 单页生命周期内只触发一次
const AUTO_DOWNLOAD_DELAY = 3000
let autoDownloadFired = false
const isIos = /iphone|ipad|ipod/i.test(navigator.userAgent)
const isWeiXin = /MicroMessenger/i.test(navigator.userAgent)
@@ -153,15 +160,59 @@ export function useAppDownload() {
return true
}
function buildParam(terminal: Terminal): donwloadParam {
return {
appId: APP_ID,
ip: ip.value,
channel: filterChannel(route.query),
domain: window.location.host || '',
// bili 默认值,安卓请求同样带 iosH5
type: 'iosH5',
terminal,
}
}
// 下载前写剪贴板,供 App 首次启动读取做安装归因(整包 URL 参数 + tid)
function writeAttribution() {
const trace_id = renewSessionTraceId()
try {
copyToClipboard(JSON.stringify({ ...route.query, tid: trace_id }))
} catch (err) {
console.log('写入归因剪贴板失败' + err)
}
}
/**
* 渠道包自动下载:bottonlist 返回 channelApkAndDownUrl 有值时,
* 安卓端进页面 delay 毫秒后自动拉起该 APK(整个页面生命周期只触发一次)。
* iOS 装不了 APK、社媒内置浏览器会被拦截跳出,这两种情况都跳过,交给用户手动点。
*/
function autoDownloadChannelApk(delay = AUTO_DOWNLOAD_DELAY) {
if (autoDownloadFired || isIos || isSocialInAppBrowser()) return
autoDownloadFired = true
// 计时与拉接口并行:3 秒从进页面算起,接口慢就等接口回来再下
const waiting = new Promise((resolve) => setTimeout(resolve, delay))
Promise.all([init(), waiting])
.then(() => {
const url = String(buttonList.value.channelApkAndDownUrl || '').trim()
if (!url) return
writeAttribution()
// 自动下载同样记一次点击,统计口径与手动点下载一致
bottonclick(buildParam('android')).catch((err) =>
console.log('自动下载埋点失败' + JSON.stringify(err)),
)
jumpToLink(url)
})
.catch((err) => console.log('渠道包自动下载失败' + err))
}
/**
* 点击下载,返回是否拿到并开始下载(false 时页面可提示稍后重试)
* @param index iOS:0 = 轻量版,1 = 商店包;Android:下载地址下标
* @param terminal 默认按 UA;PC 端弹窗里的 iOS / Android 按钮显式传入
*/
async function download(index = 0, terminal: Terminal = isIos ? 'ios' : 'android') {
const trace_id = renewSessionTraceId()
// 写剪贴板供 App 首次启动读取做安装归因:整包 URL 参数 + tid(App 按 tid 读)
copyToClipboard(JSON.stringify({ ...route.query, tid: trace_id }))
writeAttribution()
if (terminal === 'ios' && index !== 1) {
try {
@@ -173,15 +224,7 @@ export function useAppDownload() {
}
await init()
const param: donwloadParam = {
appId: APP_ID,
ip: ip.value,
channel: filterChannel(route.query),
domain: window.location.host || '',
// bili 默认值,安卓请求同样带 iosH5
type: 'iosH5',
terminal,
}
const param = buildParam(terminal)
try {
return terminal === 'ios'
? await downloadIosStore(param)
@@ -207,5 +250,6 @@ export function useAppDownload() {
iosInstallUrl,
init,
download,
autoDownloadChannelApk,
}
}