import type { Reporter } from '../Reporter'; import type { EnvContext, LinkedData } from '../types'; import { Adapter } from '../Adapter'; import { stringifyQuery, underline2HumpObjectKey } from '../utils'; // 先 store 和 view 共用,有必要再拆分 export class LiteAdapter, R extends Reporter> extends Adapter { storage = { supportSync: false, setItem(key: string, value: any) { if (!lite?.kv) return; if (value === undefined || value === null) return; (lite.kv.setItem(key, JSON.stringify(value)) as any)?.catch?.(() => { // 静默处理 }); }, /** 小心使用,这是异步的! */ async getItem(key: string, defaultValue?: string) { if (!lite?.kv) return defaultValue; try { const value = await lite.kv.getItem(key); if (value === undefined || value === null) return defaultValue; return JSON.parse(value); } catch (e) { // TODO: 报错 console.error('[Merlin] getItem failed', e); return defaultValue; } }, removeItem(key: string) { if (!lite?.kv) return; (lite.kv.removeItem(key) as any)?.catch?.(() => { // 静默处理 }); }, }; private thisHandleRouteEnter = this.handleRouteEnter.bind(this); private thisHandleUnload = this.handleUnload.bind(this); init(reporter: R) { super.init(reporter); if (!lite) { console.error('[Merlin] LiteAdapter can only be used in liteApp environment (with lite defined)'); return; } lite.addEventListener('routeEnter', this.thisHandleRouteEnter); lite.addEventListener('unload', this.thisHandleUnload); } settle() { // if (!lite) return; // lite.removeEventListener('routeEnter', this.thisHandleRouteEnter); // lite.removeEventListener('unload', this.thisHandleUnload); } updateScopeInfo() { if (!this.reporter || !lite) return; // TODO: 解析 ua 然后更新 hostInfo const info = lite.system.getSystemInfo(); this.updateScopeInfoField('network', info.networkType); this.updateScopeInfoField('devicePixelRatio', info.pixelRatio); this.handleRouteEnter(); // 本地读一下 } readLinkedData(query?: Record) { if (!this.reporter || !lite?.router) return; const queryObj = underline2HumpObjectKey(query || lite.router.currentQuery || {}); if (queryObj.contextId) { this.updateScopeInfoField('contextId', queryObj.contextId); } if (queryObj.entranceId) { this.updateScopeInfoField('entranceId', queryObj.entranceId); } if (this.reporter.scopeInfo.entranceInfo?.subEntranceid !== queryObj.subEntranceid) { this.reporter.scopeInfo.entranceInfo = { subEntranceid: queryObj.subEntranceid }; } if (queryObj.reddotId) { this.updateScopeInfoField('redDotInfo', { id: queryObj.reddotId, }); } if (queryObj.fromAccessId) { this.updateScopeInfoField('fromAccessId', queryObj.fromAccessId); } if (queryObj.fromElelmentId) { this.updateScopeInfoField('fromElementId', queryObj.fromElementId); } } get linkedData(): LinkedData { return { contextId: this.reporter?.scopeInfo.contextId, entranceId: this.reporter?.scopeInfo.entranceId, subEntranceid: this.reporter?.scopeInfo.entranceInfo?.subEntranceid, reddotId: this.reporter?.scopeInfo.redDotInfo?.id, }; } serializeLinkedData(extra?: LinkedData): string { return stringifyQuery({ ...this.linkedData, ...extra }); } async httpPost( url: string, data: string, options: { contentType: string; }, ): Promise { // try { // const succeed = lite.system.sendBeacon(url, data); // if (succeed) { // return; // } // } catch (e) {} // this?.reporter?.log('未能使用 sendBeacon 发送数据,使用 fetch'); try { await fetch(url, { method: 'POST', headers: { 'Content-Type': options.contentType, }, body: data, }); } catch (e: any) { this.reporter?.errorHandler(e); } } protected handleRouteEnter(options?: { path?: string; query?: Record }) { if (!lite || !lite.router) return; let href = options?.path || lite.router.currentRoute; const query = options?.query || lite.router.currentQuery; this.readLinkedData(query); if (query && Object.keys(query).length > 0) { href += '?'; href += stringifyQuery(query); } this.updateScopeInfoField('href', href); } protected getEnvInfo(): EnvContext { if (!lite) return {}; const info = lite.system.getSystemInfo(); return { userAgent: lite.system.getUserAgent(), // device: info.platform, deviceBrand: info.brand, deviceModel: info.model, osName: info.platform, osVersion: `${info.system}`, appVersion: info.version, liteAppVersion: info.liteAppVersion, appId: info.appId, }; } private handleUnload() { this.reporter?.settle().then(() => { this.reporter?.log('Reporter 清算结束'); }); } }