Procházet zdrojové kódy

add(study plan): add index viewmodel

zhaoyadi před 1 rokem
rodič
revize
a9354ccdd5
17 změnil soubory, kde provedl 454 přidání a 57 odebrání
  1. 1 1
      core/common/src/main/kotlin/com/zaojiao/app/core/common/di/CommonModule.kt
  2. 2 0
      data/repo/src/main/kotlin/com/zaojiao/app/data/repo/StudyPlanRepository.kt
  3. 3 3
      data/repo/src/main/kotlin/com/zaojiao/app/data/repo/di/RepoModule.kt
  4. 6 1
      data/repo/src/main/kotlin/com/zaojiao/app/data/repo/impl/StudyPlanRepositoryImpl.kt
  5. 16 0
      feat/design/src/main/kotlin/com/zaojiao/app/feat/design/Images.kt
  6. 13 35
      feat/design/src/main/kotlin/com/zaojiao/app/feat/design/viewmodel/BaseViewModel.kt
  7. 9 0
      feat/design/src/main/kotlin/com/zaojiao/app/feat/design/viewmodel/ViewModelPage.kt
  8. 2 3
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/HomePage.kt
  9. 5 1
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/index/HomeIndexViewModel.kt
  10. 4 0
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/navigation/HomeNavigation.kt
  11. 8 2
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/personal/HomePersonalViewModel.kt
  12. 336 5
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanIndexPage.kt
  13. 33 0
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanIndexViewModel.kt
  14. 10 3
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanPage.kt
  15. 0 1
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanTotalPage.kt
  16. 1 1
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanViewModel.kt
  17. 5 1
      feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/state/HomePlanIndexUiState.kt

+ 1 - 1
core/common/src/main/kotlin/com/zaojiao/app/core/common/di/CommonModule.kt

@@ -21,6 +21,6 @@ object CommonModule {
     @Singleton
     @Named("endpoint")
     fun provideEndpoint(): String {
-        return "https://open.test.luojigou.vip"
+        return "https://open.api.luojigou.vip"
     }
 }

+ 2 - 0
data/repo/src/main/kotlin/com/zaojiao/app/data/repo/StudyPlanRepository.kt

@@ -4,6 +4,8 @@ import com.zaojiao.app.data.model.studyplan.StudyPlanTodayModel
 import com.zaojiao.app.data.model.studyplan.StudyPlanTomorrowModel
 
 interface StudyPlanRepository {
+    suspend fun getHistoryList():List<StudyPlanTodayModel>
+
     suspend fun getTodayPlanList(): List<StudyPlanTodayModel>
 
     suspend fun getTomorrowPlanList(): List<StudyPlanTomorrowModel>

+ 3 - 3
data/repo/src/main/kotlin/com/zaojiao/app/data/repo/di/RepoModule.kt

@@ -25,19 +25,19 @@ interface RepoModule {
 
     @Binds
     @Singleton
-    fun bindBabyRepository(
+    fun bindsBabyRepository(
         babyRepositoryImpl: BabyRepositoryImpl,
     ): BabyRepository
 
     @Binds
     @Singleton
-    fun bindHomeRepository(
+    fun bindsHomeRepository(
         homeRepositoryImpl: HomeRepositoryImpl,
     ): HomeRepository
 
     @Binds
     @Singleton
-    fun bindStudyPlanRepository(
+    fun bindsStudyPlanRepository(
         studyPlanRepositoryImpl: StudyPlanRepositoryImpl,
     ): StudyPlanRepository
 }

+ 6 - 1
data/repo/src/main/kotlin/com/zaojiao/app/data/repo/impl/StudyPlanRepositoryImpl.kt

@@ -1,14 +1,16 @@
 package com.zaojiao.app.data.repo.impl
 
+import com.zaojiao.app.core.common.remote.di.ApplicationScope
 import com.zaojiao.app.data.model.studyplan.StudyPlanTodayModel
 import com.zaojiao.app.data.model.studyplan.StudyPlanTomorrowModel
 import com.zaojiao.app.data.remote.RemoteStudyPlanData
 import com.zaojiao.app.data.repo.StudyPlanRepository
+import kotlinx.coroutines.CoroutineScope
 import javax.inject.Inject
 
-
 class StudyPlanRepositoryImpl @Inject constructor(
     private val remoteStudyPlanData: RemoteStudyPlanData,
+    @ApplicationScope private val coroutineScope: CoroutineScope,
 ) : StudyPlanRepository {
     override suspend fun getTodayPlanList(): List<StudyPlanTodayModel> {
         return remoteStudyPlanData.getTodayPlan().run {
@@ -23,4 +25,7 @@ class StudyPlanRepositoryImpl @Inject constructor(
         }
     }
 
+    override suspend fun getHistoryList(): List<StudyPlanTodayModel> {
+        return emptyList()
+    }
 }

+ 16 - 0
feat/design/src/main/kotlin/com/zaojiao/app/feat/design/Images.kt

@@ -25,6 +25,7 @@ object Images {
                 modifier = modifier,
                 contentScale = contentScale,
                 error = ColorPainter(Colors.FF999999),
+                placeholder = ColorPainter(Colors.FF999999),
             )
         } else {
             Image(
@@ -50,4 +51,19 @@ object Images {
             contentScale = contentScale,
         )
     }
+
+    @Composable
+    fun Color(
+        modifier: Modifier = Modifier,
+        color: Color,
+        description: String? = null,
+        contentScale: ContentScale = ContentScale.Crop,
+    ) {
+        Image(
+            painter = ColorPainter(color = color),
+            contentDescription = description,
+            modifier = modifier,
+            contentScale = contentScale,
+        )
+    }
 }

+ 13 - 35
feat/design/src/main/kotlin/com/zaojiao/app/feat/design/viewmodel/BaseViewModel.kt

@@ -1,53 +1,31 @@
 package com.zaojiao.app.feat.design.viewmodel
 
+import android.util.Log
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
 import com.zaojiao.app.feat.design.UiState
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.cancel
 import kotlinx.coroutines.launch
 
-abstract class BaseViewModel<T>(
-    private val autoInitial: Boolean = true,
-    private val autoLoading: Boolean = true,
-) : ViewModel() {
+abstract class BaseViewModel<T>() : ViewModel() {
     private val _stateFlow = MutableStateFlow<UiState<T>>(UiState.Loading)
     val stateFlow: StateFlow<UiState<T>> get() = _stateFlow
 
-    init {
-        firstInit()
-    }
-
-    abstract suspend fun initData(): T
-
-    protected fun firstInit() {
-        if (autoInitial) {
-            viewModelScope.launch {
-                if (autoLoading) {
-                    setLoading()
-                }
-                try {
-                    val result = initData()
-                    setSuccess(result)
-                } catch (e: Throwable) {
-                    e.printStackTrace()
-                    setFailure(0)
-                }
-            }
+    fun initialState(showLoading: Boolean = true) = viewModelScope.launch {
+        if (showLoading) {
+            setLoading()
         }
-    }
-
-    protected fun refresh() =
-        viewModelScope.launch {
-            try {
-                val result = initData()
-                setSuccess(result)
-            } catch (e: Throwable) {
-                setFailure(0)
-            }
+        try {
+            val result = productState()
+            setSuccess(result)
+        } catch (e: Throwable) {
+            Log.e("BaseViewModel", "${this.javaClass.simpleName}: error", e)
+            setFailure(0)
         }
+    }
 
+    abstract suspend fun productState(): T
 
     protected suspend fun setLoading() {
         _stateFlow.emit(UiState.Loading)

+ 9 - 0
feat/design/src/main/kotlin/com/zaojiao/app/feat/design/viewmodel/ViewModelPage.kt

@@ -0,0 +1,9 @@
+package com.zaojiao.app.feat.design.viewmodel
+
+import androidx.compose.runtime.Composable
+
+@Deprecated("dont use")
+@Composable
+fun <S, VM : BaseViewModel<S>> ViewModelPage(viewModel: VM) {
+
+}

+ 2 - 3
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/HomePage.kt

@@ -18,7 +18,6 @@ import androidx.compose.material3.SnackbarHost
 import androidx.compose.material3.SnackbarHostState
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
@@ -32,7 +31,7 @@ import androidx.navigation.NavDestination.Companion.hierarchy
 import com.zaojiao.app.feat.home.course.HomeCourseRoute
 import com.zaojiao.app.feat.home.index.HomeIndexRoute
 import com.zaojiao.app.feat.home.personal.HomePersonalRoute
-import com.zaojiao.app.feat.home.plan.HomePlanRoute
+import com.zaojiao.app.feat.home.plan.HomeStudyPlanRoute
 import kotlinx.coroutines.launch
 
 @OptIn(ExperimentalLayoutApi::class, ExperimentalFoundationApi::class)
@@ -74,7 +73,7 @@ fun HomePage() {
                 when (it) {
                     0 -> HomeIndexRoute()
                     1 -> HomeCourseRoute()
-                    2 -> HomePlanRoute()
+                    2 -> HomeStudyPlanRoute()
                     3 -> HomePersonalRoute()
                     else -> TODO()
                 }

+ 5 - 1
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/index/HomeIndexViewModel.kt

@@ -45,7 +45,11 @@ class HomeIndexViewModel @Inject constructor(
             initialValue = HomeIndexBabyUiState.None,
         )
 
-    override suspend fun initData(): HomeIndexPageUiState {
+    init {
+        initialState()
+    }
+
+    override suspend fun productState(): HomeIndexPageUiState {
         val list = listOf(
             "https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF",
             "https://t7.baidu.com/it/u=4198287529,2774471735&fm=193&f=GIF",

+ 4 - 0
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/navigation/HomeNavigation.kt

@@ -8,10 +8,12 @@ import com.zaojiao.app.feat.home.HomePage
 import com.zaojiao.app.feat.home.course.HomeCourseRoute
 import com.zaojiao.app.feat.home.index.HomeIndexRoute
 import com.zaojiao.app.feat.home.personal.HomePersonalRoute
+import com.zaojiao.app.feat.home.plan.HomeStudyPlanRoute
 
 const val homePage = "/home"
 const val homeIndex = "/home/index"
 const val homeCourse = "/home/course"
+const val homeStudyPlan = "/home/study-plan"
 const val homePersonal = "/home/personal"
 
 fun LJGNavigator.toHomePage(navOptions: NavOptions? = null) {
@@ -25,6 +27,8 @@ fun NavGraphBuilder.homeRoute() {
 
     composable(route = homeCourse) { HomeCourseRoute() }
 
+    composable(route = homeStudyPlan) { HomeStudyPlanRoute() }
+
     composable(route = homePersonal) { HomePersonalRoute() }
 }
 

+ 8 - 2
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/personal/HomePersonalViewModel.kt

@@ -1,10 +1,10 @@
 package com.zaojiao.app.feat.home.personal
 
-import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
 import com.zaojiao.app.core.auth.data.AuthRepository
 import com.zaojiao.app.core.auth.utils.AuthState
 import com.zaojiao.app.data.repo.UserRepository
+import com.zaojiao.app.feat.design.viewmodel.BaseViewModel
 import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
@@ -16,7 +16,7 @@ import javax.inject.Inject
 class HomePersonalViewModel @Inject constructor(
     private val authRepository: AuthRepository,
     private val userRepository: UserRepository,
-) : ViewModel() {
+) : BaseViewModel<Unit>() {
 
     val userUiState: StateFlow<HomePersonalUserUiState> =
         combine(authRepository.state, userRepository.user) { auth, user ->
@@ -59,4 +59,10 @@ class HomePersonalViewModel @Inject constructor(
             started = SharingStarted.WhileSubscribed(5_000),
             initialValue = HomePersonalInteractiveUiState(),
         )
+
+    init {
+        initialState(showLoading = false)
+    }
+
+    override suspend fun productState() {}
 }

+ 336 - 5
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanIndexPage.kt

@@ -1,19 +1,59 @@
 package com.zaojiao.app.feat.home.plan
 
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.pager.HorizontalPager
+import androidx.compose.foundation.pager.rememberPagerState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.drawWithContent
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.PathEffect
+import androidx.compose.ui.graphics.drawscope.DrawStyle
+import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
 import androidx.hilt.navigation.compose.hiltViewModel
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import com.zaojiao.app.data.model.studyplan.StudyPlanTodayModel
 import com.zaojiao.app.data.model.studyplan.StudyPlanTomorrowModel
+import com.zaojiao.app.feat.design.Colors
+import com.zaojiao.app.feat.design.Expanded
+import com.zaojiao.app.feat.design.Images
+import com.zaojiao.app.feat.design.Spacer
 import com.zaojiao.app.feat.design.StatePage
 
 @Composable
-fun HomePlanIndexPage(
-    viewModel: HomePlanViewModel = hiltViewModel()
+internal fun HomePlanIndexPage(
+    viewModel: HomePlanIndexViewModel = hiltViewModel()
 ) {
     val uiState by viewModel.stateFlow.collectAsStateWithLifecycle()
 
@@ -22,26 +62,317 @@ fun HomePlanIndexPage(
             modifier = Modifier.fillMaxWidth()
         ) {
             item {
-                HomePlanTomorrow(tomorrowPlanList = this@StatePage.tomorrowPlanList)
+                HomePlanTomorrow(
+                    tomorrowPlanList = this@StatePage.tomorrowPlanList,
+                )
             }
 
-            item{
-                HomePlanToday(todayPlanList = this@StatePage.todayPlanList)
+            item {
+                Box(modifier = Modifier.height(20.dp))
+            }
+
+            item {
+                HomePlanToday(
+                    todayPlanList = this@StatePage.todayPlanList,
+                )
             }
         }
     }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 @Composable
 internal fun HomePlanTomorrow(
     tomorrowPlanList: List<StudyPlanTomorrowModel>
 ) {
+    val count = tomorrowPlanList.size
+    val pagerState = rememberPagerState()
+
+    HorizontalPager(
+        pageCount = count,
+        state = pagerState,
+        modifier = Modifier
+            .padding(horizontal = 16.dp)
+            .clip(RoundedCornerShape(35.dp))
+            .fillMaxWidth()
+            .height(70.dp)
+    ) {
+        val plan = tomorrowPlanList[it]
+
+        Box(
+            modifier = Modifier
+                .clip(RoundedCornerShape(35.dp))
+                .fillMaxSize(),
+        ) {
+            Images.Color(
+                color = Colors.from("#FFFF8024"),
+                description = "",
+                modifier = Modifier.fillMaxSize(),
+            )
+
+            Row(modifier = Modifier.fillMaxSize()) {
+                Images.Network(
+                    url = plan.courseItemImgCover,
+                    modifier = Modifier
+                        .padding(6.dp)
+                        .border(
+                            width = 1.dp,
+                            color = Color.White,
+                            shape = RoundedCornerShape(35.dp),
+                        )
+                        .clip(RoundedCornerShape(35.dp))
+                        .background(color = Colors.from("#36000000"))
+                        .aspectRatio(ratio = 1f),
+                )
+            }
+        }
+    }
 
+    if (count > 1) {
+        Row(
+            modifier = Modifier
+                .padding(top = 8.dp)
+                .fillMaxWidth()
+                .height(4.dp),
+            horizontalArrangement = Arrangement.Center,
+        ) {
+            repeat(count) {
+                if (it == pagerState.currentPage) {
+                    Box(
+                        modifier = Modifier
+                            .padding(horizontal = 2.dp)
+                            .background(
+                                color = Colors.from("#d8d8d8"),
+                                shape = RoundedCornerShape(2.dp),
+                            )
+                            .fillMaxHeight()
+                            .width(16.dp),
+                    )
+                } else {
+                    Box(
+                        modifier = Modifier
+                            .padding(horizontal = 2.dp)
+                            .background(
+                                color = Colors.from("#d8d8d8"),
+                                shape = RoundedCornerShape(2.dp),
+                            )
+                            .height(4.dp)
+                            .width(4.dp),
+                    )
+                }
+            }
+        }
+    }
 }
 
 @Composable
 internal fun HomePlanToday(
     todayPlanList: List<StudyPlanTodayModel>
 ) {
+    Box(
+        modifier = Modifier
+            .padding(horizontal = 16.dp)
+            .fillMaxWidth()
+            .height(227.dp),
+    ) {
+        Box(
+            modifier = Modifier
+                .background(
+                    brush = Brush.horizontalGradient(
+                        colors = listOf(
+                            Colors.from("#EBFEE6D5"),
+                            Colors.from("#FFFFE7D6"),
+                        )
+                    ),
+                    shape = RoundedCornerShape(20.dp)
+                )
+                .fillMaxSize()
+        )
+
+        Column(
+            modifier = Modifier.fillMaxSize(),
+        ) {
+            Row(
+                modifier = Modifier
+                    .padding(horizontal = 12.dp, vertical = 20.dp)
+                    .fillMaxWidth()
+                    .wrapContentHeight(),
+                verticalAlignment = Alignment.CenterVertically,
+            ) {
+                Text(
+                    text = "今日计划",
+                    style = TextStyle(
+                        color = Colors.from("#FFFF8024"),
+                        fontWeight = FontWeight.SemiBold,
+                        fontSize = 20.sp,
+                        lineHeight = 28.sp,
+                    ),
+                )
+
+                Spacer(width = 6.dp)
 
+                Text(
+                    text = "共${todayPlanList.size}节",
+                    style = TextStyle(
+                        color = Colors.from("#FFFF8024"),
+                        fontWeight = FontWeight.Medium,
+                        fontSize = 11.sp,
+                        lineHeight = 12.sp,
+                    ),
+                    modifier = Modifier
+                        .background(
+                            color = Colors
+                                .from("#FFFF8024")
+                                .copy(alpha = 0.2f),
+                            shape = RoundedCornerShape(
+                                topStart = 15.dp,
+                                bottomStart = 2.dp,
+                                topEnd = 15.dp,
+                                bottomEnd = 15.dp,
+                            )
+                        )
+                        .padding(horizontal = 7.dp, vertical = 3.dp)
+                        .wrapContentSize(),
+                )
+
+                Expanded()
+                Text(
+                    text = "计划日历",
+                    style = TextStyle(
+                        color = Colors.from("#FFFF8024"),
+                        fontWeight = FontWeight.Normal,
+                        fontSize = 14.sp,
+                        lineHeight = 16.sp,
+                    ),
+                )
+            }
+
+            LazyRow(
+                modifier = Modifier
+                    .weight(1f)
+                    .fillMaxWidth(),
+            ) {
+                item {
+                    Box(modifier = Modifier.width(12.dp))
+                }
+                todayPlanList.forEach {
+                    item {
+                        HomePlanTodayItem(it)
+                    }
+                }
+                item {
+                    Box(modifier = Modifier.width(12.dp))
+                }
+            }
+
+            Spacer(height = 20.dp)
+        }
+    }
+}
+
+@Composable
+private fun HomePlanTodayItem(today: StudyPlanTodayModel) {
+    Box(
+        modifier = Modifier
+            .background(color = Color.Red.copy(alpha = 0.3f))
+            .fillMaxHeight()
+            .width(262.dp),
+    ) {
+        Box(
+            modifier = Modifier
+                .padding(start = 9.dp, bottom = 9.dp)
+                .align(Alignment.TopStart)
+                .border(
+                    width = 3.dp, color = Color.White,
+                    shape = RoundedCornerShape(14.dp)
+                )
+                .background(
+                    color = Color.Green.copy(alpha = 0.3f),
+                    shape = RoundedCornerShape(14.dp),
+                )
+                .fillMaxHeight()
+                .width(96.dp)
+        ) {
+            Images.Network(
+                url = today.courseItemImgCover,
+                modifier = Modifier
+                    .clip(RoundedCornerShape(14.dp))
+                    .fillMaxSize(),
+            )
+
+            Text(
+                text = today.courseCategoryName,
+                style = TextStyle(
+                    color = Color.White,
+                    fontWeight = FontWeight.SemiBold,
+                    fontSize = 10.sp,
+                    lineHeight = 10.sp,
+                ),
+                modifier = Modifier
+                    .align(Alignment.TopStart)
+                    .padding(3.dp)
+                    .drawWithContent {
+                        this.drawContent()
+                        val radius = 3.dp.toPx()
+                        val radius2 = 6.dp.toPx()
+
+                        val width = this.size.width
+                        val height = this.size.height
+
+                        val path = Path().apply {
+                            moveTo(width + radius, 0f)
+                            arcTo(
+                                rect = Rect(
+                                    center = Offset(width + radius, radius),
+                                    radius = radius,
+                                ),
+                                startAngleDegrees = -100f,
+                                sweepAngleDegrees = -90f,
+                                forceMoveTo = true,
+                            )
+                            lineTo(width, height - radius)
+                            arcTo(
+                                rect = Rect(
+                                    center = Offset(width - radius2, height - radius2),
+                                    radius = radius2,
+                                ),
+                                startAngleDegrees = 0f,
+                                sweepAngleDegrees = 80f,
+                                forceMoveTo = true,
+                            )
+                            lineTo(radius, height)
+                            arcTo(
+                                rect = Rect(
+                                    center = Offset(radius, height + radius),
+                                    radius = radius,
+                                ),
+                                startAngleDegrees = -90f,
+                                sweepAngleDegrees = -90f,
+                                forceMoveTo = true,
+                            )
+                        }
+
+                        this.drawPath(
+                            path = path,
+                            color = Color.White,
+                            style = Stroke(
+                                width = 3.dp.toPx(),
+                            )
+                        )
+                    }
+                    .background(
+                        color = Colors
+                            .from("#FFFF8024"),
+                        shape = RoundedCornerShape(
+                            topStart = 10.dp,
+                            bottomStart = 4.dp,
+                            topEnd = 0.dp,
+                            bottomEnd = 0.dp,
+                        )
+                    )
+                    .padding(horizontal = 7.dp, vertical = 3.dp)
+                    .wrapContentSize(),
+            )
+        }
+    }
 }

+ 33 - 0
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanIndexViewModel.kt

@@ -0,0 +1,33 @@
+package com.zaojiao.app.feat.home.plan
+
+import androidx.lifecycle.viewModelScope
+import com.zaojiao.app.core.auth.data.AuthRepository
+import com.zaojiao.app.core.auth.utils.AuthState
+import com.zaojiao.app.data.repo.StudyPlanRepository
+import com.zaojiao.app.feat.design.viewmodel.BaseViewModel
+import com.zaojiao.app.feat.home.plan.state.HomePlanIndexUiState
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@HiltViewModel
+class HomePlanIndexViewModel @Inject constructor(
+    private val authRepository: AuthRepository,
+    private val studyPlanRepository: StudyPlanRepository,
+) : BaseViewModel<HomePlanIndexUiState>() {
+
+    init {
+        initialState()
+    }
+
+    override suspend fun productState(): HomePlanIndexUiState {
+        val todayPlanList = studyPlanRepository.getTodayPlanList()
+        val tomorrowPlanList = studyPlanRepository.getTomorrowPlanList()
+
+        return HomePlanIndexUiState(
+            todayPlanList = todayPlanList,
+            tomorrowPlanList = tomorrowPlanList,
+        )
+    }
+}

+ 10 - 3
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanPage.kt

@@ -1,9 +1,9 @@
 package com.zaojiao.app.feat.home.plan
 
+import android.util.Log
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.navigationBarsPadding
 import androidx.compose.foundation.layout.statusBarsPadding
 import androidx.compose.foundation.pager.HorizontalPager
 import androidx.compose.foundation.pager.rememberPagerState
@@ -13,10 +13,14 @@ import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
+import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
+import androidx.navigation.NavBackStackEntry
 import kotlinx.coroutines.launch
 
 @Composable
-internal fun HomePlanRoute() {
+internal fun HomeStudyPlanRoute() {
     HomePlanPage()
 }
 
@@ -27,6 +31,9 @@ fun HomePlanPage() {
     val pageState = rememberPagerState()
     val coroutineScope = rememberCoroutineScope()
 
+    val current = LocalViewModelStoreOwner.current
+    Log.e("view-model", "HomePlanPage: ${current is NavBackStackEntry}")
+
     Column(
         modifier = Modifier
             .statusBarsPadding()
@@ -49,7 +56,7 @@ fun HomePlanPage() {
         HorizontalPager(
             state = pageState,
             pageCount = 2,
-            userScrollEnabled = true,
+            userScrollEnabled = false,
         ) {
             when (it) {
                 0 -> HomePlanIndexPage()

+ 0 - 1
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanTotalPage.kt

@@ -10,7 +10,6 @@ import androidx.hilt.navigation.compose.hiltViewModel
 
 @Composable
 fun HomePlanTotalPage(
-    viewModel: HomePlanViewModel = hiltViewModel()
 ) {
     Box(
         modifier = Modifier

+ 1 - 1
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/HomePlanViewModel.kt

@@ -10,7 +10,7 @@ import javax.inject.Inject
 class HomePlanViewModel @Inject constructor(
     private val studyPlanRepository: StudyPlanRepository,
 ) : BaseViewModel<HomePlanIndexUiState>() {
-    override suspend fun initData(): HomePlanIndexUiState {
+    override suspend fun productState(): HomePlanIndexUiState {
         val todayPlanList = studyPlanRepository.getTodayPlanList()
         val tomorrowPlanList = studyPlanRepository.getTomorrowPlanList()
 

+ 5 - 1
feat/home/src/main/kotlin/com/zaojiao/app/feat/home/plan/state/HomePlanIndexUiState.kt

@@ -7,4 +7,8 @@ data class HomePlanIndexUiState(
     val todayPlanList: List<StudyPlanTodayModel> = emptyList(),
     val tomorrowPlanList: List<StudyPlanTomorrowModel> = emptyList(),
     val historyPlanList: List<String> = emptyList(),
-)
+){
+    companion object{
+        val logout = HomePlanIndexUiState()
+    }
+}