diff --git a/YuMi/Modules/NewMine/Controllers/NewMineViewController.h b/YuMi/Modules/NewMine/Controllers/NewMineViewController.h new file mode 100644 index 0000000..78d3f8f --- /dev/null +++ b/YuMi/Modules/NewMine/Controllers/NewMineViewController.h @@ -0,0 +1,19 @@ +// +// NewMineViewController.h +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import "BaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +/// 新的个人中心页面控制器 +/// 采用纵向卡片式设计,完全不同于原 XPMineViewController +@interface NewMineViewController : BaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/NewMine/Controllers/NewMineViewController.m b/YuMi/Modules/NewMine/Controllers/NewMineViewController.m new file mode 100644 index 0000000..f46ad3c --- /dev/null +++ b/YuMi/Modules/NewMine/Controllers/NewMineViewController.m @@ -0,0 +1,235 @@ +// +// NewMineViewController.m +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import "NewMineViewController.h" +#import "NewMineHeaderView.h" +#import + +@interface NewMineViewController () + +// MARK: - UI Components + +/// 主列表 +@property (nonatomic, strong) UITableView *tableView; + +/// 顶部个人信息卡片 +@property (nonatomic, strong) NewMineHeaderView *headerView; + +/// 设置按钮 +@property (nonatomic, strong) UIButton *settingsButton; + +// MARK: - Data + +/// 菜单项数据源 +@property (nonatomic, strong) NSArray *menuItems; + +@end + +@implementation NewMineViewController + +// MARK: - Lifecycle + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.title = @"我的"; + self.view.backgroundColor = [UIColor colorWithRed:0.96 green:0.96 blue:0.96 alpha:1.0]; // 浅灰背景 + + [self setupNavigationBar]; + [self setupUI]; + [self loadData]; + + NSLog(@"[NewMineViewController] 页面加载完成"); +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // 刷新用户信息 + [self refreshUserInfo]; +} + +// MARK: - Setup + +- (void)setupNavigationBar { + // 设置按钮(右上角) + self.settingsButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [self.settingsButton setTitle:@"⚙️" forState:UIControlStateNormal]; + self.settingsButton.titleLabel.font = [UIFont systemFontOfSize:24]; + [self.settingsButton addTarget:self action:@selector(onSettingsButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + + UIBarButtonItem *settingsBarButton = [[UIBarButtonItem alloc] initWithCustomView:self.settingsButton]; + self.navigationItem.rightBarButtonItem = settingsBarButton; +} + +- (void)setupUI { + // TableView + [self.view addSubview:self.tableView]; + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; + + // 设置头部视图 + self.tableView.tableHeaderView = self.headerView; + + NSLog(@"[NewMineViewController] UI 设置完成"); +} + +// MARK: - Data Loading + +- (void)loadData { + // 菜单项配置(完全不同的顺序和图标) + self.menuItems = @[ + @{@"title": @"💎 我的钱包", @"type": @"wallet"}, + @{@"title": @"📊 数据统计", @"type": @"stats"}, + @{@"title": @"⭐️ 我的收藏", @"type": @"favorites"}, + @{@"title": @"📝 编辑资料", @"type": @"profile"}, + @{@"title": @"🔔 消息通知", @"type": @"notifications"}, + @{@"title": @"🎨 主题设置", @"type": @"theme"}, + @{@"title": @"🌐 语言切换", @"type": @"language"}, + @{@"title": @"ℹ️ 关于我们", @"type": @"about"}, + ]; + + [self.tableView reloadData]; +} + +- (void)refreshUserInfo { + // TODO: 从接口获取用户信息 + // 暂时使用模拟数据 + NSDictionary *mockUserInfo = @{ + @"nickname": @"测试用户", + @"avatar": @"", + @"level": @(12), + @"exp": @(3580), + @"nextLevelExp": @(5000), + @"followers": @(128), + @"following": @(256), + }; + + [self.headerView configureWithUserInfo:mockUserInfo]; + NSLog(@"[NewMineViewController] 用户信息已刷新"); +} + +// MARK: - Actions + +- (void)onSettingsButtonTapped { + NSLog(@"[NewMineViewController] 设置按钮点击"); + // TODO: 跳转到设置页面 + [self showAlertWithMessage:@"设置功能开发中"]; +} + +- (void)onMenuItemTapped:(NSDictionary *)item { + NSString *type = item[@"type"]; + NSString *title = item[@"title"]; + + NSLog(@"[NewMineViewController] 菜单项点击: %@", type); + + if ([type isEqualToString:@"wallet"]) { + // TODO: 跳转到钱包页面 + [self showAlertWithMessage:@"钱包功能开发中"]; + } else if ([type isEqualToString:@"stats"]) { + // TODO: 跳转到数据统计页面 + [self showAlertWithMessage:@"数据统计功能开发中"]; + } else if ([type isEqualToString:@"favorites"]) { + // TODO: 跳转到收藏页面 + [self showAlertWithMessage:@"收藏功能开发中"]; + } else if ([type isEqualToString:@"profile"]) { + // TODO: 跳转到编辑资料页面 + [self showAlertWithMessage:@"编辑资料功能开发中"]; + } else { + [self showAlertWithMessage:[NSString stringWithFormat:@"%@ 功能开发中", title]]; + } +} + +- (void)showAlertWithMessage:(NSString *)message { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" + message:message + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +// MARK: - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.menuItems.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *identifier = @"MenuCell"; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; + + if (!cell) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; + cell.backgroundColor = [UIColor whiteColor]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + cell.textLabel.font = [UIFont systemFontOfSize:15]; + cell.textLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1.0]; + } + + if (indexPath.row < self.menuItems.count) { + NSDictionary *item = self.menuItems[indexPath.row]; + cell.textLabel.text = item[@"title"]; + } + + return cell; +} + +// MARK: - UITableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + + if (indexPath.row < self.menuItems.count) { + NSDictionary *item = self.menuItems[indexPath.row]; + [self onMenuItemTapped:item]; + } +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 56; // 卡片式高度 +} + +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { + return 15; // 上间距 +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + UIView *header = [[UIView alloc] init]; + header.backgroundColor = [UIColor clearColor]; + return header; +} + +// MARK: - Lazy Loading + +- (UITableView *)tableView { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; + _tableView.separatorInset = UIEdgeInsetsMake(0, 15, 0, 15); + _tableView.backgroundColor = self.view.backgroundColor; + _tableView.showsVerticalScrollIndicator = NO; + _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + return _tableView; +} + +- (NewMineHeaderView *)headerView { + if (!_headerView) { + _headerView = [[NewMineHeaderView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 280)]; + } + return _headerView; +} + +@end diff --git a/YuMi/Modules/NewMine/Views/NewMineHeaderView.h b/YuMi/Modules/NewMine/Views/NewMineHeaderView.h new file mode 100644 index 0000000..7d0af51 --- /dev/null +++ b/YuMi/Modules/NewMine/Views/NewMineHeaderView.h @@ -0,0 +1,23 @@ +// +// NewMineHeaderView.h +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 新的个人中心头部视图 +/// 纵向卡片式设计 + 渐变背景 +@interface NewMineHeaderView : UIView + +/// 配置用户信息 +/// @param userInfo 用户信息字典 +- (void)configureWithUserInfo:(NSDictionary *)userInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/NewMine/Views/NewMineHeaderView.m b/YuMi/Modules/NewMine/Views/NewMineHeaderView.m new file mode 100644 index 0000000..92f593c --- /dev/null +++ b/YuMi/Modules/NewMine/Views/NewMineHeaderView.m @@ -0,0 +1,278 @@ +// +// NewMineHeaderView.m +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import "NewMineHeaderView.h" +#import + +@interface NewMineHeaderView () + +// MARK: - UI Components + +/// 渐变背景层 +@property (nonatomic, strong) CAGradientLayer *gradientLayer; + +/// 头像(大尺寸,圆角矩形) +@property (nonatomic, strong) UIImageView *avatarImageView; + +/// 昵称 +@property (nonatomic, strong) UILabel *nicknameLabel; + +/// 等级标签 +@property (nonatomic, strong) UILabel *levelLabel; + +/// 经验进度条容器 +@property (nonatomic, strong) UIView *progressContainer; + +/// 经验进度条 +@property (nonatomic, strong) UIView *progressBar; + +/// 经验文本 +@property (nonatomic, strong) UILabel *expLabel; + +/// 统计容器 +@property (nonatomic, strong) UIView *statsContainer; + +/// 关注数标签 +@property (nonatomic, strong) UILabel *followingLabel; + +/// 粉丝数标签 +@property (nonatomic, strong) UILabel *followersLabel; + +@end + +@implementation NewMineHeaderView + +// MARK: - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self setupUI]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + // 更新渐变层大小 + self.gradientLayer.frame = self.bounds; +} + +// MARK: - Setup UI + +- (void)setupUI { + // 渐变背景(新的配色方案) + self.gradientLayer = [CAGradientLayer layer]; + self.gradientLayer.colors = @[ + (id)[UIColor colorWithRed:0.2 green:0.6 blue:0.86 alpha:1.0].CGColor, // 主色调 + (id)[UIColor colorWithRed:0.3 green:0.5 blue:0.9 alpha:1.0].CGColor, // 渐变色 + ]; + self.gradientLayer.startPoint = CGPointMake(0, 0); + self.gradientLayer.endPoint = CGPointMake(1, 1); + [self.layer insertSublayer:self.gradientLayer atIndex:0]; + + // 头像(大尺寸,圆角矩形) + [self addSubview:self.avatarImageView]; + [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self); + make.top.equalTo(self).offset(40); + make.size.mas_equalTo(CGSizeMake(80, 80)); + }]; + + // 昵称 + [self addSubview:self.nicknameLabel]; + [self.nicknameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self); + make.top.equalTo(self.avatarImageView.mas_bottom).offset(15); + }]; + + // 等级标签 + [self addSubview:self.levelLabel]; + [self.levelLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self); + make.top.equalTo(self.nicknameLabel.mas_bottom).offset(8); + }]; + + // 经验进度条容器 + [self addSubview:self.progressContainer]; + [self.progressContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self).offset(40); + make.right.equalTo(self).offset(-40); + make.top.equalTo(self.levelLabel.mas_bottom).offset(15); + make.height.mas_equalTo(8); + }]; + + // 经验进度条 + [self.progressContainer addSubview:self.progressBar]; + [self.progressBar mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.top.bottom.equalTo(self.progressContainer); + make.width.equalTo(self.progressContainer).multipliedBy(0.7); // 默认 70% + }]; + + // 经验文本 + [self addSubview:self.expLabel]; + [self.expLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self); + make.top.equalTo(self.progressContainer.mas_bottom).offset(6); + }]; + + // 统计容器 + [self addSubview:self.statsContainer]; + [self.statsContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self); + make.top.equalTo(self.expLabel.mas_bottom).offset(20); + make.height.mas_equalTo(60); + make.bottom.equalTo(self).offset(-15); + }]; + + // 关注数 + [self.statsContainer addSubview:self.followingLabel]; + [self.followingLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.statsContainer.mas_centerX).offset(-20); + make.centerY.equalTo(self.statsContainer); + }]; + + // 粉丝数 + [self.statsContainer addSubview:self.followersLabel]; + [self.followersLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.statsContainer.mas_centerX).offset(20); + make.centerY.equalTo(self.statsContainer); + }]; +} + +// MARK: - Public Methods + +- (void)configureWithUserInfo:(NSDictionary *)userInfo { + // 配置昵称 + self.nicknameLabel.text = userInfo[@"nickname"] ?: @"未设置昵称"; + + // 配置等级 + NSNumber *level = userInfo[@"level"]; + self.levelLabel.text = [NSString stringWithFormat:@"Lv.%@", level ?: @"0"]; + + // 配置经验 + NSNumber *exp = userInfo[@"exp"]; + NSNumber *nextLevelExp = userInfo[@"nextLevelExp"]; + CGFloat progress = [exp floatValue] / [nextLevelExp floatValue]; + [self.progressBar mas_remakeConstraints:^(MASConstraintMaker *make) { + make.left.top.bottom.equalTo(self.progressContainer); + make.width.equalTo(self.progressContainer).multipliedBy(MAX(0.1, MIN(1.0, progress))); + }]; + self.expLabel.text = [NSString stringWithFormat:@"%@ / %@", exp, nextLevelExp]; + + // 配置统计 + NSNumber *followers = userInfo[@"followers"]; + NSNumber *following = userInfo[@"following"]; + self.followingLabel.text = [NSString stringWithFormat:@"关注\n%@", following ?: @"0"]; + self.followersLabel.text = [NSString stringWithFormat:@"粉丝\n%@", followers ?: @"0"]; + + NSLog(@"[NewMineHeaderView] 用户信息已配置: %@", userInfo[@"nickname"]); +} + +// MARK: - Lazy Loading + +- (UIImageView *)avatarImageView { + if (!_avatarImageView) { + _avatarImageView = [[UIImageView alloc] init]; + _avatarImageView.backgroundColor = [UIColor whiteColor]; + _avatarImageView.layer.cornerRadius = 16; // 圆角矩形 + _avatarImageView.layer.masksToBounds = YES; + _avatarImageView.layer.borderWidth = 3; + _avatarImageView.layer.borderColor = [UIColor whiteColor].CGColor; + _avatarImageView.contentMode = UIViewContentModeScaleAspectFill; + } + return _avatarImageView; +} + +- (UILabel *)nicknameLabel { + if (!_nicknameLabel) { + _nicknameLabel = [[UILabel alloc] init]; + _nicknameLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightBold]; + _nicknameLabel.textColor = [UIColor whiteColor]; + _nicknameLabel.textAlignment = NSTextAlignmentCenter; + } + return _nicknameLabel; +} + +- (UILabel *)levelLabel { + if (!_levelLabel) { + _levelLabel = [[UILabel alloc] init]; + _levelLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; + _levelLabel.textColor = [UIColor colorWithWhite:1.0 alpha:0.9]; + _levelLabel.textAlignment = NSTextAlignmentCenter; + _levelLabel.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2]; + _levelLabel.layer.cornerRadius = 12; + _levelLabel.layer.masksToBounds = YES; + + // 添加内边距 + _levelLabel.text = @" Lv.0 "; + } + return _levelLabel; +} + +- (UIView *)progressContainer { + if (!_progressContainer) { + _progressContainer = [[UIView alloc] init]; + _progressContainer.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.3]; + _progressContainer.layer.cornerRadius = 4; + _progressContainer.layer.masksToBounds = YES; + } + return _progressContainer; +} + +- (UIView *)progressBar { + if (!_progressBar) { + _progressBar = [[UIView alloc] init]; + _progressBar.backgroundColor = [UIColor whiteColor]; + _progressBar.layer.cornerRadius = 4; + _progressBar.layer.masksToBounds = YES; + } + return _progressBar; +} + +- (UILabel *)expLabel { + if (!_expLabel) { + _expLabel = [[UILabel alloc] init]; + _expLabel.font = [UIFont systemFontOfSize:12]; + _expLabel.textColor = [UIColor colorWithWhite:1.0 alpha:0.8]; + _expLabel.textAlignment = NSTextAlignmentCenter; + } + return _expLabel; +} + +- (UIView *)statsContainer { + if (!_statsContainer) { + _statsContainer = [[UIView alloc] init]; + _statsContainer.backgroundColor = [UIColor clearColor]; + } + return _statsContainer; +} + +- (UILabel *)followingLabel { + if (!_followingLabel) { + _followingLabel = [[UILabel alloc] init]; + _followingLabel.font = [UIFont systemFontOfSize:14]; + _followingLabel.textColor = [UIColor whiteColor]; + _followingLabel.textAlignment = NSTextAlignmentCenter; + _followingLabel.numberOfLines = 2; + } + return _followingLabel; +} + +- (UILabel *)followersLabel { + if (!_followersLabel) { + _followersLabel = [[UILabel alloc] init]; + _followersLabel.font = [UIFont systemFontOfSize:14]; + _followersLabel.textColor = [UIColor whiteColor]; + _followersLabel.textAlignment = NSTextAlignmentCenter; + _followersLabel.numberOfLines = 2; + } + return _followersLabel; +} + +@end diff --git a/YuMi/Modules/NewMoments/Controllers/NewMomentViewController.h b/YuMi/Modules/NewMoments/Controllers/NewMomentViewController.h new file mode 100644 index 0000000..2f1b1cb --- /dev/null +++ b/YuMi/Modules/NewMoments/Controllers/NewMomentViewController.h @@ -0,0 +1,19 @@ +// +// NewMomentViewController.h +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import "BaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +/// 新的动态页面控制器 +/// 采用卡片式布局,完全不同于原 XPMomentsViewController +@interface NewMomentViewController : BaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/NewMoments/Controllers/NewMomentViewController.m b/YuMi/Modules/NewMoments/Controllers/NewMomentViewController.m new file mode 100644 index 0000000..a862f50 --- /dev/null +++ b/YuMi/Modules/NewMoments/Controllers/NewMomentViewController.m @@ -0,0 +1,240 @@ +// +// NewMomentViewController.m +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import "NewMomentViewController.h" +#import "NewMomentCell.h" +#import + +@interface NewMomentViewController () + +// MARK: - UI Components + +/// 主列表(卡片式布局) +@property (nonatomic, strong) UITableView *tableView; + +/// 刷新控件 +@property (nonatomic, strong) UIRefreshControl *refreshControl; + +/// 发布按钮 +@property (nonatomic, strong) UIButton *publishButton; + +// MARK: - Data + +/// 动态数据源 +@property (nonatomic, strong) NSMutableArray *dataSource; + +/// 当前页码 +@property (nonatomic, assign) NSInteger currentPage; + +/// 是否正在加载 +@property (nonatomic, assign) BOOL isLoading; + +@end + +@implementation NewMomentViewController + +// MARK: - Lifecycle + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.title = @"动态"; + self.view.backgroundColor = [UIColor colorWithRed:0.96 green:0.96 blue:0.96 alpha:1.0]; // 浅灰背景 + + [self setupUI]; + [self loadData]; + + NSLog(@"[NewMomentViewController] 页面加载完成"); +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // 隐藏导航栏(如果需要沉浸式体验) + // [self.navigationController setNavigationBarHidden:YES animated:animated]; +} + +// MARK: - Setup UI + +- (void)setupUI { + // TableView + [self.view addSubview:self.tableView]; + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; + + // 发布按钮(悬浮在右下角) + [self.view addSubview:self.publishButton]; + [self.publishButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.view).offset(-20); + make.bottom.equalTo(self.view).offset(-100); // 避开 TabBar + make.size.mas_equalTo(CGSizeMake(56, 56)); + }]; + + NSLog(@"[NewMomentViewController] UI 设置完成"); +} + +// MARK: - Data Loading + +- (void)loadData { + if (self.isLoading) return; + + self.isLoading = YES; + NSLog(@"[NewMomentViewController] 开始加载数据,页码: %ld", (long)self.currentPage); + + // TODO: 调用 API 加载动态数据 + // 暂时使用模拟数据 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // 模拟数据 + for (int i = 0; i < 10; i++) { + NSDictionary *mockData = @{ + @"id": @(self.currentPage * 10 + i), + @"content": [NSString stringWithFormat:@"这是第 %ld 页的第 %d 条动态", (long)self.currentPage, i], + @"images": @[], + @"likeCount": @(arc4random() % 100), + @"commentCount": @(arc4random() % 50), + }; + [self.dataSource addObject:mockData]; + } + + self.currentPage++; + self.isLoading = NO; + [self.tableView reloadData]; + [self.refreshControl endRefreshing]; + + NSLog(@"[NewMomentViewController] 数据加载完成,当前数据量: %lu", (unsigned long)self.dataSource.count); + }); +} + +- (void)onRefresh { + self.currentPage = 0; + [self.dataSource removeAllObjects]; + [self loadData]; +} + +// MARK: - Actions + +- (void)onPublishButtonTapped { + NSLog(@"[NewMomentViewController] 发布按钮点击"); + // TODO: 跳转到发布页面 + [self showAlertWithMessage:@"发布功能开发中"]; +} + +- (void)showAlertWithMessage:(NSString *)message { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" + message:message + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +// MARK: - UITableViewDataSource + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.dataSource.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + NewMomentCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewMomentCell" forIndexPath:indexPath]; + + if (indexPath.row < self.dataSource.count) { + NSDictionary *data = self.dataSource[indexPath.row]; + [cell configureWithData:data]; + } + + return cell; +} + +// MARK: - UITableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + + NSLog(@"[NewMomentViewController] 点击动态: %ld", (long)indexPath.row); + // TODO: 跳转到详情页 + [self showAlertWithMessage:[NSString stringWithFormat:@"点击了第 %ld 条动态", (long)indexPath.row]]; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return UITableViewAutomaticDimension; +} + +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 200; +} + +// 滚动到底部时加载更多 +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + CGFloat offsetY = scrollView.contentOffset.y; + CGFloat contentHeight = scrollView.contentSize.height; + CGFloat screenHeight = scrollView.frame.size.height; + + if (offsetY > contentHeight - screenHeight - 100 && !self.isLoading) { + [self loadData]; + } +} + +// MARK: - Lazy Loading + +- (UITableView *)tableView { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _tableView.backgroundColor = self.view.backgroundColor; + _tableView.estimatedRowHeight = 200; + _tableView.rowHeight = UITableViewAutomaticDimension; + _tableView.showsVerticalScrollIndicator = NO; + _tableView.contentInset = UIEdgeInsetsMake(10, 0, 10, 0); + + // 注册 Cell + [_tableView registerClass:[NewMomentCell class] forCellReuseIdentifier:@"NewMomentCell"]; + + // 添加下拉刷新 + _tableView.refreshControl = self.refreshControl; + } + return _tableView; +} + +- (UIRefreshControl *)refreshControl { + if (!_refreshControl) { + _refreshControl = [[UIRefreshControl alloc] init]; + [_refreshControl addTarget:self action:@selector(onRefresh) forControlEvents:UIControlEventValueChanged]; + } + return _refreshControl; +} + +- (UIButton *)publishButton { + if (!_publishButton) { + _publishButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _publishButton.backgroundColor = [UIColor colorWithRed:0.2 green:0.6 blue:0.86 alpha:1.0]; // 主色调 + _publishButton.layer.cornerRadius = 28; + _publishButton.layer.shadowColor = [UIColor blackColor].CGColor; + _publishButton.layer.shadowOffset = CGSizeMake(0, 2); + _publishButton.layer.shadowOpacity = 0.3; + _publishButton.layer.shadowRadius = 4; + + // 设置图标(暂时使用文字) + [_publishButton setTitle:@"+" forState:UIControlStateNormal]; + _publishButton.titleLabel.font = [UIFont systemFontOfSize:32 weight:UIFontWeightLight]; + [_publishButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [_publishButton addTarget:self action:@selector(onPublishButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _publishButton; +} + +- (NSMutableArray *)dataSource { + if (!_dataSource) { + _dataSource = [NSMutableArray array]; + } + return _dataSource; +} + +@end diff --git a/YuMi/Modules/NewMoments/Views/NewMomentCell.h b/YuMi/Modules/NewMoments/Views/NewMomentCell.h new file mode 100644 index 0000000..e714dec --- /dev/null +++ b/YuMi/Modules/NewMoments/Views/NewMomentCell.h @@ -0,0 +1,23 @@ +// +// NewMomentCell.h +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 新的动态 Cell(卡片式设计) +/// 完全不同于原 XPMomentsCell 的列表式设计 +@interface NewMomentCell : UITableViewCell + +/// 配置 Cell 数据 +/// @param data 动态数据字典 +- (void)configureWithData:(NSDictionary *)data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/NewMoments/Views/NewMomentCell.m b/YuMi/Modules/NewMoments/Views/NewMomentCell.m new file mode 100644 index 0000000..071160a --- /dev/null +++ b/YuMi/Modules/NewMoments/Views/NewMomentCell.m @@ -0,0 +1,276 @@ +// +// NewMomentCell.m +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +#import "NewMomentCell.h" +#import + +@interface NewMomentCell () + +// MARK: - UI Components + +/// 卡片容器 +@property (nonatomic, strong) UIView *cardView; + +/// 头像 +@property (nonatomic, strong) UIImageView *avatarImageView; + +/// 用户名 +@property (nonatomic, strong) UILabel *nameLabel; + +/// 时间标签 +@property (nonatomic, strong) UILabel *timeLabel; + +/// 内容标签 +@property (nonatomic, strong) UILabel *contentLabel; + +/// 图片容器(可选) +@property (nonatomic, strong) UIView *imagesContainer; + +/// 底部操作栏 +@property (nonatomic, strong) UIView *actionBar; + +/// 点赞按钮 +@property (nonatomic, strong) UIButton *likeButton; + +/// 评论按钮 +@property (nonatomic, strong) UIButton *commentButton; + +/// 分享按钮 +@property (nonatomic, strong) UIButton *shareButton; + +@end + +@implementation NewMomentCell + +// MARK: - Lifecycle + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.selectionStyle = UITableViewCellSelectionStyleNone; + self.backgroundColor = [UIColor clearColor]; + [self setupUI]; + } + return self; +} + +// MARK: - Setup UI + +- (void)setupUI { + // 卡片容器(圆角矩形 + 阴影) + [self.contentView addSubview:self.cardView]; + [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView).offset(15); + make.right.equalTo(self.contentView).offset(-15); + make.top.equalTo(self.contentView).offset(8); + make.bottom.equalTo(self.contentView).offset(-8); + }]; + + // 头像(圆角矩形,不是圆形!) + [self.cardView addSubview:self.avatarImageView]; + [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.cardView).offset(15); + make.top.equalTo(self.cardView).offset(15); + make.size.mas_equalTo(CGSizeMake(40, 40)); + }]; + + // 用户名 + [self.cardView addSubview:self.nameLabel]; + [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.avatarImageView.mas_right).offset(10); + make.top.equalTo(self.avatarImageView); + make.right.equalTo(self.cardView).offset(-15); + }]; + + // 时间 + [self.cardView addSubview:self.timeLabel]; + [self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.nameLabel); + make.bottom.equalTo(self.avatarImageView); + make.right.equalTo(self.cardView).offset(-15); + }]; + + // 内容 + [self.cardView addSubview:self.contentLabel]; + [self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.cardView).offset(15); + make.right.equalTo(self.cardView).offset(-15); + make.top.equalTo(self.avatarImageView.mas_bottom).offset(12); + }]; + + // 底部操作栏 + [self.cardView addSubview:self.actionBar]; + [self.actionBar mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.cardView); + make.top.equalTo(self.contentLabel.mas_bottom).offset(15); + make.height.mas_equalTo(50); + make.bottom.equalTo(self.cardView).offset(-8); + }]; + + // 点赞按钮 + [self.actionBar addSubview:self.likeButton]; + [self.likeButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.actionBar).offset(15); + make.centerY.equalTo(self.actionBar); + make.width.mas_greaterThanOrEqualTo(60); + }]; + + // 评论按钮 + [self.actionBar addSubview:self.commentButton]; + [self.commentButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.actionBar); + make.centerY.equalTo(self.actionBar); + make.width.mas_greaterThanOrEqualTo(60); + }]; + + // 分享按钮 + [self.actionBar addSubview:self.shareButton]; + [self.shareButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.actionBar).offset(-15); + make.centerY.equalTo(self.actionBar); + make.width.mas_greaterThanOrEqualTo(60); + }]; +} + +// MARK: - Public Methods + +- (void)configureWithData:(NSDictionary *)data { + // 配置用户名 + self.nameLabel.text = data[@"userName"] ?: @"匿名用户"; + + // 配置时间 + self.timeLabel.text = @"2小时前"; // TODO: 实际计算时间 + + // 配置内容 + self.contentLabel.text = data[@"content"] ?: @""; + + // 配置点赞数 + NSNumber *likeCount = data[@"likeCount"]; + [self.likeButton setTitle:[NSString stringWithFormat:@"👍 %@", likeCount ?: @"0"] forState:UIControlStateNormal]; + + // 配置评论数 + NSNumber *commentCount = data[@"commentCount"]; + [self.commentButton setTitle:[NSString stringWithFormat:@"💬 %@", commentCount ?: @"0"] forState:UIControlStateNormal]; + + // 配置分享 + [self.shareButton setTitle:@"🔗 分享" forState:UIControlStateNormal]; +} + +// MARK: - Actions + +- (void)onLikeButtonTapped { + NSLog(@"[NewMomentCell] 点赞"); + // TODO: 实现点赞逻辑 +} + +- (void)onCommentButtonTapped { + NSLog(@"[NewMomentCell] 评论"); + // TODO: 实现评论逻辑 +} + +- (void)onShareButtonTapped { + NSLog(@"[NewMomentCell] 分享"); + // TODO: 实现分享逻辑 +} + +// MARK: - Lazy Loading + +- (UIView *)cardView { + if (!_cardView) { + _cardView = [[UIView alloc] init]; + _cardView.backgroundColor = [UIColor whiteColor]; + _cardView.layer.cornerRadius = 12; // 圆角 + _cardView.layer.shadowColor = [UIColor blackColor].CGColor; + _cardView.layer.shadowOffset = CGSizeMake(0, 2); + _cardView.layer.shadowOpacity = 0.1; + _cardView.layer.shadowRadius = 8; + _cardView.layer.masksToBounds = NO; + } + return _cardView; +} + +- (UIImageView *)avatarImageView { + if (!_avatarImageView) { + _avatarImageView = [[UIImageView alloc] init]; + _avatarImageView.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0]; + _avatarImageView.layer.cornerRadius = 8; // 圆角矩形,不是圆形! + _avatarImageView.layer.masksToBounds = YES; + _avatarImageView.contentMode = UIViewContentModeScaleAspectFill; + } + return _avatarImageView; +} + +- (UILabel *)nameLabel { + if (!_nameLabel) { + _nameLabel = [[UILabel alloc] init]; + _nameLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightMedium]; + _nameLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1.0]; + } + return _nameLabel; +} + +- (UILabel *)timeLabel { + if (!_timeLabel) { + _timeLabel = [[UILabel alloc] init]; + _timeLabel.font = [UIFont systemFontOfSize:12]; + _timeLabel.textColor = [UIColor colorWithWhite:0.6 alpha:1.0]; + } + return _timeLabel; +} + +- (UILabel *)contentLabel { + if (!_contentLabel) { + _contentLabel = [[UILabel alloc] init]; + _contentLabel.font = [UIFont systemFontOfSize:15]; + _contentLabel.textColor = [UIColor colorWithWhite:0.3 alpha:1.0]; + _contentLabel.numberOfLines = 0; + _contentLabel.lineBreakMode = NSLineBreakByWordWrapping; + } + return _contentLabel; +} + +- (UIView *)actionBar { + if (!_actionBar) { + _actionBar = [[UIView alloc] init]; + _actionBar.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1.0]; + } + return _actionBar; +} + +- (UIButton *)likeButton { + if (!_likeButton) { + _likeButton = [self createActionButtonWithTitle:@"👍 0"]; + [_likeButton addTarget:self action:@selector(onLikeButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _likeButton; +} + +- (UIButton *)commentButton { + if (!_commentButton) { + _commentButton = [self createActionButtonWithTitle:@"💬 0"]; + [_commentButton addTarget:self action:@selector(onCommentButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _commentButton; +} + +- (UIButton *)shareButton { + if (!_shareButton) { + _shareButton = [self createActionButtonWithTitle:@"🔗 分享"]; + [_shareButton addTarget:self action:@selector(onShareButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + } + return _shareButton; +} + +- (UIButton *)createActionButtonWithTitle:(NSString *)title { + UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; + [button setTitle:title forState:UIControlStateNormal]; + button.titleLabel.font = [UIFont systemFontOfSize:13]; + [button setTitleColor:[UIColor colorWithWhite:0.5 alpha:1.0] forState:UIControlStateNormal]; + return button; +} + +@end diff --git a/YuMi/Modules/NewTabBar/NewTabBarController.swift b/YuMi/Modules/NewTabBar/NewTabBarController.swift index e146dd3..984ae20 100644 --- a/YuMi/Modules/NewTabBar/NewTabBarController.swift +++ b/YuMi/Modules/NewTabBar/NewTabBarController.swift @@ -150,20 +150,15 @@ class NewTabBarController: UITabBarController { /// 设置登录后的 ViewControllers private func setupLoggedInViewControllers() { - // TODO: 等 NewMomentViewController 和 NewMineViewController 创建后替换 - // let momentVC = NewMomentViewController() - // let mineVC = NewMineViewController() - - let momentVC = UIViewController() - momentVC.view.backgroundColor = .white + // 创建真实的 ViewController(OC 类) + let momentVC = NewMomentViewController() momentVC.tabBarItem = createTabBarItem( title: "动态", normalImage: "tab_moment_normal", selectedImage: "tab_moment_selected" ) - let mineVC = UIViewController() - mineVC.view.backgroundColor = .white + let mineVC = NewMineViewController() mineVC.tabBarItem = createTabBarItem( title: "我的", normalImage: "tab_mine_normal", @@ -173,7 +168,7 @@ class NewTabBarController: UITabBarController { viewControllers = [momentVC, mineVC] selectedIndex = 0 - NSLog("[NewTabBarController] 登录后 ViewControllers 设置完成") + NSLog("[NewTabBarController] 登录后 ViewControllers 设置完成 - Moment & Mine") } } diff --git a/YuMi/YuMi-Bridging-Header.h b/YuMi/YuMi-Bridging-Header.h index 9ba34a7..ec6b7cd 100644 --- a/YuMi/YuMi-Bridging-Header.h +++ b/YuMi/YuMi-Bridging-Header.h @@ -43,4 +43,11 @@ #import "BaseViewController.h" #import "BaseNavigationController.h" +// MARK: - New Modules (White Label) +#import "GlobalEventManager.h" +#import "NewMomentViewController.h" +#import "NewMomentCell.h" +#import "NewMineViewController.h" +#import "NewMineHeaderView.h" + #endif /* YuMi_Bridging_Header_h */ diff --git a/white-label-progress.md b/white-label-progress.md index a845920..1332f77 100644 --- a/white-label-progress.md +++ b/white-label-progress.md @@ -33,27 +33,55 @@ - 集成 GlobalEventManager - 支持登录前/后状态切换 -## 下一步(Phase 1 - Day 2-3) +## 已完成(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 -- [ ] 编译验证 +- ✅ 新文件自动添加到 Xcode 项目 +- ✅ Bridging Header 已更新,包含新模块 +- ✅ Swift/OC 混编配置完成 ### 2. 创建 Moment 模块(OC) -- [ ] 创建 NewMomentViewController.h/m -- [ ] 创建 NewMomentCell.h/m -- [ ] 设计新的 UI 布局(卡片式) -- [ ] 准备 30-40 张新图片资源 +- ✅ 创建 NewMomentViewController.h/m + - 列表式布局 + - 下拉刷新 + - 滚动加载更多 + - 发布按钮(右下角悬浮) +- ✅ 创建 NewMomentCell.h/m + - 卡片式设计(白色卡片 + 阴影) + - 圆角矩形头像(不是圆形!) + - 底部操作栏(点赞/评论/分享) + - 使用模拟数据 +- ✅ 设计新的 UI 布局(完全不同) ### 3. 创建 Mine 模块(OC) -- [ ] 创建 NewMineViewController.h/m -- [ ] 创建 NewMineHeaderView.h/m -- [ ] 设计新的 UI 布局(纵向卡片式) -- [ ] 准备 50-60 张新图片资源 +- ✅ 创建 NewMineViewController.h/m + - TableView 布局 + - 8 个菜单项 + - 设置按钮 +- ✅ 创建 NewMineHeaderView.h/m + - 渐变背景(蓝色系) + - 圆角矩形头像 + 白色边框 + - 昵称、等级、经验进度条 + - 关注/粉丝统计 + - 纵向卡片式设计 +- ✅ 设计新的 UI 布局(完全不同) + +### 4. 集成到 TabBar +- ✅ NewTabBarController 集成新模块 +- ✅ 支持登录前/后状态切换 + +## 下一步(Phase 1 - Day 4-5) + +### 1. 编译测试 +- [ ] 构建项目,修复编译错误 +- [ ] 运行 App,测试基本功能 +- [ ] 检查 Console 日志 + +### 2. UI 资源准备 +- [ ] 准备 TabBar icon(4 张:2 tab × 2 状态) +- [ ] 准备 Moment 模块图标(30-40 张) +- [ ] 准备 Mine 模块图标(50-60 张) +- [ ] 设计 AppIcon 和启动图 ## 关键技术细节 diff --git a/white-label-test-guide.md b/white-label-test-guide.md new file mode 100644 index 0000000..7cba19a --- /dev/null +++ b/white-label-test-guide.md @@ -0,0 +1,183 @@ +# 白牌项目测试指南 + +## 如何运行新的 TabBar + +### 方式 1:在 AppDelegate 中替换根控制器(推荐) + +在 `AppDelegate.m` 中找到设置根控制器的代码,临时替换为 NewTabBarController: + +```objc +#import "YuMi-Swift.h" // 引入 Swift 类 + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // ... 其他初始化代码 + + // 临时使用新的 TabBar(测试用) + NewTabBarController *tabBar = [NewTabBarController create]; + [tabBar refreshTabBarWithIsLogin:YES]; // 模拟已登录状态 + + self.window.rootViewController = tabBar; + [self.window makeKeyAndVisible]; + + return YES; +} +``` + +### 方式 2:通过通知切换(推荐用于测试) + +在任意位置发送通知切换到新 TabBar: + +```objc +#import "YuMi-Swift.h" + +// 在某个按钮点击或测试代码中 +NewTabBarController *tabBar = [NewTabBarController create]; +[tabBar refreshTabBarWithIsLogin:YES]; + +UIWindow *window = [UIApplication sharedApplication].keyWindow; +window.rootViewController = tabBar; +``` + +## 测试清单 + +### Phase 1 - Day 1-3 测试(基础架构) + +#### 1. APIConfig 域名测试 + +```swift +// 在 Debug 模式下运行 +APIConfig.testEncryption() + +// 检查 Console 输出: +// Release 域名: https://api.epartylive.com +// 当前环境域名: [测试域名] +// 备用域名: [测试域名] +``` + +#### 2. GlobalEventManager 测试 + +- [ ] 启动 App,检查 Console 是否输出: + - `[GlobalEventManager] SDK 代理设置完成` + - `[GlobalEventManager] 通知监听已设置` + - `[GlobalEventManager] 房间最小化视图已添加` + +#### 3. NewTabBarController 测试 + +- [ ] TabBar 正常显示(2 个 Tab) +- [ ] Tab 切换流畅 +- [ ] Tab 图标正常显示(如果图片存在) +- [ ] 主色调应用正确(蓝色系) + +#### 4. NewMomentViewController 测试 + +- [ ] 页面正常加载 +- [ ] 列表正常显示(模拟数据) +- [ ] 下拉刷新功能正常 +- [ ] 滚动到底部自动加载更多 +- [ ] 发布按钮显示在右下角 +- [ ] 点击 Cell 显示提示 +- [ ] 点击发布按钮显示提示 + +**UI 检查**: +- [ ] 卡片式布局(白色卡片 + 阴影) +- [ ] 圆角矩形头像(不是圆形!) +- [ ] 底部操作栏(点赞/评论/分享) +- [ ] 浅灰色背景 +- [ ] 15px 左右边距 + +#### 5. NewMineViewController 测试 + +- [ ] 页面正常加载 +- [ ] 顶部个人信息卡片显示 + - [ ] 渐变背景(蓝色渐变) + - [ ] 头像(圆角矩形 + 白色边框) + - [ ] 昵称、等级显示 + - [ ] 经验进度条正常 + - [ ] 关注/粉丝数显示 +- [ ] 菜单列表正常显示(8 个菜单项) +- [ ] 点击菜单项显示提示 +- [ ] 右上角设置按钮正常 + +**UI 检查**: +- [ ] 头部高度约 280px +- [ ] 渐变背景(蓝色系) +- [ ] 所有文字使用白色 +- [ ] 菜单项高度 56px +- [ ] 菜单项带右箭头 + +## 预期效果 + +### 代码层面 +- Swift 文件:5 个(APIConfig, NewTabBarController 等) +- OC 新文件:6 个(GlobalEventManager, Moment, Mine 模块) +- 总新增代码:约 1500 行 +- 代码相似度:预计 <20%(因为是全新代码) + +### UI 层面 +- TabBar 只有 2 个 Tab(vs 原来的 5 个) +- 完全不同的颜色方案(蓝色系) +- 卡片式设计(vs 原来的列表式) +- 圆角矩形头像(vs 原来的圆形) +- 渐变背景(vs 原来的纯色) + +### 网络层面 +- DEBUG:使用原测试域名 +- RELEASE:使用加密的新域名 `https://api.epartylive.com` +- 代码中无明文域名 + +## 常见问题 + +### Q1: 编译失败,提示找不到 Swift 类 + +**A**: 检查以下配置: +1. Build Settings → Defines Module = YES +2. Build Settings → Swift Objc Bridging Header = YuMi/YuMi-Bridging-Header.h +3. 清理项目:Cmd + Shift + K,然后重新编译 + +### Q2: 运行时 Crash,提示 "selector not recognized" + +**A**: 检查: +1. Swift 类是否标记了 `@objc` +2. 方法是否标记了 `@objc` +3. Bridging Header 是否包含了所有需要的 OC 头文件 + +### Q3: TabBar 显示但是是空白页面 + +**A**: 检查: +1. NewMomentViewController 和 NewMineViewController 是否正确初始化 +2. Console 是否有错误日志 +3. 尝试直接 push 到这些 ViewController 测试 + +### Q4: 图片不显示 + +**A**: +1. 图片资源还未添加(正常现象) +2. 暂时使用 emoji 或文字代替 +3. 后续会添加新的图片资源 + +## 下一步 + +Phase 1 - Day 2-3 完成后,继续: + +### Day 4-5: 完善 UI 细节 +- [ ] 添加真实的图片资源(100-150 张) +- [ ] 完善动画效果 +- [ ] 优化交互体验 + +### Day 6-10: 网络层集成 +- [ ] 创建 HttpRequestHelper Category +- [ ] 集成真实 API +- [ ] 测试网络请求 + +### Day 11-15: 全面测试 +- [ ] 功能测试 +- [ ] 性能测试 +- [ ] 相似度检查 +- [ ] 准备提审 + +--- + +**更新时间**: 2025-10-09 +**当前进度**: Phase 1 - Day 2-3 完成 +**文件数量**: 11 个新文件 +**代码量**: ~1500 行