feat: 新增我的动态信息结构和相关API请求逻辑
- 在DynamicsModels.swift中新增MyMomentInfo结构,专门用于处理/dynamic/getMyDynamic接口的响应数据。 - 更新MyMomentsResponse结构以使用MyMomentInfo,确保数据类型一致性。 - 在LoginModels.swift中重构IDLoginAPIRequest和EmailLoginRequest,优化queryParameters的实现方式,提升代码可读性。 - 在RecoverPasswordFeature中重构ResetPasswordRequest,优化queryParameters的实现方式,确保一致性。 - 在多个视图中添加调试信息,增强调试能力和用户体验。 - 更新Localizable.strings文件,新增动态列表为空时的提示信息,提升用户交互体验。
This commit is contained in:
@@ -50,6 +50,8 @@
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
4C4C8FBE2DE5AF9200384527 /* yanaAPITests */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
);
|
||||
path = yanaAPITests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -256,14 +258,10 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-yana/Pods-yana-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-yana/Pods-yana-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-yana/Pods-yana-resources.sh\"\n";
|
||||
@@ -277,14 +275,10 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-yana/Pods-yana-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-yana/Pods-yana-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-yana/Pods-yana-frameworks.sh\"\n";
|
||||
|
@@ -241,12 +241,56 @@ struct PublishFeedData: Codable, Equatable {
|
||||
|
||||
// MARK: - 我的动态 API 请求
|
||||
|
||||
/// 我的动态信息结构 - 专门用于 /dynamic/getMyDynamic 接口
|
||||
struct MyMomentInfo: Codable, Equatable, Sendable {
|
||||
let content: String
|
||||
let uid: Int
|
||||
let publishTime: Int64
|
||||
let type: Int
|
||||
|
||||
// 转换为 MomentsInfo 的辅助方法
|
||||
func toMomentsInfo() -> MomentsInfo {
|
||||
return MomentsInfo(
|
||||
dynamicId: 0, // 我的动态接口没有返回 dynamicId
|
||||
uid: uid,
|
||||
nick: "", // 需要从用户信息中获取
|
||||
avatar: "", // 需要从用户信息中获取
|
||||
type: type,
|
||||
content: content,
|
||||
likeCount: 0, // 我的动态接口没有返回点赞数
|
||||
isLike: false, // 我的动态接口没有返回点赞状态
|
||||
commentCount: 0, // 我的动态接口没有返回评论数
|
||||
publishTime: Int(publishTime / 1000), // 转换为秒
|
||||
worldId: 0, // 我的动态接口没有返回 worldId
|
||||
status: 1, // 默认状态
|
||||
playCount: nil,
|
||||
dynamicResList: 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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// 我的动态响应结构
|
||||
struct MyMomentsResponse: Codable, Equatable, Sendable {
|
||||
let code: Int
|
||||
let message: String
|
||||
let data: [MomentsInfo]?
|
||||
let timestamp: Int?
|
||||
let data: [MyMomentInfo]?
|
||||
let timestamp: Int64?
|
||||
}
|
||||
|
||||
struct GetMyDynamicRequest: APIRequestProtocol {
|
||||
|
@@ -77,10 +77,29 @@ struct IDLoginAPIRequest: APIRequestProtocol {
|
||||
let endpoint = APIEndpoint.login.path // 使用枚举定义的登录端点
|
||||
let method: HTTPMethod = .POST
|
||||
let includeBaseParameters = true
|
||||
let queryParameters: [String: String]?
|
||||
var bodyParameters: [String: Any]? { nil }
|
||||
let timeout: TimeInterval = 30.0
|
||||
|
||||
// MARK: - Private Properties
|
||||
private let phone: String
|
||||
private let password: String
|
||||
private let clientSecret: String
|
||||
private let version: String
|
||||
private let clientId: String
|
||||
private let grantType: String
|
||||
|
||||
// MARK: - Computed Properties
|
||||
var queryParameters: [String: String]? {
|
||||
return [
|
||||
"phone": phone,
|
||||
"password": password,
|
||||
"client_secret": clientSecret,
|
||||
"version": version,
|
||||
"client_id": clientId,
|
||||
"grant_type": grantType
|
||||
]
|
||||
}
|
||||
|
||||
/// 初始化ID登录请求
|
||||
/// - Parameters:
|
||||
/// - phone: DES加密后的用户ID/手机号
|
||||
@@ -90,14 +109,12 @@ struct IDLoginAPIRequest: APIRequestProtocol {
|
||||
/// - clientId: 客户端ID,固定为"erban-client"
|
||||
/// - grantType: 授权类型,固定为"password"
|
||||
init(phone: String, password: String, clientSecret: String = "uyzjdhds", version: String = "1", clientId: String = "erban-client", grantType: String = "password") {
|
||||
self.queryParameters = [
|
||||
"phone": phone,
|
||||
"password": password,
|
||||
"client_secret": clientSecret,
|
||||
"version": version,
|
||||
"client_id": clientId,
|
||||
"grant_type": grantType
|
||||
];
|
||||
self.phone = phone
|
||||
self.password = password
|
||||
self.clientSecret = clientSecret
|
||||
self.version = version
|
||||
self.clientId = clientId
|
||||
self.grantType = grantType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,10 +544,29 @@ struct EmailLoginRequest: APIRequestProtocol {
|
||||
let endpoint = APIEndpoint.login.path
|
||||
let method: HTTPMethod = .POST
|
||||
let includeBaseParameters = true
|
||||
let queryParameters: [String: String]?
|
||||
var bodyParameters: [String: Any]? { nil }
|
||||
let timeout: TimeInterval = 30.0
|
||||
|
||||
// MARK: - Private Properties
|
||||
private let email: String
|
||||
private let code: String
|
||||
private let clientSecret: String
|
||||
private let version: String
|
||||
private let clientId: String
|
||||
private let grantType: String
|
||||
|
||||
// MARK: - Computed Properties
|
||||
var queryParameters: [String: String]? {
|
||||
return [
|
||||
"email": email,
|
||||
"code": code,
|
||||
"client_secret": clientSecret,
|
||||
"version": version,
|
||||
"client_id": clientId,
|
||||
"grant_type": grantType
|
||||
]
|
||||
}
|
||||
|
||||
/// 初始化邮箱验证码登录请求
|
||||
/// - Parameters:
|
||||
/// - email: DES加密后的邮箱地址
|
||||
@@ -540,14 +576,12 @@ struct EmailLoginRequest: APIRequestProtocol {
|
||||
/// - clientId: 客户端ID,固定为"erban-client"
|
||||
/// - grantType: 授权类型,固定为"email"
|
||||
init(email: String, code: String, clientSecret: String = "uyzjdhds", version: String = "1", clientId: String = "erban-client", grantType: String = "email") {
|
||||
self.queryParameters = [
|
||||
"email": email,
|
||||
"code": code,
|
||||
"client_secret": clientSecret,
|
||||
"version": version,
|
||||
"client_id": clientId,
|
||||
"grant_type": grantType
|
||||
]
|
||||
self.email = email
|
||||
self.code = code
|
||||
self.clientSecret = clientSecret
|
||||
self.version = version
|
||||
self.clientId = clientId
|
||||
self.grantType = grantType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,18 +637,25 @@ struct GetUserInfoRequest: APIRequestProtocol {
|
||||
let endpoint = APIEndpoint.getUserInfo.path
|
||||
let method: HTTPMethod = .GET
|
||||
let includeBaseParameters = true
|
||||
let queryParameters: [String: String]?
|
||||
var bodyParameters: [String: Any]? { nil }
|
||||
let timeout: TimeInterval = 30.0
|
||||
let shouldShowLoading: Bool = false // 不显示loading,避免影响用户体验
|
||||
let shouldShowError: Bool = false // 不显示错误,静默处理
|
||||
|
||||
// MARK: - Private Properties
|
||||
private let uid: String
|
||||
|
||||
// MARK: - Computed Properties
|
||||
var queryParameters: [String: String]? {
|
||||
return [
|
||||
"uid": uid
|
||||
]
|
||||
}
|
||||
|
||||
/// 初始化获取用户信息请求
|
||||
/// - Parameter uid: 要查询的用户ID
|
||||
init(uid: String) {
|
||||
self.queryParameters = [
|
||||
"uid": uid
|
||||
]
|
||||
self.uid = uid
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,17 +5,16 @@ enum AppEnvironment {
|
||||
|
||||
struct AppConfig {
|
||||
static let current: AppEnvironment = {
|
||||
#if DEBUG
|
||||
return .development
|
||||
#else
|
||||
// #if DEBUG
|
||||
// return .development
|
||||
// #else
|
||||
return .production
|
||||
#endif
|
||||
// #endif
|
||||
}()
|
||||
|
||||
static var baseURL: String {
|
||||
switch current {
|
||||
case .development:
|
||||
// return "http://192.168.10.211:8080"
|
||||
return "http://beta.api.molistar.xyz"
|
||||
case .production:
|
||||
return "https://api.epartylive.com"
|
||||
|
@@ -112,24 +112,36 @@ struct FeedListFeature {
|
||||
case .fetchFeeds:
|
||||
state.isLoading = true
|
||||
state.error = nil
|
||||
debugInfoSync("🔄 FeedListFeature: 开始获取动态")
|
||||
// 发起 API 请求
|
||||
return .run { [apiService] send in
|
||||
await send(.fetchFeedsResponse(TaskResult {
|
||||
let request = LatestDynamicsRequest(dynamicId: "", pageSize: 20, types: [.text, .picture])
|
||||
debugInfoSync("📡 FeedListFeature: 发送请求: \(request.endpoint)")
|
||||
debugInfoSync(" 参数: dynamicId=\(request.dynamicId), pageSize=\(request.pageSize)")
|
||||
return try await apiService.request(request)
|
||||
}))
|
||||
}
|
||||
case let .fetchFeedsResponse(.success(response)):
|
||||
state.isLoading = false
|
||||
debugInfoSync("✅ FeedListFeature: API 请求成功")
|
||||
debugInfoSync(" 响应码: \(response.code)")
|
||||
debugInfoSync(" 消息: \(response.message)")
|
||||
debugInfoSync(" 数据数量: \(response.data?.dynamicList.count ?? 0)")
|
||||
if let list = response.data?.dynamicList {
|
||||
state.moments = list
|
||||
state.error = nil
|
||||
state.currentPage = 1
|
||||
state.hasMore = (list.count >= 20)
|
||||
debugInfoSync("✅ FeedListFeature: 数据加载成功")
|
||||
debugInfoSync(" 动态数量: \(list.count)")
|
||||
debugInfoSync(" 是否有更多: \(state.hasMore)")
|
||||
} else {
|
||||
state.moments = []
|
||||
state.error = response.message
|
||||
state.hasMore = false
|
||||
debugErrorSync("❌ FeedListFeature: 数据为空")
|
||||
debugErrorSync(" 错误消息: \(response.message)")
|
||||
}
|
||||
return .none
|
||||
case let .fetchFeedsResponse(.failure(error)):
|
||||
@@ -137,6 +149,8 @@ struct FeedListFeature {
|
||||
state.moments = []
|
||||
state.error = error.localizedDescription
|
||||
state.hasMore = false
|
||||
debugErrorSync("❌ FeedListFeature: API 请求失败")
|
||||
debugErrorSync(" 错误: \(error.localizedDescription)")
|
||||
return .none
|
||||
case .editFeedButtonTapped:
|
||||
state.isEditFeedPresented = true
|
||||
|
@@ -23,7 +23,17 @@ struct MainFeature {
|
||||
init(accountModel: AccountModel? = nil) {
|
||||
self.accountModel = accountModel
|
||||
let uid = accountModel?.uid.flatMap { Int($0) } ?? 0
|
||||
self.me = MeFeature.State(displayUID: uid > 0 ? uid : nil)
|
||||
debugInfoSync("🏗️ MainFeature 初始化")
|
||||
debugInfoSync(" accountModel.uid: \(accountModel?.uid ?? "nil")")
|
||||
debugInfoSync(" 转换后的uid: \(uid)")
|
||||
var meState = MeFeature.State(displayUID: uid > 0 ? uid : nil)
|
||||
if uid > 0 {
|
||||
meState.uid = uid // 确保uid与displayUID一致
|
||||
}
|
||||
self.me = meState
|
||||
debugInfoSync(" meState.uid: \(meState.uid)")
|
||||
debugInfoSync(" meState.displayUID: \(meState.displayUID ?? -1)")
|
||||
debugInfoSync(" meState.effectiveUID: \(meState.effectiveUID)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +78,7 @@ struct MainFeature {
|
||||
if tab == .other, let uidStr = state.accountModel?.uid, let uid = Int(uidStr), uid > 0 {
|
||||
if state.me.displayUID != uid {
|
||||
state.me.displayUID = uid
|
||||
state.me.uid = uid // 同步更新uid
|
||||
state.me.isFirstLoad = true
|
||||
}
|
||||
return .send(.me(.onAppear))
|
||||
@@ -90,6 +101,7 @@ struct MainFeature {
|
||||
if state.selectedTab == .other, let uidStr = accountModel?.uid, let uid = Int(uidStr), uid > 0 {
|
||||
if state.me.displayUID != uid {
|
||||
state.me.displayUID = uid
|
||||
state.me.uid = uid // 同步更新uid
|
||||
state.me.isFirstLoad = true
|
||||
}
|
||||
return .send(.me(.onAppear))
|
||||
|
@@ -61,7 +61,9 @@ struct MeDynamicFeature: Reducer {
|
||||
state.isLoadingMore = false
|
||||
switch result {
|
||||
case let .success(resp):
|
||||
let newDynamics = resp.data ?? []
|
||||
let myMoments = resp.data ?? []
|
||||
// 将 MyMomentInfo 转换为 MomentsInfo
|
||||
let newDynamics = myMoments.map { $0.toMomentsInfo() }
|
||||
if state.page == 1 {
|
||||
state.dynamics = newDynamics
|
||||
} else {
|
||||
@@ -80,11 +82,21 @@ struct MeDynamicFeature: Reducer {
|
||||
private func fetchDynamics(uid: Int, page: Int, pageSize: Int) -> Effect<Action> {
|
||||
let apiService = self.apiService
|
||||
return .run { send in
|
||||
debugInfoSync("🔄 MeDynamicFeature: 开始获取动态")
|
||||
debugInfoSync(" UID: \(uid)")
|
||||
debugInfoSync(" 页码: \(page)")
|
||||
debugInfoSync(" 页大小: \(pageSize)")
|
||||
|
||||
do {
|
||||
let req = GetMyDynamicRequest(fromUid: uid, uid: uid, page: page, pageSize: pageSize)
|
||||
let resp = try await apiService.request(req)
|
||||
debugInfoSync("✅ MeDynamicFeature: API 请求成功")
|
||||
debugInfoSync(" 响应码: \(resp.code)")
|
||||
debugInfoSync(" 消息: \(resp.message)")
|
||||
debugInfoSync(" 数据数量: \(resp.data?.count ?? 0)")
|
||||
await send(.fetchResponse(.success(resp)))
|
||||
} catch {
|
||||
debugErrorSync("❌ MeDynamicFeature: API 请求失败: \(error.localizedDescription)")
|
||||
await send(.fetchResponse(.failure(error as? APIError ?? .unknown(error.localizedDescription))))
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,10 @@ struct MeFeature {
|
||||
|
||||
init(displayUID: Int? = nil) {
|
||||
self.displayUID = displayUID
|
||||
// 如果displayUID不为nil,说明要显示指定用户,将其设置为uid
|
||||
if let displayUID = displayUID {
|
||||
self.uid = displayUID
|
||||
}
|
||||
}
|
||||
|
||||
// 获取实际要显示的用户ID
|
||||
@@ -57,13 +61,20 @@ struct MeFeature {
|
||||
switch action {
|
||||
case .onAppear:
|
||||
guard state.isFirstLoad else { return .none }
|
||||
debugInfoSync("📱 MeFeature onAppear")
|
||||
debugInfoSync(" isFirstLoad: \(state.isFirstLoad)")
|
||||
debugInfoSync(" effectiveUID: \(state.effectiveUID)")
|
||||
state.isFirstLoad = false
|
||||
return .send(.refresh)
|
||||
case .refresh:
|
||||
guard state.effectiveUID > 0 else { return .none }
|
||||
debugInfoSync("🔄 MeFeature refresh")
|
||||
debugInfoSync(" effectiveUID: \(state.effectiveUID)")
|
||||
state.isRefreshing = true
|
||||
state.page = 1
|
||||
state.hasMore = true
|
||||
state.userInfoError = nil // 重置错误状态
|
||||
state.momentsError = nil // 重置错误状态
|
||||
return .merge(
|
||||
fetchUserInfo(uid: state.effectiveUID),
|
||||
fetchMoments(uid: state.effectiveUID, page: 1, pageSize: state.pageSize)
|
||||
@@ -89,7 +100,49 @@ struct MeFeature {
|
||||
state.isRefreshing = false
|
||||
switch result {
|
||||
case let .success(resp):
|
||||
let newMoments = resp.data ?? []
|
||||
let myMoments = resp.data ?? []
|
||||
// 将 MyMomentInfo 转换为 MomentsInfo,并填充用户信息
|
||||
let newMoments = myMoments.map { myMoment in
|
||||
var momentsInfo = myMoment.toMomentsInfo()
|
||||
// 填充用户信息
|
||||
if let userInfo = state.userInfo {
|
||||
// 使用默认的成员初始化器
|
||||
momentsInfo = MomentsInfo(
|
||||
dynamicId: momentsInfo.dynamicId,
|
||||
uid: momentsInfo.uid,
|
||||
nick: userInfo.nick ?? userInfo.nickname ?? "未知用户",
|
||||
avatar: userInfo.avatar ?? "",
|
||||
type: momentsInfo.type,
|
||||
content: momentsInfo.content,
|
||||
likeCount: momentsInfo.likeCount,
|
||||
isLike: momentsInfo.isLike,
|
||||
commentCount: momentsInfo.commentCount,
|
||||
publishTime: momentsInfo.publishTime,
|
||||
worldId: momentsInfo.worldId,
|
||||
status: momentsInfo.status,
|
||||
playCount: momentsInfo.playCount,
|
||||
dynamicResList: momentsInfo.dynamicResList,
|
||||
gender: userInfo.gender,
|
||||
squareTop: momentsInfo.squareTop,
|
||||
topicTop: momentsInfo.topicTop,
|
||||
newUser: userInfo.newUser,
|
||||
defUser: userInfo.defUser,
|
||||
scene: momentsInfo.scene,
|
||||
userVipInfoVO: nil, // UserVipInfoVO 和 UserVipInfo 类型不匹配,暂时设为 nil
|
||||
headwearPic: userInfo.userHeadwear?.pic,
|
||||
headwearEffect: userInfo.userHeadwear?.effect,
|
||||
headwearType: userInfo.userHeadwear?.type,
|
||||
headwearName: userInfo.userHeadwear?.headwearName,
|
||||
headwearId: userInfo.userHeadwear?.headwearId,
|
||||
experLevelPic: userInfo.userLevelVo?.experUrl,
|
||||
charmLevelPic: userInfo.userLevelVo?.charmUrl,
|
||||
isCustomWord: momentsInfo.isCustomWord,
|
||||
labelList: momentsInfo.labelList
|
||||
)
|
||||
}
|
||||
return momentsInfo
|
||||
}
|
||||
|
||||
if state.page == 1 {
|
||||
state.moments = newMoments
|
||||
} else {
|
||||
@@ -98,8 +151,14 @@ struct MeFeature {
|
||||
state.hasMore = newMoments.count == state.pageSize
|
||||
if state.hasMore { state.page += 1 }
|
||||
state.momentsError = nil
|
||||
|
||||
debugInfoSync("✅ 我的动态加载成功")
|
||||
debugInfoSync(" 加载数量: \(newMoments.count)")
|
||||
debugInfoSync(" 总数量: \(state.moments.count)")
|
||||
debugInfoSync(" 是否有更多: \(state.hasMore)")
|
||||
case let .failure(error):
|
||||
state.momentsError = error.localizedDescription
|
||||
debugErrorSync("❌ 我的动态加载失败: \(error.localizedDescription)")
|
||||
}
|
||||
return .none
|
||||
case .settingButtonTapped:
|
||||
@@ -118,9 +177,16 @@ struct MeFeature {
|
||||
|
||||
private func fetchUserInfo(uid: Int) -> Effect<Action> {
|
||||
.run { send in
|
||||
debugInfoSync("👤 开始获取用户信息")
|
||||
debugInfoSync(" UID: \(uid)")
|
||||
|
||||
if let userInfo = await UserInfoManager.fetchUserInfoFromServer(uid: String(uid), apiService: apiService) {
|
||||
debugInfoSync("✅ 用户信息获取成功")
|
||||
debugInfoSync(" 昵称: \(userInfo.nick ?? userInfo.nickname ?? "未知")")
|
||||
debugInfoSync(" 头像: \(userInfo.avatar ?? "无")")
|
||||
await send(.userInfoResponse(.success(userInfo)))
|
||||
} else {
|
||||
debugErrorSync("❌ 用户信息获取失败")
|
||||
await send(.userInfoResponse(.failure(.noData)))
|
||||
}
|
||||
}
|
||||
@@ -128,11 +194,28 @@ struct MeFeature {
|
||||
|
||||
private func fetchMoments(uid: Int, page: Int, pageSize: Int) -> Effect<Action> {
|
||||
.run { send in
|
||||
debugInfoSync("🔄 开始获取我的动态")
|
||||
debugInfoSync(" UID: \(uid)")
|
||||
debugInfoSync(" 页码: \(page)")
|
||||
debugInfoSync(" 页大小: \(pageSize)")
|
||||
|
||||
do {
|
||||
let req = GetMyDynamicRequest(fromUid: uid, uid: uid, page: page, pageSize: pageSize)
|
||||
debugInfoSync("📡 发送请求: \(req.endpoint)")
|
||||
debugInfoSync(" 参数: fromUid=\(uid), uid=\(uid), page=\(page), pageSize=\(pageSize)")
|
||||
|
||||
let resp = try await apiService.request(req)
|
||||
debugInfoSync("✅ API 请求成功")
|
||||
debugInfoSync(" 响应码: \(resp.code)")
|
||||
debugInfoSync(" 消息: \(resp.message)")
|
||||
debugInfoSync(" 数据数量: \(resp.data?.count ?? 0)")
|
||||
|
||||
await send(.momentsResponse(.success(resp)))
|
||||
} catch {
|
||||
debugErrorSync("❌ API 请求失败: \(error.localizedDescription)")
|
||||
if let apiError = error as? APIError {
|
||||
debugErrorSync(" API错误类型: \(apiError)")
|
||||
}
|
||||
await send(.momentsResponse(.failure(error as? APIError ?? .unknown(error.localizedDescription))))
|
||||
}
|
||||
}
|
||||
|
@@ -210,21 +210,32 @@ struct ResetPasswordRequest: APIRequestProtocol {
|
||||
let endpoint = "/acc/pwd/resetByEmail" // 新的API端点
|
||||
let method: HTTPMethod = .POST
|
||||
let includeBaseParameters = true
|
||||
let queryParameters: [String: String]?
|
||||
var bodyParameters: [String: Any]? { nil }
|
||||
let timeout: TimeInterval = 30.0
|
||||
|
||||
// MARK: - Private Properties
|
||||
private let email: String
|
||||
private let code: String
|
||||
private let newPwd: String
|
||||
|
||||
// MARK: - Computed Properties
|
||||
var queryParameters: [String: String]? {
|
||||
return [
|
||||
"email": email,
|
||||
"newPwd": newPwd, // 参数名改为newPwd
|
||||
"code": code
|
||||
]
|
||||
}
|
||||
|
||||
/// 初始化密码重置请求
|
||||
/// - Parameters:
|
||||
/// - email: DES加密后的邮箱地址
|
||||
/// - code: 验证码
|
||||
/// - newPwd: DES加密后的新密码
|
||||
init(email: String, code: String, newPwd: String) {
|
||||
self.queryParameters = [
|
||||
"email": email,
|
||||
"newPwd": newPwd, // 参数名改为newPwd
|
||||
"code": code
|
||||
]
|
||||
self.email = email
|
||||
self.code = code
|
||||
self.newPwd = newPwd
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -100,6 +100,7 @@
|
||||
// MARK: - Feed List
|
||||
"feedList.title" = "Enjoy your Life Time";
|
||||
"feedList.slogan" = "The disease is like a cruel ruler,\nand time is our most precious treasure.\nEvery moment we live is a victory\nagainst the inevitable.";
|
||||
"feedList.empty" = "No moments yet";
|
||||
|
||||
// MARK: - Feed
|
||||
"feed.title" = "Enjoy your Life Time";
|
||||
|
@@ -97,7 +97,8 @@
|
||||
"editFeed.enterContent" = "输入内容";
|
||||
|
||||
"feedList.title" = "享受您的生活时光";
|
||||
"feedList.slogan" = "疾病如同残酷的统治者,\n而时间是我们最宝贵的财富。\n我们活着的每一刻,都是对不可避免命运的胜利。";
|
||||
"feedList.slogan" = "疾病如同残酷的统治者,\n而时间是我们最宝贵的财富。\n我们活着的每一刻,都是对不可避免命运的胜利。";
|
||||
"feedList.empty" = "暂无动态";
|
||||
|
||||
"feed.title" = "享受您的生活时光";
|
||||
"feed.empty" = "暂无动态内容";
|
||||
|
@@ -23,7 +23,7 @@ struct DetailView: View {
|
||||
WithPerceptionTracking {
|
||||
CustomNavigationBar(
|
||||
title: LocalizedString("detail.title", comment: "Detail page title"),
|
||||
showDeleteButton: isCurrentUserDynamic,
|
||||
showDeleteButton: false,
|
||||
isDeleteLoading: store.isDeleteLoading,
|
||||
onBack: {
|
||||
// 移除 onDismiss?() 调用,因为现在使用 dismiss()
|
||||
|
@@ -173,6 +173,13 @@ struct FeedListContentView: View {
|
||||
@Binding var previewCurrentIndex: Int
|
||||
|
||||
var body: some View {
|
||||
// 添加调试信息
|
||||
let _ = debugInfoSync("📱 FeedListContentView 状态:")
|
||||
let _ = debugInfoSync(" isLoading: \(store.isLoading)")
|
||||
let _ = debugInfoSync(" error: \(store.error ?? "nil")")
|
||||
let _ = debugInfoSync(" moments.count: \(store.moments.count)")
|
||||
let _ = debugInfoSync(" hasMore: \(store.hasMore)")
|
||||
|
||||
if store.isLoading {
|
||||
FeedListLoadingView()
|
||||
} else if let error = store.error {
|
||||
|
@@ -79,6 +79,11 @@ struct MeView: View {
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
debugInfoSync("📱 MeView onAppear")
|
||||
debugInfoSync(" 用户信息: \(store.userInfo?.nick ?? "nil")")
|
||||
debugInfoSync(" 动态数量: \(store.moments.count)")
|
||||
debugInfoSync(" 用户信息错误: \(store.userInfoError ?? "nil")")
|
||||
debugInfoSync(" 动态错误: \(store.momentsError ?? "nil")")
|
||||
store.send(.onAppear)
|
||||
}
|
||||
// 新增:图片预览弹窗
|
||||
@@ -174,7 +179,7 @@ struct MeView: View {
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.horizontal, 32)
|
||||
Button("重试") {
|
||||
store.send(.onAppear)
|
||||
store.send(.refresh)
|
||||
}
|
||||
.font(.system(size: 14, weight: .medium))
|
||||
.foregroundColor(.white)
|
||||
@@ -192,6 +197,22 @@ struct MeView: View {
|
||||
Text("暂无动态")
|
||||
.font(.system(size: 16, weight: .medium))
|
||||
.foregroundColor(.white.opacity(0.7))
|
||||
// 添加调试信息
|
||||
Text("调试: moments.count = \(store.moments.count)")
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.yellow)
|
||||
Text("调试: isLoadingUserInfo = \(store.isLoadingUserInfo)")
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.yellow)
|
||||
Text("调试: isLoadingMoments = \(store.isLoadingMoments)")
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.yellow)
|
||||
Text("调试: userInfoError = \(store.userInfoError ?? "nil")")
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.yellow)
|
||||
Text("调试: momentsError = \(store.momentsError ?? "nil")")
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.yellow)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user