@aochuang/client-sdk 1.0.367 → 1.0.369

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aochuang/client-sdk",
3
- "version": "1.0.367",
3
+ "version": "1.0.369",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -30,7 +30,8 @@ export default class ClientChatAccount {
30
30
  onAccountRemoved: null,
31
31
  onUnreadMessageNumChange: null,
32
32
  onDeleteAccountSession: null,
33
- onAccountLoaded: null
33
+ onAccountLoaded: null,
34
+ onUnreadMessageNumLog: null
34
35
  }, options)
35
36
  if (!options.loadAccountDataMethod) {
36
37
  throw new Error('缺少loadAccountDataMethod配置')
@@ -51,6 +52,19 @@ export default class ClientChatAccount {
51
52
  this.onUnreadMessageNumChange = options.onUnreadMessageNumChange
52
53
  this.onDeleteAccountSession = options.onDeleteAccountSession
53
54
  this.onAccountLoaded = options.onAccountLoaded
55
+ this.onUnreadMessageNumLog = options.onUnreadMessageNumLog
56
+ }
57
+
58
+ _addUnreadMessageNumLog (title, data) {
59
+ if (this.onUnreadMessageNumLog) {
60
+ this.onUnreadMessageNumLog({
61
+ group: 'client-chat-account:unreadMessageNum',
62
+ content: {
63
+ title,
64
+ data
65
+ }
66
+ })
67
+ }
54
68
  }
55
69
 
56
70
  get accountData () {
@@ -198,6 +212,10 @@ export default class ClientChatAccount {
198
212
  })
199
213
  }
200
214
  this.data.accountUnreadMessageNumData = nextData
215
+ this._addUnreadMessageNumLog('服务端全量刷新账号未读数量', {
216
+ source: 'refreshAll',
217
+ accounts: nextData
218
+ })
201
219
  })
202
220
  }
203
221
 
@@ -216,23 +234,33 @@ export default class ClientChatAccount {
216
234
  return true
217
235
  }
218
236
  })
237
+ const before = index >= 0 ? this.data.accountUnreadMessageNumData[index] : null
238
+ const after = {
239
+ id: wechatAccountId,
240
+ num: rs.data[0].unread || 0,
241
+ muteNum: rs.data[0].muteUnread || 0
242
+ }
219
243
  if (index >= 0) {
220
- this.data.accountUnreadMessageNumData.splice(index, 1, {
221
- id: wechatAccountId,
222
- num: rs.data[0].unread || 0,
223
- muteNum: rs.data[0].muteUnread || 0
224
- })
244
+ this.data.accountUnreadMessageNumData.splice(index, 1, after)
225
245
  } else {
226
- this.data.accountUnreadMessageNumData.push({
227
- id: wechatAccountId,
228
- num: rs.data[0].unread || 0,
229
- muteNum: rs.data[0].muteUnread || 0
230
- })
246
+ this.data.accountUnreadMessageNumData.push(after)
231
247
  }
248
+ this._addUnreadMessageNumLog('服务端刷新账号未读数量', {
249
+ source: 'refresh',
250
+ wechatAccountId,
251
+ before: before ? { num: before.num, muteNum: before.muteNum } : null,
252
+ after: { num: after.num, muteNum: after.muteNum }
253
+ })
232
254
  })
233
255
  }
234
256
 
235
- updateAccountUnreadMessageNum (accountId, callback) {
257
+ /**
258
+ * 本地增量更新账号未读数量
259
+ * @param { String } accountId
260
+ * @param { Function } callback 返回 { num, muteNum }
261
+ * @param { String } source 调用来源标记,仅用于日志排查
262
+ */
263
+ updateAccountUnreadMessageNum (accountId, callback, source) {
236
264
  return this.getAccount(accountId).then(rs => {
237
265
  if (!rs || !rs.data) {
238
266
  console.warn('未找到' + accountId + '工作微信号')
@@ -248,11 +276,26 @@ export default class ClientChatAccount {
248
276
  return true
249
277
  }
250
278
  })
279
+ const beforeNum = unreadMessageNumIndex >= 0 ? this.data.accountUnreadMessageNumData[unreadMessageNumIndex].num : 0
280
+ const beforeMuteNum = unreadMessageNumIndex >= 0 ? this.data.accountUnreadMessageNumData[unreadMessageNumIndex].muteNum : 0
251
281
  const nextReadMessageNum = callback({
252
282
  account: rs.data,
253
- unreadMesasgeNum: unreadMessageNumIndex >= 0 ? this.data.accountUnreadMessageNumData[unreadMessageNumIndex].num : 0,
254
- unreadMessageMuteNum: unreadMessageNumIndex >= 0 ? this.data.accountUnreadMessageNumData[unreadMessageNumIndex].muteNum : 0
283
+ unreadMesasgeNum: beforeNum,
284
+ unreadMessageMuteNum: beforeMuteNum
255
285
  })
286
+ if (this.onUnreadMessageNumLog && nextReadMessageNum !== undefined && nextReadMessageNum !== null) {
287
+ const afterNum = typeof nextReadMessageNum === 'object' ? nextReadMessageNum.num : nextReadMessageNum
288
+ const afterMuteNum = typeof nextReadMessageNum === 'object' ? nextReadMessageNum.muteNum : beforeMuteNum
289
+ if (afterNum !== beforeNum || afterMuteNum !== beforeMuteNum) {
290
+ this._addUnreadMessageNumLog('本地增量更新账号未读数量', {
291
+ source: source || 'unknown',
292
+ wechatAccountId: accountId,
293
+ before: { num: beforeNum, muteNum: beforeMuteNum },
294
+ after: { num: afterNum, muteNum: afterMuteNum },
295
+ delta: { num: (afterNum || 0) - (beforeNum || 0), muteNum: (afterMuteNum || 0) - (beforeMuteNum || 0) }
296
+ })
297
+ }
298
+ }
256
299
  if (nextReadMessageNum && typeof nextReadMessageNum === 'object') {
257
300
  /**
258
301
  * {
@@ -311,11 +311,22 @@ export default class ClientChatSession {
311
311
  if (!rs.data) {
312
312
  return Promise.reject('未找到会话' + sessionId)
313
313
  }
314
+ /**
315
+ * 轮询合并上下文,会依次传给每个 serializeMethod(见 client-chat.js onCmdNewMessage 里 getSession 的回调)
316
+ * baseLastMsgTime 服务端返回的会话 lastMsgTime,用来判断某条消息服务端是否已经算进 unreadMsgCount
317
+ * processedMessageIds 本次轮询期间处理过的所有消息 id
318
+ * skippedMessageIds 服务端返回的会话已经包含(wechatTime <= baseLastMsgTime)、本地不再给会话未读 +1 的消息 id
319
+ * unreadMessageIds 本地给会话未读 +1 的消息 id
320
+ * accountUnreadDelta 本次轮询期间需要累加到工作微信号(账号)未读数量上的条数。
321
+ * 注意它和 unreadMessageIds.length 不同:账号未读初始值是登录时取的,不包含本次收到的任何消息,
322
+ * 所以被 skip 的消息也要算进来;只有"正在看当前会话被直接标记已读"的消息不算
323
+ */
314
324
  const context = {
315
325
  baseLastMsgTime: rs.data.lastMsgTime || 0,
316
326
  processedMessageIds: [],
317
327
  skippedMessageIds: [],
318
- unreadMessageIds: []
328
+ unreadMessageIds: [],
329
+ accountUnreadDelta: 0
319
330
  }
320
331
  const serializeTasks = pollRequest.serializeTasks.slice().sort((a, b) => {
321
332
  return a.wechatTime - b.wechatTime || a.index - b.index
@@ -326,7 +337,11 @@ export default class ClientChatSession {
326
337
  context.processedMessageIds.push(task.messageId)
327
338
  }
328
339
  })
329
- this.addSession(rs.data, null)
340
+ // wechatAccountId 传 null 表示非分页来源,onAddSession 会把未读同步到账号;
341
+ // 同时带上 unreadDelta,让账号只累加本次新增的条数,而不是服务端返回的整个 unreadMsgCount(那里面的存量部分账号初始值已经包含了)
342
+ this.addSession(rs.data, null, {
343
+ unreadDelta: context.accountUnreadDelta
344
+ })
330
345
  const wechatAccountId = rs.data.wechatAccountId
331
346
  this._addGetSessionLog('会话轮询合并完成', {
332
347
  sessionId,
@@ -341,6 +356,7 @@ export default class ClientChatSession {
341
356
  processedMessageCount: context.processedMessageIds.length,
342
357
  skippedMessageCount: context.skippedMessageIds.length,
343
358
  unreadMessageCount: context.unreadMessageIds.length,
359
+ accountUnreadDelta: context.accountUnreadDelta,
344
360
  hasSessionMap: !!this.sessionMap[sessionId],
345
361
  hasAllSessionGroup: !!this._getSessionBySessionGroup(sessionId, ALL_WECHAT_ACCOUNT_ID),
346
362
  hasAccountSessionGroup: !!this._getSessionBySessionGroup(sessionId, wechatAccountId)
@@ -486,8 +502,10 @@ export default class ClientChatSession {
486
502
  * "unreadMsgCount": 3,
487
503
  * "wechatAccountId": "2a39a725814acf07502299ab2285fff8d44377f5"
488
504
  * }
505
+ * @params { Object } - options
506
+ * @params { Number } - options.unreadDelta 本次新增的未读条数,新消息触发getSession拉回会话时传入,用于账号未读数量只累加新增部分而不是整个unreadMsgCount
489
507
  */
490
- addSession (data, wechatAccountId) {
508
+ addSession (data, wechatAccountId, options = {}) {
491
509
  if (!data || !data.conversationId) {
492
510
  throw new Error('缺少必须参数conversationId')
493
511
  }
@@ -591,7 +609,8 @@ export default class ClientChatSession {
591
609
  }
592
610
  this.onAddSession && this.onAddSession({
593
611
  wechatAccountId,
594
- session: nextData
612
+ session: nextData,
613
+ unreadDelta: options.unreadDelta
595
614
  })
596
615
  }
597
616
 
@@ -228,8 +228,12 @@ export default class Websocket {
228
228
  exportLogData () {
229
229
  return this.socket.exportLogData()
230
230
  }
231
+
232
+ checkAndSync () {
233
+ return this.socket.checkAndSync()
234
+ }
231
235
 
232
236
  clearLogData () {
233
237
  return this.socket.clearLogData()
234
238
  }
235
- }
239
+ }
@@ -115,23 +115,42 @@ class ClientChat {
115
115
  const mergeSessionCommonOptions = (options, instance) => {
116
116
  let updateSessioning = false
117
117
  let removeSessioning = false
118
- options.onAddSession = ({ session, wechatAccountId }) => {
118
+ /**
119
+ * 会话新增回调,负责把新增会话的未读数量同步到工作微信号(账号)的未读数量上
120
+ * @param { Object } session - 新增的会话
121
+ * @param { String } wechatAccountId - 有值代表是分页加载(loadData/reload)来的会话,账号未读初始值已经包含,不累加
122
+ * @param { Number } unreadDelta - 本次真正新增的未读条数,只有新消息触发 getSession 拉回会话时才会传(见 client-chat-session.js getSession)
123
+ *
124
+ * 账号未读数量的初始值来自登录时的 getAccountUnreadMessageNumMethod,是服务端按该账号"所有会话"算的,
125
+ * 不管本地有没有分页加载到这些会话。所以非分页来源的会话要区分两种情况:
126
+ * 1. 分配过来的会话(loadAssignTaskSessionData):之前不属于这个账号,账号初始值里没有它,
127
+ * 需要把整个 session.unreadMsgCount 累加上去。此时 unreadDelta 为 undefined。
128
+ * 2. 新消息触发 getSession 拉回来的会话:一直属于这个账号,只是本地没翻页加载到,它的存量未读已经在账号初始值里了,
129
+ * 如果再把整个 unreadMsgCount 加上去就会重复计算存量部分(这就是"会话都已读了但账号还有未读数、刷新后归零"的主因)。
130
+ * 这种情况只能累加本次轮询期间新增的条数,即 unreadDelta。
131
+ */
132
+ options.onAddSession = ({ session, wechatAccountId, unreadDelta }) => {
119
133
  // 不是来源于分页的时候,没有wechatAccountId就是代表不是走的分页增加的会话,一般为获取新消息或则分配的会话
120
134
  if (!wechatAccountId && instance === this.session) {
121
- // 更新账号未读消息数量
122
- this.account.updateAccountUnreadMessageNum(session.wechatAccountId, ({ unreadMesasgeNum, unreadMessageMuteNum }) => {
123
- if (session.mute) {
124
- return {
125
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
126
- muteNum: (unreadMessageMuteNum || 0) + (session.unreadMsgCount || 0)
127
- }
128
- } else {
129
- return {
130
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
131
- muteNum: unreadMessageMuteNum
135
+ // unreadDelta 是数字 → getSession 来源,只加新增;否则 → 分配等来源,整个 unreadMsgCount 加上
136
+ const delta = typeof unreadDelta === 'number' ? unreadDelta : (session.unreadMsgCount || 0)
137
+ // delta 为 0 时不更新,避免产生无意义的账号未读更新和日志
138
+ if (delta > 0) {
139
+ // 更新账号未读消息数量
140
+ this.account.updateAccountUnreadMessageNum(session.wechatAccountId, ({ unreadMesasgeNum, unreadMessageMuteNum }) => {
141
+ if (session.mute) {
142
+ return {
143
+ num: (unreadMesasgeNum || 0) + delta,
144
+ muteNum: (unreadMessageMuteNum || 0) + delta
145
+ }
146
+ } else {
147
+ return {
148
+ num: (unreadMesasgeNum || 0) + delta,
149
+ muteNum: unreadMessageMuteNum
150
+ }
132
151
  }
133
- }
134
- })
152
+ }, typeof unreadDelta === 'number' ? 'onAddSession:getSession' : 'onAddSession')
153
+ }
135
154
  }
136
155
  // 同步未读会话
137
156
  if (instance !== this.sessionUnread && session.unreadMsgCount > 0) {
@@ -231,7 +250,7 @@ class ClientChat {
231
250
  muteNum: unreadMessageMuteNum
232
251
  }
233
252
  }
234
- })
253
+ }, 'onRemoveSession')
235
254
  // 删除会话会同步删除所有的实例,所以需要做这个检查
236
255
  if (this.sessionManage.currentSession && this.sessionManage.currentSession.conversationId === session.conversationId) {
237
256
  this.sessionManage.setCurrentSession(null)
@@ -287,7 +306,7 @@ class ClientChat {
287
306
  muteNum: unreadMessageMuteNum
288
307
  }
289
308
  }
290
- })
309
+ }, 'onSessionReadChange')
291
310
  }
292
311
  }
293
312
  this.session = new ClientChatSession({
@@ -445,8 +464,12 @@ class ClientChat {
445
464
  rs.data.lastMsgId = data.id
446
465
  rs.data.lastUpdateTime = data.updateDate
447
466
  }
467
+ // 正在看这个会话并且允许自动标记已读
468
+ const isCurrentSessionRead = this.sessionManage.currentSession && this.sessionManage.currentSession.conversationId === sessionId && this.shouldMarkCurrentSessionRead(sessionId, data)
469
+ // 会话未读数量:isAfterServerMessage 为 true 表示这条消息比服务端返回的会话 lastMsgTime 新,
470
+ // 服务端返回的 unreadMsgCount 还没算它,需要本地 +1;否则服务端已经算进去了,skip 掉避免重复
448
471
  if (!data.isSend && isAfterServerMessage) {
449
- if (this.sessionManage.currentSession && this.sessionManage.currentSession.conversationId === sessionId && this.shouldMarkCurrentSessionRead(sessionId, data)) {
472
+ if (isCurrentSessionRead) {
450
473
  rs.data.unreadMsgCount = 0
451
474
  } else {
452
475
  rs.data.unreadMsgCount = (rs.data.unreadMsgCount || 0) + 1
@@ -455,6 +478,13 @@ class ClientChat {
455
478
  } else {
456
479
  context.skippedMessageIds.push(data.id)
457
480
  }
481
+ // 账号未读数量:和会话未读数量的判断口径不一样。
482
+ // 账号未读初始值是登录时从服务端取的,不包含这条新消息,所以不管这条消息有没有被服务端算进会话的 unreadMsgCount(即不管是否被 skip),
483
+ // 账号都要 +1。唯一不加的情况是"正在看当前会话并被直接标记已读"(此时会话未读被置 0,不会再通过 onSessionReadChange 扣减账号)。
484
+ // 这个累计值会通过 addSession(rs.data, null, { unreadDelta }) 传给 onAddSession,账号只累加这个增量而不是整个 unreadMsgCount
485
+ if (!data.isSend && !(isAfterServerMessage && isCurrentSessionRead)) {
486
+ context.accountUnreadDelta += 1
487
+ }
458
488
  }
459
489
  return rs
460
490
  }, {
@@ -496,7 +526,7 @@ class ClientChat {
496
526
  muteNum: unreadMessageMuteNum
497
527
  }
498
528
  }
499
- })
529
+ }, 'onNewFriendMessage')
500
530
  }
501
531
  }
502
532
  return nextSession
@@ -581,8 +611,12 @@ class ClientChat {
581
611
  rs.data.lastMsgId = data.id
582
612
  rs.data.lastUpdateTime = data.updateDate
583
613
  }
614
+ // 正在看这个会话并且允许自动标记已读
615
+ const isCurrentSessionRead = this.sessionManage.currentSession && this.sessionManage.currentSession.conversationId === sessionId && this.shouldMarkCurrentSessionRead(sessionId, data)
616
+ // 会话未读数量:isAfterServerMessage 为 true 表示这条消息比服务端返回的会话 lastMsgTime 新,
617
+ // 服务端返回的 unreadMsgCount 还没算它,需要本地 +1;否则服务端已经算进去了,skip 掉避免重复
584
618
  if (!data.isSend && isAfterServerMessage) {
585
- if (this.sessionManage.currentSession && this.sessionManage.currentSession.conversationId === sessionId && this.shouldMarkCurrentSessionRead(sessionId, data)) {
619
+ if (isCurrentSessionRead) {
586
620
  rs.data.unreadMsgCount = 0
587
621
  } else {
588
622
  rs.data.unreadMsgCount = (rs.data.unreadMsgCount || 0) + 1
@@ -594,6 +628,13 @@ class ClientChat {
594
628
  } else {
595
629
  context.skippedMessageIds.push(data.id)
596
630
  }
631
+ // 账号未读数量:和会话未读数量的判断口径不一样。
632
+ // 账号未读初始值是登录时从服务端取的,不包含这条新消息,所以不管这条消息有没有被服务端算进会话的 unreadMsgCount(即不管是否被 skip),
633
+ // 账号都要 +1。唯一不加的情况是"正在看当前会话并被直接标记已读"(此时会话未读被置 0,不会再通过 onSessionReadChange 扣减账号)。
634
+ // 这个累计值会通过 addSession(rs.data, null, { unreadDelta }) 传给 onAddSession,账号只累加这个增量而不是整个 unreadMsgCount
635
+ if (!data.isSend && !(isAfterServerMessage && isCurrentSessionRead)) {
636
+ context.accountUnreadDelta += 1
637
+ }
597
638
  }
598
639
  return rs
599
640
  }, {
@@ -638,7 +679,7 @@ class ClientChat {
638
679
  muteNum: unreadMessageMuteNum
639
680
  }
640
681
  }
641
- })
682
+ }, 'onNewRoomMessage')
642
683
  }
643
684
  }
644
685
  return nextSession
@@ -748,6 +789,26 @@ class ClientChat {
748
789
  getAccountGreetingUnreadMsgCountMethod: options.getAccountGreetingUnreadMsgCountMethod,
749
790
  batchGetAccountGreetingUnreadMsgCountMethod: options.batchGetAccountGreetingUnreadMsgCountMethod,
750
791
  clearAccountGreetingUnreadMsgCountMethod: options.clearAccountGreetingUnreadMsgCountMethod,
792
+ // 账号未读数量变化日志,附带该账号本地会话未读之和,用于排查账号未读数和会话未读数不一致的问题
793
+ onUnreadMessageNumLog: (log) => {
794
+ if (!this.socket) {
795
+ return
796
+ }
797
+ const wechatAccountId = log.content && log.content.data && log.content.data.wechatAccountId
798
+ if (wechatAccountId && this.session) {
799
+ log.content.data.localSessionUnread = Object.keys(this.session.sessionMap).reduce((rs, id) => {
800
+ const session = this.session.sessionMap[id]
801
+ if (session && session.wechatAccountId === wechatAccountId) {
802
+ rs.num += session.unreadMsgCount || 0
803
+ if (session.mute) {
804
+ rs.muteNum += session.unreadMsgCount || 0
805
+ }
806
+ }
807
+ return rs
808
+ }, { num: 0, muteNum: 0 })
809
+ }
810
+ this.socket.addLog(log)
811
+ },
751
812
  onAccountAdded: ({ account }) => {
752
813
  return this.account.refreshAccountUnreadMessageNum({
753
814
  wechatAccountId: account.id
@@ -919,25 +980,10 @@ class ClientChat {
919
980
  return this.contacts.getFriend(sessionFriendId, true)
920
981
  })
921
982
  }
922
- // 刷新工作微信号未读消息数量
923
- if (rs && rs.length) {
924
- rs.forEach(session => {
925
- this.account.updateAccountUnreadMessageNum(session.wechatAccountId, ({ unreadMesasgeNum, unreadMessageMuteNum }) => {
926
- if (session.mute) {
927
- return {
928
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
929
- muteNum: (unreadMessageMuteNum || 0) + (session.unreadMsgCount || 0)
930
- }
931
- } else {
932
- return {
933
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
934
- muteNum: unreadMessageMuteNum
935
- }
936
- }
937
- })
938
- })
939
- }
983
+ // 分配会话的未读数量已经在onAddSession里累加到工作微信号上了,这里不再重复累加
984
+ // 转移/删除的好友如果本地没有加载到对应会话,本地是无法扣减的,所以统一以服务端为准刷新一次
940
985
  return ps.finally(() => {
986
+ this.refreshAccountsUnreadMessageNum([].concat(wechatAccountIds, data.wechatAccountIds || []))
941
987
  // 这里应该标记那些工作微信号的通讯录修改了,后面要在界面打个提示,告诉用户通讯录变化了,让手动刷新一下
942
988
  // 同时也将缓存都清理一下,例如工作微信号分组统计数量等
943
989
  this.contacts.markModify() // 标记通讯录修改
@@ -963,6 +1009,8 @@ class ClientChat {
963
1009
  this.session.removeSession(session.conversationId)
964
1010
  }
965
1011
  }
1012
+ // 本地没有加载到该会话时无法扣减未读数量,以服务端为准刷新一次
1013
+ this.refreshAccountsUnreadMessageNum(data.wechatAccountIds)
966
1014
  // todo 刷新一下微信号,如果微信号一个好友都没了,应该要删除掉的
967
1015
  this.contacts.markModify() // 标记通讯录修改
968
1016
  }
@@ -1001,25 +1049,10 @@ class ClientChat {
1001
1049
  ps = this.account.reloadData()
1002
1050
  }
1003
1051
  }
1004
- // 刷新工作微信号未读消息数量
1005
- if (rs && rs.length) {
1006
- rs.forEach(session => {
1007
- this.account.updateAccountUnreadMessageNum(session.wechatAccountId, ({ unreadMesasgeNum, unreadMessageMuteNum }) => {
1008
- if (session.mute) {
1009
- return {
1010
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
1011
- muteNum: (unreadMessageMuteNum || 0) + (session.unreadMsgCount || 0)
1012
- }
1013
- } else {
1014
- return {
1015
- num: (unreadMesasgeNum || 0) + (session.unreadMsgCount || 0),
1016
- muteNum: unreadMessageMuteNum
1017
- }
1018
- }
1019
- })
1020
- })
1021
- }
1052
+ // 分配会话的未读数量已经在onAddSession里累加到工作微信号上了,这里不再重复累加
1053
+ // 转移/删除的群聊如果本地没有加载到对应会话,本地是无法扣减的,所以统一以服务端为准刷新一次
1022
1054
  return ps.finally(() => {
1055
+ this.refreshAccountsUnreadMessageNum([].concat(wechatAccountIds, data.wechatAccountIds || []))
1023
1056
  // 这里应该标记那些工作微信号的通讯录修改了,后面要在界面打个提示,告诉用户通讯录变化了,让手动刷新一下
1024
1057
  // 同时也将缓存都清理一下,例如工作微信号分组统计数量等
1025
1058
  this.contacts.markModify() // 标记通讯录修改
@@ -1043,6 +1076,8 @@ class ClientChat {
1043
1076
  }
1044
1077
  // 删除群聊
1045
1078
  this.contacts.removeRoom(data.wechatChatroomId)
1079
+ // 本地没有加载到该会话时无法扣减未读数量,以服务端为准刷新一次
1080
+ this.refreshAccountsUnreadMessageNum(data.wechatAccountIds)
1046
1081
  }
1047
1082
  // 更新群聊
1048
1083
  else {
@@ -1080,6 +1115,8 @@ class ClientChat {
1080
1115
  wechatAccountId: data.wechatAccountId,
1081
1116
  unreadGreetingMsgCount: data.unreadGreetingMsgCount
1082
1117
  })
1118
+ // 刷新所有微信号请求数量
1119
+ this.account.getAccountGreetingUnreadMsgCount()
1083
1120
  },
1084
1121
  onCmdNewFriendRequest: ({ data }) => {
1085
1122
  // 刷新指定微信号请求数量
@@ -1151,6 +1188,10 @@ class ClientChat {
1151
1188
  Promise.all(ps).finally(() => {
1152
1189
  this.friendMessage.setLastReceiveMessageTime(Date.now())
1153
1190
  this.roomMessage.setLastReceiveMessageTime(Date.now())
1191
+ // 断线期间本地增量可能和服务端产生偏差(其他端已读、消息延迟等),重连后以服务端为准全量校准一次
1192
+ if (ps.length) {
1193
+ this.account.refreshAllAccountUnreadMesageNum()
1194
+ }
1154
1195
  })
1155
1196
  },
1156
1197
  onSocketClose: (evt) => {
@@ -1205,6 +1246,17 @@ class ClientChat {
1205
1246
  this.shouldMarkCurrentSessionReadMethod = method
1206
1247
  }
1207
1248
 
1249
+ /**
1250
+ * 以服务端为准刷新指定工作微信号的未读消息数量,用于本地增量无法处理的场景(例如本地未加载到的会话被删除/转移)
1251
+ * @param { Array<String> } wechatAccountIds
1252
+ */
1253
+ refreshAccountsUnreadMessageNum (wechatAccountIds) {
1254
+ const ids = Array.from(new Set((wechatAccountIds || []).filter(id => id && this.account.accountMap[id])))
1255
+ ids.forEach(wechatAccountId => {
1256
+ this.account.refreshAccountUnreadMessageNum({ wechatAccountId })
1257
+ })
1258
+ }
1259
+
1208
1260
  shouldMarkCurrentSessionRead (sessionId, data) {
1209
1261
  if (typeof this.shouldMarkCurrentSessionReadMethod === 'function') {
1210
1262
  return this.shouldMarkCurrentSessionReadMethod({