// // JXFavoriteViewController.m // AICity // // Created by TogetherWatch on 2025-10-20. // #import "JXFavoriteViewController.h" #import "JXAPIService.h" #import "JXDrama.h" // Cell复用标识符 static NSString * const kFavoriteCellIdentifier = @"FavoriteCell"; @interface JXFavoriteViewController () #pragma mark - UI组件 @property (nonatomic, strong) UICollectionView *collectionView; @property (nonatomic, strong) UICollectionViewFlowLayout *flowLayout; @property (nonatomic, strong) UIRefreshControl *refreshControl; @property (nonatomic, strong) UIView *emptyView; @property (nonatomic, strong) UIBarButtonItem *editButton; #pragma mark - 数据 @property (nonatomic, strong) NSMutableArray *favoriteList; @property (nonatomic, strong) NSMutableSet *selectedIndexPaths; #pragma mark - 状态 @property (nonatomic, assign) BOOL isLoading; @property (nonatomic, assign) BOOL hasMoreData; @property (nonatomic, assign) NSInteger currentPage; @property (nonatomic, assign) BOOL isEditMode; @end @implementation JXFavoriteViewController #pragma mark - 初始化 - (instancetype)init { self = [super init]; if (self) { _favoriteList = [NSMutableArray array]; _selectedIndexPaths = [NSMutableSet set]; _currentPage = 1; _hasMoreData = YES; } return self; } #pragma mark - 生命周期 - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; self.title = @"我的收藏"; [self setupUI]; [self loadFavorites]; } #pragma mark - UI设置 - (void)setupUI { // 编辑按钮 self.editButton = [[UIBarButtonItem alloc] initWithTitle:@"管理" style:UIBarButtonItemStylePlain target:self action:@selector(handleEdit)]; self.navigationItem.rightBarButtonItem = self.editButton; // 创建2列网格布局 self.flowLayout = [[UICollectionViewFlowLayout alloc] init]; self.flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; self.flowLayout.minimumLineSpacing = 12; self.flowLayout.minimumInteritemSpacing = 12; self.flowLayout.sectionInset = UIEdgeInsetsMake(12, 16, 12, 16); self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:self.flowLayout]; self.collectionView.backgroundColor = [UIColor whiteColor]; self.collectionView.delegate = self; self.collectionView.dataSource = self; self.collectionView.allowsMultipleSelection = YES; [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kFavoriteCellIdentifier]; [self.view addSubview:self.collectionView]; // 下拉刷新 self.refreshControl = [[UIRefreshControl alloc] init]; [self.refreshControl addTarget:self action:@selector(handleRefresh) forControlEvents:UIControlEventValueChanged]; [self.collectionView addSubview:self.refreshControl]; // 空状态 [self setupEmptyView]; // 约束 self.collectionView.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ [self.collectionView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor], [self.collectionView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.collectionView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], [self.collectionView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] ]]; } - (void)setupEmptyView { self.emptyView = [[UIView alloc] init]; self.emptyView.hidden = YES; [self.view addSubview:self.emptyView]; UILabel *emptyLabel = [[UILabel alloc] init]; emptyLabel.text = @"暂无收藏\n快去收藏喜欢的短剧吧~"; emptyLabel.textColor = [UIColor grayColor]; emptyLabel.font = [UIFont systemFontOfSize:14]; emptyLabel.textAlignment = NSTextAlignmentCenter; emptyLabel.numberOfLines = 0; [self.emptyView addSubview:emptyLabel]; self.emptyView.translatesAutoresizingMaskIntoConstraints = NO; emptyLabel.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ [self.emptyView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], [self.emptyView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor], [emptyLabel.centerXAnchor constraintEqualToAnchor:self.emptyView.centerXAnchor], [emptyLabel.centerYAnchor constraintEqualToAnchor:self.emptyView.centerYAnchor] ]]; } #pragma mark - 数据加载 - (void)loadFavorites { if (self.isLoading) { return; } self.isLoading = YES; // TODO: 调用API获取收藏列表 // 暂时使用示例数据 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.isLoading = NO; [self.refreshControl endRefreshing]; // 示例数据 if (self.currentPage == 1) { self.favoriteList = [@[] mutableCopy]; } [self.collectionView reloadData]; self.emptyView.hidden = (self.favoriteList.count > 0); self.editButton.enabled = (self.favoriteList.count > 0); }); } - (void)loadMoreFavorites { if (!self.hasMoreData || self.isLoading) { return; } self.currentPage++; [self loadFavorites]; } - (void)handleRefresh { self.currentPage = 1; self.hasMoreData = YES; [self loadFavorites]; } #pragma mark - 编辑模式 - (void)handleEdit { self.isEditMode = !self.isEditMode; if (self.isEditMode) { // 进入编辑模式 self.editButton.title = @"取消"; // 显示底部工具栏 [self showBottomToolbar]; } else { // 退出编辑模式 self.editButton.title = @"管理"; [self.selectedIndexPaths removeAllObjects]; [self.collectionView reloadData]; // 隐藏底部工具栏 [self hideBottomToolbar]; } } - (void)showBottomToolbar { UIToolbar *toolbar = [[UIToolbar alloc] init]; toolbar.frame = CGRectMake(0, self.view.bounds.size.height - 44, self.view.bounds.size.width, 44); toolbar.tag = 999; UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; UIBarButtonItem *deleteButton = [[UIBarButtonItem alloc] initWithTitle:@"删除" style:UIBarButtonItemStylePlain target:self action:@selector(handleBatchDelete)]; deleteButton.tintColor = [UIColor systemRedColor]; toolbar.items = @[flexSpace, deleteButton, flexSpace]; [self.view addSubview:toolbar]; } - (void)hideBottomToolbar { UIView *toolbar = [self.view viewWithTag:999]; [toolbar removeFromSuperview]; } - (void)handleBatchDelete { if (self.selectedIndexPaths.count == 0) { return; } NSString *message = [NSString stringWithFormat:@"确定要取消收藏选中的%lu部短剧吗?", (unsigned long)self.selectedIndexPaths.count]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"批量取消收藏" message:message preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) { [self performBatchDelete]; }]]; [self presentViewController:alert animated:YES completion:nil]; } - (void)performBatchDelete { // 按索引降序排序,从后往前删除 NSArray *sortedIndexPaths = [[self.selectedIndexPaths allObjects] sortedArrayUsingComparator:^NSComparisonResult(NSIndexPath *obj1, NSIndexPath *obj2) { return [@(obj2.item) compare:@(obj1.item)]; }]; for (NSIndexPath *indexPath in sortedIndexPaths) { if (indexPath.item < self.favoriteList.count) { [self.favoriteList removeObjectAtIndex:indexPath.item]; } } [self.selectedIndexPaths removeAllObjects]; [self.collectionView reloadData]; // 如果列表为空,退出编辑模式 if (self.favoriteList.count == 0) { [self handleEdit]; self.emptyView.hidden = NO; } } #pragma mark - UICollectionViewDataSource - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return self.favoriteList.count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kFavoriteCellIdentifier forIndexPath:indexPath]; // 清除旧内容 for (UIView *subview in cell.contentView.subviews) { [subview removeFromSuperview]; } JXDrama *drama = self.favoriteList[indexPath.item]; // 封面图(占位) UIView *coverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.contentView.bounds.size.width, cell.contentView.bounds.size.width * 1.4)]; coverView.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0]; [cell.contentView addSubview:coverView]; // 标题 UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, coverView.frame.size.height + 8, cell.contentView.bounds.size.width, 40)]; titleLabel.text = drama.title; titleLabel.font = [UIFont systemFontOfSize:14]; titleLabel.numberOfLines = 2; [cell.contentView addSubview:titleLabel]; // 编辑模式:显示选中状态 if (self.isEditMode) { BOOL isSelected = [self.selectedIndexPaths containsObject:indexPath]; UIView *checkmark = [[UIView alloc] initWithFrame:CGRectMake(cell.contentView.bounds.size.width - 30, 10, 24, 24)]; checkmark.backgroundColor = isSelected ? [UIColor systemBlueColor] : [UIColor colorWithWhite:0.8 alpha:0.8]; checkmark.layer.cornerRadius = 12; [cell.contentView addSubview:checkmark]; if (isSelected) { UILabel *checkLabel = [[UILabel alloc] initWithFrame:checkmark.bounds]; checkLabel.text = @"✓"; checkLabel.textColor = [UIColor whiteColor]; checkLabel.font = [UIFont boldSystemFontOfSize:16]; checkLabel.textAlignment = NSTextAlignmentCenter; [checkmark addSubview:checkLabel]; } } cell.backgroundColor = [UIColor whiteColor]; cell.layer.cornerRadius = 8; return cell; } #pragma mark - UICollectionViewDelegateFlowLayout - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { CGFloat totalWidth = collectionView.bounds.size.width; CGFloat spacing = 12; CGFloat inset = 16; CGFloat availableWidth = totalWidth - (inset * 2) - spacing; CGFloat itemWidth = availableWidth / 2; CGFloat itemHeight = itemWidth * 1.4 + 60; return CGSizeMake(itemWidth, itemHeight); } #pragma mark - UICollectionViewDelegate - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { if (self.isEditMode) { // 编辑模式:切换选中状态 if ([self.selectedIndexPaths containsObject:indexPath]) { [self.selectedIndexPaths removeObject:indexPath]; } else { [self.selectedIndexPaths addObject:indexPath]; } [collectionView reloadItemsAtIndexPaths:@[indexPath]]; } else { // 普通模式:跳转到详情或播放 JXDrama *drama = self.favoriteList[indexPath.item]; NSLog(@"[JXFavorite] 点击短剧: %@", drama.title); // TODO: 跳转到播放页或详情页 } } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { // 预加载 CGFloat offsetY = scrollView.contentOffset.y; CGFloat contentHeight = scrollView.contentSize.height; CGFloat scrollViewHeight = scrollView.bounds.size.height; if (offsetY + scrollViewHeight >= contentHeight - 200) { [self loadMoreFavorites]; } } @end