customer-chat-sdk 1.3.0 → 1.3.6

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,400 +1,610 @@
1
- # Customer SDK
2
-
3
- 一个轻量级的客服系统SDK,帮助开发者快速集成客服聊天功能到现有的Web应用中。
4
-
5
- ## 🚀 特性
6
-
7
- - **轻量级集成**: 一行代码快速接入
8
- - **悬浮图标**: 页面右下角悬浮聊天图标,支持自定义位置(x, y坐标)
9
- - **可拖拽图标**: 支持鼠标/触摸拖拽移动图标位置
10
- - **响应式设计**: PC弹窗模式 / 移动端全屏模式
11
- - **设备指纹**: 自动获取设备唯一标识
12
- - **iframe隔离**: 完全隔离的聊天界面,避免样式冲突
13
- - **通知系统**: 红点徽章、数字提醒功能
14
- - **页面截图**: 支持自动截图和上传功能,可配置截图引擎和压缩选项
15
- - **跨平台支持**: 支持UMD、ESM、CJS多种模块格式
16
-
17
- ## 📦 安装
18
-
19
- ### CDN 引入
20
-
21
- ```html
22
- <script src="https://cdn.jsdelivr.net/npm/customer-chat-sdk@1.0.20/dist/customer-sdk.min.js"></script>
23
- <script>
24
- CustomerSDK.init({
25
- agent: 'your_agent_id',
26
- token: 'jwt_token',
27
- iframeUrl: 'https://chat.example.com'
28
- });
29
- </script>
30
- ```
1
+ # CustomerSDK 使用文档
31
2
 
32
- **或者使用 unpkg:**
33
- ```html
34
- <script src="https://unpkg.com/customer-chat-sdk@1.0.20/dist/customer-sdk.min.js"></script>
35
- ```
3
+ ## 简介
36
4
 
37
- ### NPM 安装
5
+ CustomerSDK 是一个轻量级的客服 SDK,提供**图标管理**和**截图功能**。适用于需要自行管理弹窗组件的项目场景。
38
6
 
39
- ```bash
40
- npm install customer-chat-sdk```
7
+ ## 特性
41
8
 
42
- ```javascript
43
- import CustomerSDK from 'customer-chat-sdk';
9
+ - ✅ **悬浮图标** - 可拖动的悬浮图标,支持侧边吸附和磁性吸附
10
+ - **截图功能** - 自动截图、压缩、上传
11
+ - ✅ **设备识别** - 自动获取设备指纹 ID
12
+ - ✅ **通知提醒** - 支持数字和文本通知徽章
13
+ - ✅ **无 iframe** - 不包含 iframe 管理,由项目自行实现弹窗
44
14
 
45
- CustomerSDK.init({
46
- agent: 'your_agent_id',
47
- token: 'jwt_token',
48
- iframeUrl: 'https://chat.example.com'
49
- });
15
+ ## 安装
16
+
17
+ ```bash
18
+ npm install customer-chat-sdk
19
+ # 或
20
+ pnpm add customer-chat-sdk
21
+ # 或
22
+ yarn add customer-chat-sdk
50
23
  ```
51
24
 
52
- ## 🔧 快速开始
25
+ ## 快速开始
53
26
 
54
27
  ### 基础用法
55
28
 
56
- ```javascript
57
- // 初始化SDK
58
- await CustomerSDK.init({
59
- agent: 'agent_123',
60
- token: 'jwt_token_here',
61
- iframeUrl: 'https://chat.example.com',
62
- debug: true
63
- }, {
64
- // 自定义图标位置(可选)
65
- iconPosition: {
66
- x: 20, // 距离左边的距离(像素)
67
- y: 80 // 距离顶部的距离(像素)
68
- },
69
- // 或者使用CSS值
70
- // iconPosition: {
71
- // x: '20px',
72
- // y: '10%'
73
- // }
74
- });
75
-
76
- // 关闭悬浮图标
77
- CustomerSDK.hideIcon();
78
-
79
- // 打开悬浮图标
80
- CustomerSDK.showIcon();
81
-
82
- // 动态设置图标位置
83
- CustomerSDK.setIconCoordinates({ x: 50, y: 100 });
84
-
85
- // 打开聊天窗口
86
- CustomerSDK.openChat();
87
-
88
- // 检查聊天窗口是否打开
89
- const isOpen = CustomerSDK.isChatOpen();
90
-
91
- // 显示通知
92
- CustomerSDK.showNotification(5); // 数字徽章
93
- CustomerSDK.showNotification('NEW'); // 文本徽章
94
- CustomerSDK.clearNotification(); // 清除通知
29
+ ```typescript
30
+ import { CustomerSDK } from 'customer-chat-sdk'
31
+
32
+ // 创建 SDK 实例
33
+ const sdk = new CustomerSDK()
34
+
35
+ // 初始化(返回初始化结果,包含设备ID等)
36
+ const initResult = await sdk.init({
37
+ debug: true, // 开发环境开启
38
+ iconPosition: { x: 20, y: 80 },
39
+ target: '#app'
40
+ })
41
+
42
+ console.log('Device ID:', initResult.deviceId)
43
+
44
+ // 设置图标点击回调
45
+ sdk.onIconClick(() => {
46
+ // 打开您的弹窗组件
47
+ openChatPopup()
48
+ })
49
+ ```
50
+
51
+ ### 完整示例(Vue 3)
52
+
53
+ ```vue
54
+ <template>
55
+ <div id="app">
56
+ <ChatPopup
57
+ ref="chatPopupRef"
58
+ v-model:visible="chatVisible"
59
+ />
60
+ </div>
61
+ </template>
62
+
63
+ <script setup lang="ts">
64
+ import { ref, onMounted, onUnmounted } from 'vue'
65
+ import { CustomerSDK } from 'customer-chat-sdk'
66
+
67
+ const chatVisible = ref(false)
68
+ const chatPopupRef = ref()
69
+ let sdk: CustomerSDK | null = null
70
+
71
+ onMounted(async () => {
72
+ sdk = new CustomerSDK()
73
+
74
+ const initResult = await sdk.init({
75
+ debug: true,
76
+ screenshot: {
77
+ engine: 'modern-screenshot',
78
+ quality: 0.15,
79
+ compress: true,
80
+ interval: 5000
81
+ },
82
+ iconPosition: { x: 20, y: 80 },
83
+ target: '#app',
84
+ sideAttach: true,
85
+ magnetic: true
86
+ }, {
87
+ sendData: (data) => {
88
+ // 处理截图数据
89
+ chatPopupRef.value?.handleScreenshotData(data)
90
+ }
91
+ })
92
+
93
+ // 获取设备ID等信息
94
+ console.log('Device ID:', initResult.deviceId)
95
+ console.log('Referrer:', initResult.referrer)
96
+
97
+ // 图标点击打开弹窗
98
+ sdk.onIconClick(async () => {
99
+ chatVisible.value = true
100
+
101
+ // 启用截图
102
+ const config = await fetchScreenshotConfig()
103
+ if (config) {
104
+ sdk?.triggerScreenshotConfig(JSON.stringify(config))
105
+ }
106
+ })
107
+ })
108
+
109
+ onUnmounted(() => {
110
+ sdk?.destroy()
111
+ })
112
+ </script>
95
113
  ```
96
114
 
97
- ### 高级配置
115
+ ### React 示例
116
+
117
+ ```tsx
118
+ import { useEffect, useRef, useState } from 'react'
119
+ import { CustomerSDK } from 'customer-chat-sdk'
120
+
121
+ function App() {
122
+ const [chatVisible, setChatVisible] = useState(false)
123
+ const sdkRef = useRef<CustomerSDK | null>(null)
124
+
125
+ useEffect(() => {
126
+ const sdk = new CustomerSDK()
127
+ sdkRef.current = sdk
128
+
129
+ sdk.init({
130
+ debug: true,
131
+ screenshot: {
132
+ engine: 'modern-screenshot',
133
+ quality: 0.15,
134
+ compress: true
135
+ },
136
+ iconPosition: { x: 20, y: 80 },
137
+ target: '#app'
138
+ }, {
139
+ sendData: (data) => {
140
+ // 发送截图数据到后端
141
+ fetch('/api/upload-screenshot', {
142
+ method: 'POST',
143
+ headers: { 'Content-Type': 'application/octet-stream' },
144
+ body: data.data
145
+ })
146
+ }
147
+ }).then((initResult) => {
148
+ // 获取设备ID等信息
149
+ console.log('Device ID:', initResult.deviceId)
150
+
151
+ sdk.onIconClick(async () => {
152
+ setChatVisible(true)
153
+ const config = await fetchScreenshotConfig()
154
+ if (config) {
155
+ sdk.triggerScreenshotConfig(JSON.stringify(config))
156
+ }
157
+ })
158
+ })
159
+
160
+ return () => {
161
+ sdk.destroy()
162
+ }
163
+ }, [])
164
+
165
+ return <div id="app">...</div>
166
+ }
167
+ ```
98
168
 
99
- ```javascript
100
- // 高级配置
101
- await CustomerSDK.init({
102
- agent: 'your_agent_id',
103
- token: 'your_jwt_token',
104
- iframeUrl: 'https://chat.example.com',
105
- debug: true,
106
- // 截图配置(可选)
107
- screenshot: {
108
- interval: 5000, // 截图间隔(毫秒),默认5000
109
- quality: 0.4, // 图片质量(0-1),默认0.4
110
- maxWidth: 1600, // 最大宽度,默认1600
111
- maxHeight: 900, // 最大高度,默认900
112
- outputFormat: 'webp', // 输出格式:'webp' | 'jpeg' | 'png',默认webp
113
- engine: 'html2canvas', // 截图引擎(仅支持html2canvas)
114
- compress: false, // 是否启用前端压缩,默认false
115
- enableCORS: true, // 是否启用CORS处理,默认true
116
- corsMode: 'canvas-proxy', // CORS处理模式,默认canvas-proxy
117
- silentMode: false // 静默模式,减少控制台输出,默认false
118
- }
119
- }, {
120
- // iframe选项(可选)
121
- width: 400,
122
- height: 600,
123
- mode: 'auto', // 'auto' | 'fullscreen' | 'popup'
124
- draggable: false,
125
- resizable: false,
126
- allowClose: true,
127
- // 图标位置配置(可选)
128
- iconPosition: {
129
- x: 20, // 距离左边的距离(像素或CSS值,如'20px'、'10%')
130
- y: 80 // 距离顶部的距离(像素或CSS值,如'80px'、'10%')
131
- }
132
- });
169
+ ## API 文档
133
170
 
134
- // 设置自定义截图目标元素
135
- CustomerSDK.setScreenshotTarget(document.getElementById('my-container'));
171
+ ### CustomerSDK 类
136
172
 
137
- // 手动触发截图
138
- await CustomerSDK.captureScreenshot();
173
+ #### 构造函数
139
174
 
140
- // 获取截图状态
141
- const state = CustomerSDK.getScreenshotState();
142
- console.log('截图状态:', state);
175
+ ```typescript
176
+ const sdk = new CustomerSDK()
143
177
  ```
144
178
 
145
- ## 📖 API 文档
179
+ #### init(config, screenshotCallback?)
146
180
 
147
- ### 初始化方法
181
+ 初始化 SDK
182
+
183
+ ```typescript
184
+ const initResult = await sdk.init(config, screenshotCallback?)
185
+ ```
148
186
 
149
- #### `CustomerSDK.init(config, options?)`
187
+ **返回值:**
150
188
 
151
- 初始化Customer SDK,自动获取设备指纹ID并创建隐藏iframe。
189
+ 返回 `InitResult` 对象,包含:
190
+ - `deviceId: string` - 设备ID(md5后的)
191
+ - `referrer: string` - 页面来源
192
+ - `agent?: string` - 代理商ID(如果配置了)
193
+ - `timestamp: number` - 初始化时间戳
152
194
 
153
195
  **参数:**
154
196
 
155
- - `config` (SDKConfig): SDK配置选项
156
- - `options` (ChatWindowOptions?, 可选): iframe窗口选项
197
+ - `config: SDKConfig` - SDK 配置
198
+ - `screenshotCallback?: ScreenshotMessageCallback` - 截图回调(可选)
199
+
200
+ **配置选项:**
157
201
 
158
- **SDKConfig:**
159
202
  ```typescript
160
203
  interface SDKConfig {
161
- agent: string; // 代理商ID
162
- token: string; // 认证令牌
163
- iframeUrl: string; // iframe聊天页面URL (必需)
164
- debug?: boolean; // 调试模式
165
- screenshot?: ScreenshotOptions; // 截图配置(可选)
204
+ debug?: boolean // 调试模式
205
+ screenshot?: ScreenshotOptions // 截图配置
206
+ iconPosition?: { // 图标位置
207
+ x?: number | string
208
+ y?: number | string
209
+ }
210
+ target?: HTMLElement | string // 图标挂载目标
211
+ sideAttach?: boolean // 侧边吸附(默认 true)
212
+ sideHideRatio?: number // 侧边隐藏比例(默认 0.5)
213
+ magnetic?: boolean // 磁性吸附(默认 true)
214
+ magneticDirection?: 'x' | 'y' | 'both' // 磁性方向(默认 'x')
215
+ margin?: number // 边距(默认 10px)
216
+ autoAttachDelay?: number // 自动吸附延迟(默认 3000ms)
217
+ referrer?: string // 页面来源
218
+ agent?: string // 代理商ID
219
+ token?: string // 认证令牌
166
220
  }
221
+ ```
222
+
223
+ **截图配置:**
167
224
 
225
+ ```typescript
168
226
  interface ScreenshotOptions {
169
- interval?: number; // 截图间隔(毫秒),默认5000
170
- quality?: number; // 图片质量(0-1),默认0.4
171
- scale?: number; // 缩放比例,默认1
172
- maxHistory?: number; // 最大历史记录数,默认10
173
- compress?: boolean; // 是否压缩图片,默认false
174
- maxWidth?: number; // 最大宽度,默认1600
175
- maxHeight?: number; // 最大高度,默认900
176
- outputFormat?: 'webp' | 'jpeg' | 'png'; // 输出格式,默认webp
177
- enableCORS?: boolean; // 是否启用CORS处理,默认true
178
- proxyUrl?: string; // 代理服务器URL,用于处理CORS问题
179
- engine?: 'html2canvas'; // 截图引擎(仅支持html2canvas,此选项已废弃,保留仅为兼容性)
180
- corsMode?: 'simple' | 'smart' | 'proxy' | 'blob' | 'canvas-proxy' | 'ignore' | 'test-first'; // CORS处理模式,默认canvas-proxy
181
- silentMode?: boolean; // 静默模式,减少控制台输出,默认false
182
- maxRetries?: number; // 最大重试次数,默认2
227
+ engine?: 'modern-screenshot' | 'snapdom' | 'html2canvas'
228
+ quality?: number // 0-1,默认 0.15
229
+ compress?: boolean // 是否压缩
230
+ interval?: number // 默认间隔(毫秒)
231
+ maxWidth?: number // 最大宽度
232
+ maxHeight?: number // 最大高度
233
+ outputFormat?: 'webp' | 'jpeg' | 'png'
234
+ enableCORS?: boolean // 启用 CORS
235
+ proxyUrl?: string // 代理 URL
236
+ corsMode?: 'simple' | 'smart' | 'proxy' | 'blob' | 'canvas-proxy'
237
+ debug?: boolean // 截图调试
183
238
  }
184
239
  ```
185
240
 
186
- **ChatWindowOptions:**
187
- ```typescript
188
- interface ChatWindowOptions {
189
- width?: number; // iframe宽度
190
- height?: number; // iframe高度
191
- position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
192
- draggable?: boolean; // 是否可拖拽
193
- resizable?: boolean; // 是否可调整大小
194
- minimizable?: boolean; // 是否可最小化
195
- iconPosition?: IconPosition; // 图标位置配置
196
- }
241
+ **截图回调:**
197
242
 
198
- interface IconPosition {
199
- x?: number | string; // x坐标(像素值或CSS值,如'20px'、'10%')
200
- y?: number | string; // y坐标(像素值或CSS值,如'80px'、'10%')
243
+ ```typescript
244
+ interface ScreenshotMessageCallback {
245
+ sendData?: (data: {
246
+ type: 'screenshotBinary'
247
+ data: ArrayBuffer
248
+ }) => void
249
+ onConfig?: (config: string) => void
201
250
  }
202
251
  ```
203
252
 
204
- ### 核心方法
253
+ #### onIconClick(callback)
205
254
 
206
- #### `CustomerSDK.openChat()` / `CustomerSDK.closeChat()`
255
+ 设置图标点击回调(也可以在 init 中配置)
207
256
 
208
- 打开或关闭iframe聊天窗口。
257
+ ```typescript
258
+ // 方式1: 使用函数式 API(default 导出)- 可以直接调用
259
+ const CustomerSDK = await import('customer-chat-sdk')
260
+ await CustomerSDK.default.init(config)
261
+ CustomerSDK.default.onIconClick(() => {
262
+ openChatPopup()
263
+ })
264
+
265
+ // 方式2: 使用类(命名导出)- 在 init 中配置(推荐)
266
+ const sdk = new CustomerSDK()
267
+ await sdk.init(config, screenshotCallback, {
268
+ onIconClick: () => {
269
+ openChatPopup()
270
+ }
271
+ })
272
+
273
+ // 方式3: 使用类(命名导出)- 单独设置
274
+ const sdk = new CustomerSDK()
275
+ await sdk.init(config)
276
+ sdk.onIconClick(() => {
277
+ openChatPopup()
278
+ })
279
+ ```
209
280
 
210
- #### `CustomerSDK.showIcon()` / `CustomerSDK.hideIcon()`
281
+ #### updateToken(token, screenshotCallback?, initCallback?)
211
282
 
212
- 显示或隐藏悬浮图标。
283
+ 更新 token(用于用户登录/退出场景)
213
284
 
214
- #### `CustomerSDK.setIconPosition(position)`
285
+ ```typescript
286
+ // 更新 token(会自动重新初始化)
287
+ await sdk.updateToken('new-token')
215
288
 
216
- 设置图标到预设位置(兼容旧API)。
289
+ // 更新 token 并更新回调
290
+ await sdk.updateToken('new-token', {
291
+ sendData: (data) => { /* ... */ }
292
+ }, {
293
+ onIconClick: () => { /* ... */ }
294
+ })
295
+ ```
217
296
 
218
- **参数:**
219
- - `position` ('top-left' | 'top-right' | 'bottom-left' | 'bottom-right'): 预设位置
297
+ #### showNotification(badgeCount, options?)
220
298
 
221
- #### `CustomerSDK.setIconCoordinates(position)`
299
+ 显示通知
222
300
 
223
- 设置图标到自定义坐标位置。
301
+ ```typescript
302
+ sdk.showNotification(5, { pulse: true, autoHide: 5000 })
303
+ sdk.showNotification('新', { pulse: true })
304
+ ```
224
305
 
225
- **参数:**
226
- - `position` (IconPosition): 位置配置对象
227
- ```typescript
228
- {
229
- x?: number | string; // x坐标(像素值或CSS值)
230
- y?: number | string; // y坐标(像素值或CSS值)
231
- }
232
- ```
306
+ #### clearNotification()
233
307
 
234
- **示例:**
235
- ```javascript
236
- // 使用像素值
237
- CustomerSDK.setIconCoordinates({ x: 50, y: 100 });
308
+ 清除通知
238
309
 
239
- // 使用CSS值
240
- CustomerSDK.setIconCoordinates({ x: '20px', y: '10%' });
310
+ ```typescript
311
+ sdk.clearNotification()
241
312
  ```
242
313
 
243
- #### `CustomerSDK.setScreenshotTarget(element)`
244
-
245
- 设置截图目标元素。默认截图目标为 `document.body`。
314
+ #### triggerScreenshotConfig(configJson)
246
315
 
247
- **参数:**
248
- - `element` (HTMLElement): 要截图的DOM元素
316
+ 启用/停止截图
249
317
 
250
- #### `CustomerSDK.captureScreenshot()`
318
+ ```typescript
319
+ // 启用截图
320
+ const config = {
321
+ agent: 'your-agent-id',
322
+ sign: 'your-sign',
323
+ type: 1,
324
+ topic: 'screenshot',
325
+ routingKey: 'route-key',
326
+ ttl: Date.now() + 3600000, // 1小时后过期
327
+ duration: 5000 // 5秒间隔
328
+ }
329
+ sdk.triggerScreenshotConfig(JSON.stringify(config))
251
330
 
252
- 手动触发一次截图。
331
+ // 停止截图
332
+ sdk.triggerScreenshotConfig(JSON.stringify({
333
+ ...config,
334
+ ttl: 0 // 禁用
335
+ }))
336
+ ```
253
337
 
254
- **返回:** `Promise<boolean>` - 是否截图成功
338
+ #### showIcon() / hideIcon()
255
339
 
256
- #### `CustomerSDK.getScreenshotState()`
340
+ 显示/隐藏图标
257
341
 
258
- 获取截图功能的状态信息。
342
+ ```typescript
343
+ sdk.showIcon()
344
+ sdk.hideIcon()
345
+ ```
259
346
 
260
- **返回:** 状态对象,包含:
261
- - `isRunning`: 是否正在运行
262
- - `screenshotCount`: 截图次数
263
- - `lastScreenshotTime`: 最后截图时间
264
- - `error`: 错误信息
265
- - `isEnabled`: 是否启用
266
- - `isUploading`: 是否正在上传
267
- - `uploadError`: 上传错误
268
- - `uploadProgress`: 上传进度
269
- - `currentUploadConfig`: 当前上传配置
347
+ #### getDeviceId()
270
348
 
271
- #### `CustomerSDK.isChatOpen()`
349
+ 获取设备ID(md5后的)
272
350
 
273
- 检查聊天窗口是否打开。
351
+ ```typescript
352
+ const deviceId = sdk.getDeviceId()
353
+ console.log('Device ID:', deviceId)
354
+ ```
274
355
 
275
- **返回:** boolean
356
+ #### getInitResult()
276
357
 
277
- #### `CustomerSDK.sendToIframe(data)`
358
+ 获取初始化结果(包含设备ID等信息)
278
359
 
279
- 向iframe发送数据消息。
360
+ ```typescript
361
+ const initResult = sdk.getInitResult()
362
+ if (initResult) {
363
+ console.log('Device ID:', initResult.deviceId)
364
+ console.log('Referrer:', initResult.referrer)
365
+ console.log('Timestamp:', initResult.timestamp)
366
+ }
367
+ ```
280
368
 
281
- **参数:**
282
- - `data` (any): 要发送的数据
369
+ #### getScreenshotManager() / getIconManager()
283
370
 
284
- #### `CustomerSDK.showNotification(badgeCount, options?)`
371
+ 获取管理器实例(用于高级操作)
285
372
 
286
- 显示通知徽章。
373
+ ```typescript
374
+ const screenshotManager = sdk.getScreenshotManager()
375
+ const iconManager = sdk.getIconManager()
376
+ ```
287
377
 
288
- **参数:**
289
- - `badgeCount` (number | string): 徽章内容(数字或文本)
290
- - `options` (object?, 可选): { pulse?: boolean, autoHide?: number }
378
+ #### destroy()
291
379
 
292
- #### `CustomerSDK.clearNotification()`
380
+ 销毁 SDK
293
381
 
294
- 清除通知徽章。
382
+ ```typescript
383
+ sdk.destroy()
384
+ ```
295
385
 
296
- ## 🌐 URL 参数
386
+ ## 完整工作流程
297
387
 
298
- SDK会向iframe URL自动添加以下参数:
388
+ ### 1. 初始化
299
389
 
300
- - `Agent`: 代理商ID
301
- - `Authorization`: 认证令牌
302
- - `DeviceSign`: 设备指纹ID(通过FingerprintJS自动获取)
303
- - `Referrer`: 页面来源URL(通过`document.referrer`自动获取)
390
+ ```typescript
391
+ const sdk = new CustomerSDK()
392
+ const initResult = await sdk.init({
393
+ debug: true,
394
+ screenshot: { /* ... */ },
395
+ iconPosition: { x: 20, y: 80 },
396
+ target: '#app'
397
+ }, {
398
+ // 截图回调
399
+ sendData: (data) => {
400
+ // 处理截图数据
401
+ }
402
+ }, {
403
+ // 初始化回调(图标点击)
404
+ onIconClick: async () => {
405
+ openChatPopup()
406
+ // 启用截图
407
+ const config = await fetchScreenshotConfig()
408
+ if (config) {
409
+ sdk.triggerScreenshotConfig(JSON.stringify(config))
410
+ }
411
+ }
412
+ })
304
413
 
305
- **最终URL示例:**
414
+ // 获取设备ID等信息
415
+ console.log('Device ID:', initResult.deviceId)
416
+ console.log('Referrer:', initResult.referrer)
306
417
  ```
307
- https://chat.example.com?Agent=demo_app&Authorization=test_token_1703123456789&DeviceSign=abc123xyz&Referrer=https://example.com/page
418
+
419
+ ### 2. 弹窗打开时启用截图
420
+
421
+ ```typescript
422
+ // 方式1: 在 init 中配置(推荐)
423
+ await sdk.init(config, screenshotCallback, {
424
+ onIconClick: async () => {
425
+ openChatPopup()
426
+ const config = await fetchScreenshotConfig()
427
+ sdk.triggerScreenshotConfig(JSON.stringify(config))
428
+ }
429
+ })
430
+
431
+ // 方式2: 单独设置
432
+ sdk.onIconClick(async () => {
433
+ openChatPopup()
434
+ const config = await fetchScreenshotConfig()
435
+ sdk.triggerScreenshotConfig(JSON.stringify(config))
436
+ })
308
437
  ```
309
438
 
310
- ## 🔧 响应式设计
439
+ ### 2.1. 更新 token
311
440
 
312
- SDK自动检测设备类型并应用相应样式:
441
+ ```typescript
442
+ // 用户登录后更新 token
443
+ await sdk.updateToken('new-token')
444
+ ```
313
445
 
314
- **PC模式:**
315
- - 悬浮图标:默认右下角,可自定义位置(x, y坐标),支持拖拽移动
316
- - 聊天窗口:居中弹窗,可通过iframe发送`close`消息关闭
446
+ ### 3. 弹窗关闭时停止截图
317
447
 
318
- **移动端模式:**
319
- - 悬浮图标:默认右下角,可自定义位置(x, y坐标),支持触摸拖拽移动
320
- - 聊天窗口:全屏显示,可通过iframe发送`close`消息关闭
448
+ ```typescript
449
+ function closeChatPopup() {
450
+ closePopup()
451
+ sdk.triggerScreenshotConfig(JSON.stringify({
452
+ ...config,
453
+ ttl: 0
454
+ }))
455
+ }
456
+ ```
321
457
 
322
- ## 🛠️ 开发
458
+ ### 4. 清理
323
459
 
324
- ### 环境要求
460
+ ```typescript
461
+ onUnmounted(() => {
462
+ sdk?.destroy()
463
+ })
464
+ ```
325
465
 
326
- - Node.js >= 18
327
- - pnpm >= 8 (推荐) 或 npm >= 9
466
+ ## 常见场景
328
467
 
329
- ### 安装依赖
468
+ ### 只使用图标功能
330
469
 
331
- ```bash
332
- # 使用pnpm (推荐)
333
- pnpm install
470
+ ```typescript
471
+ const sdk = new CustomerSDK()
472
+ await sdk.init({
473
+ debug: true,
474
+ iconPosition: { x: 20, y: 80 },
475
+ target: '#app'
476
+ })
334
477
 
335
- # 或者使用传统npm
336
- npm install
478
+ sdk.onIconClick(() => {
479
+ openChatPopup()
480
+ })
337
481
  ```
338
482
 
339
- ### 开发命令
483
+ ### 图标 + 截图
340
484
 
341
- ```bash
342
- # 启动开发服务器
343
- pnpm dev
485
+ ```typescript
486
+ const sdk = new CustomerSDK()
487
+ await sdk.init({
488
+ screenshot: {
489
+ engine: 'modern-screenshot',
490
+ quality: 0.15,
491
+ compress: true
492
+ }
493
+ }, {
494
+ sendData: (data) => {
495
+ sendToBackend(data)
496
+ }
497
+ })
498
+ ```
344
499
 
345
- # 启动Demo页面
346
- pnpm demo
500
+ ## 注意事项
347
501
 
348
- # 构建生产版本
349
- pnpm build
502
+ 1. **调试模式**:生产环境请关闭 `debug: true`
503
+ 2. **截图性能**:合理设置截图间隔,避免过于频繁
504
+ 3. **内存管理**:及时调用 `destroy()` 清理资源
505
+ 4. **错误处理**:所有异步操作都应添加错误处理
506
+ 5. **CORS 问题**:如果遇到跨域问题,配置 `proxyUrl` 或调整 `corsMode`
350
507
 
351
- # 代码检查
352
- pnpm lint
508
+ ## 动态导入示例
353
509
 
354
- # 格式化代码
355
- pnpm format
510
+ ### 方式 1: 使用类(推荐)
356
511
 
357
- # 检查依赖更新
358
- pnpm package-check
512
+ ```typescript
513
+ const initCustomerSDK = async () => {
514
+ // 动态导入
515
+ const mod = await import('customer-chat-sdk')
516
+
517
+ // 获取 CustomerSDK 类(命名导出)
518
+ const { CustomerSDK } = mod
519
+
520
+ // ✅ 重要:必须先实例化
521
+ const sdk = new CustomerSDK()
522
+
523
+ // 初始化(调用实例方法)
524
+ const initResult = await sdk.init({
525
+ debug: true,
526
+ iconPosition: { x: 20, y: 80 },
527
+ target: '#app'
528
+ }, {
529
+ sendData: (data) => {
530
+ // 处理截图数据
531
+ }
532
+ })
533
+
534
+ // 设置图标点击回调(调用实例方法)
535
+ sdk.onIconClick(() => {
536
+ openChatPopup()
537
+ })
538
+
539
+ return sdk
540
+ }
359
541
  ```
360
542
 
361
- ### 项目结构
543
+ ### 方式 2: 使用函数式 API(default 导出)
362
544
 
363
- ```
364
- src/
365
- ├── core/ # 核心SDK功能
366
- │ ├── CustomerSDK.ts # SDK主类
367
- │ ├── IconManager.ts # 悬浮图标管理
368
- │ └── IframeManager.ts # iframe管理
369
- ├── types/ # TypeScript类型定义
370
- └── index.ts # 主入口文件
545
+ ```typescript
546
+ const initCustomerSDK = async () => {
547
+ // 动态导入
548
+ const mod = await import('customer-chat-sdk')
549
+
550
+ // 获取 default 导出(函数式 API)
551
+ const SDK = mod.default
552
+
553
+ // ✅ 直接调用函数(不需要实例化)
554
+ const initResult = await SDK.init({
555
+ debug: true,
556
+ iconPosition: { x: 20, y: 80 },
557
+ target: '#app'
558
+ })
559
+
560
+ // 使用其他函数式 API
561
+ SDK.showIcon()
562
+ SDK.showNotification(5)
563
+
564
+ return SDK
565
+ }
371
566
  ```
372
567
 
373
- ## 🔗 iframe 通信
568
+ **注意**:函数式 API 使用全局单例,只能有一个实例。如果需要多个实例或更好的类型支持,推荐使用类的方式。
374
569
 
375
- SDK通过postMessage与iframe进行通信:
570
+ ### 兼容性动态导入(自动检测)
376
571
 
377
- ```javascript
378
- // 向iframe发送数据
379
- CustomerSDK.sendToIframe({
380
- type: 'userInfo',
381
- data: {
382
- profile: { name: 'John', avatar: '...' }
572
+ ```typescript
573
+ const initCustomerSDK = async () => {
574
+ const mod = await import('customer-chat-sdk')
575
+
576
+ // 优先使用类的方式(推荐)
577
+ if (mod.CustomerSDK && typeof mod.CustomerSDK === 'function') {
578
+ const sdk = new mod.CustomerSDK()
579
+ await sdk.init({ /* ... */ })
580
+ sdk.onIconClick(() => { /* ... */ })
581
+ return sdk
383
582
  }
384
- });
385
-
386
- // iframe接收示例
387
- window.addEventListener('message', (event) => {
388
- if (event.data.type === 'userInfo') {
389
- console.log('收到用户信息:', event.data.data);
583
+
584
+ // 回退到函数式 API
585
+ if (mod.default && mod.default.init) {
586
+ const SDK = mod.default
587
+ await SDK.init({ /* ... */ })
588
+ SDK.showIcon()
589
+ return SDK
390
590
  }
391
- });
591
+
592
+ throw new Error('CustomerSDK 未找到')
593
+ }
392
594
  ```
393
595
 
394
- ## 📄 许可证
596
+ ## 类型定义
395
597
 
396
- MIT License
598
+ ```typescript
599
+ import type {
600
+ CustomerSDK,
601
+ ScreenshotMessageCallback,
602
+ SDKConfig,
603
+ ScreenshotOptions,
604
+ InitResult
605
+ } from 'customer-chat-sdk'
606
+ ```
397
607
 
398
- ## 🤝 贡献
608
+ ## 许可证
399
609
 
400
- 欢迎提交 Issue 和 Pull Request!
610
+ MIT