This commit is contained in:
谢宇宁
2026-09-15 16:25:45 +07:00
parent da39ab9a2a
commit 2d63d37930
449 changed files with 25632 additions and 24085 deletions
+79
View File
@@ -0,0 +1,79 @@
/**
* 事件上报服务
*
* LandingSDK 由 index.html 异步加载,加载完成前 window.tracker 只是一个排队用的桩函数;
* v2 SDK 不再接受桩队列回放出来的泛型调用 track({ event })(会判「非法上报」丢弃),
* 所以这里等 SDK 就绪后再走具名方法 landingPageView / landingPageClick。
*/
import type { EventCode } from './types'
const SDK_READY_TIMEOUT_MS = 10000
const SDK_POLL_MS = 30
type LandingTracker = ((payload: Record<string, any>) => Promise<unknown>) & {
landingPageView?: (properties?: Record<string, any>) => Promise<unknown>
landingPageClick?: (properties?: Record<string, any>) => Promise<unknown>
}
// 等到 window.tracker 被 App.vue initTracker 替换成真正的 SDK track(带具名方法)为止。
// 注意:SDK 的 track 是 Proxy,访问任意属性(包括 then)都会被当成事件名,所以不能直接把它交给 Promise resolve
// 否则 Promise 会去调它的 then 而永远不落定;这里用对象包一层。
function waitForTracker(): Promise<{ tracker: LandingTracker | null }> {
return new Promise((resolve) => {
const startedAt = Date.now()
const check = () => {
const tracker = (window as any).tracker as LandingTracker | undefined
if (tracker && typeof tracker.landingPageView === 'function') {
resolve({ tracker })
return
}
if (Date.now() - startedAt > SDK_READY_TIMEOUT_MS) {
resolve({ tracker: null })
return
}
setTimeout(check, SDK_POLL_MS)
}
check()
})
}
/**
* 事件上报服务类
*/
export class EventTracker {
/**
* 发送事件到服务器
*/
async sendEvent(eventCode: EventCode, properties?: Record<string, any>) {
const { tracker } = await waitForTracker()
if (!tracker) {
console.log('LandingSDK 未就绪,事件丢弃:' + eventCode)
return
}
try {
if (eventCode === 'landing_page_view' && typeof tracker.landingPageView === 'function') {
await tracker.landingPageView(properties)
} else if (eventCode === 'landing_page_click' && typeof tracker.landingPageClick === 'function') {
await tracker.landingPageClick(properties)
} else {
await tracker({ event: eventCode, ...properties })
}
} catch (err) {
console.log('埋点上报失败:' + eventCode + ' ' + err)
}
}
}
// 单例实例
let trackerInstance: EventTracker | null = null
/**
* 获取事件上报器实例(自动初始化,无需手动初始化)
*/
export function getEventTracker(): EventTracker {
if (!trackerInstance) {
trackerInstance = new EventTracker()
}
return trackerInstance
}