| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644 |
- //
- // VideoDetailCell.m
- // AICity
- //
- // Created by 张国栋 on 2025/10/22.
- // Copyright © 2025 wei.z. All rights reserved.
- //
- #import "VideoDetailCell.h"
- #import "JXSuperPlayer.h"
- #import "JXDramaContent.h"
- #import "JXInteraction.h"
- #import "GuestHelper.h"
- #import "JXEpisode.h"
- @interface VideoDetailCell () <JXSuperPlayerDelegate>
- #pragma mark - UI组件
- // 播放器容器
- @property (nonatomic, strong) UIView *playerContainerView;
- // 右侧交互按钮组
- @property (nonatomic, strong) UIButton *likeButton;
- @property (nonatomic, strong) UILabel *likeCountLabel;
- @property (nonatomic, strong) UIButton *favoriteButton;
- @property (nonatomic, strong) UILabel *favoriteCountLabel;
- @property (nonatomic, strong) UIButton *commentButton;
- @property (nonatomic, strong) UILabel *commentCountLabel;
- @property (nonatomic, strong) UIButton *collectionButton;
- // 底部信息区
- @property (nonatomic, strong) UIView *bottomInfoView;
- @property (nonatomic, strong) UILabel *titleLabel;
- @property (nonatomic, strong) UILabel *descriptionLabel;
- #pragma mark - 数据 JXEpisode
- @property (nonatomic, strong) JXEpisode *drama;
- #pragma mark - 播放器
- @property (nonatomic, strong) JXSuperPlayer *superPlayer;
- @property (nonatomic, assign) JXSuperPlayerState playerState; // 播放器状态
- // 播放超时检测
- @property (nonatomic, strong) NSTimer *playTimeoutTimer; // 播放超时检测定时器
- @property (nonatomic, strong) NSDate *playStartTime; // 播放开始时间
- @property (strong, nonatomic) UISlider *videoSlider;
- @end
- @implementation VideoDetailCell
- #pragma mark - 初始化
- - (instancetype)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- if (self) {
- [self setupUI];
- }
- return self;
- }
- - (void)prepareForReuse {
- [super prepareForReuse];
-
- NSLog(@"[JXShortDramaCell] prepareForReuse - 停止当前播放");
-
- // 只停止播放,不释放播放器实例
- // 重用播放器实例可以避免频繁创建销毁导致的连接问题
- [self stopPlay];
-
- // 停止超时检测
- [self stopPlayTimeoutTimer];
- }
- #pragma mark - UI设置
- - (void)setupUI {
- self.contentView.backgroundColor = [UIColor blackColor];
-
- // 创建播放器容器
- [self setupPlayerContainer];
-
- // 创建交互按钮组
- [self setupInteractionButtons];
-
- // 创建底部信息区
- [self setupBottomInfo];
-
-
-
- }
- - (void)setupPlayerContainer {
- self.playerContainerView = [[UIView alloc] init];
- self.playerContainerView.backgroundColor = [UIColor blackColor];
- [self.contentView addSubview:self.playerContainerView];
-
- // 约束 - 播放器下边界贴近底部导航栏(44pt高)
- self.playerContainerView.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [self.playerContainerView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor],
- [self.playerContainerView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor],
- [self.playerContainerView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor],
- [self.playerContainerView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-44]
- ]];
- }
- - (void)setupInteractionButtons {
- // // 点赞按钮
- // [self addLikeButton];
- //
- // // 收藏按钮
- // [self addFavoriteButton];
- //
- // // 评论按钮
- // [self addCommentButton];
- //
- // // 合集按钮
- // [self addCollectionButton];
-
- CGFloat width = self.contentView.bounds.size.width;
- UIView *container = [[UIView alloc] initWithFrame:CGRectMake(width - 48, kScreenHeight - safebottom - 190 - 90, 32, 190)];
- [self.contentView addSubview:container];
-
-
- // 点赞
- UIButton *likeButton = [UIButton buttonWithType:UIButtonTypeCustom];
- likeButton.frame = CGRectMake(0, 0, 32, 32);
- [likeButton setImage:[UIImage imageNamed:@"icon 1.1"] forState:UIControlStateNormal];
- [likeButton setImage:[UIImage imageNamed:@"icon 1.5"] forState:UIControlStateSelected];
- [container addSubview:likeButton];
-
- UILabel *likeCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 40, 32, 18)];
- likeCountLabel.textAlignment = NSTextAlignmentCenter;
- likeCountLabel.font = [UIFont systemFontOfSize:12];
- likeCountLabel.textColor = [UIColor whiteColor];
- // likeCountLabel.text = [self formatCount:self.interaction.likeCount];
- [container addSubview:likeCountLabel];
- self.likeButton = likeButton;
- self.likeCountLabel = likeCountLabel;
-
- // 收藏
- UIButton *favoriteButton = [UIButton buttonWithType:UIButtonTypeCustom];
- favoriteButton.frame = CGRectMake(0, CGRectGetMaxY(likeCountLabel.frame) + 20, 32, 32);
- [favoriteButton setImage:[UIImage imageNamed:@"icon 1.2"] forState:UIControlStateNormal];
- [favoriteButton setImage:[UIImage imageNamed:@"icon 1.5"] forState:UIControlStateSelected];
- [container addSubview:favoriteButton];
-
- UILabel *favoriteCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(favoriteButton.frame), 32, 18)];
- favoriteCountLabel.textAlignment = NSTextAlignmentCenter;
- favoriteCountLabel.font = [UIFont systemFontOfSize:12];
- favoriteCountLabel.textColor = [UIColor whiteColor];
- // favoriteCountLabel.text = [self formatCount:self.interaction.favoriteCount];
- [container addSubview:favoriteCountLabel];
- self.favoriteButton = favoriteButton;
- self.favoriteCountLabel = favoriteCountLabel;
-
- // 评论
- UIButton *commentButton = [UIButton buttonWithType:UIButtonTypeCustom];
- commentButton.frame = CGRectMake(0, CGRectGetMaxY(favoriteCountLabel.frame) + 20, 32, 32);
- [commentButton setImage:[UIImage imageNamed:@"icon 1.3"] forState:UIControlStateNormal];
- [container addSubview:commentButton];
- [commentButton addTarget:self action:@selector(handleCommentTap) forControlEvents:UIControlEventTouchUpInside];
- UILabel *commentCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(commentButton.frame) , 32, 18)];
- commentCountLabel.textAlignment = NSTextAlignmentCenter;
- commentCountLabel.font = [UIFont systemFontOfSize:12];
- commentCountLabel.textColor = [UIColor whiteColor];
- // commentCountLabel.text = [self formatCount:self.interaction.commentCount];
- [container addSubview:commentCountLabel];
- self.commentCountLabel = commentCountLabel;
- }
- //- (void)addLikeButton {
- //
- // UIView *likeContainer = [[UIView alloc] initWithFrame:CGRectMake(self.frame.size.width-48, self.frame.size.height-BAR_HEIGHT - 100 - 130, 32, 50)];
- // self.likeButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
- // [self.likeButton setImage:[UIImage imageNamed:@"icon 1.1"] forState:UIControlStateNormal];
- // [self.likeButton setImage:[UIImage imageNamed:@"icon 1.5"] forState:UIControlStateSelected];
- // self.likeButton.tintColor = [UIColor whiteColor];
- // [self.likeButton addTarget:self action:@selector(handleLikeTap) forControlEvents:UIControlEventTouchUpInside];
- // [likeContainer addSubview:self.likeButton];
- // self.likeCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 32, 32, 18)];
- // self.likeCountLabel.textColor = [UIColor whiteColor];
- // self.likeCountLabel.font = [UIFont systemFontOfSize:12];
- // self.likeCountLabel.textAlignment = NSTextAlignmentCenter;
- // self.likeCountLabel.text = @"0";
- // [likeContainer addSubview:self.likeCountLabel];
- // [self.contentView addSubview:likeContainer];
- //}
- //
- //- (void)addFavoriteButton {
- //
- // UIView *favoriteContainer = [[UIView alloc] initWithFrame:CGRectMake(self.frame.size.width-48, self.frame.size.height-BAR_HEIGHT - 100 - 65, 32, 50)];
- // self.favoriteButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
- // [self.favoriteButton setImage:[UIImage imageNamed:@"icon 1.2"] forState:UIControlStateNormal];
- // [self.favoriteButton setImage:[UIImage imageNamed:@"icon 1.5"] forState:UIControlStateSelected];
- // self.favoriteButton.tintColor = [UIColor whiteColor];
- // [self.favoriteButton addTarget:self action:@selector(handleFavoriteTap) forControlEvents:UIControlEventTouchUpInside];
- // [favoriteContainer addSubview:self.favoriteButton];
- // self.favoriteCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 32, 32, 18)];
- // self.favoriteCountLabel.textColor = [UIColor whiteColor];
- // self.favoriteCountLabel.font = [UIFont systemFontOfSize:12];
- // self.favoriteCountLabel.textAlignment = NSTextAlignmentCenter;
- // self.favoriteCountLabel.text = @"0";
- // [favoriteContainer addSubview:self.favoriteCountLabel];
- // [self.contentView addSubview:favoriteContainer];
- //}
- //
- //- (void)addCommentButton {
- // UIView *commentContainer = [[UIView alloc] initWithFrame:CGRectMake(self.frame.size.width-48, self.frame.size.height-BAR_HEIGHT - 100, 32, 50)];
- // self.commentButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
- // [self.commentButton setImage:[UIImage imageNamed:@"icon 1.3"] forState:UIControlStateNormal];
- // self.commentButton.tintColor = [UIColor whiteColor];
- // [self.commentButton addTarget:self action:@selector(handleCommentTap) forControlEvents:UIControlEventTouchUpInside];
- // [commentContainer addSubview:self.commentButton];
- // self.commentCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 32, 32, 18)];
- // self.commentCountLabel.textColor = [UIColor whiteColor];
- // self.commentCountLabel.font = [UIFont systemFontOfSize:12];
- // self.commentCountLabel.textAlignment = NSTextAlignmentCenter;
- // self.commentCountLabel.text = @"0";
- // [commentContainer addSubview:self.commentCountLabel];
- // [self.contentView addSubview:commentContainer];
- //}
- //
- //- (void)addCollectionButton {
- // UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - 38 - BAR_HEIGHT, SCREEN_WIDTH, 38)];
- // bottomView.backgroundColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:0.1];
- // [self.contentView addSubview:bottomView];
- // UIImageView *sImgView = [[UIImageView alloc] initWithFrame:CGRectMake(16, 10.5, 17, 17)];
- // sImgView.image = [UIImage imageNamed:@"icon 2.1 拷贝"];
- // [bottomView addSubview:sImgView];
- // UILabel *hjL = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(sImgView.frame)+4, 0, 100, 38)];
- // [bottomView addSubview:hjL];
- // hjL.font = [UIFont boldSystemFontOfSize:18];
- // hjL.textColor = UIColor.whiteColor;
- // hjL.text = @"合集";
- // UIImageView *mImgView = [[UIImageView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-27, 13.5, 11, 11)];
- // mImgView.image = [UIImage imageNamed:@"Frame 9366"];
- // [bottomView addSubview:mImgView];
- // UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleCollectionTap)];
- // [bottomView addGestureRecognizer:tap];
- //
- //}
- - (void)setupBottomInfo {
-
- self.contentView.backgroundColor = [UIColor redColor];
-
- CGFloat width = self.contentView.bounds.size.width;
- CGFloat height = self.contentView.bounds.size.height;
-
- // 播放器容器(占据上半部分)
- CGFloat playerHeight = height;
- UIView *playerContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, playerHeight)];
- playerContainer.backgroundColor = [UIColor blackColor];
- [self.contentView addSubview:playerContainer];
- [self.contentView sendSubviewToBack:playerContainer];
- // 创建播放器
- JXSuperPlayer *player = [[JXSuperPlayer alloc] initWithContainerView:playerContainer];
- player.delegate = self;
- // 右侧互动按钮
-
-
- UILabel * seeL = [[UILabel alloc] initWithFrame:CGRectMake(16, kScreenHeight - 14-safebottom, SCREEN_WIDTH - 32, 14)];
- seeL.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
- seeL.textColor = [UIColor colorWithRed:173/255.0 green:173/255.0 blue:173/255.0 alpha:1];
- [self.contentView addSubview:seeL];
- seeL.text = [NSString stringWithFormat:@"%@次播放",@"30万"];
-
- UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMinY(seeL.frame) - 58, SCREEN_WIDTH, 38)];
- bottomView.backgroundColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:0.1];
- [self.contentView addSubview:bottomView];
- UIImageView *sImgView = [[UIImageView alloc] initWithFrame:CGRectMake(16, 10.5, 17, 17)];
- sImgView.image = [UIImage imageNamed:@"icon 2.1 拷贝"];
- [bottomView addSubview:sImgView];
- UILabel *hjL = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(sImgView.frame)+4, 0, 100, 38)];
- [bottomView addSubview:hjL];
- hjL.font = [UIFont boldSystemFontOfSize:18];
- hjL.textColor = UIColor.whiteColor;
- hjL.text = @"合集";
- UIImageView *mImgView = [[UIImageView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-27, 13.5, 11, 11)];
- mImgView.image = [UIImage imageNamed:@"Frame 9366"];
- [bottomView addSubview:mImgView];
- UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleCollectionTap)];
- [bottomView addGestureRecognizer:tap];
-
- UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(16,34, SCREEN_WIDTH-32, 2)];
- [bottomView addSubview:slider];
- slider.maximumValue = 1;
- slider.minimumValue = 0;
- [slider setThumbImage:[UIImage imageNamed:@"b_jdt.png"] forState:UIControlStateNormal];
- [slider setThumbImage:[UIImage imageNamed:@"b_jdtb.png"] forState:UIControlStateHighlighted];
- [slider setMinimumTrackImage:[UIImage imageNamed:@"jdt.png"] forState:UIControlStateNormal];
- [slider setMinimumTrackImage:[UIImage imageNamed:@"jdt.png"] forState:UIControlStateHighlighted];
- [slider setMaximumTrackImage:[UIImage imageNamed:@"jdt.png"] forState:UIControlStateNormal];
- [slider setMaximumTrackImage:[UIImage imageNamed:@"jdt.png"] forState:UIControlStateHighlighted] ;
- [slider setMinimumTrackTintColor:COLOR(0, 0, 0, 0.1)];
- [slider setMaximumTrackTintColor:COLOR(0, 0, 0, 0.1)];
- slider.alpha = 0.6;
- self.videoSlider = slider;
-
- UILabel *descLabel = [[UILabel alloc] init];
- descLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightMedium];
- descLabel.textColor = [UIColor whiteColor];
- descLabel.numberOfLines = 2;
- [self.contentView addSubview:descLabel];
- [self.contentView bringSubviewToFront:descLabel];
- [descLabel mas_makeConstraints:^(MASConstraintMaker *make) {
- make.bottom.equalTo(bottomView.mas_top).offset(-15);
- make.left.equalTo(self.contentView).offset(16);
- make.width.mas_equalTo(SCREEN_WIDTH - 90);
- }];
- self.descriptionLabel = descLabel;
- UILabel *titleLabel = [[UILabel alloc] init];
- titleLabel.font = [UIFont boldSystemFontOfSize:18];
- titleLabel.textColor = [UIColor whiteColor];
- titleLabel.numberOfLines = 2;
- [self.contentView addSubview:titleLabel];
- [self.contentView bringSubviewToFront:titleLabel];
- [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
- make.bottom.equalTo(descLabel.mas_top).offset(-12.5);
- make.left.equalTo(self.contentView).offset(16);
- make.width.mas_equalTo(SCREEN_WIDTH - 90);
- }];
- self.titleLabel = titleLabel;
-
- // self.bottomInfoView = [[UIView alloc] init];
- // [self.contentView addSubview:self.bottomInfoView];
- //
- // // 标题
- // self.titleLabel = [[UILabel alloc] init];
- // self.titleLabel.textColor = [UIColor whiteColor];
- // self.titleLabel.font = [UIFont boldSystemFontOfSize:16];
- // self.titleLabel.numberOfLines = 2;
- // [self.bottomInfoView addSubview:self.titleLabel];
- //
- // // 描述
- // self.descriptionLabel = [[UILabel alloc] init];
- // self.descriptionLabel.textColor = [UIColor colorWithWhite:1.0 alpha:1];
- // self.descriptionLabel.font = [UIFont systemFontOfSize:15];
- // self.descriptionLabel.numberOfLines = 2;
- // [self.bottomInfoView addSubview:self.descriptionLabel];
- //
- // // 约束
- // self.bottomInfoView.translatesAutoresizingMaskIntoConstraints = NO;
- // self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
- // self.descriptionLabel.translatesAutoresizingMaskIntoConstraints = NO;
- //
- // [NSLayoutConstraint activateConstraints:@[
- // [self.bottomInfoView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor],
- // [self.bottomInfoView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-90],
- // [self.bottomInfoView.bottomAnchor constraintEqualToAnchor:self.contentView.safeAreaLayoutGuide.bottomAnchor constant:-(BAR_HEIGHT+54)],
- // [self.bottomInfoView.heightAnchor constraintGreaterThanOrEqualToConstant:80],
- //
- // [self.titleLabel.topAnchor constraintEqualToAnchor:self.bottomInfoView.topAnchor constant:12],
- // [self.titleLabel.leadingAnchor constraintEqualToAnchor:self.bottomInfoView.leadingAnchor constant:16],
- // [self.titleLabel.trailingAnchor constraintEqualToAnchor:self.bottomInfoView.trailingAnchor constant:-16],
- //
- // [self.descriptionLabel.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:8],
- // [self.descriptionLabel.leadingAnchor constraintEqualToAnchor:self.bottomInfoView.leadingAnchor constant:16],
- // [self.descriptionLabel.trailingAnchor constraintEqualToAnchor:self.bottomInfoView.trailingAnchor constant:-16],
- //
- // ]];
- }
- #pragma mark - 公开方法
- - (void)configureWithDrama:(JXEpisode *)drama andDiction:(JXInteraction *)model andTitle:(NSString *)title{
- self.drama = drama;
-
- // 更新UI
- self.titleLabel.text = title ?: @"未知标题";
- self.descriptionLabel.text = drama.title ?: @"暂无描述";
-
- // 更新交互数据
- [self updateLikeUI:model.isLiked count:model.likeCount];
- [self updateFavoriteUI:model.isFavorited count:model.favoriteCount];
- [self updateCommentCount:model.commentCount];
- }
- - (NSString *)formatCount:(long long)count {
- if (count >= 1000000) {
- return [NSString stringWithFormat:@"%.1fM", count / 1000000.0];
- } else if (count >= 1000) {
- return [NSString stringWithFormat:@"%.1fK", count / 1000.0];
- }
- return [NSString stringWithFormat:@"%lld", count];
- }
- - (void)startPlay {
- if (!self.drama) {
- return;
- }
-
- // 创建播放器(如果不存在)
- if (!self.superPlayer) {
- self.superPlayer = [[JXSuperPlayer alloc] initWithContainerView:self.playerContainerView];
- self.superPlayer.delegate = self;
- } else {
- NSLog(@"[JXShortDramaCell] 重用现有播放器实例");
- }
- // FileID + psign播放(DRM推荐)
- NSString *appId = self.drama.appId;
- // 如果没有appId,尝试从psign中提取
- if (!appId || appId.length == 0) {
- appId = [JXSuperPlayer extractAppIdFromPsign:self.drama.psign];
- }
-
- if (!appId) {
- return;
- }
-
-
- [self.superPlayer playWithAppId:appId
- fileId:self.drama.fileId
- psign:self.drama.psign];
-
-
- }
- - (void)stopPlay {
- if (self.superPlayer) {
- [self.superPlayer stop];
- NSLog(@"[JXShortDramaCell] 播放器已停止");
- }
- }
- - (void)pausePlay {
- if (self.superPlayer) {
- [self.superPlayer pause];
- }
- }
- - (void)resumePlay {
- if (self.superPlayer) {
- [self.superPlayer resume];
- }
- }
- - (void)updateLikeUI:(BOOL)isLiked count:(long long)count {
- self.likeButton.selected = isLiked;
- self.likeButton.tintColor = isLiked ? [UIColor systemPinkColor] : [UIColor whiteColor];
- self.likeCountLabel.text = [VideoDetailCell formattedCountWithCount:count];
- }
- - (void)updateFavoriteUI:(BOOL)isFavorited count:(long long)count {
- self.favoriteButton.selected = isFavorited;
- self.favoriteButton.tintColor = isFavorited ? [UIColor systemYellowColor] : [UIColor whiteColor];
- self.favoriteCountLabel.text = [VideoDetailCell formattedCountWithCount:count];
- }
- - (void)updateCommentCount:(long long)count {
- self.commentCountLabel.text = [VideoDetailCell formattedCountWithCount:count];
- }
- /**
- * 格式化数字显示(如 1000 -> 1K)
- */
- + (NSString *)formattedCountWithCount:(long long)count {
- if (count >= 1000000) {
- return [NSString stringWithFormat:@"%.1fM", count / 1000000.0];
- } else if (count >= 1000) {
- return [NSString stringWithFormat:@"%.1fK", count / 1000.0];
- }
- return [NSString stringWithFormat:@"%lld", count];
- }
- /**
- * 与ViewController调用匹配的方法
- */
- - (void)updateLikeCount:(NSInteger)likeCount isLiked:(BOOL)isLiked {
- [self updateLikeUI:isLiked count:likeCount];
- }
- - (void)updateFavoriteCount:(NSInteger)favoriteCount isFavorited:(BOOL)isFavorited {
- [self updateFavoriteUI:isFavorited count:favoriteCount];
- }
- #pragma mark - 按钮事件
- - (void)handleLikeTap {
- if ([self.delegate respondsToSelector:@selector(shortDramaCellDidTapLike:)]) {
- [self.delegate shortDramaCellDidTapLike:self];
- } else {
- }
- }
- - (void)handleFavoriteTap {
- if ([self.delegate respondsToSelector:@selector(shortDramaCellDidTapFavorite:)]) {
- [self.delegate shortDramaCellDidTapFavorite:self];
- } else {
- }
- }
- - (void)handleCommentTap {
-
-
- if (self.delegate) {
- SEL selector = @selector(shortDramaCellDidTapComment:);
- BOOL responds = [self.delegate respondsToSelector:selector];
- if (responds) {
- [self.delegate shortDramaCellDidTapComment:self];
- } else {
- }
- }
- }
- - (void)handleCollectionTap {
- if ([self.delegate respondsToSelector:@selector(shortDramaCellDidTapCollection:)]) {
- [self.delegate shortDramaCellDidTapCollection:self];
- }
- }
- - (void)handleDetailTap {
- if ([self.delegate respondsToSelector:@selector(shortDramaCellDidTapDetail:)]) {
- [self.delegate shortDramaCellDidTapDetail:self];
- }
- }
- #pragma mark - JXSuperPlayerDelegate
- - (void)superPlayerDidChangeState:(JXSuperPlayerState)state {
- self.playerState = state;
- switch (state) {
- case JXSuperPlayerStatePreparing:
- NSLog(@"[JXShortDramaCell] 播放器状态变更: 准备中");
- // 开始播放时启动超时检测
- [self startPlayTimeoutTimer];
- break;
- case JXSuperPlayerStatePlaying:
- NSLog(@"[JXShortDramaCell] 播放器状态变更: 播放中");
- // 成功开始播放,取消超时检测
- [self stopPlayTimeoutTimer];
- break;
- case JXSuperPlayerStatePaused:
- NSLog(@"[JXShortDramaCell] 播放器状态变更: 暂停");
- break;
- case JXSuperPlayerStateCompleted:
- NSLog(@"[JXShortDramaCell] 播放器状态变更: 播放完成");
- [self stopPlayTimeoutTimer];
- break;
- case JXSuperPlayerStateError:
- NSLog(@"[JXShortDramaCell] 播放器状态变更: 错误");
- [self stopPlayTimeoutTimer];
- break;
- default:
- break;
- }
- }
- // 播放超时检测
- - (void)startPlayTimeoutTimer {
- [self stopPlayTimeoutTimer]; // 先停止之前的定时器
- self.playStartTime = [NSDate date];
- // 30秒超时检测
- self.playTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:30.0
- target:self
- selector:@selector(onPlayTimeout)
- userInfo:nil
- repeats:NO];
- NSLog(@"[JXShortDramaCell] 启动播放超时检测: 30秒");
- }
- - (void)stopPlayTimeoutTimer {
- if (self.playTimeoutTimer) {
- [self.playTimeoutTimer invalidate];
- self.playTimeoutTimer = nil;
- self.playStartTime = nil;
- NSLog(@"[JXShortDramaCell] 停止播放超时检测");
- }
- }
- - (void)onPlayTimeout {
- NSLog(@"[JXShortDramaCell] 播放超时!30秒内未开始播放,触发恢复机制");
- // 停止定时器
- [self stopPlayTimeoutTimer];
- // 触发播放失败处理
- if ([self.delegate respondsToSelector:@selector(shortDramaCellDidFailToPlay:)]) {
- [self.delegate shortDramaCellDidFailToPlay:self];
- }
- }
- - (void)superPlayerDidUpdateProgress:(NSTimeInterval)currentTime duration:(NSTimeInterval)duration {
- // 播放进度更新(可用于显示进度条)
- // NSLog(@"[JXShortDramaCell] 播放进度: %.1f / %.1f", currentTime, duration);
- float progress = currentTime/duration;
- self.videoSlider.value = progress;
- }
- - (void)superPlayerDidFailWithError:(NSError *)error {
- NSLog(@"[JXShortDramaCell] 播放失败: %@", error.localizedDescription);
- // 检查是否是网络相关错误
- BOOL isNetworkError = [error.domain isEqualToString:NSURLErrorDomain] &&
- (error.code == NSURLErrorTimedOut ||
- error.code == NSURLErrorCannotConnectToHost ||
- error.code == NSURLErrorNetworkConnectionLost ||
- error.code == NSURLErrorNotConnectedToInternet);
- // 也检查播放器内部错误
- BOOL isPlayerError = [error.domain isEqualToString:@"JXSuperPlayer"] ||
- [error.domain isEqualToString:@"TXVodPlayer"];
- if (isNetworkError || isPlayerError) {
- NSLog(@"[JXShortDramaCell] 检测到播放错误,尝试恢复: domain=%@, code=%ld",
- error.domain, (long)error.code);
- // 延迟3秒后通知控制器重新获取播放数据
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- if ([self.delegate respondsToSelector:@selector(shortDramaCellDidFailToPlay:)]) {
- [self.delegate shortDramaCellDidFailToPlay:self];
- }
- });
- } else {
- // 其他类型的错误,直接显示
- NSLog(@"[JXShortDramaCell] 非网络错误,不进行重试: %@", error);
- }
- // 显示错误提示(可以在这里添加UI反馈)
- // TODO: 在UI上显示播放失败的提示,但不阻塞用户操作
- }
- #pragma mark - 生命周期
- - (void)dealloc {
- // 清理定时器
- [self stopPlayTimeoutTimer];
- // 清理播放器
- if (self.superPlayer) {
- [self.superPlayer releasePlayer];
- }
- }
- @end
|