diff --git a/yana/APIs/DynamicsModels.swift b/yana/APIs/DynamicsModels.swift index b591de7..cdc7e70 100644 --- a/yana/APIs/DynamicsModels.swift +++ b/yana/APIs/DynamicsModels.swift @@ -17,7 +17,7 @@ struct MomentsListData: Codable, Equatable, Sendable { } /// 动态信息结构 -public struct MomentsInfo: Codable, Equatable, Sendable { +public struct MomentsInfo: Codable, Equatable, Sendable, Identifiable { let dynamicId: Int let uid: Int let nick: String @@ -51,6 +51,7 @@ public struct MomentsInfo: Codable, Equatable, Sendable { let isCustomWord: Bool? let labelList: [String]? // 计算属性 + public var id: Int { dynamicId } // Identifiable 协议要求 var isSquareTop: Bool { (squareTop ?? 0) != 0 } var isTopicTop: Bool { (topicTop ?? 0) != 0 } var formattedPublishTime: Date { @@ -270,7 +271,8 @@ struct MyMomentInfo: Codable, Equatable, Sendable { likeCount: likeCount ?? 0, isLike: isLike ?? false, commentCount: commentCount ?? 0, - publishTime: Int(publishTime / 1000), + // 注意:UI 的 formatDisplayTime 期望毫秒,这里不做 /1000 转换 + publishTime: Int(publishTime), worldId: worldId ?? 0, status: status ?? 1, playCount: playCount, diff --git a/yana/MVVM/CommonComponents.swift b/yana/MVVM/CommonComponents.swift index 765c4fd..eaacdca 100644 --- a/yana/MVVM/CommonComponents.swift +++ b/yana/MVVM/CommonComponents.swift @@ -150,10 +150,9 @@ struct LiquidGlassBackground: View { // MARK: - 背景视图组件 struct LoginBackgroundView: View { var body: some View { - Color.blue -// Image("bg") -// .resizable() -// .aspectRatio(contentMode: .fill) + Image("bg") + .resizable() + .aspectRatio(contentMode: .fill) // .ignoresSafeArea(.all) } } diff --git a/yana/MVVM/CreateFeedPage.swift b/yana/MVVM/CreateFeedPage.swift index ea95702..87ddfa9 100644 --- a/yana/MVVM/CreateFeedPage.swift +++ b/yana/MVVM/CreateFeedPage.swift @@ -98,7 +98,7 @@ struct CreateFeedPage: View { } .frame(height: 200) .padding(.horizontal, 20) - .onChange(of: viewModel.content) { newValue in + .onChange(of: viewModel.content) { _, newValue in // 限制最大字数 if newValue.count > maxCharacters { viewModel.content = String(newValue.prefix(maxCharacters)) diff --git a/yana/MVVM/MePage.swift b/yana/MVVM/MePage.swift index 7201148..b1c3ac1 100644 --- a/yana/MVVM/MePage.swift +++ b/yana/MVVM/MePage.swift @@ -9,10 +9,13 @@ struct MePage: View { @State private var previewItem: PreviewItem? = nil @State private var previewCurrentIndex: Int = 0 + // 详情页状态 + @State private var selectedMoment: MomentsInfo? = nil + var body: some View { ZStack { // 背景 - MomentListBackgroundView() +// MomentListBackgroundView() VStack(spacing: 0) { // 顶部:大头像 + 姓名 + ID + 右上角设置 @@ -73,6 +76,10 @@ struct MePage: View { 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) @@ -163,6 +170,16 @@ struct MePage: View { previewItem = nil } } + // 详情页 + .sheet(item: $selectedMoment) { moment in + MomentDetailPage(moment: moment) { + selectedMoment = nil + debugInfoSync("📱 MePage: 详情页已关闭") + } + .navigationBarHidden(true) + .presentationDetents([.large]) + .presentationDragIndicator(.visible) + } } } diff --git a/yana/MVVM/MomentDetailPage.swift b/yana/MVVM/MomentDetailPage.swift new file mode 100644 index 0000000..8e4dce6 --- /dev/null +++ b/yana/MVVM/MomentDetailPage.swift @@ -0,0 +1,245 @@ +import SwiftUI + +// MARK: - MomentDetailPage + +struct MomentDetailPage: View { + @StateObject private var viewModel: MomentDetailViewModel + let onClose: () -> Void + + init(moment: MomentsInfo, onClose: @escaping () -> Void) { + _viewModel = StateObject(wrappedValue: MomentDetailViewModel(moment: moment)) + self.onClose = onClose + } + + var body: some View { + ZStack { + // 背景 + LoginBackgroundView() + .ignoresSafeArea() + + VStack(spacing: 0) { + // 顶部导航栏 + HStack { + Button { + onClose() + } label: { + Image(systemName: "chevron.left") + .font(.system(size: 20, weight: .medium)) + .foregroundColor(.white) + .frame(width: 44, height: 44) + .background(Color.black.opacity(0.3)) + .clipShape(Circle()) + } + + Spacer() + + Text(LocalizedString("detail.title", comment: "Detail page title")) + .font(.system(size: 18, weight: .semibold)) + .foregroundColor(.white) + .shadow(color: .black.opacity(0.5), radius: 2, x: 0, y: 1) + + Spacer() + + // 占位,保持标题居中 + Color.clear + .frame(width: 44, height: 44) + } + .padding(.horizontal, 16) + .safeAreaPadding(.top, 60) + .padding(.bottom, 12) + .background( + LinearGradient( + gradient: Gradient(colors: [ + Color.black.opacity(0.4), + Color.black.opacity(0.2), + Color.clear + ]), + startPoint: .top, + endPoint: .bottom + ) + ) + + // 内容区域 + ScrollView { + VStack(alignment: .leading, spacing: 12) { + // 用户信息 + HStack(alignment: .top) { + // 头像 + CachedAsyncImage(url: viewModel.moment.avatar) { image in + image + .resizable() + .aspectRatio(contentMode: .fill) + } placeholder: { + Circle() + .fill(Color.gray.opacity(0.3)) + .overlay( + Text(String(viewModel.moment.nick.prefix(1))) + .font(.system(size: 16, weight: .medium)) + .foregroundColor(.white) + ) + } + .frame(width: 44, height: 44) + .clipShape(Circle()) + + VStack(alignment: .leading, spacing: 2) { + Text(viewModel.moment.nick) + .font(.system(size: 16, weight: .medium)) + .foregroundColor(.white) + UserIDDisplay(uid: viewModel.moment.uid, fontSize: 12, textColor: .white.opacity(0.6)) + } + + Spacer() + + // 时间 + Text(formatDisplayTime(viewModel.moment.publishTime)) + .font(.system(size: 12, weight: .bold)) + .foregroundColor(.white.opacity(0.8)) + .padding(.horizontal, 6) + .padding(.vertical, 2) + .background(Color.white.opacity(0.15)) + .cornerRadius(4) + } + + // 动态内容 + if !viewModel.moment.content.isEmpty { + Text(viewModel.moment.content) + .font(.system(size: 16)) + .foregroundColor(.white.opacity(0.95)) + .multilineTextAlignment(.leading) + } + + // 图片网格 + if let images = viewModel.moment.dynamicResList, !images.isEmpty { + MomentImageGrid( + images: images, + onImageTap: { images, index in + viewModel.onImageTap(index) + } + ) + } + + // 互动按钮 + HStack(spacing: 20) { + Button { + viewModel.like() + } label: { + HStack(spacing: 6) { + if viewModel.isLikeLoading { + ProgressView() + .progressViewStyle(CircularProgressViewStyle(tint: viewModel.localIsLike ? .red : .white.opacity(0.8))) + .scaleEffect(0.8) + } else { + Image(systemName: viewModel.localIsLike ? "heart.fill" : "heart") + .font(.system(size: 18)) + } + Text("\(viewModel.localLikeCount)") + .font(.system(size: 16)) + } + } + .foregroundColor(viewModel.localIsLike ? .red : .white.opacity(0.9)) + .disabled(viewModel.isLikeLoading || viewModel.moment.status == 0) + .opacity(viewModel.moment.status == 0 ? 0.5 : 1.0) + + Spacer() + + // 审核中状态角标 - 与外部列表保持一致:右侧对齐并与点赞按钮居中对齐 + if viewModel.moment.status == 0 { + Text("reviewing") + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(.white) + .padding(.horizontal, 10) + .padding(.vertical, 6) + .background(Color.orange.opacity(0.85)) + .clipShape(Capsule()) + } + } + .padding(.top, 8) + } + .padding(.horizontal, 16) + .padding(.bottom, 16) + .safeAreaPadding(.top, 8) + } + } + + } + .navigationBarHidden(true) + .fullScreenCover(isPresented: $viewModel.showImagePreview) { + ImagePreviewPager( + images: viewModel.images, + currentIndex: $viewModel.currentIndex + ) { + viewModel.showImagePreview = false + } + } + .onAppear { + debugInfoSync("📱 MomentDetailPage: 显示详情页") + debugInfoSync(" 动态ID: \(viewModel.moment.dynamicId)") + debugInfoSync(" 用户: \(viewModel.moment.nick)") + debugInfoSync(" 审核状态: \(viewModel.moment.status)") + } + } + + // MARK: - 时间显示逻辑 + private func formatDisplayTime(_ timestamp: Int) -> String { + let date = Date(timeIntervalSince1970: TimeInterval(timestamp) / 1000.0) + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "zh_CN") + let now = Date() + let interval = now.timeIntervalSince(date) + let calendar = Calendar.current + if calendar.isDateInToday(date) { + if interval < 60 { + return "刚刚" + } else if interval < 3600 { + return "\(Int(interval / 60))分钟前" + } else { + return "\(Int(interval / 3600))小时前" + } + } else { + formatter.dateFormat = "MM/dd" + return formatter.string(from: date) + } + } +} + +//#Preview { +// let testMoment = MomentsInfo( +// dynamicId: 1, +// uid: 123456, +// nick: "测试用户", +// avatar: "", +// type: 0, +// content: "这是一条测试动态内容,用来测试 MomentDetailPage 的显示效果。", +// likeCount: 42, +// isLike: false, +// commentCount: 5, +// publishTime: Int(Date().timeIntervalSince1970 * 1000), +// worldId: 1, +// status: 0, // 审核中状态 +// playCount: nil, +// dynamicResList: [ +// MomentsPicture(id: 1, resUrl: "https://picsum.photos/300/300", format: "jpg", width: 300, height: 300, resDuration: nil), +// MomentsPicture(id: 2, resUrl: "https://picsum.photos/301/301", format: "jpg", width: 301, height: 301, resDuration: nil) +// ], +// gender: nil, +// squareTop: nil, +// topicTop: nil, +// newUser: nil, +// defUser: nil, +// scene: nil, +// userVipInfoVO: nil, +// headwearPic: nil, +// headwearEffect: nil, +// headwearType: nil, +// headwearName: nil, +// headwearId: nil, +// experLevelPic: nil, +// charmLevelPic: nil, +// isCustomWord: nil, +// labelList: nil +// ) +// +// MomentDetailPage(moment: testMoment) { +// print("关闭详情页") +// } +//} diff --git a/yana/MVVM/View/MomentListHomePage.swift b/yana/MVVM/View/MomentListHomePage.swift index bf0c6ca..feb6111 100644 --- a/yana/MVVM/View/MomentListHomePage.swift +++ b/yana/MVVM/View/MomentListHomePage.swift @@ -21,13 +21,16 @@ struct MomentListHomePage: View { @State private var previewItem: PreviewItem? = nil @State private var previewCurrentIndex: Int = 0 + // MARK: - 详情页状态 + @State private var selectedMoment: MomentsInfo? = nil + // MARK: - 创建动态发布页弹窗 // 迁移到上层(MainPage)统一管理,避免与 TabView 全屏弹窗冲突 var body: some View { ZStack { // 背景 - MomentListBackgroundView() +// MomentListBackgroundView() VStack(alignment: .center, spacing: 0) { // 顶部标题居中 + 右上角添加按钮(垂直居中对齐) @@ -83,6 +86,13 @@ struct MomentListHomePage: View { debugInfoSync(" 动态索引: \(index)") debugInfoSync(" 图片索引: \(tappedIndex)") debugInfoSync(" 图片数量: \(images.count)") + }, + onMomentTap: { tappedMoment in + // 处理整体点击事件 - 打开详情页 + selectedMoment = tappedMoment + debugInfoSync("➡️ MomentListHomePage: 动态被点击") + debugInfoSync(" 动态ID: \(tappedMoment.dynamicId)") + debugInfoSync(" 用户: \(tappedMoment.nick)") } ) .padding(.leading, 16) @@ -178,6 +188,16 @@ struct MomentListHomePage: View { debugInfoSync("📸 MomentListHomePage: 图片预览已关闭") } } + // MARK: - 详情页弹窗 + .sheet(item: $selectedMoment) { moment in + MomentDetailPage(moment: moment) { + selectedMoment = nil + debugInfoSync("📱 MomentListHomePage: 详情页已关闭") + } + .navigationBarHidden(true) + .presentationDetents([.large]) + .presentationDragIndicator(.visible) + } // 发布页由上层统一控制 } } diff --git a/yana/MVVM/View/MomentListItem.swift b/yana/MVVM/View/MomentListItem.swift index c9e6d05..21528ab 100644 --- a/yana/MVVM/View/MomentListItem.swift +++ b/yana/MVVM/View/MomentListItem.swift @@ -4,6 +4,7 @@ import SwiftUI struct MomentListItem: View { let moment: MomentsInfo let onImageTap: (([String], Int)) -> Void // 新增:图片点击回调 + let onMomentTap: (MomentsInfo) -> Void // 新增:整体点击回调 // 新增:点赞相关状态 @State private var isLikeLoading = false @@ -12,111 +13,134 @@ struct MomentListItem: View { init( moment: MomentsInfo, - onImageTap: @escaping (([String], Int)) -> Void = { (arg) in let (_, _) = arg; } + onImageTap: @escaping (([String], Int)) -> Void = { (arg) in let (_, _) = arg; }, + onMomentTap: @escaping (MomentsInfo) -> Void = { _ in } ) { self.moment = moment self.onImageTap = onImageTap + self.onMomentTap = onMomentTap // 初始化本地状态 self._localIsLike = State(initialValue: moment.isLike) self._localLikeCount = State(initialValue: moment.likeCount) } var body: some View { - ZStack { - RoundedRectangle(cornerRadius: 12) - .fill(Color.clear) - .overlay( - RoundedRectangle(cornerRadius: 12) - .stroke(Color.white.opacity(0.1), lineWidth: 1) - ) - .shadow(color: Color(red: 0.43, green: 0.43, blue: 0.43, opacity: 0.34), radius: 10.7, x: 0, y: 1.9) - - // 内容层 - VStack(alignment: .leading, spacing: 10) { - // 用户信息 - HStack(alignment: .top) { - // 头像 - CachedAsyncImage(url: moment.avatar) { image in - image - .resizable() - .aspectRatio(contentMode: .fill) - } placeholder: { - Circle() - .fill(Color.gray.opacity(0.3)) - .overlay( - Text(String(moment.nick.prefix(1))) - .font(.system(size: 16, weight: .medium)) - .foregroundColor(.white) - ) - } - .frame(width: 40, height: 40) - .clipShape(Circle()) - - VStack(alignment: .leading, spacing: 2) { - Text(moment.nick) - .font(.system(size: 16, weight: .medium)) - .foregroundColor(.white) - UserIDDisplay(uid: moment.uid, fontSize: 12, textColor: .white.opacity(0.6)) - } - Spacer() - // 时间 - Text(formatDisplayTime(moment.publishTime)) - .font(.system(size: 12, weight: .bold)) - .foregroundColor(.white.opacity(0.8)) - .padding(.horizontal, 6) - .padding(.vertical, 2) - .background(Color.white.opacity(0.15)) - .cornerRadius(4) - } - - // 动态内容 - if !moment.content.isEmpty { - Text(moment.content) - .font(.system(size: 14)) - .foregroundColor(.white.opacity(0.9)) - .multilineTextAlignment(.leading) - .padding(.leading, 40 + 8) // 与用户名左边对齐 - } - - // 图片网格 - if let images = moment.dynamicResList, !images.isEmpty { - MomentImageGrid( - images: images, - onImageTap: onImageTap + let isReviewing = moment.status == 0 + + ZStack(alignment: .bottomTrailing) { + ZStack { + RoundedRectangle(cornerRadius: 12) + .fill(Color.clear) + .overlay( + RoundedRectangle(cornerRadius: 12) + .stroke(Color.white.opacity(0.1), lineWidth: 1) ) - .padding(.leading, 40 + 8) - .padding(.bottom, images.count == 2 ? 30 : 0) // 两张图片时增加底部间距 - } - - // 互动按钮 - HStack(spacing: 20) { - // Like 按钮与用户名左侧对齐 - Button(action: { - if !isLikeLoading { - handleLikeTap() + .shadow(color: Color(red: 0.43, green: 0.43, blue: 0.43, opacity: 0.34), radius: 10.7, x: 0, y: 1.9) + + // 内容层 + VStack(alignment: .leading, spacing: 10) { + // 用户信息 + HStack(alignment: .top) { + // 头像 + CachedAsyncImage(url: moment.avatar) { image in + image + .resizable() + .aspectRatio(contentMode: .fill) + } placeholder: { + Circle() + .fill(Color.gray.opacity(0.3)) + .overlay( + Text(String(moment.nick.prefix(1))) + .font(.system(size: 16, weight: .medium)) + .foregroundColor(.white) + ) } - }) { - HStack(spacing: 4) { - if isLikeLoading { - ProgressView() - .progressViewStyle(CircularProgressViewStyle(tint: localIsLike ? .red : .white.opacity(0.8))) - .scaleEffect(0.8) - } else { - Image(systemName: localIsLike ? "heart.fill" : "heart") - .font(.system(size: 16)) - } - Text("\(localLikeCount)") - .font(.system(size: 14)) + .frame(width: 40, height: 40) + .clipShape(Circle()) + + VStack(alignment: .leading, spacing: 2) { + Text(moment.nick) + .font(.system(size: 16, weight: .medium)) + .foregroundColor(.white) + UserIDDisplay(uid: moment.uid, fontSize: 12, textColor: .white.opacity(0.6)) } - .foregroundColor(localIsLike ? .red : .white.opacity(0.8)) + Spacer() + // 时间 + Text(formatDisplayTime(moment.publishTime)) + .font(.system(size: 12, weight: .bold)) + .foregroundColor(.white.opacity(0.8)) + .padding(.horizontal, 6) + .padding(.vertical, 2) + .background(Color.white.opacity(0.15)) + .cornerRadius(4) } - .disabled(isLikeLoading) - .padding(.leading, 40 + 8) // 与用户名左侧对齐(头像宽度 + 间距) - Spacer() + + // 动态内容 + if !moment.content.isEmpty { + Text(moment.content) + .font(.system(size: 14)) + .foregroundColor(.white.opacity(0.9)) + .multilineTextAlignment(.leading) + .padding(.leading, 40 + 8) // 与用户名左边对齐 + } + + // 图片网格 + if let images = moment.dynamicResList, !images.isEmpty { + MomentImageGrid( + images: images, + onImageTap: onImageTap + ) + .padding(.leading, 40 + 8) + .padding(.bottom, images.count == 2 ? 30 : 0) // 两张图片时增加底部间距 + } + + // 互动按钮 + HStack(spacing: 20) { + // Like 按钮与用户名左侧对齐 + Button(action: { + if !isLikeLoading && !isReviewing { + handleLikeTap() + } + }) { + HStack(spacing: 4) { + if isLikeLoading { + ProgressView() + .progressViewStyle(CircularProgressViewStyle(tint: localIsLike ? .red : .white.opacity(0.8))) + .scaleEffect(0.8) + } else { + Image(systemName: localIsLike ? "heart.fill" : "heart") + .font(.system(size: 16)) + } + Text("\(localLikeCount)") + .font(.system(size: 14)) + } + .foregroundColor(localIsLike ? .red : .white.opacity(0.8)) + } + .disabled(isLikeLoading || isReviewing) + .opacity(isReviewing ? 0.5 : 1.0) + .padding(.leading, 40 + 8) // 与用户名左侧对齐(头像宽度 + 间距) + + Spacer() + + // 审核中状态角标 - 右侧对齐日期,垂直居中对齐点赞按钮 + if isReviewing { + Text("reviewing") + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(.white) + .padding(.horizontal, 10) + .padding(.vertical, 6) + .background(Color.orange.opacity(0.85)) + .clipShape(Capsule()) + } + } + .padding(.top, 8) } - .padding(.top, 8) + .padding(16) + } + .contentShape(Rectangle()) + .onTapGesture { + onMomentTap(moment) } - .padding(16) } } diff --git a/yana/MVVM/ViewModel/MomentDetailViewModel.swift b/yana/MVVM/ViewModel/MomentDetailViewModel.swift new file mode 100644 index 0000000..e6d1848 --- /dev/null +++ b/yana/MVVM/ViewModel/MomentDetailViewModel.swift @@ -0,0 +1,114 @@ +import SwiftUI +import Combine + +// MARK: - MomentDetailViewModel + +@MainActor +final class MomentDetailViewModel: ObservableObject { + // MARK: - Published Properties + @Published var moment: MomentsInfo + @Published var isLikeLoading = false + @Published var localIsLike: Bool + @Published var localLikeCount: Int + @Published var showImagePreview = false + @Published var images: [String] = [] + @Published var currentIndex: Int = 0 + + // MARK: - Private Properties + private var cancellables = Set() + + // MARK: - Initialization + init(moment: MomentsInfo) { + self.moment = moment + self.localIsLike = moment.isLike + self.localLikeCount = moment.likeCount + self.images = moment.dynamicResList?.compactMap { $0.resUrl } ?? [] + + debugInfoSync("📱 MomentDetailViewModel: 初始化") + debugInfoSync(" 动态ID: \(moment.dynamicId)") + debugInfoSync(" 用户: \(moment.nick)") + debugInfoSync(" 图片数量: \(images.count)") + } + + // MARK: - Public Methods + func onImageTap(_ index: Int) { + currentIndex = index + showImagePreview = true + debugInfoSync("📸 MomentDetailViewModel: 图片被点击,索引: \(index)") + } + + func like() { + guard !isLikeLoading, moment.status != 0 else { + debugInfoSync("⏸️ MomentDetailViewModel: 跳过点赞 - 正在加载: \(isLikeLoading), 审核中: \(moment.status == 0)") + return + } + + isLikeLoading = true + debugInfoSync("📡 MomentDetailViewModel: 开始点赞操作") + + Task { + do { + // 获取当前用户ID + guard let uidStr = await UserInfoManager.getCurrentUserId(), + let uid = Int(uidStr) else { + await MainActor.run { + isLikeLoading = false + } + setAPILoadingErrorSync(UUID(), errorMessage: "无法获取用户信息,请重新登录") + return + } + + // 确定请求参数 + let status = localIsLike ? 0 : 1 // 0: 取消点赞, 1: 点赞 + + // 创建 API 服务实例 + let api = LiveAPIService() + + // 创建请求 + let request = LikeDynamicRequest( + dynamicId: moment.dynamicId, + uid: uid, + status: status, + likedUid: moment.uid, + worldId: moment.worldId + ) + + debugInfoSync("📡 MomentDetailViewModel: 发送点赞请求") + debugInfoSync(" 动态ID: \(moment.dynamicId)") + debugInfoSync(" 当前状态: \(localIsLike)") + debugInfoSync(" 请求状态: \(status)") + + // 发起请求 + let response: LikeDynamicResponse = try await api.request(request) + + await MainActor.run { + isLikeLoading = false + // 处理响应 + if response.code == 200 { + localIsLike.toggle() + localLikeCount += localIsLike ? 1 : -1 + debugInfoSync("✅ MomentDetailViewModel: 点赞操作成功") + debugInfoSync(" 动态ID: \(moment.dynamicId)") + debugInfoSync(" 新状态: \(localIsLike)") + debugInfoSync(" 新数量: \(localLikeCount)") + } else { + let errorMessage = response.message.isEmpty ? "点赞失败,请重试" : response.message + setAPILoadingErrorSync(UUID(), errorMessage: errorMessage) + debugErrorSync("❌ MomentDetailViewModel: 点赞操作失败") + debugErrorSync(" 动态ID: \(moment.dynamicId)") + debugErrorSync(" 错误: \(errorMessage)") + } + } + + } catch { + await MainActor.run { + isLikeLoading = false + } + setAPILoadingErrorSync(UUID(), errorMessage: error.localizedDescription) + debugErrorSync("❌ MomentDetailViewModel: 点赞请求异常") + debugErrorSync(" 动态ID: \(moment.dynamicId)") + debugErrorSync(" 错误: \(error.localizedDescription)") + } + } + } +} diff --git a/yana/Resources/en.lproj/Localizable.strings b/yana/Resources/en.lproj/Localizable.strings index 8a71b97..b7fd862 100644 --- a/yana/Resources/en.lproj/Localizable.strings +++ b/yana/Resources/en.lproj/Localizable.strings @@ -90,10 +90,10 @@ "createFeed.processingImages" = "Processing images..."; "createFeed.publishing" = "Publishing..."; "createFeed.publish" = "Publish"; -"createFeed.title" = "Image & Text Publish"; +"createFeed.title" = "Image & Text"; // MARK: - Edit Feed -"editFeed.title" = "Image & Text Edit"; +"editFeed.title" = "Image & Text"; "editFeed.publish" = "Publish"; "editFeed.enterContent" = "Enter Content"; @@ -225,4 +225,4 @@ "config.version" = "Version"; "config.debug_mode" = "Debug Mode"; "config.api_timeout" = "API Timeout"; -"config.max_retries" = "Max Retries"; \ No newline at end of file +"config.max_retries" = "Max Retries";