@tencentcloud/ai-desk-customer-vue 1.5.5 → 1.5.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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 1.5.6 @2025.8.5
2
+
3
+ ### Features
4
+ - 保障反复切换账号、切换客服号场景下的会话状态的准确性。
5
+ - 强校验 `userID`。
6
+
1
7
  ## 1.5.5 @2024.7.30
2
8
 
3
9
  ### Fixed
@@ -256,7 +256,7 @@ const initLanguage = () => {
256
256
  let navigatorLang = convertLanguageToLowercase(navigator.language);
257
257
  language = getValidLanguage(navigatorLang);
258
258
  }
259
- }
259
+ }
260
260
  currentLanguage.value = language;
261
261
  state.set('currentLanguage', language);
262
262
  TUITranslateService.changeLanguage(language);
@@ -392,13 +392,7 @@ function onCurrentConversationIDUpdate(conversationID: string) {
392
392
  return;
393
393
  }
394
394
 
395
- if (currentConversationID.value === conversationID) {
396
- return;
397
- }
398
-
399
395
  currentConversationID.value = conversationID;
400
-
401
- // The TUICustomerServicePlugin plugin determines if the current conversation is a customer service conversation, then sets chatType and activates the conversation.
402
396
  activeConversation();
403
397
  }
404
398
 
@@ -451,6 +445,7 @@ function changeLanguage(languageCode: string) {
451
445
  activeConversation();
452
446
  });
453
447
  }
448
+
454
449
  function activeConversation() {
455
450
  TUICore.callService({
456
451
  serviceName: TUIConstants.TUICustomerServicePlugin.SERVICE.NAME,
@@ -328,6 +328,7 @@ export default {
328
328
  padding: 6px 10px;
329
329
  color: white;
330
330
  border-radius: 20px;
331
+ min-width: 100px;
331
332
  }
332
333
  .icon-container {
333
334
  position: relative;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送":"Unable to send the file as it exceeds 100 MB",
31
31
  "image 大小超过 20MB,无法发送":"Unable to send the image as it exceeds 20 MB",
32
32
  "video 大小超过 100MB,无法发送":"Unable to send the video as it exceeds 100 MB",
33
+ "userID 只能包含可打印 ASCII 字符": "The userID can only contain printable ASCII characters",
34
+ "userID 不能包含'administrator'": "The userID cannot contain the string 'administrator'",
35
+ "userID 长度不能超过45字节": "The length of the userID cannot exceed 45 bytes",
33
36
  }
34
37
  export default AIDesk;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送":"Lampas sa 100MB ang file, hindi maipadala",
31
31
  "image 大小超过 20MB,无法发送":"Hindi maipadala ang larawan dahil lampas ito sa 20 MB",
32
32
  "video 大小超过 100MB,无法发送":"Hindi maipadala ang video dahil lampas ito sa 100 MB",
33
+ "userID 只能包含可打印 ASCII 字符": "Ang UserID ay dapat naglalaman lamang ng printable ASCII characters",
34
+ "userID 不能包含'administrator'": "Ang UserID ay hindi dapat maglaman ng 'administrator'",
35
+ "userID 长度不能超过45字节": "Ang haba ng UserID ay hindi dapat lumampas sa 45 bytes",
33
36
  }
34
37
  export default AIDesk;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送":"Ukuran file melebihi 100MB, tidak dapat dikirim",
31
31
  "image 大小超过 20MB,无法发送":"Tidak dapat mengirim gambar karena melebihi 20 MB",
32
32
  "video 大小超过 100MB,无法发送":"Tidak dapat mengirim video karena melebihi 100 MB",
33
+ "userID 只能包含可打印 ASCII 字符": "UserID hanya boleh berisi karakter ASCII yang dapat dicetak",
34
+ "userID 不能包含'administrator'": "UserID tidak boleh mengandung 'administrator'",
35
+ "userID 长度不能超过45字节": "Panjang UserID tidak boleh melebihi 45 byte",
33
36
  }
34
37
  export default AIDesk;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送":"ファイルサイズが100MBを超えているため送信できません",
31
31
  "image 大小超过 20MB,无法发送":"画像のサイズが20MBを超えているため送信できません",
32
32
  "video 大小超过 100MB,无法发送":"動画のサイズが100MBを超えているため送信できません",
33
+ "userID 只能包含可打印 ASCII 字符": "UserIDは印字可能なASCII文字のみを含める必要があります",
34
+ "userID 不能包含'administrator'": "UserIDに'administrator'を含めることはできません",
35
+ "userID 长度不能超过45字节": "UserIDの長さは45バイトを超えてはいけません",
33
36
  }
34
37
  export default AIDesk;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送":"Saiz fail melebihi 100MB, tidak boleh dihantar",
31
31
  "image 大小超过 20MB,无法发送":"Tidak dapat menghantar gambar kerana melebihi 20 MB",
32
32
  "video 大小超过 100MB,无法发送":"Tidak dapat menghantar video kerana melebihi 100 MB",
33
+ "userID 只能包含可打印 ASCII 字符": "UserID hanya boleh mengandung aksara ASCII yang boleh dicetak",
34
+ "userID 不能包含'administrator'": "UserID tidak boleh mengandung 'administrator'",
35
+ "userID 长度不能超过45字节": "Panjang UserID tidak boleh melebihi 45 bait",
33
36
  }
34
37
  export default AIDesk;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送":"Размер файла превышает 100MB, отправка невозможна",
31
31
  "image 大小超过 20MB,无法发送":"Невозможно отправить изображение, так как оно превышает 20 MB",
32
32
  "video 大小超过 100MB,无法发送":"Невозможно отправить видео, так как оно превышает 100 MB",
33
+ "userID 只能包含可打印 ASCII 字符": "UserID должен содержать только печатные символы ASCII",
34
+ "userID 不能包含'administrator'": "UserID не должен содержать 'administrator'",
35
+ "userID 长度不能超过45字节": "Длина UserID не должна превышать 45 байт",
33
36
  }
34
37
  export default AIDesk;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送":"ขนาดไฟล์เกิน 100MB ไม่สามารถส่งได้",
31
31
  "image 大小超过 20MB,无法发送":"ไม่สามารถส่งรูปภาพได้เนื่องจากขนาดเกิน 20 MB",
32
32
  "video 大小超过 100MB,无法发送":"ไม่สามารถส่งวิดีโอได้เนื่องจากขนาดเกิน 100 MB",
33
+ "userID 只能包含可打印 ASCII 字符": "UserID ต้องมีเฉพาะตัวอักษร ASCII ที่พิมพ์ได้เท่านั้น",
34
+ "userID 不能包含'administrator'": "UserID ห้ามมี 'administrator'",
35
+ "userID 长度不能超过45字节": "ความยาว UserID ต้องไม่เกิน 45 ไบต์",
33
36
  }
34
37
  export default AIDesk;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送":"Kích thước tệp vượt quá 100MB, không thể gửi",
31
31
  "image 大小超过 20MB,无法发送":"Không thể gửi hình ảnh do vượt quá 20 MB",
32
32
  "video 大小超过 100MB,无法发送":"Không thể gửi video do vượt quá 100 MB",
33
+ "userID 只能包含可打印 ASCII 字符": "UserID chỉ được chứa ký tự ASCII có thể in được",
34
+ "userID 不能包含'administrator'": "UserID không được chứa 'administrator'",
35
+ "userID 长度不能超过45字节": "Độ dài UserID không được vượt quá 45 byte",
33
36
  }
34
37
  export default AIDesk;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送": "file 大小超过 100MB,无法发送",
31
31
  "image 大小超过 20MB,无法发送":"image 大小超过 20MB,无法发送",
32
32
  "video 大小超过 100MB,无法发送":"video 大小超过 100MB,无法发送",
33
+ "userID 只能包含可打印 ASCII 字符": "userID 只能包含可打印 ASCII 字符",
34
+ "userID 不能包含'administrator'": "userID 不能包含'administrator'",
35
+ "userID 长度不能超过45字节": "userID 长度不能超过45字节",
33
36
  }
34
37
  export default AIDesk;
@@ -30,5 +30,8 @@ const AIDesk = {
30
30
  "file 大小超过 100MB,无法发送":"檔案大小超過100MB,無法傳送",
31
31
  "image 大小超过 20MB,无法发送":"圖片大小超過20MB,無法傳送",
32
32
  "video 大小超过 100MB,无法发送":"影片大小超過100MB,無法傳送",
33
+ "userID 只能包含可打印 ASCII 字符": "userID 只能包含可打印 ASCII 字元",
34
+ "userID 不能包含'administrator'": "userID 不能包含'administrator'",
35
+ "userID 长度不能超过45字节": "userID 長度不能超過45位元組",
33
36
  }
34
37
  export default AIDesk;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencentcloud/ai-desk-customer-vue",
3
- "version": "1.5.5",
3
+ "version": "1.5.6",
4
4
  "description": "Vue2/Vue3 UIKit for AI Desk",
5
5
  "main": "index",
6
6
  "keywords": [
package/server.ts CHANGED
@@ -19,9 +19,9 @@ import TUIChatEngine, {
19
19
  import Log from './utils/logger';
20
20
  import { version } from './package.json'
21
21
  import { Toast, TOAST_TYPE } from "./components/common/Toast/index-web";
22
- import { switchReadStatus, transferToHuman, transferToTaskFlow } from "./utils/utils";
22
+ import { switchReadStatus, transferToHuman, transferToTaskFlow, validateUserID } from "./utils/utils";
23
23
  import state from "./utils/state";
24
- import { CUSTOM_MESSAGE_SRC, USER_DEFAULT_AVATAR } from "./constant";
24
+ import { USER_DEFAULT_AVATAR } from "./constant";
25
25
  import { vueVersion } from "./adapter-vue-web";
26
26
  import { ITransferToHumanModel, ITransferToTaskFlowModel } from './interface';
27
27
 
@@ -46,6 +46,7 @@ export default class TUICustomerServer {
46
46
  private currentCustomerServiceID: string;
47
47
  private loggedInUserID: string;
48
48
  private myProfile: IProfile;
49
+ private paramsForActiveAgain: any;
49
50
  constructor() {
50
51
  TUICore.registerService(TUIConstants.TUICustomerServicePlugin.SERVICE.NAME, this);
51
52
  TUICore.registerExtension(TUIConstants.TUIContact.EXTENSION.CONTACT_LIST.EXT_ID, this);
@@ -63,9 +64,9 @@ export default class TUICustomerServer {
63
64
  return TUICustomerServer.instance;
64
65
  }
65
66
 
66
- private loginCustomerUIKit(SDKAppID:number, userID:string, userSig:string) {
67
+ private async loginCustomerUIKit(SDKAppID:number, userID:string, userSig:string) {
67
68
  clearChatStorage(SDKAppID, userID);
68
- TUIChatEngine.login({
69
+ return TUIChatEngine.login({
69
70
  SDKAppID,
70
71
  userID,
71
72
  userSig,
@@ -74,7 +75,7 @@ export default class TUICustomerServer {
74
75
  Log.i(`login success. userID:${userID}`);
75
76
  this.isLoggedIn = true;
76
77
  this.loggedInUserID = userID;
77
- TUIConversationService.switchConversation(`C2C${this.currentCustomerServiceID}`);
78
+ this.switchConversation(`C2C${this.currentCustomerServiceID}`);
78
79
  switchReadStatus(state.get('showReadStatus'));
79
80
  TUIChatEngine.chat.callExperimentalAPI('isFeatureEnabledForStat', Math.pow(2, 42));
80
81
  })
@@ -88,24 +89,45 @@ export default class TUICustomerServer {
88
89
  })
89
90
  }
90
91
 
91
- public init(SDKAppID:number, userID:string, userSig:string) {
92
+ public async init(SDKAppID:number, userID:string, userSig:string) {
92
93
  Log.l(`TUICustomerServer.init vueVersion:${vueVersion} version:${version} SDKAppID:${SDKAppID} userID:${userID}` +
93
94
  ` isLoggedIn:${this.isLoggedIn} loggedInUserID:${this.loggedInUserID} currentCustomerServiceID:${this.currentCustomerServiceID}`);
95
+ if (userID) {
96
+ let ret = validateUserID(userID);
97
+ if (ret > 0) {
98
+ setTimeout(() => {
99
+ let reason = '';
100
+ if (ret === 1) {
101
+ reason = TUITranslateService.t("AIDesk.userID 只能包含可打印 ASCII 字符");
102
+ } else if (ret === 2) {
103
+ reason = TUITranslateService.t("AIDesk.userID 不能包含'administrator'");
104
+ } else if (ret === 3) {
105
+ reason = TUITranslateService.t("AIDesk.userID 长度不能超过45字节");
106
+ }
107
+ Toast({
108
+ message: reason,
109
+ type: TOAST_TYPE.ERROR,
110
+ duration: 30000,
111
+ });
112
+ }, 500);
113
+ return;
114
+ }
115
+ }
94
116
  if (this.isLoggedIn) {
95
117
  if (this.loggedInUserID === userID) {
96
- TUIConversationService.switchConversation(`C2C${this.currentCustomerServiceID}`);
118
+ await this.switchConversation(`C2C${this.currentCustomerServiceID}`);
97
119
  return;
98
120
  }
99
- this.unInit().finally(() => {
121
+ return this.unInit().finally(() => {
100
122
  this.isLoggedIn = false;
101
123
  this.loginCustomerUIKit(SDKAppID, userID, userSig);
102
124
  });
103
125
  } else {
104
- this.loginCustomerUIKit(SDKAppID, userID, userSig);
126
+ return this.loginCustomerUIKit(SDKAppID, userID, userSig);
105
127
  }
106
128
  }
107
129
 
108
- public initWithProfile(options: IInitWithProfile) {
130
+ public async initWithProfile(options: IInitWithProfile) {
109
131
  const { SDKAppID, userID, userSig, nickName, avatar, customerServiceID } = options;
110
132
  Log.l(`TUICustomerServer.initWithProfile version:${version}`);
111
133
  if (nickName) {
@@ -118,10 +140,10 @@ export default class TUICustomerServer {
118
140
  if (customerServiceID) {
119
141
  this.currentCustomerServiceID = customerServiceID;
120
142
  }
121
- this.init(SDKAppID, userID, userSig);
143
+ return this.init(SDKAppID, userID, userSig);
122
144
  }
123
145
 
124
- public unInit() {
146
+ public async unInit() {
125
147
  this.isLoggedIn = false;
126
148
  return TUIChatEngine.logout();
127
149
  }
@@ -228,9 +250,18 @@ export default class TUICustomerServer {
228
250
  }
229
251
  }
230
252
 
253
+ private async switchConversation(conversationID: string) {
254
+ const ret = await TUIConversationService.switchConversation(conversationID);
255
+ // -100002 即要切换的会话 ID 跟当前已打开的会话 ID 相同,这个时候我们重发 src 7,确保服务流状态正确
256
+ if (ret.code === -100002) {
257
+ this.activeServiceFlow(this.paramsForActiveAgain);
258
+ }
259
+ }
260
+
231
261
  // 激活会话服务流
232
262
  private activeServiceFlow(params: any) {
233
- Log.i(`activeServiceFlow params: language:${params.robotLang} country:${params.country} timezone:${params.timezone}`)
263
+ Log.i(`TUICustomerServer.activeServiceFlow params: language:${params.robotLang} country:${params.country} timezone:${params.timezone}`);
264
+ this.paramsForActiveAgain = { ...params };
234
265
  TUIChatService.sendCustomMessage({
235
266
  to: params.conversationID.slice(3),
236
267
  conversationType: TUIChatEngine.TYPES.CONV_C2C,
@@ -238,8 +269,8 @@ export default class TUICustomerServer {
238
269
  data: JSON.stringify({
239
270
  src: '7',
240
271
  customerServicePlugin: 0,
241
- triggeredContent: {
242
- language: params.robotLang,
272
+ triggeredContent: {
273
+ language: params.robotLang,
243
274
  country: params.country,
244
275
  timezone: params.timezone,
245
276
  }
@@ -247,5 +278,6 @@ export default class TUICustomerServer {
247
278
  },
248
279
  }, { onlineUserOnly: true });
249
280
  TUIStore.update(StoreName.CUSTOM, "isInSession", true);
281
+ Log.w(`TUICustomerServer.activeServiceFlow src 7 sent`);
250
282
  }
251
283
  }
package/utils/utils.ts CHANGED
@@ -306,4 +306,19 @@ export function transferToHuman(conversationID: string, groupID?: number, specif
306
306
  })
307
307
  }
308
308
  },{ onlineUserOnly: description ? false : true });
309
+ }
310
+
311
+ export function validateUserID(userID: string) {
312
+ let ret = 0;
313
+ if (!/^[\x20-\x7E]+$/.test(userID)) {
314
+ ret = 1;
315
+ }
316
+ if (userID.toLowerCase().includes('administrator')) {
317
+ ret = 2;
318
+ }
319
+ const byteSize = new TextEncoder().encode(userID).length;
320
+ if (byteSize > 45) {
321
+ ret = 3;
322
+ }
323
+ return ret;
309
324
  }