1. 启动时序修复:Launcher 从 ActivationActivity 改为 HomeActivity,
已激活用户直接进首页,不再闪现激活页
2. 详情页布局重构:左右分栏设计(左侧海报 + 右侧信息/操作),
全屏背景图 + 渐变遮罩,TV 端焦点导航
3. 对接后端取消订单接口 POST /api/jst/daycard/cancel/{orderNo},
用户关闭支付弹窗时自动取消未支付订单
114 lines
4.5 KiB
Kotlin
114 lines
4.5 KiB
Kotlin
package com.pukka.mediaapp.viewmodel
|
||
|
||
import android.util.Log
|
||
import androidx.lifecycle.ViewModel
|
||
import androidx.lifecycle.viewModelScope
|
||
import com.migu.bean.GetTopButtonBean
|
||
import com.pukka.mediaapp.model.LayoutSection
|
||
import com.pukka.mediaapp.model.NavItem
|
||
import com.pukka.mediaapp.network.MediaRepository
|
||
import com.pukka.mediaapp.utils.FileLogger
|
||
import kotlinx.coroutines.flow.MutableStateFlow
|
||
import kotlinx.coroutines.flow.StateFlow
|
||
import kotlinx.coroutines.flow.asStateFlow
|
||
import kotlinx.coroutines.launch
|
||
|
||
/**
|
||
* 首页 ViewModel:负责导航栏数据与二级布局楼层数据。
|
||
*/
|
||
class HomeViewModel : ViewModel() {
|
||
|
||
private val repository = MediaRepository.getInstance()
|
||
|
||
private val _navItems = MutableStateFlow<List<NavItem>>(emptyList())
|
||
val navItems: StateFlow<List<NavItem>> = _navItems.asStateFlow()
|
||
|
||
private val _sections = MutableStateFlow<List<LayoutSection>>(emptyList())
|
||
val sections: StateFlow<List<LayoutSection>> = _sections.asStateFlow()
|
||
|
||
private val _loading = MutableStateFlow(false)
|
||
val loading: StateFlow<Boolean> = _loading.asStateFlow()
|
||
|
||
private val _error = MutableStateFlow<String?>(null)
|
||
val error: StateFlow<String?> = _error.asStateFlow()
|
||
|
||
/** 默认选中的导航项位置 */
|
||
private val _selectedNavIndex = MutableStateFlow(0)
|
||
val selectedNavIndex: StateFlow<Int> = _selectedNavIndex.asStateFlow()
|
||
|
||
private var hasLoadedNav = false
|
||
|
||
/** 加载首页导航,加载成功后默认请求 isFocus=1 的导航项对应的布局。 */
|
||
fun loadNav() {
|
||
if (hasLoadedNav) return
|
||
viewModelScope.launch {
|
||
loadTopButton()
|
||
_loading.value = true
|
||
repository.getLayoutNav()
|
||
.onSuccess { response ->
|
||
val allItems = response.data
|
||
?.flatMap { it.navList ?: emptyList() }
|
||
?: emptyList()
|
||
|
||
// 只保留有布局数据的标签(type=1 为内容页)
|
||
val contentItems = allItems.filter { it.type == 1 }
|
||
_navItems.value = contentItems
|
||
FileLogger.log("HomeVM", "导航加载: ${contentItems.size} 个标签, 默认选中=${contentItems.indexOfFirst { it.isFocus == "1" }}")
|
||
hasLoadedNav = true
|
||
if (contentItems.isNotEmpty()) {
|
||
// 优先选 isFocus=="1" 的,否则选第一个
|
||
val defaultIndex = contentItems.indexOfFirst { it.isFocus == "1" }
|
||
val targetIndex = if (defaultIndex >= 0) defaultIndex else 0
|
||
_selectedNavIndex.value = targetIndex
|
||
loadLayout(contentItems[targetIndex].navid)
|
||
} else {
|
||
_loading.value = false
|
||
}
|
||
}
|
||
.onFailure {
|
||
_error.value = it.message ?: "加载导航失败"
|
||
_loading.value = false
|
||
}
|
||
}
|
||
}
|
||
|
||
/** 根据 navid 加载二级页面布局(楼层列表)。 */
|
||
fun loadLayout(navid: String) {
|
||
if (navid.isEmpty()) return
|
||
viewModelScope.launch {
|
||
_loading.value = true
|
||
repository.getLayout(navid)
|
||
.onSuccess { response ->
|
||
val sections = response.data ?: emptyList()
|
||
Log.d("HomeViewModel", "loadLayout success: ${sections.size} sections")
|
||
FileLogger.log("HomeVM", "布局加载: navid=$navid ${sections.size} 个楼层")
|
||
_sections.value = sections
|
||
}
|
||
.onFailure {
|
||
Log.e("HomeViewModel", "loadLayout failed", it)
|
||
_error.value = it.message ?: "加载内容失败"
|
||
_sections.value = emptyList()
|
||
}
|
||
_loading.value = false
|
||
}
|
||
}
|
||
|
||
/** 顶部功能键数据(供 TopView.bindData 渲染) */
|
||
private val _topButton = MutableStateFlow<GetTopButtonBean?>(null)
|
||
val topButton: StateFlow<GetTopButtonBean?> = _topButton.asStateFlow()
|
||
|
||
/** 加载顶部功能键 */
|
||
fun loadTopButton() {
|
||
viewModelScope.launch {
|
||
repository.getTopButton()
|
||
.onSuccess { _topButton.value = it }
|
||
.onFailure { FileLogger.log("HomeVM", "顶部按钮加载失败: ${it.message}") }
|
||
}
|
||
}
|
||
|
||
/** 更新选中的导航索引 */
|
||
fun selectNav(index: Int) {
|
||
_selectedNavIndex.value = index
|
||
}
|
||
}
|