@cherish8change/naviot-fillingpoint_sdk
Version:
naviot埋点SDK
145 lines (120 loc) • 4.07 kB
text/typescript
import { v4 as uuidv4 } from 'uuid';
import * as turf from "@turf/turf";
interface ReporStruct {
// 上报间隔超过一个小时后产生新的reporId,即使浏览器关闭再打开如果不超过一小时也是用旧的
reportId: string;
// 用户唯一标识
userId: string;
// 归类模块
tag: string;
// 模块名称,对应页面路由
moduleName: string;
// 用户操作
action: string;
// 操作参数
params: any;
// 纬度
latitude: number;
// 经度
longitude: number;
// 操作发生时间戳
timestamp: number;
// 是否移动设备
mobile: boolean;
userAgent: string;
platform: string;
}
type CommStr = Pick<ReporStruct, 'reportId' | 'userId' | 'latitude' | 'longitude' | 'mobile' | 'userAgent' | 'platform'>;
class FillingPointSDK {
private data: CommStr
private enable: boolean; // 启用/禁用
private STORAGE_KEY = 'FillingPoint_KEY';
private timeout = 1000 * 60 * 60;
private url = '';
private headers: RequestInit['headers'];
constructor(config: { url: string; userId: string; platform: string; mobile?: boolean, headers?: RequestInit['headers']; }) {
this.enable = true;
this.url = config.url;
this.headers = config.headers ?? {};
this.data = {
reportId: uuidv4(),
userId: config.userId,
latitude: -1,
longitude: -1,
mobile: config.mobile ?? false,
userAgent: navigator.userAgent,
platform: config.platform,
};
this.listenerGeoChange();
if (typeof window !== 'undefined' && !window.FillingPointSDK) {
// 挂载实例到 window
window.FillingPointSDK = this;
}
}
listenerGeoChange() {
navigator.geolocation.watchPosition((succ) => {
console.log('地理位置变化:', succ);
const latitude = succ.coords.latitude;
const longitude = succ.coords.longitude;
const storage = JSON.parse(localStorage.getItem(this.STORAGE_KEY) ?? '{}');
const from = turf.point([storage.latitude ?? latitude, storage.longitude ?? longitude]);
const to = turf.point([latitude, longitude]);
const distance = turf.distance(from, to); // 千米
this.setData('latitude', latitude);
this.setData('longitude', longitude);
if (distance > 3) {
const uuid = uuidv4();
this.setData('reportId', uuid);
localStorage.setItem(this.STORAGE_KEY, JSON.stringify({ ...storage, reportId: uuid, latitude, longitude }));
} else if (!storage.latitude && !storage.longitude) {
localStorage.setItem(this.STORAGE_KEY, JSON.stringify({ ...storage, latitude, longitude }));
}
}, () => {}, {});
}
getData<T extends keyof CommStr>(key: T): CommStr[T] {
return this.data[key];
}
setData<T extends keyof CommStr>(key: T, value: CommStr[T]) {
this.data[key] = value;
}
setTime(time: number) {
this.timeout = time;
}
disable() {
this.enable = false;
}
repor(tag: string, moduleName: ReporStruct['moduleName'], action: ReporStruct['action'], params: ReporStruct['params'] = '') {
if (!this.enable) return;
const timestamp = new Date().getTime();
window.requestAnimationFrame(() => {
const storage = JSON.parse(localStorage.getItem(this.STORAGE_KEY) ?? '{}');
if (timestamp - (storage.timestamp ?? 0) > this.timeout) {
const uuid = uuidv4();
this.setData('reportId', uuid);
localStorage.setItem(this.STORAGE_KEY, JSON.stringify({ ...storage, reportId: uuid, timestamp }));
} else {
localStorage.setItem(this.STORAGE_KEY, JSON.stringify({ ...storage, timestamp }));
}
const reporData: ReporStruct = {
tag,
moduleName,
action,
params,
timestamp,
...this.data,
};
if (!this.url) {
return;
}
fetch(this.url, {
method: 'post',
headers: {
"Content-Type": "application/json",
...this.headers
},
body: JSON.stringify(reporData),
});
});
}
}
export default FillingPointSDK;