customer-chat-sdk 1.1.6 → 1.1.8

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.
@@ -17,6 +17,7 @@ export declare class IframeManager {
17
17
  private isOpen;
18
18
  private isCreated;
19
19
  private debug;
20
+ private messageHandler;
20
21
  constructor(config?: IframeOptions);
21
22
  /**
22
23
  * 初始化iframe(隐藏状态)
@@ -1 +1 @@
1
- {"version":3,"file":"IframeManager.d.ts","sourceRoot":"","sources":["../../src/core/IframeManager.ts"],"names":[],"mappings":"AACA,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,CAAA;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;IACpD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,KAAK,CAAiB;gBAElB,MAAM,GAAE,aAAkB;IActC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB3B;;OAEG;IACH,IAAI,IAAI,IAAI;IA2CZ;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,IAAI,IAAI,IAAI;IA6BZ;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,IAAI,IAAI;IAgBf;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAM7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAiIpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8D1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoCzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwD3B;;OAEG;IACH,OAAO,CAAC,YAAY;CAMrB"}
1
+ {"version":3,"file":"IframeManager.d.ts","sourceRoot":"","sources":["../../src/core/IframeManager.ts"],"names":[],"mappings":"AACA,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,CAAA;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;IACpD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,cAAc,CAA+C;gBAEzD,MAAM,GAAE,aAAkB;IActC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB3B;;OAEG;IACH,IAAI,IAAI,IAAI;IA2CZ;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,IAAI,IAAI,IAAI;IA6BZ;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,IAAI,IAAI;IAyBf;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAM7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAiIpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8D1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoCzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAwB5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwD3B;;OAEG;IACH,OAAO,CAAC,YAAY;CAMrB"}
@@ -609,6 +609,7 @@ class IframeManager {
609
609
  this.isOpen = false;
610
610
  this.isCreated = false;
611
611
  this.debug = false; // debug 模式标志
612
+ this.messageHandler = null; // 消息监听器引用,用于清理
612
613
  this.config = {
613
614
  src: '',
614
615
  mode: 'auto', // 默认自动检测设备类型
@@ -727,6 +728,14 @@ class IframeManager {
727
728
  */
728
729
  destroy() {
729
730
  this.hide();
731
+ // 移除消息监听器(防止内存泄漏)
732
+ if (this.messageHandler) {
733
+ window.removeEventListener('message', this.messageHandler);
734
+ this.messageHandler = null;
735
+ if (this.debug) {
736
+ console.log('Message listener removed');
737
+ }
738
+ }
730
739
  // 移除容器
731
740
  if (this.containerElement) {
732
741
  this.containerElement.remove();
@@ -1001,12 +1010,24 @@ class IframeManager {
1001
1010
  * 设置消息监听
1002
1011
  */
1003
1012
  setupMessageListener() {
1004
- window.addEventListener('message', (event) => {
1013
+ // 如果已存在监听器,先移除旧的(防止重复添加)
1014
+ if (this.messageHandler) {
1015
+ window.removeEventListener('message', this.messageHandler);
1016
+ if (this.debug) {
1017
+ console.log('Removed old message listener');
1018
+ }
1019
+ }
1020
+ // 创建新的消息处理器并保存引用
1021
+ this.messageHandler = (event) => {
1005
1022
  // 验证消息来源(可选的安全检查)
1006
1023
  if (!this.config.src || event.origin === new URL(this.config.src).origin) {
1007
1024
  this.handleIframeMessage(event.data);
1008
1025
  }
1009
- }, false);
1026
+ };
1027
+ window.addEventListener('message', this.messageHandler, false);
1028
+ if (this.debug) {
1029
+ console.log('Message listener setup completed');
1030
+ }
1010
1031
  }
1011
1032
  /**
1012
1033
  * 处理来自iframe的消息
@@ -20792,24 +20813,40 @@ class CustomerServiceSDK {
20792
20813
  this.isInitialized = false;
20793
20814
  this.initResult = null; // 保存初始化结果
20794
20815
  this.debug = false; // debug 模式标志
20816
+ this.lastIconConfig = null; // 保存上一次的图标配置
20795
20817
  }
20796
20818
  /**
20797
20819
  * 初始化 SDK
20798
20820
  * @param config SDK配置
20799
20821
  * @param options UI选项(可选)
20822
+ * @param forceReinit 是否强制重新初始化(用于更新token等配置)
20800
20823
  * @returns 返回初始化信息(包含设备ID等)
20801
20824
  */
20802
- async init(config, options) {
20803
- if (this.isInitialized) {
20825
+ async init(config, options, forceReinit = false) {
20826
+ // 如果已经初始化且不强制重新初始化,返回之前保存的初始化信息
20827
+ if (this.isInitialized && !forceReinit) {
20804
20828
  if (this.debug) {
20805
- console.warn('CustomerSDK already initialized');
20829
+ console.warn('CustomerSDK already initialized, returning cached result. Use forceReinit=true to reinitialize.');
20806
20830
  }
20807
- // 如果已经初始化,返回之前保存的初始化信息
20808
20831
  if (this.initResult) {
20809
20832
  return this.initResult;
20810
20833
  }
20811
20834
  throw new Error('SDK already initialized but cannot retrieve initialization info');
20812
20835
  }
20836
+ // 如果需要强制重新初始化,先清理旧资源
20837
+ if (this.isInitialized && forceReinit) {
20838
+ if (this.debug) {
20839
+ console.log('Force reinitializing SDK...');
20840
+ }
20841
+ // 清理旧的 iframe 和截图管理器
20842
+ this.iframeManager?.destroy();
20843
+ this.screenshotManager?.destroy();
20844
+ this.iframeManager = null;
20845
+ this.screenshotManager = null;
20846
+ // 注意:图标管理器暂时保留,稍后检查配置是否变化再决定是否重新创建
20847
+ // 重置初始化标志
20848
+ this.isInitialized = false;
20849
+ }
20813
20850
  this.config = config;
20814
20851
  this.debug = config.debug ?? false;
20815
20852
  try {
@@ -20828,11 +20865,46 @@ class CustomerServiceSDK {
20828
20865
  agent: config.agent,
20829
20866
  timestamp: Date.now()
20830
20867
  };
20831
- // 创建悬浮图标管理器(支持自定义位置和传送目标)
20832
- const iconPosition = options?.iconPosition || undefined;
20833
- const iconTarget = options?.target || undefined;
20834
- this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20835
- await this.iconManager.show();
20868
+ // 处理图标管理器(优化:如果配置没变化,保留图标避免闪烁)
20869
+ // 如果 options 未提供,使用之前保存的配置(避免更新 token 时图标闪烁)
20870
+ const iconPosition = options?.iconPosition !== undefined
20871
+ ? options.iconPosition
20872
+ : (this.lastIconConfig?.position || undefined);
20873
+ const iconTarget = options?.target !== undefined
20874
+ ? options.target
20875
+ : (this.lastIconConfig?.target || undefined);
20876
+ // 检查图标配置是否变化
20877
+ const iconConfigChanged = this.isIconConfigChanged(iconPosition, iconTarget);
20878
+ if (iconConfigChanged) {
20879
+ // 配置变化了,需要重新创建图标管理器
20880
+ if (this.iconManager) {
20881
+ this.iconManager.hide();
20882
+ if (this.debug) {
20883
+ console.log('Icon config changed, recreating icon manager');
20884
+ }
20885
+ }
20886
+ this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20887
+ await this.iconManager.show();
20888
+ // 保存新的配置
20889
+ this.lastIconConfig = { position: iconPosition, target: iconTarget };
20890
+ }
20891
+ else {
20892
+ // 配置没变化,保留图标管理器(避免闪烁)
20893
+ if (!this.iconManager) {
20894
+ // 如果不存在,创建新的
20895
+ this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20896
+ await this.iconManager.show();
20897
+ }
20898
+ else {
20899
+ // 已存在,确保显示(可能被隐藏了)
20900
+ await this.iconManager.show();
20901
+ if (this.debug) {
20902
+ console.log('Icon config unchanged, keeping existing icon manager');
20903
+ }
20904
+ }
20905
+ // 更新配置记录
20906
+ this.lastIconConfig = { position: iconPosition, target: iconTarget };
20907
+ }
20836
20908
  // 创建iframe管理器(自动检测设备类型)
20837
20909
  this.iframeManager = new IframeManager({
20838
20910
  src: iframeUrl,
@@ -21043,6 +21115,31 @@ class CustomerServiceSDK {
21043
21115
  console.log('📸 截图配置已更新:', options);
21044
21116
  }
21045
21117
  }
21118
+ /**
21119
+ * 更新 token(用于用户登录/退出场景)
21120
+ * 如果已初始化,会重新创建 iframe 并更新 URL
21121
+ * @param token 新的 token(传空字符串或 undefined 表示移除 token)
21122
+ * @param options UI选项(可选,用于重新初始化时的配置)
21123
+ * @returns 返回更新后的初始化信息
21124
+ */
21125
+ async updateToken(token, options) {
21126
+ if (!this.isInitialized) {
21127
+ throw new Error('SDK not initialized. Call init() first.');
21128
+ }
21129
+ if (!this.config) {
21130
+ throw new Error('SDK config not found');
21131
+ }
21132
+ // 更新配置中的 token
21133
+ const updatedConfig = {
21134
+ ...this.config,
21135
+ token: token && token.trim() !== '' ? token : undefined
21136
+ };
21137
+ if (this.debug) {
21138
+ console.log('Updating token:', token ? 'Token provided' : 'Token removed');
21139
+ }
21140
+ // 强制重新初始化以应用新的 token
21141
+ return await this.init(updatedConfig, options, true);
21142
+ }
21046
21143
  /**
21047
21144
  * 销毁 SDK
21048
21145
  */
@@ -21055,6 +21152,7 @@ class CustomerServiceSDK {
21055
21152
  this.screenshotManager = null;
21056
21153
  this.config = null;
21057
21154
  this.initResult = null;
21155
+ this.lastIconConfig = null;
21058
21156
  this.isInitialized = false;
21059
21157
  if (this.debug) {
21060
21158
  console.log('CustomerSDK destroyed');
@@ -21099,6 +21197,36 @@ class CustomerServiceSDK {
21099
21197
  return fallbackId;
21100
21198
  }
21101
21199
  }
21200
+ /**
21201
+ * 检查图标配置是否变化
21202
+ */
21203
+ isIconConfigChanged(newPosition, newTarget) {
21204
+ // 如果没有保存的配置,说明是首次初始化,需要创建
21205
+ if (!this.lastIconConfig) {
21206
+ return true;
21207
+ }
21208
+ // 比较位置配置
21209
+ const positionChanged = JSON.stringify(this.lastIconConfig.position) !== JSON.stringify(newPosition);
21210
+ // 比较 target 配置
21211
+ const oldTarget = this.lastIconConfig.target;
21212
+ let targetChanged = false;
21213
+ if (oldTarget !== newTarget) {
21214
+ // 如果引用不同,进一步检查
21215
+ if (typeof oldTarget === 'string' && typeof newTarget === 'string') {
21216
+ // 都是字符串,比较值
21217
+ targetChanged = oldTarget !== newTarget;
21218
+ }
21219
+ else if (oldTarget instanceof HTMLElement && newTarget instanceof HTMLElement) {
21220
+ // 都是 HTMLElement,比较引用(引用不同就是变化了)
21221
+ targetChanged = true;
21222
+ }
21223
+ else {
21224
+ // 类型不同,肯定是变化了
21225
+ targetChanged = true;
21226
+ }
21227
+ }
21228
+ return positionChanged || targetChanged;
21229
+ }
21102
21230
  /**
21103
21231
  * 构建iframe URL(带用户参数和设备ID)
21104
21232
  */
@@ -21126,13 +21254,14 @@ let globalSDKInstance = null;
21126
21254
  * 初始化 Customer SDK
21127
21255
  * @param config SDK配置
21128
21256
  * @param options UI选项(可选)
21257
+ * @param forceReinit 是否强制重新初始化(用于更新token等配置)
21129
21258
  * @returns 返回初始化信息(包含设备ID等)
21130
21259
  */
21131
- const init = async (config, options) => {
21260
+ const init = async (config, options, forceReinit = false) => {
21132
21261
  if (!globalSDKInstance) {
21133
21262
  globalSDKInstance = new CustomerServiceSDK();
21134
21263
  }
21135
- return await globalSDKInstance.init(config, options);
21264
+ return await globalSDKInstance.init(config, options, forceReinit);
21136
21265
  };
21137
21266
  /**
21138
21267
  * 获取全局SDK实例
@@ -21241,6 +21370,16 @@ const updateScreenshotOptions = (options) => {
21241
21370
  const sdk = getInstance();
21242
21371
  sdk.updateScreenshotOptions(options);
21243
21372
  };
21373
+ /**
21374
+ * 更新 token(用于用户登录/退出场景)
21375
+ * @param token 新的 token(传空字符串或 undefined 表示移除 token)
21376
+ * @param options UI选项(可选)
21377
+ * @returns 返回更新后的初始化信息
21378
+ */
21379
+ const updateToken = async (token, options) => {
21380
+ const sdk = getInstance();
21381
+ return await sdk.updateToken(token, options);
21382
+ };
21244
21383
  // 默认导出
21245
21384
  var index = {
21246
21385
  init,
@@ -21263,6 +21402,7 @@ var index = {
21263
21402
  enableScreenshot,
21264
21403
  getScreenshotState,
21265
21404
  updateScreenshotOptions,
21405
+ updateToken,
21266
21406
  destroy
21267
21407
  };
21268
21408
 
@@ -21289,3 +21429,4 @@ exports.setScreenshotTarget = setScreenshotTarget;
21289
21429
  exports.showIcon = showIcon;
21290
21430
  exports.showNotification = showNotification;
21291
21431
  exports.updateScreenshotOptions = updateScreenshotOptions;
21432
+ exports.updateToken = updateToken;
@@ -605,6 +605,7 @@ class IframeManager {
605
605
  this.isOpen = false;
606
606
  this.isCreated = false;
607
607
  this.debug = false; // debug 模式标志
608
+ this.messageHandler = null; // 消息监听器引用,用于清理
608
609
  this.config = {
609
610
  src: '',
610
611
  mode: 'auto', // 默认自动检测设备类型
@@ -723,6 +724,14 @@ class IframeManager {
723
724
  */
724
725
  destroy() {
725
726
  this.hide();
727
+ // 移除消息监听器(防止内存泄漏)
728
+ if (this.messageHandler) {
729
+ window.removeEventListener('message', this.messageHandler);
730
+ this.messageHandler = null;
731
+ if (this.debug) {
732
+ console.log('Message listener removed');
733
+ }
734
+ }
726
735
  // 移除容器
727
736
  if (this.containerElement) {
728
737
  this.containerElement.remove();
@@ -997,12 +1006,24 @@ class IframeManager {
997
1006
  * 设置消息监听
998
1007
  */
999
1008
  setupMessageListener() {
1000
- window.addEventListener('message', (event) => {
1009
+ // 如果已存在监听器,先移除旧的(防止重复添加)
1010
+ if (this.messageHandler) {
1011
+ window.removeEventListener('message', this.messageHandler);
1012
+ if (this.debug) {
1013
+ console.log('Removed old message listener');
1014
+ }
1015
+ }
1016
+ // 创建新的消息处理器并保存引用
1017
+ this.messageHandler = (event) => {
1001
1018
  // 验证消息来源(可选的安全检查)
1002
1019
  if (!this.config.src || event.origin === new URL(this.config.src).origin) {
1003
1020
  this.handleIframeMessage(event.data);
1004
1021
  }
1005
- }, false);
1022
+ };
1023
+ window.addEventListener('message', this.messageHandler, false);
1024
+ if (this.debug) {
1025
+ console.log('Message listener setup completed');
1026
+ }
1006
1027
  }
1007
1028
  /**
1008
1029
  * 处理来自iframe的消息
@@ -20788,24 +20809,40 @@ class CustomerServiceSDK {
20788
20809
  this.isInitialized = false;
20789
20810
  this.initResult = null; // 保存初始化结果
20790
20811
  this.debug = false; // debug 模式标志
20812
+ this.lastIconConfig = null; // 保存上一次的图标配置
20791
20813
  }
20792
20814
  /**
20793
20815
  * 初始化 SDK
20794
20816
  * @param config SDK配置
20795
20817
  * @param options UI选项(可选)
20818
+ * @param forceReinit 是否强制重新初始化(用于更新token等配置)
20796
20819
  * @returns 返回初始化信息(包含设备ID等)
20797
20820
  */
20798
- async init(config, options) {
20799
- if (this.isInitialized) {
20821
+ async init(config, options, forceReinit = false) {
20822
+ // 如果已经初始化且不强制重新初始化,返回之前保存的初始化信息
20823
+ if (this.isInitialized && !forceReinit) {
20800
20824
  if (this.debug) {
20801
- console.warn('CustomerSDK already initialized');
20825
+ console.warn('CustomerSDK already initialized, returning cached result. Use forceReinit=true to reinitialize.');
20802
20826
  }
20803
- // 如果已经初始化,返回之前保存的初始化信息
20804
20827
  if (this.initResult) {
20805
20828
  return this.initResult;
20806
20829
  }
20807
20830
  throw new Error('SDK already initialized but cannot retrieve initialization info');
20808
20831
  }
20832
+ // 如果需要强制重新初始化,先清理旧资源
20833
+ if (this.isInitialized && forceReinit) {
20834
+ if (this.debug) {
20835
+ console.log('Force reinitializing SDK...');
20836
+ }
20837
+ // 清理旧的 iframe 和截图管理器
20838
+ this.iframeManager?.destroy();
20839
+ this.screenshotManager?.destroy();
20840
+ this.iframeManager = null;
20841
+ this.screenshotManager = null;
20842
+ // 注意:图标管理器暂时保留,稍后检查配置是否变化再决定是否重新创建
20843
+ // 重置初始化标志
20844
+ this.isInitialized = false;
20845
+ }
20809
20846
  this.config = config;
20810
20847
  this.debug = config.debug ?? false;
20811
20848
  try {
@@ -20824,11 +20861,46 @@ class CustomerServiceSDK {
20824
20861
  agent: config.agent,
20825
20862
  timestamp: Date.now()
20826
20863
  };
20827
- // 创建悬浮图标管理器(支持自定义位置和传送目标)
20828
- const iconPosition = options?.iconPosition || undefined;
20829
- const iconTarget = options?.target || undefined;
20830
- this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20831
- await this.iconManager.show();
20864
+ // 处理图标管理器(优化:如果配置没变化,保留图标避免闪烁)
20865
+ // 如果 options 未提供,使用之前保存的配置(避免更新 token 时图标闪烁)
20866
+ const iconPosition = options?.iconPosition !== undefined
20867
+ ? options.iconPosition
20868
+ : (this.lastIconConfig?.position || undefined);
20869
+ const iconTarget = options?.target !== undefined
20870
+ ? options.target
20871
+ : (this.lastIconConfig?.target || undefined);
20872
+ // 检查图标配置是否变化
20873
+ const iconConfigChanged = this.isIconConfigChanged(iconPosition, iconTarget);
20874
+ if (iconConfigChanged) {
20875
+ // 配置变化了,需要重新创建图标管理器
20876
+ if (this.iconManager) {
20877
+ this.iconManager.hide();
20878
+ if (this.debug) {
20879
+ console.log('Icon config changed, recreating icon manager');
20880
+ }
20881
+ }
20882
+ this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20883
+ await this.iconManager.show();
20884
+ // 保存新的配置
20885
+ this.lastIconConfig = { position: iconPosition, target: iconTarget };
20886
+ }
20887
+ else {
20888
+ // 配置没变化,保留图标管理器(避免闪烁)
20889
+ if (!this.iconManager) {
20890
+ // 如果不存在,创建新的
20891
+ this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
20892
+ await this.iconManager.show();
20893
+ }
20894
+ else {
20895
+ // 已存在,确保显示(可能被隐藏了)
20896
+ await this.iconManager.show();
20897
+ if (this.debug) {
20898
+ console.log('Icon config unchanged, keeping existing icon manager');
20899
+ }
20900
+ }
20901
+ // 更新配置记录
20902
+ this.lastIconConfig = { position: iconPosition, target: iconTarget };
20903
+ }
20832
20904
  // 创建iframe管理器(自动检测设备类型)
20833
20905
  this.iframeManager = new IframeManager({
20834
20906
  src: iframeUrl,
@@ -21039,6 +21111,31 @@ class CustomerServiceSDK {
21039
21111
  console.log('📸 截图配置已更新:', options);
21040
21112
  }
21041
21113
  }
21114
+ /**
21115
+ * 更新 token(用于用户登录/退出场景)
21116
+ * 如果已初始化,会重新创建 iframe 并更新 URL
21117
+ * @param token 新的 token(传空字符串或 undefined 表示移除 token)
21118
+ * @param options UI选项(可选,用于重新初始化时的配置)
21119
+ * @returns 返回更新后的初始化信息
21120
+ */
21121
+ async updateToken(token, options) {
21122
+ if (!this.isInitialized) {
21123
+ throw new Error('SDK not initialized. Call init() first.');
21124
+ }
21125
+ if (!this.config) {
21126
+ throw new Error('SDK config not found');
21127
+ }
21128
+ // 更新配置中的 token
21129
+ const updatedConfig = {
21130
+ ...this.config,
21131
+ token: token && token.trim() !== '' ? token : undefined
21132
+ };
21133
+ if (this.debug) {
21134
+ console.log('Updating token:', token ? 'Token provided' : 'Token removed');
21135
+ }
21136
+ // 强制重新初始化以应用新的 token
21137
+ return await this.init(updatedConfig, options, true);
21138
+ }
21042
21139
  /**
21043
21140
  * 销毁 SDK
21044
21141
  */
@@ -21051,6 +21148,7 @@ class CustomerServiceSDK {
21051
21148
  this.screenshotManager = null;
21052
21149
  this.config = null;
21053
21150
  this.initResult = null;
21151
+ this.lastIconConfig = null;
21054
21152
  this.isInitialized = false;
21055
21153
  if (this.debug) {
21056
21154
  console.log('CustomerSDK destroyed');
@@ -21095,6 +21193,36 @@ class CustomerServiceSDK {
21095
21193
  return fallbackId;
21096
21194
  }
21097
21195
  }
21196
+ /**
21197
+ * 检查图标配置是否变化
21198
+ */
21199
+ isIconConfigChanged(newPosition, newTarget) {
21200
+ // 如果没有保存的配置,说明是首次初始化,需要创建
21201
+ if (!this.lastIconConfig) {
21202
+ return true;
21203
+ }
21204
+ // 比较位置配置
21205
+ const positionChanged = JSON.stringify(this.lastIconConfig.position) !== JSON.stringify(newPosition);
21206
+ // 比较 target 配置
21207
+ const oldTarget = this.lastIconConfig.target;
21208
+ let targetChanged = false;
21209
+ if (oldTarget !== newTarget) {
21210
+ // 如果引用不同,进一步检查
21211
+ if (typeof oldTarget === 'string' && typeof newTarget === 'string') {
21212
+ // 都是字符串,比较值
21213
+ targetChanged = oldTarget !== newTarget;
21214
+ }
21215
+ else if (oldTarget instanceof HTMLElement && newTarget instanceof HTMLElement) {
21216
+ // 都是 HTMLElement,比较引用(引用不同就是变化了)
21217
+ targetChanged = true;
21218
+ }
21219
+ else {
21220
+ // 类型不同,肯定是变化了
21221
+ targetChanged = true;
21222
+ }
21223
+ }
21224
+ return positionChanged || targetChanged;
21225
+ }
21098
21226
  /**
21099
21227
  * 构建iframe URL(带用户参数和设备ID)
21100
21228
  */
@@ -21122,13 +21250,14 @@ let globalSDKInstance = null;
21122
21250
  * 初始化 Customer SDK
21123
21251
  * @param config SDK配置
21124
21252
  * @param options UI选项(可选)
21253
+ * @param forceReinit 是否强制重新初始化(用于更新token等配置)
21125
21254
  * @returns 返回初始化信息(包含设备ID等)
21126
21255
  */
21127
- const init = async (config, options) => {
21256
+ const init = async (config, options, forceReinit = false) => {
21128
21257
  if (!globalSDKInstance) {
21129
21258
  globalSDKInstance = new CustomerServiceSDK();
21130
21259
  }
21131
- return await globalSDKInstance.init(config, options);
21260
+ return await globalSDKInstance.init(config, options, forceReinit);
21132
21261
  };
21133
21262
  /**
21134
21263
  * 获取全局SDK实例
@@ -21237,6 +21366,16 @@ const updateScreenshotOptions = (options) => {
21237
21366
  const sdk = getInstance();
21238
21367
  sdk.updateScreenshotOptions(options);
21239
21368
  };
21369
+ /**
21370
+ * 更新 token(用于用户登录/退出场景)
21371
+ * @param token 新的 token(传空字符串或 undefined 表示移除 token)
21372
+ * @param options UI选项(可选)
21373
+ * @returns 返回更新后的初始化信息
21374
+ */
21375
+ const updateToken = async (token, options) => {
21376
+ const sdk = getInstance();
21377
+ return await sdk.updateToken(token, options);
21378
+ };
21240
21379
  // 默认导出
21241
21380
  var index = {
21242
21381
  init,
@@ -21259,7 +21398,8 @@ var index = {
21259
21398
  enableScreenshot,
21260
21399
  getScreenshotState,
21261
21400
  updateScreenshotOptions,
21401
+ updateToken,
21262
21402
  destroy
21263
21403
  };
21264
21404
 
21265
- 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 };
21405
+ 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 };