feat: 添加动态发布功能及相关文档
主要变更: 1. 新增 EPImageUploader.swift 和 EPProgressHUD.swift,提供图片批量上传和进度显示功能。 2. 新建 EPMomentAPISwiftHelper.swift,封装动态 API 的 Swift 版本。 3. 更新 EPMomentPublishViewController,集成新上传功能并实现发布成功通知。 4. 创建多个文档,包括实施报告、检查清单和快速使用指南,详细记录功能实现和使用方法。 5. 更新 Bridging Header,确保 Swift 和 Objective-C 代码的互操作性。 此功能旨在提升用户体验,简化动态发布流程,并提供清晰的文档支持。
This commit is contained in:
@@ -8,38 +8,29 @@
|
||||
|
||||
#import "EPMineViewController.h"
|
||||
#import "EPMineHeaderView.h"
|
||||
#import "EPMomentCell.h"
|
||||
#import <Masonry/Masonry.h>
|
||||
#import "Api+Moments.h"
|
||||
#import "EPMomentListView.h"
|
||||
#import "EPMineAPIHelper.h"
|
||||
#import "AccountInfoStorage.h"
|
||||
#import "UserInfoModel.h"
|
||||
#import "MomentsInfoModel.h"
|
||||
#import <MJExtension/MJExtension.h>
|
||||
|
||||
@interface EPMineViewController () <UITableViewDelegate, UITableViewDataSource>
|
||||
@interface EPMineViewController ()
|
||||
|
||||
// MARK: - UI Components
|
||||
|
||||
/// 主列表(显示用户动态)
|
||||
@property (nonatomic, strong) UITableView *tableView;
|
||||
/// 动态列表视图(复用 EPMomentListView)
|
||||
@property (nonatomic, strong) EPMomentListView *momentListView;
|
||||
|
||||
/// 顶部个人信息卡片
|
||||
@property (nonatomic, strong) EPMineHeaderView *headerView;
|
||||
|
||||
// MARK: - Data
|
||||
|
||||
/// 用户动态数据源
|
||||
@property (nonatomic, strong) NSMutableArray<MomentsInfoModel *> *momentsData;
|
||||
|
||||
/// 当前页码
|
||||
@property (nonatomic, assign) NSInteger currentPage;
|
||||
|
||||
/// 是否正在加载
|
||||
@property (nonatomic, assign) BOOL isLoading;
|
||||
|
||||
/// 用户信息模型
|
||||
@property (nonatomic, strong) UserInfoModel *userInfo;
|
||||
|
||||
/// API Helper
|
||||
@property (nonatomic, strong) EPMineAPIHelper *apiHelper;
|
||||
|
||||
@end
|
||||
|
||||
@implementation EPMineViewController
|
||||
@@ -49,13 +40,7 @@
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
self.momentsData = [NSMutableArray array];
|
||||
self.currentPage = 1;
|
||||
self.isLoading = NO;
|
||||
|
||||
[self setupUI];
|
||||
[self loadUserInfo];
|
||||
[self loadUserMoments];
|
||||
|
||||
NSLog(@"[EPMineViewController] 个人主页加载完成");
|
||||
}
|
||||
@@ -63,27 +48,17 @@
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// 注意:当前 ViewController 没有包装在 NavigationController 中
|
||||
// 如果未来需要导航栏,应该在 TabBarController 中包装 UINavigationController
|
||||
// 隐藏导航栏
|
||||
[self.navigationController setNavigationBarHidden:YES animated:animated];
|
||||
|
||||
// 每次显示时加载最新数据
|
||||
[self loadUserDetailInfo];
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
- (void)setupGradientBackground {
|
||||
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
|
||||
gradientLayer.frame = self.view.bounds;
|
||||
gradientLayer.colors = @[
|
||||
(id)[UIColor colorWithRed:0.3 green:0.2 blue:0.6 alpha:1.0].CGColor, // 深紫 #4C3399
|
||||
(id)[UIColor colorWithRed:0.2 green:0.3 blue:0.8 alpha:1.0].CGColor // 蓝 #3366CC
|
||||
];
|
||||
gradientLayer.startPoint = CGPointMake(0, 0);
|
||||
gradientLayer.endPoint = CGPointMake(1, 1);
|
||||
[self.view.layer insertSublayer:gradientLayer atIndex:0];
|
||||
}
|
||||
|
||||
- (void)setupUI {
|
||||
// 先设置纯色背景作为兜底,避免白色闪烁
|
||||
self.view.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.97 alpha:1.0];
|
||||
self.view.backgroundColor = [UIColor clearColor];
|
||||
|
||||
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:kImage(@"vc_bg")];
|
||||
bgImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
@@ -94,7 +69,7 @@
|
||||
}];
|
||||
|
||||
[self setupHeaderView];
|
||||
[self setupTableView];
|
||||
[self setupMomentListView];
|
||||
|
||||
NSLog(@"[EPMineViewController] UI 设置完成");
|
||||
}
|
||||
@@ -105,140 +80,56 @@
|
||||
[self.view addSubview:self.headerView];
|
||||
|
||||
[self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(20);
|
||||
make.left.right.equalTo(self.view);
|
||||
make.top.equalTo(self.view).offset(20);
|
||||
make.leading.trailing.equalTo(self.view);
|
||||
make.height.equalTo(@300);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setupTableView {
|
||||
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
|
||||
self.tableView.delegate = self;
|
||||
self.tableView.dataSource = self;
|
||||
self.tableView.backgroundColor = [UIColor clearColor];
|
||||
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||
self.tableView.showsVerticalScrollIndicator = NO;
|
||||
- (void)setupMomentListView {
|
||||
[self.view addSubview:self.momentListView];
|
||||
|
||||
// 注册动态 cell(复用 EPMomentCell)
|
||||
[self.tableView registerClass:[EPMomentCell class] forCellReuseIdentifier:@"EPMomentCell"];
|
||||
|
||||
[self.view addSubview:self.tableView];
|
||||
|
||||
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
[self.momentListView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.headerView.mas_bottom).offset(10);
|
||||
make.left.right.equalTo(self.view);
|
||||
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
|
||||
make.leading.trailing.bottom.equalTo(self.view);
|
||||
}];
|
||||
|
||||
// 添加下拉刷新
|
||||
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
|
||||
[refreshControl addTarget:self action:@selector(refreshData) forControlEvents:UIControlEventValueChanged];
|
||||
self.tableView.refreshControl = refreshControl;
|
||||
}
|
||||
|
||||
// MARK: - Data Loading
|
||||
|
||||
- (void)loadUserInfo {
|
||||
- (void)loadUserDetailInfo {
|
||||
NSString *uid = [[AccountInfoStorage instance] getUid];
|
||||
if (!uid.length) {
|
||||
NSLog(@"[EPMineViewController] 未登录,无法获取用户信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 调用真实 API 获取用户信息
|
||||
[Api getUserInfo:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||||
if (code == 200 && data.data) {
|
||||
self.userInfo = [UserInfoModel mj_objectWithKeyValues:data.data];
|
||||
|
||||
// 更新头部视图
|
||||
NSDictionary *userInfoDict = @{
|
||||
@"nickname": self.userInfo.nick ?: @"未设置昵称",
|
||||
@"avatar": self.userInfo.avatar ?: @"",
|
||||
@"uid": self.userInfo.uid > 0 ? @(self.userInfo.uid).stringValue : @"",
|
||||
@"followers": @(self.userInfo.fansNum),
|
||||
@"following": @(self.userInfo.followNum),
|
||||
};
|
||||
|
||||
[self.headerView updateWithUserInfo:userInfoDict];
|
||||
NSLog(@"[EPMineViewController] 用户信息加载成功: %@", self.userInfo.nick);
|
||||
} else {
|
||||
NSLog(@"[EPMineViewController] 用户信息加载失败: %@", msg);
|
||||
}
|
||||
} uid:uid];
|
||||
}
|
||||
|
||||
- (void)refreshUserInfo {
|
||||
[self loadUserInfo];
|
||||
}
|
||||
|
||||
- (void)loadUserMoments {
|
||||
if (self.isLoading) return;
|
||||
|
||||
NSString *uid = [[AccountInfoStorage instance] getUid];
|
||||
if (!uid.length) {
|
||||
NSLog(@"[EPMineViewController] 未登录,无法获取用户动态");
|
||||
return;
|
||||
}
|
||||
|
||||
self.isLoading = YES;
|
||||
NSString *page = [NSString stringWithFormat:@"%ld", (long)self.currentPage];
|
||||
|
||||
// 调用获取用户动态的 API(这里先用通用的动态列表 API)
|
||||
[Api momentsRecommendList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||||
self.isLoading = NO;
|
||||
[self.refreshControl endRefreshing];
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[self.apiHelper getUserDetailInfoWithUid:uid completion:^(UserInfoModel * _Nullable userInfo) {
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
self.userInfo = userInfo;
|
||||
|
||||
if (code == 200 && data.data) {
|
||||
NSArray *list = [MomentsInfoModel mj_objectArrayWithKeyValuesArray:data.data];
|
||||
if (list.count > 0) {
|
||||
[self.momentsData addObjectsFromArray:list];
|
||||
self.currentPage++;
|
||||
[self.tableView reloadData];
|
||||
NSLog(@"[EPMineViewController] 用户动态加载成功,新增 %lu 条", (unsigned long)list.count);
|
||||
}
|
||||
} else {
|
||||
NSLog(@"[EPMineViewController] 用户动态加载失败: %@", msg);
|
||||
}
|
||||
} page:page pageSize:@"10" types:@"0,2"];
|
||||
}
|
||||
|
||||
- (void)refreshData {
|
||||
self.currentPage = 1;
|
||||
[self.momentsData removeAllObjects];
|
||||
|
||||
// 手动下拉刷新时才更新用户信息
|
||||
[self loadUserInfo];
|
||||
[self loadUserMoments];
|
||||
}
|
||||
|
||||
// MARK: - UITableView DataSource
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return self.momentsData.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
EPMomentCell *cell = [tableView dequeueReusableCellWithIdentifier:@"EPMomentCell" forIndexPath:indexPath];
|
||||
cell.backgroundColor = [UIColor clearColor];
|
||||
|
||||
if (indexPath.row < self.momentsData.count) {
|
||||
[cell configureWithModel:self.momentsData[indexPath.row]];
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return 200; // 根据实际内容调整
|
||||
}
|
||||
|
||||
// MARK: - UITableView Delegate
|
||||
|
||||
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
// 滚动到底部自动加载更多
|
||||
if (indexPath.row == self.momentsData.count - 1 && !self.isLoading) {
|
||||
[self loadUserMoments];
|
||||
}
|
||||
// 更新头部视图
|
||||
NSDictionary *userInfoDict = @{
|
||||
@"nickname": userInfo.nick ?: @"未设置昵称",
|
||||
@"avatar": userInfo.avatar ?: @"",
|
||||
@"uid": userInfo.uid > 0 ? @(userInfo.uid).stringValue : @"",
|
||||
@"followers": @(userInfo.fansNum),
|
||||
@"following": @(userInfo.followNum),
|
||||
};
|
||||
[self.headerView updateWithUserInfo:userInfoDict];
|
||||
|
||||
// 使用本地数组模式显示用户动态
|
||||
[self.momentListView loadWithDynamicInfo:userInfo.dynamicInfo refreshCallback:^{
|
||||
[self loadUserDetailInfo];
|
||||
}];
|
||||
|
||||
NSLog(@"[EPMineViewController] 用户详情加载成功: %@ (动态数: %lu)",
|
||||
userInfo.nick, (unsigned long)userInfo.dynamicInfo.count);
|
||||
|
||||
} failure:^(NSInteger code, NSString * _Nullable msg) {
|
||||
NSLog(@"[EPMineViewController] 用户详情加载失败: code=%ld, msg=%@", (long)code, msg);
|
||||
}];
|
||||
}
|
||||
|
||||
// MARK: - Lazy Loading
|
||||
@@ -250,8 +141,25 @@
|
||||
return _headerView;
|
||||
}
|
||||
|
||||
- (UIRefreshControl *)refreshControl {
|
||||
return self.tableView.refreshControl;
|
||||
- (EPMomentListView *)momentListView {
|
||||
if (!_momentListView) {
|
||||
_momentListView = [[EPMomentListView alloc] initWithFrame:CGRectZero];
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
_momentListView.onSelectMoment = ^(NSInteger index) {
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
NSLog(@"[EPMineViewController] 点击了第 %ld 条动态", (long)index);
|
||||
// TODO: 跳转到动态详情页
|
||||
};
|
||||
}
|
||||
return _momentListView;
|
||||
}
|
||||
|
||||
- (EPMineAPIHelper *)apiHelper {
|
||||
if (!_apiHelper) {
|
||||
_apiHelper = [[EPMineAPIHelper alloc] init];
|
||||
}
|
||||
return _apiHelper;
|
||||
}
|
||||
|
||||
@end
|
||||
|
Reference in New Issue
Block a user