Files
peko-ios/YuMi/Modules/YMMine/View/Medals/MedalsRankViewController.m

581 lines
21 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MedalsRankViewController.m
// YuMi
//
// Created by P on 2025/6/20.
//
#import "MedalsRankViewController.h"
#import "MedalsPresenter.h"
#import "MedalsViewController.h"
#import "UserInfoModel.h"
#import <MJRefresh/MJRefresh.h>
#import "DJDKMIMOMColor.h"
@interface MedalsRankListCell : UITableViewCell
@property (nonatomic, strong) UILabel *indexLabel;
@property (nonatomic, strong) NetImageView *avatarImageView;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *countLabel;
+ (void)registerTo:(UITableView *)tableView;
+ (instancetype)cellFor:(UITableView *)tableView atIndexPath:(NSIndexPath *)index;
- (void)updateCell:(MedalsRankUserModel *)userModel atIndex:(NSInteger)index;
@end
@implementation MedalsRankListCell
+ (NSString *)cellID {
return NSStringFromClass([MedalsRankListCell class]);
}
+ (void)registerTo:(UITableView *)tableView {
[tableView registerClass:[self class] forCellReuseIdentifier:[self cellID]];
}
+ (instancetype)cellFor:(UITableView *)tableView atIndexPath:(NSIndexPath *)index {
MedalsRankListCell *cell = [tableView dequeueReusableCellWithIdentifier:[self cellID] forIndexPath:index];
return cell;
}
- (void)updateCell:(MedalsRankUserModel *)userModel atIndex:(NSInteger)index {
self.avatarImageView.imageUrl = userModel.avatar;
self.nameLabel.text = userModel.nick;
self.indexLabel.text = @(index + 4).stringValue;
self.countLabel.text = @(userModel.medalCount).stringValue;
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.backgroundColor = [UIColor clearColor];
self.contentView.backgroundColor = [UIColor clearColor];
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.indexLabel = [UILabel labelInitWithText:@"" font:kFontMedium(14) textColor:[UIColor whiteColor]];
[self.contentView addSubview:self.indexLabel];
[self.indexLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.contentView);
make.leading.mas_equalTo(18);
}];
NetImageConfig *config = [[NetImageConfig alloc] init];
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
self.avatarImageView = [[NetImageView alloc] initWithConfig:config];
[self.avatarImageView setCornerRadius:47/2];
[self.contentView addSubview:self.avatarImageView];
[self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.contentView);
make.leading.mas_equalTo(self.indexLabel.mas_trailing).offset(16);
make.size.mas_equalTo(CGSizeMake(47, 47));
}];
self.nameLabel = [UILabel labelInitWithText:@"" font:kFontSemibold(15) textColor:[UIColor whiteColor]];
[self.contentView addSubview:self.nameLabel];
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).offset(6);
make.top.mas_equalTo(self.avatarImageView);
}];
UIImageView *rankIcon = [[UIImageView alloc] initWithImage:kImage(@"medals_rank")];
[self.contentView addSubview:rankIcon];
[rankIcon mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).offset(6);
make.bottom.mas_equalTo(self.avatarImageView);
make.size.mas_equalTo(CGSizeMake(10, 14));
}];
self.countLabel = [UILabel labelInitWithText:@"" font:kFontMedium(14) textColor:[UIColor whiteColor]];
[self.contentView addSubview:self.countLabel];
[self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(rankIcon.mas_trailing).offset(6);
make.centerY.mas_equalTo(rankIcon);
}];
UILabel *detailLabel = [UILabel labelInitWithText:YMLocalizedString(@"20.20.61_text_13")
font:kFontRegular(12)
textColor:[UIColor colorWithWhite:1 alpha:0.6]];
[self.contentView addSubview:detailLabel];
[detailLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.trailing.mas_equalTo(self.contentView).offset(-28);
make.centerY.mas_equalTo(self.contentView);
}];
UIImageView *arrow = [[UIImageView alloc] initWithImage:kImage(@"grey_right_arrow")];
[self.contentView addSubview:arrow];
[arrow mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.contentView);
make.trailing.mas_equalTo(self.contentView).offset(-15);
make.size.mas_equalTo(CGSizeMake(15, 15));
}];
}
return self;
}
@end
@interface MedalsRankTopView : UIView
@property (nonatomic, assign) NSInteger topLevel;
@property (nonatomic, strong) MedalsRankUserModel *userModel;
@property (nonatomic, copy) void (^onTapBlock)(MedalsRankUserModel *userModel);
@end
@implementation MedalsRankTopView
{
NetImageView *avatarImageView;
UIImageView *decorationImageView;
UILabel *nameLabel;
UILabel *honorLabel;
UIImageView *honorImageView;
UIImageView *medalIconImageView;
UILabel *medalCountLabel;
UIStackView *medalCountStack;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NetImageConfig *config = [[NetImageConfig alloc] init];
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
avatarImageView = [[NetImageView alloc] initWithConfig:config];
[avatarImageView setCornerRadius:50];
[self addSubview:avatarImageView];
[avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self);
make.size.mas_equalTo(CGSizeMake(100, 100));
}];
decorationImageView = [[UIImageView alloc] init];
[self addSubview:decorationImageView];
[decorationImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self);
}];
honorImageView = [[UIImageView alloc] initWithImage:kImage(@"medals_rank_namebar")];
[self addSubview:honorImageView];
[honorImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self);
make.bottom.mas_equalTo(self).offset(6);
}];
honorLabel = [UILabel labelInitWithText:YMLocalizedString(@"20.20.61_text_12")
font:kFontSemibold(12)
textColor:UIColorFromRGB(0xfff27b)];
[self addSubview:honorLabel];
[honorLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(honorImageView);
}];
nameLabel = [UILabel labelInitWithText:@"" font:kFontSemibold(15) textColor:UIColorFromRGB(0xffffff)];
[self addSubview:nameLabel];
medalIconImageView = [[UIImageView alloc] initWithImage:kImage(@"medals_rank")];
medalCountLabel = [UILabel labelInitWithText:@"0" font:kFontMedium(14) textColor:UIColorFromRGB(0xffffff)];
medalCountStack = [[UIStackView alloc] initWithArrangedSubviews:@[
medalIconImageView,
medalCountLabel
]];
[self addSubview:medalCountStack];
honorLabel.hidden = YES;
honorImageView.hidden = YES;
// 添加点击手势
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapTopView)];
[self addGestureRecognizer:tapGesture];
self.userInteractionEnabled = YES;
}
return self;
}
- (void)didTapTopView {
if (self.onTapBlock && self.userModel) {
self.onTapBlock(self.userModel);
}
}
- (void)setTopLevel:(NSInteger)topLevel {
_topLevel = topLevel;
NSString *imagePath = @"";
NSInteger nameTopOffset = 0;
NSInteger bottomOffset = 0;
switch (topLevel) {
case 1:
imagePath = @"medals_rank_top_1";
honorLabel.hidden = NO;
honorImageView.hidden = NO;
nameTopOffset = 8;
bottomOffset = 40;
break;
case 2:
imagePath = @"medals_rank_top_2";
nameTopOffset = -4;
bottomOffset = 20;
break;
case 3:
imagePath = @"medals_rank_top_3";
nameTopOffset = -4;
bottomOffset = 20;
break;
default:
break;
}
[nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self);
make.top.mas_equalTo(self.mas_bottom).offset(nameTopOffset);
}];
[medalCountStack mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self);
make.top.mas_equalTo(nameLabel.mas_bottom).offset(4);
}];
if (![NSString isEmpty:imagePath]) {
decorationImageView.image = kImage(imagePath);
}
}
- (void)setUserModel:(MedalsRankUserModel *)userModel {
_userModel = userModel;
if (userModel) {
avatarImageView.imageUrl = userModel.avatar;
nameLabel.text = userModel.nick;
medalCountLabel.text = @(userModel.medalCount).stringValue;
}
}
@end
@interface MedalsRankViewController () <MedalsPresenterProtocol, UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UILabel *indexLabel;
@property (nonatomic, strong) NetImageView *avatarImageView;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *countLabel;
@property (nonatomic, strong) MedalsRankTopView *topOne;
@property (nonatomic, strong) MedalsRankTopView *topTwo;
@property (nonatomic, strong) MedalsRankTopView *topThree;
@property (nonatomic, strong) MedalsRankUserModel *mineRankModel;
@property (nonatomic, strong) NSMutableArray <MedalsRankUserModel *>*rankList;
@property (nonatomic, strong) UITableView *rankTableView;
// 分页相关属性
@property (nonatomic, assign) NSInteger currentPage;
@end
@implementation MedalsRankViewController
- (BOOL)isHiddenNavBar {
return YES;
}
- (MedalsPresenter *)createPresenter {
return [[MedalsPresenter alloc] init];
}
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化分页
self.currentPage = 1;
[self setupUI];
[self setupRefresh];
[self loadData];
}
#pragma mark -
- (void)setupUI {
self.view.backgroundColor = UIColorFromRGB(0x1B0043);
[self setupTopArea];
[self setupRankList];
[self setupBottomArea];
[self setupNavigationBar];
}
- (void)setupNavigationBar {
[self setupCustomNavigationBar:^{}
title:YMLocalizedString(@"20.20.61_text_11")
titleColor:[UIColor whiteColor]];
}
- (void)setupTopArea {
UIImageView *topBG = [[UIImageView alloc] initWithImage:kImage(@"medals_rank_top_bg")];
topBG.frame = CGRectMake(0, 0, KScreenWidth, kGetScaleWidth(270));
[self.view addSubview:topBG];
self.topOne = [self rankTopView:1];
self.topTwo = [self rankTopView:2];
self.topThree = [self rankTopView:3];
// 设置点击回调
__weak typeof(self) weakSelf = self;
self.topOne.onTapBlock = ^(MedalsRankUserModel *userModel) {
[weakSelf handleTopViewTap:userModel];
};
self.topTwo.onTapBlock = ^(MedalsRankUserModel *userModel) {
[weakSelf handleTopViewTap:userModel];
};
self.topThree.onTapBlock = ^(MedalsRankUserModel *userModel) {
[weakSelf handleTopViewTap:userModel];
};
[self.view addSubview:self.topOne];
[self.view addSubview:self.topTwo];
[self.view addSubview:self.topThree];
[self.topOne mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.view).offset(95);
make.centerX.mas_equalTo(self.view);
make.size.mas_equalTo(CGSizeMake(209, 145));
}];
[self.topTwo mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(topBG.mas_bottom);
make.leading.mas_equalTo(self.view).offset(25);
make.size.mas_equalTo(CGSizeMake(145, 145));
}];
[self.topThree mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(topBG.mas_bottom);
make.trailing.mas_equalTo(self.view).offset(-25);
make.size.mas_equalTo(CGSizeMake(145, 145));
}];
}
- (void)setupRankList {
[self.view addSubview:self.rankTableView];
CGFloat height = 84;
[self.rankTableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.topTwo.mas_bottom).offset(40);
make.bottom.mas_equalTo(self.view).offset(-height);
make.leading.trailing.mas_equalTo(self.view);
}];
}
- (void)setupBottomArea {
CGFloat height = 84;
UIView *bottomArea = [[UIView alloc] initWithFrame:CGRectMake(0, KScreenHeight - height, KScreenWidth, height)];
[bottomArea addGradientBackgroundWithColors:@[
UIColorFromRGB(0x3d1479),
UIColorFromRGB(0x1c0044),
] startPoint:CGPointMake(0.5, 0) endPoint:CGPointMake(0.5, 1) cornerRadius:0];
[self.view addSubview:bottomArea];
self.indexLabel = [UILabel labelInitWithText:@"" font:kFontMedium(14) textColor:[UIColor whiteColor]];
[bottomArea addSubview:self.indexLabel];
[self.indexLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(bottomArea);
make.leading.mas_equalTo(18);
}];
NetImageConfig *config = [[NetImageConfig alloc] init];
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
self.avatarImageView = [[NetImageView alloc] initWithConfig:config];
[self.avatarImageView setCornerRadius:47/2];
[bottomArea addSubview:self.avatarImageView];
[self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(bottomArea);
make.leading.mas_equalTo(self.indexLabel.mas_trailing).offset(16);
make.size.mas_equalTo(CGSizeMake(47, 47));
}];
self.nameLabel = [UILabel labelInitWithText:@"" font:kFontSemibold(15) textColor:[UIColor whiteColor]];
[bottomArea addSubview:self.nameLabel];
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).offset(6);
make.top.mas_equalTo(self.avatarImageView);
}];
UIImageView *rankIcon = [[UIImageView alloc] initWithImage:kImage(@"medals_rank")];
[bottomArea addSubview:rankIcon];
[rankIcon mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).offset(6);
make.bottom.mas_equalTo(self.avatarImageView);
make.size.mas_equalTo(CGSizeMake(10, 14));
}];
self.countLabel = [UILabel labelInitWithText:@"" font:kFontMedium(14) textColor:[UIColor whiteColor]];
[bottomArea addSubview:self.countLabel];
[self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(rankIcon.mas_trailing).offset(6);
make.centerY.mas_equalTo(rankIcon);
}];
}
- (void)setupRefresh {
// 设置下拉刷新
MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(headerRefresh)];
header.stateLabel.font = [UIFont systemFontOfSize:10.0];
header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:10.0];
header.stateLabel.textColor = [DJDKMIMOMColor secondTextColor];
header.lastUpdatedTimeLabel.textColor = [DJDKMIMOMColor secondTextColor];
self.rankTableView.mj_header = header;
// // 设置上拉加载更多
// MJRefreshBackNormalFooter *footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(footerRefresh)];
// footer.stateLabel.textColor = [DJDKMIMOMColor secondTextColor];
// footer.stateLabel.font = [UIFont systemFontOfSize:10.0];
// self.rankTableView.mj_footer = footer;
}
#pragma mark -
- (void)loadData {
[self.presenter rankList:self.currentPage];
}
- (void)rankListSuccess:(MedalsRankModel *)model {
// 结束刷新状态
[self.rankTableView.mj_header endRefreshing];
[self.rankTableView.mj_footer endRefreshing];
NSInteger currentRank = 4; // 从第4名开始计算前三名已经处理
if (model) {
// 第一页时更新个人信息和前三名
if (self.currentPage == 1) {
self.mineRankModel = model.mine;
self.avatarImageView.imageUrl = self.mineRankModel.avatar;
self.nameLabel.text = self.mineRankModel.nick;
self.indexLabel.text = self.mineRankModel.rank == 0 ? @"10+" : @(self.mineRankModel.rank).stringValue;
self.countLabel.text = @(self.mineRankModel.medalCount).stringValue;
self.rankList = [NSMutableArray array];
// 处理前三名显示
for (MedalsRankUserModel *user in model.rankList) {
if (user.rank == 1) {
self.topOne.userModel = user;
} else if (user.rank == 2) {
self.topTwo.userModel = user;
} else if (user.rank == 3) {
self.topThree.userModel = user;
} else {
[self.rankList addObject:user];
currentRank = MAX(currentRank, user.rank + 1);
}
}
} else {
// 非第一页,追加数据(排除前三名)
for (MedalsRankUserModel *user in model.rankList) {
if (user.rank > 3) {
[self.rankList addObject:user];
}
}
}
// 检查是否还有更多数据
if (model.rankList.count < [self.presenter rankListSize]) {
if (self.currentPage == 1) {
// 补充数据至 10 个rankList 中应有 7 个,因为前三名在 top 视图中)
NSInteger targetCount = 7; // 总共10个减去前3名
while (self.rankList.count < targetCount) {
MedalsRankUserModel *emptyUser = [[MedalsRankUserModel alloc] init];
emptyUser.rank = currentRank;
emptyUser.uid = 0;
emptyUser.avatar = @"";
emptyUser.nick = @"--";
emptyUser.medalCount = 0;
[self.rankList addObject:emptyUser];
currentRank++;
}
}
[self.rankTableView.mj_footer endRefreshingWithNoMoreData];
} else {
[self.rankTableView.mj_footer resetNoMoreData];
}
[self.rankTableView reloadData];
}
}
- (void)rankListFailure {
// 结束刷新状态
[self.rankTableView.mj_header endRefreshing];
[self.rankTableView.mj_footer endRefreshing];
// 如果是加载更多失败,页码需要回退
if (self.currentPage > 1) {
self.currentPage--;
}
}
#pragma mark - UITableView DataSource & Delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.rankList.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 70;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MedalsRankListCell *cell = [MedalsRankListCell cellFor:tableView atIndexPath:indexPath];
MedalsRankUserModel *model = [self.rankList xpSafeObjectAtIndex:indexPath.row];
[cell updateCell:model atIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 取消选中高亮效果
[tableView deselectRowAtIndexPath:indexPath animated:YES];
MedalsRankUserModel *model = [self.rankList xpSafeObjectAtIndex:indexPath.row];
[self handleTopViewTap:model];
}
- (void)handleTopViewTap:(MedalsRankUserModel *)model {
if (model) {
UserInfoModel *userInfo = [[UserInfoModel alloc] init];
userInfo.uid = model.uid;
userInfo.avatar = model.avatar;
userInfo.nick = model.nick;
MedalsViewController *vc = [[MedalsViewController alloc] initForOtherMedals:userInfo];
[self.navigationController pushViewController:vc animated:YES];
}
}
#pragma mark -
- (MedalsRankTopView *)rankTopView:(NSInteger)rank {
MedalsRankTopView *topView = [[MedalsRankTopView alloc] initWithFrame:CGRectMake(0, 0, rank == 1 ? 209 : 145, 145)];
topView.topLevel = rank;
return topView;
}
- (UITableView *)rankTableView {
if (!_rankTableView) {
_rankTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_rankTableView.delegate = self;
_rankTableView.dataSource = self;
_rankTableView.backgroundColor = [UIColor clearColor];
[MedalsRankListCell registerTo:_rankTableView];
}
return _rankTableView;
}
#pragma mark - 刷新方法
- (void)headerRefresh {
self.currentPage = 1;
[self loadData];
}
- (void)footerRefresh {
self.currentPage++;
[self loadData];
}
@end