From 82123fc232b72a4aad6237dc4c02315543315878 Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Wed, 3 Dec 2025 18:49:18 +0800 Subject: [PATCH] 1 --- keyBoard/Class/Home/M/KBCharacter.h | 27 ++++---- keyBoard/Class/Home/M/KBCharacter.m | 8 ++- keyBoard/Class/Home/VC/HomeHotVC.m | 104 +++++++++++++++++++++------- 3 files changed, 98 insertions(+), 41 deletions(-) diff --git a/keyBoard/Class/Home/M/KBCharacter.h b/keyBoard/Class/Home/M/KBCharacter.h index 1685275..6ddccef 100644 --- a/keyBoard/Class/Home/M/KBCharacter.h +++ b/keyBoard/Class/Home/M/KBCharacter.h @@ -8,30 +8,30 @@ NS_ASSUME_NONNULL_BEGIN /// 排行榜角色/角色卡片模型 -/// 对应后端返回字段: +/// 对应后端返回字段示例: /// { -/// "id": 0, -/// "title": "", -/// "characterBackground": "", -/// "avatarUrl": "", -/// "download": "", -/// "tag": 0, -/// "rank": 0 +/// "id" : 29, +/// "download" : "0x4AQSfQS0", +/// "characterName" : "Ms.", +/// "avatarUrl" : "https://...", +/// "tag" : 490, +/// "characterBackground" : "d2EWHe1ST5", +/// "rank" : 899 /// } @interface KBCharacter : NSObject /// 唯一标识,对应后端的 id @property (nonatomic, copy, nullable) NSString *characterId; -/// 标题/名称 -@property (nonatomic, copy, nullable) NSString *title; - -/// 角色背景(颜色值、图片地址或后端定义的 key) -@property (nonatomic, copy, nullable) NSString *characterBackground; +/// 名称,对应后端的 characterName +@property (nonatomic, copy, nullable) NSString *characterName; /// 头像地址 @property (nonatomic, copy, nullable) NSString *avatarUrl; +/// 角色背景(颜色值、图片地址或后端定义的 key) +@property (nonatomic, copy, nullable) NSString *characterBackground; + /// 下载量文案或数值(后端返回字符串) @property (nonatomic, copy, nullable) NSString *download; @@ -47,4 +47,3 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END - diff --git a/keyBoard/Class/Home/M/KBCharacter.m b/keyBoard/Class/Home/M/KBCharacter.m index 7d4eb54..94a778d 100644 --- a/keyBoard/Class/Home/M/KBCharacter.m +++ b/keyBoard/Class/Home/M/KBCharacter.m @@ -8,11 +8,13 @@ @implementation KBCharacter + (NSDictionary *)mj_replacedKeyFromPropertyName { - // 后端字段 id -> characterId + // 后端字段映射到本地属性 return @{ - @"characterId": @"id" + // id -> characterId + @"characterId": @"id", + // 名称字段:优先 characterName,兼容部分接口可能返回 title + @"characterName": @[@"characterName", @"title"], }; } @end - diff --git a/keyBoard/Class/Home/VC/HomeHotVC.m b/keyBoard/Class/Home/VC/HomeHotVC.m index eb5236c..5b31a3b 100644 --- a/keyBoard/Class/Home/VC/HomeHotVC.m +++ b/keyBoard/Class/Home/VC/HomeHotVC.m @@ -8,18 +8,26 @@ #import "HomeHotVC.h" // 视图 #import "KBTopThreeView.h" +#import "KBHomeVM.h" +#import "KBCharacter.h" #import "HomeHotCell.h" #import "HomeRankVC.h" #import "KBSearchVC.h" #import "HomeRankDetailPopView.h" #import "LSTPopView.h" #import + @interface HomeHotVC () // 顶部前三名视图 @property (nonatomic, strong) KBTopThreeView *topThreeView; -@property (nonatomic, strong) NSArray *dataSource; // 简单模拟数据 +/// 首页排行榜 VM +@property (nonatomic, strong) KBHomeVM *homeVM; +/// 完整的排行榜数据(接口返回) +@property (nonatomic, copy) NSArray *allCharacters; +/// 列表区域使用的数据:从第 4 名开始 +@property (nonatomic, copy) NSArray *listCharacters; @end @@ -31,13 +39,6 @@ - (void)viewDidLoad { [super viewDidLoad]; - // 构建数据(演示) - self.dataSource = @[ - @{@"rank":@4, @"title":@"Ambiguous", @"sub":@"Be Neither Too Close Nor Too Distant, Want To ...", @"joined":@NO}, - @{@"rank":@5, @"title":@"Ambiguous", @"sub":@"Be Neither Too Close Nor Too Distant, Want To ...", @"joined":@YES}, - @{@"rank":@6, @"title":@"Ambiguous", @"sub":@"Be Neither Too Close Nor Too Distant, Want To ...", @"joined":@NO}, - @{@"rank":@7, @"title":@"Ambiguous", @"sub":@"Be Neither Too Close Nor Too Distant, Want To ...", @"joined":@NO} - ]; // 搭建 UI [self.view addSubview:self.tableView]; @@ -48,29 +49,84 @@ // 顶部前三名作为 tableHeaderView(注意:tableHeaderView 需设定明确高度) CGFloat headerH = 280.0; self.topThreeView = [[KBTopThreeView alloc] initWithFrame:CGRectMake(0, 0, KB_SCREEN_WIDTH, headerH)]; - // 示例配置:三个条目的标题 - [self.topThreeView configWithItems:@[ - @{@"title":@"High EQ", @"rank":@1}, - @{@"title":@"Flirt Girls", @"rank":@2}, - @{@"title":@"Humorous", @"rank":@3} - ]]; self.tableView.tableHeaderView = self.topThreeView; + + // 请求排行榜数据 + self.homeVM = [KBHomeVM new]; + KBWeakSelf + [self.homeVM fetchRankListWithParams:nil + needShow:YES + completion:^(NSArray * _Nullable list, NSError * _Nullable error) { + if (error) { + // 错误提示已经在 VM 内部通过 HUD 处理,这里不再重复提示 + return; + } + weakSelf.allCharacters = list ?: @[]; + + // 顶部前三名数据 + NSMutableArray *topItems = [NSMutableArray array]; + NSInteger topCount = MIN(3, weakSelf.allCharacters.count); + for (NSInteger i = 0; i < topCount; i++) { + KBCharacter *c = weakSelf.allCharacters[i]; + NSInteger rank = (c.rank > 0) ? c.rank : (i + 1); + NSString *title = c.characterName ?: @""; + [topItems addObject:@{ @"title": title, @"rank": @(rank) }]; + } + if (topItems.count > 0) { + [weakSelf.topThreeView configWithItems:topItems]; + } + + // 列表部分:从第 4 名开始 + if (weakSelf.allCharacters.count > 3) { + NSRange range = NSMakeRange(3, weakSelf.allCharacters.count - 3); + weakSelf.listCharacters = [weakSelf.allCharacters subarrayWithRange:range]; + } else { + weakSelf.listCharacters = @[]; + } + [weakSelf.tableView reloadData]; + + // 通知承载 HomeHotVC 的“外层 PanModal 容器”刷新布局。 + // 1) 如果 HomeHotVC 是作为子控制器嵌在某个 VC 里(例如 HomeSheetVC), + // 则该 VC 实现了 hw_panModalSetNeedsLayoutUpdate。 + UIViewController *parent = weakSelf.parentViewController; + id target = nil; + if ([parent respondsToSelector:@selector(hw_panModalSetNeedsLayoutUpdate)]) { + target = parent; + } else { + // 2) 如果 HomeHotVC 是直接嵌在 HWPanModalContentView(如 KBPanModalView)里, + // parentViewController 可能为 nil,需要顺着 view.superview 向上寻找。 + UIView *v = weakSelf.view; + while (v && ![v respondsToSelector:@selector(hw_panModalSetNeedsLayoutUpdate)]) { + v = v.superview; + } + if (v && [v respondsToSelector:@selector(hw_panModalSetNeedsLayoutUpdate)]) { + target = v; + } + } + if (target) { + [(id)target hw_panModalSetNeedsLayoutUpdate]; + } + }]; } #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.dataSource.count; + return self.listCharacters.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { HomeHotCell *cell = [tableView dequeueReusableCellWithIdentifier:HomeHotCell.reuseId forIndexPath:indexPath]; - NSDictionary *item = self.dataSource[indexPath.row]; + KBCharacter *item = self.listCharacters[indexPath.row]; + NSInteger rank = (item.rank > 0) ? item.rank : (indexPath.row + 4); // 兜底:接口没给 rank 时,从 4 开始递增 + NSString *title = item.characterName ?: @""; + NSString *sub = item.download ?: @""; // 暂用 download 字段作为副标题展示 + BOOL joined = item.added; // 配置 cell - [cell configWithRank:[item[@"rank"] integerValue] - title:item[@"title"] - subtitle:item[@"sub"] - joined:[item[@"joined"] boolValue]]; + [cell configWithRank:rank + title:title + subtitle:sub + joined:joined]; return cell; } @@ -87,15 +143,15 @@ // UINavigationController *nav = KB_CURRENT_NAV; // [nav pushViewController:vc animated:true]; NSLog(@"==="); - + // 点击卡片 -> 展示弹窗 - NSDictionary *d = self.dataSource[indexPath.item]; + KBCharacter *c = self.listCharacters[indexPath.row]; // 自定义内容视图(尺寸可按需调节) CGFloat width = MIN(KB_SCREEN_WIDTH - 76, 420); HomeRankDetailPopView *content = [[HomeRankDetailPopView alloc] initWithFrame:CGRectMake(0, 0, width, 460)]; - NSString *title = d[@"title"] ?: @"High EQ"; - NSString *people = d[@"people"] ?: @"Download: 1 Million"; + NSString *title = c.characterName ?: @"High EQ"; + NSString *people = c.download ?: @"Download: 1 Million"; NSString *desc = @"Be Neither Too Close\nNor Too Distant"; // 示例文案 [content configWithAvatar:nil title:title download:people desc:desc];