Files
e-party-iOS/yana/MVVM/MePage.swift
edwinQQQ 327d4fd218 feat: 实现动态详情页及相关功能
- 在MePage和MomentListHomePage中新增动态点击事件,支持打开动态详情页。
- 创建MomentDetailPage视图,展示动态详细信息,包括用户信息、动态内容和互动按钮。
- 实现MomentDetailViewModel,管理动态详情页的状态和点赞逻辑。
- 更新MomentListItem组件,添加整体点击回调,提升用户交互体验。
- 优化背景视图组件,确保一致的视觉效果。
2025-09-26 16:49:18 +08:00

187 lines
8.3 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}
}
}