| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886 |
- //
- // JXShortDramaViewController.m
- // AICity
- //
- // Created by TogetherWatch on 2025-10-20.
- //
- #import "JXShortDramaViewController.h"
- #import "JXShortDramaCell.h"
- #import "JXCommentViewController.h"
- #import "JXCollectionViewController.h"
- #import "JXAPIService.h"
- #import "JXDramaContent.h"
- #import "JXCommentContent.h"
- #import "JXEpisodeInfo.h"
- #import "GuestHelper.h"
- #import "JXDetailViewController.h" // Added for detail view
- #import "SearchCommonBarView.h"
- #import "JXSearchViewController.h"
- // 复用标识符
- static NSString * const kDramaCellIdentifier = @"JXShortDramaCell";
- @interface JXShortDramaViewController () <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, JXShortDramaCellDelegate, JXCollectionViewControllerDelegate>
- #pragma mark - UI组件
- @property (nonatomic, strong) UICollectionView *collectionView;
- @property (nonatomic, strong) UICollectionViewFlowLayout *flowLayout;
- @property (nonatomic, strong) UIRefreshControl *refreshControl;
- #pragma mark - 数据
- @property (nonatomic, strong) NSMutableArray<JXDramaContent *> *dramaList;
- @property (nonatomic, copy) NSString *categoryId;
- @property (nonatomic, assign) NSInteger currentPage;
- @property (nonatomic, assign) NSInteger currentIndex; // 当前播放的索引
- #pragma mark - 状态
- @property (nonatomic, assign) BOOL isLoading;
- @property (nonatomic, assign) BOOL hasMoreData;
- @property (nonatomic, assign) BOOL hasUserVisited; // 用户是否已访问过
- @property (nonatomic, assign) BOOL isFirstLoad; // 是否首次加载
- @property (nonatomic, strong) SearchCommonBarView *searchBar;
- @end
- @implementation JXShortDramaViewController
- #pragma mark - 初始化
- - (instancetype)initWithCategoryId:(NSString *)categoryId {
- self = [super init];
- if (self) {
- _categoryId = categoryId;
- _currentPage = 1;
- _currentIndex = 0;
- _hasMoreData = YES;
- _hasUserVisited = NO; // 初始化为未访问
- _isFirstLoad = YES; // 初始化为首次加载
- _dramaList = [NSMutableArray array];
- }
- return self;
- }
- - (instancetype)init {
- return [self initWithCategoryId:nil];
- }
- #pragma mark - 生命周期
- - (void)viewDidLoad {
- [super viewDidLoad];
-
- self.view.backgroundColor = [UIColor blackColor];
-
- [self setupUI];
- [self loadInitialData];
- }
- - (void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
-
- // 隐藏导航栏(全屏沉浸式)
- [self.navigationController setNavigationBarHidden:YES animated:animated];
-
- // 标记用户已访问
- self.hasUserVisited = YES;
- // 如果是首次加载且有数据,开始播放
- if (self.isFirstLoad && self.dramaList.count > 0) {
- [self playVideoAtIndex:0];
- self.isFirstLoad = NO;
- } else {
- // 非首次,恢复当前视频播放
- [self resumeCurrentVideo];
- }
- }
- - (void)viewWillDisappear:(BOOL)animated {
- [super viewWillDisappear:animated];
-
- // 暂停所有视频
- [self pauseAllVideos];
- }
- - (void)dealloc {
- NSLog(@"[JXShortDrama] dealloc");
- }
- #pragma mark - UI设置
- - (void)setupUI {
-
-
- // 创建FlowLayout(垂直分页)
- self.flowLayout = [[UICollectionViewFlowLayout alloc] init];
- self.flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
- self.flowLayout.minimumLineSpacing = 0;
- self.flowLayout.minimumInteritemSpacing = 0;
-
- // 创建CollectionView
- self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds
- collectionViewLayout:self.flowLayout];
- self.collectionView.backgroundColor = [UIColor blackColor];
- self.collectionView.delegate = self;
- self.collectionView.dataSource = self;
- self.collectionView.pagingEnabled = YES; // 分页滚动
- self.collectionView.showsVerticalScrollIndicator = NO;
- self.collectionView.showsHorizontalScrollIndicator = NO;
-
- // 注册Cell
- [self.collectionView registerClass:[JXShortDramaCell class]
- forCellWithReuseIdentifier:kDramaCellIdentifier];
-
- [self.view addSubview:self.collectionView];
- // 添加下拉刷新
- self.refreshControl = [[UIRefreshControl alloc] init];
- self.refreshControl.tintColor = [UIColor whiteColor];
- [self.refreshControl addTarget:self
- action:@selector(handleRefresh)
- forControlEvents:UIControlEventValueChanged];
- [self.collectionView addSubview:self.refreshControl];
-
-
- self.searchBar = [[SearchCommonBarView alloc] init];
-
- self.searchBar.backgroundColor = [UIColor clearColor];
- __weak typeof(self) weakSelf = self;
- self.searchBar.searchAction = ^(NSString * _Nonnull text) {
- [weakSelf performSearchWithKeyword:text];
- };
- [self.view addSubview:self.searchBar];
- [self.view bringSubviewToFront:self.searchBar];
- [self.searchBar mas_makeConstraints:^(MASConstraintMaker *make) {
- make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
- make.left.right.equalTo(self.view);
- make.height.mas_equalTo(44);
- }];
-
- }
- - (void)performSearchWithKeyword:(NSString *)keyword {
- if (keyword.length == 0) {
- return;
- }
-
- JXSearchViewController *vc = [[JXSearchViewController alloc] initWithKeyword:keyword];
- [self.navigationController pushViewController:vc animated:YES];
- }
- #pragma mark - 数据加载
- - (void)loadInitialData {
- self.currentPage = 1;
- [self loadDramaListWithPage:1 append:NO];
- }
- - (void)loadMoreData {
- if (self.isLoading || !self.hasMoreData) {
- return;
- }
-
- self.currentPage++;
- [self loadDramaListWithPage:self.currentPage append:YES];
- }
- - (void)loadDramaListWithPage:(NSInteger)page append:(BOOL)append {
- if (self.isLoading) {
- return;
- }
-
- self.isLoading = YES;
-
- [[JXAPIService sharedService] getDramaListWithCategoryId:self.categoryId
- page:page
- pageSize:10
- success:^(id response) {
- self.isLoading = NO;
- [self.refreshControl endRefreshing];
-
- NSDictionary *data = response[@"data"];
- NSArray *items = data[@"items"]; // 后端返回的字段是 "items" 不是 "list"
-
-
- if (items.count == 0) {
- self.hasMoreData = NO;
- return;
- }
-
- // 转换为模型
- NSMutableArray *models = [NSMutableArray array];
- for (NSDictionary *dict in items) {
- JXDramaContent *drama = [[JXDramaContent alloc] initWithDictionary:dict];
- [models addObject:drama];
- }
-
- if (append) {
- [self.dramaList addObjectsFromArray:models];
- } else {
- self.dramaList = models;
- }
-
- [self.collectionView reloadData];
- [self.collectionView setContentOffset:CGPointMake(0, 0) animated:YES];
- // 首次加载后,只有用户已访问才自动播放
- if (!append && models.count > 0) {
- if (self.hasUserVisited) {
- // 获取第一个短剧的详情(包含播放源)
- // 注:使用 jx_drama_id(剧星平台ID)而不是本地 dramaId
- JXDramaContent *firstDrama = models[0];
- [[JXAPIService sharedService] getDramaDetailWithDramaId:[@(firstDrama.dramaId) stringValue]
- success:^(id response) {
- NSDictionary *data = response[@"data"];
- NSDictionary *dramaDict = data[@"drama"];
- NSArray *episodes = data[@"episodes"];
- if (dramaDict) {
- firstDrama.videoUrl = dramaDict[@"video_url"];
- // 从第一集中提取播放源(tcplayer字段在episodes中)
- if (episodes && episodes.count > 0) {
- NSDictionary *firstEpisode = episodes[0];
- firstDrama.appId = firstEpisode[@"tcplayer_app_id"];
- firstDrama.fileId = firstEpisode[@"tcplayer_file_id"];
- firstDrama.psign = firstEpisode[@"tcplayer_sign"] ?: firstEpisode[@"tcplayer_sign_265"] ?: firstEpisode[@"tcplayer_sign_264"];
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self playVideoAtIndex:0];
- });
- } else {
- // 如果详情接口没返回episodes,尝试单独获取剧集列表
- [[JXAPIService sharedService] getEpisodesWithDramaId:[@(firstDrama.dramaId) stringValue]
- success:^(id episodesResponse) {
- NSArray *episodesList = episodesResponse[@"data"][@"episodes"];
- if (episodesList && episodesList.count > 0) {
- NSDictionary *firstEp = episodesList[0];
- firstDrama.appId = firstEp[@"tcplayer_app_id"];
- firstDrama.fileId = firstEp[@"tcplayer_file_id"];
- firstDrama.psign = firstEp[@"tcplayer_sign"] ?: firstEp[@"tcplayer_sign_265"] ?: firstEp[@"tcplayer_sign_264"];
- }
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self playVideoAtIndex:0];
- });
- } failure:^(NSError *error) {
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self playVideoAtIndex:0];
- });
- }];
- }
- }
- } failure:^(NSError *error) {
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self playVideoAtIndex:0];
- });
- }];
- self.isFirstLoad = NO;
- }
- }
-
- } failure:^(NSError *error) {
- self.isLoading = NO;
- [self.refreshControl endRefreshing];
- NSLog(@"[JXShortDrama] 加载失败: %@", error.localizedDescription);
-
- // TODO: 显示错误提示
- }];
- }
- - (void)handleRefresh {
- self.hasMoreData = YES;
- [self loadInitialData];
- }
- #pragma mark - UICollectionViewDataSource
- - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
- return self.dramaList.count;
- }
- - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
- cellForItemAtIndexPath:(NSIndexPath *)indexPath {
-
- JXShortDramaCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kDramaCellIdentifier
- forIndexPath:indexPath];
-
- // 设置代理
- cell.delegate = self;
- NSLog(@"[JXShortDrama] ✅ cellForItemAtIndexPath - Cell delegate 已设置,index: %ld", (long)indexPath.item);
-
- // 配置数据
- JXDramaContent *drama = self.dramaList[indexPath.item];
- [cell configureWithDrama:drama];
- NSLog(@"[JXShortDrama] ✅ cellForItemAtIndexPath - Drama 已配置,dramaId: %lld, title: %@", drama.dramaId, drama.title);
-
- return cell;
- }
- #pragma mark - UICollectionViewDelegateFlowLayout
- - (CGSize)collectionView:(UICollectionView *)collectionView
- layout:(UICollectionViewLayout *)collectionViewLayout
- sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
- // 每个Cell占满全屏
- return self.view.bounds.size;
- }
- #pragma mark - UIScrollViewDelegate
- - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
- // 计算当前显示的索引
- CGFloat pageHeight = scrollView.bounds.size.height;
- NSInteger newIndex = (NSInteger)(scrollView.contentOffset.y / pageHeight);
- NSLog(@"[JXShortDrama] ========== 滑动结束 ==========");
- NSLog(@"[JXShortDrama] 旧索引: %ld, 新索引: %ld", (long)self.currentIndex, (long)newIndex);
- if (newIndex != self.currentIndex) {
- // 停止旧视频
- NSLog(@"[JXShortDrama] 停止旧视频: 索引 %ld", (long)self.currentIndex);
- [self stopVideoAtIndex:self.currentIndex];
- // 播放新视频
- NSLog(@"[JXShortDrama] 播放新视频: 索引 %ld", (long)newIndex);
- self.currentIndex = newIndex;
- [self playVideoAtIndex:newIndex];
- } else {
- // 索引没变,说明用户滑动后又回到原位
- // 需要恢复播放(之前在scrollViewWillBeginDragging中暂停了)
- NSLog(@"[JXShortDrama] 索引未变化,恢复当前视频播放");
- [self resumeCurrentVideo];
- }
- // 预加载逻辑
- if (newIndex >= self.dramaList.count - 3 && self.hasMoreData) {
- NSLog(@"[JXShortDrama] 触发预加载逻辑");
- [self loadMoreData];
- }
- }
- - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
- // 用户开始滑动时,暂停当前视频
- [self pauseCurrentVideo];
- }
- #pragma mark - 播放器管理
- - (void)playVideoAtIndex:(NSInteger)index {
- NSLog(@"[JXShortDrama] playVideoAtIndex:%ld", (long)index);
- if (index < 0 || index >= self.dramaList.count) {
- NSLog(@"[JXShortDrama] ❌ 索引越界: index=%ld, count=%ld", (long)index, (long)self.dramaList.count);
- return;
- }
- JXDramaContent *drama = self.dramaList[index];
- // 检查是否已有播放信息
- if ([self hasPlayInfo:drama]) {
- // 已有播放信息,直接播放
- [self doPlayVideoAtIndex:index];
- } else {
- // 需要获取播放信息
- NSLog(@"[JXShortDrama] 需要获取播放信息: dramaId=%lld", drama.dramaId);
- [self loadPlayInfoForDrama:drama atIndex:index];
- }
- }
- - (BOOL)hasPlayInfo:(JXDramaContent *)drama {
- // 检查是否有播放所需的信息
- if ([drama isFileIdMode]) {
- return drama.fileId && drama.appId && drama.psign;
- } else if ([drama isUrlMode]) {
- return drama.videoUrl;
- }
- return NO;
- }
- - (void)doPlayVideoAtIndex:(NSInteger)index {
- // 启动播放
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
- if (cell) {
- NSLog(@"[JXShortDrama] 找到Cell,开始播放");
- [cell startPlay];
- } else {
- NSLog(@"[JXShortDrama] ❌ 未找到Cell");
- }
- }
- - (void)loadPlayInfoForDrama:(JXDramaContent *)drama atIndex:(NSInteger)index {
- // 显示加载指示器
- [self showLoadingIndicatorForCellAtIndex:index];
- // 获取剧集详情,包含播放信息
- [[JXAPIService sharedService] getDramaDetailWithDramaId:[@(drama.dramaId) stringValue]
- success:^(id response) {
- NSLog(@"[JXShortDrama] 获取到剧集详情响应: %@", response);
- NSDictionary *data = response[@"data"];
- NSArray *episodes = data[@"episodes"];
- NSLog(@"[JXShortDrama] 解析数据:");
- NSLog(@"[JXShortDrama] - 完整响应: %@", response);
- NSLog(@"[JXShortDrama] - data字典: %@", data);
- NSLog(@"[JXShortDrama] - episodes数组: %@", episodes);
- NSLog(@"[JXShortDrama] - episodes数量: %lu", (unsigned long)episodes.count);
- if (episodes) {
- for (int i = 0; i < MIN(2, episodes.count); i++) {
- NSDictionary *episode = episodes[i];
- NSLog(@"[JXShortDrama] - 第%d集: %@", i+1, episode);
- }
- }
- if (episodes && episodes.count > 0) {
- NSDictionary *firstEpisode = episodes[0];
- // 提取播放信息
- drama.appId = firstEpisode[@"tcplayer_app_id"];
- drama.fileId = firstEpisode[@"tcplayer_file_id"];
- // 优先使用H.264格式
- drama.psign = firstEpisode[@"tcplayer_sign_264"] ?:
- firstEpisode[@"tcplayer_sign"] ?:
- firstEpisode[@"tcplayer_sign_265"];
- // 如果都没有,尝试其他可能的字段名
- if (!drama.psign) {
- drama.psign = firstEpisode[@"sign"] ?: firstEpisode[@"psign"];
- }
- // 备用URL模式
- drama.videoUrl = firstEpisode[@"video_url"];
- NSLog(@"[JXShortDrama] 播放信息已加载: appId=%@, fileId=%@, psign长度=%lu",
- drama.appId, drama.fileId, (unsigned long)drama.psign.length);
- // 隐藏加载指示器
- [self hideLoadingIndicatorForCellAtIndex:index];
- // 现在可以播放了
- [self doPlayVideoAtIndex:index];
- } else {
- [self hideLoadingIndicatorForCellAtIndex:index];
- NSLog(@"[JXShortDrama] ❌ 获取播放信息失败: 剧集数据为空");
- }
- } failure:^(NSError *error) {
- [self hideLoadingIndicatorForCellAtIndex:index];
- NSLog(@"[JXShortDrama] ❌ 获取播放信息失败: %@", error.localizedDescription);
- }];
- }
- - (void)stopVideoAtIndex:(NSInteger)index {
- if (index < 0 || index >= self.dramaList.count) {
- return;
- }
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
- [cell stopPlay];
- }
- - (void)pauseCurrentVideo {
- if (self.currentIndex < 0 || self.currentIndex >= self.dramaList.count) {
- return;
- }
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.currentIndex inSection:0]];
- [cell pausePlay];
- }
- - (void)resumeCurrentVideo {
- if (self.currentIndex < 0 || self.currentIndex >= self.dramaList.count) {
- return;
- }
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.currentIndex inSection:0]];
- [cell resumePlay];
- }
- - (void)pauseAllVideos {
- // 暂停所有可见的Cell
- for (NSIndexPath *indexPath in self.collectionView.indexPathsForVisibleItems) {
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
- [cell pausePlay];
- }
- }
- #pragma mark - 交互按钮处理
- - (void)handleLikeButtonAtIndex:(NSInteger)index {
- // 登录检查
- BOOL isLoggedIn = [[GuestHelper sharedHelper] checkLoginWithViewController:self action:^{
- // 登录成功后重新执行点赞操作
- // [self handleLikeButtonAtIndex:index];
- }];
-
- if (!isLoggedIn) {
- return; // 未登录,等待用户登录
- }
-
- JXDramaContent *drama = self.dramaList[index];
-
- // 点赞动画
- [self animateLikeButtonAtIndex:index];
-
- [[JXAPIService sharedService] toggleLikeWithDramaId:[@(drama.dramaId) stringValue]
- episodeId:drama.episodeId
- success:^(id response) {
- // 更新UI
- BOOL isLiked = [response[@"data"][@"isLiked"] boolValue];
- long long likeCount = [response[@"data"][@"likeCount"] longLongValue];
-
- drama.isLiked = isLiked;
- drama.likeCount = likeCount;
-
- // 更新Cell UI(直接更新,不刷新列表)
- [self updateLikeCountUI:likeCount isLiked:isLiked atIndex:index];
- } failure:^(NSError *error) {
- NSLog(@"[JXShortDrama] 点赞失败: %@", error.localizedDescription);
- }];
- }
- - (void)handleFavoriteButtonAtIndex:(NSInteger)index {
- // 登录检查
- BOOL isLoggedIn = [[GuestHelper sharedHelper] checkLoginWithViewController:self action:^{
- // 登录成功后重新执行收藏操作
- // [self handleFavoriteButtonAtIndex:index];
- }];
-
- if (!isLoggedIn) {
- return; // 未登录,等待用户登录
- }
-
- JXDramaContent *drama = self.dramaList[index];
-
- // 收藏动画
- [self animateFavoriteButtonAtIndex:index];
-
- [[JXAPIService sharedService] toggleFavoriteWithDramaId:[@(drama.dramaId) stringValue]
- success:^(id response) {
- // 更新UI
- BOOL isFavorited = [response[@"data"][@"isFavorited"] boolValue];
- long long favoriteCount = [response[@"data"][@"favoriteCount"] longLongValue];
-
- drama.isFavorited = isFavorited;
- drama.favoriteCount = favoriteCount;
-
- // 更新Cell UI(直接更新,不刷新列表)
- [self updateFavoriteCountUI:favoriteCount isFavorited:isFavorited atIndex:index];
- } failure:^(NSError *error) {
- NSLog(@"[JXShortDrama] 收藏失败: %@", error.localizedDescription);
- }];
- }
- - (void)handleCommentButtonAtIndex:(NSInteger)index {
- NSLog(@"[JXShortDrama] ========== 💬 handleCommentButtonAtIndex 开始 ==========");
- NSLog(@"[JXShortDrama] 💬 index: %ld", (long)index);
- NSLog(@"[JXShortDrama] 💬 dramaList count: %lu", (unsigned long)self.dramaList.count);
-
- // 登录检查
- NSLog(@"[JXShortDrama] 💬 开始登录检查...");
- BOOL isLoggedIn = [[GuestHelper sharedHelper] checkLoginWithViewController:self action:^{
- NSLog(@"[JXShortDrama] 💬 登录完成,重新调用 handleCommentButtonAtIndex");
- // 登录成功后重新打开评论
-
- }];
-
- NSLog(@"[JXShortDrama] 💬 登录检查结果: %@", isLoggedIn ? @"已登录 ✅" : @"未登录,等待登录");
-
- if (!isLoggedIn) {
- NSLog(@"[JXShortDrama] 💬 用户未登录,等待登录完成后再处理");
- return; // 未登录,等待用户登录
- }
-
- NSLog(@"[JXShortDrama] 💬 用户已登录,获取 drama 数据");
- if (index < 0 || index >= self.dramaList.count) {
- NSLog(@"[JXShortDrama] ❌ 索引越界,index: %ld, count: %lu", (long)index, (unsigned long)self.dramaList.count);
- return;
- }
-
- JXDramaContent *drama = self.dramaList[index];
- NSLog(@"[JXShortDrama] 💬 drama: %@, dramaId: %lld", drama.title, drama.dramaId);
- // 显示评论弹窗
- NSLog(@"[JXShortDrama] 💬 显示评论弹窗...");
- [self showCommentDialogWithDramaId:[@(drama.dramaId) stringValue]];
- NSLog(@"[JXShortDrama] 💬 评论弹窗已显示");
- }
- - (void)handleCollectionButtonAtIndex:(NSInteger)index {
- JXDramaContent *drama = self.dramaList[index];
- // 显示合集弹窗
- [self showCollectionDialogWithDramaId:[@(drama.dramaId) stringValue]];
- }
- #pragma mark - JXShortDramaCellDelegate
- - (void)shortDramaCellDidTapLike:(UICollectionViewCell *)cell {
- NSLog(@"[JXShortDramaViewController] 📍 shortDramaCellDidTapLike 被调用");
- NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
- NSLog(@"[JXShortDramaViewController] indexPath: %@", indexPath);
- if (indexPath) {
- [self handleLikeButtonAtIndex:indexPath.item];
- } else {
- NSLog(@"[JXShortDramaViewController] ❌ 无法获取 indexPath");
- }
- }
- - (void)shortDramaCellDidTapFavorite:(UICollectionViewCell *)cell {
- NSLog(@"[JXShortDramaViewController] 📍 shortDramaCellDidTapFavorite 被调用");
- NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
- NSLog(@"[JXShortDramaViewController] indexPath: %@", indexPath);
- if (indexPath) {
- [self handleFavoriteButtonAtIndex:indexPath.item];
- } else {
- NSLog(@"[JXShortDramaViewController] ❌ 无法获取 indexPath");
- }
- }
- - (void)shortDramaCellDidTapComment:(UICollectionViewCell *)cell {
- NSLog(@"[JXShortDramaViewController] ========== 📍 shortDramaCellDidTapComment 被调用 ==========");
- NSLog(@"[JXShortDramaViewController] 📍 cell: %@", cell);
- NSLog(@"[JXShortDramaViewController] 📍 cell class: %@", [cell class]);
-
- NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
- NSLog(@"[JXShortDramaViewController] 📍 indexPath: %@", indexPath);
-
- if (indexPath) {
- NSLog(@"[JXShortDramaViewController] 📍 indexPath.item: %ld", (long)indexPath.item);
- [self handleCommentButtonAtIndex:indexPath.item];
- } else {
- NSLog(@"[JXShortDramaViewController] ❌ 无法获取 indexPath");
- }
- }
- - (void)shortDramaCellDidTapCollection:(UICollectionViewCell *)cell {
- NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
- if (indexPath) {
- [self handleCollectionButtonAtIndex:indexPath.item];
- }
- }
- - (void)shortDramaCellDidTapDetail:(UICollectionViewCell *)cell {
- NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
- if (indexPath) {
- JXDramaContent *drama = self.dramaList[indexPath.item];
- NSLog(@"🎬 点击查看全部/详情,dramaId: %lld", drama.dramaId);
-
- // 跳转到详情页
- JXDetailViewController *detailVC = [[JXDetailViewController alloc] initWithDramaId:[@(drama.dramaId) stringValue]];
- [self.navigationController pushViewController:detailVC animated:YES];
- }
- }
- // 加载指示器管理
- - (void)showLoadingIndicatorForCellAtIndex:(NSInteger)index {
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
- if (cell) {
- // 在Cell上显示加载指示器
- UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
- indicator.center = CGPointMake(cell.bounds.size.width / 2, cell.bounds.size.height / 2);
- indicator.tag = 999; // 用于标识和移除
- [cell.contentView addSubview:indicator];
- [indicator startAnimating];
- // 添加半透明背景
- UIView *backgroundView = [[UIView alloc] initWithFrame:cell.bounds];
- backgroundView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
- backgroundView.tag = 998;
- [cell.contentView insertSubview:backgroundView belowSubview:indicator];
- }
- }
- - (void)hideLoadingIndicatorForCellAtIndex:(NSInteger)index {
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
- if (cell) {
- // 移除加载指示器
- UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)[cell.contentView viewWithTag:999];
- [indicator removeFromSuperview];
- // 移除背景
- UIView *backgroundView = (UIView *)[cell.contentView viewWithTag:998];
- [backgroundView removeFromSuperview];
- }
- }
- - (void)shortDramaCellDidFailToPlay:(UICollectionViewCell *)cell {
- NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
- if (indexPath) {
- JXDramaContent *drama = self.dramaList[indexPath.item];
- NSLog(@"[JXShortDrama] 播放失败,重新获取剧集数据: dramaId=%lld", drama.dramaId);
- // 显示加载指示器
- [self showLoadingIndicatorForCellAtIndex:indexPath.item];
- // 重新获取剧集详情,确保获取最新的播放签名
- [[JXAPIService sharedService] getDramaDetailWithDramaId:[@(drama.dramaId) stringValue]
- success:^(id response) {
- NSDictionary *data = response[@"data"];
- NSArray *episodes = data[@"episodes"];
- if (episodes && episodes.count > 0) {
- NSDictionary *firstEpisode = episodes[0];
- // 更新drama对象的播放数据
- drama.appId = firstEpisode[@"tcplayer_app_id"];
- drama.fileId = firstEpisode[@"tcplayer_file_id"];
- // 优先使用H.264格式(更兼容)
- drama.psign = firstEpisode[@"tcplayer_sign_264"] ?:
- firstEpisode[@"tcplayer_sign"] ?:
- firstEpisode[@"tcplayer_sign_265"];
- NSLog(@"[JXShortDrama] 剧集数据已刷新,重新尝试播放: appId=%@, fileId=%@",
- drama.appId, drama.fileId);
- // 隐藏加载指示器
- [self hideLoadingIndicatorForCellAtIndex:indexPath.item];
- // 重新尝试播放
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self playVideoAtIndex:indexPath.item];
- });
- } else {
- [self hideLoadingIndicatorForCellAtIndex:indexPath.item];
- NSLog(@"[JXShortDrama] 刷新后无可用剧集数据");
- }
- } failure:^(NSError *error) {
- [self hideLoadingIndicatorForCellAtIndex:indexPath.item];
- NSLog(@"[JXShortDrama] 刷新剧集数据失败: %@", error.localizedDescription);
- }];
- }
- }
- #pragma mark - 弹窗显示
- - (void)showCommentDialogWithDramaId:(NSString *)dramaId {
- NSLog(@"[JXShortDrama] ========== 🗨️ showCommentDialogWithDramaId 开始 ==========");
- NSLog(@"[JXShortDrama] 🗨️ dramaId: %@", dramaId);
-
- NSLog(@"[JXShortDrama] 🗨️ 创建 JXCommentViewController...");
- JXCommentViewController *commentVC = [[JXCommentViewController alloc] initWithDramaId:dramaId];
- NSLog(@"[JXShortDrama] 🗨️ commentVC 已创建: %@", commentVC);
-
- // 设置弹窗样式(底部弹出)
- if (@available(iOS 15.0, *)) {
- NSLog(@"[JXShortDrama] 🗨️ 配置 iOS 15+ 的 Sheet 弹窗样式");
- UISheetPresentationController *sheet = commentVC.sheetPresentationController;
- sheet.detents = @[
- [UISheetPresentationControllerDetent mediumDetent],
- [UISheetPresentationControllerDetent largeDetent]
- ];
- sheet.prefersGrabberVisible = YES;
- NSLog(@"[JXShortDrama] 🗨️ Sheet 样式配置完成");
- } else {
- NSLog(@"[JXShortDrama] 🗨️ iOS 版本 < 15.0,跳过 Sheet 样式配置");
- }
-
- NSLog(@"[JXShortDrama] 🗨️ 正在 present commentVC...");
- [self presentViewController:commentVC animated:YES completion:^{
- NSLog(@"[JXShortDrama] 🗨️ commentVC present 完成!");
- }];
- }
- - (void)showCollectionDialogWithDramaId:(NSString *)dramaId {
- JXCollectionViewController *collectionVC = [[JXCollectionViewController alloc] initWithDramaId:dramaId];
- collectionVC.delegate = self;
-
- // 设置弹窗样式(底部弹出)
- if (@available(iOS 15.0, *)) {
- UISheetPresentationController *sheet = collectionVC.sheetPresentationController;
- sheet.detents = @[
- [UISheetPresentationControllerDetent mediumDetent],
- [UISheetPresentationControllerDetent largeDetent]
- ];
- sheet.prefersGrabberVisible = YES;
- }
-
- [self presentViewController:collectionVC animated:YES completion:nil];
- }
- #pragma mark - JXCollectionViewControllerDelegate
- - (void)collectionViewControllerDidSelectEpisode:(NSString *)episodeId {
- NSLog(@"[JXShortDrama] 选择播放剧集: %@", episodeId);
- JXDramaContent *drama = self.dramaList[self.currentIndex];
- JXDetailViewController *detailVC = [[JXDetailViewController alloc] initWithDramaId:[NSString stringWithFormat:@"%lld",drama.dramaId]];
- detailVC.playIndex = (episodeId.intValue-1 < 0) ? 0 : episodeId.intValue-1;
- [self.navigationController pushViewController:detailVC animated:YES];
-
-
- // JXDetailViewController *detailVC = [[JXDetailViewController alloc] initWithDramaId:episodeId];
- // [self.navigationController pushViewController:detailVC animated:YES];
-
-
- // TODO: 切换到选定的剧集播放
- // 可以找到对应的短剧,然后滚动到该位置并播放
- }
- #pragma mark - 动画效果
- - (void)animateLikeButtonAtIndex:(NSInteger)index {
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
-
- if (cell && [cell respondsToSelector:@selector(likeButton)]) {
- UIButton *likeButton = [cell valueForKey:@"likeButton"];
- if (likeButton) {
- // 缩放动画:放大 -> 恢复
- [UIView animateWithDuration:0.15 animations:^{
- likeButton.transform = CGAffineTransformMakeScale(1.3, 1.3);
- } completion:^(BOOL finished) {
- [UIView animateWithDuration:0.15 animations:^{
- likeButton.transform = CGAffineTransformIdentity;
- }];
- }];
- }
- }
- }
- - (void)animateFavoriteButtonAtIndex:(NSInteger)index {
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
-
- if (cell && [cell respondsToSelector:@selector(favoriteButton)]) {
- UIButton *favoriteButton = [cell valueForKey:@"favoriteButton"];
- if (favoriteButton) {
- // 缩放动画:放大 -> 恢复
- [UIView animateWithDuration:0.15 animations:^{
- favoriteButton.transform = CGAffineTransformMakeScale(1.3, 1.3);
- } completion:^(BOOL finished) {
- [UIView animateWithDuration:0.15 animations:^{
- favoriteButton.transform = CGAffineTransformIdentity;
- }];
- }];
- }
- }
- }
- #pragma mark - UI 更新(避免视频停止)
- - (void)updateLikeCountUI:(NSInteger)likeCount isLiked:(BOOL)isLiked atIndex:(NSInteger)index {
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
-
- if (cell && [cell respondsToSelector:@selector(updateLikeCount:isLiked:)]) {
- [cell updateLikeCount:likeCount isLiked:isLiked];
- }
- }
- - (void)updateFavoriteCountUI:(NSInteger)favoriteCount isFavorited:(BOOL)isFavorited atIndex:(NSInteger)index {
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
- JXShortDramaCell *cell = (JXShortDramaCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
-
- if (cell && [cell respondsToSelector:@selector(updateFavoriteCount:isFavorited:)]) {
- [cell updateFavoriteCount:favoriteCount isFavorited:isFavorited];
- }
- }
- @end
|