// // JXCollectionViewController.m // AICity // // Created by TogetherWatch on 2025-10-20. // #import "JXCollectionViewController.h" #import "JXAPIService.h" #import "JXDrama.h" #import "JXEpisodeInfo.h" #import "JXInteraction.h" #import "JXShortDramaCell.h" #import "videoItemsCell.h" #import "videoItemsNavCell.h" // Cell复用标识符 //static NSString * const kEpisodeCellIdentifier = @"JXEpisodeCell"; @interface JXCollectionViewController () #pragma mark - UI组件 @property (nonatomic, strong) UIView *headerView; @property (strong, nonatomic) UIImageView *headImg; @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UILabel *statsLabel; @property (nonatomic, strong) UIButton *closeButton; @property (nonatomic, strong) UIView *rangePickerView; @property (nonatomic, strong) UIButton *rangeButton1; @property (nonatomic, strong) UIButton *rangeButton2; @property (nonatomic, strong) UIButton *rangeButton3; @property (nonatomic, strong) UICollectionView *collectionView; @property (nonatomic, strong) UICollectionView *collectionViewNav; @property (strong, nonatomic) NSMutableArray *navArray; #pragma mark - 数据 @property (nonatomic, copy) NSString *dramaId; @property (nonatomic, strong) JXDrama *drama; @property (nonatomic, strong) NSDictionary *pageData; @property (nonatomic, strong) NSArray *episodes; @property (nonatomic, strong) NSArray *filteredEpisodes; @property (nonatomic, assign) NSInteger selectedRange; // 0=全部, 1=1-50, 2=51-100 @end @implementation JXCollectionViewController #pragma mark - 初始化 - (instancetype)initWithDramaId:(NSString *)dramaId { self = [super init]; if (self) { _dramaId = dramaId; _selectedRange = 0; } return self; } #pragma mark - 生命周期 - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; self.pageData = [[NSDictionary alloc] init]; [self setupUI]; [self loadData]; } #pragma mark - UI设置 - (void)setupUI { // 顶部标题栏 [self setupHeader]; // 集数范围选择器 // [self setupRangePicker]; [self setupCollectionViewnav]; // 剧集列表 [self setupCollectionView]; } - (void)setupHeader { self.headerView = [[UIView alloc] init]; self.headerView.backgroundColor = [UIColor whiteColor]; [self.view addSubview:self.headerView]; //图片 self.headImg = [[UIImageView alloc] init]; self.headImg.image = [UIImage imageNamed:@"icon 2.1"]; [self.headerView addSubview:self.headImg]; // 标题 self.titleLabel = [[UILabel alloc] init]; self.titleLabel.text = @"合集"; self.titleLabel.font = [UIFont boldSystemFontOfSize:18]; self.titleLabel.textColor = [UIColor blackColor]; [self.headerView addSubview:self.titleLabel]; // 统计信息 self.statsLabel = [[UILabel alloc] init]; self.statsLabel.text = @"正在加载..."; self.statsLabel.font = [UIFont systemFontOfSize:14]; self.statsLabel.textColor = [UIColor grayColor]; [self.headerView addSubview:self.statsLabel]; // 关闭按钮 self.closeButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.closeButton setImage:[UIImage systemImageNamed:@"xmark"] forState:UIControlStateNormal]; self.closeButton.tintColor = [UIColor grayColor]; [self.closeButton addTarget:self action:@selector(handleClose) forControlEvents:UIControlEventTouchUpInside]; [self.headerView addSubview:self.closeButton]; // 约束 self.headerView.translatesAutoresizingMaskIntoConstraints = NO; self.headImg.translatesAutoresizingMaskIntoConstraints = NO; self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; self.statsLabel.translatesAutoresizingMaskIntoConstraints = NO; self.closeButton.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ [self.headerView.topAnchor constraintEqualToAnchor:self.view.topAnchor], [self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.headerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], [self.headerView.heightAnchor constraintEqualToConstant:80], [self.headImg.topAnchor constraintEqualToAnchor:self.headerView.topAnchor constant:14.5], [self.headImg.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:16], [self.headImg.widthAnchor constraintEqualToConstant:17], [self.headImg.heightAnchor constraintEqualToConstant:16.5], [self.titleLabel.topAnchor constraintEqualToAnchor:self.headerView.topAnchor constant:14.5], [self.titleLabel.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:41], [self.titleLabel.heightAnchor constraintEqualToConstant:16.5], [self.statsLabel.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:10], [self.statsLabel.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:16], [self.closeButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-16], [self.closeButton.centerYAnchor constraintEqualToAnchor:self.titleLabel.centerYAnchor], [self.closeButton.widthAnchor constraintEqualToConstant:30], [self.closeButton.heightAnchor constraintEqualToConstant:30] ]]; } - (void)setupRangePicker { // self.rangePickerView = [[UIView alloc] init]; // self.rangePickerView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; // [self.view addSubview:self.rangePickerView]; // // 全部 // self.rangeButton1 = [self createRangeButtonWithTitle:@"全部" tag:0]; // [self.rangePickerView addSubview:self.rangeButton1]; // // // 1-50 // self.rangeButton2 = [self createRangeButtonWithTitle:@"1-50集" tag:1]; // [self.rangePickerView addSubview:self.rangeButton2]; // // // 51-100 // self.rangeButton3 = [self createRangeButtonWithTitle:@"51-100集" tag:2]; // [self.rangePickerView addSubview:self.rangeButton3]; // // // 默认选中"全部" // [self selectRangeButton:self.rangeButton1]; // // // 约束 // self.rangePickerView.translatesAutoresizingMaskIntoConstraints = NO; // self.rangeButton1.translatesAutoresizingMaskIntoConstraints = NO; // self.rangeButton2.translatesAutoresizingMaskIntoConstraints = NO; // self.rangeButton3.translatesAutoresizingMaskIntoConstraints = NO; // // [NSLayoutConstraint activateConstraints:@[ // [self.rangePickerView.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor], // [self.rangePickerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], // [self.rangePickerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], // [self.rangePickerView.heightAnchor constraintEqualToConstant:50], // // [self.rangeButton1.leadingAnchor constraintEqualToAnchor:self.rangePickerView.leadingAnchor constant:16], // [self.rangeButton1.centerYAnchor constraintEqualToAnchor:self.rangePickerView.centerYAnchor], // [self.rangeButton1.widthAnchor constraintEqualToConstant:80], // [self.rangeButton1.heightAnchor constraintEqualToConstant:32], // // [self.rangeButton2.leadingAnchor constraintEqualToAnchor:self.rangeButton1.trailingAnchor constant:12], // [self.rangeButton2.centerYAnchor constraintEqualToAnchor:self.rangePickerView.centerYAnchor], // [self.rangeButton2.widthAnchor constraintEqualToConstant:80], // [self.rangeButton2.heightAnchor constraintEqualToConstant:32], // // [self.rangeButton3.leadingAnchor constraintEqualToAnchor:self.rangeButton2.trailingAnchor constant:12], // [self.rangeButton3.centerYAnchor constraintEqualToAnchor:self.rangePickerView.centerYAnchor], // [self.rangeButton3.widthAnchor constraintEqualToConstant:80], // [self.rangeButton3.heightAnchor constraintEqualToConstant:32] // ]]; } //- (UIButton *)createRangeButtonWithTitle:(NSString *)title tag:(NSInteger)tag { // UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; // [button setTitle:title forState:UIControlStateNormal]; // button.titleLabel.font = [UIFont systemFontOfSize:14]; // button.layer.cornerRadius = 16; // button.layer.borderWidth = 1.0; // button.tag = tag; // [button addTarget:self action:@selector(handleRangeButtonTap:) forControlEvents:UIControlEventTouchUpInside]; // return button; //} - (void)setupCollectionViewnav{ UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; layout.minimumLineSpacing = 6; layout.minimumInteritemSpacing = 6; layout.sectionInset = UIEdgeInsetsMake(0, 16, 0, 16); self.collectionViewNav = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; self.collectionViewNav.backgroundColor = [UIColor whiteColor]; self.collectionViewNav.delegate = self; self.collectionViewNav.dataSource = self; [self.collectionViewNav registerNib:[UINib nibWithNibName:NSStringFromClass(videoItemsNavCell.class) bundle:nil] forCellWithReuseIdentifier:NSStringFromClass(videoItemsNavCell.class)]; [self.view addSubview:self.collectionViewNav]; // 约束 self.collectionViewNav.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ [self.collectionViewNav.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor], [self.collectionViewNav.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.collectionViewNav.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], [self.collectionViewNav.heightAnchor constraintEqualToConstant:31], ]]; } - (void)setupCollectionView { UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.scrollDirection = UICollectionViewScrollDirectionVertical; layout.minimumLineSpacing = 0; layout.minimumInteritemSpacing = 0; layout.sectionInset = UIEdgeInsetsMake(16, 16, 16, 16); self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; self.collectionView.backgroundColor = [UIColor whiteColor]; self.collectionView.delegate = self; self.collectionView.dataSource = self; [self.collectionView registerNib:[UINib nibWithNibName:NSStringFromClass(videoItemsCell.class) bundle:nil] forCellWithReuseIdentifier:NSStringFromClass(videoItemsCell.class)]; [self.view addSubview:self.collectionView]; // 约束 self.collectionView.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ [self.collectionView.topAnchor constraintEqualToAnchor:self.collectionViewNav.bottomAnchor], [self.collectionView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.collectionView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], [self.collectionView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] ]]; } #pragma mark - 数据加载 - (void)loadData { // 获取短剧详情和剧集列表 [[JXAPIService sharedService] getDramaDetailWithDramaId:self.dramaId success:^(id response) { NSDictionary *dramaDict = response[@"data"]; // 解析短剧信息 self.drama = [[JXDrama alloc] initWithDictionary:dramaDict[@"drama"]]; // 解析剧集列表 NSArray *episodesArray = dramaDict[@"episodes"]; NSMutableArray *episodes = [NSMutableArray array]; for (NSDictionary *dict in episodesArray) { JXEpisodeInfo *episode = [[JXEpisodeInfo alloc] initWithDictionary:dict]; [episodes addObject:episode]; } self.episodes = episodes; // 更新UI [self updateUI]; [self filterEpisodesByRange:self.selectedRange]; } failure:^(NSError *error) { NSLog(@"[JXCollection] 加载失败: %@", error.localizedDescription); }]; } - (void)updateUI { // self.titleLabel.text = self.drama.title; // self.statsLabel.text = [NSString stringWithFormat:@"共%ld集 · %@ 播放", // (long)self.drama.totalEpisodes, // [JXShortDramaCell formattedCountWithCount:self.drama.viewCount]]; self.statsLabel.text = [NSString stringWithFormat:@"%@ 播放 · 已更新至%ld集", [JXShortDramaCell formattedCountWithCount:self.drama.viewCount], (long)self.drama.totalEpisodes]; } #pragma mark - 筛选逻辑 - (void)filterEpisodesByRange:(NSInteger)range { NSInteger all = self.drama.totalEpisodes; if (all == 0) { return; } for (int i = 1; i < all; i=i+20) { [self.navArray addObject: [NSString stringWithFormat:@"%d",i]]; } NSString *str = self.navArray[range]; NSPredicate *predicate; if (self.drama.totalEpisodes < 20) { predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"episodeNumber >= %@ AND episodeNumber <= %ld",str,self.drama.totalEpisodes]]; }else{ predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"episodeNumber >= %@ AND episodeNumber <= %d",str,str.intValue+20]]; } self.filteredEpisodes = [self.episodes filteredArrayUsingPredicate:predicate]; [self.collectionViewNav reloadData]; [self.collectionView reloadData]; } - (void)selectRangeButton:(UIButton *)button { // 重置所有按钮 for (UIButton *btn in @[self.rangeButton1, self.rangeButton2, self.rangeButton3]) { btn.selected = NO; [btn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; btn.backgroundColor = [UIColor whiteColor]; btn.layer.borderColor = [UIColor lightGrayColor].CGColor; } // 选中当前按钮 button.selected = YES; [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; button.backgroundColor = [UIColor systemBlueColor]; button.layer.borderColor = [UIColor systemBlueColor].CGColor; } #pragma mark - UICollectionViewDataSource - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { if (collectionView == self.collectionViewNav) { return self.navArray.count; } return self.filteredEpisodes.count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { if (collectionView == self.collectionViewNav) { videoItemsNavCell *cell1 = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass(videoItemsNavCell.class) forIndexPath:indexPath]; cell1.layer.cornerRadius = 5; if (self.selectedRange == indexPath.row) { cell1.backgroundColor = [UIColor colorWithRed:255/255.0 green:240/255.0 blue:234/255.0 alpha:1]; cell1.labelT.textColor = [UIColor colorWithRed:255/255.0 green:112/255.0 blue:48/255.0 alpha:1]; }else{ cell1.backgroundColor = [UIColor colorWithRed:247/255.0 green:247/255.0 blue:247/255.0 alpha:1]; cell1.labelT.textColor = [UIColor colorWithRed:140/255.0 green:140/255.0 blue:140/255.0 alpha:1]; } NSString *str = self.navArray[indexPath.row]; if (indexPath.row == self.navArray.count -1) { cell1.labelT.text = [NSString stringWithFormat:@"%@-%ld",str,self.drama.totalEpisodes]; }else{ cell1.labelT.text = [NSString stringWithFormat:@"%@-%d",str,str.intValue+19]; } return cell1; } videoItemsCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass(videoItemsCell.class) forIndexPath:indexPath]; JXEpisodeInfo *episode = self.filteredEpisodes[indexPath.item]; cell.viewVIP.hidden = !episode.isPaid; cell.btnVIP.hidden = !episode.isPaid; cell.labelT.text = episode.title; cell.labelView.text = [NSString stringWithFormat:@"%lld",episode.likeCount]; [cell.imgH sd_setImageWithURL:[NSURL URLWithString:episode.thumbnailUrl]]; cell.labelTime.text = [self getMMSSFromSS:episode.duration]; cell.vipClicked = ^{ //去会员 [MBProgressHUD showMessage:@"维护中..."]; }; cell.playClicked = ^{ if ([self.delegate respondsToSelector:@selector(collectionViewControllerDidSelectEpisode:)]) { [self.delegate collectionViewControllerDidSelectEpisode:[NSString stringWithFormat:@"%ld",episode.episodeNumber]]; } [self dismissViewControllerAnimated:YES completion:nil]; }; // JXEpisodeInfo *episode = self.filteredEpisodes[indexPath.item]; // 临时简单展示(后续可创建自定义Cell) // cell.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; // cell.layer.cornerRadius = 8; // 清除旧标签 // for (UIView *subview in cell.contentView.subviews) { // [subview removeFromSuperview]; // } // // // 第X集标签 // UILabel *label = [[UILabel alloc] init]; // label.text = [NSString stringWithFormat:@"第%ld集", (long)episode.episodeNumber]; // label.font = [UIFont boldSystemFontOfSize:14]; // label.textColor = [UIColor blackColor]; // label.textAlignment = NSTextAlignmentCenter; // [cell.contentView addSubview:label]; // // // VIP标识 // if (episode.isPaid) { // UILabel *vipLabel = [[UILabel alloc] init]; // vipLabel.text = @"VIP"; // vipLabel.font = [UIFont boldSystemFontOfSize:10]; // vipLabel.textColor = [UIColor systemOrangeColor]; // vipLabel.textAlignment = NSTextAlignmentCenter; // [cell.contentView addSubview:vipLabel]; // // vipLabel.translatesAutoresizingMaskIntoConstraints = NO; // [NSLayoutConstraint activateConstraints:@[ // [vipLabel.topAnchor constraintEqualToAnchor:cell.contentView.topAnchor constant:4], // [vipLabel.trailingAnchor constraintEqualToAnchor:cell.contentView.trailingAnchor constant:-4] // ]]; // } // // // 约束 // label.translatesAutoresizingMaskIntoConstraints = NO; // [NSLayoutConstraint activateConstraints:@[ // [label.centerXAnchor constraintEqualToAnchor:cell.contentView.centerXAnchor], // [label.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor] // ]]; return cell; } -(NSString *)getMMSSFromSS:(float)total{ int fen = (int)(total / 60 ) % 60; int miao = (int)total % 60; int shi = (int)(total / 3600); NSString *format_time = [NSString stringWithFormat:@"%@%@%@",shi>0 ?[NSString stringWithFormat:@"%02d:",shi]:@"",[NSString stringWithFormat:@"%02d:",fen],[NSString stringWithFormat:@"%02d",miao]]; return format_time; } #pragma mark - UICollectionViewDelegateFlowLayout - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { if (collectionView == self.collectionViewNav) { return CGSizeMake(60, 31); } CGFloat width = collectionView.bounds.size.width; // 3列 return CGSizeMake(width, 93); } #pragma mark - UICollectionViewDelegate - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { if (collectionView == self.collectionViewNav) { self.selectedRange = indexPath.row; NSString *str = self.navArray[indexPath.row]; NSPredicate *predicate; if (indexPath.row == self.navArray.count -1) { predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"episodeNumber >= %@ AND episodeNumber <= %ld",str,self.drama.totalEpisodes]]; }else{ predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"episodeNumber >= %@ AND episodeNumber <= %d",str,str.intValue+20]]; } self.filteredEpisodes = [self.episodes filteredArrayUsingPredicate:predicate]; [self.collectionViewNav reloadData]; [self.collectionView reloadData]; return ; } // if (self.filteredEpisodes.count > 0 && (self.filteredEpisodes.count >= indexPath.item)) { // JXEpisodeInfo *episode = self.filteredEpisodes[indexPath.item]; // // NSLog(@"[JXCollection] 选择剧集: %ld", (long)episode.episodeNumber); // // if ([self.delegate respondsToSelector:@selector(collectionViewControllerDidSelectEpisode:)]) { // [self.delegate collectionViewControllerDidSelectEpisode:episode.episodeId]; // } // // [self dismissViewControllerAnimated:YES completion:nil]; // }else{ // //测试一下 // // if ([self.delegate respondsToSelector:@selector(collectionViewControllerDidSelectEpisode:)]) { // [self.delegate collectionViewControllerDidSelectEpisode:@"1"]; // } // // [self dismissViewControllerAnimated:YES completion:nil]; // } } - (NSMutableArray *)navArray{ if (!_navArray) { _navArray = [NSMutableArray array]; } return _navArray; } - (NSDictionary *)pageData{ if (!_pageData) { _pageData = [NSDictionary dictionary]; } return _pageData; } #pragma mark - 关闭 - (void)handleClose { [self dismissViewControllerAnimated:YES completion:nil]; } @end