import Foundation import ComposableArchitecture import CasePaths @Reducer struct MainFeature { enum Tab: Int, Equatable, CaseIterable { case feed, other } @ObservableState struct State: Equatable { var selectedTab: Tab = .feed var feedList: FeedListFeature.State = .init() var me: MeFeature.State var accountModel: AccountModel? = nil // 新增:导航路径和设置页面 State var navigationPath: [Destination] = [] var appSettingState: AppSettingFeature.State? = nil // 新增:登出标志 var isLoggedOut: Bool = false init(accountModel: AccountModel? = nil) { self.accountModel = accountModel let uid = accountModel?.uid.flatMap { Int($0) } ?? 0 debugInfoSync("🏗️ MainFeature 初始化") debugInfoSync(" accountModel.uid: \(accountModel?.uid ?? "nil")") debugInfoSync(" 转换后的uid: \(uid)") // 如果没有传入accountModel,尝试从Keychain获取 if accountModel == nil { debugInfoSync(" 🔍 尝试从Keychain获取AccountModel") Task { if let savedAccountModel = await UserInfoManager.getAccountModel() { debugInfoSync(" ✅ 从Keychain获取到AccountModel: \(savedAccountModel.uid ?? "nil")") } else { debugInfoSync(" ⚠️ 从Keychain未获取到AccountModel") } } } 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)") } } // 新增:导航目标 enum Destination: Hashable, Codable, CaseIterable { case appSetting case testView } @CasePathable enum Action: Equatable { case onAppear case selectTab(Tab) case feedList(FeedListFeature.Action) case me(MeFeature.Action) case accountModelLoaded(AccountModel?) // 新增:导航相关 case navigationPathChanged([Destination]) case appSettingButtonTapped case appSettingAction(AppSettingFeature.Action) // 新增:登出 case logout } var body: some ReducerOf { Scope(state: \ .feedList, action: \ .feedList) { FeedListFeature() } Scope(state: \ .me, action: \ .me) { MeFeature() } Reduce { state, action in switch action { case .onAppear: return .run { send in let accountModel = await UserInfoManager.getAccountModel() await send(.accountModelLoaded(accountModel)) } case .selectTab(let tab): debugInfoSync("🎯 MainFeature selectTab: \(tab)") debugInfoSync(" 当前selectedTab: \(state.selectedTab)") debugInfoSync(" 新selectedTab: \(tab)") // 避免重复设置相同的tab guard state.selectedTab != tab else { debugInfoSync(" ⚠️ 重复设置相同tab,忽略") return .none } state.selectedTab = tab state.navigationPath = [] debugInfoSync(" ✅ selectedTab已更新为: \(state.selectedTab)") // 切换到MeView时,确保有有效的uid并触发数据加载 if tab == .other { if 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 debugInfoSync(" 🔄 更新MeFeature状态,uid: \(uid)") } debugInfoSync(" 📱 切换到MeView,触发数据加载") return .send(.me(.onAppear)) } else { debugInfoSync(" ⚠️ 切换到MeView但uid无效,等待AccountModel加载") } } return .none case .feedList(.testButtonTapped): state.navigationPath.append(.testView) return .none case .feedList(.createFeedPublishSuccess): // CreateFeed发布成功,刷新FeedList和Me页数据 return .merge( .send(.feedList(.reload)), .send(.me(.refresh)) ) case .feedList: return .none case let .accountModelLoaded(accountModel): state.accountModel = accountModel debugInfoSync("📦 MainFeature: AccountModel已加载") debugInfoSync(" uid: \(accountModel?.uid ?? "nil")") // 更新MeFeature状态 if 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 debugInfoSync(" 🔄 更新MeFeature状态,uid: \(uid)") } // 如果当前选中的是 MeView 标签页,则触发数据加载 if state.selectedTab == .other { debugInfoSync(" 📱 当前在MeView,触发数据加载") return .send(.me(.onAppear)) } // 如果当前选中的是 FeedView 标签页,则触发数据加载 if state.selectedTab == .feed { debugInfoSync(" 📱 当前在FeedView,触发数据加载") return .send(.feedList(.checkAuthAndLoad)) } } else { debugInfoSync(" ⚠️ AccountModel中uid无效") } return .none case .me(.settingButtonTapped): // 触发 push 到设置页,带入当前用户信息 let userInfo = state.me.userInfo let avatarURL = userInfo?.avatar let nickname = userInfo?.nick ?? "" state.appSettingState = AppSettingFeature.State(nickname: nickname, avatarURL: avatarURL, userInfo: userInfo) state.navigationPath.append(.appSetting) return .none case .me: return .none case .navigationPathChanged(let newPath): // pop 回来时清空 settingState state.navigationPath = newPath return .none case .appSettingButtonTapped: let userInfo = state.me.userInfo let avatarURL = userInfo?.avatar let nickname = userInfo?.nick ?? "" state.appSettingState = AppSettingFeature.State(nickname: nickname, avatarURL: avatarURL, userInfo: userInfo) state.navigationPath.append(.appSetting) return .none case .appSettingAction(.logoutConfirmed): // 监听到确认登出,设置登出标志 state.isLoggedOut = true return .none case .appSettingAction(.dismissTapped): // 监听到设置页的返回按钮,pop 导航栈 if !state.navigationPath.isEmpty { state.navigationPath.removeLast() } return .none case .appSettingAction(.updateUser(.success)): // 设置页用户信息变更成功,刷新Me页数据 return .send(.me(.refresh)) case .appSettingAction: return .none case .logout: // 由上层(SplashView/SplashFeature)监听,切换到登录页 return .none } } // 设置页作用域 .ifLet(\ .appSettingState, action: \ .appSettingAction) { AppSettingFeature() } } }