Phase 1 Day 1: 基础架构搭建

- 创建 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
  * 新的主色调和样式
This commit is contained in:
edwinQQQ
2025-10-09 17:48:07 +08:00
parent cebe158f7b
commit e980cd5553
7 changed files with 778 additions and 4 deletions

View File

@@ -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)",

View File

@@ -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

View File

@@ -0,0 +1,71 @@
//
// GlobalEventManager.h
// YuMi
//
// Created by AI on 2025-10-09.
// Copyright © 2025 YuMi. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
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

View File

@@ -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 <NIMSDK/NIMSDK.h>
@interface GlobalEventManager () <NIMLoginManagerDelegate, NIMChatManagerDelegate, NIMSystemNotificationManagerDelegate, NIMBroadcastManagerDelegate>
// 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<NIMMessage *> *)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

View File

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

View File

@@ -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 <NIMSDK/NIMSDK.h>
#import <AFNetworking/AFNetworking.h>
// 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 */

117
white-label-progress.md Normal file
View File

@@ -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 完成