customer-chat-sdk 1.3.0 → 1.3.5

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.
@@ -2181,741 +2181,6 @@ class IconManager {
2181
2181
  }
2182
2182
  }
2183
2183
 
2184
- class IframeManager {
2185
- constructor(config = {}) {
2186
- this.iframeElement = null;
2187
- this.containerElement = null; // 包装容器,包含iframe和关闭按钮
2188
- this.isOpen = false;
2189
- this.isCreated = false;
2190
- this.debug = false; // debug 模式标志
2191
- this.targetElement = null; // 目标元素(用于自适应宽度)
2192
- this.messageHandler = null; // 消息监听器引用(用于清理)
2193
- this.config = {
2194
- src: '',
2195
- mode: 'auto', // 默认自动检测设备类型
2196
- width: 450, // PC 模式默认宽度
2197
- height: 600,
2198
- allowClose: true,
2199
- ...config
2200
- };
2201
- this.debug = config.debug ?? false;
2202
- // 不在构造函数中添加消息监听器,延迟到 init() 中添加
2203
- // 这样可以避免创建多个实例时产生多个监听器
2204
- }
2205
- /**
2206
- * 初始化iframe(隐藏状态)
2207
- * 预创建iframe并连接到SSE,但不显示
2208
- */
2209
- async init() {
2210
- try {
2211
- // 设置消息监听器(在 init() 中而不是构造函数中,避免多次创建实例时产生多个监听器)
2212
- this.setupMessageListener();
2213
- // 关键修复:在初始化前,先清理页面上所有旧的容器元素
2214
- // 防止切换模式或多次初始化时产生重复的元素
2215
- this.cleanupOrphanedElements();
2216
- // 创建隐藏的iframe(预连接到SSE)
2217
- // 注意:createIframe 会将容器添加到 body
2218
- this.createIframe();
2219
- this.isCreated = true;
2220
- if (this.debug) {
2221
- console.log('CustomerSDK iframe initialized (hidden, SSE connected)');
2222
- }
2223
- }
2224
- catch (error) {
2225
- // 错误始终输出
2226
- console.error('Failed to initialize iframe:', error);
2227
- // 如果初始化失败,清理消息监听器
2228
- if (this.messageHandler) {
2229
- window.removeEventListener('message', this.messageHandler);
2230
- this.messageHandler = null;
2231
- }
2232
- throw error;
2233
- }
2234
- }
2235
- /**
2236
- * 显示iframe聊天窗口
2237
- */
2238
- show() {
2239
- if (this.isOpen) {
2240
- return;
2241
- }
2242
- if (!this.isCreated) {
2243
- throw new Error('Iframe not initialized. Call init() first.');
2244
- }
2245
- try {
2246
- // 显示已创建的容器
2247
- // 关键优化:容器在 init() 时已经添加到正确位置,这里只改变样式,不移动 DOM
2248
- // 这样可以避免 iframe 重新加载
2249
- if (this.containerElement) {
2250
- // 确保容器在 DOM 中(理论上已经在 init() 时添加,但为了安全)
2251
- if (!this.containerElement.parentNode) {
2252
- // 如果容器不在 DOM 中(异常情况),添加到 target 或 body
2253
- if (this.targetElement && this.targetElement !== document.body) {
2254
- // 确保 target 是相对定位
2255
- const targetStyle = window.getComputedStyle(this.targetElement);
2256
- if (targetStyle.position === 'static') {
2257
- this.targetElement.style.position = 'relative';
2258
- }
2259
- this.targetElement.appendChild(this.containerElement);
2260
- if (this.debug) {
2261
- console.log('Iframe container re-added to target element in show()');
2262
- }
2263
- }
2264
- else {
2265
- // 没有 target 或 target 是 body,添加到 body
2266
- document.body.appendChild(this.containerElement);
2267
- if (this.debug) {
2268
- console.log('Iframe container re-added to document.body in show()');
2269
- }
2270
- }
2271
- }
2272
- // 根据是否有 target 设置正确的定位方式
2273
- const useTargetWidth = !!this.targetElement && this.targetElement !== document.body;
2274
- const displayStyles = useTargetWidth ? {
2275
- // 使用 target 时,保持 absolute 定位(相对于 target)
2276
- position: 'absolute',
2277
- visibility: 'visible',
2278
- opacity: '1',
2279
- display: 'block'
2280
- } : {
2281
- // 没有 target 时,使用 fixed 定位(相对于视口)
2282
- position: 'fixed',
2283
- visibility: 'visible',
2284
- opacity: '1',
2285
- display: 'block'
2286
- };
2287
- Object.assign(this.containerElement.style, displayStyles);
2288
- // 禁用body滚动,防止出现滚动条
2289
- this.preventBodyScroll(true);
2290
- }
2291
- this.isOpen = true;
2292
- if (this.debug) {
2293
- console.log('CustomerSDK iframe shown');
2294
- }
2295
- }
2296
- catch (error) {
2297
- // 错误始终输出
2298
- console.error('Failed to show iframe:', error);
2299
- }
2300
- }
2301
- /**
2302
- * 打开iframe聊天窗口(保持兼容性)
2303
- */
2304
- open() {
2305
- this.show();
2306
- }
2307
- /**
2308
- * 隐藏iframe聊天窗口(类似v-show)
2309
- */
2310
- hide() {
2311
- if (!this.isOpen) {
2312
- return;
2313
- }
2314
- // 隐藏容器但保留DOM元素(不移动容器,避免 iframe 重新加载)
2315
- if (this.containerElement) {
2316
- Object.assign(this.containerElement.style, {
2317
- visibility: 'hidden',
2318
- opacity: '0',
2319
- display: 'none'
2320
- });
2321
- // 注意:不移动容器,保持容器在当前位置(body),避免 iframe 重新加载
2322
- }
2323
- // 恢复body滚动
2324
- this.preventBodyScroll(false);
2325
- this.isOpen = false;
2326
- if (this.debug) {
2327
- console.log('CustomerSDK iframe hidden (SSE still connected)');
2328
- }
2329
- // 触发关闭回调
2330
- if (this.config.onClose) {
2331
- this.config.onClose();
2332
- }
2333
- }
2334
- /**
2335
- * 关闭iframe聊天窗口(完全销毁,保持兼容性)
2336
- */
2337
- close() {
2338
- this.hide(); // 默认只隐藏,不销毁
2339
- }
2340
- /**
2341
- * 完全销毁iframe(需要时才调用)
2342
- */
2343
- destroy() {
2344
- this.hide();
2345
- // 移除消息监听器(防止内存泄漏)
2346
- if (this.messageHandler) {
2347
- window.removeEventListener('message', this.messageHandler);
2348
- this.messageHandler = null;
2349
- }
2350
- // 移除容器
2351
- if (this.containerElement) {
2352
- this.containerElement.remove();
2353
- this.containerElement = null;
2354
- this.iframeElement = null;
2355
- }
2356
- this.isCreated = false;
2357
- if (this.debug) {
2358
- console.log('CustomerSDK container destroyed');
2359
- }
2360
- }
2361
- /**
2362
- * 检查是否已打开
2363
- */
2364
- isIframeOpen() {
2365
- return this.isOpen;
2366
- }
2367
- /**
2368
- * 向iframe发送消息
2369
- */
2370
- sendToIframe(data) {
2371
- if (this.iframeElement && this.iframeElement.contentWindow) {
2372
- this.iframeElement.contentWindow.postMessage(data, '*');
2373
- }
2374
- }
2375
- /**
2376
- * 清理页面上孤立的容器元素(防止重复创建)
2377
- */
2378
- cleanupOrphanedElements() {
2379
- // 清理所有旧的容器元素(不属于当前实例的)
2380
- const existingContainers = document.querySelectorAll('.customer-sdk-container');
2381
- existingContainers.forEach((container) => {
2382
- if (container !== this.containerElement) {
2383
- container.remove();
2384
- if (this.debug) {
2385
- console.log('清理旧的容器元素');
2386
- }
2387
- }
2388
- });
2389
- }
2390
- /**
2391
- * 创建iframe(默认隐藏状态,用于SSE连接)
2392
- */
2393
- createIframe() {
2394
- // 创建包装容器(包含iframe和关闭按钮)
2395
- this.containerElement = document.createElement('div');
2396
- this.containerElement.className = 'customer-sdk-container';
2397
- // 确保容器不可拖动
2398
- this.containerElement.draggable = false;
2399
- // 创建iframe元素
2400
- this.iframeElement = document.createElement('iframe');
2401
- this.iframeElement.className = 'customer-sdk-iframe';
2402
- // 设置iframe属性
2403
- // 注意:URL只在初始化时设置一次,之后不会刷新
2404
- // 如果需要更新URL参数,需要重新初始化SDK
2405
- this.iframeElement.src = this.config.src || '';
2406
- this.iframeElement.frameBorder = '0';
2407
- // 添加必要权限(只保留常用的)
2408
- this.iframeElement.setAttribute('allow', [
2409
- 'microphone', // 麦克风权限
2410
- 'camera', // 摄像头权限
2411
- 'geolocation', // 地理位置权限
2412
- 'clipboard-read', // 剪贴板读取权限
2413
- 'clipboard-write', // 剪贴板写入权限
2414
- 'fullscreen', // 全屏权限
2415
- 'autoplay', // 自动播放权限
2416
- 'encrypted-media' // 加密媒体权限
2417
- ].join('; '));
2418
- // 设置sandbox属性(允许所有必要功能)
2419
- this.iframeElement.setAttribute('sandbox', [
2420
- 'allow-same-origin', // 允许同源
2421
- 'allow-scripts', // 允许脚本
2422
- 'allow-forms', // 允许表单
2423
- 'allow-popups', // 允许弹窗
2424
- 'allow-popups-to-escape-sandbox', // 允许弹窗逃逸沙箱
2425
- 'allow-presentation', // 允许演示
2426
- 'allow-top-navigation', // 允许顶级导航
2427
- 'allow-top-navigation-by-user-activation', // 允许用户激活的顶级导航
2428
- 'allow-downloads', // 允许下载
2429
- 'allow-modals', // 允许模态框
2430
- 'allow-orientation-lock', // 允许方向锁定
2431
- 'allow-pointer-lock', // 允许指针锁定
2432
- 'allow-storage-access-by-user-activation' // 允许用户激活的存储访问
2433
- ].join(' '));
2434
- // 获取目标元素(如果提供了 target)
2435
- if (this.config.target) {
2436
- this.targetElement = this.getTargetElement(this.config.target);
2437
- }
2438
- // 根据设备类型设置模式
2439
- const actualMode = this.getActualMode();
2440
- const isPC = actualMode === 'popup';
2441
- this.iframeElement.scrolling = 'auto'; // PC和移动端都显示滚动条
2442
- // 判断是否使用 target 的自适应宽度
2443
- const useTargetWidth = !!this.targetElement && this.targetElement !== document.body;
2444
- // PC模式:如果传了 target,使用 target 的宽度(自适应);否则使用配置的宽度
2445
- // 移动端:如果传了 target,使用 target 的宽度(自适应);否则全屏
2446
- const containerStyles = useTargetWidth ? {
2447
- // 使用 target 的宽度(自适应),PC 和移动端都适用
2448
- // 宽度 100% 自适应 target 的实际宽度(target 本身可能有 max-width 限制)
2449
- width: '100%',
2450
- height: '100%',
2451
- maxWidth: '100%', // 不超过 target 的宽度
2452
- maxHeight: '100%',
2453
- backgroundColor: '#ffffff',
2454
- borderRadius: isPC ? '0' : '0',
2455
- boxShadow: isPC ? 'none' : '0 -4px 16px rgba(0, 0, 0, 0.25)',
2456
- border: 'none',
2457
- position: 'absolute', // 相对于 target 元素定位
2458
- zIndex: '999999',
2459
- // 占满 target 元素
2460
- top: '0',
2461
- left: '0',
2462
- bottom: '0',
2463
- right: '0',
2464
- transform: 'none',
2465
- overflow: 'hidden',
2466
- // 初始隐藏的关键样式
2467
- visibility: 'hidden',
2468
- opacity: '0',
2469
- display: 'none'
2470
- } : (isPC ? {
2471
- // PC模式:没有 target,固定在右下角(不可拖动)
2472
- width: `${this.config.width || 450}px`,
2473
- height: `${this.config.height || 600}px`,
2474
- maxWidth: '90vw',
2475
- maxHeight: '90vh',
2476
- backgroundColor: '#ffffff',
2477
- borderRadius: '8px',
2478
- boxShadow: '0 4px 16px rgba(0, 0, 0, 0.25)',
2479
- border: 'none',
2480
- position: 'fixed',
2481
- zIndex: '999999',
2482
- // PC模式:固定在右下角
2483
- top: 'auto',
2484
- left: 'auto',
2485
- bottom: '20px',
2486
- right: '20px',
2487
- transform: 'none',
2488
- overflow: 'hidden',
2489
- // 防止拖动和选择
2490
- userSelect: 'none',
2491
- WebkitUserSelect: 'none',
2492
- MozUserSelect: 'none',
2493
- msUserSelect: 'none',
2494
- // 初始隐藏的关键样式
2495
- visibility: 'hidden',
2496
- opacity: '0',
2497
- display: 'none'
2498
- } : {
2499
- // 移动端全屏模式(没有 target,强制 100% 宽度和高度)
2500
- width: '100%',
2501
- height: '100%',
2502
- maxWidth: '100%',
2503
- maxHeight: '100%',
2504
- backgroundColor: '#ffffff',
2505
- borderRadius: '0',
2506
- boxShadow: '0 -4px 16px rgba(0, 0, 0, 0.25)',
2507
- border: 'none',
2508
- position: 'fixed',
2509
- zIndex: '999999',
2510
- // 全屏模式 - 占满整个屏幕
2511
- top: '0',
2512
- left: '0',
2513
- bottom: '0',
2514
- right: '0',
2515
- transform: 'none',
2516
- overflow: 'hidden',
2517
- // 初始隐藏的关键样式
2518
- visibility: 'hidden',
2519
- opacity: '0',
2520
- display: 'none'
2521
- });
2522
- Object.assign(this.containerElement.style, containerStyles);
2523
- // iframe填充整个容器
2524
- const iframeStyles = {
2525
- width: '100%',
2526
- height: '100%',
2527
- border: 'none',
2528
- borderRadius: 'inherit'
2529
- };
2530
- Object.assign(this.iframeElement.style, iframeStyles);
2531
- // 将iframe放入容器
2532
- this.containerElement.appendChild(this.iframeElement);
2533
- // PC模式下:禁止拖动容器
2534
- if (isPC && !useTargetWidth) {
2535
- // 阻止拖动事件
2536
- this.containerElement.addEventListener('dragstart', (e) => {
2537
- e.preventDefault();
2538
- e.stopPropagation();
2539
- return false;
2540
- }, false);
2541
- // 阻止鼠标按下事件(防止可能的拖动行为)
2542
- this.containerElement.addEventListener('mousedown', (e) => {
2543
- // 只阻止在容器边缘的拖动,允许点击 iframe 内容
2544
- const rect = this.containerElement.getBoundingClientRect();
2545
- const isOnEdge = (e.clientX < rect.left + 10 ||
2546
- e.clientX > rect.right - 10 ||
2547
- e.clientY < rect.top + 10 ||
2548
- e.clientY > rect.bottom - 10);
2549
- if (isOnEdge) {
2550
- e.preventDefault();
2551
- e.stopPropagation();
2552
- }
2553
- }, false);
2554
- }
2555
- // 添加iframe加载事件监听(移动端样式优化)
2556
- this.iframeElement.addEventListener('load', () => {
2557
- // 移动端注入自定义样式
2558
- if (!isPC) {
2559
- this.injectMobileStyles();
2560
- }
2561
- });
2562
- // 添加到目标元素或 body
2563
- if (this.targetElement && this.targetElement !== document.body) {
2564
- // 如果提供了 target,添加到 target 元素内
2565
- // 需要设置 target 为相对定位,以便 iframe 可以相对于它定位
2566
- const targetStyle = window.getComputedStyle(this.targetElement);
2567
- if (targetStyle.position === 'static') {
2568
- // 如果 target 是静态定位,设置为相对定位
2569
- this.targetElement.style.position = 'relative';
2570
- if (this.debug) {
2571
- console.log('Set target element position to relative for iframe container');
2572
- }
2573
- }
2574
- this.targetElement.appendChild(this.containerElement);
2575
- if (this.debug) {
2576
- console.log('Iframe container added to target element');
2577
- }
2578
- }
2579
- else {
2580
- // 没有 target 或 target 是 body,添加到 body
2581
- document.body.appendChild(this.containerElement);
2582
- if (this.debug) {
2583
- console.log('Iframe container added to document.body');
2584
- }
2585
- }
2586
- if (this.debug) {
2587
- console.log('CustomerSDK container created (hidden, ready for SSE)');
2588
- }
2589
- }
2590
- /**
2591
- * 向iframe注入移动端优化样式(隐藏滚动条)
2592
- */
2593
- injectMobileStyles() {
2594
- if (!this.iframeElement)
2595
- return;
2596
- try {
2597
- const iframeDoc = this.iframeElement.contentDocument ||
2598
- this.iframeElement.contentWindow?.document;
2599
- if (iframeDoc) {
2600
- // 创建样式元素
2601
- const style = iframeDoc.createElement('style');
2602
- style.textContent = `
2603
- /* 移动端iframe全屏样式优化 */
2604
- * {
2605
- -webkit-overflow-scrolling: touch !important;
2606
- }
2607
-
2608
- body, html, #app, .container {
2609
- overflow: auto !important;
2610
- -webkit-overflow-scrolling: touch !important;
2611
- }
2612
-
2613
- /* 隐藏所有滚动条 */
2614
- ::-webkit-scrollbar {
2615
- width: 0px !important;
2616
- height: 0px !important;
2617
- background: transparent !important;
2618
- }
2619
-
2620
- /* Firefox */
2621
- html {
2622
- scrollbar-width: none !important;
2623
- }
2624
-
2625
- /* IE/Edge */
2626
- body {
2627
- -ms-overflow-style: none !important;
2628
- }
2629
-
2630
- /* 确保内容可以滚动 */
2631
- body {
2632
- overflow: auto !important;
2633
- height: 100vh !important;
2634
- margin: 0 !important;
2635
- padding: 0 !important;
2636
- }
2637
- `;
2638
- // 注入样式
2639
- iframeDoc.head?.appendChild(style);
2640
- if (this.debug) {
2641
- console.log('CustomerSDK mobile styles injected successfully');
2642
- }
2643
- }
2644
- }
2645
- catch (error) {
2646
- // 跨域限制时静默忽略
2647
- if (this.debug) {
2648
- console.log('Cannot inject styles due to cross-origin restrictions:', error);
2649
- }
2650
- }
2651
- }
2652
- /**
2653
- * 控制页面滚动(移动端全屏模式使用)
2654
- */
2655
- preventBodyScroll(prevent) {
2656
- if (prevent) {
2657
- // 保存当前滚动位置
2658
- const scrollY = window.scrollY;
2659
- // 应用防止滚动的样式
2660
- Object.assign(document.body.style, {
2661
- position: 'fixed',
2662
- top: `-${scrollY}px`,
2663
- width: '100%',
2664
- overflow: 'hidden'
2665
- });
2666
- // 记录滚动位置以便恢复
2667
- document.body.setAttribute('data-scroll-position', scrollY.toString());
2668
- }
2669
- else {
2670
- // 获取保存的滚动位置
2671
- const scrollY = parseInt(document.body.getAttribute('data-scroll-position') || '0');
2672
- // 移除防止滚动的样式
2673
- Object.assign(document.body.style, {
2674
- position: '',
2675
- top: '',
2676
- width: '',
2677
- overflow: ''
2678
- });
2679
- // 移除记录的属性
2680
- document.body.removeAttribute('data-scroll-position');
2681
- // 恢复正常滚动位置
2682
- window.scrollTo(0, scrollY);
2683
- }
2684
- }
2685
- /**
2686
- * 检测设备类型
2687
- */
2688
- isMobileDevice() {
2689
- return window.innerWidth <= 768 ||
2690
- /Android|iPhone|iPad|iPod|Opera Mini|IEMobile/i.test(navigator.userAgent);
2691
- }
2692
- /**
2693
- * 获取当前显示模式
2694
- * PC 模式使用弹窗,移动端使用全屏
2695
- */
2696
- getActualMode() {
2697
- if (this.config.mode === 'auto') {
2698
- return this.isMobileDevice() ? 'fullscreen' : 'popup';
2699
- }
2700
- return this.config.mode;
2701
- }
2702
- /**
2703
- * 设置消息监听
2704
- */
2705
- setupMessageListener() {
2706
- // 如果已存在,先移除旧的监听器(防止重复添加)
2707
- if (this.messageHandler) {
2708
- window.removeEventListener('message', this.messageHandler);
2709
- }
2710
- // 创建新的消息处理器并保存引用
2711
- this.messageHandler = (event) => {
2712
- // 关键:过滤掉自己通过 dispatchEvent 发送的消息,避免无限循环
2713
- // 自己发送的消息 source 是 window,而 iframe 发送的消息 source 是 iframe.contentWindow
2714
- if (event.source === window) {
2715
- if (this.debug) {
2716
- console.log('[IframeManager] Ignoring self-broadcasted message to prevent infinite loop:', event.data);
2717
- }
2718
- return;
2719
- }
2720
- // 不验证来源,直接处理所有消息(确保消息能够被接收)
2721
- if (this.debug) {
2722
- console.log('[IframeManager] Message received:', {
2723
- data: event.data,
2724
- origin: event.origin,
2725
- source: event.source
2726
- });
2727
- }
2728
- this.handleIframeMessage(event.data);
2729
- };
2730
- window.addEventListener('message', this.messageHandler, false);
2731
- }
2732
- /**
2733
- * 处理来自iframe的消息
2734
- */
2735
- handleIframeMessage(data) {
2736
- if (this.debug) {
2737
- console.log('[IframeManager] Message from iframe received:', data);
2738
- }
2739
- // 判断data是字符串还是对象,兼容两种格式
2740
- let messageType;
2741
- if (typeof data === 'string') {
2742
- messageType = data;
2743
- }
2744
- else if (data && data.type) {
2745
- messageType = data.type;
2746
- }
2747
- else {
2748
- if (this.debug) {
2749
- console.log('[IframeManager] Unknown message format:', data);
2750
- }
2751
- return;
2752
- }
2753
- if (this.debug) {
2754
- console.log('[IframeManager] Parsed message type:', messageType);
2755
- }
2756
- // 根据消息类型处理不同的操作
2757
- switch (messageType) {
2758
- case 'iframe_ready':
2759
- if (this.debug) {
2760
- console.log('Iframe is ready');
2761
- }
2762
- break;
2763
- case 'close_iframe':
2764
- case 'close':
2765
- this.close();
2766
- break;
2767
- case 'resize_iframe':
2768
- case 'resize':
2769
- // PC模式支持 resize,移动端忽略
2770
- const actualMode = this.getActualMode();
2771
- if (actualMode === 'popup' && data.width && data.height) {
2772
- this.resizeIframe(data.width, data.height);
2773
- }
2774
- else if (this.debug) {
2775
- console.log('Resize request ignored (fullscreen mode)');
2776
- }
2777
- break;
2778
- case 'new-message':
2779
- // 新消息通知 - 触发回调让外层处理
2780
- if (this.debug) {
2781
- console.log('Received new message notification');
2782
- }
2783
- if (this.config.onMessage) {
2784
- this.config.onMessage(messageType, data);
2785
- }
2786
- break;
2787
- case 'goto-login':
2788
- // 登录跳转消息 - 广播给调用 SDK 的 Vue 页面
2789
- if (this.debug) {
2790
- console.log('Received goto-login message, broadcasting to Vue page');
2791
- }
2792
- this.broadcastMessageToPage(data);
2793
- if (this.config.onMessage) {
2794
- this.config.onMessage(messageType, data);
2795
- }
2796
- break;
2797
- case 'DCR_DEPOSIT':
2798
- // 存款跳转消息 - 广播给调用 SDK 的 Vue 页面
2799
- // 支持两种存款类型:
2800
- // 1. 钱包直充:{ type: 'DCR_DEPOSIT', payload: { depositType: 0, walletId: 69382 } }
2801
- // 2. 线下充值:{ type: 'DCR_DEPOSIT', payload: { depositType: 2, offlineTypeId: 2001, accountId: 35213 } }
2802
- if (this.debug) {
2803
- const depositType = data.payload?.depositType;
2804
- const depositTypeText = depositType === 0 ? '钱包直充' : depositType === 2 ? '线下充值' : '未知类型';
2805
- console.log(`[IframeManager] Received DCR_DEPOSIT message (${depositTypeText}):`, {
2806
- type: data.type,
2807
- payload: data.payload,
2808
- depositType: depositTypeText
2809
- });
2810
- }
2811
- this.broadcastMessageToPage(data);
2812
- if (this.config.onMessage) {
2813
- this.config.onMessage(messageType, data);
2814
- }
2815
- break;
2816
- case 'DCR_ACTIVITY':
2817
- // 跳转到优惠页面 - 广播给调用 SDK 的 Vue 页面
2818
- // 格式:{ type: 'DCR_ACTIVITY', payload: { activityId: 123 } }
2819
- if (this.debug) {
2820
- console.log('[IframeManager] Received DCR_ACTIVITY message:', {
2821
- type: data.type,
2822
- payload: data.payload,
2823
- activityId: data.payload?.activityId
2824
- });
2825
- }
2826
- this.broadcastMessageToPage(data);
2827
- if (this.config.onMessage) {
2828
- this.config.onMessage(messageType, data);
2829
- }
2830
- break;
2831
- default:
2832
- // 其他自定义消息处理
2833
- if (this.debug) {
2834
- console.log('[IframeManager] Custom message:', data);
2835
- }
2836
- break;
2837
- }
2838
- }
2839
- /**
2840
- * 向调用 SDK 的地方(Vue 页面)广播消息
2841
- * 通过 window.dispatchEvent 触发事件,让 Vue 页面中的 window.addEventListener('message') 可以收到
2842
- *
2843
- * 重要说明:
2844
- * 1. window.dispatchEvent 创建的事件会在同一窗口内触发所有监听器,无论 origin 是什么,Vue 页面都能收到
2845
- * 2. MessageEvent 的 origin 属性不能是 '*',必须是有效的 origin 字符串(如 'http://localhost:5173')
2846
- * 3. 我们使用 window.location.origin 来标识消息来源(当前页面的 origin)
2847
- * 4. 如果 Vue 页面需要检查 origin,应该检查 window.location.origin 而不是 '*'
2848
- */
2849
- broadcastMessageToPage(data) {
2850
- try {
2851
- // 使用 dispatchEvent 创建 MessageEvent,在同一窗口内触发所有监听器
2852
- // 这样调用 SDK 的 Vue 页面中的 window.addEventListener('message') 也能收到
2853
- // 注意:MessageEvent 的 origin 属性不能是 '*',必须是有效的 origin 字符串
2854
- // 我们使用 window.location.origin 来标识消息来源(当前页面的 origin)
2855
- // Vue 页面可以收到消息,因为 dispatchEvent 会在同一窗口内触发所有监听器
2856
- const messageEvent = new MessageEvent('message', {
2857
- data: data,
2858
- origin: window.location.origin, // 使用当前页面的 origin,不是 '*'(MessageEvent 不支持 '*')
2859
- source: window,
2860
- bubbles: true,
2861
- cancelable: true
2862
- });
2863
- window.dispatchEvent(messageEvent);
2864
- if (this.debug) {
2865
- console.log('[IframeManager] Message broadcasted to Vue page via window.dispatchEvent:', {
2866
- data: data,
2867
- origin: window.location.origin,
2868
- type: 'message',
2869
- note: 'origin is window.location.origin, not "*" (MessageEvent does not support "*")'
2870
- });
2871
- }
2872
- }
2873
- catch (error) {
2874
- if (this.debug) {
2875
- console.error('[IframeManager] Failed to broadcast message:', error);
2876
- }
2877
- }
2878
- }
2879
- /**
2880
- * 调整iframe大小(PC模式支持)
2881
- */
2882
- resizeIframe(width, height) {
2883
- if (this.containerElement) {
2884
- this.containerElement.style.width = `${width}px`;
2885
- this.containerElement.style.height = `${height}px`;
2886
- }
2887
- }
2888
- /**
2889
- * 获取目标元素(支持字符串选择器或 HTMLElement)
2890
- */
2891
- getTargetElement(target) {
2892
- if (typeof target === 'string') {
2893
- const element = document.querySelector(target);
2894
- if (element) {
2895
- return element;
2896
- }
2897
- else {
2898
- if (this.debug) {
2899
- console.warn(`Target element not found: ${target}, falling back to document.body`);
2900
- }
2901
- return document.body;
2902
- }
2903
- }
2904
- if (target instanceof HTMLElement) {
2905
- if (document.body.contains(target)) {
2906
- return target;
2907
- }
2908
- else {
2909
- if (this.debug) {
2910
- console.warn('Target element no longer in DOM, falling back to document.body');
2911
- }
2912
- return document.body;
2913
- }
2914
- }
2915
- return document.body;
2916
- }
2917
- }
2918
-
2919
2184
  function changeJpegDpi(uint8Array, dpi) {
2920
2185
  uint8Array[13] = 1;
2921
2186
  uint8Array[14] = dpi >> 8;
@@ -30064,6 +29329,244 @@ function requireBlowfish () {
30064
29329
 
30065
29330
  var cryptoJsExports = cryptoJs.exports;
30066
29331
 
29332
+ class CustomerSDK {
29333
+ constructor() {
29334
+ this.iconManager = null;
29335
+ this.screenshotManager = null;
29336
+ this.debug = false; // debug 模式标志
29337
+ this.deviceId = null; // 设备ID(md5后的)
29338
+ this.initResult = null; // 保存初始化结果
29339
+ }
29340
+ /**
29341
+ * 初始化SDK
29342
+ * @param config SDK配置
29343
+ * @param screenshotCallback 截图消息回调(可选)
29344
+ * @returns 返回初始化信息(包含设备ID等)
29345
+ */
29346
+ async init(config, screenshotCallback) {
29347
+ try {
29348
+ this.debug = config.debug ?? false;
29349
+ // 获取设备指纹ID
29350
+ const rawDeviceId = await this.getRawDeviceId();
29351
+ if (this.debug) {
29352
+ console.log('Raw Device ID:', rawDeviceId);
29353
+ }
29354
+ // 计算返回给前端的 deviceId:md5(deviceId + getReferrer())
29355
+ const referrer = config.referrer || document.referrer || document.location.href;
29356
+ this.deviceId = cryptoJsExports.MD5(rawDeviceId + referrer).toString();
29357
+ if (this.debug) {
29358
+ console.log('MD5 Device ID (for frontend):', this.deviceId);
29359
+ console.log('Referrer used:', referrer);
29360
+ }
29361
+ // 准备返回的初始化信息
29362
+ const initResult = {
29363
+ deviceId: this.deviceId,
29364
+ referrer,
29365
+ agent: config.agent,
29366
+ timestamp: Date.now()
29367
+ };
29368
+ // 初始化图标管理器(支持传送目标)
29369
+ const iconTarget = config.target || undefined;
29370
+ const iconPosition = config.iconPosition || undefined;
29371
+ this.iconManager = new IconManager(iconPosition, this.debug, iconTarget, {
29372
+ sideAttach: config.sideAttach,
29373
+ sideHideRatio: config.sideHideRatio,
29374
+ magnetic: config.magnetic,
29375
+ magneticDirection: config.magneticDirection,
29376
+ margin: config.margin,
29377
+ autoAttachDelay: config.autoAttachDelay
29378
+ });
29379
+ await this.iconManager.show();
29380
+ // 初始化截图管理器(如果配置了截图)
29381
+ if (config.screenshot) {
29382
+ const targetElement = typeof iconTarget === 'string'
29383
+ ? document.querySelector(iconTarget)
29384
+ : (iconTarget || document.body);
29385
+ // 创建发送回调函数
29386
+ const sendToExternal = screenshotCallback?.sendData || null;
29387
+ this.screenshotManager = new ScreenshotManager(targetElement, config.screenshot, sendToExternal || undefined);
29388
+ // 如果提供了配置回调,设置消息监听
29389
+ if (screenshotCallback?.onConfig) {
29390
+ this.setupScreenshotConfigListener(screenshotCallback.onConfig);
29391
+ }
29392
+ }
29393
+ // 保存初始化结果
29394
+ this.initResult = initResult;
29395
+ if (this.debug) {
29396
+ console.log('CustomerSDK initialized successfully (icon + screenshot only)');
29397
+ }
29398
+ // 返回初始化信息
29399
+ return initResult;
29400
+ }
29401
+ catch (error) {
29402
+ console.error('Failed to initialize CustomerSDK:', error);
29403
+ throw error;
29404
+ }
29405
+ }
29406
+ /**
29407
+ * 设置截图配置监听器(可选,用于兼容 postMessage 场景)
29408
+ */
29409
+ setupScreenshotConfigListener(onConfig) {
29410
+ const messageHandler = (event) => {
29411
+ try {
29412
+ // 验证消息类型
29413
+ if (!event.data || event.data.type !== 'checkScreenshot') {
29414
+ return;
29415
+ }
29416
+ if (this.debug) {
29417
+ console.log('[CustomerSDK] Received screenshot config message:', event.data);
29418
+ }
29419
+ // 调用外部回调
29420
+ if (event.data.data && typeof event.data.data === 'string') {
29421
+ onConfig(event.data.data);
29422
+ }
29423
+ }
29424
+ catch (error) {
29425
+ if (this.debug) {
29426
+ console.error('[CustomerSDK] Error handling screenshot config message:', error);
29427
+ }
29428
+ }
29429
+ };
29430
+ window.addEventListener('message', messageHandler);
29431
+ this._screenshotConfigHandler = messageHandler;
29432
+ }
29433
+ /**
29434
+ * 触发截图配置(用于弹窗组件场景)
29435
+ * @param configJson 截图配置的 JSON 字符串(BinaryConfig 格式)
29436
+ */
29437
+ triggerScreenshotConfig(configJson) {
29438
+ if (!this.screenshotManager) {
29439
+ if (this.debug) {
29440
+ console.warn('[CustomerSDK] ScreenshotManager not initialized');
29441
+ }
29442
+ return;
29443
+ }
29444
+ this.screenshotManager.handleScreenshotConfig(configJson);
29445
+ }
29446
+ /**
29447
+ * 隐藏图标
29448
+ */
29449
+ hideIcon() {
29450
+ this.iconManager?.hide();
29451
+ }
29452
+ /**
29453
+ * 显示图标
29454
+ */
29455
+ showIcon() {
29456
+ this.iconManager?.show();
29457
+ }
29458
+ /**
29459
+ * 设置图标点击回调
29460
+ */
29461
+ onIconClick(callback) {
29462
+ this.iconManager?.onClick(callback);
29463
+ }
29464
+ /**
29465
+ * 获取截图管理器实例(用于高级操作)
29466
+ */
29467
+ getScreenshotManager() {
29468
+ return this.screenshotManager;
29469
+ }
29470
+ /**
29471
+ * 获取图标管理器实例(用于高级操作)
29472
+ */
29473
+ getIconManager() {
29474
+ return this.iconManager;
29475
+ }
29476
+ /**
29477
+ * 获取设备ID(md5后的)
29478
+ */
29479
+ getDeviceId() {
29480
+ return this.deviceId;
29481
+ }
29482
+ /**
29483
+ * 获取初始化信息(设备ID等)
29484
+ */
29485
+ getInitResult() {
29486
+ return this.initResult;
29487
+ }
29488
+ /**
29489
+ * 获取设备指纹ID(原始)
29490
+ */
29491
+ async getRawDeviceId() {
29492
+ if (this.debug) {
29493
+ console.log('🔍 Starting to get device fingerprint...');
29494
+ }
29495
+ try {
29496
+ if (this.debug) {
29497
+ console.log('📦 Loading FingerprintJS...');
29498
+ }
29499
+ const fp = await index$1.load();
29500
+ if (this.debug) {
29501
+ console.log('🎯 Getting device fingerprint...');
29502
+ }
29503
+ const result = await fp.get();
29504
+ if (this.debug) {
29505
+ console.log('✅ FingerprintJS result:', result);
29506
+ console.log('🆔 Device ID obtained:', result.visitorId);
29507
+ }
29508
+ return result.visitorId;
29509
+ }
29510
+ catch (error) {
29511
+ if (this.debug) {
29512
+ console.warn('❌ Failed to get device fingerprint, using fallback:', error);
29513
+ }
29514
+ const fallbackId = 'device_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
29515
+ if (this.debug) {
29516
+ console.log('🆔 Fallback Device ID:', fallbackId);
29517
+ }
29518
+ return fallbackId;
29519
+ }
29520
+ }
29521
+ /**
29522
+ * 显示消息通知
29523
+ */
29524
+ showNotification(badgeCount = 1, options = {}) {
29525
+ if (!this.iconManager) {
29526
+ if (this.debug) {
29527
+ console.warn('SDK not initialized');
29528
+ }
29529
+ return;
29530
+ }
29531
+ this.iconManager.showNotification({
29532
+ badgeCount: typeof badgeCount === 'string' ? 0 : badgeCount,
29533
+ badgeText: typeof badgeCount === 'string' ? badgeCount : '',
29534
+ pulse: options.pulse || false
29535
+ });
29536
+ // 自动隐藏通知
29537
+ if (options.autoHide && options.autoHide > 0) {
29538
+ setTimeout(() => {
29539
+ this.iconManager?.clearNotification();
29540
+ }, options.autoHide);
29541
+ }
29542
+ }
29543
+ /**
29544
+ * 清除消息通知
29545
+ */
29546
+ clearNotification() {
29547
+ this.iconManager?.clearNotification();
29548
+ }
29549
+ /**
29550
+ * 销毁 SDK
29551
+ */
29552
+ destroy() {
29553
+ this.iconManager?.hide();
29554
+ this.screenshotManager?.destroy();
29555
+ // 清理截图配置监听器
29556
+ if (this._screenshotConfigHandler) {
29557
+ window.removeEventListener('message', this._screenshotConfigHandler);
29558
+ this._screenshotConfigHandler = null;
29559
+ }
29560
+ this.iconManager = null;
29561
+ this.screenshotManager = null;
29562
+ this.initResult = null;
29563
+ this.deviceId = null;
29564
+ if (this.debug) {
29565
+ console.log('CustomerSDK destroyed');
29566
+ }
29567
+ }
29568
+ }
29569
+
30067
29570
  /**
30068
29571
  * Customer SDK 主类
30069
29572
  * 只负责悬浮图标和iframe管理,不处理WebSocket连接
@@ -30072,7 +29575,6 @@ var cryptoJsExports = cryptoJs.exports;
30072
29575
  class CustomerServiceSDK {
30073
29576
  constructor() {
30074
29577
  this.iconManager = null;
30075
- this.iframeManager = null;
30076
29578
  this.screenshotManager = null;
30077
29579
  this.config = null;
30078
29580
  this.isInitialized = false;
@@ -30110,10 +29612,8 @@ class CustomerServiceSDK {
30110
29612
  if (this.debug) {
30111
29613
  console.log('Force reinitializing SDK...');
30112
29614
  }
30113
- // 清理旧的 iframe 和截图管理器
30114
- this.iframeManager?.destroy();
29615
+ // 清理旧的截图管理器
30115
29616
  this.screenshotManager?.destroy();
30116
- this.iframeManager = null;
30117
29617
  this.screenshotManager = null;
30118
29618
  // 注意:图标管理器暂时保留,稍后检查配置是否变化再决定是否重新创建
30119
29619
  // 重置初始化标志
@@ -30135,12 +29635,9 @@ class CustomerServiceSDK {
30135
29635
  console.log('MD5 Device ID (for frontend):', deviceId);
30136
29636
  console.log('Referrer used:', referrer);
30137
29637
  }
30138
- // 构建iframe URL(带参数,使用 md5 后的 deviceId)
30139
- const iframeUrl = this.buildIframeUrl(config, deviceId);
30140
29638
  // 准备返回的初始化信息(返回给前端的是 md5 后的 deviceId)
30141
29639
  const initResult = {
30142
29640
  deviceId,
30143
- iframeUrl,
30144
29641
  referrer,
30145
29642
  agent: config.agent,
30146
29643
  timestamp: Date.now()
@@ -30200,42 +29697,11 @@ class CustomerServiceSDK {
30200
29697
  // 更新配置记录
30201
29698
  this.lastIconConfig = { position: iconPosition, target: iconTarget };
30202
29699
  }
30203
- // 创建iframe管理器(自动检测设备类型)
30204
- // 如果提供了 target,iframe 会自适应 target 的宽度(PC 和移动端都适用)
30205
- // 如果没有 target,PC 模式使用默认宽度,移动端全屏
30206
- console.log('iframeUrl:', iframeUrl);
30207
- this.iframeManager = new IframeManager({
30208
- src: iframeUrl,
30209
- mode: 'auto', // 自动根据设备类型选择模式(PC弹窗,移动端全屏)
30210
- width: options?.width || 450, // PC模式宽度(像素,默认450px),仅在未提供 target 时使用
30211
- height: options?.height || 600, // PC模式高度(像素),仅在未提供 target 时使用
30212
- target: options?.target, // 目标元素(如果提供,iframe 会自适应其宽度)
30213
- allowClose: true,
30214
- debug: this.debug, // 传递 debug 标志
30215
- onMessage: (messageType, _data) => {
30216
- // 处理来自iframe的消息
30217
- if (messageType === 'new-message') {
30218
- // 显示红点通知(只显示红点,不显示数字)
30219
- this.showNotification(0, { pulse: true });
30220
- }
30221
- // checkScreenshot 消息由 ScreenshotManager 处理,不需要在这里处理
30222
- },
30223
- onClose: () => {
30224
- // iframe关闭时,清理图标拖动事件监听器,并重新显示图标
30225
- this.iconManager?.forceCleanupDragEvents();
30226
- this.iconManager?.show();
30227
- },
30228
- ...options
30229
- });
30230
- // 预初始化iframe(隐藏状态,连接SSE)
30231
- await this.iframeManager.init();
30232
- // 设置点击事件:图标 → iframe
29700
+ // 设置点击事件:图标点击回调(由外部处理)
30233
29701
  this.iconManager.onClick(() => {
30234
- // 打开iframe时清除红点通知
29702
+ // 图标点击事件由外部处理(例如打开弹窗)
29703
+ // 这里只清除通知
30235
29704
  this.clearNotification();
30236
- // 点击图标后隐藏图标
30237
- this.iconManager?.hide();
30238
- this.iframeManager?.show();
30239
29705
  });
30240
29706
  // 初始化截图管理器(如果启用了截图功能)
30241
29707
  if (config.screenshot) {
@@ -30247,10 +29713,8 @@ class CustomerServiceSDK {
30247
29713
  ...config.screenshot,
30248
29714
  debug: this.debug // 直接传递 debug 标志
30249
29715
  };
30250
- this.screenshotManager = new ScreenshotManager(targetElement, screenshotOptions, (data) => {
30251
- // 通过 IframeManager 发送消息到 iframe
30252
- this.iframeManager?.sendToIframe(data);
30253
- });
29716
+ this.screenshotManager = new ScreenshotManager(targetElement, screenshotOptions, undefined // 不再通过 iframe 发送,由外部回调处理
29717
+ );
30254
29718
  // 自动启用截图功能(用于测试,实际使用时需要通过 iframe 消息启用)
30255
29719
  this.screenshotManager.enable(true);
30256
29720
  if (this.debug) {
@@ -30261,7 +29725,7 @@ class CustomerServiceSDK {
30261
29725
  // 保存初始化结果,以便后续获取
30262
29726
  this.initResult = initResult;
30263
29727
  if (this.debug) {
30264
- console.log('CustomerSDK initialized successfully (iframe pre-connected to SSE)');
29728
+ console.log('CustomerSDK initialized successfully (icon + screenshot only)');
30265
29729
  }
30266
29730
  // 返回初始化信息
30267
29731
  return initResult;
@@ -30275,10 +29739,6 @@ class CustomerServiceSDK {
30275
29739
  this.iconManager.hide();
30276
29740
  this.iconManager = null;
30277
29741
  }
30278
- if (this.iframeManager) {
30279
- this.iframeManager.destroy();
30280
- this.iframeManager = null;
30281
- }
30282
29742
  if (this.screenshotManager) {
30283
29743
  this.screenshotManager.destroy();
30284
29744
  this.screenshotManager = null;
@@ -30324,31 +29784,6 @@ class CustomerServiceSDK {
30324
29784
  setIconStyle(style) {
30325
29785
  this.iconManager?.setStyle(style);
30326
29786
  }
30327
- /**
30328
- * 打开/关闭聊天窗口
30329
- */
30330
- openChat() {
30331
- // 打开iframe时清除红点通知
30332
- this.clearNotification();
30333
- this.iframeManager?.open();
30334
- }
30335
- closeChat() {
30336
- // 关闭iframe时,清理图标拖动事件监听器(防止页面无法操作)
30337
- this.iconManager?.forceCleanupDragEvents();
30338
- this.iframeManager?.close();
30339
- }
30340
- /**
30341
- * 检查聊天窗口是否打开
30342
- */
30343
- isChatOpen() {
30344
- return this.iframeManager?.isIframeOpen() || false;
30345
- }
30346
- /**
30347
- * 向iframe发送消息(传递用户数据等)
30348
- */
30349
- sendToIframe(data) {
30350
- this.iframeManager?.sendToIframe(data);
30351
- }
30352
29787
  /**
30353
29788
  * 获取连接状态
30354
29789
  * 注意:真正的连接状态保存在iframe中的SSE连接中
@@ -30439,40 +29874,13 @@ class CustomerServiceSDK {
30439
29874
  console.log('📸 截图配置已更新:', options);
30440
29875
  }
30441
29876
  }
30442
- /**
30443
- * 更新 token(用于用户登录/退出场景)
30444
- * 如果已初始化,会重新创建 iframe 并更新 URL
30445
- * @param token 新的 token(传空字符串或 undefined 表示移除 token)
30446
- * @param options UI选项(可选,用于重新初始化时的配置)
30447
- * @returns 返回更新后的初始化信息
30448
- */
30449
- async updateToken(token, options) {
30450
- if (!this.isInitialized) {
30451
- throw new Error('SDK not initialized. Call init() first.');
30452
- }
30453
- if (!this.config) {
30454
- throw new Error('SDK config not found');
30455
- }
30456
- // 更新配置中的 token
30457
- const updatedConfig = {
30458
- ...this.config,
30459
- token: token && token.trim() !== '' ? token : undefined
30460
- };
30461
- if (this.debug) {
30462
- console.log('Updating token:', token ? 'Token provided' : 'Token removed');
30463
- }
30464
- // 强制重新初始化以应用新的 token
30465
- return await this.init(updatedConfig, options, true);
30466
- }
30467
29877
  /**
30468
29878
  * 销毁 SDK
30469
29879
  */
30470
29880
  destroy() {
30471
29881
  this.iconManager?.hide();
30472
- this.iframeManager?.destroy(); // 使用 destroy 而不是 close,确保完全清理
30473
29882
  this.screenshotManager?.destroy();
30474
29883
  this.iconManager = null;
30475
- this.iframeManager = null;
30476
29884
  this.screenshotManager = null;
30477
29885
  this.config = null;
30478
29886
  this.initResult = null;
@@ -30557,26 +29965,6 @@ class CustomerServiceSDK {
30557
29965
  getReferrer(config) {
30558
29966
  return config.referrer || document.referrer || document.location.href;
30559
29967
  }
30560
- /**
30561
- * 构建iframe URL(带用户参数和设备ID)
30562
- */
30563
- buildIframeUrl(config, deviceId) {
30564
- const baseUrl = config.iframeUrl;
30565
- if (!baseUrl || baseUrl.trim() === '') {
30566
- throw new Error('iframeUrl is required but not provided or is empty');
30567
- }
30568
- const url = new URL(baseUrl);
30569
- // 添加用户参数(只在有值时才添加)
30570
- if (config.agent && config.agent.trim() !== '') {
30571
- url.searchParams.set('Agent', config.agent);
30572
- }
30573
- if (config.token && config.token.trim() !== '') {
30574
- url.searchParams.set('Authorization', config.token);
30575
- }
30576
- url.searchParams.set('DeviceSign', deviceId);
30577
- url.searchParams.set('Referrer', this.getReferrer(config));
30578
- return url.toString();
30579
- }
30580
29968
  }
30581
29969
  // 创建全局实例
30582
29970
  let globalSDKInstance = null;
@@ -30625,28 +30013,6 @@ const setIconStyle = (style) => {
30625
30013
  const sdk = getInstance();
30626
30014
  sdk.setIconStyle(style);
30627
30015
  };
30628
- /**
30629
- * 聊天控制API
30630
- */
30631
- const openChat = () => {
30632
- const sdk = getInstance();
30633
- sdk.openChat();
30634
- };
30635
- const closeChat = () => {
30636
- const sdk = getInstance();
30637
- sdk.closeChat();
30638
- };
30639
- const isChatOpen = () => {
30640
- const sdk = getInstance();
30641
- return sdk.isChatOpen();
30642
- };
30643
- /**
30644
- * iframe通信API
30645
- */
30646
- const sendToIframe = (data) => {
30647
- const sdk = getInstance();
30648
- sdk.sendToIframe(data);
30649
- };
30650
30016
  /**
30651
30017
  * 其他API
30652
30018
  */
@@ -30700,16 +30066,6 @@ const updateScreenshotOptions = (options) => {
30700
30066
  const sdk = getInstance();
30701
30067
  sdk.updateScreenshotOptions(options);
30702
30068
  };
30703
- /**
30704
- * 更新 token(用于用户登录/退出场景)
30705
- * @param token 新的 token(传空字符串或 undefined 表示移除 token)
30706
- * @param options UI选项(可选)
30707
- * @returns 返回更新后的初始化信息
30708
- */
30709
- const updateToken = async (token, options) => {
30710
- const sdk = getInstance();
30711
- return await sdk.updateToken(token, options);
30712
- };
30713
30069
  // 默认导出
30714
30070
  var index = {
30715
30071
  init,
@@ -30720,10 +30076,6 @@ var index = {
30720
30076
  setIconPosition,
30721
30077
  setIconCoordinates,
30722
30078
  setIconStyle,
30723
- openChat,
30724
- closeChat,
30725
- isChatOpen,
30726
- sendToIframe,
30727
30079
  getConnectionStatus,
30728
30080
  showNotification,
30729
30081
  clearNotification,
@@ -30732,8 +30084,7 @@ var index = {
30732
30084
  enableScreenshot,
30733
30085
  getScreenshotState,
30734
30086
  updateScreenshotOptions,
30735
- updateToken,
30736
30087
  destroy
30737
30088
  };
30738
30089
 
30739
- export { CustomerServiceSDK, captureScreenshot, clearNotification, closeChat, index as default, destroy, enableScreenshot, getConnectionStatus, getInitResult, getInstance, getScreenshotState, hideIcon, init, isChatOpen, openChat, sendToIframe, setIconCoordinates, setIconPosition, setIconStyle, setScreenshotTarget, showIcon, showNotification, updateScreenshotOptions, updateToken };
30090
+ export { CustomerSDK, CustomerServiceSDK, captureScreenshot, clearNotification, index as default, destroy, enableScreenshot, getConnectionStatus, getInitResult, getInstance, getScreenshotState, hideIcon, init, setIconCoordinates, setIconPosition, setIconStyle, setScreenshotTarget, showIcon, showNotification, updateScreenshotOptions };