优化AI界面,添加分页加载功能,支持动态加载更多智能体数据;重构UI布局
This commit is contained in:
@@ -28,9 +28,14 @@ import androidx.compose.foundation.pager.rememberPagerState
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
@@ -69,13 +74,24 @@ import com.aiosman.ravenow.utils.DebounceUtils
|
|||||||
import com.aiosman.ravenow.utils.ResourceCleanupManager
|
import com.aiosman.ravenow.utils.ResourceCleanupManager
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.lazy.grid.items as gridItems
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.foundation.lazy.grid.items
|
|
||||||
|
|
||||||
@OptIn( ExperimentalFoundationApi::class)
|
// 检测是否接近列表底部的扩展函数
|
||||||
|
fun LazyListState.isScrolledToEnd(buffer: Int = 3): Boolean {
|
||||||
|
val layoutInfo = this.layoutInfo
|
||||||
|
val totalItemsCount = layoutInfo.totalItemsCount
|
||||||
|
val lastVisibleItemIndex = layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0
|
||||||
|
|
||||||
|
return lastVisibleItemIndex >= (totalItemsCount - buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Agent() {
|
fun Agent() {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
@@ -89,7 +105,6 @@ fun Agent() {
|
|||||||
var scope = rememberCoroutineScope()
|
var scope = rememberCoroutineScope()
|
||||||
|
|
||||||
val viewModel: AgentViewModel = viewModel()
|
val viewModel: AgentViewModel = viewModel()
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
|
|
||||||
// 确保推荐Agent数据已加载
|
// 确保推荐Agent数据已加载
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
@@ -107,163 +122,92 @@ fun Agent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(
|
val agentItems = viewModel.agentItems
|
||||||
modifier = Modifier
|
var selectedTabIndex by remember { mutableStateOf(0) }
|
||||||
.fillMaxSize()
|
|
||||||
.verticalScroll(scrollState)
|
|
||||||
.padding(
|
|
||||||
top = statusBarPaddingValues.calculateTopPadding(),
|
|
||||||
bottom = navigationBarPaddings,
|
|
||||||
start = 16.dp,
|
|
||||||
end = 16.dp
|
|
||||||
),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.wrapContentHeight()
|
|
||||||
.height(44.dp)
|
|
||||||
.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.Start,
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
androidx.compose.material3.Text(
|
|
||||||
text = "Rave AI",
|
|
||||||
fontSize = 20.sp,
|
|
||||||
fontWeight = FontWeight.W900,
|
|
||||||
color = AppColors.text,
|
|
||||||
modifier = Modifier
|
|
||||||
.align(Alignment.CenterVertically)
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
// 无限滚动状态
|
||||||
|
val listState = rememberLazyListState()
|
||||||
|
|
||||||
Image(
|
// 创建一个可观察的滚动到底部状态
|
||||||
painter = painterResource(id = R.drawable.rider_pro_nav_search),
|
val isScrolledToEnd by remember {
|
||||||
contentDescription = "search",
|
derivedStateOf {
|
||||||
modifier = Modifier
|
listState.isScrolledToEnd()
|
||||||
.size(24.dp)
|
|
||||||
.noRippleClickable {
|
|
||||||
navController.navigate(NavigationRoute.Search.route)
|
|
||||||
},
|
|
||||||
colorFilter = ColorFilter.tint(AppColors.text)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(15.dp))
|
}
|
||||||
// // 搜索框
|
|
||||||
// Row(
|
|
||||||
// modifier = Modifier
|
|
||||||
// .height(36.dp)
|
|
||||||
// .weight(1f)
|
|
||||||
// .clip(shape = RoundedCornerShape(8.dp))
|
|
||||||
// .background(AppColors.inputBackground)
|
|
||||||
// .padding(horizontal = 8.dp, vertical = 0.dp)
|
|
||||||
// .noRippleClickable {
|
|
||||||
// // 搜索框点击事件
|
|
||||||
// },
|
|
||||||
// verticalAlignment = Alignment.CenterVertically
|
|
||||||
// ) {
|
|
||||||
// Icon(
|
|
||||||
// painter = painterResource(id = R.drawable.rider_pro_nav_search),
|
|
||||||
// contentDescription = null,
|
|
||||||
// tint = AppColors.inputHint
|
|
||||||
// )
|
|
||||||
// Box {
|
|
||||||
// Text(
|
|
||||||
// text = stringResource(R.string.search),
|
|
||||||
// modifier = Modifier.padding(start = 8.dp),
|
|
||||||
// color = AppColors.inputHint,
|
|
||||||
// fontSize = 17.sp
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Spacer(modifier = Modifier.width(16.dp))
|
|
||||||
// // 创建智能体
|
|
||||||
// Icon(
|
|
||||||
// modifier = Modifier
|
|
||||||
// .size(36.dp)
|
|
||||||
// .noRippleClickable {
|
|
||||||
// if (DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
|
|
||||||
// // 检查游客模式,如果是游客则跳转登录
|
|
||||||
// if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.CREATE_AGENT)) {
|
|
||||||
// navController.navigate(NavigationRoute.Login.route)
|
|
||||||
// } else {
|
|
||||||
// // 导航到添加智能体页面
|
|
||||||
// navController.navigate(
|
|
||||||
// NavigationRoute.AddAgent.route
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }) {
|
|
||||||
// lastClickTime = System.currentTimeMillis()
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// painter = painterResource(id = R.drawable.rider_pro_new_post_add_pic),
|
|
||||||
// contentDescription = null,
|
|
||||||
// tint = AppColors.text
|
|
||||||
// )
|
|
||||||
|
|
||||||
Column(
|
// 检测滚动到底部并加载更多数据
|
||||||
modifier = Modifier
|
LaunchedEffect(isScrolledToEnd) {
|
||||||
.fillMaxWidth()
|
if (isScrolledToEnd && !viewModel.isLoadingMore && agentItems.isNotEmpty() && viewModel.hasMoreData) {
|
||||||
.padding(vertical = 8.dp)
|
viewModel.loadMoreAgents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
) {
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = {
|
||||||
|
androidx.compose.material3.Text(
|
||||||
|
text = "Rave AI",
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.W900,
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_nav_search),
|
||||||
|
contentDescription = "search",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(24.dp)
|
||||||
|
.noRippleClickable {
|
||||||
|
navController.navigate(NavigationRoute.Search.route)
|
||||||
|
},
|
||||||
|
colorFilter = ColorFilter.tint(AppColors.text)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
containerColor = AppColors.background
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
containerColor = AppColors.background,
|
||||||
|
contentWindowInsets = WindowInsets(0, 0, 0, 0)
|
||||||
|
) { paddingValues ->
|
||||||
|
LazyColumn(
|
||||||
|
state = listState,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(paddingValues)
|
||||||
|
.padding(
|
||||||
|
bottom = navigationBarPaddings,
|
||||||
|
start = 16.dp,
|
||||||
|
end = 16.dp
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
|
||||||
// // 标题
|
// 类别标签页 - 吸顶
|
||||||
// Row(
|
stickyHeader(key = "category_tabs") {
|
||||||
// verticalAlignment = Alignment.CenterVertically,
|
Column(
|
||||||
// modifier = Modifier.padding(bottom = 12.dp)
|
|
||||||
// ) {
|
|
||||||
// Image(
|
|
||||||
// painter = painterResource(R.mipmap.rider_pro_agent2),
|
|
||||||
// contentDescription = "agent",
|
|
||||||
// modifier = Modifier.size(28.dp),
|
|
||||||
//
|
|
||||||
// )
|
|
||||||
// Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
// androidx.compose.material3.Text(
|
|
||||||
// text = stringResource(R.string.agent_recommend_agent),
|
|
||||||
// fontSize = 16.sp,
|
|
||||||
// fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
|
|
||||||
// color = AppColors.text
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
|
|
||||||
var selectedTabIndex by remember { mutableStateOf(0) }
|
|
||||||
|
|
||||||
// 标签页
|
|
||||||
LazyRow(
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.wrapContentHeight()
|
.background(AppColors.background)
|
||||||
.padding(bottom = 16.dp),
|
.padding(top = 4.dp, bottom = 8.dp)
|
||||||
horizontalArrangement = Arrangement.Start,
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
) {
|
||||||
item {
|
LazyRow(
|
||||||
CustomTabItem(
|
modifier = Modifier
|
||||||
text = stringResource(R.string.agent_recommend),
|
.fillMaxWidth()
|
||||||
isSelected = selectedTabIndex == 0,
|
.wrapContentHeight()
|
||||||
onClick = {
|
.padding(bottom = 8.dp),
|
||||||
selectedTabIndex = 0
|
horizontalArrangement = Arrangement.Start,
|
||||||
viewModel.loadAllAgents()
|
verticalAlignment = Alignment.CenterVertically
|
||||||
}
|
) {
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
|
||||||
TabSpacer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 动态添加分类标签
|
|
||||||
viewModel.categories.take(4).forEachIndexed { index, category ->
|
|
||||||
item {
|
item {
|
||||||
CustomTabItem(
|
CustomTabItem(
|
||||||
text = category.name,
|
text = stringResource(R.string.agent_recommend),
|
||||||
isSelected = selectedTabIndex == index + 1,
|
isSelected = selectedTabIndex == 0,
|
||||||
onClick = {
|
onClick = {
|
||||||
selectedTabIndex = index + 1
|
selectedTabIndex = 0
|
||||||
viewModel.loadAgentsByCategory(category.id)
|
viewModel.loadAllAgents()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -271,117 +215,177 @@ fun Agent() {
|
|||||||
item {
|
item {
|
||||||
TabSpacer()
|
TabSpacer()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
// 动态添加分类标签
|
||||||
CustomTabItem(
|
viewModel.categories.take(4).forEachIndexed { index, category ->
|
||||||
text = "scenes",
|
item {
|
||||||
isSelected = selectedTabIndex == 1,
|
CustomTabItem(
|
||||||
onClick = {
|
text = category.name,
|
||||||
selectedTabIndex = 1
|
isSelected = selectedTabIndex == index + 1,
|
||||||
|
onClick = {
|
||||||
|
selectedTabIndex = index + 1
|
||||||
|
viewModel.loadAgentsByCategory(category.id)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
item {
|
||||||
TabSpacer()
|
TabSpacer()
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
|
||||||
CustomTabItem(
|
|
||||||
text = "voices",
|
|
||||||
isSelected = selectedTabIndex == 6,
|
|
||||||
onClick = {
|
|
||||||
selectedTabIndex = 6
|
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
item {
|
||||||
TabSpacer()
|
CustomTabItem(
|
||||||
}
|
text = "scenes",
|
||||||
|
isSelected = selectedTabIndex == 1,
|
||||||
|
onClick = {
|
||||||
|
selectedTabIndex = 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
CustomTabItem(
|
TabSpacer()
|
||||||
text = "anime",
|
}
|
||||||
isSelected = selectedTabIndex == 7,
|
|
||||||
onClick = {
|
|
||||||
selectedTabIndex = 7
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
item {
|
item {
|
||||||
TabSpacer()
|
CustomTabItem(
|
||||||
}
|
text = "voices",
|
||||||
|
isSelected = selectedTabIndex == 6,
|
||||||
|
onClick = {
|
||||||
|
selectedTabIndex = 6
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
CustomTabItem(
|
TabSpacer()
|
||||||
text = "assist",
|
}
|
||||||
isSelected = selectedTabIndex == 8,
|
|
||||||
onClick = {
|
item {
|
||||||
selectedTabIndex = 8
|
CustomTabItem(
|
||||||
}
|
text = "anime",
|
||||||
)
|
isSelected = selectedTabIndex == 7,
|
||||||
|
onClick = {
|
||||||
|
selectedTabIndex = 7
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
TabSpacer()
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
CustomTabItem(
|
||||||
|
text = "assist",
|
||||||
|
isSelected = selectedTabIndex == 8,
|
||||||
|
onClick = {
|
||||||
|
selectedTabIndex = 8
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
when {
|
// 推荐内容区域
|
||||||
selectedTabIndex == 0 -> {
|
item {
|
||||||
AgentViewPagerSection(agentItems = viewModel.agentItems.take(15), viewModel)
|
Column(
|
||||||
}
|
modifier = Modifier
|
||||||
selectedTabIndex in 1..viewModel.categories.size -> {
|
.fillMaxWidth()
|
||||||
AgentViewPagerSection(agentItems = viewModel.agentItems.take(15), viewModel)
|
.padding(vertical = 8.dp)
|
||||||
}
|
) {
|
||||||
else -> {
|
when {
|
||||||
val shuffledAgents = viewModel.agentItems.shuffled().take(15)
|
selectedTabIndex == 0 -> {
|
||||||
AgentViewPagerSection(agentItems = shuffledAgents, viewModel)
|
AgentViewPagerSection(agentItems = viewModel.agentItems.take(15), viewModel)
|
||||||
|
}
|
||||||
|
selectedTabIndex in 1..viewModel.categories.size -> {
|
||||||
|
AgentViewPagerSection(agentItems = viewModel.agentItems.take(15), viewModel)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val shuffledAgents = viewModel.agentItems.shuffled().take(15)
|
||||||
|
AgentViewPagerSection(agentItems = shuffledAgents, viewModel)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.wrapContentHeight(),
|
|
||||||
// center the tabs
|
|
||||||
horizontalArrangement = Arrangement.Start,
|
|
||||||
verticalAlignment = Alignment.Bottom
|
|
||||||
) {
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.mipmap.rider_pro_agent2),
|
|
||||||
contentDescription = "agent",
|
|
||||||
modifier = Modifier.size(28.dp),
|
|
||||||
|
|
||||||
)
|
// "发现更多" 标题 - 吸顶
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
stickyHeader(key = "discover_more") {
|
||||||
androidx.compose.material3.Text(
|
Row(
|
||||||
text = stringResource(R.string.agent_find),
|
modifier = Modifier
|
||||||
fontSize = 16.sp,
|
.fillMaxWidth()
|
||||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
|
.background(AppColors.background)
|
||||||
color = AppColors.text
|
.padding(top = 8.dp, bottom = 12.dp),
|
||||||
)
|
horizontalArrangement = Arrangement.Start,
|
||||||
|
verticalAlignment = Alignment.Bottom
|
||||||
}
|
) {
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Image(
|
||||||
Column(
|
painter = painterResource(R.mipmap.rider_pro_agent2),
|
||||||
modifier = Modifier
|
contentDescription = "agent",
|
||||||
.fillMaxWidth()
|
modifier = Modifier.size(28.dp),
|
||||||
.weight(1f)
|
|
||||||
) {
|
|
||||||
val agentItems = viewModel.agentItems
|
|
||||||
LazyVerticalGrid(
|
|
||||||
columns = GridCells.Fixed(2),
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(32.dp)
|
|
||||||
) {
|
|
||||||
items(agentItems) { agentItem ->
|
|
||||||
AgentCardSquare(
|
|
||||||
agentItem = agentItem,
|
|
||||||
viewModel = viewModel,
|
|
||||||
navController = LocalNavController.current
|
|
||||||
)
|
)
|
||||||
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
|
androidx.compose.material3.Text(
|
||||||
|
text = stringResource(R.string.agent_find),
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Agent网格 - 使用行式布局
|
||||||
|
items(
|
||||||
|
items = agentItems.chunked(2),
|
||||||
|
key = { row -> row.firstOrNull()?.openId ?: "" }
|
||||||
|
) { rowItems ->
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 16.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
) {
|
||||||
|
rowItems.forEach { agentItem ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
) {
|
||||||
|
AgentCardSquare(
|
||||||
|
agentItem = agentItem,
|
||||||
|
viewModel = viewModel,
|
||||||
|
navController = LocalNavController.current
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果这一行只有一个item,添加一个空的占位符
|
||||||
|
if (rowItems.size == 1) {
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多指示器
|
||||||
|
if (viewModel.isLoadingMore) {
|
||||||
|
item {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 24.dp),
|
||||||
|
horizontalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
androidx.compose.material3.CircularProgressIndicator(
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
color = AppColors.text,
|
||||||
|
strokeWidth = 2.dp
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
|
androidx.compose.material3.Text(
|
||||||
|
text = "加载中...",
|
||||||
|
color = AppColors.secondaryText,
|
||||||
|
fontSize = 14.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,42 +38,82 @@ object AgentViewModel: ViewModel() {
|
|||||||
var isLoading by mutableStateOf(false)
|
var isLoading by mutableStateOf(false)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
// 分页相关状态
|
||||||
|
var isLoadingMore by mutableStateOf(false)
|
||||||
|
private set
|
||||||
|
|
||||||
|
var currentPage by mutableStateOf(1)
|
||||||
|
private set
|
||||||
|
|
||||||
|
var hasMoreData by mutableStateOf(true)
|
||||||
|
private set
|
||||||
|
|
||||||
|
private val pageSize = 20
|
||||||
|
private var currentCategoryId: Int? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
loadAgentData()
|
loadAgentData()
|
||||||
loadCategories()
|
loadCategories()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadAgentData(categoryId: Int? = null) {
|
private fun loadAgentData(categoryId: Int? = null, page: Int = 1, isLoadMore: Boolean = false) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
isLoading = true
|
if (isLoadMore) {
|
||||||
|
isLoadingMore = true
|
||||||
|
} else {
|
||||||
|
isLoading = true
|
||||||
|
// 重置分页状态
|
||||||
|
currentPage = 1
|
||||||
|
hasMoreData = true
|
||||||
|
currentCategoryId = categoryId
|
||||||
|
}
|
||||||
|
|
||||||
errorMessage = null
|
errorMessage = null
|
||||||
try {
|
try {
|
||||||
val response = if (categoryId != null) {
|
val response = if (categoryId != null) {
|
||||||
// 根据分类ID获取智能体
|
// 根据分类ID获取智能体
|
||||||
apiClient.getAgent(
|
apiClient.getAgent(
|
||||||
page = 1,
|
page = page,
|
||||||
pageSize = 20,
|
pageSize = pageSize,
|
||||||
withWorkflow = 1,
|
withWorkflow = 1,
|
||||||
categoryIds = listOf(categoryId)
|
categoryIds = listOf(categoryId)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// 获取所有智能体
|
// 获取所有智能体
|
||||||
apiClient.getAgent(page = 1, pageSize = 20, withWorkflow = 1)
|
apiClient.getAgent(page = page, pageSize = pageSize, withWorkflow = 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
val agents = response.body()?.data?.list ?: emptyList<Agent>()
|
val responseData = response.body()?.data
|
||||||
|
val agents = responseData?.list ?: emptyList<Agent>()
|
||||||
agentItems = agents.map { agent ->
|
val newAgentItems = agents.map { agent ->
|
||||||
AgentItem.fromAgent(agent)
|
AgentItem.fromAgent(agent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isLoadMore) {
|
||||||
|
// 加载更多:追加到现有列表
|
||||||
|
agentItems = agentItems + newAgentItems
|
||||||
|
currentPage = page
|
||||||
|
} else {
|
||||||
|
// 首次加载或刷新:替换整个列表
|
||||||
|
agentItems = newAgentItems
|
||||||
|
currentPage = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否还有更多数据
|
||||||
|
hasMoreData = agents.size >= pageSize
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
errorMessage = "获取Agent数据失败: ${response.code()}"
|
errorMessage = "获取Agent数据失败: ${response.code()}"
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
errorMessage = "网络请求失败: ${e.message}"
|
errorMessage = "网络请求失败: ${e.message}"
|
||||||
} finally {
|
} finally {
|
||||||
isLoading = false
|
if (isLoadMore) {
|
||||||
|
isLoadingMore = false
|
||||||
|
} else {
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,6 +155,23 @@ object AgentViewModel: ViewModel() {
|
|||||||
fun loadAllAgents() {
|
fun loadAllAgents() {
|
||||||
loadAgentData()
|
loadAgentData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载更多Agent数据
|
||||||
|
*/
|
||||||
|
fun loadMoreAgents() {
|
||||||
|
// 检查是否正在加载或没有更多数据
|
||||||
|
if (isLoadingMore || !hasMoreData) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val nextPage = currentPage + 1
|
||||||
|
loadAgentData(
|
||||||
|
categoryId = currentCategoryId,
|
||||||
|
page = nextPage,
|
||||||
|
isLoadMore = true
|
||||||
|
)
|
||||||
|
}
|
||||||
fun createSingleChat(
|
fun createSingleChat(
|
||||||
openId: String,
|
openId: String,
|
||||||
) {
|
) {
|
||||||
@@ -176,6 +233,10 @@ object AgentViewModel: ViewModel() {
|
|||||||
errorMessage = null
|
errorMessage = null
|
||||||
isRefreshing = false
|
isRefreshing = false
|
||||||
isLoading = false
|
isLoading = false
|
||||||
|
isLoadingMore = false
|
||||||
|
currentPage = 1
|
||||||
|
hasMoreData = true
|
||||||
|
currentCategoryId = null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user