From 0b8bcfe800703b8f007a92cd03837ad704e8e9bd Mon Sep 17 00:00:00 2001 From: AndyChen1024 Date: Wed, 9 Sep 2026 22:19:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=80=8C=E9=A6=96=E9=A1=B5=E3=80=8D?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=B8=B8=E5=AE=A2=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mingyuan/android_client/AppNavHost.kt | 1 + .../data/repository/FakeHomeRepository.kt | 59 ++++++++++++------- .../core/domain/repository/HomeRepository.kt | 2 + .../android_client/feature/home/HomeScreen.kt | 40 +++++++++++-- .../feature/home/HomeViewModel.kt | 21 +++++-- 5 files changed, 93 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/mingyuan/android_client/AppNavHost.kt b/app/src/main/java/com/mingyuan/android_client/AppNavHost.kt index 81ea34b..39445d7 100644 --- a/app/src/main/java/com/mingyuan/android_client/AppNavHost.kt +++ b/app/src/main/java/com/mingyuan/android_client/AppNavHost.kt @@ -74,6 +74,7 @@ fun AppNavHost() { HomeScreen( onNavigateToCheckin = { navigateToTab(CHECKIN_ROUTE) }, onNavigateToPlan = { navigateToTab(PLAN_ROUTE) }, + onNavigateToProfile = { navigateToTab(PROFILE_ROUTE) }, ) } composable(CHECKIN_ROUTE) { CheckinScreen() } diff --git a/core/data/src/main/kotlin/com/mingyuan/android_client/core/data/repository/FakeHomeRepository.kt b/core/data/src/main/kotlin/com/mingyuan/android_client/core/data/repository/FakeHomeRepository.kt index 6bcccff..dbf3621 100644 --- a/core/data/src/main/kotlin/com/mingyuan/android_client/core/data/repository/FakeHomeRepository.kt +++ b/core/data/src/main/kotlin/com/mingyuan/android_client/core/data/repository/FakeHomeRepository.kt @@ -18,32 +18,49 @@ class FakeHomeRepository @Inject constructor() : HomeRepository { emit(seedHome()) } + override fun observeGuestHome(): Flow = flow { + delay(250) + emit(seedGuestHome()) + } + private fun seedHome() = HomeData( greeting = "晚上好", displayName = "张三", encouragement = "坚持每周打卡,与小组共同进步。", - modules = listOf( - HomeModule("checkin", "📋", "打卡介绍", "每日打卡记录", ModuleDestination.CHECKIN), - HomeModule("plan", "📝", "计划介绍", "周/月/年计划", ModuleDestination.PLAN), - HomeModule("about", "ℹ️", "关于我们", "了解明缘云道场", ModuleDestination.ABOUT), + modules = modules(), + intros = intros(), + ) + + private fun seedGuestHome() = HomeData( + greeting = "欢迎来到明缘云道场", + displayName = "游客", + encouragement = "登录后即可打卡、提交计划", + modules = modules(), + intros = intros(), + ) + + private fun modules() = listOf( + HomeModule("checkin", "📋", "打卡介绍", "每日打卡记录", ModuleDestination.CHECKIN), + HomeModule("plan", "📝", "计划介绍", "周/月/年计划", ModuleDestination.PLAN), + HomeModule("about", "ℹ️", "关于我们", "了解明缘云道场", ModuleDestination.ABOUT), + ) + + private fun intros() = listOf( + IntroCard( + "📚 学习成长工具", + "明缘云道场是一款专注于个人成长的效率工具,通过每周打卡与计划管理,帮助你养成良好的学习习惯,实现持续进步。好好学习,天天向上。", + ), + IntroCard( + "✅ 周打卡", + "每周打卡,支持多种状态记录(正常、迟到、请假、早退、不参加讨论等)。查看小组打卡情况,与同学们互相监督、共同进步。", + ), + IntroCard( + "📝 计划管理", + "提供周计划、月计划、年计划三级管理,支持文字与图片上传。清晰追踪每个周期的目标完成情况,让成长有迹可循。", ), - intros = listOf( - IntroCard( - "📚 学习成长工具", - "明缘云道场是一款专注于个人成长的效率工具,通过每周打卡与计划管理,帮助你养成良好的学习习惯,实现持续进步。好好学习,天天向上。", - ), - IntroCard( - "✅ 周打卡", - "每周打卡,支持多种状态记录(正常、迟到、请假、早退、不参加讨论等)。查看小组打卡情况,与同学们互相监督、共同进步。", - ), - IntroCard( - "📝 计划管理", - "提供周计划、月计划、年计划三级管理,支持文字与图片上传。清晰追踪每个周期的目标完成情况,让成长有迹可循。", - ), - IntroCard( - "👥 小组共学", - "加入学习小组,查看组员的打卡与计划完成情况。在集体的氛围中保持学习动力,与志同道合的伙伴一起成长。", - ), + IntroCard( + "👥 小组共学", + "加入学习小组,查看组员的打卡与计划完成情况。在集体的氛围中保持学习动力,与志同道合的伙伴一起成长。", ), ) } diff --git a/core/domain/src/main/kotlin/com/mingyuan/android_client/core/domain/repository/HomeRepository.kt b/core/domain/src/main/kotlin/com/mingyuan/android_client/core/domain/repository/HomeRepository.kt index d190442..7e73862 100644 --- a/core/domain/src/main/kotlin/com/mingyuan/android_client/core/domain/repository/HomeRepository.kt +++ b/core/domain/src/main/kotlin/com/mingyuan/android_client/core/domain/repository/HomeRepository.kt @@ -5,4 +5,6 @@ import kotlinx.coroutines.flow.Flow interface HomeRepository { fun observeHome(): Flow + + fun observeGuestHome(): Flow } diff --git a/feature/home/src/main/kotlin/com/mingyuan/android_client/feature/home/HomeScreen.kt b/feature/home/src/main/kotlin/com/mingyuan/android_client/feature/home/HomeScreen.kt index 90ee75e..a29dcd8 100644 --- a/feature/home/src/main/kotlin/com/mingyuan/android_client/feature/home/HomeScreen.kt +++ b/feature/home/src/main/kotlin/com/mingyuan/android_client/feature/home/HomeScreen.kt @@ -16,9 +16,14 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow @@ -51,10 +56,12 @@ const val HOME_ROUTE = "home" fun HomeScreen( onNavigateToCheckin: () -> Unit, onNavigateToPlan: () -> Unit, + onNavigateToProfile: () -> Unit, modifier: Modifier = Modifier, viewModel: HomeViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() + var showLoginDialog by remember { mutableStateOf(false) } when (val state = uiState) { is HomeUiState.Loading -> HomeSkeleton(modifier) @@ -67,15 +74,40 @@ fun HomeScreen( is HomeUiState.Success -> HomeContent( data = state.data, onModuleClick = { module -> - when (module.destination) { - ModuleDestination.CHECKIN -> onNavigateToCheckin() - ModuleDestination.PLAN -> onNavigateToPlan() - ModuleDestination.ABOUT -> Unit + if (state.isGuest) { + showLoginDialog = true + } else { + when (module.destination) { + ModuleDestination.CHECKIN -> onNavigateToCheckin() + ModuleDestination.PLAN -> onNavigateToPlan() + ModuleDestination.ABOUT -> Unit + } } }, modifier = modifier, ) } + + if (showLoginDialog) { + AlertDialog( + onDismissRequest = { showLoginDialog = false }, + title = { Text("登录提示") }, + text = { Text("登录后使用此功能,是否前往登录?") }, + confirmButton = { + TextButton( + onClick = { + showLoginDialog = false + onNavigateToProfile() + }, + ) { + Text("去登录") + } + }, + dismissButton = { + TextButton(onClick = { showLoginDialog = false }) { Text("取消") } + }, + ) + } } @Composable diff --git a/feature/home/src/main/kotlin/com/mingyuan/android_client/feature/home/HomeViewModel.kt b/feature/home/src/main/kotlin/com/mingyuan/android_client/feature/home/HomeViewModel.kt index b604664..3664b2e 100644 --- a/feature/home/src/main/kotlin/com/mingyuan/android_client/feature/home/HomeViewModel.kt +++ b/feature/home/src/main/kotlin/com/mingyuan/android_client/feature/home/HomeViewModel.kt @@ -3,11 +3,13 @@ package com.mingyuan.android_client.feature.home import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mingyuan.android_client.core.domain.repository.HomeRepository +import com.mingyuan.android_client.core.domain.repository.SessionRepository import com.mingyuan.android_client.core.model.HomeData import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn @@ -15,22 +17,31 @@ import javax.inject.Inject sealed interface HomeUiState { data object Loading : HomeUiState - data class Success(val data: HomeData) : HomeUiState + data class Success(val data: HomeData, val isGuest: Boolean) : HomeUiState data class Error(val message: String) : HomeUiState } @HiltViewModel class HomeViewModel @Inject constructor( homeRepository: HomeRepository, + sessionRepository: SessionRepository, ) : ViewModel() { - val uiState: StateFlow = homeRepository.observeHome() - .map(HomeUiState::Success) - .onStart { emit(HomeUiState.Loading) } + val uiState: StateFlow = sessionRepository.isLoggedIn + .flatMapLatest { loggedIn -> + val source = if (loggedIn) { + homeRepository.observeHome() + } else { + homeRepository.observeGuestHome() + } + source + .map { HomeUiState.Success(it, isGuest = !loggedIn) } + .onStart { emit(HomeUiState.Loading) } + } .catch { emit(HomeUiState.Error(it.message ?: "加载失败,请稍后再试")) } .stateIn( scope = viewModelScope, - started = SharingStarted.WhileSubscribed(5_000), + started = SharingStarted.Eagerly, initialValue = HomeUiState.Loading, ) }