| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- //
- // 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 () <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
- #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) NSArray<JXEpisodeInfo *> *episodes;
- @property (nonatomic, strong) NSArray<JXEpisodeInfo *> *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 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];
- self.drama = [JXDrama mj_objectWithKeyValues:dramaDict context:nil];
- // 解析剧集列表
- 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 == 0 ? 95 :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)handleRangeButtonTap:(UIButton *)sender {
- // [self selectRangeButton:sender];
- // self.selectedRange = sender.tag;
- // [self filterEpisodesByRange:self.selectedRange];
- //}
- - (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.navArray.count ? 20 : 0; //写死的,后面要改
- // 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)
- // 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;
- }
- #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;
- }
- #pragma mark - 关闭
- - (void)handleClose {
- [self dismissViewControllerAnimated:YES completion:nil];
- }
- @end
|