自动下载添加
This commit is contained in:
@@ -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()
|
||||
})
|
||||
|
||||
|
||||
@@ -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
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user