@aochuang/client-sdk 1.0.344 → 1.0.345

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.
Files changed (142) hide show
  1. package/components/index.js +1 -6
  2. package/components/session-select/session-select-item.vue +9 -8
  3. package/components/wechat-chat-control/calling/calling.vue +3 -0
  4. package/components/wechat-chat-control/voice/voice.vue +4 -0
  5. package/components/wework-chat-control/company-card/company-card.vue +1 -1
  6. package/components/wework-chat-control/file-url/file-url.vue +5 -2
  7. package/components/wework-chat-control/image/image.vue +2 -137
  8. package/components/wework-chat-control/index.js +6 -6
  9. package/components/wework-chat-control/text/text.vue +3 -22
  10. package/components/wework-chat-control/util.js +6 -12
  11. package/components/wework-chat-control/video/video.vue +2 -10
  12. package/components/wework-chat-control/voice/voice.vue +1 -1
  13. package/components/wework-chat-panel/chat-panel-controls/company-card/company-card.vue +35 -0
  14. package/components/wework-chat-panel/chat-panel-controls/expression/expression.vue +36 -0
  15. package/components/wework-chat-panel/chat-panel-controls/file-url/file-url.vue +35 -0
  16. package/components/wework-chat-panel/chat-panel-controls/image/image.vue +36 -0
  17. package/components/wework-chat-panel/chat-panel-controls/index.js +35 -0
  18. package/components/wework-chat-panel/chat-panel-controls/jx-sys-text/jx-sys-text.vue +28 -0
  19. package/components/wework-chat-panel/chat-panel-controls/link/link.vue +35 -0
  20. package/components/wework-chat-panel/chat-panel-controls/location/location.vue +35 -0
  21. package/components/wework-chat-panel/chat-panel-controls/text/text.vue +43 -0
  22. package/components/wework-chat-panel/chat-panel-controls/unkonw/unkonw.vue +39 -0
  23. package/components/wework-chat-panel/chat-panel-controls/video/video.vue +37 -0
  24. package/components/wework-chat-panel/chat-panel-controls/voice/voice.vue +35 -0
  25. package/components/wework-chat-panel/chat-panel-item.vue +35 -12
  26. package/components/wework-chat-panel/chat-panel.vue +12 -95
  27. package/package.json +3 -10
  28. package/services/client-chat/client-chat-wechat/client-chat-account.js +1 -1
  29. package/services/client-chat/client-chat-wechat/client-chat-session.js +106 -14
  30. package/services/client-chat/client-chat-wechat/client-chat.js +226 -50
  31. package/services/client-chat/client-chat-wework/client-chat-concats.js +17 -81
  32. package/services/client-chat/client-chat-wework/client-chat-message.js +5 -5
  33. package/services/client-chat/client-chat-wework/client-chat-session.js +2 -50
  34. package/services/client-chat/client-chat-wework/client-chat-socket.js +1 -9
  35. package/services/client-chat/client-chat-wework/client-chat.js +11 -278
  36. package/services/client-chat/client-chat-wework/utils.js +5 -5
  37. package/uni-common/account-portray/account-portray.vue +51 -0
  38. package/uni-common/account-select/account-select-item.vue +172 -0
  39. package/uni-common/account-select/account-select.vue +252 -0
  40. package/uni-common/all-friend-avatar/all-friend-avatar.vue +49 -0
  41. package/uni-common/friend-avatar/default.svg +1 -0
  42. package/uni-common/friend-avatar/friend-avatar.vue +27 -0
  43. package/uni-common/friend-avatar/index.js +3 -0
  44. package/uni-common/friend-loader/friend-loader.vue +53 -0
  45. package/uni-common/friend-portray/friend-portray.vue +56 -0
  46. package/uni-common/group-avatar/default.svg +1 -0
  47. package/uni-common/group-avatar/group-avatar.vue +18 -0
  48. package/uni-common/group-avatar/index.js +3 -0
  49. package/uni-common/room-avatar/default.svg +6 -0
  50. package/uni-common/room-avatar/index.js +3 -0
  51. package/uni-common/room-avatar/room-avatar.vue +27 -0
  52. package/uni-common/room-loader/room-loader.vue +53 -0
  53. package/uni-common/room-portray/room-portray.vue +56 -0
  54. package/uni-components/chat-control/calling/calling.vue +91 -0
  55. package/uni-components/chat-control/calling/phone-fill.svg +1 -0
  56. package/uni-components/chat-control/calling/vidicon-fill.svg +1 -0
  57. package/uni-components/chat-control/channel-video/channel-video.vue +89 -0
  58. package/uni-components/chat-control/channel-video-card/channel-video-card.vue +105 -0
  59. package/uni-components/chat-control/channel-video-live/channel-video-live.vue +92 -0
  60. package/uni-components/chat-control/chat-control-config-item/chat-control-config-item.vue +20 -0
  61. package/uni-components/chat-control/chat-control-config-item/index.js +3 -0
  62. package/uni-components/chat-control/chat-control-config-msg/chat-control-config-msg-app.vue +25 -0
  63. package/uni-components/chat-control/chat-control-config-msg/chat-control-config-msg-h5.vue +21 -0
  64. package/{components/wework-chat-control/wework-chat-control-config.vue → uni-components/chat-control/chat-control-config.vue} +13 -16
  65. package/uni-components/chat-control/chat-control.vue +218 -0
  66. package/uni-components/chat-control/company-card/company-card.vue +123 -0
  67. package/uni-components/chat-control/const.js +28 -0
  68. package/uni-components/chat-control/expression/expression.vue +41 -0
  69. package/uni-components/chat-control/image/image.vue +68 -0
  70. package/uni-components/chat-control/index.js +89 -0
  71. package/uni-components/chat-control/location/location.vue +110 -0
  72. package/uni-components/chat-control/member-change/member-change.vue +32 -0
  73. package/uni-components/chat-control/quote-message/quote-message.vue +216 -0
  74. package/uni-components/chat-control/real-time-position/real-time-position.vue +62 -0
  75. package/uni-components/chat-control/redpacket/red-envelope.svg +1 -0
  76. package/uni-components/chat-control/redpacket/redpacket.vue +75 -0
  77. package/uni-components/chat-control/share-card/share-card.vue +101 -0
  78. package/uni-components/chat-control/system/system.vue +69 -0
  79. package/uni-components/chat-control/system-batch-message/system-batch-message.vue +30 -0
  80. package/uni-components/chat-control/system-text/system-text.vue +32 -0
  81. package/uni-components/chat-control/text/text.vue +67 -0
  82. package/uni-components/chat-control/text-with-at/text-with-at.vue +51 -0
  83. package/uni-components/chat-control/transfer/red-transfer.svg +1 -0
  84. package/uni-components/chat-control/transfer/transfer.vue +80 -0
  85. package/uni-components/chat-control/unkonw/unkonw.vue +37 -0
  86. package/uni-components/chat-control/url/icons/file-excel-line.svg +1 -0
  87. package/uni-components/chat-control/url/icons/file-info-line.svg +1 -0
  88. package/uni-components/chat-control/url/icons/file-music-line.svg +1 -0
  89. package/uni-components/chat-control/url/icons/file-pdf-line.svg +1 -0
  90. package/uni-components/chat-control/url/icons/file-ppt-line.svg +1 -0
  91. package/uni-components/chat-control/url/icons/file-settings-line.svg +1 -0
  92. package/uni-components/chat-control/url/icons/file-text-line.svg +1 -0
  93. package/uni-components/chat-control/url/icons/file-unknow-line.svg +1 -0
  94. package/uni-components/chat-control/url/icons/file-word-line.svg +1 -0
  95. package/uni-components/chat-control/url/icons/file-zip-line.svg +1 -0
  96. package/uni-components/chat-control/url/icons/index.js +24 -0
  97. package/uni-components/chat-control/url/miniprogram.svg +1 -0
  98. package/uni-components/chat-control/url/url-miniprogram.vue +116 -0
  99. package/uni-components/chat-control/url/url.vue +306 -0
  100. package/uni-components/chat-control/url-new/icons/file-excel-line.svg +1 -0
  101. package/uni-components/chat-control/url-new/icons/file-info-line.svg +1 -0
  102. package/uni-components/chat-control/url-new/icons/file-music-line.svg +1 -0
  103. package/uni-components/chat-control/url-new/icons/file-pdf-line.svg +1 -0
  104. package/uni-components/chat-control/url-new/icons/file-ppt-line.svg +1 -0
  105. package/uni-components/chat-control/url-new/icons/file-settings-line.svg +1 -0
  106. package/uni-components/chat-control/url-new/icons/file-text-line.svg +1 -0
  107. package/uni-components/chat-control/url-new/icons/file-unknow-line.svg +1 -0
  108. package/uni-components/chat-control/url-new/icons/file-word-line.svg +1 -0
  109. package/uni-components/chat-control/url-new/icons/file-zip-line.svg +1 -0
  110. package/uni-components/chat-control/url-new/icons/index.js +24 -0
  111. package/uni-components/chat-control/url-new/url-new.vue +110 -0
  112. package/uni-components/chat-control/utils.js +12 -0
  113. package/uni-components/chat-control/video/video.vue +156 -0
  114. package/uni-components/chat-control/voice/voice.vue +166 -0
  115. package/uni-components/chat-editor/chat-editor-chartlet/chat-editor-chartlet-collect.vue +84 -0
  116. package/uni-components/chat-editor/chat-editor-chartlet/chat-editor-chartlet-system.vue +28 -0
  117. package/uni-components/chat-editor/chat-editor-chartlet/chat-editor-chartlet.vue +85 -0
  118. package/uni-components/chat-editor/chat-editor-func/chat-editor-func.vue +157 -0
  119. package/uni-components/chat-editor/chat-editor-func-at/chat-editor-func-at-panel.vue +158 -0
  120. package/uni-components/chat-editor/chat-editor-func-at/chat-editor-func-at.vue +61 -0
  121. package/uni-components/chat-editor/chat-editor-func-button/chat-editor-func-button.vue +58 -0
  122. package/uni-components/chat-editor/chat-editor-func-file/chat-editor-func-file.vue +54 -0
  123. package/uni-components/chat-editor/chat-editor-func-image/chat-editor-func-image.vue +42 -0
  124. package/uni-components/chat-editor/chat-editor-func-video/chat-editor-func-video.vue +42 -0
  125. package/uni-components/chat-editor/chat-editor-func-voice/chat-editor-func-voice.vue +25 -0
  126. package/uni-components/chat-editor/chat-editor-message-send/chat-editor-message-send.vue +158 -0
  127. package/uni-components/chat-editor/chat-editor-quote/chat-editor-quote.vue +75 -0
  128. package/uni-components/chat-editor/chat-editor.vue +257 -0
  129. package/uni-components/chat-editor/index.js +10 -0
  130. package/uni-components/chat-editor/util.js +65 -0
  131. package/uni-components/chat-panel/chat-panel-chats-box.vue +238 -0
  132. package/uni-components/chat-panel/chat-panel-chats-forward/chat-panel-chats-forward.vue +273 -0
  133. package/uni-components/chat-panel/chat-panel-chats-item.vue +578 -0
  134. package/uni-components/chat-panel/chat-panel-chats-status/chat-panel-chats-status.vue +71 -0
  135. package/uni-components/chat-panel/chat-panel-chats.vue +368 -0
  136. package/uni-components/chat-panel/chat-panel.vue +227 -0
  137. package/uni-components/contacts-group-select/contacts-group-select-item.vue +85 -0
  138. package/uni-components/contacts-group-select/contacts-group-select-panel.vue +119 -0
  139. package/uni-components/contacts-group-select/contacts-group-select.vue +150 -0
  140. package/components/wework-chat-control/wework-chat-control-config-item.vue +0 -24
  141. package/components/wework-chat-control/wework-chat-control-config-msg.vue +0 -25
  142. package/components/wework-chat-panel/chat-panel-chat-status/chat-panel-chat-status.vue +0 -73
@@ -5,20 +5,39 @@ import { createPollRequest } from '../../../utils/util.js'
5
5
 
6
6
  const ALL_WECHAT_ACCOUNT_ID = 'all'
7
7
 
8
- const loopLoadAssignSessionData = (fetchFn, params) => {
8
+ const ASSIGN_SESSION_LOG_PREFIX = '[client-chat][assign-session]'
9
+ const ASSIGN_SESSION_MERGE_EXCLUDE_FIELDS = [
10
+ 'conversationId',
11
+ 'wechatAccountId',
12
+ 'lastMsgTime',
13
+ 'lastUpdateTime',
14
+ 'stickyOnTop',
15
+ 'mute',
16
+ 'lastAtMsgContent'
17
+ ]
18
+
19
+ const loopLoadAssignSessionData = (fetchFn, params, onPageLoaded) => {
9
20
  let lastPs = null
10
21
  let lastRs = null
11
22
  let result = []
23
+ let page = 0
12
24
  const loopFn = (params, total) => {
13
25
  const { taskId, size, ...nextParams } = params
26
+ page += 1
14
27
  lastPs = fetchFn(Object.assign({}, nextParams, {
15
28
  size,
16
29
  taskId,
17
30
  total
18
31
  }))
19
32
  lastRs = lastPs.then(rs => {
20
- result = result.concat(rs.data || [])
21
- if (rs.data.length < size) {
33
+ const pageData = rs.data || []
34
+ result = result.concat(pageData)
35
+ onPageLoaded && onPageLoaded({
36
+ page,
37
+ pageSize: pageData.length,
38
+ total: result.length
39
+ })
40
+ if (pageData.length < size) {
22
41
  return result
23
42
  } else {
24
43
  return loopFn(params, result.length)
@@ -188,7 +207,7 @@ export default class ClientChatSession {
188
207
  * @params { Object } data - 会话数据集合
189
208
  * @params { String } wechatAccountId - 如果传wechatAccountId那么后面addSession的时候如果传wechatAccountId那么才会更新lastUpdateTime或者lastMsgTime,本质的意思是只有通过reload和loadData才刷新lastUpdateTime或者lastMsgTime,避免这个时间乱套了
190
209
  */
191
- setSessionData (data, wechatAccountId, reset = true) {
210
+ setSessionData (data, wechatAccountId, reset = true, context) {
192
211
  if (reset) {
193
212
  this.sessionMap = {}
194
213
  this.data.sessionGroupData = {}
@@ -200,7 +219,7 @@ export default class ClientChatSession {
200
219
  if (item.isDeleted) {
201
220
  this.removeSession(item.conversationId)
202
221
  } else {
203
- this.addSession(item, wechatAccountId)
222
+ this.addSession(item, wechatAccountId, context)
204
223
  }
205
224
  })
206
225
  }
@@ -229,14 +248,14 @@ export default class ClientChatSession {
229
248
  }
230
249
 
231
250
  getSession (sessionId, serializeMethod) {
232
- if (this.sessionMap[sessionId]) {
251
+ if (this.sessionMap[sessionId]) {
233
252
  return Promise.resolve({
234
253
  data: this.sessionMap[sessionId]
235
254
  })
236
255
  }
237
256
  // 这里需要轮询从后端获取会话,后端会话更新和创建是异步的,所以要多轮训请求几次
238
257
  if (this.pollRequestMap[sessionId]) {
239
- this.pollRequestMap[sessionId].stop()
258
+ return this.pollRequestMap[sessionId].ps
240
259
  }
241
260
  const pollRequest = createPollRequest(({ done, fail }) => {
242
261
  return this.getSessionMethod({
@@ -248,7 +267,7 @@ export default class ClientChatSession {
248
267
  })
249
268
  })
250
269
  this.pollRequestMap[sessionId] = pollRequest
251
- return pollRequest.start().then(rs => {
270
+ this.pollRequestMap[sessionId].ps = pollRequest.start().then(rs => {
252
271
  if (serializeMethod) {
253
272
  rs = serializeMethod(rs)
254
273
  }
@@ -263,6 +282,7 @@ export default class ClientChatSession {
263
282
  delete this.pollRequestMap[sessionId]
264
283
  }
265
284
  })
285
+ return this.pollRequestMap[sessionId].ps
266
286
  }
267
287
 
268
288
  findSession (findFn) {
@@ -387,7 +407,7 @@ export default class ClientChatSession {
387
407
  * "wechatAccountId": "2a39a725814acf07502299ab2285fff8d44377f5"
388
408
  * }
389
409
  */
390
- addSession (data, wechatAccountId) {
410
+ addSession (data, wechatAccountId, context) {
391
411
  if (!data || !data.conversationId) {
392
412
  throw new Error('缺少必须参数conversationId')
393
413
  }
@@ -403,11 +423,54 @@ export default class ClientChatSession {
403
423
  return
404
424
  }
405
425
  let nextData = data
426
+ let assignMergeLog = null
406
427
  // 如果会话已经存在,那么取已经存在的,以后有需要可以用data更新已经存在的会话,保持引用关系
407
428
  if (this.sessionMap[data.conversationId]) {
408
429
  nextData = this.sessionMap[data.conversationId]
430
+ const unreadBefore = nextData.unreadMsgCount || 0
431
+ const muteBefore = !!nextData.mute
432
+ const changedFields = []
433
+ Object.keys(data).forEach(key => {
434
+ if (ASSIGN_SESSION_MERGE_EXCLUDE_FIELDS.indexOf(key) >= 0 || nextData[key] === data[key]) {
435
+ return
436
+ }
437
+ changedFields.push(key)
438
+ Vue.set(nextData, key, data[key])
439
+ })
440
+ if (context && context.source === 'assign-task') {
441
+ assignMergeLog = {
442
+ taskId: context.taskId,
443
+ conversationId: data.conversationId,
444
+ wechatAccountId: data.wechatAccountId,
445
+ existed: true,
446
+ changedFields,
447
+ unreadBefore,
448
+ unreadFromServer: data.unreadMsgCount || 0,
449
+ unreadAfter: nextData.unreadMsgCount || 0,
450
+ muteBefore,
451
+ muteFromServer: !!data.mute,
452
+ muteAfter: !!nextData.mute,
453
+ preservedFields: ASSIGN_SESSION_MERGE_EXCLUDE_FIELDS.slice()
454
+ }
455
+ }
409
456
  } else {
410
457
  this.sessionMap[data.conversationId] = nextData
458
+ if (context && context.source === 'assign-task') {
459
+ assignMergeLog = {
460
+ taskId: context.taskId,
461
+ conversationId: data.conversationId,
462
+ wechatAccountId: data.wechatAccountId,
463
+ existed: false,
464
+ changedFields: [],
465
+ unreadBefore: null,
466
+ unreadFromServer: data.unreadMsgCount || 0,
467
+ unreadAfter: data.unreadMsgCount || 0,
468
+ muteBefore: null,
469
+ muteFromServer: !!data.mute,
470
+ muteAfter: !!data.mute,
471
+ preservedFields: []
472
+ }
473
+ }
411
474
  }
412
475
  const topField = nextData.stickyOnTop ? 0 : 1 // 置顶
413
476
  if (wechatAccountId && wechatAccountId !== ALL_WECHAT_ACCOUNT_ID && nextData.wechatAccountId !== wechatAccountId) {
@@ -489,8 +552,11 @@ export default class ClientChatSession {
489
552
  this.data.virtualSessionData.splice(virtualSessionIndex, 1)
490
553
  }
491
554
  this.onAddSession && this.onAddSession({
492
- session: data
555
+ session: nextData
493
556
  })
557
+ if (assignMergeLog) {
558
+ console.info(ASSIGN_SESSION_LOG_PREFIX, 'merge', assignMergeLog)
559
+ }
494
560
  }
495
561
 
496
562
  removeSession (conversationId) {
@@ -624,7 +690,9 @@ export default class ClientChatSession {
624
690
  return true
625
691
  }
626
692
  })
627
- this.data.sessionGroupData[groupId][topField][oldSortFields.day][oldSortFields.milliseconds].splice(index, 1)
693
+ if (index >= 0) {
694
+ this.data.sessionGroupData[groupId][topField][oldSortFields.day][oldSortFields.milliseconds].splice(index, 1)
695
+ }
628
696
  }
629
697
  })
630
698
  })
@@ -684,7 +752,9 @@ export default class ClientChatSession {
684
752
  return true
685
753
  }
686
754
  })
687
- this.data.sessionGroupData[groupId][topField][sortFields.day][sortFields.milliseconds].splice(index, 1)
755
+ if (index >= 0) {
756
+ this.data.sessionGroupData[groupId][topField][sortFields.day][sortFields.milliseconds].splice(index, 1)
757
+ }
688
758
  }
689
759
  })
690
760
  })
@@ -829,14 +899,36 @@ export default class ClientChatSession {
829
899
  total: 0 , // 已获取总数
830
900
  size: 50 // 每次获取数量
831
901
  }, params)
902
+ const taskId = params.taskId
903
+ console.info(ASSIGN_SESSION_LOG_PREFIX, 'load-start', {
904
+ taskId,
905
+ total: params.total,
906
+ size: params.size
907
+ })
832
908
  this.data.loadAssignTaskSessioning = true
833
909
  return loopLoadAssignSessionData((nextParams) => {
834
910
  return this.loadAssignTaskSessionDataMethod(nextParams)
835
- }, params).then(rs => {
911
+ }, params, pageInfo => {
912
+ console.info(ASSIGN_SESSION_LOG_PREFIX, 'page-loaded', Object.assign({ taskId }, pageInfo))
913
+ }).then(rs => {
836
914
  if (rs && rs.length) {
837
- this.setSessionData(rs, null, false)
915
+ this.setSessionData(rs, null, false, {
916
+ source: 'assign-task',
917
+ taskId
918
+ })
838
919
  }
920
+ console.info(ASSIGN_SESSION_LOG_PREFIX, 'load-complete', {
921
+ taskId,
922
+ sessionCount: rs ? rs.length : 0,
923
+ wechatAccountIds: Array.from(new Set((rs || []).map(session => session.wechatAccountId)))
924
+ })
839
925
  return rs
926
+ }).catch(error => {
927
+ console.error(ASSIGN_SESSION_LOG_PREFIX, 'load-error', {
928
+ taskId,
929
+ message: error && error.message ? error.message : String(error)
930
+ })
931
+ throw error
840
932
  }).finally(() => {
841
933
  this.data.loadAssignTaskSessioning = false
842
934
  })
@@ -43,6 +43,136 @@ function appendLastAtMsgContent (lastAtMsgContent, atMessage) {
43
43
  return messages.concat(atMessage)
44
44
  }
45
45
 
46
+ const ASSIGN_SESSION_LOG_PREFIX = '[client-chat][assign-session]'
47
+
48
+ function getAccountUnreadSnapshot (account, accountIds) {
49
+ const accountIdMap = accountIds && accountIds.reduce((result, accountId) => {
50
+ result[accountId] = true
51
+ return result
52
+ }, {})
53
+ return (account.accountUnreadMessageNumData || []).filter(item => {
54
+ return !accountIdMap || accountIdMap[item.id]
55
+ }).map(item => ({
56
+ wechatAccountId: item.id,
57
+ unread: item.num || 0,
58
+ muteUnread: item.muteNum || 0
59
+ }))
60
+ }
61
+
62
+ function getAssignAccountIds (sessions) {
63
+ return Object.keys((sessions || []).reduce((result, session) => {
64
+ if (session && session.wechatAccountId) {
65
+ result[session.wechatAccountId] = true
66
+ }
67
+ return result
68
+ }, {}))
69
+ }
70
+
71
+ function getSessionUnreadSnapshot (sessionInstance) {
72
+ return Object.keys(sessionInstance.sessionMap || {}).reduce((result, conversationId) => {
73
+ const session = sessionInstance.sessionMap[conversationId]
74
+ result[conversationId] = {
75
+ wechatAccountId: session.wechatAccountId,
76
+ unread: session.unreadMsgCount || 0,
77
+ mute: !!session.mute
78
+ }
79
+ return result
80
+ }, {})
81
+ }
82
+
83
+ function getAssignUnreadChanges (clientChat, sessions, sessionUnreadBefore, accountIdBeforeMap, taskId) {
84
+ const sessionMap = {}
85
+ const sessionData = sessions || []
86
+ sessionData.forEach(session => {
87
+ if (!session || !session.conversationId) {
88
+ return
89
+ }
90
+ if (sessionMap[session.conversationId]) {
91
+ console.warn(ASSIGN_SESSION_LOG_PREFIX, 'duplicate-session', {
92
+ taskId,
93
+ conversationId: session.conversationId,
94
+ wechatAccountId: session.wechatAccountId
95
+ })
96
+ }
97
+ sessionMap[session.conversationId] = session
98
+ })
99
+ const accountChangeMap = {}
100
+ Object.keys(sessionMap).forEach(conversationId => {
101
+ const serverSession = sessionMap[conversationId]
102
+ const localSession = clientChat.session.sessionMap[conversationId] || serverSession
103
+ const before = sessionUnreadBefore[conversationId]
104
+ const beforeUnread = before ? before.unread : 0
105
+ const beforeMute = before ? before.mute : false
106
+ const afterUnread = localSession.unreadMsgCount || 0
107
+ const afterMute = !!localSession.mute
108
+ const wechatAccountId = localSession.wechatAccountId
109
+ if (!accountChangeMap[wechatAccountId]) {
110
+ accountChangeMap[wechatAccountId] = {
111
+ wechatAccountId,
112
+ unreadDelta: 0,
113
+ muteDelta: 0,
114
+ isNewAccount: !accountIdBeforeMap[wechatAccountId],
115
+ sessionCount: 0
116
+ }
117
+ }
118
+ accountChangeMap[wechatAccountId].unreadDelta += afterUnread - beforeUnread
119
+ accountChangeMap[wechatAccountId].muteDelta += (afterMute ? afterUnread : 0) - (beforeMute ? beforeUnread : 0)
120
+ accountChangeMap[wechatAccountId].sessionCount += 1
121
+ })
122
+ return Object.keys(accountChangeMap).map(accountId => accountChangeMap[accountId])
123
+ }
124
+
125
+ function updateAssignAccountUnread (clientChat, changes, taskId, eventType) {
126
+ return Promise.all(changes.map(change => {
127
+ const accountUnreadBefore = getAccountUnreadSnapshot(clientChat.account, [change.wechatAccountId])[0] || {
128
+ wechatAccountId: change.wechatAccountId,
129
+ unread: 0,
130
+ muteUnread: 0
131
+ }
132
+ let promise
133
+ let strategy
134
+ if (change.isNewAccount) {
135
+ strategy = 'server-refresh'
136
+ promise = clientChat.account.refreshAccountUnreadMessageNum({
137
+ wechatAccountId: change.wechatAccountId
138
+ })
139
+ } else if (change.unreadDelta || change.muteDelta) {
140
+ strategy = 'delta'
141
+ promise = clientChat.account.updateAccountUnreadMessageNum(change.wechatAccountId, ({ unreadMesasgeNum, unreadMessageMuteNum }) => ({
142
+ num: Math.max(0, (unreadMesasgeNum || 0) + change.unreadDelta),
143
+ muteNum: Math.max(0, (unreadMessageMuteNum || 0) + change.muteDelta)
144
+ }))
145
+ } else {
146
+ strategy = 'no-change'
147
+ promise = Promise.resolve()
148
+ }
149
+ return promise.then(() => {
150
+ console.info(ASSIGN_SESSION_LOG_PREFIX, 'account-unread-updated', {
151
+ eventType,
152
+ taskId,
153
+ wechatAccountId: change.wechatAccountId,
154
+ sessionCount: change.sessionCount,
155
+ unreadDelta: change.unreadDelta,
156
+ muteDelta: change.muteDelta,
157
+ strategy,
158
+ before: accountUnreadBefore,
159
+ after: getAccountUnreadSnapshot(clientChat.account, [change.wechatAccountId])[0] || null
160
+ })
161
+ }).catch(error => {
162
+ console.error(ASSIGN_SESSION_LOG_PREFIX, 'account-unread-update-error', {
163
+ eventType,
164
+ taskId,
165
+ wechatAccountId: change.wechatAccountId,
166
+ unreadDelta: change.unreadDelta,
167
+ muteDelta: change.muteDelta,
168
+ strategy,
169
+ message: error && error.message ? error.message : String(error)
170
+ })
171
+ throw error
172
+ })
173
+ }))
174
+ }
175
+
46
176
  class ClientChat {
47
177
  data = Vue.observable({
48
178
  connectStatus: CONNECT_STATUS.Normal
@@ -452,9 +582,15 @@ class ClientChat {
452
582
  }
453
583
  })
454
584
  })
455
- } else {
456
- this.session.updateSession(sessionId, ({ session }) => {
457
- const nextSession = {
585
+ } else {
586
+ this.session.updateSession(sessionId, ({ session }) => {
587
+ // listChange/getSession may already include this message in unreadMsgCount.
588
+ // Only count messages newer than the session watermark.
589
+ const isNewerMessage = data.wechatTime > (session.lastMsgTime || 0)
590
+ if (!isNewerMessage) {
591
+ return {}
592
+ }
593
+ const nextSession = {
458
594
  lastMsgContent: data.content,
459
595
  lastMsgType: data.msgType,
460
596
  lastMsgTime: data.wechatTime,
@@ -462,7 +598,7 @@ class ClientChat {
462
598
  lastUpdateTime: data.updateDate,
463
599
  unreadMsgCount: session.unreadMsgCount
464
600
  }
465
- if (!data.isSend) {
601
+ if (!data.isSend && isNewerMessage) {
466
602
  if (this.sessionManage.currentSession && this.sessionManage.currentSession.conversationId === sessionId && this.shouldMarkCurrentSessionRead(sessionId, data)) {
467
603
  // 标记已读
468
604
  this.session.setSessionRead(sessionId)
@@ -594,9 +730,15 @@ class ClientChat {
594
730
  }
595
731
  })
596
732
  })
597
- } else {
598
- this.session.updateSession(sessionId, ({ session }) => {
599
- const nextSession = {
733
+ } else {
734
+ this.session.updateSession(sessionId, ({ session }) => {
735
+ // listChange/getSession may already include this message in unreadMsgCount.
736
+ // Only count messages newer than the session watermark.
737
+ const isNewerMessage = data.wechatTime > (session.lastMsgTime || 0)
738
+ if (!isNewerMessage) {
739
+ return {}
740
+ }
741
+ const nextSession = {
600
742
  lastMsgContent: data.content,
601
743
  lastMsgType: data.msgType,
602
744
  lastMsgTime: data.wechatTime,
@@ -604,7 +746,7 @@ class ClientChat {
604
746
  lastUpdateTime: data.updateDate,
605
747
  unreadMsgCount: session.unreadMsgCount
606
748
  }
607
- if (!data.isSend) {
749
+ if (!data.isSend && isNewerMessage) {
608
750
  if (this.sessionManage.currentSession && this.sessionManage.currentSession.conversationId === sessionId && this.shouldMarkCurrentSessionRead(sessionId, data)) {
609
751
  // 标记已读
610
752
  this.session.setSessionRead(sessionId)
@@ -854,6 +996,16 @@ class ClientChat {
854
996
  },
855
997
  // 好友有变化,如分配的情况
856
998
  onCmdFriendInfoChanged: ({ data }) => {
999
+ const assignAccountUnreadBefore = data.changeType === 4 ? getAccountUnreadSnapshot(this.account) : null
1000
+ if (data.changeType === 4) {
1001
+ console.info(ASSIGN_SESSION_LOG_PREFIX, 'socket-event', {
1002
+ eventType: 'friend-info-changed',
1003
+ taskId: data.taskId,
1004
+ changeType: data.changeType,
1005
+ itemCount: Array.isArray(data.friends) ? data.friends.length : 0,
1006
+ accountUnreadBefore: assignAccountUnreadBefore
1007
+ })
1008
+ }
857
1009
  if (!this.socketFriendInfoChangedSerialQueue) {
858
1010
  this.socketFriendInfoChangedSerialQueue = createSerialQueue()
859
1011
  }
@@ -867,14 +1019,19 @@ class ClientChat {
867
1019
  accountIds: (this.account.accountData || []).map(v => v.id)
868
1020
  })
869
1021
  } else {
1022
+ const sessionUnreadBefore = getSessionUnreadSnapshot(this.session)
1023
+ const accountIdBeforeMap = Object.keys(this.account.accountMap || {}).reduce((result, accountId) => {
1024
+ result[accountId] = true
1025
+ return result
1026
+ }, {})
870
1027
  // 增量拉取分配产生的会话
871
1028
  return this.session.loadAssignTaskSessionData({
872
1029
  taskId: data.taskId
873
1030
  }).then((rs) => {
874
- const wechatAccountIds = Object.keys((rs || []).reduce((rs, v) => {
875
- rs[v.wechatAccountId] = true
876
- return rs
877
- }, {}))
1031
+ const wechatAccountIds = getAssignAccountIds(rs)
1032
+ const accountUnreadBefore = assignAccountUnreadBefore.filter(item => wechatAccountIds.indexOf(item.wechatAccountId) >= 0)
1033
+ const accountUnreadChanges = getAssignUnreadChanges(this, rs, sessionUnreadBefore, accountIdBeforeMap, data.taskId)
1034
+ let accountUnreadUpdated = false
878
1035
  const changeFriendMap = {}
879
1036
  // 删除changeType为3移除的好友,例如转移的场景
880
1037
  if (data.friends && data.friends.length) {
@@ -907,25 +1064,27 @@ class ClientChat {
907
1064
  return this.contacts.getFriend(sessionFriendId, true)
908
1065
  })
909
1066
  }
910
- // 刷新工作微信号未读消息数量
911
- if (rs && rs.length) {
912
- rs.forEach(session => {
913
- this.account.updateAccountUnreadMessageNum(session.wechatAccountId, ({ unreadMesasgeNum, unreadMessageMuteNum }) => {
914
- if (session.mute) {
915
- return {
916
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
917
- muteNum: (unreadMessageMuteNum || 0) + (session.unreadMsgCount || 0)
918
- }
919
- } else {
920
- return {
921
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
922
- muteNum: unreadMessageMuteNum
923
- }
924
- }
925
- })
1067
+ ps = ps.then(() => updateAssignAccountUnread(this, accountUnreadChanges, data.taskId, 'friend-info-changed')).then(() => {
1068
+ accountUnreadUpdated = true
1069
+ }).catch(error => {
1070
+ console.error(ASSIGN_SESSION_LOG_PREFIX, 'socket-process-error', {
1071
+ eventType: 'friend-info-changed',
1072
+ taskId: data.taskId,
1073
+ message: error && error.message ? error.message : String(error)
926
1074
  })
927
- }
1075
+ throw error
1076
+ })
928
1077
  return ps.finally(() => {
1078
+ console.info(ASSIGN_SESSION_LOG_PREFIX, 'socket-complete', {
1079
+ eventType: 'friend-info-changed',
1080
+ taskId: data.taskId,
1081
+ sessionCount: rs ? rs.length : 0,
1082
+ wechatAccountIds,
1083
+ accountUnreadChanges,
1084
+ accountUnreadBefore,
1085
+ accountUnreadAfter: getAccountUnreadSnapshot(this.account, wechatAccountIds),
1086
+ accountUnreadUpdated
1087
+ })
929
1088
  // 这里应该标记那些工作微信号的通讯录修改了,后面要在界面打个提示,告诉用户通讯录变化了,让手动刷新一下
930
1089
  // 同时也将缓存都清理一下,例如工作微信号分组统计数量等
931
1090
  this.contacts.markModify() // 标记通讯录修改
@@ -964,16 +1123,31 @@ class ClientChat {
964
1123
  },
965
1124
  // 群聊有变化,如分配的情况
966
1125
  onCmdChatroomInfoChanged: ({ data }) => {
1126
+ const assignAccountUnreadBefore = data.changeType === 4 ? getAccountUnreadSnapshot(this.account) : null
1127
+ if (data.changeType === 4) {
1128
+ console.info(ASSIGN_SESSION_LOG_PREFIX, 'socket-event', {
1129
+ eventType: 'chatroom-info-changed',
1130
+ taskId: data.taskId,
1131
+ changeType: data.changeType,
1132
+ itemCount: Array.isArray(data.chatrooms) ? data.chatrooms.length : 0,
1133
+ accountUnreadBefore: assignAccountUnreadBefore
1134
+ })
1135
+ }
967
1136
  // 配分群聊
968
1137
  if (data.changeType === 4) {
1138
+ const sessionUnreadBefore = getSessionUnreadSnapshot(this.session)
1139
+ const accountIdBeforeMap = Object.keys(this.account.accountMap || {}).reduce((result, accountId) => {
1140
+ result[accountId] = true
1141
+ return result
1142
+ }, {})
969
1143
  // 增量拉取分配产生的会话
970
1144
  return this.session.loadAssignTaskSessionData({
971
1145
  taskId: data.taskId
972
1146
  }).then((rs) => {
973
- const wechatAccountIds = Object.keys((rs || []).reduce((rs, v) => {
974
- rs[v.wechatAccountId] = true
975
- return rs
976
- }, {}))
1147
+ const wechatAccountIds = getAssignAccountIds(rs)
1148
+ const accountUnreadBefore = assignAccountUnreadBefore.filter(item => wechatAccountIds.indexOf(item.wechatAccountId) >= 0)
1149
+ const accountUnreadChanges = getAssignUnreadChanges(this, rs, sessionUnreadBefore, accountIdBeforeMap, data.taskId)
1150
+ let accountUnreadUpdated = false
977
1151
  // 删除changeType为3移除的群聊,例如转移的场景
978
1152
  if (data.chatrooms && data.chatrooms.length) {
979
1153
  data.chatrooms.forEach(room => {
@@ -989,25 +1163,27 @@ class ClientChat {
989
1163
  ps = this.account.reloadData()
990
1164
  }
991
1165
  }
992
- // 刷新工作微信号未读消息数量
993
- if (rs && rs.length) {
994
- rs.forEach(session => {
995
- this.account.updateAccountUnreadMessageNum(session.wechatAccountId, ({ unreadMesasgeNum, unreadMessageMuteNum }) => {
996
- if (session.mute) {
997
- return {
998
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
999
- muteNum: (unreadMessageMuteNum || 0) + (session.unreadMsgCount || 0)
1000
- }
1001
- } else {
1002
- return {
1003
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
1004
- muteNum: unreadMessageMuteNum
1005
- }
1006
- }
1007
- })
1166
+ ps = ps.then(() => updateAssignAccountUnread(this, accountUnreadChanges, data.taskId, 'chatroom-info-changed')).then(() => {
1167
+ accountUnreadUpdated = true
1168
+ }).catch(error => {
1169
+ console.error(ASSIGN_SESSION_LOG_PREFIX, 'socket-process-error', {
1170
+ eventType: 'chatroom-info-changed',
1171
+ taskId: data.taskId,
1172
+ message: error && error.message ? error.message : String(error)
1008
1173
  })
1009
- }
1174
+ throw error
1175
+ })
1010
1176
  return ps.finally(() => {
1177
+ console.info(ASSIGN_SESSION_LOG_PREFIX, 'socket-complete', {
1178
+ eventType: 'chatroom-info-changed',
1179
+ taskId: data.taskId,
1180
+ sessionCount: rs ? rs.length : 0,
1181
+ wechatAccountIds,
1182
+ accountUnreadChanges,
1183
+ accountUnreadBefore,
1184
+ accountUnreadAfter: getAccountUnreadSnapshot(this.account, wechatAccountIds),
1185
+ accountUnreadUpdated
1186
+ })
1011
1187
  // 这里应该标记那些工作微信号的通讯录修改了,后面要在界面打个提示,告诉用户通讯录变化了,让手动刷新一下
1012
1188
  // 同时也将缓存都清理一下,例如工作微信号分组统计数量等
1013
1189
  this.contacts.markModify() // 标记通讯录修改