首页UI调整

This commit is contained in:
weber
2025-08-14 19:04:20 +08:00
parent 112efa74e7
commit 2de8127882
3 changed files with 243 additions and 133 deletions

View File

@@ -7,8 +7,8 @@ import com.aiosman.ravenow.entity.ProfileEntity
import com.google.gson.annotations.SerializedName
data class Agent(
@SerializedName("author")
val author: String,
/*@SerializedName("author")
val author: String,*/
@SerializedName("avatar")
val avatar: String,
@SerializedName("breakMode")

View File

@@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -19,6 +20,8 @@ import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.Card
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.platform.LocalContext
import androidx.compose.material.ExperimentalMaterialApi
@@ -41,16 +44,21 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.draw.blur
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import androidx.lifecycle.viewmodel.compose.viewModel
import com.aiosman.ravenow.AppStore
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R
import kotlinx.coroutines.launch
import com.aiosman.ravenow.data.Room
import com.aiosman.ravenow.data.Agent
import com.aiosman.ravenow.data.api.ApiClient
import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.AgentCard
import com.aiosman.ravenow.ui.post.NewPostViewModel
// Banner数据类
data class BannerItem(
@@ -60,7 +68,7 @@ data class BannerItem(
val imageUrl: String,
val backgroundImageUrl: String,
val userCount: Int,
val agentName: String
val agentName: String,
) {
companion object {
fun fromRoom(room: Room): BannerItem {
@@ -68,7 +76,7 @@ data class BannerItem(
id = room.id,
title = room.name ?: "聊天室",
subtitle = room.description ?: "欢迎加入我们的聊天室",
imageUrl = room.avatar ?: "",
imageUrl = "${ApiClient.BASE_API_URL+"/outside"}${room.creator.profile.avatar}"+"?token="+"${AppStore.token}" ?: "",
backgroundImageUrl = "${ApiClient.BASE_API_URL+"/outside"}${room.recommendBanner}"+"?token="+"${AppStore.token}" ?: "",
userCount = room.userCount,
agentName = room.creator.profile.nickname
@@ -84,7 +92,7 @@ data class AgentItem(
val desc: String,
val avatar: String,
val useCount: Int,
val author: String
//val author: String
) {
companion object {
fun fromAgent(agent: Agent): AgentItem {
@@ -94,7 +102,7 @@ data class AgentItem(
desc = agent.desc,
avatar = "${ApiClient.BASE_API_URL+"/outside"}${agent.avatar}"+"?token="+"${AppStore.token}",
useCount = agent.useCount,
author = agent.author
//author = agent.author
)
}
}
@@ -106,6 +114,7 @@ data class AgentItem(
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun Explore() {
val navController = LocalNavController.current
val AppColors = LocalAppTheme.current
val scope = rememberCoroutineScope()
val viewModel: ExploreViewModel = viewModel()
@@ -118,27 +127,13 @@ fun Explore() {
isRefreshing = viewModel.isRefreshing
}
// 处理刷新
LaunchedEffect(isRefreshing) {
if (isRefreshing) {
viewModel.refreshBannerData()
viewModel.refreshAgentData()
// 模拟网络请求延迟
kotlinx.coroutines.delay(2000)
isRefreshing = false
}
}
val pullRefreshState = rememberPullRefreshState(
refreshing = isRefreshing,
onRefresh = {
scope.launch {
isRefreshing = true
// 重新请求数据
viewModel.refreshBannerData()
viewModel.refreshAgentData()
// 模拟网络请求延迟
kotlinx.coroutines.delay(2000)
isRefreshing = false
}
}
)
@@ -150,7 +145,7 @@ fun Explore() {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
.padding(vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
// 左侧头像
@@ -210,20 +205,22 @@ fun Explore() {
}
// 右侧聊天按钮
androidx.compose.material3.Button(
onClick = {
// 聊天逻辑
},
colors = androidx.compose.material3.ButtonDefaults.buttonColors(
containerColor = AppColors.main,
contentColor = Color.White
),
shape = RoundedCornerShape(20.dp),
modifier = Modifier.size(width = 60.dp, height = 32.dp)
Box(
modifier = Modifier
.size(width = 60.dp, height = 32.dp)
.background(
color = Color(0X147c7480),
shape = RoundedCornerShape(8.dp)
)
.clickable {
// 聊天逻辑
},
contentAlignment = Alignment.Center
) {
Text(
text = "聊天",
fontSize = 12.sp,
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
@@ -300,77 +297,111 @@ fun Explore() {
}
@Composable
fun HotChatRoomCard(roomItem: BannerItem) {
fun HotChatRoomGridItem(roomItem: BannerItem) {
val AppColors = LocalAppTheme.current
Card(
Row(
modifier = Modifier
.width(160.dp)
.height(80.dp),
shape = RoundedCornerShape(12.dp),
elevation = androidx.compose.material3.CardDefaults.cardElevation(defaultElevation = 4.dp)
.padding(horizontal = 2.dp, vertical = 4.dp)
.background( when (roomItem.id % 6) {
0 -> Color(0x285856d6)
1 -> Color(0x2832ade6)
2 -> Color(0x28ff9500)
3 -> Color(0x28ff3b30)
4 -> Color(0x28af52de)
else -> Color(0x28ffcc00)
},
shape = RoundedCornerShape(12.dp)),
verticalAlignment = Alignment.CenterVertically
) {
Row(
// 左侧图标
Box(
modifier = Modifier
.fillMaxSize()
.padding(12.dp),
verticalAlignment = Alignment.CenterVertically
.size(24.dp)
.padding(start = 16.dp),
contentAlignment = Alignment.Center
) {
// 左侧图标
Box(
modifier = Modifier
.size(32.dp)
.background(
color = when (roomItem.id % 5) {
0 -> Color(0xFFE3F2FD) // 浅蓝色
1 -> Color(0xFFF3E5F5) // 浅紫色
2 -> Color(0xFFFFF3E0) // 浅橙色
3 -> Color(0xFFFCE4EC) // 浅粉色
else -> Color(0xFFFFF8E1) // 浅黄色
},
shape = RoundedCornerShape(8.dp)
),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(R.drawable.rider_pro_group_chat),
contentDescription = "chat",
modifier = Modifier.size(16.dp),
colorFilter = ColorFilter.tint(Color.White)
)
}
Image(
painter = painterResource(R.drawable.rider_pro_group_chat),
contentDescription = "chat",
modifier = Modifier.size(12.dp),
Spacer(modifier = Modifier.width(8.dp))
// 右侧文字
Text(
text = roomItem.title,
fontSize = 12.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500,
color = AppColors.text,
maxLines = 2,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
modifier = Modifier.weight(1f)
)
}
}
Spacer(modifier = Modifier.width(6.dp))
// 右侧文字
Text(
text = roomItem.title,
fontSize = 14.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500,
color = AppColors.text,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
modifier = Modifier.padding(end = 16.dp, top = 8.dp, bottom = 8.dp)
)
}
}
@Composable
fun HotChatRoomSection(roomItems: List<BannerItem>) {
LazyRow(
fun HotChatRoomGrid(roomItems: List<BannerItem>) {
val AppColors = LocalAppTheme.current
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.spacedBy(12.dp)
.wrapContentWidth()
.padding(vertical = 2.dp)
) {
items(roomItems.size) { index ->
HotChatRoomCard(roomItem = roomItems[index])
repeat(3) { rowIndex ->
Row(
modifier = Modifier
.wrapContentWidth()
.padding(vertical = 2.dp),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.spacedBy(8.dp)
) {
repeat(3) { columnIndex ->
val itemIndex = rowIndex * 3 + columnIndex
if (itemIndex < roomItems.size) {
val roomItem = roomItems[itemIndex]
HotChatRoomGridItem(roomItem = roomItem)
} else {
// 填充空白占位
Spacer(modifier = Modifier.width(80.dp))
}
}
}
}
}
}
@Composable
fun HotChatRoomGridSection(roomItems: List<BannerItem>) {
val AppColors = LocalAppTheme.current
// 每行显示3个数据总共3行
val itemsPerRow = 3
val totalRows = 3
val totalItems = itemsPerRow * totalRows
// 计算需要多少个完整的3x3网格
val gridCount = (roomItems.size + totalItems - 1) / totalItems
LazyRow(
modifier = Modifier.fillMaxWidth(),
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 0.dp),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.spacedBy(6.dp)
) {
repeat(gridCount) { gridIndex ->
item {
HotChatRoomGrid(roomItems = roomItems.drop(gridIndex * totalItems).take(totalItems))
}
}
}
}
@Composable
fun BannerCard(bannerItem: BannerItem) {
@@ -390,6 +421,7 @@ fun Explore() {
// 背景图片
if (bannerItem.backgroundImageUrl.isNotEmpty()) {
CustomAsyncImage(
context = context,
imageUrl = bannerItem.backgroundImageUrl,
contentDescription = "背景图片",
modifier = Modifier.fillMaxSize(),
@@ -414,15 +446,14 @@ fun Explore() {
// 内容
Column(
modifier = Modifier
.fillMaxSize()
.padding(20.dp),
.fillMaxSize(),
verticalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween
) {
// 顶部:用户数量
Row(
Row(
verticalAlignment = Alignment.CenterVertically
) {
Image(
/* Image(
painter = painterResource(R.drawable.rider_pro_nav_profile),
contentDescription = "chat",
modifier = Modifier.size(16.dp),
@@ -434,7 +465,7 @@ fun Explore() {
fontSize = 12.sp,
color = Color.White,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
)*/
}
// 底部:标题和描述
@@ -443,7 +474,8 @@ fun Explore() {
text = bannerItem.title,
fontSize = 24.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.Bold,
color = Color.White
color = Color.White,
modifier = Modifier.padding(start = 16.dp)
)
Spacer(modifier = Modifier.height(8.dp))
Text(
@@ -451,57 +483,96 @@ fun Explore() {
fontSize = 14.sp,
color = Color.White.copy(alpha = 0.9f),
maxLines = 2,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
modifier = Modifier.padding(start = 16.dp)
)
Spacer(modifier = Modifier.height(16.dp))
Row(
modifier = Modifier.fillMaxWidth(),
modifier = Modifier.fillMaxWidth().background(brush = androidx.compose.ui.graphics.Brush.verticalGradient(
colors = listOf(
Color(0x00000000), // 底部颜色(透明)
Color(0x33000000), // 顶部颜色
)
)),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
// Agent信息
Row(
verticalAlignment = Alignment.CenterVertically
Box(
modifier = Modifier
.wrapContentWidth()
.padding(8.dp),
contentAlignment = Alignment.Center
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp)
) {
Box(
modifier = Modifier
.size(24.dp)
.background(
Color.White.copy(alpha = 0.2f),
RoundedCornerShape(16.dp)
).blur(6.dp),
contentAlignment = Alignment.Center
) {
CustomAsyncImage(
context = context,
imageUrl = bannerItem.imageUrl,
contentDescription = "agent Image",
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxSize()
)
}
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(
text = bannerItem.agentName,
fontSize = 10.sp,
color = Color(0xfff5f5f5).copy(alpha = 0.6f),
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
// 新增的文字行
Text(
text = bannerItem.subtitle,
fontSize = 12.sp,
color = Color.White,
fontWeight = androidx.compose.ui.text.font.FontWeight.W400,
modifier = Modifier.padding(top = 2.dp)
)
}
}
}
Column (
modifier = Modifier
.wrapContentWidth()
.padding(end = 16.dp)
){
// 进入按钮
Box(
modifier = Modifier
.size(32.dp)
.background(Color.White.copy(alpha = 0.2f), RoundedCornerShape(16.dp)),
.width(69.dp)
.height(29.dp)
.background(
color = Color(0x7dffffff),
shape = RoundedCornerShape(8.dp)
)
.clickable {
// 进入房间逻辑
},
contentAlignment = Alignment.Center
) {
Text(
text = bannerItem.agentName.firstOrNull().toString(),
text = "进入",
fontSize = 14.sp,
color = Color.White,
fontWeight = androidx.compose.ui.text.font.FontWeight.Bold
fontWeight = androidx.compose.ui.text.font.FontWeight.W600
)
}
Spacer(modifier = Modifier.width(8.dp))
Text(
text = bannerItem.agentName,
fontSize = 14.sp,
color = Color.White,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
// 进入按钮
androidx.compose.material3.Button(
onClick = {
// 进入房间逻辑
},
colors = androidx.compose.material3.ButtonDefaults.buttonColors(
containerColor = Color.White.copy(alpha = 0.9f),
contentColor = Color(0xFF4CAF50)
),
shape = RoundedCornerShape(20.dp)
) {
Text(
text = "进入",
fontSize = 14.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600
)
}
}
}
@@ -522,7 +593,6 @@ fun Explore() {
// 可以添加更多不同高度的内容项
// 四个圆角布局
item {
Row(
modifier = Modifier
@@ -532,6 +602,10 @@ fun Explore() {
) {
// 第一个
Column(
modifier = Modifier
.clickable {
navController.navigate(NavigationRoute.CreateGroupChat.route)
},
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
@@ -545,7 +619,7 @@ fun Explore() {
contentDescription = "创建群聊",
modifier = Modifier.size(24.dp),
)
)
}
Spacer(modifier = Modifier.size(8.dp))
Text(
@@ -558,6 +632,11 @@ fun Explore() {
// 第二个
Column(
modifier = Modifier
.clickable {
navController.navigate(
NavigationRoute.AddAgent.route)
},
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
@@ -568,10 +647,10 @@ fun Explore() {
) {
Image(
painter = painterResource(R.mipmap.rider_pro_agent),
contentDescription = "创建Agent",
contentDescription = "创建智能体",
modifier = Modifier.size(24.dp),
)
)
}
Spacer(modifier = Modifier.size(8.dp))
Text(
@@ -584,6 +663,11 @@ fun Explore() {
// 第三个
Column(
modifier = Modifier
.clickable {
NewPostViewModel.asNewPost()
navController.navigate("NewPost")
},
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
@@ -620,7 +704,7 @@ fun Explore() {
) {
Image(
painter = painterResource(R.mipmap.rider_pro_fire),
contentDescription = "热门Agents",
contentDescription = "热门智能体",
modifier = Modifier.size(24.dp),
)
@@ -645,6 +729,32 @@ fun BannerSection(bannerItems: List<BannerItem>) {
val pagerState = rememberPagerState(pageCount = { bannerItems.size })
// 预加载banner图片
LaunchedEffect(bannerItems) {
bannerItems.forEach { bannerItem ->
if (bannerItem.backgroundImageUrl.isNotEmpty()) {
// 预加载背景图片
com.aiosman.ravenow.utils.Utils.getImageLoader(context).enqueue(
coil.request.ImageRequest.Builder(context)
.data(bannerItem.backgroundImageUrl)
.memoryCachePolicy(coil.request.CachePolicy.ENABLED)
.diskCachePolicy(coil.request.CachePolicy.ENABLED)
.build()
)
}
if (bannerItem.imageUrl.isNotEmpty()) {
// 预加载头像图片
com.aiosman.ravenow.utils.Utils.getImageLoader(context).enqueue(
coil.request.ImageRequest.Builder(context)
.data(bannerItem.imageUrl)
.memoryCachePolicy(coil.request.CachePolicy.ENABLED)
.diskCachePolicy(coil.request.CachePolicy.ENABLED)
.build()
)
}
}
}
Column {
// Banner内容
Box(
@@ -705,7 +815,7 @@ fun BannerSection(bannerItems: List<BannerItem>) {
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "正在高能对话中",
fontSize = 16.sp,
fontSize = 20.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
color = AppColors.text
)
@@ -736,7 +846,7 @@ fun BannerSection(bannerItems: List<BannerItem>) {
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "推荐Agent",
text = "推荐给你的智能体",
fontSize = 16.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
color = AppColors.text
@@ -761,9 +871,9 @@ fun BannerSection(bannerItems: List<BannerItem>) {
modifier = Modifier.padding(bottom = 12.dp)
) {
Image(
painter = painterResource(R.mipmap.rider_pro_group),
painter = painterResource(R.mipmap.rider_pro_hot_room),
contentDescription = "chat room",
modifier = Modifier.size(16.dp),
modifier = Modifier.size(24.dp),
colorFilter = ColorFilter.tint(Color(0xFFFFA500))
)
Spacer(modifier = Modifier.width(4.dp))
@@ -776,7 +886,7 @@ fun BannerSection(bannerItems: List<BannerItem>) {
}
// 热门聊天室列表
//HotChatRoomSection(roomItems = viewModel.bannerItems)
HotChatRoomGridSection(roomItems = viewModel.bannerItems)
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B