feat: 新任务提示条 + 按taskIds直接加载

1. 首页新增"有N条新任务 点击查看"提示条
   - pendingCount>0 时显示,点击/查看后消失
   - 和红点共存:提示条=统一入口,红点=分类提示

2. TaskListFragment 通知模式
   - 有 filterTaskIds 时跳过 queryTaskIds
   - 直接按 taskId 构建列表,调 lookTaskDetail 加载详情
   - 不受 status 筛选限制,跨状态任务都能显示

3. 横幅/提示条共用 navigateToNewTasks()
   - 1个任务→跳详情,多个→跳列表
   - 跳转后清除红点+提示条+pendingTaskIds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dongliang
2026-04-29 16:42:09 +09:30
parent 463ff1373d
commit 6418c2f36f
4 changed files with 100 additions and 39 deletions

View File

@@ -69,6 +69,8 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
private lateinit var dotPool: View
private lateinit var dotPunch: View
private lateinit var dotComplete: View
// 新任务提示条
private lateinit var tvNewTaskHint: TextView
// ===== 设置页 View 引用 =====
private lateinit var tvAvatarLetter: TextView
@@ -128,12 +130,14 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
override fun onResume() {
super.onResume()
// 从其他页面返回时,有未读通知 → 直接显示红点(不靠 diffStats
// 原因onViewCreated 的 fetchStatistics 已更新 lastStatsdiffStats 对比不出差异
// 从其他页面返回时,恢复新任务提示
if (notificationManager.pendingCount > 0) {
// 红点(不靠 diffStats直接显示
dotPool.visibility = View.VISIBLE
dotPunch.visibility = View.VISIBLE
dotComplete.visibility = View.VISIBLE
// 提示条
updateNewTaskHint()
}
}
@@ -280,6 +284,12 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
dotPunch = page.findViewById(R.id.dotPunch)
dotComplete = page.findViewById(R.id.dotComplete)
// 新任务提示条
tvNewTaskHint = page.findViewById(R.id.tvNewTaskHint)
tvNewTaskHint.setOnClickListener {
navigateToNewTasks()
}
// 快捷区卡片点击 → 跳转任务列表 + 清除红点
page.findViewById<View>(R.id.cardPool)?.setOnClickListener {
dotPool.visibility = View.GONE
@@ -429,10 +439,11 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
is AppEvent.BluetoothStateChanged -> {
statusBar.updateBluetooth(event.isOn)
}
// 新任务到达 → 刷新统计 + 红点
// 新任务到达 → 刷新统计 + 红点 + 提示条
is AppEvent.NewTaskArrived -> {
Timber.d("首页: 新任务到达 (${event.count} 条)")
fetchStatistics(checkDots = true)
updateNewTaskHint()
setupBannerClick(event.taskIds)
}
// MQTT 消息
@@ -524,37 +535,57 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
findNavController().navigate(R.id.action_home_to_taskList, bundle)
}
/** 更新新任务提示条 */
private fun updateNewTaskHint() {
val count = notificationManager.pendingCount
if (count > 0) {
tvNewTaskHint.text = "${count}条新任务 点击查看"
tvNewTaskHint.visibility = View.VISIBLE
} else {
tvNewTaskHint.visibility = View.GONE
}
}
/**
* 设置通知横幅点击回调
* 点击时从 notificationManager.pendingTaskIds 取所有累积的任务 ID
* 1 个任务 → 跳任务详情;多个 → 跳任务列表(传 taskIds 只显示新任务)
* 跳转查看所有新任务(横幅/提示条共用)
* 1 个任务 → 跳详情;多个 → 跳列表按 taskIds 加载
*/
private fun navigateToNewTasks() {
val currentDest = findNavController().currentDestination?.id
if (currentDest != R.id.homeFragment) return
val allIds = notificationManager.pendingTaskIds
if (allIds.isEmpty()) return
if (allIds.size == 1) {
val taskId = allIds.first().toLongOrNull() ?: 0L
val bundle = bundleOf("taskId" to taskId)
findNavController().navigate(R.id.action_home_to_taskDetail, bundle)
} else {
val bundle = bundleOf(
"taskIds" to allIds.mapNotNull { it.toLongOrNull() }.toLongArray()
)
findNavController().navigate(R.id.action_home_to_taskList, bundle)
}
// 清除所有提示
clearNewTaskIndicators()
}
/** 清除所有新任务提示(红点+提示条+未读) */
private fun clearNewTaskIndicators() {
dotPool.visibility = View.GONE
dotPunch.visibility = View.GONE
dotComplete.visibility = View.GONE
tvNewTaskHint.visibility = View.GONE
notificationManager.consumeAll()
}
/** 设置通知横幅点击回调 */
private fun setupBannerClick(taskIds: List<String>) {
val mainActivity = activity as? com.xiaoqu.watch.app.MainActivity ?: return
mainActivity.notificationBanner.onClick = {
val currentDest = findNavController().currentDestination?.id
if (currentDest == R.id.homeFragment) {
// 取所有累积的任务 ID不是事件参数的防覆盖丢失
val allIds = notificationManager.pendingTaskIds
if (allIds.size == 1) {
// 1 个任务 → 直接跳详情
val taskId = allIds.first().toLongOrNull() ?: 0L
val bundle = bundleOf("taskId" to taskId)
findNavController().navigate(R.id.action_home_to_taskDetail, bundle)
} else if (allIds.isNotEmpty()) {
// 多个任务 → 跳任务列表(传 taskIds 只显示新任务)
val bundle = bundleOf(
"tableStatus" to 2,
"taskIds" to allIds.mapNotNull { it.toLongOrNull() }.toLongArray()
)
findNavController().navigate(R.id.action_home_to_taskList, bundle)
}
// 清除所有红点和未读
dotPool.visibility = View.GONE
dotPunch.visibility = View.GONE
dotComplete.visibility = View.GONE
notificationManager.consumeAll()
}
navigateToNewTasks()
}
}
}

View File

@@ -120,22 +120,29 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
/** 第一步:获取任务 ID 列表 */
private fun fetchTaskIds() {
showLoading()
// 通知跳转:有 taskIds 时不走 queryTaskIds直接按 ID 构建列表
val ids = filterTaskIds
if (ids != null && ids.isNotEmpty()) {
taskList = ids.map { TaskItem(id = it) }
Timber.d("任务列表: 通知模式, ${ids.size} 个任务")
if (taskList.isNotEmpty()) {
fetchCurrentDetail()
} else {
showEmpty()
}
return
}
// 正常流程:按 status 筛选
viewLifecycleOwner.lifecycleScope.launch {
val params = hashMapOf<String, Any>("status" to currentStatus)
val result = safeApiCall { taskApi.getTaskIds(params) }
when (result) {
is ApiResult.Success -> {
var list = result.data ?: emptyList()
// 如果有 taskIds 过滤(通知跳转),只保留指定任务
val ids = filterTaskIds
if (ids != null && ids.isNotEmpty()) {
list = list.filter { item ->
ids.any { it.toString() == item.id.toString() }
}
}
taskList = list
Timber.d("任务列表: status=$currentStatus, count=${taskList.size}, filter=${ids?.size ?: 0}")
taskList = result.data ?: emptyList()
Timber.d("任务列表: status=$currentStatus, count=${taskList.size}")
if (taskList.isNotEmpty()) {
// 确保 taskIndex 在范围内
if (taskIndex >= taskList.size) taskIndex = taskList.size - 1

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 新任务提示条背景(蓝色半透明圆角) -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1A3B9EFF" />
<corners android:radius="12dp" />
</shape>

View File

@@ -42,6 +42,22 @@
</LinearLayout>
<!-- 新任务提示条pendingCount>0 时显示,点击查看所有新任务) -->
<TextView
android:id="@+id/tvNewTaskHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="@drawable/bg_new_task_hint"
android:gravity="center"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="有1条新任务 点击查看"
android:textColor="#FF3B9EFF"
android:textSize="18sp"
android:textStyle="bold"
android:visibility="gone" />
<!-- 快捷区 gap:6px→8dp -->
<LinearLayout
android:layout_width="match_parent"