Files
real-e-party-iOS/YuMi/Modules/NewMoments/Controllers/NewMomentViewController.m
edwinQQQ 98fb194718 Phase 1 Day 2-3: 创建 Moment 和 Mine 模块
- 创建 NewMomentViewController(OC)
  * 列表式布局 + 下拉刷新 + 滚动加载
  * 发布按钮(右下角悬浮)
  * 使用模拟数据

- 创建 NewMomentCell(OC)
  * 卡片式设计(白色卡片 + 阴影)
  * 圆角矩形头像(不是圆形!)
  * 底部操作栏(点赞/评论/分享)

- 创建 NewMineViewController(OC)
  * TableView 布局 + 8 个菜单项
  * 设置按钮(右上角)

- 创建 NewMineHeaderView(OC)
  * 渐变背景(蓝色系)
  * 圆角矩形头像 + 白色边框
  * 昵称、等级、经验进度条
  * 关注/粉丝统计
  * 纵向卡片式设计

- 集成到 NewTabBarController
  * 使用真实的 ViewController 替换占位
  * 支持登录前/后状态切换

- 更新 Bridging Header
  * 添加新模块的 OC 类引用

- 创建测试指南文档
  * 如何运行新 TabBar
  * 测试清单
  * 常见问题解答

新增文件:
- NewMomentViewController.h/m
- NewMomentCell.h/m
- NewMineViewController.h/m
- NewMineHeaderView.h/m
- white-label-test-guide.md

代码量:约 1500 行
2025-10-09 17:54:32 +08:00

241 lines
7.8 KiB
Objective-C

//
// NewMomentViewController.m
// YuMi
//
// Created by AI on 2025-10-09.
// Copyright © 2025 YuMi. All rights reserved.
//
#import "NewMomentViewController.h"
#import "NewMomentCell.h"
#import <Masonry/Masonry.h>
@interface NewMomentViewController () <UITableViewDelegate, UITableViewDataSource>
// 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