
- 在MePage和MomentListHomePage中新增动态点击事件,支持打开动态详情页。 - 创建MomentDetailPage视图,展示动态详细信息,包括用户信息、动态内容和互动按钮。 - 实现MomentDetailViewModel,管理动态详情页的状态和点赞逻辑。 - 更新MomentListItem组件,添加整体点击回调,提升用户交互体验。 - 优化背景视图组件,确保一致的视觉效果。
187 lines
8.3 KiB
Swift
187 lines
8.3 KiB
Swift
import SwiftUI
|
||
|
||
struct MePage: View {
|
||
let onLogout: () -> Void
|
||
@State private var isShowingSettings: Bool = false
|
||
@StateObject private var viewModel = MePageViewModel()
|
||
|
||
// 图片预览状态
|
||
@State private var previewItem: PreviewItem? = nil
|
||
@State private var previewCurrentIndex: Int = 0
|
||
|
||
// 详情页状态
|
||
@State private var selectedMoment: MomentsInfo? = nil
|
||
|
||
var body: some View {
|
||
ZStack {
|
||
// 背景
|
||
// MomentListBackgroundView()
|
||
|
||
VStack(spacing: 0) {
|
||
// 顶部:大头像 + 姓名 + ID + 右上角设置
|
||
ZStack(alignment: .topTrailing) {
|
||
VStack(spacing: 12) {
|
||
AsyncImage(url: URL(string: viewModel.avatarURL)) { image in
|
||
image.resizable().scaledToFill()
|
||
} placeholder: {
|
||
Image(systemName: "person.circle.fill")
|
||
.resizable()
|
||
.scaledToFill()
|
||
.foregroundColor(.gray)
|
||
}
|
||
.frame(width: 132, height: 132)
|
||
.clipShape(Circle())
|
||
.overlay(Circle().stroke(Color.white, lineWidth: 3))
|
||
.shadow(color: .black.opacity(0.25), radius: 10, x: 0, y: 6)
|
||
|
||
Text(viewModel.nickname.isEmpty ? "未知用户" : viewModel.nickname)
|
||
.font(.system(size: 34, weight: .semibold))
|
||
.foregroundColor(.white)
|
||
.lineLimit(1)
|
||
.minimumScaleFactor(0.6)
|
||
|
||
if viewModel.userId > 0 {
|
||
HStack(spacing: 6) {
|
||
Text("ID:\(viewModel.userId)")
|
||
.font(.system(size: 16))
|
||
.foregroundColor(.white.opacity(0.8))
|
||
Image(systemName: "doc.on.doc")
|
||
.foregroundColor(.white.opacity(0.8))
|
||
}
|
||
}
|
||
}
|
||
.frame(maxWidth: .infinity)
|
||
.padding(.top, 24)
|
||
|
||
Button(action: { isShowingSettings = true }) {
|
||
Image(systemName: "gearshape")
|
||
.font(.system(size: 24, weight: .medium))
|
||
.foregroundColor(.white)
|
||
.frame(width: 40, height: 40)
|
||
.background(Color.black.opacity(0.3))
|
||
.clipShape(Circle())
|
||
}
|
||
.padding(.trailing, 16)
|
||
.padding(.top, 8)
|
||
}
|
||
.padding(.bottom, 8)
|
||
|
||
// 下部:只显示当前用户的动态列表
|
||
if !viewModel.moments.isEmpty {
|
||
ScrollView {
|
||
LazyVStack(spacing: 16) {
|
||
ForEach(Array(viewModel.moments.enumerated()), id: \.offset) { index, moment in
|
||
MomentListItem(
|
||
moment: moment,
|
||
onImageTap: { images, tappedIndex in
|
||
previewCurrentIndex = tappedIndex
|
||
previewItem = PreviewItem(images: images, index: tappedIndex)
|
||
},
|
||
onMomentTap: { tapped in
|
||
selectedMoment = tapped
|
||
debugInfoSync("➡️ MePage: 动态被点击 - ID: \(tapped.dynamicId)")
|
||
}
|
||
)
|
||
.padding(.horizontal, 16)
|
||
.onAppear {
|
||
if index == viewModel.moments.count - 3 {
|
||
viewModel.loadMoreData()
|
||
}
|
||
}
|
||
}
|
||
if viewModel.isLoadingMore {
|
||
HStack {
|
||
ProgressView()
|
||
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||
.scaleEffect(0.8)
|
||
Text("加载更多...")
|
||
.font(.system(size: 14))
|
||
.foregroundColor(.white.opacity(0.8))
|
||
}
|
||
.padding(.vertical, 20)
|
||
}
|
||
if !viewModel.hasMore && !viewModel.moments.isEmpty {
|
||
Text("没有更多数据了")
|
||
.font(.system(size: 14))
|
||
.foregroundColor(.white.opacity(0.6))
|
||
.padding(.vertical, 20)
|
||
}
|
||
}
|
||
.padding(.bottom, 160)
|
||
}
|
||
.refreshable { await viewModel.refreshData() }
|
||
} else if viewModel.isLoading {
|
||
ProgressView()
|
||
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||
.padding(.top, 20)
|
||
} else if let error = viewModel.errorMessage {
|
||
VStack(spacing: 16) {
|
||
Text(error)
|
||
.font(.system(size: 14))
|
||
.foregroundColor(.red)
|
||
.multilineTextAlignment(.center)
|
||
.padding(.horizontal, 20)
|
||
Button(action: { Task { await viewModel.refreshData() } }) {
|
||
Text("重试")
|
||
.font(.system(size: 14, weight: .medium))
|
||
.foregroundColor(.white)
|
||
.padding(.horizontal, 20)
|
||
.padding(.vertical, 8)
|
||
.background(Color.white.opacity(0.2))
|
||
.cornerRadius(8)
|
||
}
|
||
}
|
||
.padding(.top, 20)
|
||
} else {
|
||
VStack(spacing: 12) {
|
||
Image(systemName: "doc.text")
|
||
.font(.system(size: 32))
|
||
.foregroundColor(.white.opacity(0.5))
|
||
Text("暂无动态")
|
||
.font(.system(size: 16, weight: .medium))
|
||
.foregroundColor(.white.opacity(0.7))
|
||
}
|
||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||
}
|
||
Spacer()
|
||
}
|
||
.safeAreaPadding(.top, 8)
|
||
}
|
||
.onAppear { viewModel.onAppear() }
|
||
.onReceive(NotificationCenter.default.publisher(for: .init("CreateFeedPublished"))) { _ in
|
||
Task { await viewModel.refreshData() }
|
||
}
|
||
.sheet(isPresented: $isShowingSettings) {
|
||
SettingPage(
|
||
onBack: { isShowingSettings = false },
|
||
onLogout: {
|
||
isShowingSettings = false
|
||
onLogout()
|
||
}
|
||
)
|
||
.navigationBarHidden(true)
|
||
}
|
||
// 图片预览
|
||
.sheet(item: $previewItem) { item in
|
||
ImagePreviewPager(
|
||
images: item.images as [String],
|
||
currentIndex: $previewCurrentIndex
|
||
) {
|
||
previewItem = nil
|
||
}
|
||
}
|
||
// 详情页
|
||
.sheet(item: $selectedMoment) { moment in
|
||
MomentDetailPage(moment: moment) {
|
||
selectedMoment = nil
|
||
debugInfoSync("📱 MePage: 详情页已关闭")
|
||
}
|
||
.navigationBarHidden(true)
|
||
.presentationDetents([.large])
|
||
.presentationDragIndicator(.visible)
|
||
}
|
||
}
|
||
}
|
||
|
||
|