react-track-hooks 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -1,10 +1,290 @@
1
1
  # react-track-hooks
2
2
 
3
- React 埋点 Hooks 库,支持点击埋点、曝光埋点、页面停留时长埋点,内置失败重试机制。
3
+ [![npm version](https://img.shields.io/npm/v/react-track-hooks.svg)](https://www.npmjs.com/package/react-track-hooks)
4
+ [![license](https://img.shields.io/npm/l/react-track-hooks.svg)](https://github.com/PassingTraveller111/react-track-hooks/blob/main/LICENSE)
4
5
 
5
- ## 安装
6
+ 一个轻量、易用的 React 埋点 Hooks 库,支持点击埋点、曝光埋点、页面停留时长埋点、自定义埋点,内置失败重试机制,适配 React/Next.js 项目。
7
+
8
+ ## 特性
9
+ - 🚀 开箱即用:提供常用埋点场景的 Hooks,无需重复封装
10
+ - 🔄 失败重试:内置 localStorage 缓存 + 指数退避重试,确保埋点不丢失
11
+ - 🎯 精准控制:曝光埋点支持可见比例、单次触发配置
12
+ - ⚡ 轻量无依赖:体积小,不引入额外冗余依赖
13
+ - 📝 完整 TypeScript 类型:提供完善的类型声明,开发更友好
14
+ - 🌐 框架适配:兼容 React 16+、Next.js(App Router/Pages Router)
6
15
 
16
+ ## 安装
7
17
  ```bash
18
+ # npm
8
19
  npm install react-track-hooks --save
9
- # 或
10
- yarn add react-track-hooks
20
+
21
+ # yarn
22
+ yarn add react-track-hooks
23
+
24
+ # pnpm
25
+ pnpm add react-track-hooks
26
+ ```
27
+
28
+
29
+ ## 快速开始
30
+
31
+ ### 1. 全局配置(项目入口)
32
+ 在 React/Next.js 项目的入口文件(如 `App.tsx`/`layout.tsx`)中配置全局参数:
33
+
34
+ #### React 项目
35
+ ```tsx
36
+ import { setTrackGlobalConfig, useTrackRetryListener } from 'react-track-hooks';
37
+
38
+ function App() {
39
+ // 全局埋点配置(只执行一次)
40
+ setTrackGlobalConfig({
41
+ trackUrl: 'https://api.yourdomain.com/track', // 替换为你的埋点接口地址
42
+ enable: process.env.NODE_ENV === 'production', // 生产环境开启
43
+ retryConfig: {
44
+ maxRetryTimes: 5, // 最大重试次数
45
+ initialDelay: 1000, // 初始重试延迟(ms)
46
+ delayMultiplier: 2, // 延迟倍数(指数退避)
47
+ },
48
+ });
49
+
50
+ // 启用失败埋点自动重试监听(全局只执行一次)
51
+ useTrackRetryListener();
52
+
53
+ return <>{/* 你的应用内容 */}</>;
54
+ }
55
+ ```
56
+
57
+ #### Next.js App Router
58
+ ```tsx
59
+ // app/components/TrackProvider.tsx (客户端组件)
60
+ 'use client';
61
+ import { setTrackGlobalConfig, useTrackRetryListener } from 'react-track-hooks';
62
+
63
+ export const TrackProvider = () => {
64
+ setTrackGlobalConfig({
65
+ trackUrl: 'https://api.yourdomain.com/track',
66
+ enable: process.env.NODE_ENV === 'production',
67
+ });
68
+
69
+ useTrackRetryListener();
70
+ return null;
71
+ };
72
+
73
+ // app/layout.tsx (根布局)
74
+ import { TrackProvider } from './components/TrackProvider';
75
+
76
+ export default function RootLayout({ children }) {
77
+ return (
78
+ <html>
79
+ <body>
80
+ <TrackProvider />
81
+ {children}
82
+ </body>
83
+ </html>
84
+ );
85
+ }
86
+ ```
87
+
88
+ ### 2. 业务组件中使用埋点 Hooks
89
+
90
+ #### 点击埋点
91
+ ```tsx
92
+ import { useTrackClick } from 'react-track-hooks';
93
+
94
+ function ButtonComponent() {
95
+ // 初始化点击埋点
96
+ const handleClick = useTrackClick(
97
+ 'button_click', // 埋点事件名
98
+ { button_type: 'primary', page: 'home' }, // 基础参数
99
+ { enable: true } // 单个埋点开关(可选)
100
+ );
101
+
102
+ return (
103
+ // 点击时可追加动态参数
104
+ <button onClick={(e) => handleClick(e, { click_pos: 'top' })}>
105
+ 测试点击埋点
106
+ </button>
107
+ );
108
+ }
109
+ ```
110
+
111
+ #### 曝光埋点
112
+ ```tsx
113
+ import { useTrackExposure } from 'react-track-hooks';
114
+
115
+ function CardComponent() {
116
+ // 初始化曝光埋点(返回 ref 绑定到目标元素)
117
+ const exposureRef = useTrackExposure(
118
+ 'card_exposure', // 埋点事件名
119
+ { card_id: '123456', card_type: 'product' }, // 基础参数
120
+ {
121
+ exposureThreshold: 0.8, // 元素可见比例≥80%时触发
122
+ exposureOnce: true, // 仅触发一次曝光
123
+ }
124
+ );
125
+
126
+ return (
127
+ <div ref={exposureRef} style={{ width: '300px', height: '200px' }}>
128
+ 这是一个曝光埋点卡片
129
+ </div>
130
+ );
131
+ }
132
+ ```
133
+
134
+ #### 页面停留时长埋点
135
+ ```tsx
136
+ import { useTrackPageStay } from 'react-track-hooks';
137
+
138
+ function HomePage() {
139
+ // 初始化页面停留埋点(组件挂载时自动监听)
140
+ useTrackPageStay(
141
+ 'page_stay', // 埋点事件名
142
+ { page_path: '/home', platform: 'web' } // 基础参数
143
+ );
144
+
145
+ return <div>首页内容</div>;
146
+ }
147
+ ```
148
+
149
+ #### 自定义埋点
150
+ ```tsx
151
+ import { useTrackCustom } from 'react-track-hooks';
152
+
153
+ function FormComponent() {
154
+ // 初始化自定义埋点
155
+ const triggerCustomTrack = useTrackCustom(
156
+ 'form_submit', // 埋点事件名
157
+ { form_id: 'login_form' } // 基础参数
158
+ );
159
+
160
+ const handleSubmit = () => {
161
+ // 手动触发自定义埋点,可追加动态参数
162
+ triggerCustomTrack({ submit_time: Date.now(), status: 'success' });
163
+ };
164
+
165
+ return <button onClick={handleSubmit}>提交表单</button>;
166
+ }
167
+ ```
168
+
169
+ ### 3. 手动重试失败埋点
170
+ ```tsx
171
+ import { retryFailedTracks } from 'react-track-hooks';
172
+
173
+ function RetryButton() {
174
+ const handleRetry = async () => {
175
+ // 手动触发失败埋点重试(force: true 强制立即重试)
176
+ const success = await retryFailedTracks(true);
177
+ if (success) {
178
+ alert('失败埋点重试完成!');
179
+ }
180
+ };
181
+
182
+ return <button onClick={handleRetry}>重试失败埋点</button>;
183
+ }
184
+ ```
185
+
186
+ ## API 文档
187
+
188
+ ### 全局配置
189
+ #### setTrackGlobalConfig(config: TrackGlobalConfig)
190
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
191
+ |------|------|------|--------|------|
192
+ | trackUrl | string | 是 | - | 埋点上报接口地址 |
193
+ | enable | boolean | 否 | true | 是否开启埋点 |
194
+ | retryConfig | RetryConfig | 否 | 见下方 | 重试配置 |
195
+
196
+ #### RetryConfig 类型
197
+ | 参数 | 类型 | 默认值 | 说明 |
198
+ |------|------|--------|------|
199
+ | maxRetryTimes | number | 3 | 最大重试次数 |
200
+ | initialDelay | number | 1000 | 初始重试延迟(ms) |
201
+ | delayMultiplier | number | 2 | 延迟倍数(指数退避) |
202
+
203
+ ### Hooks
204
+ #### useTrackRetryListener()
205
+ - 作用:全局监听页面状态(初始化/切回标签页),自动重试失败埋点
206
+ - 注意:全局只需调用一次,建议放在项目入口
207
+
208
+ #### useTrackClick(eventName, baseParams?, config?)
209
+ | 参数 | 类型 | 必填 | 说明 |
210
+ |------|------|------|------|
211
+ | eventName | string | 是 | 埋点事件名 |
212
+ | baseParams | TrackParams | 否 | 基础业务参数 |
213
+ | config | TrackItemConfig | 否 | 单个埋点配置 |
214
+ | 返回值 | (e?, extraParams?) => void | - | 点击事件处理函数,可追加动态参数 |
215
+
216
+ #### useTrackExposure(eventName, baseParams?, config?)
217
+ | 参数 | 类型 | 必填 | 说明 |
218
+ |------|------|------|------|
219
+ | eventName | string | 是 | 埋点事件名 |
220
+ | baseParams | TrackParams | 否 | 基础业务参数 |
221
+ | config | TrackExposureConfig | 否 | 曝光配置 |
222
+ | 返回值 | React.RefObject<HTMLElement> | - | 需绑定到目标元素的 ref |
223
+
224
+ #### TrackExposureConfig 类型
225
+ | 参数 | 类型 | 默认值 | 说明 |
226
+ |------|------|--------|------|
227
+ | exposureThreshold | number | 0.5 | 触发曝光的可见比例(0-1) |
228
+ | exposureOnce | boolean | true | 是否仅触发一次曝光 |
229
+
230
+ #### useTrackPageStay(eventName, baseParams?, config?)
231
+ | 参数 | 类型 | 必填 | 说明 |
232
+ |------|------|------|------|
233
+ | eventName | string | 是 | 埋点事件名 |
234
+ | baseParams | TrackParams | 否 | 基础业务参数 |
235
+ | config | TrackItemConfig | 否 | 单个埋点配置 |
236
+
237
+ #### useTrackCustom(eventName, baseParams?, config?)
238
+ | 参数 | 类型 | 必填 | 说明 |
239
+ |------|------|------|------|
240
+ | eventName | string | 是 | 埋点事件名 |
241
+ | baseParams | TrackParams | 否 | 基础业务参数 |
242
+ | config | TrackItemConfig | 否 | 单个埋点配置 |
243
+ | 返回值 | (extraParams?) => Promise<void> | - | 手动触发埋点的函数 |
244
+
245
+ ### 工具函数
246
+ #### retryFailedTracks(force?: boolean): Promise<boolean>
247
+ | 参数 | 类型 | 默认值 | 说明 |
248
+ |------|------|--------|------|
249
+ | force | boolean | false | 是否强制立即重试(忽略退避时间) |
250
+ | 返回值 | Promise<boolean> | - | 重试是否成功 |
251
+
252
+ ### 通用类型
253
+ #### TrackParams
254
+ ```ts
255
+ interface TrackParams {
256
+ [key: string]: any; // 自定义业务参数
257
+ }
258
+ ```
259
+
260
+ #### TrackItemConfig
261
+ ```ts
262
+ interface TrackItemConfig {
263
+ enable?: boolean; // 单个埋点开关,覆盖全局配置
264
+ }
265
+ ```
266
+
267
+ ## 适配说明
268
+ - React 版本:支持 React 16.8+(Hooks 最低兼容版本)
269
+ - Next.js 版本:支持 Next.js 13+(App Router/Pages Router)
270
+ - 浏览器兼容:支持所有现代浏览器,IE 需自行兼容 Promise/IntersectionObserver
271
+
272
+ ## 常见问题
273
+ ### Q1: TS7016 类型声明找不到?
274
+ A: 确保安装的是最新版本,若仍报错,可在项目中添加类型声明文件:
275
+ ```ts
276
+ // types/react-track-hooks.d.ts
277
+ declare module 'react-track-hooks';
278
+ ```
279
+
280
+ ### Q2: 曝光埋点不触发?
281
+ A: 检查:
282
+ 1. 元素是否绑定 ref;
283
+ 2. 可见比例是否达到 `exposureThreshold`;
284
+ 3. 元素是否为固定定位/脱离文档流(需确保 IntersectionObserver 能检测到)。
285
+
286
+ ### Q3: 埋点上报失败不重试?
287
+ A: 确保已调用 `useTrackRetryListener()`,且重试次数未超过 `maxRetryTimes`。
288
+
289
+ ## 许可证
290
+ MIT © [liujingmin](https://github.com/PassingTraveller111)
package/dist/index.cjs.js CHANGED
@@ -161,7 +161,6 @@ const useTrack = (params, config = {}) => {
161
161
  }, [mergedConfig]);
162
162
  return { triggerTrack };
163
163
  };
164
- // 以下 Hooks 代码无需修改(useTrackClick/useTrackExposure 等),因为它们基于 useTrack 封装
165
164
  const useTrackClick = (eventName, customParams = {}, config = {}) => {
166
165
  const { triggerTrack } = useTrack({ eventName, type: exports.TrackType.CLICK, ...customParams }, config);
167
166
  const handleClick = react.useCallback((e, extraParams = {}) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/types.ts","../src/trackHooks.ts"],"sourcesContent":["// src/types.ts\nexport enum TrackType {\n CLICK = 'click',\n EXPOSURE = 'exposure',\n PAGE_STAY = 'page_stay',\n CUSTOM = 'custom'\n}\n\nexport interface TrackParams {\n eventName: string;\n type: TrackType;\n [key: string]: any;\n}\n\n// 新增:全局配置类型\nexport interface TrackGlobalConfig {\n // 埋点上报接口 URL\n trackUrl: string;\n // 是否开启埋点\n enable?: boolean;\n // 重试配置\n retryConfig?: {\n maxRetryTimes: number;\n initialDelay: number;\n delayMultiplier: number;\n };\n}\n\n// 调整:TrackConfig 继承并扩展全局配置,支持单个 Hook 覆盖\nexport interface TrackConfig extends Partial<TrackGlobalConfig> {\n exposureOnce?: boolean;\n exposureThreshold?: number;\n}\n\nexport interface FailedTrackParams extends TrackParams {\n retryTime: number;\n retryCount?: number;\n}","// src/trackHooks.ts\nimport { useEffect, useRef, useCallback } from 'react';\nimport { TrackType, TrackParams, TrackConfig, TrackGlobalConfig, FailedTrackParams } from './types';\n\n// 全局配置(默认值),并提供修改全局配置的方法\nlet GLOBAL_TRACK_CONFIG: TrackGlobalConfig = {\n trackUrl: '/api/track', // 默认上报地址\n enable: true,\n retryConfig: {\n maxRetryTimes: 3,\n initialDelay: 1000,\n delayMultiplier: 2\n }\n};\n\n/**\n * 设置全局埋点配置(项目初始化时调用一次即可)\n * @param config 全局配置\n */\nexport const setTrackGlobalConfig = (config: Partial<TrackGlobalConfig>) => {\n GLOBAL_TRACK_CONFIG = { ...GLOBAL_TRACK_CONFIG, ...config };\n};\n\n// 2. 调整默认配置,合并全局配置\nconst getMergedDefaultConfig = (): TrackConfig => ({\n exposureOnce: true,\n exposureThreshold: 0.5,\n ...GLOBAL_TRACK_CONFIG // 继承全局配置(trackUrl、enable、retryConfig)\n});\n\n// ---------------------- 埋点发送 & 重试核心逻辑 ----------------------\nexport const getFailedTracks = (): FailedTrackParams[] => {\n try {\n return JSON.parse(localStorage.getItem('failedTracks') || '[]');\n } catch (error) {\n console.error('读取失败埋点数据失败:', error);\n return [];\n }\n};\n\nexport const saveFailedTracks = (tracks: FailedTrackParams[]) => {\n try {\n localStorage.setItem('failedTracks', JSON.stringify(tracks));\n } catch (error) {\n console.error('保存失败埋点数据失败:', error);\n }\n};\n\n/**\n * 重试失败的埋点(使用全局配置的 trackUrl)\n */\nexport const retryFailedTracks = async (force = false) => {\n const failedTracks = getFailedTracks();\n if (failedTracks.length === 0) return;\n\n const { retryConfig, trackUrl } = GLOBAL_TRACK_CONFIG;\n const retryableTracks = failedTracks.filter(track => {\n const currentRetryCount = track.retryCount || 0;\n const timeCondition = force || Date.now() - track.retryTime >= retryConfig!.initialDelay * Math.pow(retryConfig!.delayMultiplier, currentRetryCount);\n return currentRetryCount < retryConfig!.maxRetryTimes && timeCondition;\n });\n\n if (retryableTracks.length === 0) return;\n\n for (const track of retryableTracks) {\n try {\n // 使用全局配置的 trackUrl\n await fetch(trackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...track,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer,\n retryCount: (track.retryCount || 0) + 1\n })\n });\n console.log('埋点重试成功:', track.eventName);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) failedTracks.splice(index, 1);\n } catch (error) {\n console.error('埋点重试失败:', track.eventName, error);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) {\n failedTracks[index].retryCount = (failedTracks[index].retryCount || 0) + 1;\n failedTracks[index].retryTime = Date.now();\n }\n }\n }\n\n saveFailedTracks(failedTracks);\n};\n\n/**\n * 通用埋点发送函数(支持单个 Hook 覆盖 trackUrl)\n * @param params 埋点参数\n * @param config 单个 Hook 的配置(可覆盖 trackUrl)\n */\nconst sendTrack = async (params: TrackParams, config: TrackConfig) => {\n if (!params.eventName) {\n console.warn('埋点缺少必要参数:eventName');\n return;\n }\n\n // 优先级:单个 Hook 配置 > 全局配置\n const finalTrackUrl = config.trackUrl || GLOBAL_TRACK_CONFIG.trackUrl;\n const isEnable = config.enable ?? GLOBAL_TRACK_CONFIG.enable;\n\n if (!isEnable) return;\n\n try {\n // 使用最终确定的 trackUrl 发送请求\n await fetch(finalTrackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...params,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer\n })\n });\n console.log('埋点上报成功:', params);\n\n if (window.requestIdleCallback) {\n window.requestIdleCallback(() => retryFailedTracks(), { timeout: 2000 });\n } else {\n setTimeout(() => retryFailedTracks(), 1000);\n }\n } catch (error) {\n console.error('埋点上报失败:', error);\n const failedTracks = getFailedTracks();\n failedTracks.push({ ...params, retryTime: Date.now(), retryCount: 0 });\n saveFailedTracks(failedTracks);\n }\n};\n\n// ---------------------- 核心 Hooks 实现 ----------------------\nexport const useTrack = (params: TrackParams, config: TrackConfig = {}) => {\n // 合并默认配置(含全局配置)和单个 Hook 配置\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const trackRef = useRef(params);\n\n useEffect(() => {\n trackRef.current = params;\n }, [params]);\n\n const triggerTrack = useCallback((customParams = {}) => {\n const finalParams = {\n ...trackRef.current,\n ...customParams\n };\n // 把 mergedConfig 传给 sendTrack,支持覆盖 trackUrl\n sendTrack(finalParams, mergedConfig);\n }, [mergedConfig]);\n\n return { triggerTrack };\n};\n\n// 以下 Hooks 代码无需修改(useTrackClick/useTrackExposure 等),因为它们基于 useTrack 封装\nexport const useTrackClick = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CLICK, ...customParams },\n config\n );\n\n const handleClick = useCallback((e?: React.MouseEvent, extraParams = {}) => {\n const clickParams = { clientX: e?.clientX || 0, clientY: e?.clientY || 0, ...extraParams };\n triggerTrack(clickParams);\n }, [triggerTrack]);\n\n return handleClick;\n};\n\nexport const useTrackExposure = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.EXPOSURE, ...customParams },\n mergedConfig\n );\n\n const targetRef = useRef<HTMLElement>(null);\n const hasReported = useRef(false);\n\n useEffect(() => {\n if (!mergedConfig.enable) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && !hasReported.current) {\n const exposureParams = {\n intersectionRatio: entry.intersectionRatio,\n boundingClientRect: entry.boundingClientRect,\n exposureTime: Date.now()\n };\n triggerTrack(exposureParams);\n\n if (mergedConfig.exposureOnce) {\n hasReported.current = true;\n observer.unobserve(entry.target);\n }\n }\n });\n },\n { threshold: mergedConfig.exposureThreshold }\n );\n\n const target = targetRef.current;\n if (target) observer.observe(target);\n\n return () => {\n if (target) observer.unobserve(target);\n observer.disconnect();\n };\n }, [mergedConfig, triggerTrack]);\n\n return targetRef;\n};\n\nexport const useTrackPageStay = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.PAGE_STAY, ...customParams },\n config\n );\n\n const startTime = useRef(Date.now());\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n if (document.hidden) {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n } else {\n startTime.current = Date.now();\n }\n };\n\n const handleBeforeUnload = () => {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n window.addEventListener('beforeunload', handleBeforeUnload);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n window.removeEventListener('beforeunload', handleBeforeUnload);\n };\n }, [triggerTrack]);\n};\n\nexport const useTrackCustom = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CUSTOM, ...customParams },\n config\n );\n\n return triggerTrack;\n};\n\nexport const useTrackRetryListener = () => {\n useEffect(() => {\n const initTimer = setTimeout(() => retryFailedTracks(), 3000);\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n retryFailedTracks();\n }\n };\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n let idleCallbackId: number | null = null;\n const checkIdleRetry = () => {\n retryFailedTracks();\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n };\n if (window.requestIdleCallback) {\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n }\n\n return () => {\n clearTimeout(initTimer);\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n if (idleCallbackId !== null && window.cancelIdleCallback) {\n window.cancelIdleCallback(idleCallbackId);\n }\n };\n }, []);\n};"],"names":["TrackType","useRef","useEffect","useCallback"],"mappings":";;;;AAAA;AACYA;AAAZ,CAAA,UAAY,SAAS,EAAA;AACjB,IAAA,SAAA,CAAA,OAAA,CAAA,GAAA,OAAe;AACf,IAAA,SAAA,CAAA,UAAA,CAAA,GAAA,UAAqB;AACrB,IAAA,SAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;AACvB,IAAA,SAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AACrB,CAAC,EALWA,iBAAS,KAATA,iBAAS,GAAA,EAAA,CAAA,CAAA;;ACDrB;AAIA;AACA,IAAI,mBAAmB,GAAsB;IACzC,QAAQ,EAAE,YAAY;AACtB,IAAA,MAAM,EAAE,IAAI;AACZ,IAAA,WAAW,EAAE;AACT,QAAA,aAAa,EAAE,CAAC;AAChB,QAAA,YAAY,EAAE,IAAI;AAClB,QAAA,eAAe,EAAE;AACpB;CACJ;AAED;;;AAGG;AACI,MAAM,oBAAoB,GAAG,CAAC,MAAkC,KAAI;IACvE,mBAAmB,GAAG,EAAE,GAAG,mBAAmB,EAAE,GAAG,MAAM,EAAE;AAC/D;AAEA;AACA,MAAM,sBAAsB,GAAG,OAAoB;AAC/C,IAAA,YAAY,EAAE,IAAI;AAClB,IAAA,iBAAiB,EAAE,GAAG;IACtB,GAAG,mBAAmB;AACzB,CAAA,CAAC;AAEF;AACO,MAAM,eAAe,GAAG,MAA0B;AACrD,IAAA,IAAI;AACA,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC;IACnE;IAAE,OAAO,KAAK,EAAE;AACZ,QAAA,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC;AACnC,QAAA,OAAO,EAAE;IACb;AACJ;AAEO,MAAM,gBAAgB,GAAG,CAAC,MAA2B,KAAI;AAC5D,IAAA,IAAI;AACA,QAAA,YAAY,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAChE;IAAE,OAAO,KAAK,EAAE;AACZ,QAAA,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC;IACvC;AACJ;AAEA;;AAEG;AACI,MAAM,iBAAiB,GAAG,OAAO,KAAK,GAAG,KAAK,KAAI;AACrD,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;AACtC,IAAA,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE;AAE/B,IAAA,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,mBAAmB;IACrD,MAAM,eAAe,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,IAAG;AAChD,QAAA,MAAM,iBAAiB,GAAG,KAAK,CAAC,UAAU,IAAI,CAAC;QAC/C,MAAM,aAAa,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,IAAI,WAAY,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,WAAY,CAAC,eAAe,EAAE,iBAAiB,CAAC;AACpJ,QAAA,OAAO,iBAAiB,GAAG,WAAY,CAAC,aAAa,IAAI,aAAa;AAC1E,IAAA,CAAC,CAAC;AAEF,IAAA,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;QAAE;AAElC,IAAA,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE;AACjC,QAAA,IAAI;;YAEA,MAAM,KAAK,CAAC,QAAQ,EAAE;AAClB,gBAAA,MAAM,EAAE,MAAM;AACd,gBAAA,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;AAC/C,gBAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;AACjB,oBAAA,GAAG,KAAK;AACR,oBAAA,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;oBACrB,SAAS,EAAE,SAAS,CAAC,SAAS;AAC9B,oBAAA,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;oBACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oBAC3B,UAAU,EAAE,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI;iBACzC;AACJ,aAAA,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;YACvC,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,CAAC;YAC7G,IAAI,KAAK,GAAG,CAAC,CAAC;AAAE,gBAAA,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD;QAAE,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC;YAChD,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,CAAC;AAC7G,YAAA,IAAI,KAAK,GAAG,EAAE,EAAE;AACZ,gBAAA,YAAY,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC;gBAC1E,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE;YAC9C;QACJ;IACJ;IAEA,gBAAgB,CAAC,YAAY,CAAC;AAClC;AAEA;;;;AAIG;AACH,MAAM,SAAS,GAAG,OAAO,MAAmB,EAAE,MAAmB,KAAI;;AACjE,IAAA,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;AACnB,QAAA,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC;QAClC;IACJ;;IAGA,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,IAAI,mBAAmB,CAAC,QAAQ;IACrE,MAAM,QAAQ,GAAG,CAAA,EAAA,GAAA,MAAM,CAAC,MAAM,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,mBAAmB,CAAC,MAAM;AAE5D,IAAA,IAAI,CAAC,QAAQ;QAAE;AAEf,IAAA,IAAI;;QAEA,MAAM,KAAK,CAAC,aAAa,EAAE;AACvB,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;AAC/C,YAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;AACjB,gBAAA,GAAG,MAAM;AACT,gBAAA,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,SAAS,EAAE,SAAS,CAAC,SAAS;AAC9B,gBAAA,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;gBACzB,QAAQ,EAAE,QAAQ,CAAC;aACtB;AACJ,SAAA,CAAC;AACF,QAAA,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC;AAE9B,QAAA,IAAI,MAAM,CAAC,mBAAmB,EAAE;AAC5B,YAAA,MAAM,CAAC,mBAAmB,CAAC,MAAM,iBAAiB,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5E;aAAO;YACH,UAAU,CAAC,MAAM,iBAAiB,EAAE,EAAE,IAAI,CAAC;QAC/C;IACJ;IAAE,OAAO,KAAK,EAAE;AACZ,QAAA,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC;AAC/B,QAAA,MAAM,YAAY,GAAG,eAAe,EAAE;AACtC,QAAA,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;QACtE,gBAAgB,CAAC,YAAY,CAAC;IAClC;AACJ,CAAC;AAED;AACO,MAAM,QAAQ,GAAG,CAAC,MAAmB,EAAE,MAAA,GAAsB,EAAE,KAAI;;IAEtE,MAAM,YAAY,GAAG,EAAE,GAAG,sBAAsB,EAAE,EAAE,GAAG,MAAM,EAAE;AAC/D,IAAA,MAAM,QAAQ,GAAGC,YAAM,CAAC,MAAM,CAAC;IAE/BC,eAAS,CAAC,MAAK;AACX,QAAA,QAAQ,CAAC,OAAO,GAAG,MAAM;AAC7B,IAAA,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IAEZ,MAAM,YAAY,GAAGC,iBAAW,CAAC,CAAC,YAAY,GAAG,EAAE,KAAI;AACnD,QAAA,MAAM,WAAW,GAAG;YAChB,GAAG,QAAQ,CAAC,OAAO;AACnB,YAAA,GAAG;SACN;;AAED,QAAA,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC;AACxC,IAAA,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;IAElB,OAAO,EAAE,YAAY,EAAE;AAC3B;AAEA;AACO,MAAM,aAAa,GAAG,CACzB,SAAiB,EACjB,YAAA,GAAoC,EAAE,EACtC,MAAA,GAAsB,EAAE,KACxB;IACA,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,CAC7B,EAAE,SAAS,EAAE,IAAI,EAAEH,iBAAS,CAAC,KAAK,EAAE,GAAG,YAAY,EAAE,EACrD,MAAM,CACT;IAED,MAAM,WAAW,GAAGG,iBAAW,CAAC,CAAC,CAAoB,EAAE,WAAW,GAAG,EAAE,KAAI;AACvE,QAAA,MAAM,WAAW,GAAG,EAAE,OAAO,EAAE,CAAA,CAAC,KAAA,IAAA,IAAD,CAAC,KAAA,MAAA,GAAA,MAAA,GAAD,CAAC,CAAE,OAAO,KAAI,CAAC,EAAE,OAAO,EAAE,CAAA,CAAC,KAAA,IAAA,IAAD,CAAC,uBAAD,CAAC,CAAE,OAAO,KAAI,CAAC,EAAE,GAAG,WAAW,EAAE;QAC1F,YAAY,CAAC,WAAW,CAAC;AAC7B,IAAA,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;AAElB,IAAA,OAAO,WAAW;AACtB;AAEO,MAAM,gBAAgB,GAAG,CAC5B,SAAiB,EACjB,YAAA,GAAoC,EAAE,EACtC,MAAA,GAAsB,EAAE,KACxB;IACA,MAAM,YAAY,GAAG,EAAE,GAAG,sBAAsB,EAAE,EAAE,GAAG,MAAM,EAAE;IAC/D,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,CAC7B,EAAE,SAAS,EAAE,IAAI,EAAEH,iBAAS,CAAC,QAAQ,EAAE,GAAG,YAAY,EAAE,EACxD,YAAY,CACf;AAED,IAAA,MAAM,SAAS,GAAGC,YAAM,CAAc,IAAI,CAAC;AAC3C,IAAA,MAAM,WAAW,GAAGA,YAAM,CAAC,KAAK,CAAC;IAEjCC,eAAS,CAAC,MAAK;QACX,IAAI,CAAC,YAAY,CAAC,MAAM;YAAE;QAE1B,MAAM,QAAQ,GAAG,IAAI,oBAAoB,CACrC,CAAC,OAAO,KAAI;AACR,YAAA,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,KAAI;gBACtB,IAAI,KAAK,CAAC,cAAc,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;AAC9C,oBAAA,MAAM,cAAc,GAAG;wBACnB,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;wBAC1C,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;AAC5C,wBAAA,YAAY,EAAE,IAAI,CAAC,GAAG;qBACzB;oBACD,YAAY,CAAC,cAAc,CAAC;AAE5B,oBAAA,IAAI,YAAY,CAAC,YAAY,EAAE;AAC3B,wBAAA,WAAW,CAAC,OAAO,GAAG,IAAI;AAC1B,wBAAA,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;oBACpC;gBACJ;AACJ,YAAA,CAAC,CAAC;QACN,CAAC,EACD,EAAE,SAAS,EAAE,YAAY,CAAC,iBAAiB,EAAE,CAChD;AAED,QAAA,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO;AAChC,QAAA,IAAI,MAAM;AAAE,YAAA,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;AAEpC,QAAA,OAAO,MAAK;AACR,YAAA,IAAI,MAAM;AAAE,gBAAA,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC;YACtC,QAAQ,CAAC,UAAU,EAAE;AACzB,QAAA,CAAC;AACL,IAAA,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;AAEhC,IAAA,OAAO,SAAS;AACpB;AAEO,MAAM,gBAAgB,GAAG,CAC5B,SAAiB,EACjB,YAAA,GAAoC,EAAE,EACtC,MAAA,GAAsB,EAAE,KACxB;IACA,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,CAC7B,EAAE,SAAS,EAAE,IAAI,EAAEF,iBAAS,CAAC,SAAS,EAAE,GAAG,YAAY,EAAE,EACzD,MAAM,CACT;IAED,MAAM,SAAS,GAAGC,YAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAEpCC,eAAS,CAAC,MAAK;QACX,MAAM,sBAAsB,GAAG,MAAK;AAChC,YAAA,IAAI,QAAQ,CAAC,MAAM,EAAE;gBACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO;AAC/C,gBAAA,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC;YAC9B;iBAAO;AACH,gBAAA,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE;YAClC;AACJ,QAAA,CAAC;QAED,MAAM,kBAAkB,GAAG,MAAK;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO;AAC/C,YAAA,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC;AAC9B,QAAA,CAAC;AAED,QAAA,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC;AACrE,QAAA,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,CAAC;AAE3D,QAAA,OAAO,MAAK;AACR,YAAA,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC;AACxE,YAAA,MAAM,CAAC,mBAAmB,CAAC,cAAc,EAAE,kBAAkB,CAAC;AAClE,QAAA,CAAC;AACL,IAAA,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;AACtB;AAEO,MAAM,cAAc,GAAG,CAC1B,SAAiB,EACjB,YAAA,GAAoC,EAAE,EACtC,MAAA,GAAsB,EAAE,KACxB;IACA,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,CAC7B,EAAE,SAAS,EAAE,IAAI,EAAEF,iBAAS,CAAC,MAAM,EAAE,GAAG,YAAY,EAAE,EACtD,MAAM,CACT;AAED,IAAA,OAAO,YAAY;AACvB;AAEO,MAAM,qBAAqB,GAAG,MAAK;IACtCE,eAAS,CAAC,MAAK;AACX,QAAA,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,iBAAiB,EAAE,EAAE,IAAI,CAAC;QAE7D,MAAM,sBAAsB,GAAG,MAAK;AAChC,YAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;AAClB,gBAAA,iBAAiB,EAAE;YACvB;AACJ,QAAA,CAAC;AACD,QAAA,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC;QAErE,IAAI,cAAc,GAAkB,IAAI;QACxC,MAAM,cAAc,GAAG,MAAK;AACxB,YAAA,iBAAiB,EAAE;AACnB,YAAA,cAAc,GAAG,MAAM,CAAC,mBAAmB,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACnF,QAAA,CAAC;AACD,QAAA,IAAI,MAAM,CAAC,mBAAmB,EAAE;AAC5B,YAAA,cAAc,GAAG,MAAM,CAAC,mBAAmB,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACnF;AAEA,QAAA,OAAO,MAAK;YACR,YAAY,CAAC,SAAS,CAAC;AACvB,YAAA,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC;YACxE,IAAI,cAAc,KAAK,IAAI,IAAI,MAAM,CAAC,kBAAkB,EAAE;AACtD,gBAAA,MAAM,CAAC,kBAAkB,CAAC,cAAc,CAAC;YAC7C;AACJ,QAAA,CAAC;IACL,CAAC,EAAE,EAAE,CAAC;AACV;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/types.ts","../src/trackHooks.ts"],"sourcesContent":["// src/types.ts\nexport enum TrackType {\n CLICK = 'click',\n EXPOSURE = 'exposure',\n PAGE_STAY = 'page_stay',\n CUSTOM = 'custom'\n}\n\nexport interface TrackParams {\n eventName: string;\n type: TrackType;\n [key: string]: any;\n}\n\n// 新增:全局配置类型\nexport interface TrackGlobalConfig {\n // 埋点上报接口 URL\n trackUrl: string;\n // 是否开启埋点\n enable?: boolean;\n // 重试配置\n retryConfig?: {\n maxRetryTimes: number;\n initialDelay: number;\n delayMultiplier: number;\n };\n}\n\n// 调整:TrackConfig 继承并扩展全局配置,支持单个 Hook 覆盖\nexport interface TrackConfig extends Partial<TrackGlobalConfig> {\n exposureOnce?: boolean;\n exposureThreshold?: number;\n}\n\nexport interface FailedTrackParams extends TrackParams {\n retryTime: number;\n retryCount?: number;\n}","// src/trackHooks.ts\nimport { useEffect, useRef, useCallback } from 'react';\nimport { TrackType, TrackParams, TrackConfig, TrackGlobalConfig, FailedTrackParams } from './types';\n\n// 全局配置(默认值),并提供修改全局配置的方法\nlet GLOBAL_TRACK_CONFIG: TrackGlobalConfig = {\n trackUrl: '/api/track', // 默认上报地址\n enable: true,\n retryConfig: {\n maxRetryTimes: 3,\n initialDelay: 1000,\n delayMultiplier: 2\n }\n};\n\n/**\n * 设置全局埋点配置(项目初始化时调用一次即可)\n * @param config 全局配置\n */\nexport const setTrackGlobalConfig = (config: Partial<TrackGlobalConfig>) => {\n GLOBAL_TRACK_CONFIG = { ...GLOBAL_TRACK_CONFIG, ...config };\n};\n\n// 2. 调整默认配置,合并全局配置\nconst getMergedDefaultConfig = (): TrackConfig => ({\n exposureOnce: true,\n exposureThreshold: 0.5,\n ...GLOBAL_TRACK_CONFIG // 继承全局配置(trackUrl、enable、retryConfig)\n});\n\n// ---------------------- 埋点发送 & 重试核心逻辑 ----------------------\nexport const getFailedTracks = (): FailedTrackParams[] => {\n try {\n return JSON.parse(localStorage.getItem('failedTracks') || '[]');\n } catch (error) {\n console.error('读取失败埋点数据失败:', error);\n return [];\n }\n};\n\nexport const saveFailedTracks = (tracks: FailedTrackParams[]) => {\n try {\n localStorage.setItem('failedTracks', JSON.stringify(tracks));\n } catch (error) {\n console.error('保存失败埋点数据失败:', error);\n }\n};\n\n/**\n * 重试失败的埋点(使用全局配置的 trackUrl)\n */\nexport const retryFailedTracks = async (force = false) => {\n const failedTracks = getFailedTracks();\n if (failedTracks.length === 0) return;\n\n const { retryConfig, trackUrl } = GLOBAL_TRACK_CONFIG;\n const retryableTracks = failedTracks.filter(track => {\n const currentRetryCount = track.retryCount || 0;\n const timeCondition = force || Date.now() - track.retryTime >= retryConfig!.initialDelay * Math.pow(retryConfig!.delayMultiplier, currentRetryCount);\n return currentRetryCount < retryConfig!.maxRetryTimes && timeCondition;\n });\n\n if (retryableTracks.length === 0) return;\n\n for (const track of retryableTracks) {\n try {\n // 使用全局配置的 trackUrl\n await fetch(trackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...track,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer,\n retryCount: (track.retryCount || 0) + 1\n })\n });\n console.log('埋点重试成功:', track.eventName);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) failedTracks.splice(index, 1);\n } catch (error) {\n console.error('埋点重试失败:', track.eventName, error);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) {\n failedTracks[index].retryCount = (failedTracks[index].retryCount || 0) + 1;\n failedTracks[index].retryTime = Date.now();\n }\n }\n }\n\n saveFailedTracks(failedTracks);\n};\n\n/**\n * 通用埋点发送函数(支持单个 Hook 覆盖 trackUrl)\n * @param params 埋点参数\n * @param config 单个 Hook 的配置(可覆盖 trackUrl)\n */\nconst sendTrack = async (params: TrackParams, config: TrackConfig) => {\n if (!params.eventName) {\n console.warn('埋点缺少必要参数:eventName');\n return;\n }\n\n // 优先级:单个 Hook 配置 > 全局配置\n const finalTrackUrl = config.trackUrl || GLOBAL_TRACK_CONFIG.trackUrl;\n const isEnable = config.enable ?? GLOBAL_TRACK_CONFIG.enable;\n\n if (!isEnable) return;\n\n try {\n // 使用最终确定的 trackUrl 发送请求\n await fetch(finalTrackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...params,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer\n })\n });\n console.log('埋点上报成功:', params);\n\n if (window.requestIdleCallback) {\n window.requestIdleCallback(() => retryFailedTracks(), { timeout: 2000 });\n } else {\n setTimeout(() => retryFailedTracks(), 1000);\n }\n } catch (error) {\n console.error('埋点上报失败:', error);\n const failedTracks = getFailedTracks();\n failedTracks.push({ ...params, retryTime: Date.now(), retryCount: 0 });\n saveFailedTracks(failedTracks);\n }\n};\n\n// ---------------------- 核心 Hooks 实现 ----------------------\nexport const useTrack = (params: TrackParams, config: TrackConfig = {}) => {\n // 合并默认配置(含全局配置)和单个 Hook 配置\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const trackRef = useRef(params);\n\n useEffect(() => {\n trackRef.current = params;\n }, [params]);\n\n const triggerTrack = useCallback((customParams = {}) => {\n const finalParams = {\n ...trackRef.current,\n ...customParams\n };\n // 把 mergedConfig 传给 sendTrack,支持覆盖 trackUrl\n sendTrack(finalParams, mergedConfig);\n }, [mergedConfig]);\n\n return { triggerTrack };\n};\n\nexport const useTrackClick = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CLICK, ...customParams },\n config\n );\n\n const handleClick = useCallback((e?: React.MouseEvent, extraParams = {}) => {\n const clickParams = { clientX: e?.clientX || 0, clientY: e?.clientY || 0, ...extraParams };\n triggerTrack(clickParams);\n }, [triggerTrack]);\n\n return handleClick;\n};\n\nexport const useTrackExposure = <T extends HTMLElement = HTMLElement>(\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.EXPOSURE, ...customParams },\n mergedConfig\n );\n\n const targetRef = useRef<T>(null);\n const hasReported = useRef(false);\n\n useEffect(() => {\n if (!mergedConfig.enable) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && !hasReported.current) {\n const exposureParams = {\n intersectionRatio: entry.intersectionRatio,\n boundingClientRect: entry.boundingClientRect,\n exposureTime: Date.now()\n };\n triggerTrack(exposureParams);\n\n if (mergedConfig.exposureOnce) {\n hasReported.current = true;\n observer.unobserve(entry.target);\n }\n }\n });\n },\n { threshold: mergedConfig.exposureThreshold }\n );\n\n const target = targetRef.current;\n if (target) observer.observe(target);\n\n return () => {\n if (target) observer.unobserve(target);\n observer.disconnect();\n };\n }, [mergedConfig, triggerTrack]);\n\n return targetRef;\n};\n\nexport const useTrackPageStay = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.PAGE_STAY, ...customParams },\n config\n );\n\n const startTime = useRef(Date.now());\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n if (document.hidden) {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n } else {\n startTime.current = Date.now();\n }\n };\n\n const handleBeforeUnload = () => {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n window.addEventListener('beforeunload', handleBeforeUnload);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n window.removeEventListener('beforeunload', handleBeforeUnload);\n };\n }, [triggerTrack]);\n};\n\nexport const useTrackCustom = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CUSTOM, ...customParams },\n config\n );\n\n return triggerTrack;\n};\n\nexport const useTrackRetryListener = () => {\n useEffect(() => {\n const initTimer = setTimeout(() => retryFailedTracks(), 3000);\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n retryFailedTracks();\n }\n };\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n let idleCallbackId: number | null = null;\n const checkIdleRetry = () => {\n retryFailedTracks();\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n };\n if (window.requestIdleCallback) {\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n }\n\n return () => {\n clearTimeout(initTimer);\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n if (idleCallbackId !== null && window.cancelIdleCallback) {\n window.cancelIdleCallback(idleCallbackId);\n }\n };\n }, []);\n};"],"names":["TrackType","useRef","useEffect","useCallback"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -44,7 +44,7 @@ declare const useTrack: (params: TrackParams, config?: TrackConfig) => {
44
44
  triggerTrack: (customParams?: {}) => void;
45
45
  };
46
46
  declare const useTrackClick: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => (e?: React.MouseEvent, extraParams?: {}) => void;
47
- declare const useTrackExposure: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => react.RefObject<HTMLElement>;
47
+ declare const useTrackExposure: <T extends HTMLElement = HTMLElement>(eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => react.RefObject<T>;
48
48
  declare const useTrackPageStay: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => void;
49
49
  declare const useTrackCustom: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => (customParams?: {}) => void;
50
50
  declare const useTrackRetryListener: () => void;
package/dist/index.esm.js CHANGED
@@ -159,7 +159,6 @@ const useTrack = (params, config = {}) => {
159
159
  }, [mergedConfig]);
160
160
  return { triggerTrack };
161
161
  };
162
- // 以下 Hooks 代码无需修改(useTrackClick/useTrackExposure 等),因为它们基于 useTrack 封装
163
162
  const useTrackClick = (eventName, customParams = {}, config = {}) => {
164
163
  const { triggerTrack } = useTrack({ eventName, type: TrackType.CLICK, ...customParams }, config);
165
164
  const handleClick = useCallback((e, extraParams = {}) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/types.ts","../src/trackHooks.ts"],"sourcesContent":["// src/types.ts\nexport enum TrackType {\n CLICK = 'click',\n EXPOSURE = 'exposure',\n PAGE_STAY = 'page_stay',\n CUSTOM = 'custom'\n}\n\nexport interface TrackParams {\n eventName: string;\n type: TrackType;\n [key: string]: any;\n}\n\n// 新增:全局配置类型\nexport interface TrackGlobalConfig {\n // 埋点上报接口 URL\n trackUrl: string;\n // 是否开启埋点\n enable?: boolean;\n // 重试配置\n retryConfig?: {\n maxRetryTimes: number;\n initialDelay: number;\n delayMultiplier: number;\n };\n}\n\n// 调整:TrackConfig 继承并扩展全局配置,支持单个 Hook 覆盖\nexport interface TrackConfig extends Partial<TrackGlobalConfig> {\n exposureOnce?: boolean;\n exposureThreshold?: number;\n}\n\nexport interface FailedTrackParams extends TrackParams {\n retryTime: number;\n retryCount?: number;\n}","// src/trackHooks.ts\nimport { useEffect, useRef, useCallback } from 'react';\nimport { TrackType, TrackParams, TrackConfig, TrackGlobalConfig, FailedTrackParams } from './types';\n\n// 全局配置(默认值),并提供修改全局配置的方法\nlet GLOBAL_TRACK_CONFIG: TrackGlobalConfig = {\n trackUrl: '/api/track', // 默认上报地址\n enable: true,\n retryConfig: {\n maxRetryTimes: 3,\n initialDelay: 1000,\n delayMultiplier: 2\n }\n};\n\n/**\n * 设置全局埋点配置(项目初始化时调用一次即可)\n * @param config 全局配置\n */\nexport const setTrackGlobalConfig = (config: Partial<TrackGlobalConfig>) => {\n GLOBAL_TRACK_CONFIG = { ...GLOBAL_TRACK_CONFIG, ...config };\n};\n\n// 2. 调整默认配置,合并全局配置\nconst getMergedDefaultConfig = (): TrackConfig => ({\n exposureOnce: true,\n exposureThreshold: 0.5,\n ...GLOBAL_TRACK_CONFIG // 继承全局配置(trackUrl、enable、retryConfig)\n});\n\n// ---------------------- 埋点发送 & 重试核心逻辑 ----------------------\nexport const getFailedTracks = (): FailedTrackParams[] => {\n try {\n return JSON.parse(localStorage.getItem('failedTracks') || '[]');\n } catch (error) {\n console.error('读取失败埋点数据失败:', error);\n return [];\n }\n};\n\nexport const saveFailedTracks = (tracks: FailedTrackParams[]) => {\n try {\n localStorage.setItem('failedTracks', JSON.stringify(tracks));\n } catch (error) {\n console.error('保存失败埋点数据失败:', error);\n }\n};\n\n/**\n * 重试失败的埋点(使用全局配置的 trackUrl)\n */\nexport const retryFailedTracks = async (force = false) => {\n const failedTracks = getFailedTracks();\n if (failedTracks.length === 0) return;\n\n const { retryConfig, trackUrl } = GLOBAL_TRACK_CONFIG;\n const retryableTracks = failedTracks.filter(track => {\n const currentRetryCount = track.retryCount || 0;\n const timeCondition = force || Date.now() - track.retryTime >= retryConfig!.initialDelay * Math.pow(retryConfig!.delayMultiplier, currentRetryCount);\n return currentRetryCount < retryConfig!.maxRetryTimes && timeCondition;\n });\n\n if (retryableTracks.length === 0) return;\n\n for (const track of retryableTracks) {\n try {\n // 使用全局配置的 trackUrl\n await fetch(trackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...track,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer,\n retryCount: (track.retryCount || 0) + 1\n })\n });\n console.log('埋点重试成功:', track.eventName);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) failedTracks.splice(index, 1);\n } catch (error) {\n console.error('埋点重试失败:', track.eventName, error);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) {\n failedTracks[index].retryCount = (failedTracks[index].retryCount || 0) + 1;\n failedTracks[index].retryTime = Date.now();\n }\n }\n }\n\n saveFailedTracks(failedTracks);\n};\n\n/**\n * 通用埋点发送函数(支持单个 Hook 覆盖 trackUrl)\n * @param params 埋点参数\n * @param config 单个 Hook 的配置(可覆盖 trackUrl)\n */\nconst sendTrack = async (params: TrackParams, config: TrackConfig) => {\n if (!params.eventName) {\n console.warn('埋点缺少必要参数:eventName');\n return;\n }\n\n // 优先级:单个 Hook 配置 > 全局配置\n const finalTrackUrl = config.trackUrl || GLOBAL_TRACK_CONFIG.trackUrl;\n const isEnable = config.enable ?? GLOBAL_TRACK_CONFIG.enable;\n\n if (!isEnable) return;\n\n try {\n // 使用最终确定的 trackUrl 发送请求\n await fetch(finalTrackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...params,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer\n })\n });\n console.log('埋点上报成功:', params);\n\n if (window.requestIdleCallback) {\n window.requestIdleCallback(() => retryFailedTracks(), { timeout: 2000 });\n } else {\n setTimeout(() => retryFailedTracks(), 1000);\n }\n } catch (error) {\n console.error('埋点上报失败:', error);\n const failedTracks = getFailedTracks();\n failedTracks.push({ ...params, retryTime: Date.now(), retryCount: 0 });\n saveFailedTracks(failedTracks);\n }\n};\n\n// ---------------------- 核心 Hooks 实现 ----------------------\nexport const useTrack = (params: TrackParams, config: TrackConfig = {}) => {\n // 合并默认配置(含全局配置)和单个 Hook 配置\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const trackRef = useRef(params);\n\n useEffect(() => {\n trackRef.current = params;\n }, [params]);\n\n const triggerTrack = useCallback((customParams = {}) => {\n const finalParams = {\n ...trackRef.current,\n ...customParams\n };\n // 把 mergedConfig 传给 sendTrack,支持覆盖 trackUrl\n sendTrack(finalParams, mergedConfig);\n }, [mergedConfig]);\n\n return { triggerTrack };\n};\n\n// 以下 Hooks 代码无需修改(useTrackClick/useTrackExposure 等),因为它们基于 useTrack 封装\nexport const useTrackClick = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CLICK, ...customParams },\n config\n );\n\n const handleClick = useCallback((e?: React.MouseEvent, extraParams = {}) => {\n const clickParams = { clientX: e?.clientX || 0, clientY: e?.clientY || 0, ...extraParams };\n triggerTrack(clickParams);\n }, [triggerTrack]);\n\n return handleClick;\n};\n\nexport const useTrackExposure = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.EXPOSURE, ...customParams },\n mergedConfig\n );\n\n const targetRef = useRef<HTMLElement>(null);\n const hasReported = useRef(false);\n\n useEffect(() => {\n if (!mergedConfig.enable) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && !hasReported.current) {\n const exposureParams = {\n intersectionRatio: entry.intersectionRatio,\n boundingClientRect: entry.boundingClientRect,\n exposureTime: Date.now()\n };\n triggerTrack(exposureParams);\n\n if (mergedConfig.exposureOnce) {\n hasReported.current = true;\n observer.unobserve(entry.target);\n }\n }\n });\n },\n { threshold: mergedConfig.exposureThreshold }\n );\n\n const target = targetRef.current;\n if (target) observer.observe(target);\n\n return () => {\n if (target) observer.unobserve(target);\n observer.disconnect();\n };\n }, [mergedConfig, triggerTrack]);\n\n return targetRef;\n};\n\nexport const useTrackPageStay = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.PAGE_STAY, ...customParams },\n config\n );\n\n const startTime = useRef(Date.now());\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n if (document.hidden) {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n } else {\n startTime.current = Date.now();\n }\n };\n\n const handleBeforeUnload = () => {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n window.addEventListener('beforeunload', handleBeforeUnload);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n window.removeEventListener('beforeunload', handleBeforeUnload);\n };\n }, [triggerTrack]);\n};\n\nexport const useTrackCustom = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CUSTOM, ...customParams },\n config\n );\n\n return triggerTrack;\n};\n\nexport const useTrackRetryListener = () => {\n useEffect(() => {\n const initTimer = setTimeout(() => retryFailedTracks(), 3000);\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n retryFailedTracks();\n }\n };\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n let idleCallbackId: number | null = null;\n const checkIdleRetry = () => {\n retryFailedTracks();\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n };\n if (window.requestIdleCallback) {\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n }\n\n return () => {\n clearTimeout(initTimer);\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n if (idleCallbackId !== null && window.cancelIdleCallback) {\n window.cancelIdleCallback(idleCallbackId);\n }\n };\n }, []);\n};"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/types.ts","../src/trackHooks.ts"],"sourcesContent":["// src/types.ts\nexport enum TrackType {\n CLICK = 'click',\n EXPOSURE = 'exposure',\n PAGE_STAY = 'page_stay',\n CUSTOM = 'custom'\n}\n\nexport interface TrackParams {\n eventName: string;\n type: TrackType;\n [key: string]: any;\n}\n\n// 新增:全局配置类型\nexport interface TrackGlobalConfig {\n // 埋点上报接口 URL\n trackUrl: string;\n // 是否开启埋点\n enable?: boolean;\n // 重试配置\n retryConfig?: {\n maxRetryTimes: number;\n initialDelay: number;\n delayMultiplier: number;\n };\n}\n\n// 调整:TrackConfig 继承并扩展全局配置,支持单个 Hook 覆盖\nexport interface TrackConfig extends Partial<TrackGlobalConfig> {\n exposureOnce?: boolean;\n exposureThreshold?: number;\n}\n\nexport interface FailedTrackParams extends TrackParams {\n retryTime: number;\n retryCount?: number;\n}","// src/trackHooks.ts\nimport { useEffect, useRef, useCallback } from 'react';\nimport { TrackType, TrackParams, TrackConfig, TrackGlobalConfig, FailedTrackParams } from './types';\n\n// 全局配置(默认值),并提供修改全局配置的方法\nlet GLOBAL_TRACK_CONFIG: TrackGlobalConfig = {\n trackUrl: '/api/track', // 默认上报地址\n enable: true,\n retryConfig: {\n maxRetryTimes: 3,\n initialDelay: 1000,\n delayMultiplier: 2\n }\n};\n\n/**\n * 设置全局埋点配置(项目初始化时调用一次即可)\n * @param config 全局配置\n */\nexport const setTrackGlobalConfig = (config: Partial<TrackGlobalConfig>) => {\n GLOBAL_TRACK_CONFIG = { ...GLOBAL_TRACK_CONFIG, ...config };\n};\n\n// 2. 调整默认配置,合并全局配置\nconst getMergedDefaultConfig = (): TrackConfig => ({\n exposureOnce: true,\n exposureThreshold: 0.5,\n ...GLOBAL_TRACK_CONFIG // 继承全局配置(trackUrl、enable、retryConfig)\n});\n\n// ---------------------- 埋点发送 & 重试核心逻辑 ----------------------\nexport const getFailedTracks = (): FailedTrackParams[] => {\n try {\n return JSON.parse(localStorage.getItem('failedTracks') || '[]');\n } catch (error) {\n console.error('读取失败埋点数据失败:', error);\n return [];\n }\n};\n\nexport const saveFailedTracks = (tracks: FailedTrackParams[]) => {\n try {\n localStorage.setItem('failedTracks', JSON.stringify(tracks));\n } catch (error) {\n console.error('保存失败埋点数据失败:', error);\n }\n};\n\n/**\n * 重试失败的埋点(使用全局配置的 trackUrl)\n */\nexport const retryFailedTracks = async (force = false) => {\n const failedTracks = getFailedTracks();\n if (failedTracks.length === 0) return;\n\n const { retryConfig, trackUrl } = GLOBAL_TRACK_CONFIG;\n const retryableTracks = failedTracks.filter(track => {\n const currentRetryCount = track.retryCount || 0;\n const timeCondition = force || Date.now() - track.retryTime >= retryConfig!.initialDelay * Math.pow(retryConfig!.delayMultiplier, currentRetryCount);\n return currentRetryCount < retryConfig!.maxRetryTimes && timeCondition;\n });\n\n if (retryableTracks.length === 0) return;\n\n for (const track of retryableTracks) {\n try {\n // 使用全局配置的 trackUrl\n await fetch(trackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...track,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer,\n retryCount: (track.retryCount || 0) + 1\n })\n });\n console.log('埋点重试成功:', track.eventName);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) failedTracks.splice(index, 1);\n } catch (error) {\n console.error('埋点重试失败:', track.eventName, error);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) {\n failedTracks[index].retryCount = (failedTracks[index].retryCount || 0) + 1;\n failedTracks[index].retryTime = Date.now();\n }\n }\n }\n\n saveFailedTracks(failedTracks);\n};\n\n/**\n * 通用埋点发送函数(支持单个 Hook 覆盖 trackUrl)\n * @param params 埋点参数\n * @param config 单个 Hook 的配置(可覆盖 trackUrl)\n */\nconst sendTrack = async (params: TrackParams, config: TrackConfig) => {\n if (!params.eventName) {\n console.warn('埋点缺少必要参数:eventName');\n return;\n }\n\n // 优先级:单个 Hook 配置 > 全局配置\n const finalTrackUrl = config.trackUrl || GLOBAL_TRACK_CONFIG.trackUrl;\n const isEnable = config.enable ?? GLOBAL_TRACK_CONFIG.enable;\n\n if (!isEnable) return;\n\n try {\n // 使用最终确定的 trackUrl 发送请求\n await fetch(finalTrackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...params,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer\n })\n });\n console.log('埋点上报成功:', params);\n\n if (window.requestIdleCallback) {\n window.requestIdleCallback(() => retryFailedTracks(), { timeout: 2000 });\n } else {\n setTimeout(() => retryFailedTracks(), 1000);\n }\n } catch (error) {\n console.error('埋点上报失败:', error);\n const failedTracks = getFailedTracks();\n failedTracks.push({ ...params, retryTime: Date.now(), retryCount: 0 });\n saveFailedTracks(failedTracks);\n }\n};\n\n// ---------------------- 核心 Hooks 实现 ----------------------\nexport const useTrack = (params: TrackParams, config: TrackConfig = {}) => {\n // 合并默认配置(含全局配置)和单个 Hook 配置\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const trackRef = useRef(params);\n\n useEffect(() => {\n trackRef.current = params;\n }, [params]);\n\n const triggerTrack = useCallback((customParams = {}) => {\n const finalParams = {\n ...trackRef.current,\n ...customParams\n };\n // 把 mergedConfig 传给 sendTrack,支持覆盖 trackUrl\n sendTrack(finalParams, mergedConfig);\n }, [mergedConfig]);\n\n return { triggerTrack };\n};\n\nexport const useTrackClick = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CLICK, ...customParams },\n config\n );\n\n const handleClick = useCallback((e?: React.MouseEvent, extraParams = {}) => {\n const clickParams = { clientX: e?.clientX || 0, clientY: e?.clientY || 0, ...extraParams };\n triggerTrack(clickParams);\n }, [triggerTrack]);\n\n return handleClick;\n};\n\nexport const useTrackExposure = <T extends HTMLElement = HTMLElement>(\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.EXPOSURE, ...customParams },\n mergedConfig\n );\n\n const targetRef = useRef<T>(null);\n const hasReported = useRef(false);\n\n useEffect(() => {\n if (!mergedConfig.enable) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && !hasReported.current) {\n const exposureParams = {\n intersectionRatio: entry.intersectionRatio,\n boundingClientRect: entry.boundingClientRect,\n exposureTime: Date.now()\n };\n triggerTrack(exposureParams);\n\n if (mergedConfig.exposureOnce) {\n hasReported.current = true;\n observer.unobserve(entry.target);\n }\n }\n });\n },\n { threshold: mergedConfig.exposureThreshold }\n );\n\n const target = targetRef.current;\n if (target) observer.observe(target);\n\n return () => {\n if (target) observer.unobserve(target);\n observer.disconnect();\n };\n }, [mergedConfig, triggerTrack]);\n\n return targetRef;\n};\n\nexport const useTrackPageStay = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.PAGE_STAY, ...customParams },\n config\n );\n\n const startTime = useRef(Date.now());\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n if (document.hidden) {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n } else {\n startTime.current = Date.now();\n }\n };\n\n const handleBeforeUnload = () => {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n window.addEventListener('beforeunload', handleBeforeUnload);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n window.removeEventListener('beforeunload', handleBeforeUnload);\n };\n }, [triggerTrack]);\n};\n\nexport const useTrackCustom = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CUSTOM, ...customParams },\n config\n );\n\n return triggerTrack;\n};\n\nexport const useTrackRetryListener = () => {\n useEffect(() => {\n const initTimer = setTimeout(() => retryFailedTracks(), 3000);\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n retryFailedTracks();\n }\n };\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n let idleCallbackId: number | null = null;\n const checkIdleRetry = () => {\n retryFailedTracks();\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n };\n if (window.requestIdleCallback) {\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n }\n\n return () => {\n clearTimeout(initTimer);\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n if (idleCallbackId !== null && window.cancelIdleCallback) {\n window.cancelIdleCallback(idleCallbackId);\n }\n };\n }, []);\n};"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@ export declare const useTrack: (params: TrackParams, config?: TrackConfig) => {
14
14
  triggerTrack: (customParams?: {}) => void;
15
15
  };
16
16
  export declare const useTrackClick: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => (e?: React.MouseEvent, extraParams?: {}) => void;
17
- export declare const useTrackExposure: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => import("react").RefObject<HTMLElement>;
17
+ export declare const useTrackExposure: <T extends HTMLElement = HTMLElement>(eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => import("react").RefObject<T>;
18
18
  export declare const useTrackPageStay: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => void;
19
19
  export declare const useTrackCustom: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => (customParams?: {}) => void;
20
20
  export declare const useTrackRetryListener: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"trackHooks.d.ts","sourceRoot":"","sources":["../src/trackHooks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAapG;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,OAAO,CAAC,iBAAiB,CAAC,SAEtE,CAAC;AAUF,eAAO,MAAM,eAAe,QAAO,iBAAiB,EAOnD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,iBAAiB,EAAE,SAM3D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAU,eAAa,kBA0CpD,CAAC;AAgDF,eAAO,MAAM,QAAQ,GAAI,QAAQ,WAAW,EAAE,SAAQ,WAAgB;;CAmBrE,CAAC;AAGF,eAAO,MAAM,aAAa,GACtB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,UAOa,KAAK,CAAC,UAAU,2BAMxD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GACzB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,2CA6C3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GACzB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,SAgC3B,CAAC;AAEF,eAAO,MAAM,cAAc,GACvB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,gCAQ3B,CAAC;AAEF,eAAO,MAAM,qBAAqB,YA4BjC,CAAC"}
1
+ {"version":3,"file":"trackHooks.d.ts","sourceRoot":"","sources":["../src/trackHooks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAapG;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,OAAO,CAAC,iBAAiB,CAAC,SAEtE,CAAC;AAUF,eAAO,MAAM,eAAe,QAAO,iBAAiB,EAOnD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,iBAAiB,EAAE,SAM3D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAU,eAAa,kBA0CpD,CAAC;AAgDF,eAAO,MAAM,QAAQ,GAAI,QAAQ,WAAW,EAAE,SAAQ,WAAgB;;CAmBrE,CAAC;AAEF,eAAO,MAAM,aAAa,GACtB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,UAOa,KAAK,CAAC,UAAU,2BAMxD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAChE,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,iCA6C3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GACzB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,SAgC3B,CAAC;AAEF,eAAO,MAAM,cAAc,GACvB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,gCAQ3B,CAAC;AAEF,eAAO,MAAM,qBAAqB,YA4BjC,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "react-track-hooks",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "React 埋点 Hooks 库,支持点击、曝光、页面停留时长埋点及失败重试",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
7
- "types": "module",
7
+ "types": "dist/index.d.ts",
8
8
  "files": [
9
9
  "dist",
10
10
  "README.md",