Refactor: 优化关注列表和代码逻辑

本次提交主要包含以下更改:

- **关注/粉丝列表逻辑修正**:修复了在 `FollowerListViewModel` 和 `FollowingListViewModel` 中 `followerId` 和 `followingId` 属性赋值错误的问题,确保正确加载关注和粉丝列表。
- **分页大小调整**:将 `BaseFollowModel` 中分页加载的 `pageSize` 从 5 调整为 20,以提高用户体验。
- **个人资料页智能体展示**:
    - 在 `AccountProfileV2` 和 `AccountProfileViewModel` 中增加了对用户智能体列表的加载和展示逻辑。
    - 修复了 `MyProfileViewModel` 中加载当前用户智能体时 `authorId` 传递错误的问题。
    - 优化了 `UserAgentsRow` 和 `UserAgentsViewModel` 的逻辑,确保正确加载和显示用户智能体,并在用户切换时清理旧数据。
- **代码清理**:移除了部分冗余的 `println` 调试信息。
- **Agent创建流程优化**:在 `AddAgentViewModel` 和 `AgentImageCropScreen` 中,确保在已有裁剪图片时直接使用,避免重复裁剪。
This commit is contained in:
2025-08-31 23:50:52 +08:00
parent 281169cfcb
commit 2907e7f9a6
15 changed files with 35 additions and 47 deletions

View File

@@ -138,10 +138,7 @@ fun AddAgentScreen() {
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
placeholderRes = R.mipmap.rider_pro_agent_avatar placeholderRes = R.mipmap.rider_pro_agent_avatar
) )
// 调试信息
LaunchedEffect(model.croppedBitmap) {
println("AddAgent: croppedBitmap changed: ${model.croppedBitmap != null}")
}
Box( Box(
modifier = Modifier modifier = Modifier
.size(32.dp) .size(32.dp)
@@ -149,7 +146,6 @@ fun AddAgentScreen() {
.background(appColors.main) .background(appColors.main)
.align(Alignment.BottomEnd) .align(Alignment.BottomEnd)
.noRippleClickable { .noRippleClickable {
println("AddAgent: Navigating to AgentImageCrop")
navController.navigate(NavigationRoute.AgentImageCrop.route) navController.navigate(NavigationRoute.AgentImageCrop.route)
}, },
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
@@ -226,7 +222,6 @@ fun AddAgentScreen() {
if (validationError != null) { if (validationError != null) {
// 显示验证错误 // 显示验证错误
errorMessage = validationError errorMessage = validationError
println("AddAgent: Validation error: $validationError")
return@ActionButton return@ActionButton
} }
@@ -236,16 +231,13 @@ fun AddAgentScreen() {
// 调用创建智能体API // 调用创建智能体API
model.viewModelScope.launch { model.viewModelScope.launch {
try { try {
println("AddAgent: Starting to create agent...")
val result = model.createAgent(context) val result = model.createAgent(context)
if (result != null) { if (result != null) {
println("AddAgent: Agent created successfully, closing page")
// 创建成功,清空数据并关闭页面 // 创建成功,清空数据并关闭页面
model.clearData() model.clearData()
navController.popBackStack() navController.popBackStack()
} }
} catch (e: Exception) { } catch (e: Exception) {
println("AddAgent: Error creating agent: ${e.message}")
// 显示错误信息 // 显示错误信息
errorMessage = "创建智能体失败: ${e.message}" errorMessage = "创建智能体失败: ${e.message}"
e.printStackTrace() e.printStackTrace()

View File

@@ -26,11 +26,9 @@ object AddAgentViewModel : ViewModel() {
var isFromAddAgent by mutableStateOf(false) var isFromAddAgent by mutableStateOf(false)
suspend fun updateAgentAvatar(context: Context) { suspend fun updateAgentAvatar(context: Context) {
println("AddAgentViewModel: updateAgentAvatar called, croppedBitmap: ${croppedBitmap != null}")
croppedBitmap?.let { croppedBitmap?.let {
val file = File(context.cacheDir, "agent_avatar.jpg") val file = File(context.cacheDir, "agent_avatar.jpg")
it.compress(Bitmap.CompressFormat.JPEG, 100, file.outputStream()) it.compress(Bitmap.CompressFormat.JPEG, 100, file.outputStream())
println("AddAgentViewModel: Avatar saved to ${file.absolutePath}")
// 这里可以上传图片到服务器,暂时先保存到本地 // 这里可以上传图片到服务器,暂时先保存到本地
// UploadImage(file, "agent_avatar.jpg", "", "jpg") // UploadImage(file, "agent_avatar.jpg", "", "jpg")
} }
@@ -39,7 +37,6 @@ object AddAgentViewModel : ViewModel() {
suspend fun createAgent(context: Context): AgentEntity? { suspend fun createAgent(context: Context): AgentEntity? {
try { try {
isUpdating = true isUpdating = true
println("AddAgentViewModel: Creating agent with name: $name, desc: $desc")
// 准备头像文件 // 准备头像文件
val avatarFile = if (croppedBitmap != null) { val avatarFile = if (croppedBitmap != null) {
@@ -57,12 +54,8 @@ object AddAgentViewModel : ViewModel() {
avatar = avatarFile avatar = avatarFile
) )
println("AddAgentViewModel: Agent created successfully with ID: ${result.id}")
return result return result
} catch (e: Exception) { } catch (e: Exception)
println("AddAgentViewModel: Error creating agent: ${e.message}")
throw e throw e
} finally { } finally {
isUpdating = false isUpdating = false

View File

@@ -128,7 +128,6 @@ fun AgentImageCropScreen() {
modifier = Modifier.clickable { modifier = Modifier.clickable {
if (croppedBitmap != null) { if (croppedBitmap != null) {
// 如果已经有裁剪结果,直接返回 // 如果已经有裁剪结果,直接返回
println("AgentImageCrop: Using existing cropped bitmap")
AddAgentViewModel.croppedBitmap = croppedBitmap AddAgentViewModel.croppedBitmap = croppedBitmap
AddAgentViewModel.viewModelScope.launch { AddAgentViewModel.viewModelScope.launch {
AddAgentViewModel.updateAgentAvatar(context) AddAgentViewModel.updateAgentAvatar(context)
@@ -139,7 +138,6 @@ fun AgentImageCropScreen() {
imageCrop?.let { imageCrop?.let {
val bitmap = it.onCrop() val bitmap = it.onCrop()
croppedBitmap = bitmap croppedBitmap = bitmap
println("AgentImageCrop: Cropped bitmap created: ${bitmap != null}")
} }
} }
} }

View File

@@ -113,10 +113,8 @@ fun ImageCropScreen() {
modifier = Modifier.clickable { modifier = Modifier.clickable {
imageCrop?.let { imageCrop?.let {
val bitmap = it.onCrop() val bitmap = it.onCrop()
println("ImageCrop: Cropped bitmap created: ${bitmap != null}")
// 专门处理个人资料头像 // 专门处理个人资料头像
println("ImageCrop: Setting bitmap to AccountEditViewModel for user profile")
AccountEditViewModel.croppedBitmap = bitmap AccountEditViewModel.croppedBitmap = bitmap
AccountEditViewModel.viewModelScope.launch { AccountEditViewModel.viewModelScope.launch {
AccountEditViewModel.updateUserProfile(context) AccountEditViewModel.updateUserProfile(context)

View File

@@ -36,12 +36,12 @@ open class BaseFollowModel:ViewModel() {
isLoading = true isLoading = true
viewModelScope.launch { viewModelScope.launch {
Pager( Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false), config = PagingConfig(pageSize = 20, enablePlaceholders = false),
pagingSourceFactory = { pagingSourceFactory = {
AccountPagingSource( AccountPagingSource(
userService, userService,
followerId = followingId, followerId = followerId,
followingId = followerId followingId = followingId
) )
} }
).flow.cachedIn(viewModelScope).collectLatest { ).flow.cachedIn(viewModelScope).collectLatest {

View File

@@ -3,5 +3,5 @@ package com.aiosman.ravenow.ui.follower
class FollowerListViewModel( class FollowerListViewModel(
val userId: Int val userId: Int
) : BaseFollowModel() { ) : BaseFollowModel() {
override var followingId: Int? = userId override var followerId: Int? = userId
} }

View File

@@ -21,5 +21,5 @@ import kotlinx.coroutines.launch
class FollowingListViewModel( class FollowingListViewModel(
val userId: Int val userId: Int
) : BaseFollowModel() { ) : BaseFollowModel() {
override var followerId: Int? = userId override var followingId: Int? = userId
} }

View File

@@ -157,9 +157,7 @@ object AgentChatListViewModel : ViewModel() {
} }
agentChatList = result?.conversationList?.map { msg: V2TIMConversation -> agentChatList = result?.conversationList?.map { msg: V2TIMConversation ->
val conversation = AgentConversation.convertToAgentConversation(msg, context) AgentConversation.convertToAgentConversation(msg, context)
println("AgentChatList: Conversation ${conversation.nickname} has ${conversation.unreadCount} unread messages")
conversation
} ?: emptyList() } ?: emptyList()
} }

View File

@@ -157,9 +157,7 @@ object FriendChatListViewModel : ViewModel() {
} ?: emptyList() } ?: emptyList()
friendChatList = filteredConversations.map { msg: V2TIMConversation -> friendChatList = filteredConversations.map { msg: V2TIMConversation ->
val conversation = FriendConversation.convertToFriendConversation(msg, context) FriendConversation.convertToFriendConversation(msg, context)
println("FriendChatList: Conversation ${conversation.nickname} has ${conversation.unreadCount} unread messages")
conversation
} }
} }

View File

@@ -178,9 +178,7 @@ object GroupChatListViewModel : ViewModel() {
} ?: emptyList() } ?: emptyList()
groupChatList = filteredConversations.map { msg: V2TIMConversation -> groupChatList = filteredConversations.map { msg: V2TIMConversation ->
val conversation = GroupConversation.convertToGroupConversation(msg, context) GroupConversation.convertToGroupConversation(msg, context)
println("GroupChatList: Conversation ${conversation.groupName} has ${conversation.unreadCount} unread messages")
conversation
} }
} }

View File

@@ -74,7 +74,8 @@ object MyProfileViewModel : ViewModel() {
profile?.let { profile?.let {
try { try {
momentLoader.loadData(extra = MomentLoaderExtraArgs(authorId = it.id)) momentLoader.loadData(extra = MomentLoaderExtraArgs(authorId = it.id))
agentLoader.loadData(extra = AgentLoaderExtraArgs(authorId = it.id)) // MyProfileViewModel 总是加载当前用户的数据所以传递null以调用getMyAgent()
agentLoader.loadData(extra = AgentLoaderExtraArgs(authorId = null))
} catch (e: Exception) { } catch (e: Exception) {
Log.e("MyProfileViewModel", "loadProfile: ", e) Log.e("MyProfileViewModel", "loadProfile: ", e)
} }

View File

@@ -48,17 +48,14 @@ fun UserAgentsRow(
onAgentClick: (AgentEntity) -> Unit = {} onAgentClick: (AgentEntity) -> Unit = {}
) { ) {
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val viewModel: UserAgentsViewModel = viewModel() val viewModel: UserAgentsViewModel = viewModel(key = "UserAgentsViewModel_${userId ?: "self"}")
val isSelf = userId == null val isSelf = userId == null
// 加载用户的智能体数据 // 加载用户的智能体数据
LaunchedEffect(userId) { LaunchedEffect(userId) {
// 无论userId是否为null都加载数据 // 无论userId是否为null都加载数据
// null表示加载当前用户自己的智能体 // null表示加载当前用户自己的智能体
println("UserAgentsRow: LaunchedEffect 触发, userId = $userId, isSelf = $isSelf")
println("UserAgentsRow: 准备调用 viewModel.loadUserAgents")
viewModel.loadUserAgents(userId) viewModel.loadUserAgents(userId)
println("UserAgentsRow: 已调用 viewModel.loadUserAgents")
} }
// 总是显示智能体区域,即使没有数据也显示标题和状态 // 总是显示智能体区域,即使没有数据也显示标题和状态
@@ -78,7 +75,6 @@ fun UserAgentsRow(
when { when {
viewModel.isLoading -> { viewModel.isLoading -> {
// 显示加载状态 // 显示加载状态
println("UserAgentsRow: 显示加载状态")
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -94,7 +90,6 @@ fun UserAgentsRow(
} }
viewModel.error != null -> { viewModel.error != null -> {
// 显示错误状态 // 显示错误状态
println("UserAgentsRow: 显示错误状态, error = ${viewModel.error}")
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -110,7 +105,6 @@ fun UserAgentsRow(
} }
viewModel.agents.isEmpty() -> { viewModel.agents.isEmpty() -> {
// 显示空状态 // 显示空状态
println("UserAgentsRow: 显示空状态, agents.size = ${viewModel.agents.size}")
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -126,7 +120,6 @@ fun UserAgentsRow(
} }
else -> { else -> {
// 显示智能体列表 // 显示智能体列表
println("UserAgentsRow: 显示智能体列表, agents.size = ${viewModel.agents.size}")
LazyRow( LazyRow(
horizontalArrangement = Arrangement.spacedBy(12.dp), horizontalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()

View File

@@ -28,16 +28,15 @@ class UserAgentsViewModel : ViewModel() {
fun loadUserAgents(userId: Int?) { fun loadUserAgents(userId: Int?) {
viewModelScope.launch { viewModelScope.launch {
// 先清理之前的数据
clearAgents()
isLoading = true isLoading = true
error = null error = null
try { try {
println("UserAgentsViewModel: 开始加载智能体数据, userId = $userId")
agentLoader.loadData(AgentLoaderExtraArgs(authorId = userId)) agentLoader.loadData(AgentLoaderExtraArgs(authorId = userId))
println("UserAgentsViewModel: 加载完成, agents.size = ${agents.size}")
} catch (e: Exception) { } catch (e: Exception) {
error = e.message ?: "加载失败" error = e.message ?: "加载失败"
println("UserAgentsViewModel: 加载失败, error = $error")
e.printStackTrace() e.printStackTrace()
} finally { } finally {
isLoading = false isLoading = false

View File

@@ -27,6 +27,7 @@ fun AccountProfileV2(id: String){
} }
ProfileV3( ProfileV3(
moments = model.moments, moments = model.moments,
agents = model.agents,
profile = model.profile, profile = model.profile,
isSelf = isSelf, isSelf = isSelf,
postCount = model.momentLoader.total, postCount = model.momentLoader.total,
@@ -53,6 +54,9 @@ fun AccountProfileV2(id: String){
model.followUser(id) model.followUser(id)
} }
} }
},
onAgentClick = { agent ->
// TODO: 处理Agent点击事件导航到聊天页面
} }
) )
} }

View File

@@ -10,6 +10,9 @@ import com.aiosman.ravenow.data.AccountService
import com.aiosman.ravenow.data.AccountServiceImpl import com.aiosman.ravenow.data.AccountServiceImpl
import com.aiosman.ravenow.data.UserServiceImpl import com.aiosman.ravenow.data.UserServiceImpl
import com.aiosman.ravenow.entity.AccountProfileEntity import com.aiosman.ravenow.entity.AccountProfileEntity
import com.aiosman.ravenow.entity.AgentEntity
import com.aiosman.ravenow.entity.AgentLoader
import com.aiosman.ravenow.entity.AgentLoaderExtraArgs
import com.aiosman.ravenow.entity.MomentEntity import com.aiosman.ravenow.entity.MomentEntity
import com.aiosman.ravenow.entity.MomentLoader import com.aiosman.ravenow.entity.MomentLoader
import com.aiosman.ravenow.entity.MomentLoaderExtraArgs import com.aiosman.ravenow.entity.MomentLoaderExtraArgs
@@ -32,6 +35,13 @@ class AccountProfileViewModel : ViewModel() {
} }
} }
var moments by mutableStateOf<List<MomentEntity>>(listOf()) var moments by mutableStateOf<List<MomentEntity>>(listOf())
var agentLoader = AgentLoader().apply {
onListChanged = {
agents = it
}
}
var agents by mutableStateOf<List<AgentEntity>>(listOf())
init { init {
EventBus.getDefault().register(this) EventBus.getDefault().register(this)
} }
@@ -54,6 +64,12 @@ class AccountProfileViewModel : ViewModel() {
profile?.let { profile?.let {
try { try {
momentLoader.loadData(MomentLoaderExtraArgs(authorId = it.id)) momentLoader.loadData(MomentLoaderExtraArgs(authorId = it.id))
// 根据是否是当前用户来决定传递authorId
// 如果是当前用户传递null以调用getMyAgent()
// 如果是其他用户传递用户ID以调用getAgent(authorId)
val isSelf = it.id.toString() == com.aiosman.ravenow.AppState.UserId.toString()
val authorId = if (isSelf) null else it.id
agentLoader.loadData(AgentLoaderExtraArgs(authorId = authorId))
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }