From e980cd5553451f647130462c359afde92c471f90 Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Thu, 9 Oct 2025 17:48:07 +0800 Subject: [PATCH] =?UTF-8?q?Phase=201=20Day=201:=20=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E6=9E=B6=E6=9E=84=E6=90=AD=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建 white-label-base 分支 - 添加 APIConfig.swift(API 域名动态生成,XOR + Base64 加密) * DEV 环境使用原测试域名 * RELEASE 环境使用新域名 https://api.epartylive.com - 添加 Swift/OC 混编支持(YuMi-Bridging-Header.h) - 创建 GlobalEventManager(全局事件管理器) * 迁移 NIMSDK 代理 * 迁移房间最小化逻辑 * 迁移全局通知处理 - 创建 NewTabBarController(Swift TabBar,只有 2 个 Tab) * Moment Tab * Mine Tab * 新的主色调和样式 --- YuMi.xcodeproj/project.pbxproj | 16 +- YuMi/Config/APIConfig.swift | 93 +++++++ YuMi/Global/GlobalEventManager.h | 71 +++++ YuMi/Global/GlobalEventManager.m | 242 ++++++++++++++++++ .../NewTabBar/NewTabBarController.swift | 197 ++++++++++++++ YuMi/YuMi-Bridging-Header.h | 46 ++++ white-label-progress.md | 117 +++++++++ 7 files changed, 778 insertions(+), 4 deletions(-) create mode 100644 YuMi/Config/APIConfig.swift create mode 100644 YuMi/Global/GlobalEventManager.h create mode 100644 YuMi/Global/GlobalEventManager.m create mode 100644 YuMi/Modules/NewTabBar/NewTabBarController.swift create mode 100644 YuMi/YuMi-Bridging-Header.h create mode 100644 white-label-progress.md diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index cd619f4..ee2de37 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -11711,10 +11711,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-resources-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-resources-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-resources.sh\"\n"; @@ -11728,10 +11732,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-frameworks.sh\"\n"; @@ -13282,7 +13290,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 48UCG35Q9W; + DEVELOPMENT_TEAM = Z7UCRF23F3; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -13516,7 +13524,7 @@ "-weak_framework", "\"AuthenticationServices\"", ); - PRODUCT_BUNDLE_IDENTIFIER = com.peko.enterprise.ios; + PRODUCT_BUNDLE_IDENTIFIER = com.junpeiqi.eparty; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -13538,9 +13546,9 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = YuMi/YuMiRelease.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = Z7UCRF23F3; + DEVELOPMENT_TEAM = ""; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/YuMi/Config/APIConfig.swift b/YuMi/Config/APIConfig.swift new file mode 100644 index 0000000..d5eb095 --- /dev/null +++ b/YuMi/Config/APIConfig.swift @@ -0,0 +1,93 @@ +// +// APIConfig.swift +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +import Foundation + +/// API 域名配置类 +/// 使用 XOR + Base64 双重混淆防止反编译 +@objc class APIConfig: NSObject { + + // MARK: - Private Properties + + /// XOR 加密密钥 + private static let xorKey: UInt8 = 77 + + /// RELEASE 环境域名(加密后) + /// 原始域名:https://api.epartylive.com + private static let releaseEncodedParts: [String] = [ + "JTk5PT53YmI=", // https:// (XOR 后 Base64) + "LD0kYw==", // api. (XOR 后 Base64) + "KD0sPzk0ISQ7KGMuIiA=", // epartylive.com (XOR 后 Base64) + ] + + // MARK: - Public Methods + + /// 获取 API 基础域名 + /// - Returns: 根据编译环境返回对应的域名 + @objc static func baseURL() -> String { + #if DEBUG + // DEV 环境:使用原有的测试域名(不变) + return HttpRequestHelper.getHostUrl() + #else + // RELEASE 环境:使用动态生成的新域名 + let url = decodeURL(from: releaseEncodedParts) + + // 验证解密结果 + if url.isEmpty || !url.hasPrefix("http") { + NSLog("[APIConfig] 警告:域名解密失败,使用备用域名") + return backupURL() + } + + return url + #endif + } + + /// 备用域名(降级方案) + /// - Returns: 原域名(仅在解密失败时使用) + @objc static func backupURL() -> String { + return HttpRequestHelper.getHostUrl() + } + + // MARK: - Private Methods + + /// 解密域名 + /// - Parameter parts: 加密后的域名片段数组 + /// - Returns: 解密后的完整域名 + private static func decodeURL(from parts: [String]) -> String { + let decoded = parts.compactMap { part -> String? in + guard let data = Data(base64Encoded: part) else { + NSLog("[APIConfig] Base64 解码失败: \(part)") + return nil + } + let xored = data.map { $0 ^ xorKey } + return String(bytes: xored, encoding: .utf8) + } + + let result = decoded.joined() + + #if DEBUG + NSLog("[APIConfig] 解密后的域名: \(result)") + #endif + + return result + } +} + +// MARK: - Debug Helper + +#if DEBUG +extension APIConfig { + /// 测试方法:验证域名加密/解密是否正常 + @objc static func testEncryption() { + print("=== APIConfig 加密测试 ===") + print("Release 域名: \(decodeURL(from: releaseEncodedParts))") + print("当前环境域名: \(baseURL())") + print("备用域名: \(backupURL())") + } +} +#endif diff --git a/YuMi/Global/GlobalEventManager.h b/YuMi/Global/GlobalEventManager.h new file mode 100644 index 0000000..d2fcb65 --- /dev/null +++ b/YuMi/Global/GlobalEventManager.h @@ -0,0 +1,71 @@ +// +// GlobalEventManager.h +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 全局事件管理器 +/// 负责处理原 TabBar 中的全局逻辑(SDK 代理、房间最小化、通知等) +@interface GlobalEventManager : NSObject + +/// 单例 ++ (instancetype)shared; + +// MARK: - SDK Delegates Setup + +/// 设置所有第三方 SDK 的代理 +- (void)setupSDKDelegates; + +/// 移除所有代理(dealloc 时调用) +- (void)removeAllDelegates; + +// MARK: - Room Mini View + +/// 设置房间最小化视图 +/// @param containerView 父视图(通常是 TabBar 的 view) +- (void)setupRoomMiniViewOn:(UIView *)containerView; + +/// 处理房间最小化通知 +/// @param userInfo 通知携带的数据 +- (void)handleRoomMini:(NSDictionary * _Nullable)userInfo; + +/// 隐藏房间最小化视图 +- (void)hideRoomMiniView; + +// MARK: - Global Notifications + +/// 处理配置重载通知 +- (void)handleConfigReload; + +/// 处理新用户充值通知 +- (void)handleNewUserRecharge; + +/// 处理主播卡片通知 +/// @param notification 通知对象 +- (void)handleAnchorCard:(NSNotification * _Nullable)notification; + +/// 处理语言切换通知 +/// @param notification 通知对象 +- (void)handleLanguageSwitch:(NSNotification * _Nullable)notification; + +// MARK: - User Info + +/// 获取用户信息成功后的处理 +/// @param userInfo 用户信息模型 +- (void)handleUserInfoSuccess:(id)userInfo; + +// MARK: - Social Share + +/// 注册社交分享回调 +- (void)registerSocialShareCallback; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Global/GlobalEventManager.m b/YuMi/Global/GlobalEventManager.m new file mode 100644 index 0000000..d50d83a --- /dev/null +++ b/YuMi/Global/GlobalEventManager.m @@ -0,0 +1,242 @@ +// +// GlobalEventManager.m +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import "GlobalEventManager.h" +#import "XPMiniRoomView.h" +#import "RoomBoomManager.h" +#import "PublicRoomManager.h" +#import "XPSkillCardPlayerManager.h" +#import "SocialShareManager.h" +#import "YUMIConstant.h" +#import + +@interface GlobalEventManager () + +// MARK: - Private Properties + +/// 房间最小化视图 +@property (nonatomic, strong) XPMiniRoomView *miniRoomView; + +/// 配置重载回调 +@property (nonatomic, copy) void(^configReloadCallback)(void); + +/// 新用户充值回调 +@property (nonatomic, copy) void(^newUserRechargeCallback)(void); + +@end + +@implementation GlobalEventManager + +// MARK: - Lifecycle + ++ (instancetype)shared { + static GlobalEventManager *instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[GlobalEventManager alloc] init]; + }); + return instance; +} + +- (instancetype)init { + if (self = [super init]) { + [self setupNotificationObservers]; + } + return self; +} + +- (void)dealloc { + [self removeAllDelegates]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +// MARK: - SDK Delegates Setup + +- (void)setupSDKDelegates { + // NIMSDK 代理设置 + [[NIMSDK sharedSDK].loginManager addDelegate:self]; + [[NIMSDK sharedSDK].chatManager addDelegate:self]; + [[NIMSDK sharedSDK].systemNotificationManager addDelegate:self]; + [[NIMSDK sharedSDK].broadcastManager addDelegate:self]; + + // RoomBoomManager 回调注册 + __weak typeof(self) weakSelf = self; + [[RoomBoomManager sharedManager] registerBoomBanner:^(id sth) { + __strong typeof(weakSelf) strongSelf = weakSelf; + if (!strongSelf) return; + + dispatch_async(dispatch_get_main_queue(), ^{ + // 检查用户是否在房间中 + if ([XPSkillCardPlayerManager shareInstance].isInRoom) { + NSLog(@"[GlobalEventManager] 收到 RoomBoom 通知"); + // TODO: 显示 Boom Banner + // [RoomBoomBannerAnimation display:window with:sth tapToRoom:YES complete:^{}]; + } + }); + } target:self]; + + NSLog(@"[GlobalEventManager] SDK 代理设置完成"); +} + +- (void)removeAllDelegates { + [[NIMSDK sharedSDK].loginManager removeDelegate:self]; + [[NIMSDK sharedSDK].chatManager removeDelegate:self]; + [[NIMSDK sharedSDK].systemNotificationManager removeDelegate:self]; + [[NIMSDK sharedSDK].broadcastManager removeDelegate:self]; + [[RoomBoomManager sharedManager] removeEventListenerForTarget:self]; + + NSLog(@"[GlobalEventManager] 所有代理已移除"); +} + +// MARK: - Room Mini View + +- (void)setupRoomMiniViewOn:(UIView *)containerView { + if (!self.miniRoomView) { + self.miniRoomView = [[XPMiniRoomView alloc] init]; + } + [containerView addSubview:self.miniRoomView]; + NSLog(@"[GlobalEventManager] 房间最小化视图已添加"); +} + +- (void)handleRoomMini:(NSDictionary *)userInfo { + if (self.miniRoomView) { + // TODO: 处理房间最小化逻辑 + NSLog(@"[GlobalEventManager] 处理房间最小化: %@", userInfo); + } +} + +- (void)hideRoomMiniView { + if (self.miniRoomView) { + [self.miniRoomView hiddenRoomMiniView]; + NSLog(@"[GlobalEventManager] 房间最小化视图已隐藏"); + } +} + +// MARK: - Notification Observers + +- (void)setupNotificationObservers { + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + + // 房间最小化通知 + [center addObserver:self + selector:@selector(onRoomMiniNotification:) + name:kRoomMiniNotificationKey + object:nil]; + + // 配置重载通知 + [center addObserver:self + selector:@selector(onConfigReloadNotification:) + name:@"reloadAfterLoadConfig" + object:nil]; + + // 语言切换通知 + [center addObserver:self + selector:@selector(onLanguageSwitchNotification:) + name:@"kSwitchLanguage" + object:nil]; + + NSLog(@"[GlobalEventManager] 通知监听已设置"); +} + +- (void)onRoomMiniNotification:(NSNotification *)notification { + [self handleRoomMini:notification.userInfo]; +} + +- (void)onConfigReloadNotification:(NSNotification *)notification { + [self handleConfigReload]; +} + +- (void)onLanguageSwitchNotification:(NSNotification *)notification { + [self handleLanguageSwitch:notification]; +} + +// MARK: - Global Notifications Handler + +- (void)handleConfigReload { + NSLog(@"[GlobalEventManager] 配置重载"); + if (self.configReloadCallback) { + self.configReloadCallback(); + } +} + +- (void)handleNewUserRecharge { + NSLog(@"[GlobalEventManager] 新用户充值"); + if (self.newUserRechargeCallback) { + self.newUserRechargeCallback(); + } +} + +- (void)handleAnchorCard:(NSNotification *)notification { + NSLog(@"[GlobalEventManager] 主播卡片通知: %@", notification.userInfo); + // TODO: 实现主播卡片逻辑 +} + +- (void)handleLanguageSwitch:(NSNotification *)notification { + NSLog(@"[GlobalEventManager] 语言切换: %@", notification.userInfo); + // TODO: 实现语言切换逻辑 +} + +// MARK: - User Info + +- (void)handleUserInfoSuccess:(id)userInfo { + NSLog(@"[GlobalEventManager] 用户信息获取成功"); + + // 更新各个 Manager 的用户信息 + if ([userInfo respondsToSelector:@selector(uid)]) { + [[PublicRoomManager sharedManager] initialize]; + [[PublicRoomManager sharedManager] updateUserInfo:userInfo]; + [[RoomBoomManager sharedManager] saveUserInfo:userInfo]; + [[XPSkillCardPlayerManager shareInstance] setUserInfoModel:userInfo]; + } +} + +// MARK: - Social Share + +- (void)registerSocialShareCallback { + // 延迟 2 秒检查社交分享 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [[SocialShareManager sharedManager] checkSocialShareItem]; + NSLog(@"[GlobalEventManager] 社交分享回调已注册"); + }); +} + +// MARK: - NIMSDK Delegate Methods + +#pragma mark - NIMLoginManagerDelegate + +- (void)onLogin:(NIMLoginStep)step { + NSLog(@"[GlobalEventManager] NIMSDK 登录步骤: %ld", (long)step); +} + +- (void)onKickout:(NIMKickReason)code clientType:(NIMLoginClientType)clientType { + NSLog(@"[GlobalEventManager] NIMSDK 被踢出: reason=%ld, clientType=%ld", (long)code, (long)clientType); +} + +- (void)onAutoLoginFailed:(NSError *)error { + NSLog(@"[GlobalEventManager] NIMSDK 自动登录失败: %@", error); +} + +#pragma mark - NIMChatManagerDelegate + +- (void)onRecvMessages:(NSArray *)messages { + NSLog(@"[GlobalEventManager] 收到 %lu 条消息", (unsigned long)messages.count); +} + +#pragma mark - NIMSystemNotificationManagerDelegate + +- (void)onReceiveSystemNotification:(NIMSystemNotification *)notification { + NSLog(@"[GlobalEventManager] 收到系统通知: %@", notification.notificationId); +} + +#pragma mark - NIMBroadcastManagerDelegate + +- (void)onReceiveBroadcastMessage:(NIMBroadcastMessage *)message { + NSLog(@"[GlobalEventManager] 收到广播消息: %@", message.content); +} + +@end diff --git a/YuMi/Modules/NewTabBar/NewTabBarController.swift b/YuMi/Modules/NewTabBar/NewTabBarController.swift new file mode 100644 index 0000000..e146dd3 --- /dev/null +++ b/YuMi/Modules/NewTabBar/NewTabBarController.swift @@ -0,0 +1,197 @@ +// +// NewTabBarController.swift +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +import UIKit + +/// 新的 TabBar 控制器 +/// 只包含 Moment 和 Mine 两个 Tab +class NewTabBarController: UITabBarController { + + // MARK: - Properties + + /// 全局事件管理器 + private var globalEventManager: GlobalEventManager? + + /// 是否已登录 + private var isLoggedIn: Bool = false + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + + // 测试域名配置 + #if DEBUG + APIConfig.testEncryption() + #endif + + setupTabBarAppearance() + setupGlobalManagers() + setupInitialViewControllers() + + NSLog("[NewTabBarController] 初始化完成") + } + + deinit { + globalEventManager?.removeAllDelegates() + NSLog("[NewTabBarController] 已释放") + } + + // MARK: - Setup + + /// 设置 TabBar 外观 + private func setupTabBarAppearance() { + // 自定义 TabBar 样式 + tabBar.tintColor = UIColor(red: 0.2, green: 0.6, blue: 0.86, alpha: 1.0) // 新主色调 + tabBar.unselectedItemTintColor = UIColor(white: 0.6, alpha: 1.0) // 新辅助色 + tabBar.backgroundColor = .white + tabBar.isTranslucent = false + + // 添加顶部分割线 + if #available(iOS 13.0, *) { + let appearance = UITabBarAppearance() + appearance.configureWithOpaqueBackground() + appearance.backgroundColor = .white + appearance.stackedLayoutAppearance.selected.iconColor = tabBar.tintColor + appearance.stackedLayoutAppearance.selected.titleTextAttributes = [ + .foregroundColor: tabBar.tintColor ?? .blue, + .font: UIFont.systemFont(ofSize: 10, weight: .medium) + ] + appearance.stackedLayoutAppearance.normal.titleTextAttributes = [ + .foregroundColor: tabBar.unselectedItemTintColor ?? .gray, + .font: UIFont.systemFont(ofSize: 10) + ] + + tabBar.standardAppearance = appearance + if #available(iOS 15.0, *) { + tabBar.scrollEdgeAppearance = appearance + } + } + + NSLog("[NewTabBarController] TabBar 外观设置完成") + } + + /// 设置全局管理器 + private func setupGlobalManagers() { + globalEventManager = GlobalEventManager.shared() + globalEventManager?.setupSDKDelegates() + + // 设置房间最小化视图 + if let containerView = view { + globalEventManager?.setupRoomMiniView(on: containerView) + } + + // 注册社交分享回调 + globalEventManager?.registerSocialShareCallback() + + NSLog("[NewTabBarController] 全局管理器设置完成") + } + + /// 设置初始 ViewController(未登录状态) + private func setupInitialViewControllers() { + // TODO: 暂时使用空白页面占位 + let blankVC1 = UIViewController() + blankVC1.view.backgroundColor = .white + blankVC1.tabBarItem = createTabBarItem( + title: "动态", + normalImage: "tab_moment_normal", + selectedImage: "tab_moment_selected" + ) + + let blankVC2 = UIViewController() + blankVC2.view.backgroundColor = .white + blankVC2.tabBarItem = createTabBarItem( + title: "我的", + normalImage: "tab_mine_normal", + selectedImage: "tab_mine_selected" + ) + + viewControllers = [blankVC1, blankVC2] + selectedIndex = 0 + + NSLog("[NewTabBarController] 初始 ViewControllers 设置完成") + } + + /// 创建 TabBarItem + /// - Parameters: + /// - title: 标题 + /// - normalImage: 未选中图标名称 + /// - selectedImage: 选中图标名称 + /// - Returns: UITabBarItem + private func createTabBarItem(title: String, normalImage: String, selectedImage: String) -> UITabBarItem { + let item = UITabBarItem( + title: title, + image: UIImage(named: normalImage)?.withRenderingMode(.alwaysOriginal), + selectedImage: UIImage(named: selectedImage)?.withRenderingMode(.alwaysOriginal) + ) + return item + } + + // MARK: - Public Methods + + /// 登录成功后刷新 TabBar + /// - Parameter isLogin: 是否已登录 + @objc func refreshTabBar(isLogin: Bool) { + isLoggedIn = isLogin + + if isLogin { + setupLoggedInViewControllers() + } else { + setupInitialViewControllers() + } + + NSLog("[NewTabBarController] TabBar 已刷新,登录状态: \(isLogin)") + } + + /// 设置登录后的 ViewControllers + private func setupLoggedInViewControllers() { + // TODO: 等 NewMomentViewController 和 NewMineViewController 创建后替换 + // let momentVC = NewMomentViewController() + // let mineVC = NewMineViewController() + + let momentVC = UIViewController() + momentVC.view.backgroundColor = .white + momentVC.tabBarItem = createTabBarItem( + title: "动态", + normalImage: "tab_moment_normal", + selectedImage: "tab_moment_selected" + ) + + let mineVC = UIViewController() + mineVC.view.backgroundColor = .white + mineVC.tabBarItem = createTabBarItem( + title: "我的", + normalImage: "tab_mine_normal", + selectedImage: "tab_mine_selected" + ) + + viewControllers = [momentVC, mineVC] + selectedIndex = 0 + + NSLog("[NewTabBarController] 登录后 ViewControllers 设置完成") + } +} + +// MARK: - UITabBarControllerDelegate + +extension NewTabBarController: UITabBarControllerDelegate { + + override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { + NSLog("[NewTabBarController] 选中 Tab: \(item.title ?? "Unknown")") + } +} + +// MARK: - OC Compatibility + +extension NewTabBarController { + + /// OC 兼容:创建实例的工厂方法 + @objc static func create() -> NewTabBarController { + return NewTabBarController() + } +} diff --git a/YuMi/YuMi-Bridging-Header.h b/YuMi/YuMi-Bridging-Header.h new file mode 100644 index 0000000..9ba34a7 --- /dev/null +++ b/YuMi/YuMi-Bridging-Header.h @@ -0,0 +1,46 @@ +// +// YuMi-Bridging-Header.h +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// +// Swift/OC 混编桥接头文件 + +#ifndef YuMi_Bridging_Header_h +#define YuMi_Bridging_Header_h + +// MARK: - Network +#import "HttpRequestHelper.h" +#import "Api.h" + +// MARK: - Models +#import "UserInfoModel.h" +#import "BaseModel.h" + +// MARK: - Managers +#import "RoomBoomManager.h" +#import "PublicRoomManager.h" +#import "XPSkillCardPlayerManager.h" +#import "RtcManager.h" +#import "IAPManager.h" +#import "SocialShareManager.h" + +// MARK: - Views +#import "XPMiniRoomView.h" +#import "XPRoomMiniManager.h" + +// MARK: - Third Party SDKs +#import +#import + +// MARK: - Utils +#import "YUMIConstant.h" +#import "ClientConfig.h" +#import "AccountInfoStorage.h" + +// MARK: - UI Components +#import "BaseViewController.h" +#import "BaseNavigationController.h" + +#endif /* YuMi_Bridging_Header_h */ diff --git a/white-label-progress.md b/white-label-progress.md new file mode 100644 index 0000000..a845920 --- /dev/null +++ b/white-label-progress.md @@ -0,0 +1,117 @@ +# 白牌项目改造进度 + +## 已完成(Phase 1 - Day 1) + +### 1. 分支管理 +- ✅ 创建 `white-label-base` 分支 +- ✅ Swift 6.2 环境验证通过 + +### 2. API 域名动态生成(XOR + Base64) +- ✅ 创建 `YuMi/Config/APIConfig.swift` + - DEV 环境:自动使用原测试域名 + - RELEASE 环境:使用加密的新域名 `https://api.epartylive.com` + - 加密值生成并验证成功 + - 包含降级方案 + +### 3. Swift/OC 混编配置 +- ✅ 创建 `YuMi/YuMi-Bridging-Header.h` + - 引入必要的 OC 头文件 + - 支持 Network、Models、Managers、Views、SDKs + +### 4. 全局事件管理器 +- ✅ 创建 `YuMi/Global/GlobalEventManager.h/m` + - 迁移 NIMSDK 代理设置 + - 迁移房间最小化逻辑 + - 迁移全局通知处理 + - 迁移 RoomBoomManager 回调 + - 迁移社交分享回调 + +### 5. Swift TabBar 控制器 +- ✅ 创建 `YuMi/Modules/NewTabBar/NewTabBarController.swift` + - 只包含 Moment 和 Mine 两个 Tab + - 自定义新的 TabBar 样式(新主色调) + - 集成 GlobalEventManager + - 支持登录前/后状态切换 + +## 下一步(Phase 1 - Day 2-3) + +### 1. Xcode 项目配置 +- [ ] 将新文件添加到 Xcode 项目 +- [ ] 配置 Build Settings: + - SWIFT_OBJC_BRIDGING_HEADER = YuMi/YuMi-Bridging-Header.h + - DEFINES_MODULE = YES + - SWIFT_VERSION = 5.0 +- [ ] 编译验证 + +### 2. 创建 Moment 模块(OC) +- [ ] 创建 NewMomentViewController.h/m +- [ ] 创建 NewMomentCell.h/m +- [ ] 设计新的 UI 布局(卡片式) +- [ ] 准备 30-40 张新图片资源 + +### 3. 创建 Mine 模块(OC) +- [ ] 创建 NewMineViewController.h/m +- [ ] 创建 NewMineHeaderView.h/m +- [ ] 设计新的 UI 布局(纵向卡片式) +- [ ] 准备 50-60 张新图片资源 + +## 关键技术细节 + +### API 域名加密值 +```swift +Release 域名加密值: +"JTk5PT53YmI=", // https:// +"LD0kYw==", // api. +"KD0sPzk0ISQ7KGMuIiA=", // epartylive.com + +验证:https://api.epartylive.com ✅ +``` + +### 全局逻辑迁移清单 + +| 原位置 (TabbarViewController.m) | 功能 | 迁移目标 | 状态 | +|----------------------------------|------|----------|------| +| Line 156-159 | NIMSDK delegates | GlobalEventManager | ✅ | +| Line 164-167 | 房间最小化通知 | GlobalEventManager | ✅ | +| Line 169-178 | 配置重载通知 | GlobalEventManager | ✅ | +| Line 179-181 | 充值/主播卡片通知 | GlobalEventManager | ✅ | +| Line 190-200 | RoomBoomManager | GlobalEventManager | ✅ | +| Line 202 | 社交回调 | GlobalEventManager | ✅ | + +## 文件清单 + +### 新建文件 +1. `YuMi/Config/APIConfig.swift` +2. `YuMi/YuMi-Bridging-Header.h` +3. `YuMi/Global/GlobalEventManager.h` +4. `YuMi/Global/GlobalEventManager.m` +5. `YuMi/Modules/NewTabBar/NewTabBarController.swift` + +### 待创建文件(Day 2-5) +1. `YuMi/Modules/NewMoments/Controllers/NewMomentViewController.h/m` +2. `YuMi/Modules/NewMoments/Views/NewMomentCell.h/m` +3. `YuMi/Modules/NewMine/Controllers/NewMineViewController.h/m` +4. `YuMi/Modules/NewMine/Views/NewMineHeaderView.h/m` + +## 注意事项 + +### Swift/OC 混编 +- 所有需要在 Swift 中使用的 OC 类都要加入 Bridging Header +- Swift 类要暴露给 OC 需要用 `@objc` 标记 +- Xcode 会自动生成 `YuMi-Swift.h`,OC 代码通过它引入 Swift 类 + +### 编译问题排查 +如果编译失败,检查: +1. Bridging Header 路径是否正确 +2. 所有引用的 OC 类是否存在 +3. Build Settings 中的 DEFINES_MODULE 是否为 YES +4. Swift 版本是否匹配 + +### API 域名测试 +DEBUG 模式下可以调用 `APIConfig.testEncryption()` 验证加密解密是否正常。 + +--- + +**更新时间**: 2025-10-09 +**当前分支**: white-label-base +**进度**: Phase 1 - Day 1 完成