Files
peko-ios/YuMi/Modules/YMMine/View/Medals/MedalsWearingViewController.m
edwinQQQ 99db078b62 feat(勋章): 新增多等级高亮功能并优化勋章展示逻辑
refactor(勋章排行): 重构排行榜分页加载和刷新逻辑

fix(会话): 优化官方账号判断逻辑和跳转处理

style(UI): 调整勋章排行榜和游戏菜单UI布局

chore: 更新Podfile配置和bitcode框架列表
2025-07-03 19:35:17 +08:00

402 lines
15 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.

//
// MedalsWearingViewController.m
// YuMi
//
// Created by P on 2025/6/19.
//
#import "MedalsWearingViewController.h"
#import "MedalsPresenter.h"
#import "MedalsWearingListCollectionViewCell.h"
#import "MedalsWearingControlCollectionViewCell.h"
#import "MJRefresh.h"
#import "UserInfoModel.h"
#import "XPWebViewController.h"
@interface MedalsWearingViewController () <UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, MedalsPresenterProtocol>
@property (nonatomic, strong) UIView *dismissArea;
@property (nonatomic, strong) UIView *contentArea;
@property (nonatomic, strong) UIImageView *controlAreaBG;
@property (nonatomic, strong) UICollectionView *controlAreaCollectionView;
@property (nonatomic, strong) UICollectionView *medalsAreaCollectionView;
@property (nonatomic, assign) NSInteger medalsAreaPage;
@property (nonatomic, copy) NSArray <MedalVo *> *useMedalsVo;
@property (nonatomic, copy) NSArray <MedalVo *> *allMedalsVo;
@property (nonatomic, copy) NSDictionary *vipSeatDic;
@property (nonatomic, assign) NSInteger minVipLevelForSeats;
// 数据变化标记
@property (nonatomic, assign) BOOL hasDataChanged;
@end
@implementation MedalsWearingViewController
- (MedalsPresenter *)createPresenter {
return [[MedalsPresenter alloc] init];
}
- (BOOL)isHiddenNavBar {
return YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.medalsAreaPage = 1;
self.hasDataChanged = NO; // 初始化数据变化标记
[self setupUI];
[self setupRefresh];
[self loadMedals];
}
- (void)setupUI {
self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
[self.view addSubview:self.dismissArea];
[self.view addSubview:self.contentArea];
[self.contentArea addSubview:self.controlAreaBG];
[self.contentArea addSubview:self.controlAreaCollectionView];
[self.controlAreaBG mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(46);
make.leading.trailing.mas_equalTo(self.contentArea).inset(14);
make.height.mas_equalTo(kGetScaleWidth(147));
}];
[self.controlAreaCollectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self.controlAreaBG).insets(UIEdgeInsetsMake(15, 15, 0, 15));
}];
[self.contentArea addSubview:self.medalsAreaCollectionView];
[self.medalsAreaCollectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.controlAreaBG.mas_bottom).offset(14);
make.leading.trailing.mas_equalTo(self.controlAreaBG);
make.bottom.mas_equalTo(self.contentArea);
}];
}
- (void)setupRefresh {
MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(headerRefresh)];
header.lastUpdatedTimeLabel.hidden = YES;
header.stateLabel.hidden = YES;
self.medalsAreaCollectionView.mj_header = header;
MJRefreshBackNormalFooter *footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(footerRefresh)];
self.medalsAreaCollectionView.mj_footer = footer;
}
- (void)loadMedals {
[self.presenter mineAllMedals:self.medalsAreaPage];
}
#pragma mark - User Actions
- (void)handleTapGesture:(id)sender {
[self dismissViewController];
}
- (void)dismissViewController {
// 如果数据发生了变化,触发回调
if (self.hasDataChanged && self.dataChangedCallback) {
self.dataChangedCallback();
}
[self.view removeFromSuperview];
[self removeFromParentViewController];
}
#pragma mark -
- (void)mineAllMedalsSuccess:(MineAllMedalModel *)model {
[self endRefresh];
// 重置最低VIP level
self.minVipLevelForSeats = 0;
if (model.allMedals.count < [self.presenter pageSize]) {
[self.medalsAreaCollectionView.mj_footer endRefreshingWithNoMoreData];
} else {
[self.medalsAreaCollectionView.mj_footer resetNoMoreData];
}
self.vipSeatDic = model.vipMedalSeatVos;
self.allMedalsVo = model.allMedals;
self.useMedalsVo = model.useMedals;
[self.controlAreaCollectionView reloadData];
[self.medalsAreaCollectionView reloadData];
}
- (void)mineAllMedalsFailure {
[self endRefresh];
// 如果是加载更多失败,页码需要回退
if (self.medalsAreaPage > 1) {
self.medalsAreaPage--;
}
}
- (void)useMedalSuccess {
// 标记数据已变化
self.hasDataChanged = YES;
[self headerRefresh];
}
- (void)userMedalsFailure {
}
- (void)endRefresh {
[self.medalsAreaCollectionView.mj_header endRefreshing];
[self.medalsAreaCollectionView.mj_footer endRefreshing];
}
#pragma mark -
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if (collectionView == self.controlAreaCollectionView) {
return 10;
} else if (collectionView == self.medalsAreaCollectionView) {
return self.allMedalsVo.count;
}
return 0;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
if (collectionView == self.controlAreaCollectionView) {
MedalsWearingControlCollectionViewCell *cell = [MedalsWearingControlCollectionViewCell cellFor:collectionView atIndexPath:indexPath];
// 找到 vipSeatDic 的最小 key判断当前 index 是否适用显示 VIP level
NSInteger minSeatIndex = NSIntegerMax;
for (NSString *key in self.vipSeatDic.allKeys) {
NSInteger seatIndex = [key integerValue];
if (seatIndex < minSeatIndex) {
minSeatIndex = seatIndex;
}
}
// 当前 cell 的座位索引从1开始
NSInteger currentSeatIndex = indexPath.row + 1;
// 只有当前座位索引大于等于最小座位索引时,才处理 VIP level 逻辑
if (minSeatIndex != NSIntegerMax && currentSeatIndex >= minSeatIndex) {
// 根据 vipSeatDic 数据判断是否调用 updateVIPLevel
NSString *seatKey = [NSString stringWithFormat:@"%ld", (long)currentSeatIndex];
NSArray *vipLevels = self.vipSeatDic[seatKey];
if (vipLevels && vipLevels.count > 0) {
// 找到最低的 VIP level
NSInteger currentMinVipLevel = NSIntegerMax;
for (NSNumber *levelNum in vipLevels) {
NSInteger level = [levelNum integerValue];
if (level < currentMinVipLevel) {
currentMinVipLevel = level;
}
}
if (currentMinVipLevel != NSIntegerMax) {
// 更新全局最低VIP level
self.minVipLevelForSeats = currentMinVipLevel;
[cell updateVIPLevel:currentMinVipLevel];
}
} else if (self.minVipLevelForSeats >= 0) {
// 当前座位没有对应的vip seat vo但之前已经有最低VIP level则沿用
[cell updateVIPLevel:self.minVipLevelForSeats];
}
} else {
// 如果当前座位索引小于最小座位索引,则不显示 VIP level
[cell updateVIPLevel:-1];
}
MedalVo *medalVo = [self.useMedalsVo xpSafeObjectAtIndex:indexPath.row];
[cell updateMedal:medalVo];
return cell;
} else if (collectionView == self.medalsAreaCollectionView) {
MedalsWearingListCollectionViewCell *cell = [MedalsWearingListCollectionViewCell cellFor:collectionView atIndexPath:indexPath];
[cell updateCell:[self.allMedalsVo xpSafeObjectAtIndex:indexPath.row]];
return cell;
}
return nil;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (collectionView == self.controlAreaCollectionView) {
// 当前 cell 的座位索引从1开始
NSInteger currentSeatIndex = indexPath.row + 1;
NSString *seatKey = [NSString stringWithFormat:@"%ld", (long)currentSeatIndex];
NSArray *vipLevels = self.vipSeatDic[seatKey];
// 计算当前位置显示的VIP level
NSInteger displayedVipLevel = -1;
// 找到 vipSeatDic 的最小 key
NSInteger minSeatIndex = NSIntegerMax;
for (NSString *key in self.vipSeatDic.allKeys) {
NSInteger seatIndex = [key integerValue];
if (seatIndex < minSeatIndex) {
minSeatIndex = seatIndex;
}
}
// 判断当前位置的VIP level
if (minSeatIndex != NSIntegerMax && currentSeatIndex >= minSeatIndex) {
if (vipLevels && vipLevels.count > 0) {
// 找到最低的 VIP level
NSInteger currentMinVipLevel = NSIntegerMax;
for (NSNumber *levelNum in vipLevels) {
NSInteger level = [levelNum integerValue];
if (level < currentMinVipLevel) {
currentMinVipLevel = level;
}
}
if (currentMinVipLevel != NSIntegerMax) {
displayedVipLevel = currentMinVipLevel;
}
} else if (self.minVipLevelForSeats > 0) {
displayedVipLevel = self.minVipLevelForSeats;
}
}
UserVipInfoVo *vipVo = self.userInfo.userVipInfoVO;
if (vipVo) {
if (vipVo.vipLevel < displayedVipLevel) {
TTAlertConfig * config = [[TTAlertConfig alloc] init];
// config.actionStyle = 0;
config.title = YMLocalizedString(@"20.20.61_text_17");
config.message = YMLocalizedString(@"20.20.61_text_15");
TTAlertButtonConfig *confirmCongif = config.confirmButtonConfig;
confirmCongif.title = YMLocalizedString(@"20.20.61_text_18");
config.confirmButtonConfig = confirmCongif;
@kWeakify(self);
[TTPopup alertWithConfig:config confirmHandler:^{
@kStrongify(self);
XPWebViewController * webVC =[[XPWebViewController alloc] initWithRoomUID:nil];
webVC.url = URLWithType(kVIP);
[self.navigationController pushViewController:webVC animated:YES];
} cancelHandler:^{
}];
}
}
NSLog(@"[MedalsWearing] 点击位置: %ld, 座位索引: %ld, 显示VIP等级: %ld, VIP数据: %@, 最小座位索引: %ld, 全局最低VIP: %ld",
(long)indexPath.row,
(long)currentSeatIndex,
(long)displayedVipLevel,
vipLevels ?: @"",
(long)minSeatIndex,
(long)self.minVipLevelForSeats);
} else if (collectionView == self.medalsAreaCollectionView) {
if (self.useMedalsVo.count >= 10) {
TTAlertConfig * config = [[TTAlertConfig alloc] init];
config.actionStyle = 0;
config.title = YMLocalizedString(@"UserDetail_CP_Toast_0");
config.message = YMLocalizedString(@"20.20.61_text_16");
[TTPopup alertWithConfig:config confirmHandler:^{
} cancelHandler:^{
}];
} else {
MedalVo *vo = [self.allMedalsVo xpSafeObjectAtIndex:indexPath.row];
if (vo) {
[self.presenter updateMedalUseStatus:vo.id isUse:!vo.useStatus];
}
}
}
}
// 处理 cell 的可见性
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
if ([cell isKindOfClass:[MedalsWearingListCollectionViewCell class]]) {
[(MedalsWearingListCollectionViewCell *)cell willDisplay];
}
}
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
if ([cell isKindOfClass:[MedalsWearingListCollectionViewCell class]]) {
[(MedalsWearingListCollectionViewCell *)cell didEndDisplaying];
}
}
#pragma mark - Refresh Actions
- (void)headerRefresh {
self.medalsAreaPage = 1;
[self loadMedals];
}
- (void)footerRefresh {
self.medalsAreaPage++;
[self loadMedals];
}
#pragma mark - Lazy Load
- (UIView *)dismissArea {
if (!_dismissArea) {
_dismissArea = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, kGetScaleWidth(192))];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
[_dismissArea addGestureRecognizer:tap];
}
return _dismissArea;
}
- (UIView *)contentArea {
if (!_contentArea) {
_contentArea = [[UIView alloc] initWithFrame:CGRectMake(0, kGetScaleWidth(192), KScreenWidth, KScreenHeight - kGetScaleWidth(192))];
[_contentArea setBackgroundColor:UIColorFromRGB(0x1B0043)];
[_contentArea setCornerRadius:16 corners:kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner borderWidth:0 borderColor:[UIColor clearColor]];
UILabel *titleLabel = [UILabel labelInitWithText:YMLocalizedString(@"20.20.61_text_2") font:kFontMedium(16) textColor:[UIColor whiteColor]];
[_contentArea addSubview:titleLabel];
[titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(_contentArea);
make.top.mas_equalTo(12);
make.height.mas_equalTo(22);
}];
}
return _contentArea;
}
- (UIImageView *)controlAreaBG {
if (!_controlAreaBG) {
_controlAreaBG = [[UIImageView alloc] initWithImage:kImage(@"medals_control_bg")];
}
return _controlAreaBG;
}
- (UICollectionView *)controlAreaCollectionView {
if (!_controlAreaCollectionView) {
CGFloat length = (KScreenWidth - 60 - 21 *4)/5.0;
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(length, length);
layout.minimumInteritemSpacing = 21;
layout.minimumLineSpacing = 19;
_controlAreaCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_controlAreaCollectionView.backgroundColor = [UIColor clearColor];
_controlAreaCollectionView.delegate = self;
_controlAreaCollectionView.dataSource = self;
_controlAreaCollectionView.clipsToBounds = NO;
[MedalsWearingControlCollectionViewCell registerTo:_controlAreaCollectionView];
}
return _controlAreaCollectionView;
}
- (UICollectionView *)medalsAreaCollectionView {
if (!_medalsAreaCollectionView) {
CGFloat length = kGetScaleWidth(166);
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(length, length);
layout.minimumInteritemSpacing = 12;
layout.minimumLineSpacing = 14;
_medalsAreaCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_medalsAreaCollectionView.backgroundColor = [UIColor clearColor];
_medalsAreaCollectionView.delegate = self;
_medalsAreaCollectionView.dataSource = self;
[MedalsWearingListCollectionViewCell registerTo:_medalsAreaCollectionView];
}
return _medalsAreaCollectionView;
}
@end