lee_web_track_sdk 0.0.16 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +37 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +37 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1198,7 +1198,7 @@ var getUserId = function() {
|
|
|
1198
1198
|
};
|
|
1199
1199
|
// src/utils/browser.ts
|
|
1200
1200
|
var import_bowser = __toESM(require("bowser"), 1);
|
|
1201
|
-
var getBrowserAndDeviceInfo = function() {
|
|
1201
|
+
var getBrowserAndDeviceInfo = function(adapter) {
|
|
1202
1202
|
var defRes = {
|
|
1203
1203
|
browserName: "unknown",
|
|
1204
1204
|
browserVersion: "unknown",
|
|
@@ -1207,26 +1207,45 @@ var getBrowserAndDeviceInfo = function() {
|
|
|
1207
1207
|
platformName: "unknown"
|
|
1208
1208
|
};
|
|
1209
1209
|
try {
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1210
|
+
if (adapter === "web") {
|
|
1211
|
+
var ua = window.navigator.userAgent;
|
|
1212
|
+
if (!ua) return defRes;
|
|
1213
|
+
var info = import_bowser.default.parse(ua);
|
|
1214
|
+
var browser = info.browser, os = info.os, platform = info.platform;
|
|
1215
|
+
return {
|
|
1216
|
+
browserName: browser.name || "unknown",
|
|
1217
|
+
browserVersion: browser.version || "unknown",
|
|
1218
|
+
osName: os.name || "unknown",
|
|
1219
|
+
osVersion: os.version || "unknown",
|
|
1220
|
+
platformName: platform.type || "unknown"
|
|
1221
|
+
};
|
|
1222
|
+
} else {
|
|
1223
|
+
if (!wx) return defRes;
|
|
1224
|
+
var info1 = wx.getDeviceInfo();
|
|
1225
|
+
var brand = info1.brand, model = info1.model, platform1 = info1.platform, system = info1.system;
|
|
1226
|
+
return {
|
|
1227
|
+
browserName: brand || "miniProgram",
|
|
1228
|
+
browserVersion: model || "unknown",
|
|
1229
|
+
osName: system || "unknown",
|
|
1230
|
+
osVersion: system || "unknown",
|
|
1231
|
+
platformName: platform1 || "unknown"
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
1221
1234
|
} catch (error) {
|
|
1222
1235
|
logWarn(error);
|
|
1223
1236
|
return defRes;
|
|
1224
1237
|
}
|
|
1225
1238
|
};
|
|
1226
|
-
var getDeviceResolution = function() {
|
|
1227
|
-
if (
|
|
1228
|
-
|
|
1229
|
-
|
|
1239
|
+
var getDeviceResolution = function(adapter) {
|
|
1240
|
+
if (adapter === "web") {
|
|
1241
|
+
if (!window) return "unknown";
|
|
1242
|
+
var screen = window.screen;
|
|
1243
|
+
return "".concat(screen.width, "x").concat(screen.height);
|
|
1244
|
+
} else {
|
|
1245
|
+
if (!wx) return "unknown";
|
|
1246
|
+
var screen1 = wx.getWindowInfo();
|
|
1247
|
+
return "".concat(screen1.screenWidth, "x").concat(screen1.screenHeight);
|
|
1248
|
+
}
|
|
1230
1249
|
};
|
|
1231
1250
|
// src/plugin/track/trackClass.ts
|
|
1232
1251
|
var FrTrack = /*#__PURE__*/ function() {
|
|
@@ -1595,7 +1614,7 @@ var FrTrack = /*#__PURE__*/ function() {
|
|
|
1595
1614
|
user_id: this.userId,
|
|
1596
1615
|
device_type: platformName,
|
|
1597
1616
|
user_agent: "os: ".concat(osName, "--v").concat(osVersion, ", browser: ").concat(browserName, "--v").concat(browserVersion),
|
|
1598
|
-
screen_resolution: getDeviceResolution(),
|
|
1617
|
+
screen_resolution: getDeviceResolution(this.instanceConfig.adapter),
|
|
1599
1618
|
user_timezone: getUserTimeZone(),
|
|
1600
1619
|
event_time: Date.now(),
|
|
1601
1620
|
custom_data: null
|
|
@@ -1834,8 +1853,8 @@ var FrTrack = /*#__PURE__*/ function() {
|
|
|
1834
1853
|
{
|
|
1835
1854
|
key: "init",
|
|
1836
1855
|
value: function init() {
|
|
1856
|
+
this.browserInfo = getBrowserAndDeviceInfo(this.instanceConfig.adapter);
|
|
1837
1857
|
if (this.instanceConfig.adapter === "web" && window) {
|
|
1838
|
-
this.browserInfo = getBrowserAndDeviceInfo();
|
|
1839
1858
|
this.onBrowserClose();
|
|
1840
1859
|
this.frUserView();
|
|
1841
1860
|
if (this.pluginOptions.autoPv) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/hl/Desktop/project/track-sdk/dist/index.cjs","../src/index.ts","../src/config/index.ts","../src/adapter/web/cache.ts","../src/core/cache.ts","../src/core/report.ts","../src/core/init.ts","../src/static/constant.ts","../src/utils/utils.ts","../src/utils/validator.ts","../src/core/clean.ts","../src/core/aggregation.ts","../src/adapter/web/report.ts","../src/adapter/wx/cache.ts","../src/adapter/wx/report.ts","../src/adapter/index.ts","../src/utils/uuid.ts","../src/utils/browser.ts","../src/plugin/track/trackClass.ts","../src/plugin/track/index.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","index_exports","default","index_default","module","exports","MAX_CACHE_SIZE","MAX_CACHE_TIME","MAX_TIMEOUT","defaultConfig","project_name","report_url","app_version","adapter","maxCacheSize","maxCacheTime","maxTimeout","isDebug","plugins","type","options","autoPv","localForage","require","Cache","initCache","CacheClass","Report","initReport","ReportClass","url","Error","coreInit","config","instance","$cache","cache","$report","report","timeout","EVENT_TYPES","CAN_AGGREGATION_TYPES","EVENT_KEYS","CACHE_DATA_NAME","CACHE_ERR_DATA_NAME","logInfo","message","title","logTitle","console","log","logWarn","warn","logError","error","getVariableType","variable","typeString","toString","slice","toLowerCase","generateFallbackUUID","replace","c","r","Math","random","v","generateUserId","crypto","randomUUID","overrideHistoryMethods","originalMethod","history","args","res","apply","e","Event","window","dispatchEvent","getUserTimeZone","Intl","DateTimeFormat","resolvedOptions","timeZone","offset","Date","getTimezoneOffset","debounce","fn","delay","immediate","timer","flag","clearTimeout","setTimeout","sanitizeCustomData","data","sanitized","entries","validateEventType","eventType","includes","validateEventKey","params","keys","cleanTrackData","rawData","tempIds","Set","resultData","filter","rawItem","eventKeyResult","eventTypeResult","event_type","eventTime","event_time","minDateTime","getTime","id","event_name","has","add","errReason","aggregationData","i","item","is_aggregation","currentDate","setHours","resultItem","find","push","user_id","customData","custom_data","count","length","WebCache","getItem","set","currentData","cacheData","Array","isArray","setItem","remove","removeItem","clear","cache_default","WebReport","retry","failedData","callback","retryCount","err","send","Promise","resolve","reject","navigator","jsonData","JSON","stringify","formData","FormData","append","status","sendBeacon","xhr","XMLHttpRequest","open","setRequestHeader","onload","response","onerror","report_default","WxCache","wx","getStorageSync","setStorageSync","removeStorageSync","clearStorageSync","WxReport","request","method","success","fail","getEnv","isMiniProgram","getSystemInfoSync","getAdapter","configEnv","env","getUserId","track_uuid","localStorage","uuid","import_bowser","getBrowserAndDeviceInfo","defRes","browserName","browserVersion","osName","osVersion","platformName","ua","userAgent","info","Browser","parse","browser","os","platform","version","getDeviceResolution","screen","width","height","FrTrack","pluginOptions","userId","uvTimer","lastUvReportTime","browserInfo","taskQueue","isProcessing","reportPrevData","reportErrCacheData","cacheFn","reportFn","instanceConfig","debouncePv","href","location","page_url","page_name","singleTrack","processQueue","currentTask","shift","addTask","task","taskWithDesc","reportCacheData","cleanInfo","result","catch","loopReport","clearInterval","setInterval","onBrowserClose","addEventListener","document","visibilityState","nativePv","methodsList","forEach","toSetCacheData","track","trackParams","assign","device_type","user_agent","screen_resolution","user_timezone","now","baseParams","setUser","updatedData","map","frModuleView","frModuleClick","frLoginEvent","frOrderEvent","frCustomEvent","frLogEvent","frClickEvent","frAutoPageView","pushState","replaceState","frPageView","frUserView","interval","frPageDestroy","frReport","init","trackClass_default","trackPlugin","defaultEnable","install","sdkInstance","defaultOptions","frameType","router","$track","frTrack","FrWebSDK","isInit","userConfig","plugin","getInstance","webSdk"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/index.ts\nvar index_exports = {};\n__export(index_exports, {\n default: () => index_default\n});\nmodule.exports = __toCommonJS(index_exports);\n\n// src/config/index.ts\nvar MAX_CACHE_SIZE = 15;\nvar MAX_CACHE_TIME = 3e5;\nvar MAX_TIMEOUT = 1e4;\nvar defaultConfig = {\n project_name: \"\",\n report_url: \"\",\n app_version: \"\",\n adapter: \"web\",\n maxCacheSize: MAX_CACHE_SIZE,\n maxCacheTime: MAX_CACHE_TIME,\n maxTimeout: MAX_TIMEOUT,\n isDebug: false,\n plugins: [\n {\n type: \"track\",\n options: {\n autoPv: true\n // frameType: 'js',\n // router: null\n }\n }\n ]\n};\n\n// src/adapter/web/cache.ts\nvar localForage = __toESM(require(\"localforage\"), 1);\n\n// src/core/cache.ts\nvar Cache = class {\n constructor(options) {\n if (options) {\n this.options = options;\n }\n }\n};\nfunction initCache(CacheClass, options) {\n return new CacheClass(options);\n}\n\n// src/core/report.ts\nvar Report = class {\n constructor(options) {\n this.options = options;\n }\n};\nfunction initReport(ReportClass, options) {\n if (!options.url) {\n throw new Error(\"\\u8BF7\\u4F20\\u5165\\u4E0A\\u62A5\\u5730\\u5740url\");\n }\n return new ReportClass(options);\n}\n\n// src/core/init.ts\nvar coreInit = ({ config, adapter, instance: instance2 }) => {\n instance2.$cache = initCache(adapter.cache);\n instance2.$report = initReport(adapter.report, {\n url: config.report_url,\n timeout: config.maxTimeout\n });\n};\n\n// src/static/constant.ts\nvar EVENT_TYPES = [\n \"page_view\",\n \"user_view\",\n \"page_destroy\",\n \"click_event\",\n \"module_click\",\n \"module_view\",\n \"login_event\",\n \"order_event\",\n \"custom_event\",\n \"log_event\"\n];\nvar CAN_AGGREGATION_TYPES = [\"page_view\", \"user_view\"];\nvar EVENT_KEYS = [\n \"project_name\",\n \"event_type\",\n \"event_name\",\n \"event_time\",\n \"user_id\",\n \"app_version\",\n \"user_timezone\",\n \"device_type\",\n \"user_agent\",\n \"screen_resolution\",\n \"custom_data\",\n \"is_aggregation\"\n];\nvar CACHE_DATA_NAME = \"fr-track-cache-data\";\nvar CACHE_ERR_DATA_NAME = \"fr-track-cache-err-data\";\n\n// src/utils/utils.ts\nvar logInfo = (message, title, isDebug = false) => {\n if (!isDebug) return;\n const logTitle = title ? `[Fr-track log ${title}]` : \"[Fr-track log]\";\n console.log(`${logTitle}:`, message);\n};\nvar logWarn = (message, title) => {\n const logTitle = title ? `[Fr-track warning ${title}]` : \"[Fr-track warning]\";\n console.warn(`${logTitle}:`, message);\n};\nvar logError = (message, title) => {\n const logTitle = title ? `[Fr-track error ${title}]` : \"[Fr-track error]\";\n console.error(`${logTitle}:`, message);\n};\nvar getVariableType = (variable) => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\nvar generateFallbackUUID = () => {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n};\nvar generateUserId = () => {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return generateFallbackUUID();\n};\nvar overrideHistoryMethods = (type) => {\n const originalMethod = history[type];\n return function(...args) {\n const res = originalMethod.apply(this, args);\n const e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\nvar getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n logWarn(error, \"\\u65E0\\u6CD5\\u83B7\\u53D6\\u65F6\\u533A\\u540D\\u79F0\\uFF0C\\u4F7F\\u7528\\u504F\\u79FB\\u91CF\\u63A8\\u7B97:\");\n const offset = (/* @__PURE__ */ new Date()).getTimezoneOffset();\n if (offset >= 0) {\n return `\\u897F${offset / 60}\\u533A`;\n } else {\n return `\\u4E1C${-offset / 60}\\u533A`;\n }\n }\n};\nfunction debounce(fn, delay = 800, immediate = false) {\n let timer = null;\n let flag = false;\n return function(...args) {\n if (immediate && !flag) {\n fn.apply(this, args);\n }\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n flag = true;\n timer = setTimeout(() => {\n fn.apply(this, args);\n flag = false;\n }, delay);\n };\n}\nvar sanitizeCustomData = (data) => {\n const sanitized = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\") {\n sanitized[key] = value.replace(/<[^>]*>/g, \"\");\n } else if (getVariableType(value) === \"object\") {\n sanitized[key] = sanitizeCustomData(value);\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n};\n\n// src/utils/validator.ts\nfunction validateEventType(eventType) {\n return typeof eventType === \"string\" && EVENT_TYPES.includes(eventType);\n}\nfunction validateEventKey(params) {\n const type = getVariableType(params);\n if (!params || type !== \"object\") {\n logWarn(\"Event params must be an object\");\n return false;\n }\n const keys = Object.keys(params);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key)) {\n logWarn(`Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n\n// src/core/clean.ts\nvar cleanTrackData = (rawData) => {\n try {\n const tempIds = /* @__PURE__ */ new Set();\n const resultData = rawData.filter((rawItem) => {\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n logWarn(\"\\u4E8B\\u4EF6\\u7C7B\\u578B\\u4E0D\\u5408\\u6CD5\");\n return false;\n }\n const eventTime = rawItem.event_time;\n const minDateTime = (/* @__PURE__ */ new Date(\"2025-12-01\")).getTime();\n if (!eventTime || typeof eventTime !== \"number\" || eventTime < minDateTime) {\n return false;\n }\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: \"success\",\n data: resultData\n };\n } catch (error) {\n logError(error, \"\\u6E05\\u6D17\\u5931\\u8D25\");\n const errReason = error.message || \"Unknown error\";\n return {\n type: \"fail\",\n errReason,\n data: rawData\n };\n }\n};\n\n// src/core/aggregation.ts\nvar aggregationData = (rawData) => {\n try {\n const resultData = [];\n for (let i = 0; i < rawData.length; i++) {\n const rawItem = rawData[i];\n if (!rawItem) continue;\n const item = { ...rawItem };\n if (CAN_AGGREGATION_TYPES.includes(item.event_type) || item.is_aggregation) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n (r) => r.event_time === currentDate && r.event_type === item.event_type && r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n if (item.event_type === \"user_view\") {\n resultItem.user_id = item.user_id;\n }\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n logError(error, \"\\u805A\\u5408\\u5931\\u8D25\");\n return rawData;\n }\n};\n\n// src/adapter/web/cache.ts\nvar WebCache = class extends Cache {\n constructor(options) {\n super(options);\n }\n async get(name) {\n const res = await localForage.getItem(name);\n return res || [];\n }\n async set(name, data) {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n await localForage.setItem(name, currentData);\n } else {\n await localForage.setItem(name, cacheData);\n }\n }\n async remove(name) {\n await localForage.removeItem(name);\n }\n async clear() {\n await localForage.clear();\n }\n};\nvar cache_default = WebCache;\n\n// src/adapter/web/report.ts\nvar WebReport = class extends Report {\n constructor(options) {\n super(options);\n }\n async retry(failedData, callback, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3e3);\n }\n }\n async send(data) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (\"sendBeacon\" in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append(\"data\", jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.timeout = timeout;\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n xhr.onload = () => {\n resolve(xhr.response);\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n }\n};\nvar report_default = WebReport;\n\n// src/adapter/wx/cache.ts\nvar WxCache = class extends Cache {\n constructor(options) {\n super(options);\n }\n async get(name) {\n const res = wx.getStorageSync(name);\n return res || [];\n }\n async set(name, data) {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n wx.setStorageSync(name, currentData);\n } else {\n wx.setStorageSync(name, cacheData);\n }\n }\n async remove(name) {\n wx.removeStorageSync(name);\n }\n async clear() {\n wx.clearStorageSync();\n }\n};\nvar cache_default2 = WxCache;\n\n// src/adapter/wx/report.ts\nvar WxReport = class extends Report {\n constructor(options) {\n super(options);\n }\n async retry(failedData, callback, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3e3);\n }\n }\n async send(data) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (wx && wx.request) {\n wx.request({\n url,\n method: \"POST\",\n data,\n timeout,\n success: function success(res) {\n resolve(res);\n },\n fail: function fail(err) {\n reject(err);\n }\n });\n } else {\n reject();\n }\n });\n }\n};\nvar report_default2 = WxReport;\n\n// src/adapter/index.ts\nvar getEnv = () => {\n const isMiniProgram = wx && typeof wx.getSystemInfoSync === \"function\";\n return isMiniProgram ? \"miniProgram\" : \"web\";\n};\nvar getAdapter = (configEnv) => {\n const env = configEnv || getEnv();\n if (env === \"miniProgram\") {\n return {\n env: \"miniProgram\",\n cache: cache_default2,\n report: report_default2\n };\n }\n return {\n env: \"web\",\n cache: cache_default,\n report: report_default\n };\n};\n\n// src/utils/uuid.ts\nvar getUserId = () => {\n try {\n const track_uuid = localStorage.getItem(\"track_uuid\");\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem(\"track_uuid\", uuid);\n return uuid;\n } catch (e) {\n return generateUserId();\n }\n};\n\n// src/utils/browser.ts\nvar import_bowser = __toESM(require(\"bowser\"), 1);\nvar getBrowserAndDeviceInfo = () => {\n const defRes = {\n browserName: \"unknown\",\n browserVersion: \"unknown\",\n osName: \"unknown\",\n osVersion: \"unknown\",\n platformName: \"unknown\"\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = import_bowser.default.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || \"unknown\",\n browserVersion: browser.version || \"unknown\",\n osName: os.name || \"unknown\",\n osVersion: os.version || \"unknown\",\n platformName: platform.type || \"unknown\"\n };\n } catch (error) {\n logWarn(error);\n return defRes;\n }\n};\nvar getDeviceResolution = () => {\n if (!window) return \"unknown\";\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\n// src/plugin/track/trackClass.ts\nvar FrTrack = class {\n constructor(instance2, pluginOptions) {\n this.userId = getUserId();\n this.timer = null;\n this.uvTimer = null;\n this.lastUvReportTime = 0;\n this.browserInfo = null;\n this.taskQueue = [];\n this.isProcessing = false;\n this.reportPrevData = () => {\n this.reportErrCacheData();\n };\n if (!instance2) {\n throw new Error(\"\\u8BF7\\u4F20\\u5165SDk\\u5B9E\\u4F8B\");\n }\n this.cacheFn = instance2.$cache;\n this.reportFn = instance2.$report;\n this.instanceConfig = instance2.config;\n this.pluginOptions = pluginOptions;\n this.debouncePv = debounce((type) => {\n const href = window.location.href || \"\";\n logInfo(type, \"\\u4E8B\\u4EF6\\u89E6\\u53D1\", this.instanceConfig.isDebug);\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: \"unknown\",\n count: 1\n }\n };\n this.singleTrack(\"page_view\", params);\n }, 300);\n }\n /* 执行异步队列任务 */\n async processQueue() {\n if (this.isProcessing || this.taskQueue.length === 0) return;\n this.isProcessing = true;\n const currentTask = this.taskQueue.shift();\n try {\n await currentTask.fn();\n logInfo(`\\u2705 \\u4EFB\\u52A1\\u6267\\u884C\\u6210\\u529F\\uFF1A${currentTask.desc}`, \"\", this.instanceConfig.isDebug);\n } catch (err) {\n logInfo(err, `\\u274C \\u4EFB\\u52A1\\u6267\\u884C\\u5931\\u8D25\\uFF1A${currentTask.desc}`, this.instanceConfig.isDebug);\n } finally {\n this.isProcessing = false;\n this.processQueue();\n }\n }\n /* 异步队列添加任务 */\n addTask(task) {\n const taskWithDesc = {\n desc: `${task.type} \\u4EFB\\u52A1`,\n ...task\n };\n this.taskQueue.push(taskWithDesc);\n this.processQueue();\n }\n /* 上报缓存数据 */\n async reportCacheData() {\n this.addTask({\n type: \"report_send\",\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get(CACHE_DATA_NAME);\n if (!cacheData?.length) return;\n const cleanInfo = cleanTrackData(cacheData);\n if (cleanInfo.type !== \"success\") {\n logWarn(cleanInfo.errReason);\n } else {\n const result = aggregationData(cleanInfo.data);\n logInfo(result, \"\\u4E0A\\u62A5\\u6570\\u636E\", this.instanceConfig.isDebug);\n if (result?.length) {\n this.reportFn.send(result).catch((err) => {\n logError(err, \"\\u4E0A\\u62A5\\u5931\\u8D25\\u6570\\u636E\\u5F02\\u5E38\");\n this.cacheFn.set(CACHE_ERR_DATA_NAME, result);\n });\n }\n }\n await this.cacheFn.remove(CACHE_DATA_NAME);\n }\n });\n }\n /* 上报缓存的失败数据 */\n async reportErrCacheData() {\n this.addTask({\n type: \"report_send\",\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get(CACHE_ERR_DATA_NAME);\n if (!cacheData?.length) return;\n this.reportFn.send(cacheData).catch((err) => {\n logError(err, \"\\u4E0A\\u62A5\\u5931\\u8D25\\u6570\\u636E\\u5F02\\u5E38\");\n });\n await this.cacheFn.remove(CACHE_ERR_DATA_NAME);\n }\n });\n }\n /* 定时循环上报 */\n loopReport() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.timer = setInterval(() => {\n this.reportCacheData();\n }, this.instanceConfig.maxCacheTime);\n }\n /* 浏览器关闭时触发 */\n onBrowserClose() {\n window.addEventListener(\"beforeunload\", () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.reportCacheData();\n });\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState !== \"visible\") {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.reportCacheData();\n } else {\n this.loopReport();\n }\n });\n }\n nativePv() {\n const methodsList = [\"popstate\", \"hashchange\", \"pushState\", \"replaceState\"];\n this.debouncePv(\"\\u521D\\u6B21\\u4E0A\\u62A5\");\n methodsList.forEach((method) => {\n window.addEventListener(method, () => {\n this.debouncePv(method);\n });\n });\n }\n // private vuePv() {\n // if (!this.pluginOptions.router) {\n // throw new Error('请传入路由实例');\n // }\n // const router = this.pluginOptions.router as any;\n // router.afterEach((to: any) => {\n // const params = {\n // event_name: to.path,\n // custom_data: {\n // page_url: to.fullPath || '--',\n // page_name: to.name || '--',\n // count: 1\n // }\n // };\n // this.singleTrack('page_view', params);\n // });\n // }\n async toSetCacheData(params) {\n logInfo(params, \"\\u8BBE\\u7F6E\\u7F13\\u5B58\\u6570\\u636E\", this.instanceConfig.isDebug);\n this.addTask({\n type: \"cache_set\",\n fn: async () => {\n if (!this.cacheFn) return;\n const { maxCacheSize } = this.instanceConfig;\n const res = await this.cacheFn.get(CACHE_DATA_NAME);\n if (res?.length >= maxCacheSize) {\n this.reportCacheData();\n this.toSetCacheData(params);\n } else {\n await this.cacheFn.set(CACHE_DATA_NAME, params);\n }\n }\n });\n }\n async track(params) {\n const { project_name, app_version } = this.instanceConfig;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo;\n if (params.custom_data) {\n params.custom_data = sanitizeCustomData(params.custom_data);\n }\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n this.toSetCacheData(trackParams);\n }\n singleTrack(eventType, params) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n /**\n * @method 自定义用户id\n */\n setUser(id) {\n this.userId = id;\n this.addTask({\n type: \"cache_update\",\n fn: async () => {\n const cacheData = await this.cacheFn.get(CACHE_DATA_NAME);\n if (cacheData?.length) {\n const updatedData = cacheData.map((item) => ({\n ...item,\n user_id: id\n }));\n await this.cacheFn.set(CACHE_DATA_NAME, updatedData);\n }\n }\n });\n }\n /**\n * @method 模块view\n */\n frModuleView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"module_view\", params);\n }\n /**\n * @method 模块click\n */\n frModuleClick(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"module_click\", params);\n }\n /**\n * @method 登录事件\n */\n frLoginEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"login_event\", params);\n }\n /**\n * @method 生单事件\n */\n frOrderEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"order_event\", params);\n }\n /**\n * @method 自定义事件\n */\n frCustomEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"custom_event\", params);\n }\n /**\n * @method 日志事件\n */\n frLogEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"log_event\", params);\n }\n /**\n * @method 点击事件\n */\n frClickEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"click_event\", params);\n }\n /**\n * @method 自动收集pv事件\n */\n frAutoPageView() {\n window.history.pushState = overrideHistoryMethods(\"pushState\");\n window.history.replaceState = overrideHistoryMethods(\"replaceState\");\n this.nativePv();\n }\n /**\n * @method pv事件\n */\n frPageView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"page_view\", params);\n }\n /**\n * @method uv事件\n */\n frUserView() {\n this.lastUvReportTime = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n const interval = 60 * 60 * 1e3;\n const params = {\n event_name: \"user_view\"\n };\n this.singleTrack(\"user_view\", params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n if (now > this.lastUvReportTime + 24 * interval) {\n this.lastUvReportTime = now;\n this.singleTrack(\"user_view\", params);\n }\n }, interval);\n }\n /**\n * @method 页面销毁事件\n */\n frPageDestroy(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"page_destroy\", params);\n }\n /**\n * @method 手动立即上报缓存的数据\n */\n frReport() {\n this.reportCacheData();\n }\n init() {\n if (this.instanceConfig.adapter === \"web\" && window) {\n this.browserInfo = getBrowserAndDeviceInfo();\n this.onBrowserClose();\n this.frUserView();\n if (this.pluginOptions.autoPv) {\n this.frAutoPageView();\n }\n }\n this.reportPrevData();\n this.loopReport();\n }\n};\nvar trackClass_default = FrTrack;\n\n// src/plugin/track/index.ts\nvar trackPlugin = {\n name: \"track\",\n defaultEnable: true,\n install: (sdkInstance, pluginOptions) => {\n try {\n if (!sdkInstance?.$cache || !sdkInstance?.$report) return;\n const defaultOptions = {\n frameType: \"js\",\n router: void 0,\n autoPv: true\n };\n if (pluginOptions) {\n Object.assign(defaultOptions, pluginOptions);\n }\n if (sdkInstance.$track) return;\n const frTrack = new trackClass_default(sdkInstance, defaultOptions);\n sdkInstance.$track = frTrack;\n frTrack.init();\n } catch (err) {\n logError(err, \"trackPlugin\\u521D\\u59CB\\u5316\\u5931\\u8D25\");\n }\n }\n};\n\n// src/index.ts\nvar instance = null;\nvar FrWebSDK = class {\n constructor() {\n this.isInit = false;\n this.config = defaultConfig;\n this.adapter = null;\n }\n init(userConfig) {\n if (this.isInit) {\n logWarn(\"SDK\\u5DF2\\u521D\\u59CB\\u5316\");\n return this;\n }\n this.config = { ...defaultConfig, ...userConfig };\n this.adapter = getAdapter(this.config.adapter);\n coreInit({\n config: this.config,\n adapter: this.adapter,\n instance: this\n });\n if (this.config.plugins) {\n this.config.plugins.forEach((plugin) => {\n if (plugin.type === \"track\") {\n trackPlugin.install(this, plugin.options);\n }\n });\n }\n this.isInit = true;\n return this;\n }\n};\nfunction getInstance() {\n if (!instance) {\n instance = new FrWebSDK();\n }\n return instance;\n}\nvar webSdk = getInstance();\nvar index_default = webSdk;\n","// src/index.js\nimport { defaultConfig } from './config';\nimport { getAdapter } from './adapter/index';\nimport { coreInit } from './core/index.js';\nimport { logWarn } from './utils/utils';\nimport { Cache, Report } from './core';\nimport { trackPlugin } from './plugin/track';\nimport FrTrack from './plugin/track/trackClass';\nimport type { Options, CustomOptions } from './types';\n\nlet instance: InstanceType<typeof FrWebSDK> | null = null;\n\nclass FrWebSDK {\n private adapter: any;\n public isInit: boolean;\n public config: Options;\n public $cache!: InstanceType<typeof Cache>;\n public $report!: InstanceType<typeof Report>;\n public $track!: InstanceType<typeof FrTrack>;\n\n constructor() {\n this.isInit = false;\n this.config = defaultConfig;\n this.adapter = null;\n }\n\n init(userConfig: CustomOptions) {\n if (this.isInit) {\n logWarn('SDK已初始化');\n return this;\n }\n // 合并配置\n this.config = { ...defaultConfig, ...userConfig };\n // 获取适配器\n this.adapter = getAdapter(this.config.adapter);\n // 核心初始化\n coreInit({\n config: this.config,\n adapter: this.adapter,\n instance: this\n });\n // 获取用户插件\n if (this.config.plugins) {\n this.config.plugins.forEach(plugin => {\n if (plugin.type === 'track') {\n trackPlugin.install(this, plugin.options);\n }\n });\n }\n\n this.isInit = true;\n\n return this;\n }\n}\n\n// 获取单例\nfunction getInstance() {\n if (!instance) {\n instance = new FrWebSDK();\n }\n return instance;\n}\n\ntype TrackInstance = InstanceType<typeof FrWebSDK>;\n\nconst webSdk = getInstance();\nexport default webSdk;\nexport type { TrackInstance };\n","import type { Options } from '../types';\n\nconst MAX_CACHE_SIZE = 15;\nconst MAX_CACHE_TIME = 300000;\nconst MAX_TIMEOUT = 10000;\n\nconst defaultConfig: Options = {\n project_name: '',\n report_url: '',\n app_version: '',\n adapter: 'web',\n maxCacheSize: MAX_CACHE_SIZE,\n maxCacheTime: MAX_CACHE_TIME,\n maxTimeout: MAX_TIMEOUT,\n isDebug: false,\n plugins: [\n {\n type: 'track',\n options: {\n autoPv: true\n // frameType: 'js',\n // router: null\n }\n }\n ]\n};\n\nexport { defaultConfig };\n","import * as localForage from 'localforage';\nimport { Cache } from '../../core';\nimport type { CacheName } from '../../core/types';\n\nclass WebCache extends Cache {\n constructor(options?: Record<string, unknown>) {\n super(options);\n }\n\n public async get<T>(name: CacheName) {\n const res = await localForage.getItem<T[]>(name);\n return res || [];\n }\n\n public async set<T>(name: CacheName, data: T | T[]): Promise<void> {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n await localForage.setItem(name, currentData);\n } else {\n await localForage.setItem(name, cacheData);\n }\n }\n\n public async remove(name: CacheName) {\n await localForage.removeItem(name);\n }\n\n public async clear(): Promise<void> {\n await localForage.clear();\n }\n}\n\nexport default WebCache;\n","import type { CacheName } from './types';\n\nexport abstract class Cache {\n protected options;\n constructor(options?: Record<string, unknown>) {\n if (options) {\n this.options = options;\n }\n }\n public abstract get<T>(name: CacheName): Promise<T[]> | T[];\n public abstract set<T>(name: CacheName, data: T | T[]): Promise<void> | void;\n public abstract remove(name: CacheName): void | Promise<void>;\n public abstract clear(): void | Promise<void>;\n}\n\n// 导出初始化方法(适配具体实现)\nexport function initCache<T extends Cache>(\n CacheClass: new (options: unknown) => T,\n options?: { [key: string]: unknown }\n): T {\n return new CacheClass(options);\n}\n\ntype CacheType = InstanceType<typeof Cache>;\n\nexport type { CacheType };\n","import type { ReportReq } from './types';\n\nexport abstract class Report {\n protected options;\n constructor(options: ReportReq) {\n this.options = options;\n }\n public abstract send<T>(data: T[]): Promise<unknown>;\n public abstract retry<T>(failedData: T[], callback?: () => void): void;\n}\n\n// 导出初始化方法(适配具体实现)\nexport function initReport<T extends Report>(\n ReportClass: new (options: unknown) => T,\n options: ReportReq\n): T {\n if (!options.url) {\n throw new Error('请传入上报地址url');\n }\n return new ReportClass(options);\n}\n\ntype ReportType = InstanceType<typeof Report>;\n\nexport type { ReportType };\n","import { initCache } from './cache';\nimport { initReport } from './report';\nconst coreInit = ({ config, adapter, instance }: any) => {\n // 初始化缓存\n instance.$cache = initCache(adapter.cache);\n // 初始化上报\n instance.$report = initReport(adapter.report, {\n url: config.report_url,\n timeout: config.maxTimeout\n });\n};\n\nexport { coreInit };\n","const EVENT_TYPES = [\n 'page_view',\n 'user_view',\n 'page_destroy',\n 'click_event',\n 'module_click',\n 'module_view',\n 'login_event',\n 'order_event',\n 'custom_event',\n 'log_event'\n] as const;\n\nconst CAN_AGGREGATION_TYPES = ['page_view', 'user_view'] as const;\n\nconst EVENT_KEYS = [\n 'project_name',\n 'event_type',\n 'event_name',\n 'event_time',\n 'user_id',\n 'app_version',\n 'user_timezone',\n 'device_type',\n 'user_agent',\n 'screen_resolution',\n 'custom_data',\n 'is_aggregation'\n] as const;\n\nconst CACHE_DATA_NAME = 'fr-track-cache-data';\nconst CACHE_ERR_DATA_NAME = 'fr-track-cache-err-data';\n\nexport { EVENT_TYPES, EVENT_KEYS, CAN_AGGREGATION_TYPES, CACHE_DATA_NAME, CACHE_ERR_DATA_NAME };\n","/**\n * 公共打印日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n * @param { boolean } isDebug 是否调试模式\n */\nconst logInfo = (message: unknown, title?: string, isDebug = false): void => {\n if (!isDebug) return;\n const logTitle = title ? `[Fr-track log ${title}]` : '[Fr-track log]';\n console.log(`${logTitle}:`, message);\n};\n\n/**\n * 公共打印警告日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n */\nconst logWarn = (message: unknown, title?: string): void => {\n const logTitle = title ? `[Fr-track warning ${title}]` : '[Fr-track warning]';\n console.warn(`${logTitle}:`, message);\n};\n\n/**\n * 公共打印异常日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n */\nconst logError = (message: unknown, title?: string): void => {\n const logTitle = title ? `[Fr-track error ${title}]` : '[Fr-track error]';\n console.error(`${logTitle}:`, message);\n};\n\n/**\n * 获取变量类型\n * @param { unknown } variable 变量\n * @return { string } 类型字符串\n */\nconst getVariableType = (variable: unknown): string => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\n\n/**\n * 手动实现 UUID v4\n * @returns { string } uuid\n */\nconst generateFallbackUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * 生成uuid\n * @returns { string } uuid\n */\nconst generateUserId = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // 降级方案\n return generateFallbackUUID();\n};\n\n/**\n * 重写history的pushState和replaceState\n */\nconst overrideHistoryMethods = <T extends keyof History>(type: T): any => {\n const originalMethod = history[type];\n return function (this: any, ...args: any) {\n const res = originalMethod.apply(this, args);\n const e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\n\n/**\n * 获取用户时区\n */\nconst getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n logWarn(error, '无法获取时区名称,使用偏移量推算:');\n const offset = new Date().getTimezoneOffset();\n if (offset >= 0) {\n return `西${offset / 60}区`;\n } else {\n return `东${-offset / 60}区`;\n }\n }\n};\n\n/**\n * 触发事件后,延迟指定时间再执行函数;若延迟内再次触发,重新计时\n * @param fn 要防抖的目标函数(支持任意参数、任意返回值,保留this指向)\n * @param delay 防抖延迟时间,默认800毫秒\n * @param immediate 是否立即执行(true:首次触发立即执行,后续延迟内触发重新计时;false:延迟后执行)\n * @returns 包装后的防抖函数(与原函数参数一致,无返回值)\n */\nexport function debounce<F extends (...args: any[]) => any>(\n fn: F,\n delay: number = 800,\n immediate: boolean = false\n): (...args: Parameters<F>) => void {\n let timer: number | null = null;\n let flag = false;\n\n return function (this: ThisParameterType<F>, ...args: Parameters<F>) {\n if (immediate && !flag) {\n fn.apply(this, args);\n }\n\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n\n flag = true;\n timer = setTimeout(() => {\n fn.apply(this, args);\n flag = false;\n }, delay);\n };\n}\n\n/**\n * 递归处理自定义数据,对字符串进行HTML标签过滤,对对象递归处理\n * @param data 自定义数据对象\n * @returns 处理后的自定义数据对象\n */\nconst sanitizeCustomData = (data: Record<string, unknown>) => {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === 'string') {\n sanitized[key] = value.replace(/<[^>]*>/g, '');\n } else if (getVariableType(value) === 'object') {\n sanitized[key] = sanitizeCustomData(value as Record<string, unknown>);\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n};\n\nexport {\n logInfo,\n logWarn,\n logError,\n getVariableType,\n generateUserId,\n overrideHistoryMethods,\n getUserTimeZone,\n sanitizeCustomData\n};\n","import { EVENT_TYPES, EVENT_KEYS } from '../static/constant';\nimport { getVariableType, logWarn } from './utils';\nimport type { EventsType } from '../types';\n\n/**\n * @method 校验事件类型\n */\nexport function validateEventType(eventType?: unknown): boolean {\n return typeof eventType === 'string' && EVENT_TYPES.includes(eventType as EventsType);\n}\n\n/**\n * @method 校验字段\n */\nexport function validateEventKey(params?: unknown): boolean {\n const type = getVariableType(params);\n if (!params || type !== 'object') {\n logWarn('Event params must be an object');\n return false;\n }\n const keys = Object.keys(params as Record<string, unknown>);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key as (typeof EVENT_KEYS)[number])) {\n logWarn(`Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n","import { validateEventType, validateEventKey } from '../utils/validator';\nimport { logWarn, logError } from '../utils/utils';\n// TODO: 解耦\nimport type { TrackEventItem } from '../plugin/track/types';\n\n/**\n * 清洗上报数据\n * @param { array } rawData 待清洗的原数据\n * @returns { array } 清洗后的数据\n */\nconst cleanTrackData = (\n rawData: TrackEventItem[]\n): {\n type: 'success' | 'fail';\n errReason?: string;\n data: TrackEventItem[];\n} => {\n try {\n // 过滤非法的事件类型、非法的时间日期\n const tempIds = new Set();\n const resultData = rawData.filter(rawItem => {\n // 缺失必要字段\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n\n // event_type校验不通过\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n logWarn('事件类型不合法');\n return false;\n }\n\n // event_time校验不通过\n const eventTime = rawItem.event_time;\n const minDateTime = new Date('2025-12-01').getTime();\n if (!eventTime || typeof eventTime !== 'number' || eventTime < minDateTime) {\n return false;\n }\n\n // 相同时间戳相同事件已存在\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: 'success',\n data: resultData\n };\n } catch (error) {\n logError(error, '清洗失败');\n const errReason = (error as Error).message || 'Unknown error';\n return {\n type: 'fail',\n errReason: errReason,\n data: rawData\n };\n }\n};\n\nexport { cleanTrackData };\n","import { CAN_AGGREGATION_TYPES } from '../static/constant';\nimport { logError } from '../utils/utils';\n// TODO: 解耦\nimport type { TrackEventItem } from '../plugin/track/types';\n\n/**\n * 聚合数据\n * @param { array } rawData 需要聚合的原数据\n * @returns { array } 聚合后的数据\n */\nconst aggregationData = (rawData: TrackEventItem[]): TrackEventItem[] => {\n try {\n const resultData: TrackEventItem[] = [];\n for (let i = 0; i < rawData.length; i++) {\n const rawItem = rawData[i];\n if (!rawItem) continue;\n const item = { ...rawItem };\n /**\n * 以\"天\"为维度,将以下事件进行聚合\n * pv、uv、自定义指定需要聚合的数据\n */\n if (\n CAN_AGGREGATION_TYPES.includes(item.event_type as (typeof CAN_AGGREGATION_TYPES)[number]) ||\n item.is_aggregation\n ) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time as number).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n r =>\n r.event_time === currentDate &&\n r.event_type === item.event_type &&\n r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n // 如果是uv,后面的userId覆盖之前\n if (item.event_type === 'user_view') {\n resultItem.user_id = item.user_id;\n }\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n logError(error, '聚合失败');\n // 聚合失败则直接上报原数据\n return rawData;\n }\n};\n\nexport { aggregationData };\n","import { Report } from '../../core';\nimport type { ReportReq } from '../../core/types';\n\nclass WebReport extends Report {\n constructor(options: ReportReq) {\n super(options);\n }\n\n public async retry<T>(failedData: T[], callback?: () => void, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3000);\n }\n }\n\n public async send<T>(data: T[]) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if ('sendBeacon' in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append('data', jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', url, true);\n xhr.timeout = timeout;\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = () => {\n resolve(xhr.response);\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n }\n}\n\nexport default WebReport;\n","import { Cache } from '../../core';\nimport type { CacheName } from '../../core/types';\n\nclass WxCache extends Cache {\n constructor(options?: Record<string, unknown>) {\n super(options);\n }\n\n public async get(name: CacheName) {\n const res = wx.getStorageSync(name);\n return res || [];\n }\n\n public async set<T>(name: CacheName, data: T | T[]): Promise<void> {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n wx.setStorageSync(name, currentData);\n } else {\n wx.setStorageSync(name, cacheData);\n }\n }\n\n public async remove(name: CacheName) {\n wx.removeStorageSync(name);\n }\n\n public async clear(): Promise<void> {\n wx.clearStorageSync();\n }\n}\n\nexport default WxCache;\n","import { Report } from '../../core';\nimport type { ReportReq } from '../../core/types';\n\nclass WxReport extends Report {\n constructor(options: ReportReq) {\n super(options);\n }\n\n public async retry<T>(failedData: T[], callback?: () => void, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3000);\n }\n }\n\n public async send<T>(data: T[]) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (wx && wx.request) {\n wx.request({\n url,\n method: 'POST',\n data: data,\n timeout,\n success: function success(res: any) {\n resolve(res);\n },\n fail: function fail(err: any) {\n reject(err);\n }\n });\n } else {\n reject();\n }\n });\n }\n}\n\nexport default WxReport;\n","import WebCache from './web/cache';\nimport WebReport from './web/report';\nimport WxCache from './wx/cache';\nimport WxReport from './wx/report';\n\n/**\n * 获取运行环境\n */\nconst getEnv = () => {\n const isMiniProgram = wx && typeof wx.getSystemInfoSync === 'function';\n return isMiniProgram ? 'miniProgram' : 'web';\n};\n\n/**\n * 获取对应环境的配置w\n */\nconst getAdapter = (configEnv: string) => {\n const env = configEnv || getEnv();\n if (env === 'miniProgram') {\n return {\n env: 'miniProgram',\n cache: WxCache,\n report: WxReport\n };\n }\n return {\n env: 'web',\n cache: WebCache,\n report: WebReport\n };\n};\n\nexport { getAdapter };\n","import { generateUserId } from '../utils/utils';\n\n/**\n * 获取user_id\n */\nconst getUserId = (): string => {\n try {\n // 查看缓存是否有已生成的uuid\n const track_uuid = localStorage.getItem('track_uuid');\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem('track_uuid', uuid);\n return uuid;\n } catch (e) {\n return generateUserId();\n }\n};\n\nexport { getUserId };\n","import Browser from 'bowser';\nimport { logWarn } from './utils';\nimport type { BrowserInfoType } from '../types';\n\n/**\n * 获取浏览器及设备信息\n * @returns { object | null }\n */\nconst getBrowserAndDeviceInfo = (): BrowserInfoType => {\n const defRes = {\n browserName: 'unknown',\n browserVersion: 'unknown',\n osName: 'unknown',\n osVersion: 'unknown',\n platformName: 'unknown'\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || 'unknown',\n browserVersion: browser.version || 'unknown',\n osName: os.name || 'unknown',\n osVersion: os.version || 'unknown',\n platformName: platform.type || 'unknown'\n };\n } catch (error) {\n logWarn(error);\n return defRes;\n }\n};\n\n/**\n * 获取设备分辨率\n * @return { string } 分辨率信息\n */\nconst getDeviceResolution = (): string => {\n if (!window) return 'unknown';\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\nexport { getBrowserAndDeviceInfo, getDeviceResolution };\n","import { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from '../../static/constant';\nimport { getUserId } from '../../utils/uuid';\nimport { cleanTrackData, aggregationData } from '../../core';\nimport { getBrowserAndDeviceInfo, getDeviceResolution } from '../../utils/browser';\nimport {\n overrideHistoryMethods,\n getUserTimeZone,\n logInfo,\n logWarn,\n logError,\n sanitizeCustomData,\n debounce\n} from '../../utils/utils';\n\nimport type { BrowserInfoType, TrackInstance, TrackPluginOptions } from '../types';\nimport type { TrackEventItem, TrackParams, CustomData, EventsType, TrackTask } from './types';\nimport type { Cache } from '../../core/cache';\nimport type { Report } from '../../core/report';\nimport type { Options } from '../../types';\n\nclass FrTrack<T = TrackEventItem> {\n private userId = getUserId();\n private timer: number | null = null;\n private uvTimer: number | null = null;\n private lastUvReportTime: number = 0;\n private browserInfo: BrowserInfoType | null = null;\n private pluginOptions: TrackPluginOptions;\n private taskQueue: TrackTask[] = [];\n private isProcessing = false;\n private cacheFn: Cache;\n private reportFn: Report;\n private instanceConfig: Options;\n private debouncePv: (key: string) => void;\n\n constructor(instance: TrackInstance, pluginOptions: TrackPluginOptions) {\n if (!instance) {\n throw new Error('请传入SDk实例');\n }\n this.cacheFn = instance.$cache;\n this.reportFn = instance.$report;\n this.instanceConfig = instance.config;\n this.pluginOptions = pluginOptions;\n this.debouncePv = debounce((type: string) => {\n // 初次加载手动执行\n const href = window.location.href || '';\n logInfo(type, '事件触发', this.instanceConfig.isDebug);\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: 'unknown',\n count: 1\n }\n };\n this.singleTrack('page_view', params);\n }, 300);\n }\n\n /* 执行异步队列任务 */\n private async processQueue() {\n // 如果正在执行任务,或队列为空 直接返回\n if (this.isProcessing || this.taskQueue.length === 0) return;\n // 开始执行\n this.isProcessing = true;\n // 取出队列第一个任务\n const currentTask = this.taskQueue.shift()!;\n try {\n await currentTask.fn();\n logInfo(`✅ 任务执行成功:${currentTask.desc}`, '', this.instanceConfig.isDebug);\n } catch (err) {\n logInfo(err, `❌ 任务执行失败:${currentTask.desc}`, this.instanceConfig.isDebug);\n } finally {\n this.isProcessing = false;\n this.processQueue();\n }\n }\n\n /* 异步队列添加任务 */\n private addTask<T>(task: TrackTask<T>) {\n const taskWithDesc = {\n desc: `${task.type} 任务`,\n ...task\n };\n this.taskQueue.push(taskWithDesc);\n // 添加后启动任务\n this.processQueue();\n }\n\n /* 上报缓存数据 */\n private async reportCacheData() {\n this.addTask({\n type: 'report_send',\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (!cacheData?.length) return;\n // 清洗\n const cleanInfo = cleanTrackData(cacheData as TrackEventItem[]);\n if (cleanInfo.type !== 'success') {\n logWarn(cleanInfo.errReason);\n // TODO: 上报失败原因及数据 清空缓存\n } else {\n // 聚合\n const result = aggregationData(cleanInfo.data);\n logInfo(result, '上报数据', this.instanceConfig.isDebug);\n if (result?.length) {\n this.reportFn.send<T>(result as T[]).catch(err => {\n logError(err, '上报失败数据异常');\n this.cacheFn.set(CACHE_ERR_DATA_NAME, result);\n });\n }\n }\n // 不管上报是否成功,删除缓存\n await this.cacheFn.remove(CACHE_DATA_NAME);\n }\n });\n }\n\n /* 上报缓存的失败数据 */\n private async reportErrCacheData() {\n this.addTask({\n type: 'report_send',\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get<T>(CACHE_ERR_DATA_NAME);\n if (!cacheData?.length) return;\n this.reportFn.send<T>(cacheData).catch(err => {\n logError(err, '上报失败数据异常');\n });\n await this.cacheFn.remove(CACHE_ERR_DATA_NAME);\n }\n });\n }\n\n private reportPrevData = () => {\n this.reportErrCacheData();\n };\n\n /* 定时循环上报 */\n private loopReport() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.timer = setInterval(() => {\n this.reportCacheData();\n }, this.instanceConfig.maxCacheTime);\n }\n\n /* 浏览器关闭时触发 */\n private onBrowserClose() {\n /**\n * 浏览器环境\n */\n window.addEventListener('beforeunload', () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.reportCacheData();\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState !== 'visible') {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.reportCacheData();\n } else {\n // 重启定时器\n this.loopReport();\n }\n });\n }\n\n private nativePv() {\n const methodsList = ['popstate', 'hashchange', 'pushState', 'replaceState'];\n // 初始化上报一次\n this.debouncePv('初次上报');\n methodsList.forEach(method => {\n window.addEventListener(method, () => {\n this.debouncePv(method);\n });\n });\n }\n\n // private vuePv() {\n // if (!this.pluginOptions.router) {\n // throw new Error('请传入路由实例');\n // }\n // const router = this.pluginOptions.router as any;\n // router.afterEach((to: any) => {\n // const params = {\n // event_name: to.path,\n // custom_data: {\n // page_url: to.fullPath || '--',\n // page_name: to.name || '--',\n // count: 1\n // }\n // };\n // this.singleTrack('page_view', params);\n // });\n // }\n\n private async toSetCacheData(params: T) {\n logInfo(params, '设置缓存数据', this.instanceConfig.isDebug);\n this.addTask({\n type: 'cache_set',\n fn: async () => {\n if (!this.cacheFn) return;\n const { maxCacheSize } = this.instanceConfig;\n const res = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (res?.length >= maxCacheSize) {\n this.reportCacheData();\n // 上报成功后, 再设置缓存\n this.toSetCacheData(params);\n } else {\n await this.cacheFn.set<T>(CACHE_DATA_NAME, params);\n }\n }\n });\n }\n\n private async track(params: TrackParams) {\n const { project_name, app_version } = this.instanceConfig;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo!;\n if (params.custom_data) {\n params.custom_data = sanitizeCustomData(params.custom_data);\n }\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n this.toSetCacheData(trackParams);\n }\n\n private singleTrack<T extends Omit<TrackParams, 'event_type'>>(\n eventType: EventsType,\n params: T & (keyof T extends keyof Omit<TrackParams, 'event_type'> ? T : never)\n ) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n\n /**\n * @method 自定义用户id\n */\n public setUser(id: string) {\n this.userId = id;\n // 更新userId\n this.addTask({\n type: 'cache_update',\n fn: async () => {\n const cacheData = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (cacheData?.length) {\n const updatedData = cacheData.map(item => ({\n ...item,\n user_id: id\n }));\n await this.cacheFn.set(CACHE_DATA_NAME, updatedData);\n }\n }\n });\n }\n\n /**\n * @method 模块view\n */\n public frModuleView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('module_view', params);\n }\n\n /**\n * @method 模块click\n */\n public frModuleClick(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('module_click', params);\n }\n\n /**\n * @method 登录事件\n */\n public frLoginEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('login_event', params);\n }\n\n /**\n * @method 生单事件\n */\n public frOrderEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('order_event', params);\n }\n\n /**\n * @method 自定义事件\n */\n public frCustomEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('custom_event', params);\n }\n\n /**\n * @method 日志事件\n */\n public frLogEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('log_event', params);\n }\n\n /**\n * @method 点击事件\n */\n public frClickEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('click_event', params);\n }\n\n /**\n * @method 自动收集pv事件\n */\n private frAutoPageView() {\n // if (this.pluginOptions.frameType === 'js') {\n window.history.pushState = overrideHistoryMethods('pushState');\n window.history.replaceState = overrideHistoryMethods('replaceState');\n this.nativePv();\n // } else if (this.pluginOptions.frameType === 'vue') {\n // this.vuePv()\n // }\n }\n\n /**\n * @method pv事件\n */\n public frPageView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('page_view', params);\n }\n\n /**\n * @method uv事件\n */\n public frUserView() {\n this.lastUvReportTime = new Date().setHours(0, 0, 0, 0);\n // 一小时检查一次\n const interval = 60 * 60 * 1000;\n const params = {\n event_name: 'user_view'\n };\n this.singleTrack('user_view', params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = new Date().setHours(0, 0, 0, 0);\n if (now > this.lastUvReportTime + 24 * interval) {\n // 超过24小时,再次上报uv\n // 更新上报时间\n this.lastUvReportTime = now;\n this.singleTrack('user_view', params);\n }\n }, interval);\n }\n\n /**\n * @method 页面销毁事件\n */\n public frPageDestroy(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('page_destroy', params);\n }\n\n /**\n * @method 手动立即上报缓存的数据\n */\n public frReport() {\n this.reportCacheData();\n }\n\n public init() {\n /**\n * 浏览器环境下\n */\n if (this.instanceConfig.adapter === 'web' && window) {\n /**\n * 获取浏览器信息\n */\n this.browserInfo = getBrowserAndDeviceInfo();\n /**\n * 监听浏览器关闭事件,进行上报\n */\n this.onBrowserClose();\n\n /**\n * 统计uv\n */\n this.frUserView();\n\n /**\n * 判断是否监听pv事件\n */\n if (this.pluginOptions.autoPv) {\n this.frAutoPageView();\n }\n }\n\n /**\n * 1. 判断缓存是否有没有传输的数据\n * 2. 判断上次是否有失败的数据存储在缓存中\n */\n this.reportPrevData();\n /**\n * 3. 开启定时器轮询,达到时间阈值进行上报\n */\n this.loopReport();\n }\n}\n\nexport default FrTrack;\n","import FrTrack from './trackClass';\n\nimport type { BasePlugin, TrackPluginOptions } from '../types';\nimport { logError } from '../../utils/utils';\n\nconst trackPlugin: BasePlugin<TrackPluginOptions> = {\n name: 'track',\n defaultEnable: true,\n install: (sdkInstance, pluginOptions) => {\n try {\n if (!sdkInstance?.$cache || !sdkInstance?.$report) return;\n const defaultOptions: TrackPluginOptions = {\n frameType: 'js',\n router: undefined,\n autoPv: true\n };\n if (pluginOptions) {\n Object.assign(defaultOptions, pluginOptions);\n }\n\n if (sdkInstance.$track) return;\n const frTrack = new FrTrack(sdkInstance, defaultOptions);\n sdkInstance.$track = frTrack;\n frTrack.init();\n } catch (err) {\n logError(err, 'trackPlugin初始化失败');\n }\n }\n};\n\nexport { trackPlugin };\n"]}
|
|
1
|
+
{"version":3,"sources":["/Users/hl/Desktop/project/track-sdk/dist/index.cjs","../src/index.ts","../src/config/index.ts","../src/adapter/web/cache.ts","../src/core/cache.ts","../src/core/report.ts","../src/core/init.ts","../src/static/constant.ts","../src/utils/utils.ts","../src/utils/validator.ts","../src/core/clean.ts","../src/core/aggregation.ts","../src/adapter/web/report.ts","../src/adapter/wx/cache.ts","../src/adapter/wx/report.ts","../src/adapter/index.ts","../src/utils/uuid.ts","../src/utils/browser.ts","../src/plugin/track/trackClass.ts","../src/plugin/track/index.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","index_exports","default","index_default","module","exports","MAX_CACHE_SIZE","MAX_CACHE_TIME","MAX_TIMEOUT","defaultConfig","project_name","report_url","app_version","adapter","maxCacheSize","maxCacheTime","maxTimeout","isDebug","plugins","type","options","autoPv","localForage","require","Cache","initCache","CacheClass","Report","initReport","ReportClass","url","Error","coreInit","config","instance","$cache","cache","$report","report","timeout","EVENT_TYPES","CAN_AGGREGATION_TYPES","EVENT_KEYS","CACHE_DATA_NAME","CACHE_ERR_DATA_NAME","logInfo","message","title","logTitle","console","log","logWarn","warn","logError","error","getVariableType","variable","typeString","toString","slice","toLowerCase","generateFallbackUUID","replace","c","r","Math","random","v","generateUserId","crypto","randomUUID","overrideHistoryMethods","originalMethod","history","args","res","apply","e","Event","window","dispatchEvent","getUserTimeZone","Intl","DateTimeFormat","resolvedOptions","timeZone","offset","Date","getTimezoneOffset","debounce","fn","delay","immediate","timer","flag","clearTimeout","setTimeout","sanitizeCustomData","data","sanitized","entries","validateEventType","eventType","includes","validateEventKey","params","keys","cleanTrackData","rawData","tempIds","Set","resultData","filter","rawItem","eventKeyResult","eventTypeResult","event_type","eventTime","event_time","minDateTime","getTime","id","event_name","has","add","errReason","aggregationData","i","item","is_aggregation","currentDate","setHours","resultItem","find","push","user_id","customData","custom_data","count","length","WebCache","getItem","set","currentData","cacheData","Array","isArray","setItem","remove","removeItem","clear","cache_default","WebReport","retry","failedData","callback","retryCount","err","send","Promise","resolve","reject","navigator","jsonData","JSON","stringify","formData","FormData","append","status","sendBeacon","xhr","XMLHttpRequest","open","setRequestHeader","onload","response","onerror","report_default","WxCache","wx","getStorageSync","setStorageSync","removeStorageSync","clearStorageSync","WxReport","request","method","success","fail","getEnv","isMiniProgram","getSystemInfoSync","getAdapter","configEnv","env","getUserId","track_uuid","localStorage","uuid","import_bowser","getBrowserAndDeviceInfo","defRes","browserName","browserVersion","osName","osVersion","platformName","ua","userAgent","info","Browser","parse","browser","os","platform","version","getDeviceInfo","brand","model","system","getDeviceResolution","screen","width","height","getWindowInfo","screenWidth","screenHeight","FrTrack","pluginOptions","userId","uvTimer","lastUvReportTime","browserInfo","taskQueue","isProcessing","reportPrevData","reportErrCacheData","cacheFn","reportFn","instanceConfig","debouncePv","href","location","page_url","page_name","singleTrack","processQueue","currentTask","shift","addTask","task","taskWithDesc","reportCacheData","cleanInfo","result","catch","loopReport","clearInterval","setInterval","onBrowserClose","addEventListener","document","visibilityState","nativePv","methodsList","forEach","toSetCacheData","track","trackParams","assign","device_type","user_agent","screen_resolution","user_timezone","now","baseParams","setUser","updatedData","map","frModuleView","frModuleClick","frLoginEvent","frOrderEvent","frCustomEvent","frLogEvent","frClickEvent","frAutoPageView","pushState","replaceState","frPageView","frUserView","interval","frPageDestroy","frReport","init","trackClass_default","trackPlugin","defaultEnable","install","sdkInstance","defaultOptions","frameType","router","$track","frTrack","FrWebSDK","isInit","userConfig","plugin","getInstance","webSdk"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/index.ts\nvar index_exports = {};\n__export(index_exports, {\n default: () => index_default\n});\nmodule.exports = __toCommonJS(index_exports);\n\n// src/config/index.ts\nvar MAX_CACHE_SIZE = 15;\nvar MAX_CACHE_TIME = 3e5;\nvar MAX_TIMEOUT = 1e4;\nvar defaultConfig = {\n project_name: \"\",\n report_url: \"\",\n app_version: \"\",\n adapter: \"web\",\n maxCacheSize: MAX_CACHE_SIZE,\n maxCacheTime: MAX_CACHE_TIME,\n maxTimeout: MAX_TIMEOUT,\n isDebug: false,\n plugins: [\n {\n type: \"track\",\n options: {\n autoPv: true\n // frameType: 'js',\n // router: null\n }\n }\n ]\n};\n\n// src/adapter/web/cache.ts\nvar localForage = __toESM(require(\"localforage\"), 1);\n\n// src/core/cache.ts\nvar Cache = class {\n constructor(options) {\n if (options) {\n this.options = options;\n }\n }\n};\nfunction initCache(CacheClass, options) {\n return new CacheClass(options);\n}\n\n// src/core/report.ts\nvar Report = class {\n constructor(options) {\n this.options = options;\n }\n};\nfunction initReport(ReportClass, options) {\n if (!options.url) {\n throw new Error(\"\\u8BF7\\u4F20\\u5165\\u4E0A\\u62A5\\u5730\\u5740url\");\n }\n return new ReportClass(options);\n}\n\n// src/core/init.ts\nvar coreInit = ({ config, adapter, instance: instance2 }) => {\n instance2.$cache = initCache(adapter.cache);\n instance2.$report = initReport(adapter.report, {\n url: config.report_url,\n timeout: config.maxTimeout\n });\n};\n\n// src/static/constant.ts\nvar EVENT_TYPES = [\n \"page_view\",\n \"user_view\",\n \"page_destroy\",\n \"click_event\",\n \"module_click\",\n \"module_view\",\n \"login_event\",\n \"order_event\",\n \"custom_event\",\n \"log_event\"\n];\nvar CAN_AGGREGATION_TYPES = [\"page_view\", \"user_view\"];\nvar EVENT_KEYS = [\n \"project_name\",\n \"event_type\",\n \"event_name\",\n \"event_time\",\n \"user_id\",\n \"app_version\",\n \"user_timezone\",\n \"device_type\",\n \"user_agent\",\n \"screen_resolution\",\n \"custom_data\",\n \"is_aggregation\"\n];\nvar CACHE_DATA_NAME = \"fr-track-cache-data\";\nvar CACHE_ERR_DATA_NAME = \"fr-track-cache-err-data\";\n\n// src/utils/utils.ts\nvar logInfo = (message, title, isDebug = false) => {\n if (!isDebug) return;\n const logTitle = title ? `[Fr-track log ${title}]` : \"[Fr-track log]\";\n console.log(`${logTitle}:`, message);\n};\nvar logWarn = (message, title) => {\n const logTitle = title ? `[Fr-track warning ${title}]` : \"[Fr-track warning]\";\n console.warn(`${logTitle}:`, message);\n};\nvar logError = (message, title) => {\n const logTitle = title ? `[Fr-track error ${title}]` : \"[Fr-track error]\";\n console.error(`${logTitle}:`, message);\n};\nvar getVariableType = (variable) => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\nvar generateFallbackUUID = () => {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n};\nvar generateUserId = () => {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return generateFallbackUUID();\n};\nvar overrideHistoryMethods = (type) => {\n const originalMethod = history[type];\n return function(...args) {\n const res = originalMethod.apply(this, args);\n const e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\nvar getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n logWarn(error, \"\\u65E0\\u6CD5\\u83B7\\u53D6\\u65F6\\u533A\\u540D\\u79F0\\uFF0C\\u4F7F\\u7528\\u504F\\u79FB\\u91CF\\u63A8\\u7B97:\");\n const offset = (/* @__PURE__ */ new Date()).getTimezoneOffset();\n if (offset >= 0) {\n return `\\u897F${offset / 60}\\u533A`;\n } else {\n return `\\u4E1C${-offset / 60}\\u533A`;\n }\n }\n};\nfunction debounce(fn, delay = 800, immediate = false) {\n let timer = null;\n let flag = false;\n return function(...args) {\n if (immediate && !flag) {\n fn.apply(this, args);\n }\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n flag = true;\n timer = setTimeout(() => {\n fn.apply(this, args);\n flag = false;\n }, delay);\n };\n}\nvar sanitizeCustomData = (data) => {\n const sanitized = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\") {\n sanitized[key] = value.replace(/<[^>]*>/g, \"\");\n } else if (getVariableType(value) === \"object\") {\n sanitized[key] = sanitizeCustomData(value);\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n};\n\n// src/utils/validator.ts\nfunction validateEventType(eventType) {\n return typeof eventType === \"string\" && EVENT_TYPES.includes(eventType);\n}\nfunction validateEventKey(params) {\n const type = getVariableType(params);\n if (!params || type !== \"object\") {\n logWarn(\"Event params must be an object\");\n return false;\n }\n const keys = Object.keys(params);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key)) {\n logWarn(`Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n\n// src/core/clean.ts\nvar cleanTrackData = (rawData) => {\n try {\n const tempIds = /* @__PURE__ */ new Set();\n const resultData = rawData.filter((rawItem) => {\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n logWarn(\"\\u4E8B\\u4EF6\\u7C7B\\u578B\\u4E0D\\u5408\\u6CD5\");\n return false;\n }\n const eventTime = rawItem.event_time;\n const minDateTime = (/* @__PURE__ */ new Date(\"2025-12-01\")).getTime();\n if (!eventTime || typeof eventTime !== \"number\" || eventTime < minDateTime) {\n return false;\n }\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: \"success\",\n data: resultData\n };\n } catch (error) {\n logError(error, \"\\u6E05\\u6D17\\u5931\\u8D25\");\n const errReason = error.message || \"Unknown error\";\n return {\n type: \"fail\",\n errReason,\n data: rawData\n };\n }\n};\n\n// src/core/aggregation.ts\nvar aggregationData = (rawData) => {\n try {\n const resultData = [];\n for (let i = 0; i < rawData.length; i++) {\n const rawItem = rawData[i];\n if (!rawItem) continue;\n const item = { ...rawItem };\n if (CAN_AGGREGATION_TYPES.includes(item.event_type) || item.is_aggregation) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n (r) => r.event_time === currentDate && r.event_type === item.event_type && r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n if (item.event_type === \"user_view\") {\n resultItem.user_id = item.user_id;\n }\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n logError(error, \"\\u805A\\u5408\\u5931\\u8D25\");\n return rawData;\n }\n};\n\n// src/adapter/web/cache.ts\nvar WebCache = class extends Cache {\n constructor(options) {\n super(options);\n }\n async get(name) {\n const res = await localForage.getItem(name);\n return res || [];\n }\n async set(name, data) {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n await localForage.setItem(name, currentData);\n } else {\n await localForage.setItem(name, cacheData);\n }\n }\n async remove(name) {\n await localForage.removeItem(name);\n }\n async clear() {\n await localForage.clear();\n }\n};\nvar cache_default = WebCache;\n\n// src/adapter/web/report.ts\nvar WebReport = class extends Report {\n constructor(options) {\n super(options);\n }\n async retry(failedData, callback, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3e3);\n }\n }\n async send(data) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (\"sendBeacon\" in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append(\"data\", jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.timeout = timeout;\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n xhr.onload = () => {\n resolve(xhr.response);\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n }\n};\nvar report_default = WebReport;\n\n// src/adapter/wx/cache.ts\nvar WxCache = class extends Cache {\n constructor(options) {\n super(options);\n }\n async get(name) {\n const res = wx.getStorageSync(name);\n return res || [];\n }\n async set(name, data) {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n wx.setStorageSync(name, currentData);\n } else {\n wx.setStorageSync(name, cacheData);\n }\n }\n async remove(name) {\n wx.removeStorageSync(name);\n }\n async clear() {\n wx.clearStorageSync();\n }\n};\nvar cache_default2 = WxCache;\n\n// src/adapter/wx/report.ts\nvar WxReport = class extends Report {\n constructor(options) {\n super(options);\n }\n async retry(failedData, callback, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3e3);\n }\n }\n async send(data) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (wx && wx.request) {\n wx.request({\n url,\n method: \"POST\",\n data,\n timeout,\n success: function success(res) {\n resolve(res);\n },\n fail: function fail(err) {\n reject(err);\n }\n });\n } else {\n reject();\n }\n });\n }\n};\nvar report_default2 = WxReport;\n\n// src/adapter/index.ts\nvar getEnv = () => {\n const isMiniProgram = wx && typeof wx.getSystemInfoSync === \"function\";\n return isMiniProgram ? \"miniProgram\" : \"web\";\n};\nvar getAdapter = (configEnv) => {\n const env = configEnv || getEnv();\n if (env === \"miniProgram\") {\n return {\n env: \"miniProgram\",\n cache: cache_default2,\n report: report_default2\n };\n }\n return {\n env: \"web\",\n cache: cache_default,\n report: report_default\n };\n};\n\n// src/utils/uuid.ts\nvar getUserId = () => {\n try {\n const track_uuid = localStorage.getItem(\"track_uuid\");\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem(\"track_uuid\", uuid);\n return uuid;\n } catch (e) {\n return generateUserId();\n }\n};\n\n// src/utils/browser.ts\nvar import_bowser = __toESM(require(\"bowser\"), 1);\nvar getBrowserAndDeviceInfo = (adapter) => {\n const defRes = {\n browserName: \"unknown\",\n browserVersion: \"unknown\",\n osName: \"unknown\",\n osVersion: \"unknown\",\n platformName: \"unknown\"\n };\n try {\n if (adapter === \"web\") {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = import_bowser.default.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || \"unknown\",\n browserVersion: browser.version || \"unknown\",\n osName: os.name || \"unknown\",\n osVersion: os.version || \"unknown\",\n platformName: platform.type || \"unknown\"\n };\n } else {\n if (!wx) return defRes;\n const info = wx.getDeviceInfo();\n const { brand, model, platform, system } = info;\n return {\n browserName: brand || \"miniProgram\",\n browserVersion: model || \"unknown\",\n osName: system || \"unknown\",\n osVersion: system || \"unknown\",\n platformName: platform || \"unknown\"\n };\n }\n } catch (error) {\n logWarn(error);\n return defRes;\n }\n};\nvar getDeviceResolution = (adapter) => {\n if (adapter === \"web\") {\n if (!window) return \"unknown\";\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n } else {\n if (!wx) return \"unknown\";\n const screen = wx.getWindowInfo();\n return `${screen.screenWidth}x${screen.screenHeight}`;\n }\n};\n\n// src/plugin/track/trackClass.ts\nvar FrTrack = class {\n constructor(instance2, pluginOptions) {\n this.userId = getUserId();\n this.timer = null;\n this.uvTimer = null;\n this.lastUvReportTime = 0;\n this.browserInfo = null;\n this.taskQueue = [];\n this.isProcessing = false;\n this.reportPrevData = () => {\n this.reportErrCacheData();\n };\n if (!instance2) {\n throw new Error(\"\\u8BF7\\u4F20\\u5165SDk\\u5B9E\\u4F8B\");\n }\n this.cacheFn = instance2.$cache;\n this.reportFn = instance2.$report;\n this.instanceConfig = instance2.config;\n this.pluginOptions = pluginOptions;\n this.debouncePv = debounce((type) => {\n const href = window.location.href || \"\";\n logInfo(type, \"\\u4E8B\\u4EF6\\u89E6\\u53D1\", this.instanceConfig.isDebug);\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: \"unknown\",\n count: 1\n }\n };\n this.singleTrack(\"page_view\", params);\n }, 300);\n }\n /* 执行异步队列任务 */\n async processQueue() {\n if (this.isProcessing || this.taskQueue.length === 0) return;\n this.isProcessing = true;\n const currentTask = this.taskQueue.shift();\n try {\n await currentTask.fn();\n logInfo(`\\u2705 \\u4EFB\\u52A1\\u6267\\u884C\\u6210\\u529F\\uFF1A${currentTask.desc}`, \"\", this.instanceConfig.isDebug);\n } catch (err) {\n logInfo(err, `\\u274C \\u4EFB\\u52A1\\u6267\\u884C\\u5931\\u8D25\\uFF1A${currentTask.desc}`, this.instanceConfig.isDebug);\n } finally {\n this.isProcessing = false;\n this.processQueue();\n }\n }\n /* 异步队列添加任务 */\n addTask(task) {\n const taskWithDesc = {\n desc: `${task.type} \\u4EFB\\u52A1`,\n ...task\n };\n this.taskQueue.push(taskWithDesc);\n this.processQueue();\n }\n /* 上报缓存数据 */\n async reportCacheData() {\n this.addTask({\n type: \"report_send\",\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get(CACHE_DATA_NAME);\n if (!cacheData?.length) return;\n const cleanInfo = cleanTrackData(cacheData);\n if (cleanInfo.type !== \"success\") {\n logWarn(cleanInfo.errReason);\n } else {\n const result = aggregationData(cleanInfo.data);\n logInfo(result, \"\\u4E0A\\u62A5\\u6570\\u636E\", this.instanceConfig.isDebug);\n if (result?.length) {\n this.reportFn.send(result).catch((err) => {\n logError(err, \"\\u4E0A\\u62A5\\u5931\\u8D25\\u6570\\u636E\\u5F02\\u5E38\");\n this.cacheFn.set(CACHE_ERR_DATA_NAME, result);\n });\n }\n }\n await this.cacheFn.remove(CACHE_DATA_NAME);\n }\n });\n }\n /* 上报缓存的失败数据 */\n async reportErrCacheData() {\n this.addTask({\n type: \"report_send\",\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get(CACHE_ERR_DATA_NAME);\n if (!cacheData?.length) return;\n this.reportFn.send(cacheData).catch((err) => {\n logError(err, \"\\u4E0A\\u62A5\\u5931\\u8D25\\u6570\\u636E\\u5F02\\u5E38\");\n });\n await this.cacheFn.remove(CACHE_ERR_DATA_NAME);\n }\n });\n }\n /* 定时循环上报 */\n loopReport() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.timer = setInterval(() => {\n this.reportCacheData();\n }, this.instanceConfig.maxCacheTime);\n }\n /* 浏览器关闭时触发 */\n onBrowserClose() {\n window.addEventListener(\"beforeunload\", () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.reportCacheData();\n });\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState !== \"visible\") {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.reportCacheData();\n } else {\n this.loopReport();\n }\n });\n }\n nativePv() {\n const methodsList = [\"popstate\", \"hashchange\", \"pushState\", \"replaceState\"];\n this.debouncePv(\"\\u521D\\u6B21\\u4E0A\\u62A5\");\n methodsList.forEach((method) => {\n window.addEventListener(method, () => {\n this.debouncePv(method);\n });\n });\n }\n // private vuePv() {\n // if (!this.pluginOptions.router) {\n // throw new Error('请传入路由实例');\n // }\n // const router = this.pluginOptions.router as any;\n // router.afterEach((to: any) => {\n // const params = {\n // event_name: to.path,\n // custom_data: {\n // page_url: to.fullPath || '--',\n // page_name: to.name || '--',\n // count: 1\n // }\n // };\n // this.singleTrack('page_view', params);\n // });\n // }\n async toSetCacheData(params) {\n logInfo(params, \"\\u8BBE\\u7F6E\\u7F13\\u5B58\\u6570\\u636E\", this.instanceConfig.isDebug);\n this.addTask({\n type: \"cache_set\",\n fn: async () => {\n if (!this.cacheFn) return;\n const { maxCacheSize } = this.instanceConfig;\n const res = await this.cacheFn.get(CACHE_DATA_NAME);\n if (res?.length >= maxCacheSize) {\n this.reportCacheData();\n this.toSetCacheData(params);\n } else {\n await this.cacheFn.set(CACHE_DATA_NAME, params);\n }\n }\n });\n }\n async track(params) {\n const { project_name, app_version } = this.instanceConfig;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo;\n if (params.custom_data) {\n params.custom_data = sanitizeCustomData(params.custom_data);\n }\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(this.instanceConfig.adapter),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n this.toSetCacheData(trackParams);\n }\n singleTrack(eventType, params) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n /**\n * @method 自定义用户id\n */\n setUser(id) {\n this.userId = id;\n this.addTask({\n type: \"cache_update\",\n fn: async () => {\n const cacheData = await this.cacheFn.get(CACHE_DATA_NAME);\n if (cacheData?.length) {\n const updatedData = cacheData.map((item) => ({\n ...item,\n user_id: id\n }));\n await this.cacheFn.set(CACHE_DATA_NAME, updatedData);\n }\n }\n });\n }\n /**\n * @method 模块view\n */\n frModuleView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"module_view\", params);\n }\n /**\n * @method 模块click\n */\n frModuleClick(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"module_click\", params);\n }\n /**\n * @method 登录事件\n */\n frLoginEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"login_event\", params);\n }\n /**\n * @method 生单事件\n */\n frOrderEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"order_event\", params);\n }\n /**\n * @method 自定义事件\n */\n frCustomEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"custom_event\", params);\n }\n /**\n * @method 日志事件\n */\n frLogEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"log_event\", params);\n }\n /**\n * @method 点击事件\n */\n frClickEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"click_event\", params);\n }\n /**\n * @method 自动收集pv事件\n */\n frAutoPageView() {\n window.history.pushState = overrideHistoryMethods(\"pushState\");\n window.history.replaceState = overrideHistoryMethods(\"replaceState\");\n this.nativePv();\n }\n /**\n * @method pv事件\n */\n frPageView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"page_view\", params);\n }\n /**\n * @method uv事件\n */\n frUserView() {\n this.lastUvReportTime = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n const interval = 60 * 60 * 1e3;\n const params = {\n event_name: \"user_view\"\n };\n this.singleTrack(\"user_view\", params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n if (now > this.lastUvReportTime + 24 * interval) {\n this.lastUvReportTime = now;\n this.singleTrack(\"user_view\", params);\n }\n }, interval);\n }\n /**\n * @method 页面销毁事件\n */\n frPageDestroy(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"page_destroy\", params);\n }\n /**\n * @method 手动立即上报缓存的数据\n */\n frReport() {\n this.reportCacheData();\n }\n init() {\n this.browserInfo = getBrowserAndDeviceInfo(this.instanceConfig.adapter);\n if (this.instanceConfig.adapter === \"web\" && window) {\n this.onBrowserClose();\n this.frUserView();\n if (this.pluginOptions.autoPv) {\n this.frAutoPageView();\n }\n }\n this.reportPrevData();\n this.loopReport();\n }\n};\nvar trackClass_default = FrTrack;\n\n// src/plugin/track/index.ts\nvar trackPlugin = {\n name: \"track\",\n defaultEnable: true,\n install: (sdkInstance, pluginOptions) => {\n try {\n if (!sdkInstance?.$cache || !sdkInstance?.$report) return;\n const defaultOptions = {\n frameType: \"js\",\n router: void 0,\n autoPv: true\n };\n if (pluginOptions) {\n Object.assign(defaultOptions, pluginOptions);\n }\n if (sdkInstance.$track) return;\n const frTrack = new trackClass_default(sdkInstance, defaultOptions);\n sdkInstance.$track = frTrack;\n frTrack.init();\n } catch (err) {\n logError(err, \"trackPlugin\\u521D\\u59CB\\u5316\\u5931\\u8D25\");\n }\n }\n};\n\n// src/index.ts\nvar instance = null;\nvar FrWebSDK = class {\n constructor() {\n this.isInit = false;\n this.config = defaultConfig;\n this.adapter = null;\n }\n init(userConfig) {\n if (this.isInit) {\n logWarn(\"SDK\\u5DF2\\u521D\\u59CB\\u5316\");\n return this;\n }\n this.config = { ...defaultConfig, ...userConfig };\n this.adapter = getAdapter(this.config.adapter);\n coreInit({\n config: this.config,\n adapter: this.adapter,\n instance: this\n });\n if (this.config.plugins) {\n this.config.plugins.forEach((plugin) => {\n if (plugin.type === \"track\") {\n trackPlugin.install(this, plugin.options);\n }\n });\n }\n this.isInit = true;\n return this;\n }\n};\nfunction getInstance() {\n if (!instance) {\n instance = new FrWebSDK();\n }\n return instance;\n}\nvar webSdk = getInstance();\nvar index_default = webSdk;\n","// src/index.js\nimport { defaultConfig } from './config';\nimport { getAdapter } from './adapter/index';\nimport { coreInit } from './core/index.js';\nimport { logWarn } from './utils/utils';\nimport { Cache, Report } from './core';\nimport { trackPlugin } from './plugin/track';\nimport FrTrack from './plugin/track/trackClass';\nimport type { Options, CustomOptions } from './types';\n\nlet instance: InstanceType<typeof FrWebSDK> | null = null;\n\nclass FrWebSDK {\n private adapter: any;\n public isInit: boolean;\n public config: Options;\n public $cache!: InstanceType<typeof Cache>;\n public $report!: InstanceType<typeof Report>;\n public $track!: InstanceType<typeof FrTrack>;\n\n constructor() {\n this.isInit = false;\n this.config = defaultConfig;\n this.adapter = null;\n }\n\n init(userConfig: CustomOptions) {\n if (this.isInit) {\n logWarn('SDK已初始化');\n return this;\n }\n // 合并配置\n this.config = { ...defaultConfig, ...userConfig };\n // 获取适配器\n this.adapter = getAdapter(this.config.adapter);\n // 核心初始化\n coreInit({\n config: this.config,\n adapter: this.adapter,\n instance: this\n });\n // 获取用户插件\n if (this.config.plugins) {\n this.config.plugins.forEach(plugin => {\n if (plugin.type === 'track') {\n trackPlugin.install(this, plugin.options);\n }\n });\n }\n\n this.isInit = true;\n\n return this;\n }\n}\n\n// 获取单例\nfunction getInstance() {\n if (!instance) {\n instance = new FrWebSDK();\n }\n return instance;\n}\n\ntype TrackInstance = InstanceType<typeof FrWebSDK>;\n\nconst webSdk = getInstance();\nexport default webSdk;\nexport type { TrackInstance };\n","import type { Options } from '../types';\n\nconst MAX_CACHE_SIZE = 15;\nconst MAX_CACHE_TIME = 300000;\nconst MAX_TIMEOUT = 10000;\n\nconst defaultConfig: Options = {\n project_name: '',\n report_url: '',\n app_version: '',\n adapter: 'web',\n maxCacheSize: MAX_CACHE_SIZE,\n maxCacheTime: MAX_CACHE_TIME,\n maxTimeout: MAX_TIMEOUT,\n isDebug: false,\n plugins: [\n {\n type: 'track',\n options: {\n autoPv: true\n // frameType: 'js',\n // router: null\n }\n }\n ]\n};\n\nexport { defaultConfig };\n","import * as localForage from 'localforage';\nimport { Cache } from '../../core';\nimport type { CacheName } from '../../core/types';\n\nclass WebCache extends Cache {\n constructor(options?: Record<string, unknown>) {\n super(options);\n }\n\n public async get<T>(name: CacheName) {\n const res = await localForage.getItem<T[]>(name);\n return res || [];\n }\n\n public async set<T>(name: CacheName, data: T | T[]): Promise<void> {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n await localForage.setItem(name, currentData);\n } else {\n await localForage.setItem(name, cacheData);\n }\n }\n\n public async remove(name: CacheName) {\n await localForage.removeItem(name);\n }\n\n public async clear(): Promise<void> {\n await localForage.clear();\n }\n}\n\nexport default WebCache;\n","import type { CacheName } from './types';\n\nexport abstract class Cache {\n protected options;\n constructor(options?: Record<string, unknown>) {\n if (options) {\n this.options = options;\n }\n }\n public abstract get<T>(name: CacheName): Promise<T[]> | T[];\n public abstract set<T>(name: CacheName, data: T | T[]): Promise<void> | void;\n public abstract remove(name: CacheName): void | Promise<void>;\n public abstract clear(): void | Promise<void>;\n}\n\n// 导出初始化方法(适配具体实现)\nexport function initCache<T extends Cache>(\n CacheClass: new (options: unknown) => T,\n options?: { [key: string]: unknown }\n): T {\n return new CacheClass(options);\n}\n\ntype CacheType = InstanceType<typeof Cache>;\n\nexport type { CacheType };\n","import type { ReportReq } from './types';\n\nexport abstract class Report {\n protected options;\n constructor(options: ReportReq) {\n this.options = options;\n }\n public abstract send<T>(data: T[]): Promise<unknown>;\n public abstract retry<T>(failedData: T[], callback?: () => void): void;\n}\n\n// 导出初始化方法(适配具体实现)\nexport function initReport<T extends Report>(\n ReportClass: new (options: unknown) => T,\n options: ReportReq\n): T {\n if (!options.url) {\n throw new Error('请传入上报地址url');\n }\n return new ReportClass(options);\n}\n\ntype ReportType = InstanceType<typeof Report>;\n\nexport type { ReportType };\n","import { initCache } from './cache';\nimport { initReport } from './report';\nconst coreInit = ({ config, adapter, instance }: any) => {\n // 初始化缓存\n instance.$cache = initCache(adapter.cache);\n // 初始化上报\n instance.$report = initReport(adapter.report, {\n url: config.report_url,\n timeout: config.maxTimeout\n });\n};\n\nexport { coreInit };\n","const EVENT_TYPES = [\n 'page_view',\n 'user_view',\n 'page_destroy',\n 'click_event',\n 'module_click',\n 'module_view',\n 'login_event',\n 'order_event',\n 'custom_event',\n 'log_event'\n] as const;\n\nconst CAN_AGGREGATION_TYPES = ['page_view', 'user_view'] as const;\n\nconst EVENT_KEYS = [\n 'project_name',\n 'event_type',\n 'event_name',\n 'event_time',\n 'user_id',\n 'app_version',\n 'user_timezone',\n 'device_type',\n 'user_agent',\n 'screen_resolution',\n 'custom_data',\n 'is_aggregation'\n] as const;\n\nconst CACHE_DATA_NAME = 'fr-track-cache-data';\nconst CACHE_ERR_DATA_NAME = 'fr-track-cache-err-data';\n\nexport { EVENT_TYPES, EVENT_KEYS, CAN_AGGREGATION_TYPES, CACHE_DATA_NAME, CACHE_ERR_DATA_NAME };\n","/**\n * 公共打印日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n * @param { boolean } isDebug 是否调试模式\n */\nconst logInfo = (message: unknown, title?: string, isDebug = false): void => {\n if (!isDebug) return;\n const logTitle = title ? `[Fr-track log ${title}]` : '[Fr-track log]';\n console.log(`${logTitle}:`, message);\n};\n\n/**\n * 公共打印警告日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n */\nconst logWarn = (message: unknown, title?: string): void => {\n const logTitle = title ? `[Fr-track warning ${title}]` : '[Fr-track warning]';\n console.warn(`${logTitle}:`, message);\n};\n\n/**\n * 公共打印异常日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n */\nconst logError = (message: unknown, title?: string): void => {\n const logTitle = title ? `[Fr-track error ${title}]` : '[Fr-track error]';\n console.error(`${logTitle}:`, message);\n};\n\n/**\n * 获取变量类型\n * @param { unknown } variable 变量\n * @return { string } 类型字符串\n */\nconst getVariableType = (variable: unknown): string => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\n\n/**\n * 手动实现 UUID v4\n * @returns { string } uuid\n */\nconst generateFallbackUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * 生成uuid\n * @returns { string } uuid\n */\nconst generateUserId = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // 降级方案\n return generateFallbackUUID();\n};\n\n/**\n * 重写history的pushState和replaceState\n */\nconst overrideHistoryMethods = <T extends keyof History>(type: T): any => {\n const originalMethod = history[type];\n return function (this: any, ...args: any) {\n const res = originalMethod.apply(this, args);\n const e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\n\n/**\n * 获取用户时区\n */\nconst getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n logWarn(error, '无法获取时区名称,使用偏移量推算:');\n const offset = new Date().getTimezoneOffset();\n if (offset >= 0) {\n return `西${offset / 60}区`;\n } else {\n return `东${-offset / 60}区`;\n }\n }\n};\n\n/**\n * 触发事件后,延迟指定时间再执行函数;若延迟内再次触发,重新计时\n * @param fn 要防抖的目标函数(支持任意参数、任意返回值,保留this指向)\n * @param delay 防抖延迟时间,默认800毫秒\n * @param immediate 是否立即执行(true:首次触发立即执行,后续延迟内触发重新计时;false:延迟后执行)\n * @returns 包装后的防抖函数(与原函数参数一致,无返回值)\n */\nexport function debounce<F extends (...args: any[]) => any>(\n fn: F,\n delay: number = 800,\n immediate: boolean = false\n): (...args: Parameters<F>) => void {\n let timer: number | null = null;\n let flag = false;\n\n return function (this: ThisParameterType<F>, ...args: Parameters<F>) {\n if (immediate && !flag) {\n fn.apply(this, args);\n }\n\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n\n flag = true;\n timer = setTimeout(() => {\n fn.apply(this, args);\n flag = false;\n }, delay);\n };\n}\n\n/**\n * 递归处理自定义数据,对字符串进行HTML标签过滤,对对象递归处理\n * @param data 自定义数据对象\n * @returns 处理后的自定义数据对象\n */\nconst sanitizeCustomData = (data: Record<string, unknown>) => {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === 'string') {\n sanitized[key] = value.replace(/<[^>]*>/g, '');\n } else if (getVariableType(value) === 'object') {\n sanitized[key] = sanitizeCustomData(value as Record<string, unknown>);\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n};\n\nexport {\n logInfo,\n logWarn,\n logError,\n getVariableType,\n generateUserId,\n overrideHistoryMethods,\n getUserTimeZone,\n sanitizeCustomData\n};\n","import { EVENT_TYPES, EVENT_KEYS } from '../static/constant';\nimport { getVariableType, logWarn } from './utils';\nimport type { EventsType } from '../types';\n\n/**\n * @method 校验事件类型\n */\nexport function validateEventType(eventType?: unknown): boolean {\n return typeof eventType === 'string' && EVENT_TYPES.includes(eventType as EventsType);\n}\n\n/**\n * @method 校验字段\n */\nexport function validateEventKey(params?: unknown): boolean {\n const type = getVariableType(params);\n if (!params || type !== 'object') {\n logWarn('Event params must be an object');\n return false;\n }\n const keys = Object.keys(params as Record<string, unknown>);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key as (typeof EVENT_KEYS)[number])) {\n logWarn(`Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n","import { validateEventType, validateEventKey } from '../utils/validator';\nimport { logWarn, logError } from '../utils/utils';\n// TODO: 解耦\nimport type { TrackEventItem } from '../plugin/track/types';\n\n/**\n * 清洗上报数据\n * @param { array } rawData 待清洗的原数据\n * @returns { array } 清洗后的数据\n */\nconst cleanTrackData = (\n rawData: TrackEventItem[]\n): {\n type: 'success' | 'fail';\n errReason?: string;\n data: TrackEventItem[];\n} => {\n try {\n // 过滤非法的事件类型、非法的时间日期\n const tempIds = new Set();\n const resultData = rawData.filter(rawItem => {\n // 缺失必要字段\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n\n // event_type校验不通过\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n logWarn('事件类型不合法');\n return false;\n }\n\n // event_time校验不通过\n const eventTime = rawItem.event_time;\n const minDateTime = new Date('2025-12-01').getTime();\n if (!eventTime || typeof eventTime !== 'number' || eventTime < minDateTime) {\n return false;\n }\n\n // 相同时间戳相同事件已存在\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: 'success',\n data: resultData\n };\n } catch (error) {\n logError(error, '清洗失败');\n const errReason = (error as Error).message || 'Unknown error';\n return {\n type: 'fail',\n errReason: errReason,\n data: rawData\n };\n }\n};\n\nexport { cleanTrackData };\n","import { CAN_AGGREGATION_TYPES } from '../static/constant';\nimport { logError } from '../utils/utils';\n// TODO: 解耦\nimport type { TrackEventItem } from '../plugin/track/types';\n\n/**\n * 聚合数据\n * @param { array } rawData 需要聚合的原数据\n * @returns { array } 聚合后的数据\n */\nconst aggregationData = (rawData: TrackEventItem[]): TrackEventItem[] => {\n try {\n const resultData: TrackEventItem[] = [];\n for (let i = 0; i < rawData.length; i++) {\n const rawItem = rawData[i];\n if (!rawItem) continue;\n const item = { ...rawItem };\n /**\n * 以\"天\"为维度,将以下事件进行聚合\n * pv、uv、自定义指定需要聚合的数据\n */\n if (\n CAN_AGGREGATION_TYPES.includes(item.event_type as (typeof CAN_AGGREGATION_TYPES)[number]) ||\n item.is_aggregation\n ) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time as number).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n r =>\n r.event_time === currentDate &&\n r.event_type === item.event_type &&\n r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n // 如果是uv,后面的userId覆盖之前\n if (item.event_type === 'user_view') {\n resultItem.user_id = item.user_id;\n }\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n logError(error, '聚合失败');\n // 聚合失败则直接上报原数据\n return rawData;\n }\n};\n\nexport { aggregationData };\n","import { Report } from '../../core';\nimport type { ReportReq } from '../../core/types';\n\nclass WebReport extends Report {\n constructor(options: ReportReq) {\n super(options);\n }\n\n public async retry<T>(failedData: T[], callback?: () => void, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3000);\n }\n }\n\n public async send<T>(data: T[]) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if ('sendBeacon' in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append('data', jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', url, true);\n xhr.timeout = timeout;\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = () => {\n resolve(xhr.response);\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n }\n}\n\nexport default WebReport;\n","import { Cache } from '../../core';\nimport type { CacheName } from '../../core/types';\n\nclass WxCache extends Cache {\n constructor(options?: Record<string, unknown>) {\n super(options);\n }\n\n public async get(name: CacheName) {\n const res = wx.getStorageSync(name);\n return res || [];\n }\n\n public async set<T>(name: CacheName, data: T | T[]): Promise<void> {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n wx.setStorageSync(name, currentData);\n } else {\n wx.setStorageSync(name, cacheData);\n }\n }\n\n public async remove(name: CacheName) {\n wx.removeStorageSync(name);\n }\n\n public async clear(): Promise<void> {\n wx.clearStorageSync();\n }\n}\n\nexport default WxCache;\n","import { Report } from '../../core';\nimport type { ReportReq } from '../../core/types';\n\nclass WxReport extends Report {\n constructor(options: ReportReq) {\n super(options);\n }\n\n public async retry<T>(failedData: T[], callback?: () => void, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3000);\n }\n }\n\n public async send<T>(data: T[]) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (wx && wx.request) {\n wx.request({\n url,\n method: 'POST',\n data: data,\n timeout,\n success: function success(res: any) {\n resolve(res);\n },\n fail: function fail(err: any) {\n reject(err);\n }\n });\n } else {\n reject();\n }\n });\n }\n}\n\nexport default WxReport;\n","import WebCache from './web/cache';\nimport WebReport from './web/report';\nimport WxCache from './wx/cache';\nimport WxReport from './wx/report';\n\n/**\n * 获取运行环境\n */\nconst getEnv = () => {\n const isMiniProgram = wx && typeof wx.getSystemInfoSync === 'function';\n return isMiniProgram ? 'miniProgram' : 'web';\n};\n\n/**\n * 获取对应环境的配置w\n */\nconst getAdapter = (configEnv: string) => {\n const env = configEnv || getEnv();\n if (env === 'miniProgram') {\n return {\n env: 'miniProgram',\n cache: WxCache,\n report: WxReport\n };\n }\n return {\n env: 'web',\n cache: WebCache,\n report: WebReport\n };\n};\n\nexport { getAdapter };\n","import { generateUserId } from '../utils/utils';\n\n/**\n * 获取user_id\n */\nconst getUserId = (): string => {\n try {\n // 查看缓存是否有已生成的uuid\n const track_uuid = localStorage.getItem('track_uuid');\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem('track_uuid', uuid);\n return uuid;\n } catch (e) {\n return generateUserId();\n }\n};\n\nexport { getUserId };\n","import Browser from 'bowser';\nimport { logWarn } from './utils';\nimport type { BrowserInfoType, AdapterType } from '../types';\n\n/**\n * 获取浏览器及设备信息\n * @returns { object | null }\n */\nconst getBrowserAndDeviceInfo = (adapter: AdapterType): BrowserInfoType => {\n const defRes = {\n browserName: 'unknown',\n browserVersion: 'unknown',\n osName: 'unknown',\n osVersion: 'unknown',\n platformName: 'unknown'\n };\n try {\n if (adapter === 'web') {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || 'unknown',\n browserVersion: browser.version || 'unknown',\n osName: os.name || 'unknown',\n osVersion: os.version || 'unknown',\n platformName: platform.type || 'unknown'\n };\n } else {\n if (!wx) return defRes;\n const info = wx.getDeviceInfo();\n const { brand, model, platform, system } = info;\n return {\n browserName: brand || 'miniProgram',\n browserVersion: model || 'unknown',\n osName: system || 'unknown',\n osVersion: system || 'unknown',\n platformName: platform || 'unknown'\n };\n }\n } catch (error) {\n logWarn(error);\n return defRes;\n }\n};\n\n/**\n * 获取设备分辨率\n * @return { string } 分辨率信息\n */\nconst getDeviceResolution = (adapter: AdapterType): string => {\n if (adapter === 'web') {\n if (!window) return 'unknown';\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n } else {\n if (!wx) return 'unknown';\n const screen = wx.getWindowInfo();\n return `${screen.screenWidth}x${screen.screenHeight}`;\n }\n};\n\nexport { getBrowserAndDeviceInfo, getDeviceResolution };\n","import { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from '../../static/constant';\nimport { getUserId } from '../../utils/uuid';\nimport { cleanTrackData, aggregationData } from '../../core';\nimport { getBrowserAndDeviceInfo, getDeviceResolution } from '../../utils/browser';\nimport {\n overrideHistoryMethods,\n getUserTimeZone,\n logInfo,\n logWarn,\n logError,\n sanitizeCustomData,\n debounce\n} from '../../utils/utils';\n\nimport type { BrowserInfoType, TrackInstance, TrackPluginOptions } from '../types';\nimport type { TrackEventItem, TrackParams, CustomData, EventsType, TrackTask } from './types';\nimport type { Cache } from '../../core/cache';\nimport type { Report } from '../../core/report';\nimport type { Options } from '../../types';\n\nclass FrTrack<T = TrackEventItem> {\n private userId = getUserId();\n private timer: number | null = null;\n private uvTimer: number | null = null;\n private lastUvReportTime: number = 0;\n private browserInfo: BrowserInfoType | null = null;\n private pluginOptions: TrackPluginOptions;\n private taskQueue: TrackTask[] = [];\n private isProcessing = false;\n private cacheFn: Cache;\n private reportFn: Report;\n private instanceConfig: Options;\n private debouncePv: (key: string) => void;\n\n constructor(instance: TrackInstance, pluginOptions: TrackPluginOptions) {\n if (!instance) {\n throw new Error('请传入SDk实例');\n }\n this.cacheFn = instance.$cache;\n this.reportFn = instance.$report;\n this.instanceConfig = instance.config;\n this.pluginOptions = pluginOptions;\n this.debouncePv = debounce((type: string) => {\n // 初次加载手动执行\n const href = window.location.href || '';\n logInfo(type, '事件触发', this.instanceConfig.isDebug);\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: 'unknown',\n count: 1\n }\n };\n this.singleTrack('page_view', params);\n }, 300);\n }\n\n /* 执行异步队列任务 */\n private async processQueue() {\n // 如果正在执行任务,或队列为空 直接返回\n if (this.isProcessing || this.taskQueue.length === 0) return;\n // 开始执行\n this.isProcessing = true;\n // 取出队列第一个任务\n const currentTask = this.taskQueue.shift()!;\n try {\n await currentTask.fn();\n logInfo(`✅ 任务执行成功:${currentTask.desc}`, '', this.instanceConfig.isDebug);\n } catch (err) {\n logInfo(err, `❌ 任务执行失败:${currentTask.desc}`, this.instanceConfig.isDebug);\n } finally {\n this.isProcessing = false;\n this.processQueue();\n }\n }\n\n /* 异步队列添加任务 */\n private addTask<T>(task: TrackTask<T>) {\n const taskWithDesc = {\n desc: `${task.type} 任务`,\n ...task\n };\n this.taskQueue.push(taskWithDesc);\n // 添加后启动任务\n this.processQueue();\n }\n\n /* 上报缓存数据 */\n private async reportCacheData() {\n this.addTask({\n type: 'report_send',\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (!cacheData?.length) return;\n // 清洗\n const cleanInfo = cleanTrackData(cacheData as TrackEventItem[]);\n if (cleanInfo.type !== 'success') {\n logWarn(cleanInfo.errReason);\n // TODO: 上报失败原因及数据 清空缓存\n } else {\n // 聚合\n const result = aggregationData(cleanInfo.data);\n logInfo(result, '上报数据', this.instanceConfig.isDebug);\n if (result?.length) {\n this.reportFn.send<T>(result as T[]).catch(err => {\n logError(err, '上报失败数据异常');\n this.cacheFn.set(CACHE_ERR_DATA_NAME, result);\n });\n }\n }\n // 不管上报是否成功,删除缓存\n await this.cacheFn.remove(CACHE_DATA_NAME);\n }\n });\n }\n\n /* 上报缓存的失败数据 */\n private async reportErrCacheData() {\n this.addTask({\n type: 'report_send',\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get<T>(CACHE_ERR_DATA_NAME);\n if (!cacheData?.length) return;\n this.reportFn.send<T>(cacheData).catch(err => {\n logError(err, '上报失败数据异常');\n });\n await this.cacheFn.remove(CACHE_ERR_DATA_NAME);\n }\n });\n }\n\n private reportPrevData = () => {\n this.reportErrCacheData();\n };\n\n /* 定时循环上报 */\n private loopReport() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.timer = setInterval(() => {\n this.reportCacheData();\n }, this.instanceConfig.maxCacheTime);\n }\n\n /* 浏览器关闭时触发 */\n private onBrowserClose() {\n /**\n * 浏览器环境\n */\n window.addEventListener('beforeunload', () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.reportCacheData();\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState !== 'visible') {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.reportCacheData();\n } else {\n // 重启定时器\n this.loopReport();\n }\n });\n }\n\n private nativePv() {\n const methodsList = ['popstate', 'hashchange', 'pushState', 'replaceState'];\n // 初始化上报一次\n this.debouncePv('初次上报');\n methodsList.forEach(method => {\n window.addEventListener(method, () => {\n this.debouncePv(method);\n });\n });\n }\n\n // private vuePv() {\n // if (!this.pluginOptions.router) {\n // throw new Error('请传入路由实例');\n // }\n // const router = this.pluginOptions.router as any;\n // router.afterEach((to: any) => {\n // const params = {\n // event_name: to.path,\n // custom_data: {\n // page_url: to.fullPath || '--',\n // page_name: to.name || '--',\n // count: 1\n // }\n // };\n // this.singleTrack('page_view', params);\n // });\n // }\n\n private async toSetCacheData(params: T) {\n logInfo(params, '设置缓存数据', this.instanceConfig.isDebug);\n this.addTask({\n type: 'cache_set',\n fn: async () => {\n if (!this.cacheFn) return;\n const { maxCacheSize } = this.instanceConfig;\n const res = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (res?.length >= maxCacheSize) {\n this.reportCacheData();\n // 上报成功后, 再设置缓存\n this.toSetCacheData(params);\n } else {\n await this.cacheFn.set<T>(CACHE_DATA_NAME, params);\n }\n }\n });\n }\n\n private async track(params: TrackParams) {\n const { project_name, app_version } = this.instanceConfig;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo!;\n if (params.custom_data) {\n params.custom_data = sanitizeCustomData(params.custom_data);\n }\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(this.instanceConfig.adapter),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n this.toSetCacheData(trackParams);\n }\n\n private singleTrack<T extends Omit<TrackParams, 'event_type'>>(\n eventType: EventsType,\n params: T & (keyof T extends keyof Omit<TrackParams, 'event_type'> ? T : never)\n ) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n\n /**\n * @method 自定义用户id\n */\n public setUser(id: string) {\n this.userId = id;\n // 更新userId\n this.addTask({\n type: 'cache_update',\n fn: async () => {\n const cacheData = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (cacheData?.length) {\n const updatedData = cacheData.map(item => ({\n ...item,\n user_id: id\n }));\n await this.cacheFn.set(CACHE_DATA_NAME, updatedData);\n }\n }\n });\n }\n\n /**\n * @method 模块view\n */\n public frModuleView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('module_view', params);\n }\n\n /**\n * @method 模块click\n */\n public frModuleClick(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('module_click', params);\n }\n\n /**\n * @method 登录事件\n */\n public frLoginEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('login_event', params);\n }\n\n /**\n * @method 生单事件\n */\n public frOrderEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('order_event', params);\n }\n\n /**\n * @method 自定义事件\n */\n public frCustomEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('custom_event', params);\n }\n\n /**\n * @method 日志事件\n */\n public frLogEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('log_event', params);\n }\n\n /**\n * @method 点击事件\n */\n public frClickEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('click_event', params);\n }\n\n /**\n * @method 自动收集pv事件\n */\n private frAutoPageView() {\n // if (this.pluginOptions.frameType === 'js') {\n window.history.pushState = overrideHistoryMethods('pushState');\n window.history.replaceState = overrideHistoryMethods('replaceState');\n this.nativePv();\n // } else if (this.pluginOptions.frameType === 'vue') {\n // this.vuePv()\n // }\n }\n\n /**\n * @method pv事件\n */\n public frPageView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('page_view', params);\n }\n\n /**\n * @method uv事件\n */\n public frUserView() {\n this.lastUvReportTime = new Date().setHours(0, 0, 0, 0);\n // 一小时检查一次\n const interval = 60 * 60 * 1000;\n const params = {\n event_name: 'user_view'\n };\n this.singleTrack('user_view', params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = new Date().setHours(0, 0, 0, 0);\n if (now > this.lastUvReportTime + 24 * interval) {\n // 超过24小时,再次上报uv\n // 更新上报时间\n this.lastUvReportTime = now;\n this.singleTrack('user_view', params);\n }\n }, interval);\n }\n\n /**\n * @method 页面销毁事件\n */\n public frPageDestroy(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('page_destroy', params);\n }\n\n /**\n * @method 手动立即上报缓存的数据\n */\n public frReport() {\n this.reportCacheData();\n }\n\n public init() {\n /**\n * 获取浏览器信息\n */\n this.browserInfo = getBrowserAndDeviceInfo(this.instanceConfig.adapter);\n /**\n * 浏览器环境下\n */\n if (this.instanceConfig.adapter === 'web' && window) {\n /**\n * 监听浏览器关闭事件,进行上报\n */\n this.onBrowserClose();\n\n /**\n * 统计uv\n */\n this.frUserView();\n\n /**\n * 判断是否监听pv事件\n */\n if (this.pluginOptions.autoPv) {\n this.frAutoPageView();\n }\n }\n\n /**\n * 1. 判断缓存是否有没有传输的数据\n * 2. 判断上次是否有失败的数据存储在缓存中\n */\n this.reportPrevData();\n /**\n * 3. 开启定时器轮询,达到时间阈值进行上报\n */\n this.loopReport();\n }\n}\n\nexport default FrTrack;\n","import FrTrack from './trackClass';\n\nimport type { BasePlugin, TrackPluginOptions } from '../types';\nimport { logError } from '../../utils/utils';\n\nconst trackPlugin: BasePlugin<TrackPluginOptions> = {\n name: 'track',\n defaultEnable: true,\n install: (sdkInstance, pluginOptions) => {\n try {\n if (!sdkInstance?.$cache || !sdkInstance?.$report) return;\n const defaultOptions: TrackPluginOptions = {\n frameType: 'js',\n router: undefined,\n autoPv: true\n };\n if (pluginOptions) {\n Object.assign(defaultOptions, pluginOptions);\n }\n\n if (sdkInstance.$track) return;\n const frTrack = new FrTrack(sdkInstance, defaultOptions);\n sdkInstance.$track = frTrack;\n frTrack.init();\n } catch (err) {\n logError(err, 'trackPlugin初始化失败');\n }\n }\n};\n\nexport { trackPlugin };\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1137,7 +1137,7 @@ var getUserId = function() {
|
|
|
1137
1137
|
};
|
|
1138
1138
|
// src/utils/browser.ts
|
|
1139
1139
|
import Browser from "bowser";
|
|
1140
|
-
var getBrowserAndDeviceInfo = function() {
|
|
1140
|
+
var getBrowserAndDeviceInfo = function(adapter) {
|
|
1141
1141
|
var defRes = {
|
|
1142
1142
|
browserName: "unknown",
|
|
1143
1143
|
browserVersion: "unknown",
|
|
@@ -1146,26 +1146,45 @@ var getBrowserAndDeviceInfo = function() {
|
|
|
1146
1146
|
platformName: "unknown"
|
|
1147
1147
|
};
|
|
1148
1148
|
try {
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1149
|
+
if (adapter === "web") {
|
|
1150
|
+
var ua = window.navigator.userAgent;
|
|
1151
|
+
if (!ua) return defRes;
|
|
1152
|
+
var info = Browser.parse(ua);
|
|
1153
|
+
var browser = info.browser, os = info.os, platform = info.platform;
|
|
1154
|
+
return {
|
|
1155
|
+
browserName: browser.name || "unknown",
|
|
1156
|
+
browserVersion: browser.version || "unknown",
|
|
1157
|
+
osName: os.name || "unknown",
|
|
1158
|
+
osVersion: os.version || "unknown",
|
|
1159
|
+
platformName: platform.type || "unknown"
|
|
1160
|
+
};
|
|
1161
|
+
} else {
|
|
1162
|
+
if (!wx) return defRes;
|
|
1163
|
+
var info1 = wx.getDeviceInfo();
|
|
1164
|
+
var brand = info1.brand, model = info1.model, platform1 = info1.platform, system = info1.system;
|
|
1165
|
+
return {
|
|
1166
|
+
browserName: brand || "miniProgram",
|
|
1167
|
+
browserVersion: model || "unknown",
|
|
1168
|
+
osName: system || "unknown",
|
|
1169
|
+
osVersion: system || "unknown",
|
|
1170
|
+
platformName: platform1 || "unknown"
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1160
1173
|
} catch (error) {
|
|
1161
1174
|
logWarn(error);
|
|
1162
1175
|
return defRes;
|
|
1163
1176
|
}
|
|
1164
1177
|
};
|
|
1165
|
-
var getDeviceResolution = function() {
|
|
1166
|
-
if (
|
|
1167
|
-
|
|
1168
|
-
|
|
1178
|
+
var getDeviceResolution = function(adapter) {
|
|
1179
|
+
if (adapter === "web") {
|
|
1180
|
+
if (!window) return "unknown";
|
|
1181
|
+
var screen = window.screen;
|
|
1182
|
+
return "".concat(screen.width, "x").concat(screen.height);
|
|
1183
|
+
} else {
|
|
1184
|
+
if (!wx) return "unknown";
|
|
1185
|
+
var screen1 = wx.getWindowInfo();
|
|
1186
|
+
return "".concat(screen1.screenWidth, "x").concat(screen1.screenHeight);
|
|
1187
|
+
}
|
|
1169
1188
|
};
|
|
1170
1189
|
// src/plugin/track/trackClass.ts
|
|
1171
1190
|
var FrTrack = /*#__PURE__*/ function() {
|
|
@@ -1535,7 +1554,7 @@ var FrTrack = /*#__PURE__*/ function() {
|
|
|
1535
1554
|
user_id: this.userId,
|
|
1536
1555
|
device_type: platformName,
|
|
1537
1556
|
user_agent: "os: ".concat(osName, "--v").concat(osVersion, ", browser: ").concat(browserName, "--v").concat(browserVersion),
|
|
1538
|
-
screen_resolution: getDeviceResolution(),
|
|
1557
|
+
screen_resolution: getDeviceResolution(this.instanceConfig.adapter),
|
|
1539
1558
|
user_timezone: getUserTimeZone(),
|
|
1540
1559
|
event_time: Date.now(),
|
|
1541
1560
|
custom_data: null
|
|
@@ -1774,8 +1793,8 @@ var FrTrack = /*#__PURE__*/ function() {
|
|
|
1774
1793
|
{
|
|
1775
1794
|
key: "init",
|
|
1776
1795
|
value: function init() {
|
|
1796
|
+
this.browserInfo = getBrowserAndDeviceInfo(this.instanceConfig.adapter);
|
|
1777
1797
|
if (this.instanceConfig.adapter === "web" && window) {
|
|
1778
|
-
this.browserInfo = getBrowserAndDeviceInfo();
|
|
1779
1798
|
this.onBrowserClose();
|
|
1780
1799
|
this.frUserView();
|
|
1781
1800
|
if (this.pluginOptions.autoPv) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/hl/Desktop/project/track-sdk/dist/index.js","../src/config/index.ts","../src/adapter/web/cache.ts","../src/core/cache.ts","../src/core/report.ts","../src/core/init.ts","../src/static/constant.ts","../src/utils/utils.ts","../src/utils/validator.ts","../src/core/clean.ts","../src/core/aggregation.ts","../src/adapter/web/report.ts","../src/adapter/wx/cache.ts","../src/adapter/wx/report.ts","../src/adapter/index.ts","../src/utils/uuid.ts","../src/utils/browser.ts","../src/plugin/track/trackClass.ts","../src/plugin/track/index.ts","../src/index.ts"],"names":["MAX_CACHE_SIZE","MAX_CACHE_TIME","MAX_TIMEOUT","defaultConfig","project_name","report_url","app_version","adapter","maxCacheSize","maxCacheTime","maxTimeout","isDebug","plugins","type","options","autoPv","localForage","Cache","initCache","CacheClass","Report","initReport","ReportClass","url","Error","coreInit","config","instance","$cache","cache","$report","report","timeout","EVENT_TYPES","CAN_AGGREGATION_TYPES","EVENT_KEYS","CACHE_DATA_NAME","CACHE_ERR_DATA_NAME","logInfo","message","title","logTitle","console","log","logWarn","warn","logError","error","getVariableType","variable","typeString","Object","prototype","toString","call","slice","toLowerCase","generateFallbackUUID","replace","c","r","Math","random","v","generateUserId","crypto","randomUUID","overrideHistoryMethods","originalMethod","history","args","res","apply","e","Event","window","dispatchEvent","getUserTimeZone","Intl","DateTimeFormat","resolvedOptions","timeZone","offset","Date","getTimezoneOffset","debounce","fn","delay","immediate","timer","flag","clearTimeout","setTimeout","sanitizeCustomData","data","sanitized","entries","key","value","validateEventType","eventType","includes","validateEventKey","params","keys","cleanTrackData","rawData","tempIds","Set","resultData","filter","rawItem","eventKeyResult","eventTypeResult","event_type","eventTime","event_time","minDateTime","getTime","id","event_name","has","add","errReason","aggregationData","i","item","is_aggregation","currentDate","setHours","resultItem","find","push","user_id","customData","custom_data","count","length","WebCache","get","name","getItem","set","currentData","cacheData","Array","isArray","setItem","remove","removeItem","clear","cache_default","WebReport","retry","failedData","callback","retryCount","err","send","Promise","resolve","reject","navigator","jsonData","JSON","stringify","formData","FormData","append","status","sendBeacon","xhr","XMLHttpRequest","open","setRequestHeader","onload","response","onerror","report_default","WxCache","wx","getStorageSync","setStorageSync","removeStorageSync","clearStorageSync","WxReport","request","method","success","fail","getEnv","isMiniProgram","getSystemInfoSync","getAdapter","configEnv","env","getUserId","track_uuid","localStorage","uuid","Browser","getBrowserAndDeviceInfo","defRes","browserName","browserVersion","osName","osVersion","platformName","ua","userAgent","info","parse","browser","os","platform","version","getDeviceResolution","screen","width","height","FrTrack","pluginOptions","userId","uvTimer","lastUvReportTime","browserInfo","taskQueue","isProcessing","reportPrevData","reportErrCacheData","cacheFn","reportFn","instanceConfig","debouncePv","href","location","page_url","page_name","singleTrack","processQueue","currentTask","shift","desc","addTask","task","taskWithDesc","reportCacheData","cleanInfo","result","catch","loopReport","clearInterval","setInterval","onBrowserClose","addEventListener","document","visibilityState","nativePv","methodsList","forEach","toSetCacheData","track","trackParams","assign","device_type","user_agent","screen_resolution","user_timezone","now","baseParams","setUser","updatedData","map","frModuleView","frModuleClick","frLoginEvent","frOrderEvent","frCustomEvent","frLogEvent","frClickEvent","frAutoPageView","pushState","replaceState","frPageView","frUserView","interval","frPageDestroy","frReport","init","trackClass_default","trackPlugin","defaultEnable","install","sdkInstance","defaultOptions","frameType","router","$track","frTrack","FrWebSDK","isInit","userConfig","plugin","getInstance","webSdk","index_default","default"],"mappings":"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","sourcesContent":["// src/config/index.ts\nvar MAX_CACHE_SIZE = 15;\nvar MAX_CACHE_TIME = 3e5;\nvar MAX_TIMEOUT = 1e4;\nvar defaultConfig = {\n project_name: \"\",\n report_url: \"\",\n app_version: \"\",\n adapter: \"web\",\n maxCacheSize: MAX_CACHE_SIZE,\n maxCacheTime: MAX_CACHE_TIME,\n maxTimeout: MAX_TIMEOUT,\n isDebug: false,\n plugins: [\n {\n type: \"track\",\n options: {\n autoPv: true\n // frameType: 'js',\n // router: null\n }\n }\n ]\n};\n\n// src/adapter/web/cache.ts\nimport * as localForage from \"localforage\";\n\n// src/core/cache.ts\nvar Cache = class {\n constructor(options) {\n if (options) {\n this.options = options;\n }\n }\n};\nfunction initCache(CacheClass, options) {\n return new CacheClass(options);\n}\n\n// src/core/report.ts\nvar Report = class {\n constructor(options) {\n this.options = options;\n }\n};\nfunction initReport(ReportClass, options) {\n if (!options.url) {\n throw new Error(\"\\u8BF7\\u4F20\\u5165\\u4E0A\\u62A5\\u5730\\u5740url\");\n }\n return new ReportClass(options);\n}\n\n// src/core/init.ts\nvar coreInit = ({ config, adapter, instance: instance2 }) => {\n instance2.$cache = initCache(adapter.cache);\n instance2.$report = initReport(adapter.report, {\n url: config.report_url,\n timeout: config.maxTimeout\n });\n};\n\n// src/static/constant.ts\nvar EVENT_TYPES = [\n \"page_view\",\n \"user_view\",\n \"page_destroy\",\n \"click_event\",\n \"module_click\",\n \"module_view\",\n \"login_event\",\n \"order_event\",\n \"custom_event\",\n \"log_event\"\n];\nvar CAN_AGGREGATION_TYPES = [\"page_view\", \"user_view\"];\nvar EVENT_KEYS = [\n \"project_name\",\n \"event_type\",\n \"event_name\",\n \"event_time\",\n \"user_id\",\n \"app_version\",\n \"user_timezone\",\n \"device_type\",\n \"user_agent\",\n \"screen_resolution\",\n \"custom_data\",\n \"is_aggregation\"\n];\nvar CACHE_DATA_NAME = \"fr-track-cache-data\";\nvar CACHE_ERR_DATA_NAME = \"fr-track-cache-err-data\";\n\n// src/utils/utils.ts\nvar logInfo = (message, title, isDebug = false) => {\n if (!isDebug) return;\n const logTitle = title ? `[Fr-track log ${title}]` : \"[Fr-track log]\";\n console.log(`${logTitle}:`, message);\n};\nvar logWarn = (message, title) => {\n const logTitle = title ? `[Fr-track warning ${title}]` : \"[Fr-track warning]\";\n console.warn(`${logTitle}:`, message);\n};\nvar logError = (message, title) => {\n const logTitle = title ? `[Fr-track error ${title}]` : \"[Fr-track error]\";\n console.error(`${logTitle}:`, message);\n};\nvar getVariableType = (variable) => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\nvar generateFallbackUUID = () => {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n};\nvar generateUserId = () => {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return generateFallbackUUID();\n};\nvar overrideHistoryMethods = (type) => {\n const originalMethod = history[type];\n return function(...args) {\n const res = originalMethod.apply(this, args);\n const e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\nvar getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n logWarn(error, \"\\u65E0\\u6CD5\\u83B7\\u53D6\\u65F6\\u533A\\u540D\\u79F0\\uFF0C\\u4F7F\\u7528\\u504F\\u79FB\\u91CF\\u63A8\\u7B97:\");\n const offset = (/* @__PURE__ */ new Date()).getTimezoneOffset();\n if (offset >= 0) {\n return `\\u897F${offset / 60}\\u533A`;\n } else {\n return `\\u4E1C${-offset / 60}\\u533A`;\n }\n }\n};\nfunction debounce(fn, delay = 800, immediate = false) {\n let timer = null;\n let flag = false;\n return function(...args) {\n if (immediate && !flag) {\n fn.apply(this, args);\n }\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n flag = true;\n timer = setTimeout(() => {\n fn.apply(this, args);\n flag = false;\n }, delay);\n };\n}\nvar sanitizeCustomData = (data) => {\n const sanitized = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\") {\n sanitized[key] = value.replace(/<[^>]*>/g, \"\");\n } else if (getVariableType(value) === \"object\") {\n sanitized[key] = sanitizeCustomData(value);\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n};\n\n// src/utils/validator.ts\nfunction validateEventType(eventType) {\n return typeof eventType === \"string\" && EVENT_TYPES.includes(eventType);\n}\nfunction validateEventKey(params) {\n const type = getVariableType(params);\n if (!params || type !== \"object\") {\n logWarn(\"Event params must be an object\");\n return false;\n }\n const keys = Object.keys(params);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key)) {\n logWarn(`Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n\n// src/core/clean.ts\nvar cleanTrackData = (rawData) => {\n try {\n const tempIds = /* @__PURE__ */ new Set();\n const resultData = rawData.filter((rawItem) => {\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n logWarn(\"\\u4E8B\\u4EF6\\u7C7B\\u578B\\u4E0D\\u5408\\u6CD5\");\n return false;\n }\n const eventTime = rawItem.event_time;\n const minDateTime = (/* @__PURE__ */ new Date(\"2025-12-01\")).getTime();\n if (!eventTime || typeof eventTime !== \"number\" || eventTime < minDateTime) {\n return false;\n }\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: \"success\",\n data: resultData\n };\n } catch (error) {\n logError(error, \"\\u6E05\\u6D17\\u5931\\u8D25\");\n const errReason = error.message || \"Unknown error\";\n return {\n type: \"fail\",\n errReason,\n data: rawData\n };\n }\n};\n\n// src/core/aggregation.ts\nvar aggregationData = (rawData) => {\n try {\n const resultData = [];\n for (let i = 0; i < rawData.length; i++) {\n const rawItem = rawData[i];\n if (!rawItem) continue;\n const item = { ...rawItem };\n if (CAN_AGGREGATION_TYPES.includes(item.event_type) || item.is_aggregation) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n (r) => r.event_time === currentDate && r.event_type === item.event_type && r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n if (item.event_type === \"user_view\") {\n resultItem.user_id = item.user_id;\n }\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n logError(error, \"\\u805A\\u5408\\u5931\\u8D25\");\n return rawData;\n }\n};\n\n// src/adapter/web/cache.ts\nvar WebCache = class extends Cache {\n constructor(options) {\n super(options);\n }\n async get(name) {\n const res = await localForage.getItem(name);\n return res || [];\n }\n async set(name, data) {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n await localForage.setItem(name, currentData);\n } else {\n await localForage.setItem(name, cacheData);\n }\n }\n async remove(name) {\n await localForage.removeItem(name);\n }\n async clear() {\n await localForage.clear();\n }\n};\nvar cache_default = WebCache;\n\n// src/adapter/web/report.ts\nvar WebReport = class extends Report {\n constructor(options) {\n super(options);\n }\n async retry(failedData, callback, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3e3);\n }\n }\n async send(data) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (\"sendBeacon\" in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append(\"data\", jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.timeout = timeout;\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n xhr.onload = () => {\n resolve(xhr.response);\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n }\n};\nvar report_default = WebReport;\n\n// src/adapter/wx/cache.ts\nvar WxCache = class extends Cache {\n constructor(options) {\n super(options);\n }\n async get(name) {\n const res = wx.getStorageSync(name);\n return res || [];\n }\n async set(name, data) {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n wx.setStorageSync(name, currentData);\n } else {\n wx.setStorageSync(name, cacheData);\n }\n }\n async remove(name) {\n wx.removeStorageSync(name);\n }\n async clear() {\n wx.clearStorageSync();\n }\n};\nvar cache_default2 = WxCache;\n\n// src/adapter/wx/report.ts\nvar WxReport = class extends Report {\n constructor(options) {\n super(options);\n }\n async retry(failedData, callback, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3e3);\n }\n }\n async send(data) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (wx && wx.request) {\n wx.request({\n url,\n method: \"POST\",\n data,\n timeout,\n success: function success(res) {\n resolve(res);\n },\n fail: function fail(err) {\n reject(err);\n }\n });\n } else {\n reject();\n }\n });\n }\n};\nvar report_default2 = WxReport;\n\n// src/adapter/index.ts\nvar getEnv = () => {\n const isMiniProgram = wx && typeof wx.getSystemInfoSync === \"function\";\n return isMiniProgram ? \"miniProgram\" : \"web\";\n};\nvar getAdapter = (configEnv) => {\n const env = configEnv || getEnv();\n if (env === \"miniProgram\") {\n return {\n env: \"miniProgram\",\n cache: cache_default2,\n report: report_default2\n };\n }\n return {\n env: \"web\",\n cache: cache_default,\n report: report_default\n };\n};\n\n// src/utils/uuid.ts\nvar getUserId = () => {\n try {\n const track_uuid = localStorage.getItem(\"track_uuid\");\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem(\"track_uuid\", uuid);\n return uuid;\n } catch (e) {\n return generateUserId();\n }\n};\n\n// src/utils/browser.ts\nimport Browser from \"bowser\";\nvar getBrowserAndDeviceInfo = () => {\n const defRes = {\n browserName: \"unknown\",\n browserVersion: \"unknown\",\n osName: \"unknown\",\n osVersion: \"unknown\",\n platformName: \"unknown\"\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || \"unknown\",\n browserVersion: browser.version || \"unknown\",\n osName: os.name || \"unknown\",\n osVersion: os.version || \"unknown\",\n platformName: platform.type || \"unknown\"\n };\n } catch (error) {\n logWarn(error);\n return defRes;\n }\n};\nvar getDeviceResolution = () => {\n if (!window) return \"unknown\";\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\n// src/plugin/track/trackClass.ts\nvar FrTrack = class {\n constructor(instance2, pluginOptions) {\n this.userId = getUserId();\n this.timer = null;\n this.uvTimer = null;\n this.lastUvReportTime = 0;\n this.browserInfo = null;\n this.taskQueue = [];\n this.isProcessing = false;\n this.reportPrevData = () => {\n this.reportErrCacheData();\n };\n if (!instance2) {\n throw new Error(\"\\u8BF7\\u4F20\\u5165SDk\\u5B9E\\u4F8B\");\n }\n this.cacheFn = instance2.$cache;\n this.reportFn = instance2.$report;\n this.instanceConfig = instance2.config;\n this.pluginOptions = pluginOptions;\n this.debouncePv = debounce((type) => {\n const href = window.location.href || \"\";\n logInfo(type, \"\\u4E8B\\u4EF6\\u89E6\\u53D1\", this.instanceConfig.isDebug);\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: \"unknown\",\n count: 1\n }\n };\n this.singleTrack(\"page_view\", params);\n }, 300);\n }\n /* 执行异步队列任务 */\n async processQueue() {\n if (this.isProcessing || this.taskQueue.length === 0) return;\n this.isProcessing = true;\n const currentTask = this.taskQueue.shift();\n try {\n await currentTask.fn();\n logInfo(`\\u2705 \\u4EFB\\u52A1\\u6267\\u884C\\u6210\\u529F\\uFF1A${currentTask.desc}`, \"\", this.instanceConfig.isDebug);\n } catch (err) {\n logInfo(err, `\\u274C \\u4EFB\\u52A1\\u6267\\u884C\\u5931\\u8D25\\uFF1A${currentTask.desc}`, this.instanceConfig.isDebug);\n } finally {\n this.isProcessing = false;\n this.processQueue();\n }\n }\n /* 异步队列添加任务 */\n addTask(task) {\n const taskWithDesc = {\n desc: `${task.type} \\u4EFB\\u52A1`,\n ...task\n };\n this.taskQueue.push(taskWithDesc);\n this.processQueue();\n }\n /* 上报缓存数据 */\n async reportCacheData() {\n this.addTask({\n type: \"report_send\",\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get(CACHE_DATA_NAME);\n if (!cacheData?.length) return;\n const cleanInfo = cleanTrackData(cacheData);\n if (cleanInfo.type !== \"success\") {\n logWarn(cleanInfo.errReason);\n } else {\n const result = aggregationData(cleanInfo.data);\n logInfo(result, \"\\u4E0A\\u62A5\\u6570\\u636E\", this.instanceConfig.isDebug);\n if (result?.length) {\n this.reportFn.send(result).catch((err) => {\n logError(err, \"\\u4E0A\\u62A5\\u5931\\u8D25\\u6570\\u636E\\u5F02\\u5E38\");\n this.cacheFn.set(CACHE_ERR_DATA_NAME, result);\n });\n }\n }\n await this.cacheFn.remove(CACHE_DATA_NAME);\n }\n });\n }\n /* 上报缓存的失败数据 */\n async reportErrCacheData() {\n this.addTask({\n type: \"report_send\",\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get(CACHE_ERR_DATA_NAME);\n if (!cacheData?.length) return;\n this.reportFn.send(cacheData).catch((err) => {\n logError(err, \"\\u4E0A\\u62A5\\u5931\\u8D25\\u6570\\u636E\\u5F02\\u5E38\");\n });\n await this.cacheFn.remove(CACHE_ERR_DATA_NAME);\n }\n });\n }\n /* 定时循环上报 */\n loopReport() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.timer = setInterval(() => {\n this.reportCacheData();\n }, this.instanceConfig.maxCacheTime);\n }\n /* 浏览器关闭时触发 */\n onBrowserClose() {\n window.addEventListener(\"beforeunload\", () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.reportCacheData();\n });\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState !== \"visible\") {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.reportCacheData();\n } else {\n this.loopReport();\n }\n });\n }\n nativePv() {\n const methodsList = [\"popstate\", \"hashchange\", \"pushState\", \"replaceState\"];\n this.debouncePv(\"\\u521D\\u6B21\\u4E0A\\u62A5\");\n methodsList.forEach((method) => {\n window.addEventListener(method, () => {\n this.debouncePv(method);\n });\n });\n }\n // private vuePv() {\n // if (!this.pluginOptions.router) {\n // throw new Error('请传入路由实例');\n // }\n // const router = this.pluginOptions.router as any;\n // router.afterEach((to: any) => {\n // const params = {\n // event_name: to.path,\n // custom_data: {\n // page_url: to.fullPath || '--',\n // page_name: to.name || '--',\n // count: 1\n // }\n // };\n // this.singleTrack('page_view', params);\n // });\n // }\n async toSetCacheData(params) {\n logInfo(params, \"\\u8BBE\\u7F6E\\u7F13\\u5B58\\u6570\\u636E\", this.instanceConfig.isDebug);\n this.addTask({\n type: \"cache_set\",\n fn: async () => {\n if (!this.cacheFn) return;\n const { maxCacheSize } = this.instanceConfig;\n const res = await this.cacheFn.get(CACHE_DATA_NAME);\n if (res?.length >= maxCacheSize) {\n this.reportCacheData();\n this.toSetCacheData(params);\n } else {\n await this.cacheFn.set(CACHE_DATA_NAME, params);\n }\n }\n });\n }\n async track(params) {\n const { project_name, app_version } = this.instanceConfig;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo;\n if (params.custom_data) {\n params.custom_data = sanitizeCustomData(params.custom_data);\n }\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n this.toSetCacheData(trackParams);\n }\n singleTrack(eventType, params) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n /**\n * @method 自定义用户id\n */\n setUser(id) {\n this.userId = id;\n this.addTask({\n type: \"cache_update\",\n fn: async () => {\n const cacheData = await this.cacheFn.get(CACHE_DATA_NAME);\n if (cacheData?.length) {\n const updatedData = cacheData.map((item) => ({\n ...item,\n user_id: id\n }));\n await this.cacheFn.set(CACHE_DATA_NAME, updatedData);\n }\n }\n });\n }\n /**\n * @method 模块view\n */\n frModuleView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"module_view\", params);\n }\n /**\n * @method 模块click\n */\n frModuleClick(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"module_click\", params);\n }\n /**\n * @method 登录事件\n */\n frLoginEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"login_event\", params);\n }\n /**\n * @method 生单事件\n */\n frOrderEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"order_event\", params);\n }\n /**\n * @method 自定义事件\n */\n frCustomEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"custom_event\", params);\n }\n /**\n * @method 日志事件\n */\n frLogEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"log_event\", params);\n }\n /**\n * @method 点击事件\n */\n frClickEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"click_event\", params);\n }\n /**\n * @method 自动收集pv事件\n */\n frAutoPageView() {\n window.history.pushState = overrideHistoryMethods(\"pushState\");\n window.history.replaceState = overrideHistoryMethods(\"replaceState\");\n this.nativePv();\n }\n /**\n * @method pv事件\n */\n frPageView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"page_view\", params);\n }\n /**\n * @method uv事件\n */\n frUserView() {\n this.lastUvReportTime = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n const interval = 60 * 60 * 1e3;\n const params = {\n event_name: \"user_view\"\n };\n this.singleTrack(\"user_view\", params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n if (now > this.lastUvReportTime + 24 * interval) {\n this.lastUvReportTime = now;\n this.singleTrack(\"user_view\", params);\n }\n }, interval);\n }\n /**\n * @method 页面销毁事件\n */\n frPageDestroy(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"page_destroy\", params);\n }\n /**\n * @method 手动立即上报缓存的数据\n */\n frReport() {\n this.reportCacheData();\n }\n init() {\n if (this.instanceConfig.adapter === \"web\" && window) {\n this.browserInfo = getBrowserAndDeviceInfo();\n this.onBrowserClose();\n this.frUserView();\n if (this.pluginOptions.autoPv) {\n this.frAutoPageView();\n }\n }\n this.reportPrevData();\n this.loopReport();\n }\n};\nvar trackClass_default = FrTrack;\n\n// src/plugin/track/index.ts\nvar trackPlugin = {\n name: \"track\",\n defaultEnable: true,\n install: (sdkInstance, pluginOptions) => {\n try {\n if (!sdkInstance?.$cache || !sdkInstance?.$report) return;\n const defaultOptions = {\n frameType: \"js\",\n router: void 0,\n autoPv: true\n };\n if (pluginOptions) {\n Object.assign(defaultOptions, pluginOptions);\n }\n if (sdkInstance.$track) return;\n const frTrack = new trackClass_default(sdkInstance, defaultOptions);\n sdkInstance.$track = frTrack;\n frTrack.init();\n } catch (err) {\n logError(err, \"trackPlugin\\u521D\\u59CB\\u5316\\u5931\\u8D25\");\n }\n }\n};\n\n// src/index.ts\nvar instance = null;\nvar FrWebSDK = class {\n constructor() {\n this.isInit = false;\n this.config = defaultConfig;\n this.adapter = null;\n }\n init(userConfig) {\n if (this.isInit) {\n logWarn(\"SDK\\u5DF2\\u521D\\u59CB\\u5316\");\n return this;\n }\n this.config = { ...defaultConfig, ...userConfig };\n this.adapter = getAdapter(this.config.adapter);\n coreInit({\n config: this.config,\n adapter: this.adapter,\n instance: this\n });\n if (this.config.plugins) {\n this.config.plugins.forEach((plugin) => {\n if (plugin.type === \"track\") {\n trackPlugin.install(this, plugin.options);\n }\n });\n }\n this.isInit = true;\n return this;\n }\n};\nfunction getInstance() {\n if (!instance) {\n instance = new FrWebSDK();\n }\n return instance;\n}\nvar webSdk = getInstance();\nvar index_default = webSdk;\nexport {\n index_default as default\n};\n","import type { Options } from '../types';\n\nconst MAX_CACHE_SIZE = 15;\nconst MAX_CACHE_TIME = 300000;\nconst MAX_TIMEOUT = 10000;\n\nconst defaultConfig: Options = {\n project_name: '',\n report_url: '',\n app_version: '',\n adapter: 'web',\n maxCacheSize: MAX_CACHE_SIZE,\n maxCacheTime: MAX_CACHE_TIME,\n maxTimeout: MAX_TIMEOUT,\n isDebug: false,\n plugins: [\n {\n type: 'track',\n options: {\n autoPv: true\n // frameType: 'js',\n // router: null\n }\n }\n ]\n};\n\nexport { defaultConfig };\n","import * as localForage from 'localforage';\nimport { Cache } from '../../core';\nimport type { CacheName } from '../../core/types';\n\nclass WebCache extends Cache {\n constructor(options?: Record<string, unknown>) {\n super(options);\n }\n\n public async get<T>(name: CacheName) {\n const res = await localForage.getItem<T[]>(name);\n return res || [];\n }\n\n public async set<T>(name: CacheName, data: T | T[]): Promise<void> {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n await localForage.setItem(name, currentData);\n } else {\n await localForage.setItem(name, cacheData);\n }\n }\n\n public async remove(name: CacheName) {\n await localForage.removeItem(name);\n }\n\n public async clear(): Promise<void> {\n await localForage.clear();\n }\n}\n\nexport default WebCache;\n","import type { CacheName } from './types';\n\nexport abstract class Cache {\n protected options;\n constructor(options?: Record<string, unknown>) {\n if (options) {\n this.options = options;\n }\n }\n public abstract get<T>(name: CacheName): Promise<T[]> | T[];\n public abstract set<T>(name: CacheName, data: T | T[]): Promise<void> | void;\n public abstract remove(name: CacheName): void | Promise<void>;\n public abstract clear(): void | Promise<void>;\n}\n\n// 导出初始化方法(适配具体实现)\nexport function initCache<T extends Cache>(\n CacheClass: new (options: unknown) => T,\n options?: { [key: string]: unknown }\n): T {\n return new CacheClass(options);\n}\n\ntype CacheType = InstanceType<typeof Cache>;\n\nexport type { CacheType };\n","import type { ReportReq } from './types';\n\nexport abstract class Report {\n protected options;\n constructor(options: ReportReq) {\n this.options = options;\n }\n public abstract send<T>(data: T[]): Promise<unknown>;\n public abstract retry<T>(failedData: T[], callback?: () => void): void;\n}\n\n// 导出初始化方法(适配具体实现)\nexport function initReport<T extends Report>(\n ReportClass: new (options: unknown) => T,\n options: ReportReq\n): T {\n if (!options.url) {\n throw new Error('请传入上报地址url');\n }\n return new ReportClass(options);\n}\n\ntype ReportType = InstanceType<typeof Report>;\n\nexport type { ReportType };\n","import { initCache } from './cache';\nimport { initReport } from './report';\nconst coreInit = ({ config, adapter, instance }: any) => {\n // 初始化缓存\n instance.$cache = initCache(adapter.cache);\n // 初始化上报\n instance.$report = initReport(adapter.report, {\n url: config.report_url,\n timeout: config.maxTimeout\n });\n};\n\nexport { coreInit };\n","const EVENT_TYPES = [\n 'page_view',\n 'user_view',\n 'page_destroy',\n 'click_event',\n 'module_click',\n 'module_view',\n 'login_event',\n 'order_event',\n 'custom_event',\n 'log_event'\n] as const;\n\nconst CAN_AGGREGATION_TYPES = ['page_view', 'user_view'] as const;\n\nconst EVENT_KEYS = [\n 'project_name',\n 'event_type',\n 'event_name',\n 'event_time',\n 'user_id',\n 'app_version',\n 'user_timezone',\n 'device_type',\n 'user_agent',\n 'screen_resolution',\n 'custom_data',\n 'is_aggregation'\n] as const;\n\nconst CACHE_DATA_NAME = 'fr-track-cache-data';\nconst CACHE_ERR_DATA_NAME = 'fr-track-cache-err-data';\n\nexport { EVENT_TYPES, EVENT_KEYS, CAN_AGGREGATION_TYPES, CACHE_DATA_NAME, CACHE_ERR_DATA_NAME };\n","/**\n * 公共打印日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n * @param { boolean } isDebug 是否调试模式\n */\nconst logInfo = (message: unknown, title?: string, isDebug = false): void => {\n if (!isDebug) return;\n const logTitle = title ? `[Fr-track log ${title}]` : '[Fr-track log]';\n console.log(`${logTitle}:`, message);\n};\n\n/**\n * 公共打印警告日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n */\nconst logWarn = (message: unknown, title?: string): void => {\n const logTitle = title ? `[Fr-track warning ${title}]` : '[Fr-track warning]';\n console.warn(`${logTitle}:`, message);\n};\n\n/**\n * 公共打印异常日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n */\nconst logError = (message: unknown, title?: string): void => {\n const logTitle = title ? `[Fr-track error ${title}]` : '[Fr-track error]';\n console.error(`${logTitle}:`, message);\n};\n\n/**\n * 获取变量类型\n * @param { unknown } variable 变量\n * @return { string } 类型字符串\n */\nconst getVariableType = (variable: unknown): string => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\n\n/**\n * 手动实现 UUID v4\n * @returns { string } uuid\n */\nconst generateFallbackUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * 生成uuid\n * @returns { string } uuid\n */\nconst generateUserId = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // 降级方案\n return generateFallbackUUID();\n};\n\n/**\n * 重写history的pushState和replaceState\n */\nconst overrideHistoryMethods = <T extends keyof History>(type: T): any => {\n const originalMethod = history[type];\n return function (this: any, ...args: any) {\n const res = originalMethod.apply(this, args);\n const e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\n\n/**\n * 获取用户时区\n */\nconst getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n logWarn(error, '无法获取时区名称,使用偏移量推算:');\n const offset = new Date().getTimezoneOffset();\n if (offset >= 0) {\n return `西${offset / 60}区`;\n } else {\n return `东${-offset / 60}区`;\n }\n }\n};\n\n/**\n * 触发事件后,延迟指定时间再执行函数;若延迟内再次触发,重新计时\n * @param fn 要防抖的目标函数(支持任意参数、任意返回值,保留this指向)\n * @param delay 防抖延迟时间,默认800毫秒\n * @param immediate 是否立即执行(true:首次触发立即执行,后续延迟内触发重新计时;false:延迟后执行)\n * @returns 包装后的防抖函数(与原函数参数一致,无返回值)\n */\nexport function debounce<F extends (...args: any[]) => any>(\n fn: F,\n delay: number = 800,\n immediate: boolean = false\n): (...args: Parameters<F>) => void {\n let timer: number | null = null;\n let flag = false;\n\n return function (this: ThisParameterType<F>, ...args: Parameters<F>) {\n if (immediate && !flag) {\n fn.apply(this, args);\n }\n\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n\n flag = true;\n timer = setTimeout(() => {\n fn.apply(this, args);\n flag = false;\n }, delay);\n };\n}\n\n/**\n * 递归处理自定义数据,对字符串进行HTML标签过滤,对对象递归处理\n * @param data 自定义数据对象\n * @returns 处理后的自定义数据对象\n */\nconst sanitizeCustomData = (data: Record<string, unknown>) => {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === 'string') {\n sanitized[key] = value.replace(/<[^>]*>/g, '');\n } else if (getVariableType(value) === 'object') {\n sanitized[key] = sanitizeCustomData(value as Record<string, unknown>);\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n};\n\nexport {\n logInfo,\n logWarn,\n logError,\n getVariableType,\n generateUserId,\n overrideHistoryMethods,\n getUserTimeZone,\n sanitizeCustomData\n};\n","import { EVENT_TYPES, EVENT_KEYS } from '../static/constant';\nimport { getVariableType, logWarn } from './utils';\nimport type { EventsType } from '../types';\n\n/**\n * @method 校验事件类型\n */\nexport function validateEventType(eventType?: unknown): boolean {\n return typeof eventType === 'string' && EVENT_TYPES.includes(eventType as EventsType);\n}\n\n/**\n * @method 校验字段\n */\nexport function validateEventKey(params?: unknown): boolean {\n const type = getVariableType(params);\n if (!params || type !== 'object') {\n logWarn('Event params must be an object');\n return false;\n }\n const keys = Object.keys(params as Record<string, unknown>);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key as (typeof EVENT_KEYS)[number])) {\n logWarn(`Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n","import { validateEventType, validateEventKey } from '../utils/validator';\nimport { logWarn, logError } from '../utils/utils';\n// TODO: 解耦\nimport type { TrackEventItem } from '../plugin/track/types';\n\n/**\n * 清洗上报数据\n * @param { array } rawData 待清洗的原数据\n * @returns { array } 清洗后的数据\n */\nconst cleanTrackData = (\n rawData: TrackEventItem[]\n): {\n type: 'success' | 'fail';\n errReason?: string;\n data: TrackEventItem[];\n} => {\n try {\n // 过滤非法的事件类型、非法的时间日期\n const tempIds = new Set();\n const resultData = rawData.filter(rawItem => {\n // 缺失必要字段\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n\n // event_type校验不通过\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n logWarn('事件类型不合法');\n return false;\n }\n\n // event_time校验不通过\n const eventTime = rawItem.event_time;\n const minDateTime = new Date('2025-12-01').getTime();\n if (!eventTime || typeof eventTime !== 'number' || eventTime < minDateTime) {\n return false;\n }\n\n // 相同时间戳相同事件已存在\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: 'success',\n data: resultData\n };\n } catch (error) {\n logError(error, '清洗失败');\n const errReason = (error as Error).message || 'Unknown error';\n return {\n type: 'fail',\n errReason: errReason,\n data: rawData\n };\n }\n};\n\nexport { cleanTrackData };\n","import { CAN_AGGREGATION_TYPES } from '../static/constant';\nimport { logError } from '../utils/utils';\n// TODO: 解耦\nimport type { TrackEventItem } from '../plugin/track/types';\n\n/**\n * 聚合数据\n * @param { array } rawData 需要聚合的原数据\n * @returns { array } 聚合后的数据\n */\nconst aggregationData = (rawData: TrackEventItem[]): TrackEventItem[] => {\n try {\n const resultData: TrackEventItem[] = [];\n for (let i = 0; i < rawData.length; i++) {\n const rawItem = rawData[i];\n if (!rawItem) continue;\n const item = { ...rawItem };\n /**\n * 以\"天\"为维度,将以下事件进行聚合\n * pv、uv、自定义指定需要聚合的数据\n */\n if (\n CAN_AGGREGATION_TYPES.includes(item.event_type as (typeof CAN_AGGREGATION_TYPES)[number]) ||\n item.is_aggregation\n ) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time as number).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n r =>\n r.event_time === currentDate &&\n r.event_type === item.event_type &&\n r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n // 如果是uv,后面的userId覆盖之前\n if (item.event_type === 'user_view') {\n resultItem.user_id = item.user_id;\n }\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n logError(error, '聚合失败');\n // 聚合失败则直接上报原数据\n return rawData;\n }\n};\n\nexport { aggregationData };\n","import { Report } from '../../core';\nimport type { ReportReq } from '../../core/types';\n\nclass WebReport extends Report {\n constructor(options: ReportReq) {\n super(options);\n }\n\n public async retry<T>(failedData: T[], callback?: () => void, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3000);\n }\n }\n\n public async send<T>(data: T[]) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if ('sendBeacon' in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append('data', jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', url, true);\n xhr.timeout = timeout;\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = () => {\n resolve(xhr.response);\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n }\n}\n\nexport default WebReport;\n","import { Cache } from '../../core';\nimport type { CacheName } from '../../core/types';\n\nclass WxCache extends Cache {\n constructor(options?: Record<string, unknown>) {\n super(options);\n }\n\n public async get(name: CacheName) {\n const res = wx.getStorageSync(name);\n return res || [];\n }\n\n public async set<T>(name: CacheName, data: T | T[]): Promise<void> {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n wx.setStorageSync(name, currentData);\n } else {\n wx.setStorageSync(name, cacheData);\n }\n }\n\n public async remove(name: CacheName) {\n wx.removeStorageSync(name);\n }\n\n public async clear(): Promise<void> {\n wx.clearStorageSync();\n }\n}\n\nexport default WxCache;\n","import { Report } from '../../core';\nimport type { ReportReq } from '../../core/types';\n\nclass WxReport extends Report {\n constructor(options: ReportReq) {\n super(options);\n }\n\n public async retry<T>(failedData: T[], callback?: () => void, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3000);\n }\n }\n\n public async send<T>(data: T[]) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (wx && wx.request) {\n wx.request({\n url,\n method: 'POST',\n data: data,\n timeout,\n success: function success(res: any) {\n resolve(res);\n },\n fail: function fail(err: any) {\n reject(err);\n }\n });\n } else {\n reject();\n }\n });\n }\n}\n\nexport default WxReport;\n","import WebCache from './web/cache';\nimport WebReport from './web/report';\nimport WxCache from './wx/cache';\nimport WxReport from './wx/report';\n\n/**\n * 获取运行环境\n */\nconst getEnv = () => {\n const isMiniProgram = wx && typeof wx.getSystemInfoSync === 'function';\n return isMiniProgram ? 'miniProgram' : 'web';\n};\n\n/**\n * 获取对应环境的配置w\n */\nconst getAdapter = (configEnv: string) => {\n const env = configEnv || getEnv();\n if (env === 'miniProgram') {\n return {\n env: 'miniProgram',\n cache: WxCache,\n report: WxReport\n };\n }\n return {\n env: 'web',\n cache: WebCache,\n report: WebReport\n };\n};\n\nexport { getAdapter };\n","import { generateUserId } from '../utils/utils';\n\n/**\n * 获取user_id\n */\nconst getUserId = (): string => {\n try {\n // 查看缓存是否有已生成的uuid\n const track_uuid = localStorage.getItem('track_uuid');\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem('track_uuid', uuid);\n return uuid;\n } catch (e) {\n return generateUserId();\n }\n};\n\nexport { getUserId };\n","import Browser from 'bowser';\nimport { logWarn } from './utils';\nimport type { BrowserInfoType } from '../types';\n\n/**\n * 获取浏览器及设备信息\n * @returns { object | null }\n */\nconst getBrowserAndDeviceInfo = (): BrowserInfoType => {\n const defRes = {\n browserName: 'unknown',\n browserVersion: 'unknown',\n osName: 'unknown',\n osVersion: 'unknown',\n platformName: 'unknown'\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || 'unknown',\n browserVersion: browser.version || 'unknown',\n osName: os.name || 'unknown',\n osVersion: os.version || 'unknown',\n platformName: platform.type || 'unknown'\n };\n } catch (error) {\n logWarn(error);\n return defRes;\n }\n};\n\n/**\n * 获取设备分辨率\n * @return { string } 分辨率信息\n */\nconst getDeviceResolution = (): string => {\n if (!window) return 'unknown';\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\nexport { getBrowserAndDeviceInfo, getDeviceResolution };\n","import { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from '../../static/constant';\nimport { getUserId } from '../../utils/uuid';\nimport { cleanTrackData, aggregationData } from '../../core';\nimport { getBrowserAndDeviceInfo, getDeviceResolution } from '../../utils/browser';\nimport {\n overrideHistoryMethods,\n getUserTimeZone,\n logInfo,\n logWarn,\n logError,\n sanitizeCustomData,\n debounce\n} from '../../utils/utils';\n\nimport type { BrowserInfoType, TrackInstance, TrackPluginOptions } from '../types';\nimport type { TrackEventItem, TrackParams, CustomData, EventsType, TrackTask } from './types';\nimport type { Cache } from '../../core/cache';\nimport type { Report } from '../../core/report';\nimport type { Options } from '../../types';\n\nclass FrTrack<T = TrackEventItem> {\n private userId = getUserId();\n private timer: number | null = null;\n private uvTimer: number | null = null;\n private lastUvReportTime: number = 0;\n private browserInfo: BrowserInfoType | null = null;\n private pluginOptions: TrackPluginOptions;\n private taskQueue: TrackTask[] = [];\n private isProcessing = false;\n private cacheFn: Cache;\n private reportFn: Report;\n private instanceConfig: Options;\n private debouncePv: (key: string) => void;\n\n constructor(instance: TrackInstance, pluginOptions: TrackPluginOptions) {\n if (!instance) {\n throw new Error('请传入SDk实例');\n }\n this.cacheFn = instance.$cache;\n this.reportFn = instance.$report;\n this.instanceConfig = instance.config;\n this.pluginOptions = pluginOptions;\n this.debouncePv = debounce((type: string) => {\n // 初次加载手动执行\n const href = window.location.href || '';\n logInfo(type, '事件触发', this.instanceConfig.isDebug);\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: 'unknown',\n count: 1\n }\n };\n this.singleTrack('page_view', params);\n }, 300);\n }\n\n /* 执行异步队列任务 */\n private async processQueue() {\n // 如果正在执行任务,或队列为空 直接返回\n if (this.isProcessing || this.taskQueue.length === 0) return;\n // 开始执行\n this.isProcessing = true;\n // 取出队列第一个任务\n const currentTask = this.taskQueue.shift()!;\n try {\n await currentTask.fn();\n logInfo(`✅ 任务执行成功:${currentTask.desc}`, '', this.instanceConfig.isDebug);\n } catch (err) {\n logInfo(err, `❌ 任务执行失败:${currentTask.desc}`, this.instanceConfig.isDebug);\n } finally {\n this.isProcessing = false;\n this.processQueue();\n }\n }\n\n /* 异步队列添加任务 */\n private addTask<T>(task: TrackTask<T>) {\n const taskWithDesc = {\n desc: `${task.type} 任务`,\n ...task\n };\n this.taskQueue.push(taskWithDesc);\n // 添加后启动任务\n this.processQueue();\n }\n\n /* 上报缓存数据 */\n private async reportCacheData() {\n this.addTask({\n type: 'report_send',\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (!cacheData?.length) return;\n // 清洗\n const cleanInfo = cleanTrackData(cacheData as TrackEventItem[]);\n if (cleanInfo.type !== 'success') {\n logWarn(cleanInfo.errReason);\n // TODO: 上报失败原因及数据 清空缓存\n } else {\n // 聚合\n const result = aggregationData(cleanInfo.data);\n logInfo(result, '上报数据', this.instanceConfig.isDebug);\n if (result?.length) {\n this.reportFn.send<T>(result as T[]).catch(err => {\n logError(err, '上报失败数据异常');\n this.cacheFn.set(CACHE_ERR_DATA_NAME, result);\n });\n }\n }\n // 不管上报是否成功,删除缓存\n await this.cacheFn.remove(CACHE_DATA_NAME);\n }\n });\n }\n\n /* 上报缓存的失败数据 */\n private async reportErrCacheData() {\n this.addTask({\n type: 'report_send',\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get<T>(CACHE_ERR_DATA_NAME);\n if (!cacheData?.length) return;\n this.reportFn.send<T>(cacheData).catch(err => {\n logError(err, '上报失败数据异常');\n });\n await this.cacheFn.remove(CACHE_ERR_DATA_NAME);\n }\n });\n }\n\n private reportPrevData = () => {\n this.reportErrCacheData();\n };\n\n /* 定时循环上报 */\n private loopReport() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.timer = setInterval(() => {\n this.reportCacheData();\n }, this.instanceConfig.maxCacheTime);\n }\n\n /* 浏览器关闭时触发 */\n private onBrowserClose() {\n /**\n * 浏览器环境\n */\n window.addEventListener('beforeunload', () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.reportCacheData();\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState !== 'visible') {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.reportCacheData();\n } else {\n // 重启定时器\n this.loopReport();\n }\n });\n }\n\n private nativePv() {\n const methodsList = ['popstate', 'hashchange', 'pushState', 'replaceState'];\n // 初始化上报一次\n this.debouncePv('初次上报');\n methodsList.forEach(method => {\n window.addEventListener(method, () => {\n this.debouncePv(method);\n });\n });\n }\n\n // private vuePv() {\n // if (!this.pluginOptions.router) {\n // throw new Error('请传入路由实例');\n // }\n // const router = this.pluginOptions.router as any;\n // router.afterEach((to: any) => {\n // const params = {\n // event_name: to.path,\n // custom_data: {\n // page_url: to.fullPath || '--',\n // page_name: to.name || '--',\n // count: 1\n // }\n // };\n // this.singleTrack('page_view', params);\n // });\n // }\n\n private async toSetCacheData(params: T) {\n logInfo(params, '设置缓存数据', this.instanceConfig.isDebug);\n this.addTask({\n type: 'cache_set',\n fn: async () => {\n if (!this.cacheFn) return;\n const { maxCacheSize } = this.instanceConfig;\n const res = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (res?.length >= maxCacheSize) {\n this.reportCacheData();\n // 上报成功后, 再设置缓存\n this.toSetCacheData(params);\n } else {\n await this.cacheFn.set<T>(CACHE_DATA_NAME, params);\n }\n }\n });\n }\n\n private async track(params: TrackParams) {\n const { project_name, app_version } = this.instanceConfig;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo!;\n if (params.custom_data) {\n params.custom_data = sanitizeCustomData(params.custom_data);\n }\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n this.toSetCacheData(trackParams);\n }\n\n private singleTrack<T extends Omit<TrackParams, 'event_type'>>(\n eventType: EventsType,\n params: T & (keyof T extends keyof Omit<TrackParams, 'event_type'> ? T : never)\n ) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n\n /**\n * @method 自定义用户id\n */\n public setUser(id: string) {\n this.userId = id;\n // 更新userId\n this.addTask({\n type: 'cache_update',\n fn: async () => {\n const cacheData = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (cacheData?.length) {\n const updatedData = cacheData.map(item => ({\n ...item,\n user_id: id\n }));\n await this.cacheFn.set(CACHE_DATA_NAME, updatedData);\n }\n }\n });\n }\n\n /**\n * @method 模块view\n */\n public frModuleView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('module_view', params);\n }\n\n /**\n * @method 模块click\n */\n public frModuleClick(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('module_click', params);\n }\n\n /**\n * @method 登录事件\n */\n public frLoginEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('login_event', params);\n }\n\n /**\n * @method 生单事件\n */\n public frOrderEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('order_event', params);\n }\n\n /**\n * @method 自定义事件\n */\n public frCustomEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('custom_event', params);\n }\n\n /**\n * @method 日志事件\n */\n public frLogEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('log_event', params);\n }\n\n /**\n * @method 点击事件\n */\n public frClickEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('click_event', params);\n }\n\n /**\n * @method 自动收集pv事件\n */\n private frAutoPageView() {\n // if (this.pluginOptions.frameType === 'js') {\n window.history.pushState = overrideHistoryMethods('pushState');\n window.history.replaceState = overrideHistoryMethods('replaceState');\n this.nativePv();\n // } else if (this.pluginOptions.frameType === 'vue') {\n // this.vuePv()\n // }\n }\n\n /**\n * @method pv事件\n */\n public frPageView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('page_view', params);\n }\n\n /**\n * @method uv事件\n */\n public frUserView() {\n this.lastUvReportTime = new Date().setHours(0, 0, 0, 0);\n // 一小时检查一次\n const interval = 60 * 60 * 1000;\n const params = {\n event_name: 'user_view'\n };\n this.singleTrack('user_view', params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = new Date().setHours(0, 0, 0, 0);\n if (now > this.lastUvReportTime + 24 * interval) {\n // 超过24小时,再次上报uv\n // 更新上报时间\n this.lastUvReportTime = now;\n this.singleTrack('user_view', params);\n }\n }, interval);\n }\n\n /**\n * @method 页面销毁事件\n */\n public frPageDestroy(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('page_destroy', params);\n }\n\n /**\n * @method 手动立即上报缓存的数据\n */\n public frReport() {\n this.reportCacheData();\n }\n\n public init() {\n /**\n * 浏览器环境下\n */\n if (this.instanceConfig.adapter === 'web' && window) {\n /**\n * 获取浏览器信息\n */\n this.browserInfo = getBrowserAndDeviceInfo();\n /**\n * 监听浏览器关闭事件,进行上报\n */\n this.onBrowserClose();\n\n /**\n * 统计uv\n */\n this.frUserView();\n\n /**\n * 判断是否监听pv事件\n */\n if (this.pluginOptions.autoPv) {\n this.frAutoPageView();\n }\n }\n\n /**\n * 1. 判断缓存是否有没有传输的数据\n * 2. 判断上次是否有失败的数据存储在缓存中\n */\n this.reportPrevData();\n /**\n * 3. 开启定时器轮询,达到时间阈值进行上报\n */\n this.loopReport();\n }\n}\n\nexport default FrTrack;\n","import FrTrack from './trackClass';\n\nimport type { BasePlugin, TrackPluginOptions } from '../types';\nimport { logError } from '../../utils/utils';\n\nconst trackPlugin: BasePlugin<TrackPluginOptions> = {\n name: 'track',\n defaultEnable: true,\n install: (sdkInstance, pluginOptions) => {\n try {\n if (!sdkInstance?.$cache || !sdkInstance?.$report) return;\n const defaultOptions: TrackPluginOptions = {\n frameType: 'js',\n router: undefined,\n autoPv: true\n };\n if (pluginOptions) {\n Object.assign(defaultOptions, pluginOptions);\n }\n\n if (sdkInstance.$track) return;\n const frTrack = new FrTrack(sdkInstance, defaultOptions);\n sdkInstance.$track = frTrack;\n frTrack.init();\n } catch (err) {\n logError(err, 'trackPlugin初始化失败');\n }\n }\n};\n\nexport { trackPlugin };\n","// src/index.js\nimport { defaultConfig } from './config';\nimport { getAdapter } from './adapter/index';\nimport { coreInit } from './core/index.js';\nimport { logWarn } from './utils/utils';\nimport { Cache, Report } from './core';\nimport { trackPlugin } from './plugin/track';\nimport FrTrack from './plugin/track/trackClass';\nimport type { Options, CustomOptions } from './types';\n\nlet instance: InstanceType<typeof FrWebSDK> | null = null;\n\nclass FrWebSDK {\n private adapter: any;\n public isInit: boolean;\n public config: Options;\n public $cache!: InstanceType<typeof Cache>;\n public $report!: InstanceType<typeof Report>;\n public $track!: InstanceType<typeof FrTrack>;\n\n constructor() {\n this.isInit = false;\n this.config = defaultConfig;\n this.adapter = null;\n }\n\n init(userConfig: CustomOptions) {\n if (this.isInit) {\n logWarn('SDK已初始化');\n return this;\n }\n // 合并配置\n this.config = { ...defaultConfig, ...userConfig };\n // 获取适配器\n this.adapter = getAdapter(this.config.adapter);\n // 核心初始化\n coreInit({\n config: this.config,\n adapter: this.adapter,\n instance: this\n });\n // 获取用户插件\n if (this.config.plugins) {\n this.config.plugins.forEach(plugin => {\n if (plugin.type === 'track') {\n trackPlugin.install(this, plugin.options);\n }\n });\n }\n\n this.isInit = true;\n\n return this;\n }\n}\n\n// 获取单例\nfunction getInstance() {\n if (!instance) {\n instance = new FrWebSDK();\n }\n return instance;\n}\n\ntype TrackInstance = InstanceType<typeof FrWebSDK>;\n\nconst webSdk = getInstance();\nexport default webSdk;\nexport type { TrackInstance };\n"]}
|
|
1
|
+
{"version":3,"sources":["/Users/hl/Desktop/project/track-sdk/dist/index.js","../src/config/index.ts","../src/adapter/web/cache.ts","../src/core/cache.ts","../src/core/report.ts","../src/core/init.ts","../src/static/constant.ts","../src/utils/utils.ts","../src/utils/validator.ts","../src/core/clean.ts","../src/core/aggregation.ts","../src/adapter/web/report.ts","../src/adapter/wx/cache.ts","../src/adapter/wx/report.ts","../src/adapter/index.ts","../src/utils/uuid.ts","../src/utils/browser.ts","../src/plugin/track/trackClass.ts","../src/plugin/track/index.ts","../src/index.ts"],"names":["MAX_CACHE_SIZE","MAX_CACHE_TIME","MAX_TIMEOUT","defaultConfig","project_name","report_url","app_version","adapter","maxCacheSize","maxCacheTime","maxTimeout","isDebug","plugins","type","options","autoPv","localForage","Cache","initCache","CacheClass","Report","initReport","ReportClass","url","Error","coreInit","config","instance","$cache","cache","$report","report","timeout","EVENT_TYPES","CAN_AGGREGATION_TYPES","EVENT_KEYS","CACHE_DATA_NAME","CACHE_ERR_DATA_NAME","logInfo","message","title","logTitle","console","log","logWarn","warn","logError","error","getVariableType","variable","typeString","Object","prototype","toString","call","slice","toLowerCase","generateFallbackUUID","replace","c","r","Math","random","v","generateUserId","crypto","randomUUID","overrideHistoryMethods","originalMethod","history","args","res","apply","e","Event","window","dispatchEvent","getUserTimeZone","Intl","DateTimeFormat","resolvedOptions","timeZone","offset","Date","getTimezoneOffset","debounce","fn","delay","immediate","timer","flag","clearTimeout","setTimeout","sanitizeCustomData","data","sanitized","entries","key","value","validateEventType","eventType","includes","validateEventKey","params","keys","cleanTrackData","rawData","tempIds","Set","resultData","filter","rawItem","eventKeyResult","eventTypeResult","event_type","eventTime","event_time","minDateTime","getTime","id","event_name","has","add","errReason","aggregationData","i","item","is_aggregation","currentDate","setHours","resultItem","find","push","user_id","customData","custom_data","count","length","WebCache","get","name","getItem","set","currentData","cacheData","Array","isArray","setItem","remove","removeItem","clear","cache_default","WebReport","retry","failedData","callback","retryCount","err","send","Promise","resolve","reject","navigator","jsonData","JSON","stringify","formData","FormData","append","status","sendBeacon","xhr","XMLHttpRequest","open","setRequestHeader","onload","response","onerror","report_default","WxCache","wx","getStorageSync","setStorageSync","removeStorageSync","clearStorageSync","WxReport","request","method","success","fail","getEnv","isMiniProgram","getSystemInfoSync","getAdapter","configEnv","env","getUserId","track_uuid","localStorage","uuid","Browser","getBrowserAndDeviceInfo","defRes","browserName","browserVersion","osName","osVersion","platformName","ua","userAgent","info","parse","browser","os","platform","version","getDeviceInfo","brand","model","system","getDeviceResolution","screen","width","height","getWindowInfo","screenWidth","screenHeight","FrTrack","pluginOptions","userId","uvTimer","lastUvReportTime","browserInfo","taskQueue","isProcessing","reportPrevData","reportErrCacheData","cacheFn","reportFn","instanceConfig","debouncePv","href","location","page_url","page_name","singleTrack","processQueue","currentTask","shift","desc","addTask","task","taskWithDesc","reportCacheData","cleanInfo","result","catch","loopReport","clearInterval","setInterval","onBrowserClose","addEventListener","document","visibilityState","nativePv","methodsList","forEach","toSetCacheData","track","trackParams","assign","device_type","user_agent","screen_resolution","user_timezone","now","baseParams","setUser","updatedData","map","frModuleView","frModuleClick","frLoginEvent","frOrderEvent","frCustomEvent","frLogEvent","frClickEvent","frAutoPageView","pushState","replaceState","frPageView","frUserView","interval","frPageDestroy","frReport","init","trackClass_default","trackPlugin","defaultEnable","install","sdkInstance","defaultOptions","frameType","router","$track","frTrack","FrWebSDK","isInit","userConfig","plugin","getInstance","webSdk","index_default","default"],"mappings":"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","sourcesContent":["// src/config/index.ts\nvar MAX_CACHE_SIZE = 15;\nvar MAX_CACHE_TIME = 3e5;\nvar MAX_TIMEOUT = 1e4;\nvar defaultConfig = {\n project_name: \"\",\n report_url: \"\",\n app_version: \"\",\n adapter: \"web\",\n maxCacheSize: MAX_CACHE_SIZE,\n maxCacheTime: MAX_CACHE_TIME,\n maxTimeout: MAX_TIMEOUT,\n isDebug: false,\n plugins: [\n {\n type: \"track\",\n options: {\n autoPv: true\n // frameType: 'js',\n // router: null\n }\n }\n ]\n};\n\n// src/adapter/web/cache.ts\nimport * as localForage from \"localforage\";\n\n// src/core/cache.ts\nvar Cache = class {\n constructor(options) {\n if (options) {\n this.options = options;\n }\n }\n};\nfunction initCache(CacheClass, options) {\n return new CacheClass(options);\n}\n\n// src/core/report.ts\nvar Report = class {\n constructor(options) {\n this.options = options;\n }\n};\nfunction initReport(ReportClass, options) {\n if (!options.url) {\n throw new Error(\"\\u8BF7\\u4F20\\u5165\\u4E0A\\u62A5\\u5730\\u5740url\");\n }\n return new ReportClass(options);\n}\n\n// src/core/init.ts\nvar coreInit = ({ config, adapter, instance: instance2 }) => {\n instance2.$cache = initCache(adapter.cache);\n instance2.$report = initReport(adapter.report, {\n url: config.report_url,\n timeout: config.maxTimeout\n });\n};\n\n// src/static/constant.ts\nvar EVENT_TYPES = [\n \"page_view\",\n \"user_view\",\n \"page_destroy\",\n \"click_event\",\n \"module_click\",\n \"module_view\",\n \"login_event\",\n \"order_event\",\n \"custom_event\",\n \"log_event\"\n];\nvar CAN_AGGREGATION_TYPES = [\"page_view\", \"user_view\"];\nvar EVENT_KEYS = [\n \"project_name\",\n \"event_type\",\n \"event_name\",\n \"event_time\",\n \"user_id\",\n \"app_version\",\n \"user_timezone\",\n \"device_type\",\n \"user_agent\",\n \"screen_resolution\",\n \"custom_data\",\n \"is_aggregation\"\n];\nvar CACHE_DATA_NAME = \"fr-track-cache-data\";\nvar CACHE_ERR_DATA_NAME = \"fr-track-cache-err-data\";\n\n// src/utils/utils.ts\nvar logInfo = (message, title, isDebug = false) => {\n if (!isDebug) return;\n const logTitle = title ? `[Fr-track log ${title}]` : \"[Fr-track log]\";\n console.log(`${logTitle}:`, message);\n};\nvar logWarn = (message, title) => {\n const logTitle = title ? `[Fr-track warning ${title}]` : \"[Fr-track warning]\";\n console.warn(`${logTitle}:`, message);\n};\nvar logError = (message, title) => {\n const logTitle = title ? `[Fr-track error ${title}]` : \"[Fr-track error]\";\n console.error(`${logTitle}:`, message);\n};\nvar getVariableType = (variable) => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\nvar generateFallbackUUID = () => {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n};\nvar generateUserId = () => {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return generateFallbackUUID();\n};\nvar overrideHistoryMethods = (type) => {\n const originalMethod = history[type];\n return function(...args) {\n const res = originalMethod.apply(this, args);\n const e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\nvar getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n logWarn(error, \"\\u65E0\\u6CD5\\u83B7\\u53D6\\u65F6\\u533A\\u540D\\u79F0\\uFF0C\\u4F7F\\u7528\\u504F\\u79FB\\u91CF\\u63A8\\u7B97:\");\n const offset = (/* @__PURE__ */ new Date()).getTimezoneOffset();\n if (offset >= 0) {\n return `\\u897F${offset / 60}\\u533A`;\n } else {\n return `\\u4E1C${-offset / 60}\\u533A`;\n }\n }\n};\nfunction debounce(fn, delay = 800, immediate = false) {\n let timer = null;\n let flag = false;\n return function(...args) {\n if (immediate && !flag) {\n fn.apply(this, args);\n }\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n flag = true;\n timer = setTimeout(() => {\n fn.apply(this, args);\n flag = false;\n }, delay);\n };\n}\nvar sanitizeCustomData = (data) => {\n const sanitized = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\") {\n sanitized[key] = value.replace(/<[^>]*>/g, \"\");\n } else if (getVariableType(value) === \"object\") {\n sanitized[key] = sanitizeCustomData(value);\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n};\n\n// src/utils/validator.ts\nfunction validateEventType(eventType) {\n return typeof eventType === \"string\" && EVENT_TYPES.includes(eventType);\n}\nfunction validateEventKey(params) {\n const type = getVariableType(params);\n if (!params || type !== \"object\") {\n logWarn(\"Event params must be an object\");\n return false;\n }\n const keys = Object.keys(params);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key)) {\n logWarn(`Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n\n// src/core/clean.ts\nvar cleanTrackData = (rawData) => {\n try {\n const tempIds = /* @__PURE__ */ new Set();\n const resultData = rawData.filter((rawItem) => {\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n logWarn(\"\\u4E8B\\u4EF6\\u7C7B\\u578B\\u4E0D\\u5408\\u6CD5\");\n return false;\n }\n const eventTime = rawItem.event_time;\n const minDateTime = (/* @__PURE__ */ new Date(\"2025-12-01\")).getTime();\n if (!eventTime || typeof eventTime !== \"number\" || eventTime < minDateTime) {\n return false;\n }\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: \"success\",\n data: resultData\n };\n } catch (error) {\n logError(error, \"\\u6E05\\u6D17\\u5931\\u8D25\");\n const errReason = error.message || \"Unknown error\";\n return {\n type: \"fail\",\n errReason,\n data: rawData\n };\n }\n};\n\n// src/core/aggregation.ts\nvar aggregationData = (rawData) => {\n try {\n const resultData = [];\n for (let i = 0; i < rawData.length; i++) {\n const rawItem = rawData[i];\n if (!rawItem) continue;\n const item = { ...rawItem };\n if (CAN_AGGREGATION_TYPES.includes(item.event_type) || item.is_aggregation) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n (r) => r.event_time === currentDate && r.event_type === item.event_type && r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n if (item.event_type === \"user_view\") {\n resultItem.user_id = item.user_id;\n }\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n logError(error, \"\\u805A\\u5408\\u5931\\u8D25\");\n return rawData;\n }\n};\n\n// src/adapter/web/cache.ts\nvar WebCache = class extends Cache {\n constructor(options) {\n super(options);\n }\n async get(name) {\n const res = await localForage.getItem(name);\n return res || [];\n }\n async set(name, data) {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n await localForage.setItem(name, currentData);\n } else {\n await localForage.setItem(name, cacheData);\n }\n }\n async remove(name) {\n await localForage.removeItem(name);\n }\n async clear() {\n await localForage.clear();\n }\n};\nvar cache_default = WebCache;\n\n// src/adapter/web/report.ts\nvar WebReport = class extends Report {\n constructor(options) {\n super(options);\n }\n async retry(failedData, callback, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3e3);\n }\n }\n async send(data) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (\"sendBeacon\" in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append(\"data\", jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.timeout = timeout;\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n xhr.onload = () => {\n resolve(xhr.response);\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n }\n};\nvar report_default = WebReport;\n\n// src/adapter/wx/cache.ts\nvar WxCache = class extends Cache {\n constructor(options) {\n super(options);\n }\n async get(name) {\n const res = wx.getStorageSync(name);\n return res || [];\n }\n async set(name, data) {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n wx.setStorageSync(name, currentData);\n } else {\n wx.setStorageSync(name, cacheData);\n }\n }\n async remove(name) {\n wx.removeStorageSync(name);\n }\n async clear() {\n wx.clearStorageSync();\n }\n};\nvar cache_default2 = WxCache;\n\n// src/adapter/wx/report.ts\nvar WxReport = class extends Report {\n constructor(options) {\n super(options);\n }\n async retry(failedData, callback, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3e3);\n }\n }\n async send(data) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (wx && wx.request) {\n wx.request({\n url,\n method: \"POST\",\n data,\n timeout,\n success: function success(res) {\n resolve(res);\n },\n fail: function fail(err) {\n reject(err);\n }\n });\n } else {\n reject();\n }\n });\n }\n};\nvar report_default2 = WxReport;\n\n// src/adapter/index.ts\nvar getEnv = () => {\n const isMiniProgram = wx && typeof wx.getSystemInfoSync === \"function\";\n return isMiniProgram ? \"miniProgram\" : \"web\";\n};\nvar getAdapter = (configEnv) => {\n const env = configEnv || getEnv();\n if (env === \"miniProgram\") {\n return {\n env: \"miniProgram\",\n cache: cache_default2,\n report: report_default2\n };\n }\n return {\n env: \"web\",\n cache: cache_default,\n report: report_default\n };\n};\n\n// src/utils/uuid.ts\nvar getUserId = () => {\n try {\n const track_uuid = localStorage.getItem(\"track_uuid\");\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem(\"track_uuid\", uuid);\n return uuid;\n } catch (e) {\n return generateUserId();\n }\n};\n\n// src/utils/browser.ts\nimport Browser from \"bowser\";\nvar getBrowserAndDeviceInfo = (adapter) => {\n const defRes = {\n browserName: \"unknown\",\n browserVersion: \"unknown\",\n osName: \"unknown\",\n osVersion: \"unknown\",\n platformName: \"unknown\"\n };\n try {\n if (adapter === \"web\") {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || \"unknown\",\n browserVersion: browser.version || \"unknown\",\n osName: os.name || \"unknown\",\n osVersion: os.version || \"unknown\",\n platformName: platform.type || \"unknown\"\n };\n } else {\n if (!wx) return defRes;\n const info = wx.getDeviceInfo();\n const { brand, model, platform, system } = info;\n return {\n browserName: brand || \"miniProgram\",\n browserVersion: model || \"unknown\",\n osName: system || \"unknown\",\n osVersion: system || \"unknown\",\n platformName: platform || \"unknown\"\n };\n }\n } catch (error) {\n logWarn(error);\n return defRes;\n }\n};\nvar getDeviceResolution = (adapter) => {\n if (adapter === \"web\") {\n if (!window) return \"unknown\";\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n } else {\n if (!wx) return \"unknown\";\n const screen = wx.getWindowInfo();\n return `${screen.screenWidth}x${screen.screenHeight}`;\n }\n};\n\n// src/plugin/track/trackClass.ts\nvar FrTrack = class {\n constructor(instance2, pluginOptions) {\n this.userId = getUserId();\n this.timer = null;\n this.uvTimer = null;\n this.lastUvReportTime = 0;\n this.browserInfo = null;\n this.taskQueue = [];\n this.isProcessing = false;\n this.reportPrevData = () => {\n this.reportErrCacheData();\n };\n if (!instance2) {\n throw new Error(\"\\u8BF7\\u4F20\\u5165SDk\\u5B9E\\u4F8B\");\n }\n this.cacheFn = instance2.$cache;\n this.reportFn = instance2.$report;\n this.instanceConfig = instance2.config;\n this.pluginOptions = pluginOptions;\n this.debouncePv = debounce((type) => {\n const href = window.location.href || \"\";\n logInfo(type, \"\\u4E8B\\u4EF6\\u89E6\\u53D1\", this.instanceConfig.isDebug);\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: \"unknown\",\n count: 1\n }\n };\n this.singleTrack(\"page_view\", params);\n }, 300);\n }\n /* 执行异步队列任务 */\n async processQueue() {\n if (this.isProcessing || this.taskQueue.length === 0) return;\n this.isProcessing = true;\n const currentTask = this.taskQueue.shift();\n try {\n await currentTask.fn();\n logInfo(`\\u2705 \\u4EFB\\u52A1\\u6267\\u884C\\u6210\\u529F\\uFF1A${currentTask.desc}`, \"\", this.instanceConfig.isDebug);\n } catch (err) {\n logInfo(err, `\\u274C \\u4EFB\\u52A1\\u6267\\u884C\\u5931\\u8D25\\uFF1A${currentTask.desc}`, this.instanceConfig.isDebug);\n } finally {\n this.isProcessing = false;\n this.processQueue();\n }\n }\n /* 异步队列添加任务 */\n addTask(task) {\n const taskWithDesc = {\n desc: `${task.type} \\u4EFB\\u52A1`,\n ...task\n };\n this.taskQueue.push(taskWithDesc);\n this.processQueue();\n }\n /* 上报缓存数据 */\n async reportCacheData() {\n this.addTask({\n type: \"report_send\",\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get(CACHE_DATA_NAME);\n if (!cacheData?.length) return;\n const cleanInfo = cleanTrackData(cacheData);\n if (cleanInfo.type !== \"success\") {\n logWarn(cleanInfo.errReason);\n } else {\n const result = aggregationData(cleanInfo.data);\n logInfo(result, \"\\u4E0A\\u62A5\\u6570\\u636E\", this.instanceConfig.isDebug);\n if (result?.length) {\n this.reportFn.send(result).catch((err) => {\n logError(err, \"\\u4E0A\\u62A5\\u5931\\u8D25\\u6570\\u636E\\u5F02\\u5E38\");\n this.cacheFn.set(CACHE_ERR_DATA_NAME, result);\n });\n }\n }\n await this.cacheFn.remove(CACHE_DATA_NAME);\n }\n });\n }\n /* 上报缓存的失败数据 */\n async reportErrCacheData() {\n this.addTask({\n type: \"report_send\",\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get(CACHE_ERR_DATA_NAME);\n if (!cacheData?.length) return;\n this.reportFn.send(cacheData).catch((err) => {\n logError(err, \"\\u4E0A\\u62A5\\u5931\\u8D25\\u6570\\u636E\\u5F02\\u5E38\");\n });\n await this.cacheFn.remove(CACHE_ERR_DATA_NAME);\n }\n });\n }\n /* 定时循环上报 */\n loopReport() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.timer = setInterval(() => {\n this.reportCacheData();\n }, this.instanceConfig.maxCacheTime);\n }\n /* 浏览器关闭时触发 */\n onBrowserClose() {\n window.addEventListener(\"beforeunload\", () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.reportCacheData();\n });\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState !== \"visible\") {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.reportCacheData();\n } else {\n this.loopReport();\n }\n });\n }\n nativePv() {\n const methodsList = [\"popstate\", \"hashchange\", \"pushState\", \"replaceState\"];\n this.debouncePv(\"\\u521D\\u6B21\\u4E0A\\u62A5\");\n methodsList.forEach((method) => {\n window.addEventListener(method, () => {\n this.debouncePv(method);\n });\n });\n }\n // private vuePv() {\n // if (!this.pluginOptions.router) {\n // throw new Error('请传入路由实例');\n // }\n // const router = this.pluginOptions.router as any;\n // router.afterEach((to: any) => {\n // const params = {\n // event_name: to.path,\n // custom_data: {\n // page_url: to.fullPath || '--',\n // page_name: to.name || '--',\n // count: 1\n // }\n // };\n // this.singleTrack('page_view', params);\n // });\n // }\n async toSetCacheData(params) {\n logInfo(params, \"\\u8BBE\\u7F6E\\u7F13\\u5B58\\u6570\\u636E\", this.instanceConfig.isDebug);\n this.addTask({\n type: \"cache_set\",\n fn: async () => {\n if (!this.cacheFn) return;\n const { maxCacheSize } = this.instanceConfig;\n const res = await this.cacheFn.get(CACHE_DATA_NAME);\n if (res?.length >= maxCacheSize) {\n this.reportCacheData();\n this.toSetCacheData(params);\n } else {\n await this.cacheFn.set(CACHE_DATA_NAME, params);\n }\n }\n });\n }\n async track(params) {\n const { project_name, app_version } = this.instanceConfig;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo;\n if (params.custom_data) {\n params.custom_data = sanitizeCustomData(params.custom_data);\n }\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(this.instanceConfig.adapter),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n this.toSetCacheData(trackParams);\n }\n singleTrack(eventType, params) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n /**\n * @method 自定义用户id\n */\n setUser(id) {\n this.userId = id;\n this.addTask({\n type: \"cache_update\",\n fn: async () => {\n const cacheData = await this.cacheFn.get(CACHE_DATA_NAME);\n if (cacheData?.length) {\n const updatedData = cacheData.map((item) => ({\n ...item,\n user_id: id\n }));\n await this.cacheFn.set(CACHE_DATA_NAME, updatedData);\n }\n }\n });\n }\n /**\n * @method 模块view\n */\n frModuleView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"module_view\", params);\n }\n /**\n * @method 模块click\n */\n frModuleClick(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"module_click\", params);\n }\n /**\n * @method 登录事件\n */\n frLoginEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"login_event\", params);\n }\n /**\n * @method 生单事件\n */\n frOrderEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"order_event\", params);\n }\n /**\n * @method 自定义事件\n */\n frCustomEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"custom_event\", params);\n }\n /**\n * @method 日志事件\n */\n frLogEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"log_event\", params);\n }\n /**\n * @method 点击事件\n */\n frClickEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"click_event\", params);\n }\n /**\n * @method 自动收集pv事件\n */\n frAutoPageView() {\n window.history.pushState = overrideHistoryMethods(\"pushState\");\n window.history.replaceState = overrideHistoryMethods(\"replaceState\");\n this.nativePv();\n }\n /**\n * @method pv事件\n */\n frPageView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"page_view\", params);\n }\n /**\n * @method uv事件\n */\n frUserView() {\n this.lastUvReportTime = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n const interval = 60 * 60 * 1e3;\n const params = {\n event_name: \"user_view\"\n };\n this.singleTrack(\"user_view\", params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n if (now > this.lastUvReportTime + 24 * interval) {\n this.lastUvReportTime = now;\n this.singleTrack(\"user_view\", params);\n }\n }, interval);\n }\n /**\n * @method 页面销毁事件\n */\n frPageDestroy(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"page_destroy\", params);\n }\n /**\n * @method 手动立即上报缓存的数据\n */\n frReport() {\n this.reportCacheData();\n }\n init() {\n this.browserInfo = getBrowserAndDeviceInfo(this.instanceConfig.adapter);\n if (this.instanceConfig.adapter === \"web\" && window) {\n this.onBrowserClose();\n this.frUserView();\n if (this.pluginOptions.autoPv) {\n this.frAutoPageView();\n }\n }\n this.reportPrevData();\n this.loopReport();\n }\n};\nvar trackClass_default = FrTrack;\n\n// src/plugin/track/index.ts\nvar trackPlugin = {\n name: \"track\",\n defaultEnable: true,\n install: (sdkInstance, pluginOptions) => {\n try {\n if (!sdkInstance?.$cache || !sdkInstance?.$report) return;\n const defaultOptions = {\n frameType: \"js\",\n router: void 0,\n autoPv: true\n };\n if (pluginOptions) {\n Object.assign(defaultOptions, pluginOptions);\n }\n if (sdkInstance.$track) return;\n const frTrack = new trackClass_default(sdkInstance, defaultOptions);\n sdkInstance.$track = frTrack;\n frTrack.init();\n } catch (err) {\n logError(err, \"trackPlugin\\u521D\\u59CB\\u5316\\u5931\\u8D25\");\n }\n }\n};\n\n// src/index.ts\nvar instance = null;\nvar FrWebSDK = class {\n constructor() {\n this.isInit = false;\n this.config = defaultConfig;\n this.adapter = null;\n }\n init(userConfig) {\n if (this.isInit) {\n logWarn(\"SDK\\u5DF2\\u521D\\u59CB\\u5316\");\n return this;\n }\n this.config = { ...defaultConfig, ...userConfig };\n this.adapter = getAdapter(this.config.adapter);\n coreInit({\n config: this.config,\n adapter: this.adapter,\n instance: this\n });\n if (this.config.plugins) {\n this.config.plugins.forEach((plugin) => {\n if (plugin.type === \"track\") {\n trackPlugin.install(this, plugin.options);\n }\n });\n }\n this.isInit = true;\n return this;\n }\n};\nfunction getInstance() {\n if (!instance) {\n instance = new FrWebSDK();\n }\n return instance;\n}\nvar webSdk = getInstance();\nvar index_default = webSdk;\nexport {\n index_default as default\n};\n","import type { Options } from '../types';\n\nconst MAX_CACHE_SIZE = 15;\nconst MAX_CACHE_TIME = 300000;\nconst MAX_TIMEOUT = 10000;\n\nconst defaultConfig: Options = {\n project_name: '',\n report_url: '',\n app_version: '',\n adapter: 'web',\n maxCacheSize: MAX_CACHE_SIZE,\n maxCacheTime: MAX_CACHE_TIME,\n maxTimeout: MAX_TIMEOUT,\n isDebug: false,\n plugins: [\n {\n type: 'track',\n options: {\n autoPv: true\n // frameType: 'js',\n // router: null\n }\n }\n ]\n};\n\nexport { defaultConfig };\n","import * as localForage from 'localforage';\nimport { Cache } from '../../core';\nimport type { CacheName } from '../../core/types';\n\nclass WebCache extends Cache {\n constructor(options?: Record<string, unknown>) {\n super(options);\n }\n\n public async get<T>(name: CacheName) {\n const res = await localForage.getItem<T[]>(name);\n return res || [];\n }\n\n public async set<T>(name: CacheName, data: T | T[]): Promise<void> {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n await localForage.setItem(name, currentData);\n } else {\n await localForage.setItem(name, cacheData);\n }\n }\n\n public async remove(name: CacheName) {\n await localForage.removeItem(name);\n }\n\n public async clear(): Promise<void> {\n await localForage.clear();\n }\n}\n\nexport default WebCache;\n","import type { CacheName } from './types';\n\nexport abstract class Cache {\n protected options;\n constructor(options?: Record<string, unknown>) {\n if (options) {\n this.options = options;\n }\n }\n public abstract get<T>(name: CacheName): Promise<T[]> | T[];\n public abstract set<T>(name: CacheName, data: T | T[]): Promise<void> | void;\n public abstract remove(name: CacheName): void | Promise<void>;\n public abstract clear(): void | Promise<void>;\n}\n\n// 导出初始化方法(适配具体实现)\nexport function initCache<T extends Cache>(\n CacheClass: new (options: unknown) => T,\n options?: { [key: string]: unknown }\n): T {\n return new CacheClass(options);\n}\n\ntype CacheType = InstanceType<typeof Cache>;\n\nexport type { CacheType };\n","import type { ReportReq } from './types';\n\nexport abstract class Report {\n protected options;\n constructor(options: ReportReq) {\n this.options = options;\n }\n public abstract send<T>(data: T[]): Promise<unknown>;\n public abstract retry<T>(failedData: T[], callback?: () => void): void;\n}\n\n// 导出初始化方法(适配具体实现)\nexport function initReport<T extends Report>(\n ReportClass: new (options: unknown) => T,\n options: ReportReq\n): T {\n if (!options.url) {\n throw new Error('请传入上报地址url');\n }\n return new ReportClass(options);\n}\n\ntype ReportType = InstanceType<typeof Report>;\n\nexport type { ReportType };\n","import { initCache } from './cache';\nimport { initReport } from './report';\nconst coreInit = ({ config, adapter, instance }: any) => {\n // 初始化缓存\n instance.$cache = initCache(adapter.cache);\n // 初始化上报\n instance.$report = initReport(adapter.report, {\n url: config.report_url,\n timeout: config.maxTimeout\n });\n};\n\nexport { coreInit };\n","const EVENT_TYPES = [\n 'page_view',\n 'user_view',\n 'page_destroy',\n 'click_event',\n 'module_click',\n 'module_view',\n 'login_event',\n 'order_event',\n 'custom_event',\n 'log_event'\n] as const;\n\nconst CAN_AGGREGATION_TYPES = ['page_view', 'user_view'] as const;\n\nconst EVENT_KEYS = [\n 'project_name',\n 'event_type',\n 'event_name',\n 'event_time',\n 'user_id',\n 'app_version',\n 'user_timezone',\n 'device_type',\n 'user_agent',\n 'screen_resolution',\n 'custom_data',\n 'is_aggregation'\n] as const;\n\nconst CACHE_DATA_NAME = 'fr-track-cache-data';\nconst CACHE_ERR_DATA_NAME = 'fr-track-cache-err-data';\n\nexport { EVENT_TYPES, EVENT_KEYS, CAN_AGGREGATION_TYPES, CACHE_DATA_NAME, CACHE_ERR_DATA_NAME };\n","/**\n * 公共打印日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n * @param { boolean } isDebug 是否调试模式\n */\nconst logInfo = (message: unknown, title?: string, isDebug = false): void => {\n if (!isDebug) return;\n const logTitle = title ? `[Fr-track log ${title}]` : '[Fr-track log]';\n console.log(`${logTitle}:`, message);\n};\n\n/**\n * 公共打印警告日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n */\nconst logWarn = (message: unknown, title?: string): void => {\n const logTitle = title ? `[Fr-track warning ${title}]` : '[Fr-track warning]';\n console.warn(`${logTitle}:`, message);\n};\n\n/**\n * 公共打印异常日志方法\n * @param { string } title 日志标题信息\n * @param { string } message 日志内容信息\n */\nconst logError = (message: unknown, title?: string): void => {\n const logTitle = title ? `[Fr-track error ${title}]` : '[Fr-track error]';\n console.error(`${logTitle}:`, message);\n};\n\n/**\n * 获取变量类型\n * @param { unknown } variable 变量\n * @return { string } 类型字符串\n */\nconst getVariableType = (variable: unknown): string => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\n\n/**\n * 手动实现 UUID v4\n * @returns { string } uuid\n */\nconst generateFallbackUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * 生成uuid\n * @returns { string } uuid\n */\nconst generateUserId = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // 降级方案\n return generateFallbackUUID();\n};\n\n/**\n * 重写history的pushState和replaceState\n */\nconst overrideHistoryMethods = <T extends keyof History>(type: T): any => {\n const originalMethod = history[type];\n return function (this: any, ...args: any) {\n const res = originalMethod.apply(this, args);\n const e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\n\n/**\n * 获取用户时区\n */\nconst getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n logWarn(error, '无法获取时区名称,使用偏移量推算:');\n const offset = new Date().getTimezoneOffset();\n if (offset >= 0) {\n return `西${offset / 60}区`;\n } else {\n return `东${-offset / 60}区`;\n }\n }\n};\n\n/**\n * 触发事件后,延迟指定时间再执行函数;若延迟内再次触发,重新计时\n * @param fn 要防抖的目标函数(支持任意参数、任意返回值,保留this指向)\n * @param delay 防抖延迟时间,默认800毫秒\n * @param immediate 是否立即执行(true:首次触发立即执行,后续延迟内触发重新计时;false:延迟后执行)\n * @returns 包装后的防抖函数(与原函数参数一致,无返回值)\n */\nexport function debounce<F extends (...args: any[]) => any>(\n fn: F,\n delay: number = 800,\n immediate: boolean = false\n): (...args: Parameters<F>) => void {\n let timer: number | null = null;\n let flag = false;\n\n return function (this: ThisParameterType<F>, ...args: Parameters<F>) {\n if (immediate && !flag) {\n fn.apply(this, args);\n }\n\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n\n flag = true;\n timer = setTimeout(() => {\n fn.apply(this, args);\n flag = false;\n }, delay);\n };\n}\n\n/**\n * 递归处理自定义数据,对字符串进行HTML标签过滤,对对象递归处理\n * @param data 自定义数据对象\n * @returns 处理后的自定义数据对象\n */\nconst sanitizeCustomData = (data: Record<string, unknown>) => {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === 'string') {\n sanitized[key] = value.replace(/<[^>]*>/g, '');\n } else if (getVariableType(value) === 'object') {\n sanitized[key] = sanitizeCustomData(value as Record<string, unknown>);\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n};\n\nexport {\n logInfo,\n logWarn,\n logError,\n getVariableType,\n generateUserId,\n overrideHistoryMethods,\n getUserTimeZone,\n sanitizeCustomData\n};\n","import { EVENT_TYPES, EVENT_KEYS } from '../static/constant';\nimport { getVariableType, logWarn } from './utils';\nimport type { EventsType } from '../types';\n\n/**\n * @method 校验事件类型\n */\nexport function validateEventType(eventType?: unknown): boolean {\n return typeof eventType === 'string' && EVENT_TYPES.includes(eventType as EventsType);\n}\n\n/**\n * @method 校验字段\n */\nexport function validateEventKey(params?: unknown): boolean {\n const type = getVariableType(params);\n if (!params || type !== 'object') {\n logWarn('Event params must be an object');\n return false;\n }\n const keys = Object.keys(params as Record<string, unknown>);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key as (typeof EVENT_KEYS)[number])) {\n logWarn(`Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n","import { validateEventType, validateEventKey } from '../utils/validator';\nimport { logWarn, logError } from '../utils/utils';\n// TODO: 解耦\nimport type { TrackEventItem } from '../plugin/track/types';\n\n/**\n * 清洗上报数据\n * @param { array } rawData 待清洗的原数据\n * @returns { array } 清洗后的数据\n */\nconst cleanTrackData = (\n rawData: TrackEventItem[]\n): {\n type: 'success' | 'fail';\n errReason?: string;\n data: TrackEventItem[];\n} => {\n try {\n // 过滤非法的事件类型、非法的时间日期\n const tempIds = new Set();\n const resultData = rawData.filter(rawItem => {\n // 缺失必要字段\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n\n // event_type校验不通过\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n logWarn('事件类型不合法');\n return false;\n }\n\n // event_time校验不通过\n const eventTime = rawItem.event_time;\n const minDateTime = new Date('2025-12-01').getTime();\n if (!eventTime || typeof eventTime !== 'number' || eventTime < minDateTime) {\n return false;\n }\n\n // 相同时间戳相同事件已存在\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: 'success',\n data: resultData\n };\n } catch (error) {\n logError(error, '清洗失败');\n const errReason = (error as Error).message || 'Unknown error';\n return {\n type: 'fail',\n errReason: errReason,\n data: rawData\n };\n }\n};\n\nexport { cleanTrackData };\n","import { CAN_AGGREGATION_TYPES } from '../static/constant';\nimport { logError } from '../utils/utils';\n// TODO: 解耦\nimport type { TrackEventItem } from '../plugin/track/types';\n\n/**\n * 聚合数据\n * @param { array } rawData 需要聚合的原数据\n * @returns { array } 聚合后的数据\n */\nconst aggregationData = (rawData: TrackEventItem[]): TrackEventItem[] => {\n try {\n const resultData: TrackEventItem[] = [];\n for (let i = 0; i < rawData.length; i++) {\n const rawItem = rawData[i];\n if (!rawItem) continue;\n const item = { ...rawItem };\n /**\n * 以\"天\"为维度,将以下事件进行聚合\n * pv、uv、自定义指定需要聚合的数据\n */\n if (\n CAN_AGGREGATION_TYPES.includes(item.event_type as (typeof CAN_AGGREGATION_TYPES)[number]) ||\n item.is_aggregation\n ) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time as number).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n r =>\n r.event_time === currentDate &&\n r.event_type === item.event_type &&\n r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n // 如果是uv,后面的userId覆盖之前\n if (item.event_type === 'user_view') {\n resultItem.user_id = item.user_id;\n }\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n logError(error, '聚合失败');\n // 聚合失败则直接上报原数据\n return rawData;\n }\n};\n\nexport { aggregationData };\n","import { Report } from '../../core';\nimport type { ReportReq } from '../../core/types';\n\nclass WebReport extends Report {\n constructor(options: ReportReq) {\n super(options);\n }\n\n public async retry<T>(failedData: T[], callback?: () => void, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3000);\n }\n }\n\n public async send<T>(data: T[]) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if ('sendBeacon' in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append('data', jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', url, true);\n xhr.timeout = timeout;\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = () => {\n resolve(xhr.response);\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n }\n}\n\nexport default WebReport;\n","import { Cache } from '../../core';\nimport type { CacheName } from '../../core/types';\n\nclass WxCache extends Cache {\n constructor(options?: Record<string, unknown>) {\n super(options);\n }\n\n public async get(name: CacheName) {\n const res = wx.getStorageSync(name);\n return res || [];\n }\n\n public async set<T>(name: CacheName, data: T | T[]): Promise<void> {\n const currentData = await this.get(name);\n const cacheData = Array.isArray(data) ? data : [data];\n if (currentData.length) {\n currentData.push(...cacheData);\n wx.setStorageSync(name, currentData);\n } else {\n wx.setStorageSync(name, cacheData);\n }\n }\n\n public async remove(name: CacheName) {\n wx.removeStorageSync(name);\n }\n\n public async clear(): Promise<void> {\n wx.clearStorageSync();\n }\n}\n\nexport default WxCache;\n","import { Report } from '../../core';\nimport type { ReportReq } from '../../core/types';\n\nclass WxReport extends Report {\n constructor(options: ReportReq) {\n super(options);\n }\n\n public async retry<T>(failedData: T[], callback?: () => void, retryCount = 1) {\n if (!failedData?.length) return;\n if (retryCount >= 3) {\n if (!callback) return;\n callback();\n return;\n }\n try {\n await this.send(failedData);\n } catch (err) {\n setTimeout(() => {\n this.retry(failedData, callback, retryCount + 1);\n }, 3000);\n }\n }\n\n public async send<T>(data: T[]) {\n const { url, timeout } = this.options;\n return new Promise((resolve, reject) => {\n if (wx && wx.request) {\n wx.request({\n url,\n method: 'POST',\n data: data,\n timeout,\n success: function success(res: any) {\n resolve(res);\n },\n fail: function fail(err: any) {\n reject(err);\n }\n });\n } else {\n reject();\n }\n });\n }\n}\n\nexport default WxReport;\n","import WebCache from './web/cache';\nimport WebReport from './web/report';\nimport WxCache from './wx/cache';\nimport WxReport from './wx/report';\n\n/**\n * 获取运行环境\n */\nconst getEnv = () => {\n const isMiniProgram = wx && typeof wx.getSystemInfoSync === 'function';\n return isMiniProgram ? 'miniProgram' : 'web';\n};\n\n/**\n * 获取对应环境的配置w\n */\nconst getAdapter = (configEnv: string) => {\n const env = configEnv || getEnv();\n if (env === 'miniProgram') {\n return {\n env: 'miniProgram',\n cache: WxCache,\n report: WxReport\n };\n }\n return {\n env: 'web',\n cache: WebCache,\n report: WebReport\n };\n};\n\nexport { getAdapter };\n","import { generateUserId } from '../utils/utils';\n\n/**\n * 获取user_id\n */\nconst getUserId = (): string => {\n try {\n // 查看缓存是否有已生成的uuid\n const track_uuid = localStorage.getItem('track_uuid');\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem('track_uuid', uuid);\n return uuid;\n } catch (e) {\n return generateUserId();\n }\n};\n\nexport { getUserId };\n","import Browser from 'bowser';\nimport { logWarn } from './utils';\nimport type { BrowserInfoType, AdapterType } from '../types';\n\n/**\n * 获取浏览器及设备信息\n * @returns { object | null }\n */\nconst getBrowserAndDeviceInfo = (adapter: AdapterType): BrowserInfoType => {\n const defRes = {\n browserName: 'unknown',\n browserVersion: 'unknown',\n osName: 'unknown',\n osVersion: 'unknown',\n platformName: 'unknown'\n };\n try {\n if (adapter === 'web') {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || 'unknown',\n browserVersion: browser.version || 'unknown',\n osName: os.name || 'unknown',\n osVersion: os.version || 'unknown',\n platformName: platform.type || 'unknown'\n };\n } else {\n if (!wx) return defRes;\n const info = wx.getDeviceInfo();\n const { brand, model, platform, system } = info;\n return {\n browserName: brand || 'miniProgram',\n browserVersion: model || 'unknown',\n osName: system || 'unknown',\n osVersion: system || 'unknown',\n platformName: platform || 'unknown'\n };\n }\n } catch (error) {\n logWarn(error);\n return defRes;\n }\n};\n\n/**\n * 获取设备分辨率\n * @return { string } 分辨率信息\n */\nconst getDeviceResolution = (adapter: AdapterType): string => {\n if (adapter === 'web') {\n if (!window) return 'unknown';\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n } else {\n if (!wx) return 'unknown';\n const screen = wx.getWindowInfo();\n return `${screen.screenWidth}x${screen.screenHeight}`;\n }\n};\n\nexport { getBrowserAndDeviceInfo, getDeviceResolution };\n","import { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from '../../static/constant';\nimport { getUserId } from '../../utils/uuid';\nimport { cleanTrackData, aggregationData } from '../../core';\nimport { getBrowserAndDeviceInfo, getDeviceResolution } from '../../utils/browser';\nimport {\n overrideHistoryMethods,\n getUserTimeZone,\n logInfo,\n logWarn,\n logError,\n sanitizeCustomData,\n debounce\n} from '../../utils/utils';\n\nimport type { BrowserInfoType, TrackInstance, TrackPluginOptions } from '../types';\nimport type { TrackEventItem, TrackParams, CustomData, EventsType, TrackTask } from './types';\nimport type { Cache } from '../../core/cache';\nimport type { Report } from '../../core/report';\nimport type { Options } from '../../types';\n\nclass FrTrack<T = TrackEventItem> {\n private userId = getUserId();\n private timer: number | null = null;\n private uvTimer: number | null = null;\n private lastUvReportTime: number = 0;\n private browserInfo: BrowserInfoType | null = null;\n private pluginOptions: TrackPluginOptions;\n private taskQueue: TrackTask[] = [];\n private isProcessing = false;\n private cacheFn: Cache;\n private reportFn: Report;\n private instanceConfig: Options;\n private debouncePv: (key: string) => void;\n\n constructor(instance: TrackInstance, pluginOptions: TrackPluginOptions) {\n if (!instance) {\n throw new Error('请传入SDk实例');\n }\n this.cacheFn = instance.$cache;\n this.reportFn = instance.$report;\n this.instanceConfig = instance.config;\n this.pluginOptions = pluginOptions;\n this.debouncePv = debounce((type: string) => {\n // 初次加载手动执行\n const href = window.location.href || '';\n logInfo(type, '事件触发', this.instanceConfig.isDebug);\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: 'unknown',\n count: 1\n }\n };\n this.singleTrack('page_view', params);\n }, 300);\n }\n\n /* 执行异步队列任务 */\n private async processQueue() {\n // 如果正在执行任务,或队列为空 直接返回\n if (this.isProcessing || this.taskQueue.length === 0) return;\n // 开始执行\n this.isProcessing = true;\n // 取出队列第一个任务\n const currentTask = this.taskQueue.shift()!;\n try {\n await currentTask.fn();\n logInfo(`✅ 任务执行成功:${currentTask.desc}`, '', this.instanceConfig.isDebug);\n } catch (err) {\n logInfo(err, `❌ 任务执行失败:${currentTask.desc}`, this.instanceConfig.isDebug);\n } finally {\n this.isProcessing = false;\n this.processQueue();\n }\n }\n\n /* 异步队列添加任务 */\n private addTask<T>(task: TrackTask<T>) {\n const taskWithDesc = {\n desc: `${task.type} 任务`,\n ...task\n };\n this.taskQueue.push(taskWithDesc);\n // 添加后启动任务\n this.processQueue();\n }\n\n /* 上报缓存数据 */\n private async reportCacheData() {\n this.addTask({\n type: 'report_send',\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (!cacheData?.length) return;\n // 清洗\n const cleanInfo = cleanTrackData(cacheData as TrackEventItem[]);\n if (cleanInfo.type !== 'success') {\n logWarn(cleanInfo.errReason);\n // TODO: 上报失败原因及数据 清空缓存\n } else {\n // 聚合\n const result = aggregationData(cleanInfo.data);\n logInfo(result, '上报数据', this.instanceConfig.isDebug);\n if (result?.length) {\n this.reportFn.send<T>(result as T[]).catch(err => {\n logError(err, '上报失败数据异常');\n this.cacheFn.set(CACHE_ERR_DATA_NAME, result);\n });\n }\n }\n // 不管上报是否成功,删除缓存\n await this.cacheFn.remove(CACHE_DATA_NAME);\n }\n });\n }\n\n /* 上报缓存的失败数据 */\n private async reportErrCacheData() {\n this.addTask({\n type: 'report_send',\n fn: async () => {\n if (!this.cacheFn || !this.reportFn) return;\n const cacheData = await this.cacheFn.get<T>(CACHE_ERR_DATA_NAME);\n if (!cacheData?.length) return;\n this.reportFn.send<T>(cacheData).catch(err => {\n logError(err, '上报失败数据异常');\n });\n await this.cacheFn.remove(CACHE_ERR_DATA_NAME);\n }\n });\n }\n\n private reportPrevData = () => {\n this.reportErrCacheData();\n };\n\n /* 定时循环上报 */\n private loopReport() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.timer = setInterval(() => {\n this.reportCacheData();\n }, this.instanceConfig.maxCacheTime);\n }\n\n /* 浏览器关闭时触发 */\n private onBrowserClose() {\n /**\n * 浏览器环境\n */\n window.addEventListener('beforeunload', () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.reportCacheData();\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState !== 'visible') {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.reportCacheData();\n } else {\n // 重启定时器\n this.loopReport();\n }\n });\n }\n\n private nativePv() {\n const methodsList = ['popstate', 'hashchange', 'pushState', 'replaceState'];\n // 初始化上报一次\n this.debouncePv('初次上报');\n methodsList.forEach(method => {\n window.addEventListener(method, () => {\n this.debouncePv(method);\n });\n });\n }\n\n // private vuePv() {\n // if (!this.pluginOptions.router) {\n // throw new Error('请传入路由实例');\n // }\n // const router = this.pluginOptions.router as any;\n // router.afterEach((to: any) => {\n // const params = {\n // event_name: to.path,\n // custom_data: {\n // page_url: to.fullPath || '--',\n // page_name: to.name || '--',\n // count: 1\n // }\n // };\n // this.singleTrack('page_view', params);\n // });\n // }\n\n private async toSetCacheData(params: T) {\n logInfo(params, '设置缓存数据', this.instanceConfig.isDebug);\n this.addTask({\n type: 'cache_set',\n fn: async () => {\n if (!this.cacheFn) return;\n const { maxCacheSize } = this.instanceConfig;\n const res = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (res?.length >= maxCacheSize) {\n this.reportCacheData();\n // 上报成功后, 再设置缓存\n this.toSetCacheData(params);\n } else {\n await this.cacheFn.set<T>(CACHE_DATA_NAME, params);\n }\n }\n });\n }\n\n private async track(params: TrackParams) {\n const { project_name, app_version } = this.instanceConfig;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo!;\n if (params.custom_data) {\n params.custom_data = sanitizeCustomData(params.custom_data);\n }\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(this.instanceConfig.adapter),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n this.toSetCacheData(trackParams);\n }\n\n private singleTrack<T extends Omit<TrackParams, 'event_type'>>(\n eventType: EventsType,\n params: T & (keyof T extends keyof Omit<TrackParams, 'event_type'> ? T : never)\n ) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n\n /**\n * @method 自定义用户id\n */\n public setUser(id: string) {\n this.userId = id;\n // 更新userId\n this.addTask({\n type: 'cache_update',\n fn: async () => {\n const cacheData = await this.cacheFn.get<T>(CACHE_DATA_NAME);\n if (cacheData?.length) {\n const updatedData = cacheData.map(item => ({\n ...item,\n user_id: id\n }));\n await this.cacheFn.set(CACHE_DATA_NAME, updatedData);\n }\n }\n });\n }\n\n /**\n * @method 模块view\n */\n public frModuleView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('module_view', params);\n }\n\n /**\n * @method 模块click\n */\n public frModuleClick(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('module_click', params);\n }\n\n /**\n * @method 登录事件\n */\n public frLoginEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('login_event', params);\n }\n\n /**\n * @method 生单事件\n */\n public frOrderEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('order_event', params);\n }\n\n /**\n * @method 自定义事件\n */\n public frCustomEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('custom_event', params);\n }\n\n /**\n * @method 日志事件\n */\n public frLogEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('log_event', params);\n }\n\n /**\n * @method 点击事件\n */\n public frClickEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('click_event', params);\n }\n\n /**\n * @method 自动收集pv事件\n */\n private frAutoPageView() {\n // if (this.pluginOptions.frameType === 'js') {\n window.history.pushState = overrideHistoryMethods('pushState');\n window.history.replaceState = overrideHistoryMethods('replaceState');\n this.nativePv();\n // } else if (this.pluginOptions.frameType === 'vue') {\n // this.vuePv()\n // }\n }\n\n /**\n * @method pv事件\n */\n public frPageView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('page_view', params);\n }\n\n /**\n * @method uv事件\n */\n public frUserView() {\n this.lastUvReportTime = new Date().setHours(0, 0, 0, 0);\n // 一小时检查一次\n const interval = 60 * 60 * 1000;\n const params = {\n event_name: 'user_view'\n };\n this.singleTrack('user_view', params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = new Date().setHours(0, 0, 0, 0);\n if (now > this.lastUvReportTime + 24 * interval) {\n // 超过24小时,再次上报uv\n // 更新上报时间\n this.lastUvReportTime = now;\n this.singleTrack('user_view', params);\n }\n }, interval);\n }\n\n /**\n * @method 页面销毁事件\n */\n public frPageDestroy(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('page_destroy', params);\n }\n\n /**\n * @method 手动立即上报缓存的数据\n */\n public frReport() {\n this.reportCacheData();\n }\n\n public init() {\n /**\n * 获取浏览器信息\n */\n this.browserInfo = getBrowserAndDeviceInfo(this.instanceConfig.adapter);\n /**\n * 浏览器环境下\n */\n if (this.instanceConfig.adapter === 'web' && window) {\n /**\n * 监听浏览器关闭事件,进行上报\n */\n this.onBrowserClose();\n\n /**\n * 统计uv\n */\n this.frUserView();\n\n /**\n * 判断是否监听pv事件\n */\n if (this.pluginOptions.autoPv) {\n this.frAutoPageView();\n }\n }\n\n /**\n * 1. 判断缓存是否有没有传输的数据\n * 2. 判断上次是否有失败的数据存储在缓存中\n */\n this.reportPrevData();\n /**\n * 3. 开启定时器轮询,达到时间阈值进行上报\n */\n this.loopReport();\n }\n}\n\nexport default FrTrack;\n","import FrTrack from './trackClass';\n\nimport type { BasePlugin, TrackPluginOptions } from '../types';\nimport { logError } from '../../utils/utils';\n\nconst trackPlugin: BasePlugin<TrackPluginOptions> = {\n name: 'track',\n defaultEnable: true,\n install: (sdkInstance, pluginOptions) => {\n try {\n if (!sdkInstance?.$cache || !sdkInstance?.$report) return;\n const defaultOptions: TrackPluginOptions = {\n frameType: 'js',\n router: undefined,\n autoPv: true\n };\n if (pluginOptions) {\n Object.assign(defaultOptions, pluginOptions);\n }\n\n if (sdkInstance.$track) return;\n const frTrack = new FrTrack(sdkInstance, defaultOptions);\n sdkInstance.$track = frTrack;\n frTrack.init();\n } catch (err) {\n logError(err, 'trackPlugin初始化失败');\n }\n }\n};\n\nexport { trackPlugin };\n","// src/index.js\nimport { defaultConfig } from './config';\nimport { getAdapter } from './adapter/index';\nimport { coreInit } from './core/index.js';\nimport { logWarn } from './utils/utils';\nimport { Cache, Report } from './core';\nimport { trackPlugin } from './plugin/track';\nimport FrTrack from './plugin/track/trackClass';\nimport type { Options, CustomOptions } from './types';\n\nlet instance: InstanceType<typeof FrWebSDK> | null = null;\n\nclass FrWebSDK {\n private adapter: any;\n public isInit: boolean;\n public config: Options;\n public $cache!: InstanceType<typeof Cache>;\n public $report!: InstanceType<typeof Report>;\n public $track!: InstanceType<typeof FrTrack>;\n\n constructor() {\n this.isInit = false;\n this.config = defaultConfig;\n this.adapter = null;\n }\n\n init(userConfig: CustomOptions) {\n if (this.isInit) {\n logWarn('SDK已初始化');\n return this;\n }\n // 合并配置\n this.config = { ...defaultConfig, ...userConfig };\n // 获取适配器\n this.adapter = getAdapter(this.config.adapter);\n // 核心初始化\n coreInit({\n config: this.config,\n adapter: this.adapter,\n instance: this\n });\n // 获取用户插件\n if (this.config.plugins) {\n this.config.plugins.forEach(plugin => {\n if (plugin.type === 'track') {\n trackPlugin.install(this, plugin.options);\n }\n });\n }\n\n this.isInit = true;\n\n return this;\n }\n}\n\n// 获取单例\nfunction getInstance() {\n if (!instance) {\n instance = new FrWebSDK();\n }\n return instance;\n}\n\ntype TrackInstance = InstanceType<typeof FrWebSDK>;\n\nconst webSdk = getInstance();\nexport default webSdk;\nexport type { TrackInstance };\n"]}
|