From 58ef336df4d0ff5606954c18657c9a7f1e0985a0 Mon Sep 17 00:00:00 2001 From: dongliang Date: Wed, 29 Apr 2026 16:59:56 +0930 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=94=A8=E9=80=9A=E7=9F=A5=E5=89=8D?= =?UTF-8?q?=E5=BF=AB=E7=85=A7=E7=B2=BE=E7=A1=AE=E6=98=BE=E7=A4=BA=E7=BA=A2?= =?UTF-8?q?=E7=82=B9=EF=BC=88=E5=8C=BA=E5=88=86=E9=A6=96=E9=A1=B5/?= =?UTF-8?q?=E9=9D=9E=E9=A6=96=E9=A1=B5=E5=9C=BA=E6=99=AF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:非首页返回时,onViewCreated已覆盖lastStats, 导致diffStats对比不出差异,红点要么全显要么不显。 修复: 1. NotificationManager新增preNotificationStats - 首条通知到达时保存当前lastStats快照 - consumeAll时清除 - 不会被onViewCreated的fetchStatistics覆盖 2. HomeFragment.onResume用preNotificationStats做精确diffStats - 有快照→fetchStatisticsForDots(baseline, acknowledged) - 只给变化且未查看的分类显示红点 - 无快照→降级为全显(未查看的) 场景验证: - 首页收到通知→当场diffStats→红点精确 ✅ - 首页点红点→对应消除,其他保留 ✅ - 首页点通知→consumeAll→返回后全部消除 ✅ - 非首页返回→preNotificationStats对比→红点精确 ✅ Co-Authored-By: Claude Opus 4.6 (1M context) --- .../service/manager/NotificationManager.kt | 10 ++++ .../com/xiaoqu/watch/ui/home/HomeFragment.kt | 56 ++++++++++++++++--- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/xiaoqu/watch/service/manager/NotificationManager.kt b/app/src/main/java/com/xiaoqu/watch/service/manager/NotificationManager.kt index 69058d4..0d946ad 100644 --- a/app/src/main/java/com/xiaoqu/watch/service/manager/NotificationManager.kt +++ b/app/src/main/java/com/xiaoqu/watch/service/manager/NotificationManager.kt @@ -66,6 +66,10 @@ class NotificationManager @Inject constructor( /** 上次统计数据(对比红点用) */ var lastStats: TaskStatistics? = null + /** 通知到达前的统计快照(用于非首页返回后精确 diffStats) */ + var preNotificationStats: TaskStatistics? = null + private set + /** 协程作用域 */ private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob()) @@ -111,6 +115,11 @@ class NotificationManager @Inject constructor( val taskIds = parseTaskIds(rawJson) if (taskIds.isEmpty()) return + // 保存通知到达前的统计快照(只在首次通知时保存,后续累积不覆盖) + if (preNotificationStats == null) { + preNotificationStats = lastStats?.copy() + } + addTaskIds(taskIds) // 震动 + 亮屏(只在首条时触发,暂存的合并后不重复震动) @@ -152,6 +161,7 @@ class NotificationManager @Inject constructor( _pendingTaskIds.clear() acknowledgedCards.clear() _cardIncrements.clear() + preNotificationStats = null Timber.d("通知: 已清空全部未读") } diff --git a/app/src/main/java/com/xiaoqu/watch/ui/home/HomeFragment.kt b/app/src/main/java/com/xiaoqu/watch/ui/home/HomeFragment.kt index 4a3c480..25c374b 100644 --- a/app/src/main/java/com/xiaoqu/watch/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/xiaoqu/watch/ui/home/HomeFragment.kt @@ -130,19 +130,59 @@ class HomeFragment : BaseFragment() { override fun onResume() { super.onResume() - // 从其他页面返回时,只恢复未查看分类的红点 - if (notificationManager.pendingCount > 0) { - val ack = notificationManager.acknowledgedCards - if (2 !in ack) dotPool.visibility = View.VISIBLE - if (3 !in ack) dotPunch.visibility = View.VISIBLE - if (4 !in ack) dotComplete.visibility = View.VISIBLE - updateNewTaskHint() - } else { + if (notificationManager.pendingCount <= 0) { // 全部已查看 → 清除所有提示 dotPool.visibility = View.GONE dotPunch.visibility = View.GONE dotComplete.visibility = View.GONE tvNewTaskHint.visibility = View.GONE + return + } + + // 有未读通知 → 用 preNotificationStats 精确对比红点 + // (preNotificationStats 是通知到达前的快照,不会被 onViewCreated 的 fetchStatistics 覆盖) + val ack = notificationManager.acknowledgedCards + val baseline = notificationManager.preNotificationStats + if (baseline != null) { + // 精确模式:对比快照和当前统计,只给变化的分类显示红点 + fetchStatisticsForDots(baseline, ack) + } else { + // 无快照(首次加载等):已查看的不显示,未查看的显示 + if (2 !in ack) dotPool.visibility = View.VISIBLE + if (3 !in ack) dotPunch.visibility = View.VISIBLE + if (4 !in ack) dotComplete.visibility = View.VISIBLE + } + updateNewTaskHint() + } + + /** + * 用通知前快照精确对比红点(非首页返回时调用) + * @param baseline 通知到达前的统计快照 + * @param acknowledged 已查看的分类集合 + */ + private fun fetchStatisticsForDots(baseline: com.xiaoqu.watch.data.task.TaskStatistics, acknowledged: Set) { + viewLifecycleOwner.lifecycleScope.launch { + val result = safeApiCall { taskApi.getStatistics() } + if (result is ApiResult.Success && result.data != null) { + val data = result.data + val changed = notificationManager.diffStats(baseline, data) + + // 只给变化且未查看的分类显示红点 + dotPool.visibility = if (2 in changed && 2 !in acknowledged) View.VISIBLE else View.GONE + dotPunch.visibility = if (3 in changed && 3 !in acknowledged) View.VISIBLE else View.GONE + dotComplete.visibility = if (4 in changed && 4 !in acknowledged) View.VISIBLE else View.GONE + + // 记录增量(供 acknowledgeCard 扣减用) + if (2 in changed) notificationManager.recordCardIncrement(2, data.waitForTask - baseline.waitForTask) + if (3 in changed) notificationManager.recordCardIncrement(3, data.treatTask - baseline.treatTask) + if (4 in changed) notificationManager.recordCardIncrement(4, data.incompleteTask - baseline.incompleteTask) + + // 更新数字 + tvPoolNum.text = data.waitForTask.toString() + tvPunchNum.text = data.treatTask.toString() + tvCompleteNum.text = data.incompleteTask.toString() + notificationManager.lastStats = data + } } }