2025-11-06 19:19:12 +08:00
|
|
|
|
//
|
|
|
|
|
|
// HomeRankContentVC.m
|
|
|
|
|
|
// keyBoard
|
|
|
|
|
|
//
|
|
|
|
|
|
// Created by Mac on 2025/11/6.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
2025-11-06 19:51:50 +08:00
|
|
|
|
@import UIKit;
|
2025-11-06 19:19:12 +08:00
|
|
|
|
#import "HomeRankContentVC.h"
|
2025-11-11 14:38:38 +08:00
|
|
|
|
#import "HomeRankDetailPopView.h" // 自定义弹窗内容视图
|
|
|
|
|
|
#import "LSTPopView.h" // LSTPopView 弹窗框架
|
2025-11-06 19:19:12 +08:00
|
|
|
|
|
2025-11-06 19:51:50 +08:00
|
|
|
|
// 自定义卡片 Cell
|
|
|
|
|
|
#import "HomeRankCardCell.h"
|
2025-12-03 19:19:20 +08:00
|
|
|
|
#import "KBHomeVM.h"
|
|
|
|
|
|
#import "KBCharacter.h"
|
2025-12-04 19:12:34 +08:00
|
|
|
|
#import "KBHUD.h"
|
2025-12-04 16:59:59 +08:00
|
|
|
|
#import "KBMyVM.h" // 引入用户人设变更通知
|
2025-11-06 19:51:50 +08:00
|
|
|
|
|
|
|
|
|
|
@interface HomeRankContentVC ()
|
2025-12-03 19:19:20 +08:00
|
|
|
|
@property (nonatomic, copy, nullable) NSString *tagId; // 当前标签 id
|
|
|
|
|
|
@property (nonatomic, strong) KBHomeVM *homeVM;
|
|
|
|
|
|
@property (nonatomic, strong) NSArray<KBCharacter *> *characters; // 当前标签下的角色列表
|
2025-11-06 19:19:12 +08:00
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
@implementation HomeRankContentVC
|
|
|
|
|
|
|
2025-12-03 19:19:20 +08:00
|
|
|
|
- (instancetype)initWithTagId:(NSString *)tagId {
|
|
|
|
|
|
if (self = [super init]) {
|
|
|
|
|
|
_tagId = [tagId copy];
|
|
|
|
|
|
}
|
|
|
|
|
|
return self;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (instancetype)init {
|
|
|
|
|
|
return [self initWithTagId:nil];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-06 19:19:12 +08:00
|
|
|
|
- (void)viewDidLoad {
|
|
|
|
|
|
[super viewDidLoad];
|
2025-11-06 19:51:50 +08:00
|
|
|
|
|
|
|
|
|
|
self.view.backgroundColor = COLOR_WITH_RGB(246/255.0, 253/255.0, 249/255.0, 1.0); // 淡绿色背景
|
2025-12-03 19:19:20 +08:00
|
|
|
|
self.characters = @[];
|
|
|
|
|
|
self.homeVM = [KBHomeVM new];
|
2025-11-06 19:51:50 +08:00
|
|
|
|
|
|
|
|
|
|
[self.view addSubview:self.collectionView];
|
|
|
|
|
|
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.edges.equalTo(self.view);
|
2025-11-06 19:19:12 +08:00
|
|
|
|
}];
|
2025-12-03 19:19:20 +08:00
|
|
|
|
|
2025-12-04 16:59:59 +08:00
|
|
|
|
// 监听“用户人设删除”通知,用于同步更新加号按钮状态
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
|
|
selector:@selector(kb_onUserCharacterDeleted:)
|
|
|
|
|
|
name:KBUserCharacterDeletedNotification
|
|
|
|
|
|
object:nil];
|
|
|
|
|
|
|
2025-12-03 19:19:20 +08:00
|
|
|
|
// 加载当前 tag 下的角色列表
|
|
|
|
|
|
[self loadCharactersForCurrentTag];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-04 16:59:59 +08:00
|
|
|
|
- (void)dealloc {
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-03 19:19:20 +08:00
|
|
|
|
- (void)loadCharactersForCurrentTag {
|
2025-12-04 16:59:59 +08:00
|
|
|
|
[self kb_requestCharactersWithShowHUD:YES];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 内部通用方法:根据 tag 请求角色列表
|
|
|
|
|
|
- (void)kb_requestCharactersWithShowHUD:(BOOL)needShow {
|
2025-12-03 19:19:20 +08:00
|
|
|
|
KBWeakSelf
|
|
|
|
|
|
[self.homeVM fetchRankListByTagId:self.tagId
|
2025-12-04 16:59:59 +08:00
|
|
|
|
needShow:needShow
|
2025-12-03 19:19:20 +08:00
|
|
|
|
completion:^(NSArray<KBCharacter *> * _Nullable list, NSError * _Nullable error) {
|
|
|
|
|
|
if (error) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
weakSelf.characters = list ?: @[];
|
|
|
|
|
|
[weakSelf.collectionView reloadData];
|
|
|
|
|
|
}];
|
2025-11-06 19:19:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-04 16:59:59 +08:00
|
|
|
|
/// 收到“用户人设删除”通知:如果当前列表包含该 id,则刷新接口数据
|
|
|
|
|
|
- (void)kb_onUserCharacterDeleted:(NSNotification *)note {
|
|
|
|
|
|
NSNumber *cid = note.userInfo[@"characterId"];
|
|
|
|
|
|
if (!cid) { return; }
|
|
|
|
|
|
NSInteger targetId = cid.integerValue;
|
|
|
|
|
|
if (targetId <= 0) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
BOOL contains = NO;
|
|
|
|
|
|
for (KBCharacter *c in self.characters) {
|
2025-12-04 19:12:34 +08:00
|
|
|
|
if (c.ID.integerValue == targetId) {
|
2025-12-04 16:59:59 +08:00
|
|
|
|
contains = YES;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!contains) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
// 后端会根据最新的人设状态返回 added 字段,刷新本页 UI
|
|
|
|
|
|
[self kb_requestCharactersWithShowHUD:NO];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-06 19:51:50 +08:00
|
|
|
|
- (UICollectionView *)collectionView{
|
|
|
|
|
|
if (!_collectionView) {
|
|
|
|
|
|
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
|
|
|
|
|
layout.sectionInset = UIEdgeInsetsMake(16, 16, 16, 16);
|
|
|
|
|
|
layout.minimumLineSpacing = 24;
|
|
|
|
|
|
layout.minimumInteritemSpacing = 16;
|
2025-11-06 19:19:12 +08:00
|
|
|
|
|
2025-11-06 19:51:50 +08:00
|
|
|
|
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
|
|
|
|
|
_collectionView.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
// _collectionView.alwaysBounceVertical = YES;
|
|
|
|
|
|
_collectionView.bounces = false;
|
|
|
|
|
|
_collectionView.dataSource = self;
|
|
|
|
|
|
_collectionView.delegate = self;
|
|
|
|
|
|
[_collectionView registerClass:[HomeRankCardCell class] forCellWithReuseIdentifier:@"HomeRankCardCell"];
|
|
|
|
|
|
// self.collectionView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
|
|
|
|
}
|
|
|
|
|
|
return _collectionView;
|
2025-11-06 19:19:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-11-06 19:51:50 +08:00
|
|
|
|
#pragma mark - UICollectionViewDataSource
|
2025-11-06 19:19:12 +08:00
|
|
|
|
|
2025-11-06 19:51:50 +08:00
|
|
|
|
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
2025-12-03 19:19:20 +08:00
|
|
|
|
return self.characters.count;
|
2025-11-06 19:19:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-06 19:51:50 +08:00
|
|
|
|
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
|
|
HomeRankCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"HomeRankCardCell" forIndexPath:indexPath];
|
2025-12-03 19:19:20 +08:00
|
|
|
|
KBCharacter *c = self.characters[indexPath.item];
|
|
|
|
|
|
// 直接把模型交给 cell,由 cell 自己负责展示
|
|
|
|
|
|
cell.character = c;
|
2025-11-10 15:38:30 +08:00
|
|
|
|
KBWeakSelf
|
2025-12-04 19:24:42 +08:00
|
|
|
|
__weak typeof(cell) weakCell = cell;
|
2025-11-06 19:51:50 +08:00
|
|
|
|
cell.onTapAction = ^{
|
2025-12-04 19:24:42 +08:00
|
|
|
|
__strong typeof(weakSelf) self = weakSelf;
|
|
|
|
|
|
HomeRankCardCell *strongCell = weakCell;
|
|
|
|
|
|
if (!self || !strongCell) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
NSIndexPath *currentIndexPath = [collectionView indexPathForCell:strongCell];
|
|
|
|
|
|
if (!currentIndexPath) { return; }
|
|
|
|
|
|
if (currentIndexPath.item >= self.characters.count) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
KBCharacter *mc = self.characters[currentIndexPath.item];
|
|
|
|
|
|
// 已添加状态下不允许再次点击
|
|
|
|
|
|
if (mc.added) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
NSString *cidStr = mc.ID ?: @"";
|
|
|
|
|
|
if (cidStr.length == 0) { return; }
|
|
|
|
|
|
NSNumber *cid = @([cidStr integerValue]);
|
2025-12-08 16:39:47 +08:00
|
|
|
|
NSString *emoji = mc.emoji ? mc.emoji : @"";
|
2025-12-04 19:24:42 +08:00
|
|
|
|
|
2025-12-08 16:39:47 +08:00
|
|
|
|
[self.homeVM addUserCharacterWithId:cid emoji : emoji
|
2025-12-04 19:24:42 +08:00
|
|
|
|
completion:^(BOOL success, NSError * _Nullable error) {
|
|
|
|
|
|
if (!success) {
|
|
|
|
|
|
NSString *msg = error.localizedDescription ?: KBLocalized(@"Network error");
|
|
|
|
|
|
[KBHUD showInfo:msg];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 添加成功:更新模型状态并刷新该 item(按钮变为已添加且不可再点)
|
|
|
|
|
|
mc.added = YES;
|
|
|
|
|
|
NSMutableArray *m = [self.characters mutableCopy];
|
|
|
|
|
|
[m replaceObjectAtIndex:currentIndexPath.item withObject:mc];
|
|
|
|
|
|
self.characters = [m copy];
|
|
|
|
|
|
[self.collectionView reloadItemsAtIndexPaths:@[currentIndexPath]];
|
|
|
|
|
|
}];
|
2025-11-06 19:51:50 +08:00
|
|
|
|
};
|
|
|
|
|
|
return cell;
|
2025-11-06 19:19:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-06 19:51:50 +08:00
|
|
|
|
#pragma mark - UICollectionViewDelegateFlowLayout
|
|
|
|
|
|
|
|
|
|
|
|
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
|
2025-11-11 14:38:38 +08:00
|
|
|
|
CGFloat totalHInset = 16 + 16;
|
|
|
|
|
|
CGFloat spacing = 16;
|
|
|
|
|
|
CGFloat w = collectionView.bounds.size.width - totalHInset;
|
2025-11-06 19:51:50 +08:00
|
|
|
|
CGFloat cellWidth = (w - spacing) / 2.0;
|
|
|
|
|
|
// 固定高度,接近示意图比例
|
2025-11-07 21:57:42 +08:00
|
|
|
|
CGFloat cellHeight = 234.0;
|
2025-11-06 19:51:50 +08:00
|
|
|
|
return CGSizeMake(floor(cellWidth), cellHeight);
|
2025-11-06 19:19:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-11 14:38:38 +08:00
|
|
|
|
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
|
|
|
|
|
|
// 点击卡片 -> 展示弹窗
|
2025-12-03 19:19:20 +08:00
|
|
|
|
KBCharacter *c = self.characters[indexPath.item];
|
2025-11-11 14:38:38 +08:00
|
|
|
|
|
|
|
|
|
|
// 自定义内容视图(尺寸可按需调节)
|
|
|
|
|
|
CGFloat width = MIN(KB_SCREEN_WIDTH - 76, 420);
|
|
|
|
|
|
HomeRankDetailPopView *content = [[HomeRankDetailPopView alloc] initWithFrame:CGRectMake(0, 0, width, 460)];
|
2025-12-03 19:19:20 +08:00
|
|
|
|
NSString *title = c.characterName ?: @"High EQ";
|
|
|
|
|
|
NSString *people = c.download ?: @"Download: 1 Million";
|
2025-11-11 14:38:38 +08:00
|
|
|
|
NSString *desc = @"Be Neither Too Close\nNor Too Distant"; // 示例文案
|
2025-12-04 20:04:02 +08:00
|
|
|
|
// [content configWithAvatar:nil title:title download:people desc:desc];
|
|
|
|
|
|
content.character = c;
|
2025-11-11 14:38:38 +08:00
|
|
|
|
// 创建并弹出
|
|
|
|
|
|
LSTPopView *pop = [LSTPopView initWithCustomView:content
|
|
|
|
|
|
parentView:nil
|
|
|
|
|
|
popStyle:LSTPopStyleScale
|
|
|
|
|
|
dismissStyle:LSTDismissStyleScale];
|
|
|
|
|
|
pop.hemStyle = LSTHemStyleCenter; // 居中
|
|
|
|
|
|
pop.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
|
|
|
|
|
pop.isClickBgDismiss = YES; // 点击背景关闭
|
|
|
|
|
|
pop.cornerRadius = 0; // 自定义 view 自处理圆角
|
|
|
|
|
|
|
|
|
|
|
|
__weak typeof(pop) weakPop = pop;
|
|
|
|
|
|
content.saveHandler = ^{ [weakPop dismiss]; };
|
|
|
|
|
|
content.closeHandler = ^{ [weakPop dismiss]; };
|
|
|
|
|
|
|
|
|
|
|
|
[pop pop];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-06 19:19:12 +08:00
|
|
|
|
|
|
|
|
|
|
#pragma mark - JXCategoryListContentViewDelegate
|
|
|
|
|
|
- (UIView *)listView {
|
|
|
|
|
|
return self.view;
|
|
|
|
|
|
}
|
2025-11-06 19:51:50 +08:00
|
|
|
|
|
2025-11-06 19:19:12 +08:00
|
|
|
|
@end
|