diff --git a/QXLive/Base/QXBaseViewController.h b/QXLive/Base/QXBaseViewController.h index 78aadcf..9e34b88 100644 --- a/QXLive/Base/QXBaseViewController.h +++ b/QXLive/Base/QXBaseViewController.h @@ -24,6 +24,8 @@ NS_ASSUME_NONNULL_BEGIN imageurl :图片名称或链接 */ -(void)updateBgImage:(NSString*)imageUrl; + +-(void)updateBackImage:(UIImage *)image; @end NS_ASSUME_NONNULL_END diff --git a/QXLive/Base/QXBaseViewController.m b/QXLive/Base/QXBaseViewController.m index cd22184..b191e79 100644 --- a/QXLive/Base/QXBaseViewController.m +++ b/QXLive/Base/QXBaseViewController.m @@ -82,6 +82,10 @@ self.bgImageView.image = [UIImage imageNamed:imageUrl]; } } + +-(void)updateBackImage:(UIImage *)image{ + [self.backBtn setImage:image forState:(UIControlStateNormal)]; +} -(UIImageView *)bgImageView{ if (!_bgImageView) { _bgImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)]; diff --git a/QXLive/Base/QXButton.h b/QXLive/Base/QXButton.h new file mode 100644 index 0000000..091c780 --- /dev/null +++ b/QXLive/Base/QXButton.h @@ -0,0 +1,16 @@ +// +// QXButton.h +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface QXButton : UIButton +@property (nonatomic,strong)id object; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Base/QXButton.m b/QXLive/Base/QXButton.m new file mode 100644 index 0000000..f2b328f --- /dev/null +++ b/QXLive/Base/QXButton.m @@ -0,0 +1,20 @@ +// +// QXButton.m +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXButton.h" + +@implementation QXButton + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect { + // Drawing code +} +*/ + +@end diff --git a/QXLive/Base/QXGlobal.h b/QXLive/Base/QXGlobal.h index 81ae55d..c5251b8 100644 --- a/QXLive/Base/QXGlobal.h +++ b/QXLive/Base/QXGlobal.h @@ -108,6 +108,10 @@ typedef void (^showFinishBlock)(void); -(void)finishTask; -(void)vibrationFeedback; + + +-(void)dirfViewDidToBackground; +-(void)dirfViewBecomeToFront; @end diff --git a/QXLive/Base/QXGlobal.m b/QXLive/Base/QXGlobal.m index 79cb752..0fefa83 100644 --- a/QXLive/Base/QXGlobal.m +++ b/QXLive/Base/QXGlobal.m @@ -23,6 +23,12 @@ #import "QXRedPacketManager.h" #import "QXGiftDisplayManager.h" +#import "QXDrifNobilityJoinRoomView.h" +#import "QXDrifRoomHourRankView.h" +#import "QXGiftDriftView.h" +#import "QXMeetActivityDriftView.h" +#import "QXRedPacketDriftView.h" + @interface QXGlobal() @property (nonatomic,assign)BOOL isLogin; @@ -309,6 +315,8 @@ [[QXRedPacketManager sharedManager] destoryRedpacketInfo]; /// 移除房间内礼物飘屏 [[QXGiftDisplayManager sharedManager] clearAll]; + /// 不显示进入特效 + [[QXDrifNobilityJoinRoomView shareView] dirfViewDidToBackground]; /// 移除特效 [[QXGiftPlayerManager shareManager] destroyEffectSvga]; /// 退出声网 @@ -364,4 +372,15 @@ } return _offLineDict; } + +-(void)dirfViewDidToBackground{ + [[QXDrifNobilityJoinRoomView shareView] dirfViewDidToBackground]; + [[QXDrifRoomHourRankView shareView] dirfViewDidToBackground]; + [[QXGiftDriftView shareView] dirfViewDidToBackground]; + [[QXMeetActivityDriftView shareView] dirfViewDidToBackground]; + [[QXRedPacketDriftView shareView] dirfViewDidToBackground]; +} +-(void)dirfViewBecomeToFront{ + +} @end diff --git a/QXLive/Dynamic(语圈)/Controller/QXExpansionViewController.m b/QXLive/Dynamic(语圈)/Controller/QXExpansionViewController.m index 255e6c5..4d9d23f 100644 --- a/QXLive/Dynamic(语圈)/Controller/QXExpansionViewController.m +++ b/QXLive/Dynamic(语圈)/Controller/QXExpansionViewController.m @@ -145,6 +145,15 @@ cell.model = model; return cell; } +-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{ + QXExpansionCell *eCell = (QXExpansionCell *)cell; + [eCell nameStartAnimate]; +} +-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{ + QXExpansionCell *eCell = (QXExpansionCell *)cell; + [eCell nameStopAnimate]; +} + -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ QXUserHomeModel *model = self.dataArray[indexPath.row]; NSArray *imgArr; @@ -154,7 +163,7 @@ // NSArray * CGFloat itemH = 94; if (imgArr.count == 1) { - itemH = (SCREEN_WIDTH-15-15-15)/2 + 94; + itemH = (SCREEN_WIDTH-15-15-15)/2 + 94+10; }else if(imgArr.count > 1){ if (imgArr.count > 3) { itemH = (SCREEN_WIDTH-16*2-12*2-10*2)/3*2+10+94+ScaleWidth(10); diff --git a/QXLive/Dynamic(语圈)/View/QXExpansionCell.h b/QXLive/Dynamic(语圈)/View/QXExpansionCell.h index 222a1d4..09ede84 100644 --- a/QXLive/Dynamic(语圈)/View/QXExpansionCell.h +++ b/QXLive/Dynamic(语圈)/View/QXExpansionCell.h @@ -8,20 +8,22 @@ #import #import "QXUserModel.h" #import "QXSeatHeaderView.h" +#import "CKShimmerLabel.h" NS_ASSUME_NONNULL_BEGIN @interface QXExpansionCell : UITableViewCell @property (weak, nonatomic) IBOutlet UIView *bgView; @property (weak, nonatomic) IBOutlet QXSeatHeaderView *avatarImgV; -@property (weak, nonatomic) IBOutlet UILabel *nicknameLab; -@property (weak, nonatomic) IBOutlet UIImageView *levelImgV; +@property (weak, nonatomic) IBOutlet CKShimmerLabel *nameLabel; @property (weak, nonatomic) IBOutlet UILabel *ageLabel; @property (weak, nonatomic) IBOutlet UIButton *followBtn; @property (weak, nonatomic) IBOutlet UIView *imgsBgView; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *imgsBgViewHeightCon; @property (weak, nonatomic) IBOutlet UIImageView *sexImageView; @property (nonatomic, strong) QXUserHomeModel *model; +-(void)nameStartAnimate; +-(void)nameStopAnimate; @end NS_ASSUME_NONNULL_END diff --git a/QXLive/Dynamic(语圈)/View/QXExpansionCell.m b/QXLive/Dynamic(语圈)/View/QXExpansionCell.m index f9f663f..3bc422e 100644 --- a/QXLive/Dynamic(语圈)/View/QXExpansionCell.m +++ b/QXLive/Dynamic(语圈)/View/QXExpansionCell.m @@ -37,6 +37,12 @@ make.size.mas_equalTo(CGSizeMake(imgWidth, imgWidth)); }]; } + self.nameLabel.textColor = RGB16(0x212121); + self.nameLabel.shimmerWidth = 20; + self.nameLabel.shimmerRadius = 20; + self.nameLabel.durationTime = 1;; + self.nameLabel.font = [UIFont boldSystemFontOfSize:15]; + [self.nameLabel stopShimmer]; } - (IBAction)chatAction:(id)sender { if (self.model.room_id.intValue > 0) { @@ -55,11 +61,13 @@ self.avatarImgV.nobilityImageView.image = nil; } if ([model.nickname_color isExist]) { - self.nicknameLab.textColor = [UIColor colorWithHexString:model.nickname_color]; + self.nameLabel.shimmerColor = [UIColor colorWithHexString:model.nickname_color]; +// [self.nameLabel startShimmer]; }else{ - self.nicknameLab.textColor = RGB16(0x212121); + self.nameLabel.shimmerColor = [UIColor clearColor]; +// [self.nameLabel stopShimmer]; } - self.nicknameLab.text = model.nickname; + self.nameLabel.text = model.nickname; self.ageLabel.text = [NSString stringWithFormat:@"%ld岁 ip属地: %@",[model.birthday ageWithDateOfBirth],model.loginip]; CGFloat imgWidth = (SCREEN_WIDTH-16*2-12*2-10*2)/3; UIImageView *firstImgV = self.imgViewsArray.firstObject; @@ -112,6 +120,31 @@ self.followBtn.selected = NO; } } +-(void)nameStartAnimate{ + if ([self.model.nickname_color isExist]) { + [self.nameLabel stopShimmer]; + [self.nameLabel layoutSubviews]; + self.nameLabel.shimmerWidth = 20; + self.nameLabel.shimmerRadius = 20; + self.nameLabel.durationTime = 1; + self.nameLabel.shimmerColor = [UIColor colorWithHexString:self.model.nickname_color]; + [self.nameLabel startShimmer]; + } +// else{ +// self.nameLabel.shimmerColor = [UIColor clearColor]; +// [self.nameLabel stopShimmer]; +// } +} +-(void)nameStopAnimate{ + if ([self.model.nickname_color isExist]) { + self.nameLabel.shimmerColor = [UIColor colorWithHexString:self.model.nickname_color]; + [self.nameLabel stopShimmer]; + } +// else{ +// self.nameLabel.shimmerColor = [UIColor clearColor]; +// [self.nameLabel stopShimmer]; +// } +} -(void)previewPhotoWithCurrentIndex:(NSInteger)currentIndex{ NSArray *images = [self.model.home_bgimages componentsSeparatedByString:@","]; diff --git a/QXLive/Dynamic(语圈)/View/QXExpansionCell.xib b/QXLive/Dynamic(语圈)/View/QXExpansionCell.xib index 3f68b6a..11df19d 100644 --- a/QXLive/Dynamic(语圈)/View/QXExpansionCell.xib +++ b/QXLive/Dynamic(语圈)/View/QXExpansionCell.xib @@ -10,14 +10,14 @@ - + - + - + @@ -35,37 +35,18 @@ - - - + - + @@ -96,14 +77,23 @@ + + - @@ -111,11 +101,10 @@ - - - - + + + @@ -142,8 +131,7 @@ - - + diff --git a/QXLive/HomePage(声播)/Model/QXRoomBestFriendModel.h b/QXLive/HomePage(声播)/Model/QXRoomBestFriendModel.h new file mode 100644 index 0000000..5ef86a3 --- /dev/null +++ b/QXLive/HomePage(声播)/Model/QXRoomBestFriendModel.h @@ -0,0 +1,22 @@ +// +// QXRoomBestFriendModel.h +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@class QXRoomBestFriendListModel,QXRoomBestFriendListSubModel; +@interface QXRoomBestFriendModel : NSObject +@property (nonatomic,strong)QXUserCpInfoModel *cp; +@property (nonatomic,strong)NSArray *no_cp; +@end +@interface QXRoomBestFriendListModel : NSObject +@property (nonatomic,strong)NSString *relation_name; +@property (nonatomic,strong)NSArray *relation_list; +@end + + +NS_ASSUME_NONNULL_END diff --git a/QXLive/HomePage(声播)/Model/QXRoomBestFriendModel.m b/QXLive/HomePage(声播)/Model/QXRoomBestFriendModel.m new file mode 100644 index 0000000..e581daf --- /dev/null +++ b/QXLive/HomePage(声播)/Model/QXRoomBestFriendModel.m @@ -0,0 +1,28 @@ +// +// QXRoomBestFriendModel.m +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXRoomBestFriendModel.h" + +@implementation QXRoomBestFriendModel ++(NSDictionary *)modelContainerPropertyGenericClass{ + return @{ + @"no_cp": @"QXRoomBestFriendListModel", + @"cp": @"QXUserCpInfoModel", + }; +} +@end +@implementation QXRoomBestFriendListModel ++(NSDictionary *)modelContainerPropertyGenericClass{ + return @{ + @"relation_list": @"QXRelationshipListModel", + }; +} +@end + + + + diff --git a/QXLive/HomePage(声播)/Model/QXRoomFriendRelationModel.h b/QXLive/HomePage(声播)/Model/QXRoomFriendRelationModel.h index c01fd01..7148fe8 100644 --- a/QXLive/HomePage(声播)/Model/QXRoomFriendRelationModel.h +++ b/QXLive/HomePage(声播)/Model/QXRoomFriendRelationModel.h @@ -23,6 +23,11 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,strong)NSString *room_id; @property (nonatomic,strong)NSString *relation_name; + +@property (nonatomic,strong)NSString *end_time; +@property (nonatomic,strong)NSString *sex2; +@property (nonatomic,strong)NSString *sex1; +@property (nonatomic,strong)NSString *delete_me_coin; @end NS_ASSUME_NONNULL_END diff --git a/QXLive/Login(登录)/Model/QXLoginModel.h b/QXLive/Login(登录)/Model/QXLoginModel.h index c0a5c0b..03369ec 100644 --- a/QXLive/Login(登录)/Model/QXLoginModel.h +++ b/QXLive/Login(登录)/Model/QXLoginModel.h @@ -44,6 +44,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,strong)NSString *is_hide; /// 当前状态:0-取消隐身,1-隐身进入 @property (nonatomic,strong)NSString *hide_status; +/// 当前状态:-1 未认证歌手, 0待审核 1已认证 2被拒绝 +@property (nonatomic,strong)NSString *singer_status; /// 各种卡片 @property (nonatomic,strong)NSArray *icon; /// 1 能聊天 0不能聊天 diff --git a/QXLive/Manager/QXRoomMessageManager.h b/QXLive/Manager/QXRoomMessageManager.h index f12a473..bcb7c8e 100644 --- a/QXLive/Manager/QXRoomMessageManager.h +++ b/QXLive/Manager/QXRoomMessageManager.h @@ -10,6 +10,7 @@ #import "QXRoomModel.h" #import "QXRoomFriendRelationModel.h" #import "QXRedPacketModel.h" +#import "QXUserSongListModel.h" typedef NS_ENUM(NSInteger) { /// 清空消息 @@ -20,6 +21,11 @@ typedef NS_ENUM(NSInteger) { QXRoomMessageTypeMuteRemoteAudio = 125, /// 关闭自己声音 QXRoomMessageTypeMuteLocalAudio = 126, + /// 发送|接收到心动信号 + QXRoomMessageTypeSendAndRecieveCpHeartSignal = 130, + /// cp双向奔赴 + QXRoomMessageTypeCpHeartFinished = 131, + /// 基础文本消息类型 QXRoomMessageTypeText = 1, /// 基础表情类型 @@ -132,6 +138,13 @@ typedef NS_ENUM(NSInteger) { QXRoomMessageTypeSendRedpacket = 1060, /// 红包已被抢完 QXRoomMessageTypeRedpacketFinished = 1061, + + /// 点歌房当前歌曲发生变化 + QXRoomMessageTypeSingerRoomCurrentSongDidChanged = 1070, + /// 点歌房下一首歌曲发生变化 + QXRoomMessageTypeSingerRoomNextSongDidChanged = 1071, + /// 歌曲数量发生变化 + QXRoomMessageTypeSingerRoomSongCountDidChanged = 1072, }QXRoomMessageType; NS_ASSUME_NONNULL_BEGIN @protocol QXRoomMessageManagerDelegate @@ -268,11 +281,22 @@ NS_ASSUME_NONNULL_BEGIN /// 房间用户在线状态发生变化 //-(void)roomUserOnlineStatusDidChanged:(BOOL)isOnline userId:(NSString*)userId; + + +/// 点唱房当前歌曲信息发生变化 +-(void)singerSongCurrentSongInfoDidChanged:(QXUserSongListModel*)model; +/// 点唱房下一首歌信息发生变化 +-(void)singerSongNextSongInfoDidChanged:(QXUserSongListModel*)model; +/// 已点歌曲数量发生变化 +-(void)singerSongCountDidChanged:(NSString*)count; + @end @interface QXRoomMessageManager : NSObject @property (nonatomic,weak)iddelegate; +(instancetype)shared; + +-(void)addC2CObserver; /// 加入房间群组 -(void)joinGroupWithRoomId:(NSString*)roomId; @@ -284,6 +308,8 @@ NS_ASSUME_NONNULL_BEGIN -(void)sendChatEmoji:(QXEmojiModel *)emoji; -(void)sendC2CMessage:(NSString *)message messageType:(QXRoomMessageType)messageType userId:(NSString*)userId; + +-(void)showCpFinishedAlertViewWithText:(NSString*)text; @end @interface QXRoomMessage : NSObject diff --git a/QXLive/Manager/QXRoomMessageManager.m b/QXLive/Manager/QXRoomMessageManager.m index 6fdd485..1f4eb42 100644 --- a/QXLive/Manager/QXRoomMessageManager.m +++ b/QXLive/Manager/QXRoomMessageManager.m @@ -13,6 +13,7 @@ #import #import "TUIChatConfig.h" #import "QXDrifNobilityJoinRoomView.h" +#import "QXCustomAlertView.h" @interface QXRoomMessageManager() @property (nonatomic,strong)NSString *groupId; @@ -34,13 +35,15 @@ } return self; } +-(void)addC2CObserver{ + [[V2TIMManager sharedInstance] addSimpleMsgListener:self]; +} -(void)joinGroupWithRoomId:(NSString *)roomId{ MJWeakSelf if (self.groupId) { [self quitGroupWithRoomId:self.groupId]; } [[V2TIMManager sharedInstance] addGroupListener:self]; - [[V2TIMManager sharedInstance] addSimpleMsgListener:self]; [[V2TIMManager sharedInstance] addAdvancedMsgListener:self]; NSString *groupId = [NSString stringWithFormat:@"room%@",roomId]; [[V2TIMManager sharedInstance] joinGroup:groupId msg:@"大家好,我来啦" succ:^{ @@ -57,7 +60,6 @@ self.groupId = nil; self.roomId = nil; [[V2TIMManager sharedInstance] removeGroupListener:self]; - [[V2TIMManager sharedInstance] removeSimpleMsgListener:self]; [[V2TIMManager sharedInstance] removeAdvancedMsgListener:self]; NSString *groupId = [NSString stringWithFormat:@"room%@",roomId]; [[V2TIMManager sharedInstance] quitGroup:groupId succ:^{ @@ -653,6 +655,28 @@ } } break; + + case QXRoomMessageTypeSingerRoomCurrentSongDidChanged:{ + QXUserSongListModel *songInfo = [QXUserSongListModel yy_modelWithJSON:msg.Text[@"song_info"]]; + if (self.delegate && [self.delegate respondsToSelector:@selector(singerSongCurrentSongInfoDidChanged:)]) { + [self.delegate singerSongCurrentSongInfoDidChanged:songInfo]; + } + } + break; + case QXRoomMessageTypeSingerRoomNextSongDidChanged:{ + QXUserSongListModel *songInfo = [QXUserSongListModel yy_modelWithJSON:msg.Text[@"next_song_info"]]; + if (self.delegate && [self.delegate respondsToSelector:@selector(singerSongNextSongInfoDidChanged:)]) { + [self.delegate singerSongNextSongInfoDidChanged:songInfo]; + } + } + break; + case QXRoomMessageTypeSingerRoomSongCountDidChanged:{ + NSString *songCount = [NSString stringWithFormat:@"%@",msg.Text[@"count"]]; + if (self.delegate && [self.delegate respondsToSelector:@selector(singerSongCountDidChanged:)]) { + [self.delegate singerSongCountDidChanged:songCount]; + } + } + break; default: break; } @@ -672,6 +696,42 @@ */ +-(void)reSendGiftWithId:(NSString*)giftId userId:(NSString*)userId{ + MJWeakSelf + [QXMineNetwork userCpReSendWithGiftId:giftId userId:userId roomId:self.roomId successBlock:^(NSDictionary * _Nonnull dict) { + + id object = dict[@"cp_type"]; + if ([object isKindOfClass:[NSDictionary class]]) { + NSDictionary *cpDict = (NSDictionary *)object; + NSString *cp_type = object[@"cp_type"]; + if (cp_type.intValue == 1) { + /// 单向送cp礼物 + NSString *jsonStr = [cpDict jsonStringEncoded]; + [[QXRoomMessageManager shared] sendC2CMessage:jsonStr messageType:(QXRoomMessageTypeSendAndRecieveCpHeartSignal) userId:userId]; + }else if (cp_type.intValue == 2){ + /// cp礼物已达成双向绑定 + NSString *jsonStr = [cpDict jsonStringEncoded]; + [[QXRoomMessageManager shared] sendC2CMessage:jsonStr messageType:(QXRoomMessageTypeCpHeartFinished) userId:userId]; + NSString *message = [NSString stringWithFormat:@"%@",cpDict[@"text"]]; + [weakSelf showCpFinishedAlertViewWithText:message]; + }else{ + + } + } + + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + showToast(msg); + }]; +} +-(void)showCpFinishedAlertViewWithText:(NSString*)text{ + QXCustomAlertView *alertView = [[QXCustomAlertView alloc] init]; + + [alertView showInView:KEYWINDOW title:@"缘定三生 此刻同心" message:text cancleTitle:@"稍后进入" commitTitle:@"进入心动空间"]; + + alertView.commitBlock = ^{ + QXLOG(@"进入心动空间"); + }; +} -(void)onRecvC2CTextMessage:(NSString *)msgID sender:(V2TIMUserInfo *)info text:(NSString *)text{ @@ -688,6 +748,23 @@ if (self.delegate && [self.delegate respondsToSelector:@selector(pkMuteRemoteAudio:fromUserInfo:)]) { [self.delegate pkMuteRemoteAudio:is_mute==1 fromUserInfo:model.FromUserInfo]; } + }else if (meesageType == QXRoomMessageTypeSendAndRecieveCpHeartSignal){ + NSString *json = [NSString stringWithFormat:@"%@",msg.Text[@"text"]]; + NSDictionary *dict = [json jsonValueDecoded]; + NSString *message = [NSString stringWithFormat:@"%@",dict[@"text1"]]; + __block NSString *gift_id = [NSString stringWithFormat:@"%@",dict[@"gift_id"]]; + QXRoomChatListModel *model = [QXRoomChatListModel yy_modelWithJSON:msg.Text]; + QXCustomAlertView *alertView = [[QXCustomAlertView alloc] init]; + [alertView showInView:KEYWINDOW title:@"心动信号" message:message cancleTitle:@"再想想" commitTitle:@"回赠"]; + MJWeakSelf + alertView.commitBlock = ^{ + [weakSelf reSendGiftWithId:gift_id userId:model.FromUserInfo.user_id]; + }; + }else if (meesageType == QXRoomMessageTypeCpHeartFinished){ + NSString *json = [NSString stringWithFormat:@"%@",msg.Text[@"text"]]; + NSDictionary *dict = [json jsonValueDecoded]; + NSString *message = [NSString stringWithFormat:@"%@",dict[@"text1"]]; + [self showCpFinishedAlertViewWithText:message]; } } -(void)onRecvGroupCustomMessage:(NSString *)msgID groupID:(NSString *)groupID sender:(V2TIMGroupMemberInfo *)info customData:(NSData *)data{ @@ -719,7 +796,7 @@ }else if (meesageType == QXRoomMessageTypeMuteLocalAudio){ NSString *json = [NSString stringWithFormat:@"%@",msg.Text[@"text"]]; NSDictionary *dict = [json jsonValueDecoded]; - NSInteger is_mute = [[dict objectForKey:@"is_mute"] integerValue]; +// NSInteger is_mute = [[dict objectForKey:@"is_mute"] integerValue]; QXUserHomeModel *userModel = [QXUserHomeModel yy_modelWithJSON:msg.Text[@"FromUserInfo"]]; AgoraRtcAudioVolumeInfo *userInfo = [[AgoraRtcAudioVolumeInfo alloc] init]; userInfo.uid = userModel.user_id.longLongValue; @@ -855,9 +932,9 @@ [[V2TIMManager sharedInstance] sendMessage:message1 receiver:toUserId groupID:nil priority:(V2TIM_PRIORITY_HIGH) onlineUserOnly:YES offlinePushInfo:nil progress:^(uint32_t progress) { } succ:^{ - + QXLOG(@"c2c发送成功"); } fail:^(int code, NSString * _Nullable desc) { - + QXLOG(@"c2c发送失败"); }]; } @end diff --git a/QXLive/Mine(音域)/Controller/QXMineViewController.m b/QXLive/Mine(音域)/Controller/QXMineViewController.m index f503484..01367e8 100644 --- a/QXLive/Mine(音域)/Controller/QXMineViewController.m +++ b/QXLive/Mine(音域)/Controller/QXMineViewController.m @@ -33,6 +33,9 @@ #import "QXGiftWallViewController.h" #import "QXNobilityViewController.h" #import "QXHomePageNetwork.h" +#import "QXRoomSingerAuthViewController.h" +#import "QXMineSongListViewController.h" +#import "QXIntimateViewController.h" #import @interface QXMineViewController () @@ -148,6 +151,19 @@ [WXApi sendReq:req completion:nil]; } break; + case QXMineServiceTypeSingerAuth:{ + QXLOG(@"点击了歌手认证"); + QXRoomSingerAuthViewController *vc = [[QXRoomSingerAuthViewController alloc] init]; + vc.singer_status = self.userModel.singer_status; + [self.navigationController pushViewController:vc animated:YES]; + } + break; + case QXMineServiceTypeSongList:{ + QXLOG(@"我的歌单"); + QXMineSongListViewController *vc = [[QXMineSongListViewController alloc] init]; + [self.navigationController pushViewController:vc animated:YES]; + } + break; default: break; } @@ -195,7 +211,9 @@ break; case QXMainHeaderOptionTypeFriend:{ QXLOG(@"跳转挚友"); - + QXIntimateViewController *vc = [[QXIntimateViewController alloc] init]; + vc.userId = QXGlobal.shareGlobal.loginModel.user_id; + [self.navigationController pushViewController:vc animated:YES]; } break; case QXMainHeaderOptionTypeGiftWall:{ @@ -288,11 +306,11 @@ if (indexPath.row == 0) { return ScaleWidth(110); }else{ - if (QXGlobal.shareGlobal.isOpenRecharge) { +// if (QXGlobal.shareGlobal.isOpenRecharge) { return ScaleWidth(168); - }else{ - return ScaleWidth(110); - } +// }else{ +// return ScaleWidth(110); +// } } } -(void)getBanner{ diff --git a/QXLive/Mine(音域)/Controller/个人主页/QXUserHomePageViewController.m b/QXLive/Mine(音域)/Controller/个人主页/QXUserHomePageViewController.m index 9dddecc..4eeb236 100644 --- a/QXLive/Mine(音域)/Controller/个人主页/QXUserHomePageViewController.m +++ b/QXLive/Mine(音域)/Controller/个人主页/QXUserHomePageViewController.m @@ -16,6 +16,8 @@ #import "QXCreatPhotosViewController.h" #import "QXMineNetwork.h" #import "QXPhotosDetailVC.h" +#import "QXIntimateContentView.h" +#import "QXHeartBeatSpaceViewController.h" @interface QXUserHomePageViewController () @property (nonatomic,strong)UIImageView * backgourdImageView; @@ -27,6 +29,7 @@ @property (nonatomic, strong) JXCategoryTitleView *categoryView; @property (nonatomic, strong) NSArray *titles; @property (nonatomic, assign)CGRect cycleScrollViewFrame; +@property (nonatomic, strong)QXUserHomeModel *userModel; @end @implementation QXUserHomePageViewController @@ -44,6 +47,8 @@ self.navigationController.navigationBar.backgroundColor = [UIColor clearColor]; } - (void)initSubViews{ + self.bgImageHidden = YES; + self.view.backgroundColor = RGB16(0xF3F3F3); self.cycleScrollView = [SDCycleScrollView cycleScrollViewWithFrame:CGRectMake(0, 0, self.view.width, 121+NavContentHeight+16) delegate:self placeholderImage:[UIImage imageNamed:@"user_header_placehoulder"]]; self.cycleScrollView.bannerImageViewContentMode = UIViewContentModeScaleAspectFill; @@ -57,7 +62,7 @@ self.cycleScrollViewFrame = self.backgourdImageView.frame; [self.view addSubview:self.backgourdImageView]; - self.titles = @[QXText(@"动态"),QXText(@"礼物墙"),QXText(@"我的相册")]; + self.titles = @[QXText(@"动态"),QXText(@"挚友"),QXText(@"我的相册")]; _categoryView = [[JXCategoryTitleView alloc] init]; self.categoryView.frame = CGRectMake(0, 0, 200, 48); self.categoryView.titles = self.titles; @@ -106,7 +111,15 @@ -(void)getUserInfo{ MJWeakSelf [QXMineNetwork userHomePageWithUserId:self.user_id successBlock:^(QXUserHomeModel * _Nonnull userModel) { + weakSelf.userModel = userModel; + weakSelf.headerView.hidden = NO; weakSelf.headerView.model = userModel; + if (weakSelf.userModel.cp_info != nil) { + weakSelf.headerView.height = 243+ScaleWidth(40)+8+ScaleWidth(100)+14; + }else{ + weakSelf.headerView.height = 243+ScaleWidth(40)+8; + } + [weakSelf.pagingView resizeTableHeaderViewHeightWithAnimatable:NO duration:0.1 curve:UIViewAnimationCurveLinear]; NSArray *imgs; if (userModel.home_bgimages.length > 0) { imgs = [userModel.home_bgimages componentsSeparatedByString:@","]; @@ -134,7 +147,7 @@ return self.headerView; } - (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView { - return 215+26; + return self.headerView.height; } - (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView { @@ -155,10 +168,13 @@ dynamicView.backgroundColor = RGB16(0xf6f6f6); return dynamicView; }else if(index == 1){ - QXUserGiftWallView *giftWallView = [[QXUserGiftWallView alloc] init]; - giftWallView.backgroundColor = RGB16(0xf6f6f6); - giftWallView.user_id = self.user_id; - return giftWallView; +// QXUserGiftWallView *giftWallView = [[QXUserGiftWallView alloc] init]; +// giftWallView.backgroundColor = RGB16(0xf6f6f6); +// giftWallView.user_id = self.user_id; +// return giftWallView; + QXIntimateContentView *intimateView = [[QXIntimateContentView alloc] init]; + intimateView.userId = self.user_id; + return intimateView; }else{ QXUserPhotosView *photosView = [[QXUserPhotosView alloc] init]; photosView.user_id = self.user_id; @@ -179,6 +195,8 @@ -(QXUserHomeHeaderView *)headerView{ if (!_headerView) { _headerView = [[QXUserHomeHeaderView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 215+26)]; + _headerView.userId = self.user_id; + _headerView.hidden = YES; } return _headerView; } diff --git a/QXLive/Mine(音域)/Controller/亲密关系/QXHeartBeatSpaceViewController.h b/QXLive/Mine(音域)/Controller/亲密关系/QXHeartBeatSpaceViewController.h new file mode 100644 index 0000000..34946c6 --- /dev/null +++ b/QXLive/Mine(音域)/Controller/亲密关系/QXHeartBeatSpaceViewController.h @@ -0,0 +1,16 @@ +// +// QXHeartBeatSpaceViewController.h +// QXLive +// +// Created by 启星 on 2025/11/21. +// + +#import "QXBaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface QXHeartBeatSpaceViewController : QXBaseViewController +@property (nonatomic,strong)NSString *userId; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/Controller/亲密关系/QXHeartBeatSpaceViewController.m b/QXLive/Mine(音域)/Controller/亲密关系/QXHeartBeatSpaceViewController.m new file mode 100644 index 0000000..b368621 --- /dev/null +++ b/QXLive/Mine(音域)/Controller/亲密关系/QXHeartBeatSpaceViewController.m @@ -0,0 +1,22 @@ +// +// QXHeartBeatSpaceViewController.m +// QXLive +// 心动空间 +// Created by 启星 on 2025/11/21. +// + +#import "QXHeartBeatSpaceViewController.h" + +@interface QXHeartBeatSpaceViewController () + +@end + +@implementation QXHeartBeatSpaceViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + + +@end diff --git a/QXLive/Mine(音域)/Controller/亲密关系/QXIntimateViewController.h b/QXLive/Mine(音域)/Controller/亲密关系/QXIntimateViewController.h new file mode 100644 index 0000000..67467a9 --- /dev/null +++ b/QXLive/Mine(音域)/Controller/亲密关系/QXIntimateViewController.h @@ -0,0 +1,16 @@ +// +// QXIntimateViewController.h +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXBaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface QXIntimateViewController : QXBaseViewController +@property (nonatomic,strong)NSString *userId; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/Controller/亲密关系/QXIntimateViewController.m b/QXLive/Mine(音域)/Controller/亲密关系/QXIntimateViewController.m new file mode 100644 index 0000000..d9d4254 --- /dev/null +++ b/QXLive/Mine(音域)/Controller/亲密关系/QXIntimateViewController.m @@ -0,0 +1,242 @@ +// +// QXIntimateViewController.m +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXIntimateViewController.h" +#import "QXIntimateCpCell.h" +#import "QXIntimateListCell.h" +#import "QXIntimateNoCpCell.h" +#import "QXMineNetwork.h" +#import "QXButton.h" +#import "QXMoreIntimateViewController.h" +#import "QXIntimateMoreListCell.h" +#import "QXHeartBeatSpaceViewController.h" + +@interface QXIntimateViewController () +@property (nonatomic,strong)UITableView *tableView; +@property (nonatomic,strong)QXRoomBestFriendModel *model; +@end + +@implementation QXIntimateViewController + +- (void)viewDidLoad { + self.isNoChangeBgImage = YES; + [super viewDidLoad]; + // Do any additional setup after loading the view. +} +-(void)viewWillAppear:(BOOL)animated{ + [super viewWillAppear:animated]; + [self.navigationController setNavigationBarHidden:NO animated:YES]; +} +-(void)setNavgationItems{ + [super setNavgationItems]; +} + +- (void)initSubViews{ + self.page = 1; + [self updateBgImage:@"mine_intimate_bg"]; + [self updateBackImage:[UIImage imageNamed:@"mine_intimate_back"]]; + UIImageView *titleImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mine_intimate_title_img"]]; + [self.view addSubview:titleImageView]; + [titleImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.view); + make.width.mas_equalTo(ScaleWidth(178)); + make.height.mas_equalTo(ScaleWidth(68)); + make.top.mas_equalTo(NavContentHeight); + }]; + [self.view addSubview:self.tableView]; +} +-(void)setUserId:(NSString *)userId{ + _userId = userId; + self.page = 1; + [self getList]; +} +-(void)getList{ + MJWeakSelf + [QXMineNetwork userBestFriendsListWithUserId:self.userId page:self.page successBlock:^(QXRoomBestFriendModel * _Nonnull model) { + weakSelf.model = model; + if (weakSelf.page == 1) { + [weakSelf.dataArray removeAllObjects]; + } + [weakSelf.dataArray addObjectsFromArray:model.no_cp]; + [weakSelf.tableView reloadData]; + if (model.no_cp.count == 0) { + weakSelf.tableView.mj_footer.state = MJRefreshStateNoMoreData; + }else{ + [weakSelf.tableView.mj_footer endRefreshing]; + } + [weakSelf.tableView.mj_header endRefreshing]; + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + + }]; +} + +-(void)moreAction:(QXButton*)btn{ + QXRoomBestFriendListModel *md = btn.object; + QXMoreIntimateViewController *vc = [[QXMoreIntimateViewController alloc] init]; + vc.userId = self.userId; + vc.relation_id = md.relation_list.firstObject.relation_id; + [self.navigationController pushViewController:vc animated:YES]; +} + +-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ + if (self.model == nil) { + return 0; + }else{ + return 1+self.dataArray.count; + } +} + +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ + return 1; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ + if (indexPath.section == 0) { + if (self.model.cp) { + QXIntimateCpCell *cell = [QXIntimateCpCell cellWithTableView:tableView]; + cell.model = self.model.cp; + return cell; + }else{ + QXIntimateNoCpCell *cell = [QXIntimateNoCpCell cellWithTableView:tableView]; + return cell; + } + }else{ + QXRoomBestFriendListModel *md = self.dataArray[indexPath.section-1]; + if (md.relation_list.count > 1) { + QXIntimateListCell*cell = [QXIntimateListCell cellWithTableView:tableView]; + if (self.dataArray.count>0) { + QXRoomBestFriendListModel *md = self.dataArray[indexPath.section-1]; + cell.model = md; + } + return cell; + }else{ + MJWeakSelf + QXIntimateMoreListCell *cell = [QXIntimateMoreListCell cellWithTableView:tableView]; + QXRoomBestFriendListModel *md = self.dataArray.firstObject; + cell.model = md.relation_list.firstObject; + cell.deleteSuccessBlock = ^(QXRelationshipListModel * _Nonnull model) { + weakSelf.page = 1; + [weakSelf getList]; + }; + return cell; + } + + } +} + +-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ + UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.width, 50)]; + UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mine_intimate_title_bg"]]; + UILabel *titleLabel = [[UILabel alloc] init]; + titleLabel.font = [UIFont boldSystemFontOfSize:16]; + titleLabel.textColor = RGB16(0xffffff); + QXButton *btn = [[QXButton alloc] init]; + [btn setTitle:@"更多>>" forState:(UIControlStateNormal)]; + [btn setTitleColor:RGB16(0xE973FC) forState:(UIControlStateNormal)]; + btn.titleLabel.font = [UIFont systemFontOfSize:12]; + [btn addTarget:self action:@selector(moreAction:) forControlEvents:(UIControlEventTouchUpInside)]; + [header addSubview:btn]; + [header addSubview:imageView]; + [header addSubview:titleLabel]; + [imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(132); + make.height.mas_equalTo(36); + make.centerX.centerY.equalTo(header); + }]; + [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(header); + make.centerY.equalTo(header).offset(2); + }]; + [btn mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.mas_equalTo(-23); + make.top.bottom.equalTo(header); + make.width.mas_equalTo(40); + }]; + if (section == 0) { + titleLabel.text = @"心动"; + btn.hidden = YES; + }else{ + QXRoomBestFriendListModel *md = self.dataArray[section-1]; + titleLabel.text = md.relation_name; + if (md.relation_list.count>1) { + btn.hidden = NO; + btn.object = md; + }else{ + btn.hidden = YES; + } + } + return header; +} +-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ + return 50; +} + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ + if (indexPath.section == 0) { + if (self.model.cp) { + return ScaleWidth(100); + }else{ + return ScaleWidth(36); + } + }else{ + QXRoomBestFriendListModel *md = self.dataArray[indexPath.section-1]; + if (md.relation_list.count > 1) { + return ScaleWidth(92)+18; + }else{ + if (md.relation_list.count == 0) { + return 0; + }else{ + return ScaleWidth(100)+16; + } + } + + } +} + +-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{ + UIView *footer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.width, 15)]; + return footer; +} + +-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ + return 15; +} +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ + if (indexPath.section == 0) { + if (self.model.cp) { + QXHeartBeatSpaceViewController *vc = [[QXHeartBeatSpaceViewController alloc] init]; + vc.userId = self.userId; + [self.navigationController pushViewController:vc animated:YES]; + } + } +} +-(UITableView *)tableView{ + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, NavContentHeight+ScaleWidth(68), SCREEN_WIDTH, SCREEN_HEIGHT -NavContentHeight-ScaleWidth(68)) style:(UITableViewStyleGrouped)]; + _tableView.dataSource = self; + _tableView.delegate = self; + _tableView.backgroundColor = [UIColor clearColor]; + _tableView.tableFooterView = [UIView new]; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + if (@available(iOS 15.0, *)) { + _tableView.sectionHeaderTopPadding = 0; + } else { + // Fallback on earlier versions + } + MJWeakSelf + _tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + weakSelf.page = 1; + [weakSelf getList]; + }]; + _tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{ + weakSelf.page++; + [weakSelf getList]; + }]; + } + return _tableView; +} +@end diff --git a/QXLive/Mine(音域)/Controller/亲密关系/QXMoreIntimateViewController.h b/QXLive/Mine(音域)/Controller/亲密关系/QXMoreIntimateViewController.h new file mode 100644 index 0000000..50c69c2 --- /dev/null +++ b/QXLive/Mine(音域)/Controller/亲密关系/QXMoreIntimateViewController.h @@ -0,0 +1,17 @@ +// +// QXMoreIntimateViewController.h +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXBaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface QXMoreIntimateViewController : QXBaseViewController +@property (nonatomic,strong)NSString *userId; +@property (nonatomic,strong)NSString *relation_id; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/Controller/亲密关系/QXMoreIntimateViewController.m b/QXLive/Mine(音域)/Controller/亲密关系/QXMoreIntimateViewController.m new file mode 100644 index 0000000..d907673 --- /dev/null +++ b/QXLive/Mine(音域)/Controller/亲密关系/QXMoreIntimateViewController.m @@ -0,0 +1,76 @@ +// +// QXMoreIntimateViewController.m +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXMoreIntimateViewController.h" +#import "QXMineNetwork.h" +#import "QXIntimateMoreListCell.h" + +@interface QXMoreIntimateViewController () +@property (nonatomic,strong)UITableView *tableView; +@end + +@implementation QXMoreIntimateViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} +-(void)setUserId:(NSString *)userId{ + _userId = userId; +} +-(void)setRelation_id:(NSString *)relation_id{ + _relation_id = relation_id; + if (self.userId) { + [self getList]; + } +} +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ + return self.dataArray.count; +} +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ + QXIntimateMoreListCell *cell = [QXIntimateMoreListCell cellWithTableView:tableView]; + cell.model = self.dataArray[indexPath.row]; + MJWeakSelf + cell.topSuccessBlock = ^(QXRelationshipListModel * _Nonnull model) { + [weakSelf getList]; + }; + cell.deleteSuccessBlock = ^(QXRelationshipListModel * _Nonnull model) { + [weakSelf getList]; + }; + return cell; +} +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ + return ScaleWidth(92)+16; +} + +-(void)getList{ + MJWeakSelf + [QXMineNetwork userBestFriendsMoreListWithUserId:self.userId relation_id:self.relation_id successBlock:^(NSArray * _Nonnull model) { + [weakSelf.dataArray removeAllObjects]; + [weakSelf.dataArray addObjectsFromArray:model]; + [weakSelf.tableView reloadData]; + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + + }]; +} +-(UITableView *)tableView{ + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, NavContentHeight+ScaleWidth(68), SCREEN_WIDTH, SCREEN_HEIGHT -NavContentHeight-ScaleWidth(68)) style:(UITableViewStyleGrouped)]; + _tableView.dataSource = self; + _tableView.delegate = self; + _tableView.backgroundColor = [UIColor clearColor]; + _tableView.tableFooterView = [UIView new]; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + if (@available(iOS 15.0, *)) { + _tableView.sectionHeaderTopPadding = 0; + } else { + // Fallback on earlier versions + } + } + return _tableView; +} +@end diff --git a/QXLive/Mine(音域)/Controller/歌单列表/QXMineSongListViewController.h b/QXLive/Mine(音域)/Controller/歌单列表/QXMineSongListViewController.h new file mode 100644 index 0000000..4b8aa97 --- /dev/null +++ b/QXLive/Mine(音域)/Controller/歌单列表/QXMineSongListViewController.h @@ -0,0 +1,16 @@ +// +// QXMineSongListViewController.h +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import "QXBaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface QXMineSongListViewController : QXBaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/Controller/歌单列表/QXMineSongListViewController.m b/QXLive/Mine(音域)/Controller/歌单列表/QXMineSongListViewController.m new file mode 100644 index 0000000..17da4de --- /dev/null +++ b/QXLive/Mine(音域)/Controller/歌单列表/QXMineSongListViewController.m @@ -0,0 +1,196 @@ +// +// QXMineSongListViewController.m +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import "QXMineSongListViewController.h" +#import "QXMineNetwork.h" +#import "QXMineSongListCell.h" +#import "QXMineAddSongView.h" +#import "QXMineAddSongGiftView.h" +#import "QXCustomAlertView.h" + +@interface QXMineSongListViewController () +@property (nonatomic,strong)UITableView *tableView; +@property (nonatomic,strong)UILabel *countLabel; +@property (nonatomic,strong)QXMineAddSongView *addSongView; +@end + +@implementation QXMineSongListViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} +-(void)viewWillAppear:(BOOL)animated{ + [super viewWillAppear:animated]; + [self.navigationController setNavigationBarHidden:NO animated:YES]; +} +-(void)viewWillDisappear:(BOOL)animated{ + [super viewWillDisappear:animated]; + +} + +-(void)setNavgationItems{ + [super setNavgationItems];; + self.navigationItem.title = @"歌单列表"; + UIButton*recordBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)]; + [recordBtn setTitle:QXText(@"新增") forState:(UIControlStateNormal)]; + [recordBtn setTitleColor:QXConfig.themeColor forState:(UIControlStateNormal)]; + recordBtn.titleLabel.font = [UIFont systemFontOfSize:16]; + [recordBtn addTarget:self action:@selector(addAction) forControlEvents:(UIControlEventTouchUpInside)]; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:recordBtn]; +} +-(void)initSubViews{ + self.page = 1; + self.countLabel = [[UILabel alloc] initWithFrame:CGRectMake(16, NavContentHeight+12, 200, 17)]; + self.countLabel.textColor = RGB16A(0x000000,0.45); + self.countLabel.font = [UIFont systemFontOfSize:12]; + self.countLabel.text = @"共0首歌"; + [self.view addSubview:self.countLabel]; + + [self.view addSubview:self.tableView]; + [self getSongList]; +} + +-(void)getSongList{ + MJWeakSelf + [QXMineNetwork getUserSongListWithRoomId:@"" user_id:QXGlobal.shareGlobal.loginModel.user_id page:self.page SuccessBlock:^(NSArray * _Nonnull list, NSString * _Nonnull count) { + weakSelf.countLabel.text = [NSString stringWithFormat:@"共有%@首歌",count]; + if (weakSelf.page == 1) { + [weakSelf.dataArray removeAllObjects]; + } + [weakSelf.dataArray addObjectsFromArray:list]; + [weakSelf.tableView reloadData]; + [weakSelf.tableView.mj_header endRefreshing]; + if (list.count == 0) { + weakSelf.tableView.mj_footer.state = MJRefreshStateNoMoreData; + }else{ + [weakSelf.tableView.mj_header endRefreshing]; + } + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + + }]; +} + +-(void)didSeletedGift:(QXGiftModel *)giftModel giftCount:(nonnull NSString *)giftCount{ + giftModel.num = giftCount; + self.addSongView.giftModel = giftModel; +} + +-(void)qx_mineAddSongViewDidSeleteGift{ + QXMineAddSongGiftView *giftView = [[QXMineAddSongGiftView alloc] initWithFrame:[UIScreen mainScreen].bounds]; + giftView.delegate = self; + [giftView showInView:self.view]; +} + +-(void)qx_mineAddSongViewCommitWithSongName:(NSString *)songName giftModel:(QXGiftModel *)giftModel{ + MJWeakSelf + [QXMineNetwork mineUserAddAndDeleteAndEditWithType:0 Id:@"" songName:songName giftId:giftModel.gift_id giftNum:giftModel.num successBlock:^(NSDictionary * _Nonnull dict) { + showToast(@"添加成功"); + [weakSelf.addSongView hide]; + weakSelf.page = 1; + [weakSelf getSongList]; + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + showToast(@"添加失败"); + }]; +} +-(void)qx_mineAddSongViewDidRemove{ + self.addSongView = nil; +} +-(void)qx_mineEditSongViewCommitWithSongModel:(QXUserSongListModel *)songModel{ + MJWeakSelf + [QXMineNetwork mineUserAddAndDeleteAndEditWithType:1 Id:songModel.id songName:songModel.song_name giftId:songModel.gift_id giftNum:songModel.gift_num successBlock:^(NSDictionary * _Nonnull dict) { + showToast(@"修改成功"); + [weakSelf.addSongView hide]; + weakSelf.page = 1; + [weakSelf getSongList]; + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + showToast(@"修改失败"); + }]; +} +-(void)addAction{ + self.addSongView = [[QXMineAddSongView alloc] initWithFrame:[UIScreen mainScreen].bounds]; + self.addSongView.delegate = self; + [self.addSongView showInView:self.view]; +} + +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ + return self.dataArray.count; +} +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ + QXMineSongListCell *cell = [QXMineSongListCell cellWithTableView:tableView]; + cell.model = self.dataArray[indexPath.row]; + return cell; +} +-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{ + return YES; +} +-(UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath{ + QXUserSongListModel *model = self.dataArray[indexPath.row]; + MJWeakSelf + UIContextualAction *deletAction = [UIContextualAction contextualActionWithStyle:(UIContextualActionStyleDestructive) title:@"删除" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { + [weakSelf deleteSongWithModel:model]; + completionHandler(YES); + }]; + UIContextualAction *editAction = [UIContextualAction contextualActionWithStyle:(UIContextualActionStyleNormal) title:@"编辑" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { + [weakSelf editSongWithModel:model]; + completionHandler(YES); + }]; + editAction.backgroundColor = RGB16(0x3665F9); + UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[deletAction,editAction]]; + return config; +} + + +-(void)deleteSongWithModel:(QXUserSongListModel*)model{ + QXCustomAlertView *alertView = [[QXCustomAlertView alloc] init]; + [alertView showInView:self.view title:@"您确定要删除歌曲吗" message:[NSString stringWithFormat:@"歌曲名称:%@\n礼物信息:%@ x%@",model.song_name,model.gift_name,model.gift_num] cancleTitle:@"取消" commitTitle:@"确定"]; + MJWeakSelf + alertView.commitBlock = ^{ + [QXMineNetwork mineUserAddAndDeleteAndEditWithType:2 Id:model.id songName:model.song_name giftId:model.gift_id giftNum:model.gift_num successBlock:^(NSDictionary * _Nonnull dict) { + showToast(@"删除成功"); + weakSelf.page = 1; + [weakSelf getSongList]; + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + showToast(@"删除失败"); + }]; + }; +} + +-(void)editSongWithModel:(QXUserSongListModel*)model{ + self.addSongView = [[QXMineAddSongView alloc] initWithFrame:[UIScreen mainScreen].bounds]; + self.addSongView.delegate = self; + self.addSongView.songModel = model; + [self.addSongView showInView:self.view]; +} + +-(UITableView *)tableView{ + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectMake(16, self.countLabel.bottom+5, SCREEN_WIDTH-32, SCREEN_HEIGHT-NavContentHeight) style:(UITableViewStylePlain)]; + _tableView.dataSource = self; + _tableView.delegate = self; + _tableView.backgroundColor = [UIColor whiteColor]; + [_tableView addRoundedCornersWithRadius:16 byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)]; + _tableView.rowHeight = 45; +// _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + if (@available(iOS 15.0, *)) { + _tableView.sectionHeaderTopPadding = 0; + } else { + // Fallback on earlier versions + } + MJWeakSelf + _tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + weakSelf.page = 1; + [weakSelf getSongList]; + }]; + _tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{ + weakSelf.page++; + [weakSelf getSongList]; + }]; + } + return _tableView; +} +@end diff --git a/QXLive/Mine(音域)/Controller/歌手认证/QXRoomSingerAuthViewController.h b/QXLive/Mine(音域)/Controller/歌手认证/QXRoomSingerAuthViewController.h new file mode 100644 index 0000000..a39207b --- /dev/null +++ b/QXLive/Mine(音域)/Controller/歌手认证/QXRoomSingerAuthViewController.h @@ -0,0 +1,17 @@ +// +// QXRoomSingerAuthViewController.h +// QXLive +// +// Created by 启星 on 2025/11/12. +// + +#import "QXBaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface QXRoomSingerAuthViewController : QXBaseViewController +/// 当前状态:-1 未认证歌手, 0待审核 1已认证 2被拒绝 +@property (nonatomic,strong)NSString *singer_status; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/Controller/歌手认证/QXRoomSingerAuthViewController.m b/QXLive/Mine(音域)/Controller/歌手认证/QXRoomSingerAuthViewController.m new file mode 100644 index 0000000..c02342c --- /dev/null +++ b/QXLive/Mine(音域)/Controller/歌手认证/QXRoomSingerAuthViewController.m @@ -0,0 +1,116 @@ +// +// QXRoomSingerAuthViewController.m +// QXLive +// +// Created by 启星 on 2025/11/12. +// + +#import "QXRoomSingerAuthViewController.h" +#import "QXAudioRecorderView.h" + +@interface QXRoomSingerAuthViewController () +@property (nonatomic,strong)UIView *contentView; +@property (nonatomic,strong)UIImageView *contentImageView; + +@property (nonatomic,strong)UIImageView *myAuthImageView; +@property (nonatomic,strong)UIImageView *authStatusImageView; +@property (nonatomic,strong)UILabel *authStatusLabel; + +@property (nonatomic,strong)QXAudioRecorderView *audioRecorderView; +@end + +@implementation QXRoomSingerAuthViewController + +- (void)viewDidLoad { + self.isNoChangeBgImage = YES; + [super viewDidLoad]; + // Do any additional setup after loading the view. +} +-(void)viewWillAppear:(BOOL)animated{ + [super viewWillAppear:animated]; + [self.navigationController setNavigationBarHidden:NO animated:YES]; + self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:RGB16(0xffffff)}; +} +-(void)viewWillDisappear:(BOOL)animated{ + [super viewWillDisappear:animated]; + self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:RGB16(0x000000)}; +} +-(void)setNavgationItems{ + [super setNavgationItems]; + self.navigationTintColor = RGB16(0xffffff); + self.navigationItem.title = @"歌手认证"; + +} + +- (void)initSubViews{ + [self updateBgImage:@"singer_auth_bg"]; + self.contentView = [[UIView alloc] initWithFrame:CGRectMake(16, ScaleWidth(300), SCREEN_WIDTH-32, ScaleWidth(140))]; + [self.view addSubview:self.contentView]; + self.contentImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"singer_auth_center_bg"]]; + self.contentImageView.contentMode = UIViewContentModeScaleToFill; + self.contentImageView.frame = self.contentView.bounds; + [self.contentView addSubview:self.contentImageView]; + + self.myAuthImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"singer_auth_title_image"]]; + self.myAuthImageView.frame = CGRectMake((self.contentView.width-ScaleWidth(69))/2, ScaleWidth(10), ScaleWidth(69), ScaleWidth(24)); + [self.contentView addSubview:self.myAuthImageView]; + + self.authStatusImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"singer_auth_status_no"]]; + self.authStatusImageView.frame = CGRectMake((self.contentView.width-ScaleWidth(52))/2, self.myAuthImageView.bottom+ScaleWidth(22), ScaleWidth(52), ScaleWidth(52)); + [self.contentView addSubview:self.authStatusImageView]; + + self.authStatusLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.authStatusImageView.bottom+4, self.contentView.width, 17)]; + self.authStatusLabel.text = @"暂未认证"; + self.authStatusLabel.textColor = RGB16A(0x000000, 0.45); + self.authStatusLabel.font = [UIFont systemFontOfSize:12]; + self.authStatusLabel.textAlignment = NSTextAlignmentCenter; + [self.contentView addSubview:self.authStatusLabel]; + + + self.audioRecorderView = [[QXAudioRecorderView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT-kSafeAreaBottom-246, SCREEN_WIDTH, 246+kSafeAreaBottom) maxDuration:300]; + self.audioRecorderView.delegate = self; + self.audioRecorderView.hidden = YES; + [self.view addSubview:self.audioRecorderView]; + if ([self.singer_status isEqualToString:@"-1"] || [self.singer_status isEqualToString:@"2"]) { + self.audioRecorderView.hidden = NO; + } + if ([self.singer_status isEqualToString:@"-1"]) { + self.authStatusLabel.text = @"暂未认证"; + self.authStatusLabel.textColor = RGB16A(0x000000, 0.45); + }else if ([self.singer_status isEqualToString:@"0"]) { + self.authStatusLabel.text = @"待审核"; + self.authStatusLabel.textColor = RGB16(0xFF8832); + }else if ([self.singer_status isEqualToString:@"1"]) { + self.authStatusLabel.text = @"已认证"; + self.authStatusLabel.textColor = QXConfig.themeColor; + }else if ([self.singer_status isEqualToString:@"2"]) { + self.authStatusLabel.text = @"已拒绝"; + self.authStatusLabel.textColor = RGB16(0xFF2424); + } +} +#pragma mark - AudioRecorderViewDelegate + +- (void)qxAudioRecorderView:(QXAudioRecorderView *)recorderView didChangeState:(AudioRecorderState)state{ + NSLog(@"录音状态改变: %ld", (long)state); + +} + +- (void)qxAudioRecorderView:(QXAudioRecorderView *)recorderView didFinishRecordingWithMP3File:(NSURL *)mp3FileURL duration:(NSTimeInterval)duration{ + NSLog(@"录音完成,MP3文件: %@, 总时长: %.1f秒", mp3FileURL, duration); + + // 这里可以上传文件或进行其他处理 + NSData *audioData = [NSData dataWithContentsOfURL:mp3FileURL]; + NSLog(@"MP3文件大小: %.2f KB", audioData.length / 1024.0); +} + +- (void)qxAudioRecorderView:(QXAudioRecorderView *)recorderView didFailWithError:(NSError *)error{ + NSLog(@"录音失败: %@", error); + +} + +- (void)qxAudioRecorderView:(QXAudioRecorderView *)recorderView didUpdateProgress:(NSTimeInterval)progress totalDuration:(NSTimeInterval)totalDuration{ + // 实时更新进度 + +} + +@end diff --git a/QXLive/Mine(音域)/Controller/爵位/QXNobilityDetailViewController.m b/QXLive/Mine(音域)/Controller/爵位/QXNobilityDetailViewController.m index 0d244d6..1704861 100644 --- a/QXLive/Mine(音域)/Controller/爵位/QXNobilityDetailViewController.m +++ b/QXLive/Mine(音域)/Controller/爵位/QXNobilityDetailViewController.m @@ -157,6 +157,19 @@ [self setPirce]; [self.collectionView reloadData]; }); + _openBtn.enabled = YES; + if (![self.cruuent_nobility_id isExist]) { + [_openBtn setBackgroundImage:[UIImage imageNamed:@"nobility_detail_open_btn_nor"] forState:(UIControlStateNormal)]; + return; + } + if (self.currentIndex #import "QXGiftModel.h" #import "QXSongListModel.h" +#import "QXUserSongListModel.h" NS_ASSUME_NONNULL_BEGIN -@class QXRoomInfoModel,QXRoomPitModel,QXRoomOwnerModel,QXHeadLineModel,QXRoomAuction,QXRoomAuctionUser,QXRoomCpUser,QXRoomPkInfo,QXRoomFriendInfo,QXRoomFriendHeartListModel,QXRoomActivitySubModel,QXRoomActivityModel; +@class QXRoomInfoModel,QXRoomPitModel,QXRoomOwnerModel,QXHeadLineModel,QXRoomAuction,QXRoomAuctionUser,QXRoomCpUser,QXRoomPkInfo,QXRoomFriendInfo,QXRoomFriendHeartListModel,QXRoomActivitySubModel,QXRoomActivityModel,QXSingerInfo; @interface QXRoomModel : NSObject /// 房间信息 @property (nonatomic,strong)QXRoomInfoModel *room_info; @@ -20,6 +21,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,strong)QXRoomOwnerModel *user_info; /// 当前演唱者信息 @property (nonatomic,strong)QXSongListModel *song_user_info; +/// 点唱房演唱者信息 +@property (nonatomic,strong)QXSingerInfo *singer_info; /// 下一首歌曲信息 @property (nonatomic,strong)QXSongListModel *nextInfo; /// 拍卖房信息 @@ -375,4 +378,11 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,strong)NSString *xlh_status; @property (nonatomic,assign)long end_time; @end + + +@interface QXSingerInfo : NSObject +/// 心动值 +@property (nonatomic,strong)QXUserSongListModel *song_info; +@property (nonatomic,strong)QXUserSongListModel *next_song_info; +@end NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/Model/QXRoomModel.m b/QXLive/Mine(音域)/Model/QXRoomModel.m index c973c90..2f3d839 100644 --- a/QXLive/Mine(音域)/Model/QXRoomModel.m +++ b/QXLive/Mine(音域)/Model/QXRoomModel.m @@ -21,6 +21,7 @@ @"song_pit_list":@"QXRoomPitModel", @"friend_info":@"QXRoomFriendInfo", @"gift_cycle":@"QXRoomActivityModel", + @"singer_info":@"QXSingerInfo", }; } @@ -144,3 +145,14 @@ @end + + +@implementation QXSingerInfo ++(NSDictionary *)modelContainerPropertyGenericClass{ + return @{ + @"song_info" : @"QXUserSongListModel", + @"next_song_info" : @"QXUserSongListModel", + }; +} + +@end diff --git a/QXLive/Mine(音域)/Model/QXUserModel.h b/QXLive/Mine(音域)/Model/QXUserModel.h index 49346a1..24d485b 100644 --- a/QXLive/Mine(音域)/Model/QXUserModel.h +++ b/QXLive/Mine(音域)/Model/QXUserModel.h @@ -7,7 +7,7 @@ #import -@class QXRelationshipListModel; +@class QXRelationshipListModel,QXUserCpInfoModel; NS_ASSUME_NONNULL_BEGIN @interface QXUserModel : NSObject @@ -47,6 +47,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,strong)NSString *is_hide; /// 当前状态:0-取消隐身,1-隐身进入 @property (nonatomic,strong)NSString *hide_status; +/// 当前状态:-1 未认证歌手, 0待审核 1已认证 2被拒绝 +@property (nonatomic,strong)NSString *singer_status; /// 在线状态 @property (nonatomic,assign)BOOL is_online; /// 1 能聊天 0不能聊天 @@ -124,6 +126,8 @@ NS_ASSUME_NONNULL_BEGIN /// 是否使用靓号 0未使用 1 已使用 @property (nonatomic,strong)NSString *is_use_code; +@property (nonatomic,strong)QXUserCpInfoModel *cp_info; + -(instancetype)copyModel; @end @@ -208,8 +212,10 @@ NS_ASSUME_NONNULL_BEGIN /// 角色 1-房主 > 2-管理员 > 3主持人 >4 普通用户 排序 @property (nonatomic,strong)NSString *role; -@property (nonatomic,strong)QXRelationshipListModel *qinmi; -@property (nonatomic,strong)QXRelationshipListModel *zhenai; +@property (nonatomic,strong)QXUserCpInfoModel *cp_info; + +//@property (nonatomic,strong)QXRelationshipListModel *qinmi; +//@property (nonatomic,strong)QXRelationshipListModel *zhenai; @end @@ -254,7 +260,23 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,strong)NSString *image; /// 亲密拍心动值 @property (nonatomic,strong)NSString *heart_value; +@property (nonatomic,strong)NSString *sex2; +@property (nonatomic,strong)NSString *sex1; /// 1-置顶,0-不置顶 @property (nonatomic,strong)NSString *is_top; @end + +@interface QXUserCpInfoModel : NSObject +@property (nonatomic,strong)NSString *name; +@property (nonatomic,strong)NSString *user_id1; +@property (nonatomic,strong)NSString *user_id2; +@property (nonatomic,strong)NSString *level; +@property (nonatomic,strong)NSString *exp; +/// 挂件(装扮)地址 +@property (nonatomic,strong)NSString *pendant; +/// 挂件上的头像位置:0-上,1-右上,2-右,3-右下,4-下,5-左下,6-左,7-左上' +@property (nonatomic,strong)NSString *direction; +@property (nonatomic,strong)QXUserModel *user_info1; +@property (nonatomic,strong)QXUserModel *user_info2; +@end NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/Model/QXUserModel.m b/QXLive/Mine(音域)/Model/QXUserModel.m index 8552c91..7bcb223 100644 --- a/QXLive/Mine(音域)/Model/QXUserModel.m +++ b/QXLive/Mine(音域)/Model/QXUserModel.m @@ -16,7 +16,10 @@ +(NSDictionary *)modelContainerPropertyGenericClass{ - return @{@"tag_list" : @"QXUserTag"}; + return @{ + @"tag_list" : @"QXUserTag", + @"cp_info": @"QXUserCpInfoModel" + }; } @@ -56,8 +59,9 @@ +(NSDictionary *)modelContainerPropertyGenericClass{ return @{ - @"qinmi" : @"QXRelationshipListModel", - @"zhenai" : @"QXRelationshipListModel" +// @"qinmi" : @"QXRelationshipListModel", +// @"zhenai" : @"QXRelationshipListModel" + @"cp_info": @"QXUserCpInfoModel" }; } @@ -79,3 +83,17 @@ @end + + +@implementation QXUserCpInfoModel + ++(NSDictionary *)modelContainerPropertyGenericClass{ + return @{ +// @"qinmi" : @"QXRelationshipListModel", +// @"zhenai" : @"QXRelationshipListModel" + @"user_info1": @"QXUserModel", + @"user_info2": @"QXUserModel", + }; +} + +@end diff --git a/QXLive/Mine(音域)/Services/QXMineNetwork.h b/QXLive/Mine(音域)/Services/QXMineNetwork.h index 44dd29c..daa559b 100644 --- a/QXLive/Mine(音域)/Services/QXMineNetwork.h +++ b/QXLive/Mine(音域)/Services/QXMineNetwork.h @@ -28,6 +28,8 @@ #import "QXNobilityModel.h" #import "QXNobilityListModel.h" #import "QXNobilityGetPriceModel.h" +#import "QXUserSongListModel.h" +#import "QXRoomBestFriendModel.h" NS_ASSUME_NONNULL_BEGIN @@ -1186,6 +1188,99 @@ NS_ASSUME_NONNULL_BEGIN successBlock:(void (^)(NSDictionary* dict))successBlock failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + +/** + 歌手认证 + */ ++(void)singerAuthWithSong:(NSString*)song + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + + +/** + 用户歌单 + */ ++(void)getUserSongListWithRoomId:(NSString*)room_id + user_id:(NSString*)user_id + page:(NSInteger)page + SuccessBlock:(void (^)(NSArray* list,NSString*count))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + + +/** + 用户添加/修改/删除歌曲 + type 0 添加 1 修改 2 删除 + */ ++(void)mineUserAddAndDeleteAndEditWithType:(NSInteger)type + Id:(NSString*)Id + songName:(NSString*)songName + giftId:(NSString*)giftId + giftNum:(NSString*)giftNum + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + +/** + 点歌 + */ ++(void)requestSongWithSongId:(NSString*)songId + roomId:(NSString*)roomId + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + + +/** + 点歌列表 + */ ++(void)requestSongWithRoomId:(NSString*)roomId + type:(NSInteger)type + page:(NSInteger)page + successBlock:(void (^)(NSArray* list,NSString*count))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + +/** + 歌曲置顶 + */ ++(void)requestSongToTopWithId:(NSString*)Id + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + +/** + 获取点歌房歌曲数量 + */ ++(void)requestSongCountWithRoomId:(NSString*)roomId + successBlock:(void (^)(QXUserSongListCount*model))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + +/** + 点唱房切歌 + */ ++(void)requsetSongNextActionWithId:(NSString*)Id + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; +/** + cp礼物回赠 + */ ++(void)userCpReSendWithGiftId:(NSString *)giftId + userId:(NSString*)userId + roomId:(NSString*)roomId + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; +/** + 获取挚友列表 + */ ++(void)userBestFriendsListWithUserId:(NSString*)userId + page:(NSInteger)page + successBlock:(void (^)(QXRoomBestFriendModel* model))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + +/** + 更多挚友列表 + */ ++(void)userBestFriendsMoreListWithUserId:(NSString*)userId + relation_id:(NSString*)relation_id + successBlock:(void (^)(NSArray< QXRelationshipListModel*>* model))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock; + @end diff --git a/QXLive/Mine(音域)/Services/QXMineNetwork.m b/QXLive/Mine(音域)/Services/QXMineNetwork.m index 8a485cb..af883b0 100644 --- a/QXLive/Mine(音域)/Services/QXMineNetwork.m +++ b/QXLive/Mine(音域)/Services/QXMineNetwork.m @@ -22,6 +22,7 @@ [QXGlobal shareGlobal].loginModel.nickname_color = userModel.nickname_color; [QXGlobal shareGlobal].loginModel.is_hide = userModel.is_hide; [QXGlobal shareGlobal].loginModel.hide_status = userModel.hide_status; + [QXGlobal shareGlobal].loginModel.singer_status = userModel.singer_status; [[QXGlobal shareGlobal] updateUserInfoWithMolde:[QXGlobal shareGlobal].loginModel]; BOOL api_version = [responseObject[@"api_version"] boolValue]; [QXGlobal shareGlobal].isAppStore = api_version; @@ -687,10 +688,30 @@ @"pit_number":pit_number?pit_number:@"", @"heart_id":heart_id?heart_id:@"" }; + __block NSString *userId = to_uid; [[QXRequset shareInstance] postWithUrl:QXSendGift parameters:parameters needCache:NO success:^(id responseObject) { if (successBlock) { successBlock(responseObject[@"data"]); } +// NSDictionary *cp_type = [NSDictionary stringWithFormat:@"%@",responseObject[@"data"][@"cp_type"]]; + id object = responseObject[@"data"][@"cp_type"]; + if ([object isKindOfClass:[NSDictionary class]]) { + NSDictionary *cpDict = (NSDictionary *)object; + NSString *cp_type = [NSString stringWithFormat:@"%@",cpDict[@"cp_type"]]; + if (cp_type.intValue == 1) { + /// 单向送cp礼物 + NSString *jsonStr = [cpDict jsonStringEncoded]; + [[QXRoomMessageManager shared] sendC2CMessage:jsonStr messageType:(QXRoomMessageTypeSendAndRecieveCpHeartSignal) userId:userId]; + }else if (cp_type.intValue == 2){ + /// cp礼物已达成双向绑定 + NSString *jsonStr = [cpDict jsonStringEncoded]; + [[QXRoomMessageManager shared] sendC2CMessage:jsonStr messageType:(QXRoomMessageTypeCpHeartFinished) userId:userId]; + [[QXRoomMessageManager shared] showCpFinishedAlertViewWithText:[NSString stringWithFormat:@"%@",cpDict[@"text"]]]; + }else{ + + } + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { failBlock(error,msg); }]; @@ -2314,4 +2335,213 @@ }]; } ++(void)singerAuthWithSong:(NSString*)song + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock{ + NSDictionary *parameters =@{ + @"song":song?song:@"", + }; + [[QXRequset shareInstance] postWithUrl:QXMineSingerAuth parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + successBlock(responseObject[@"data"]); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} + ++(void)getUserSongListWithRoomId:(NSString *)room_id + user_id:(NSString *)user_id + page:(NSInteger)page + SuccessBlock:(void (^)(NSArray* list,NSString*count))successBlock + failBlock:(void (^)(NSError * _Nonnull, NSString * _Nonnull))failBlock{ + NSDictionary *parameters =@{ + @"room_id":room_id?room_id:@"", + @"user_id":user_id?user_id:@"", + @"page":[NSNumber numberWithInteger:page] + }; + [[QXRequset shareInstance] postWithUrl:QXMineGetSingerSongList parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + NSArray*list = [NSArray yy_modelArrayWithClass:[QXUserSongListModel class] json:responseObject[@"data"][@"lists"]]; + NSString*count = [NSString stringWithFormat:@"%@",responseObject[@"data"][@"count"]]; + successBlock(list,count); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} + ++(void)mineUserAddAndDeleteAndEditWithType:(NSInteger)type + Id:(NSString*)Id + songName:(NSString*)songName + giftId:(NSString*)giftId + giftNum:(NSString*)giftNum + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock{ + NSString *url = QXMineSingerAddSong; + if (type == 0) { + url = QXMineSingerAddSong; + }else if(type == 1){ + url = QXMineSingerEidtSong; + }else{ + url = QXMineSingerDeleteSong; + } + + NSDictionary *parameters =@{ + @"id":Id?:@"", + @"song_name":songName?:@"", + @"gift_id":giftId?:@"", + @"gift_num":giftNum?:@"", + }; + [[QXRequset shareInstance] postWithUrl:url parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + successBlock(responseObject[@"data"]); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} +/** + 点歌 + */ ++(void)requestSongWithSongId:(NSString*)songId + roomId:(NSString*)roomId + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock{ + NSDictionary *parameters =@{ + @"song_id":songId?:@"", + @"room_id":roomId?:@"", + }; + [[QXRequset shareInstance] postWithUrl:QXRoomRequestSong parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + successBlock(responseObject[@"data"]); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} + + +/** + 点歌列表 + */ ++(void)requestSongWithRoomId:(NSString*)roomId + type:(NSInteger)type + page:(NSInteger)page + successBlock:(void (^)(NSArray* list,NSString*count))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock{ + NSDictionary *parameters =@{ + @"type":[NSNumber numberWithInteger:type], + @"room_id":roomId?:@"", + @"page":[NSNumber numberWithInteger:page] + }; + [[QXRequset shareInstance] postWithUrl:QXRoomAllSongList parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + NSArray*list = [NSArray yy_modelArrayWithClass:[QXUserSongListModel class] json:responseObject[@"data"][@"lists"]]; + NSString*count = [NSString stringWithFormat:@"%@",responseObject[@"data"][@"count"]]; + successBlock(list,count); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} + +/** + 歌曲置顶 + */ ++(void)requestSongToTopWithId:(NSString*)Id + successBlock:(void (^)(NSDictionary* dict))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock{ + NSDictionary *parameters =@{ + @"id":Id?:@"", + }; + [[QXRequset shareInstance] postWithUrl:QXRoomRequestSongTop parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + successBlock(responseObject[@"data"]); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} + ++(void)requestSongCountWithRoomId:(NSString*)roomId + successBlock:(void (^)(QXUserSongListCount*model))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock{ + NSDictionary *parameters =@{ + @"room_id":roomId?:@"", + }; + [[QXRequset shareInstance] postWithUrl:QXRoomRequestSongCount parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + QXUserSongListCount *countModel = [QXUserSongListCount yy_modelWithJSON:responseObject[@"data"]]; + successBlock(countModel); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} + + ++(void)requsetSongNextActionWithId:(NSString *)Id successBlock:(void (^)(NSDictionary * _Nonnull))successBlock failBlock:(void (^)(NSError * _Nonnull, NSString * _Nonnull))failBlock{ + NSDictionary *parameters =@{ + @"id":Id?:@"", + }; + [[QXRequset shareInstance] postWithUrl:QXRoomRequestSongNext parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + successBlock(responseObject[@"data"]); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} + + ++(void)userCpReSendWithGiftId:(NSString *)giftId userId:(NSString*)userId roomId:(NSString*)roomId successBlock:(void (^)(NSDictionary * _Nonnull))successBlock failBlock:(void (^)(NSError * _Nonnull, NSString * _Nonnull))failBlock{ + NSDictionary *parameters =@{ + @"gift_id":giftId?:@"", + @"user_id":userId?:@"", + @"room_id":roomId?:@"" + }; + [[QXRequset shareInstance] postWithUrl:QXUserCpResend parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + successBlock(responseObject[@"data"]); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} ++(void)userBestFriendsListWithUserId:(NSString*)userId + page:(NSInteger)page + successBlock:(void (^)(QXRoomBestFriendModel* model))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock{ + NSDictionary *parameters =@{ + @"user_id":userId?:@"", + @"page":[NSNumber numberWithInteger:page] + }; + [[QXRequset shareInstance] postWithUrl:QXBestFriendsList parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + QXRoomBestFriendModel *model = [QXRoomBestFriendModel yy_modelWithJSON:responseObject[@"data"]]; + successBlock(model); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} + ++(void)userBestFriendsMoreListWithUserId:(NSString*)userId + relation_id:(NSString*)relation_id + successBlock:(void (^)(NSArray< QXRelationshipListModel*>* model))successBlock + failBlock:(void (^)(NSError * error, NSString * msg))failBlock{ + NSDictionary *parameters =@{ + @"user_id":userId?:@"", + @"relation_id":relation_id?:@"" + }; + [[QXRequset shareInstance] postWithUrl:QXBestFriendsMoreList parameters:parameters needCache:NO success:^(id responseObject) { + if (successBlock) { + NSArray *list = [NSArray yy_modelArrayWithClass:[QXRelationshipListModel class] json:responseObject[@"data"]]; + successBlock(list); + } + } fail:^(NSError *error, NSString *msg, NSURLSessionDataTask *task) { + failBlock(error,msg); + }]; +} @end diff --git a/QXLive/Mine(音域)/View/QXMainHeaderView.m b/QXLive/Mine(音域)/View/QXMainHeaderView.m index ec7a6d5..6f50a9b 100644 --- a/QXLive/Mine(音域)/View/QXMainHeaderView.m +++ b/QXLive/Mine(音域)/View/QXMainHeaderView.m @@ -87,7 +87,9 @@ self.nameLabel = [[CKShimmerLabel alloc] initWithFrame:CGRectMake(self.userHeaderView.right+6, self.userHeaderView.top+5, self.width-self.userHeaderView.right-16-6, 22)]; self.nameLabel.shimmerWidth = 20; self.nameLabel.shimmerRadius = 20; - self.nameLabel.shimmerColor = [UIColor yellowColor]; + self.nameLabel.durationTime = 1; + self.nameLabel.text = @"羽声语音"; +// self.nameLabel.shimmerColor = [UIColor yellowColor]; self.nameLabel.repeat = YES; self.nameLabel.textColor = RGB16A(0xffffff,0.85); self.nameLabel.font = [UIFont boldSystemFontOfSize:18]; @@ -321,6 +323,7 @@ if (QXGlobal.shareGlobal.isOpenRecharge) { [self.toolsArray insertObject:self.rechargeModel atIndex:0]; } + [self.collectionView reloadData]; } -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return self.toolsArray.count; @@ -367,9 +370,10 @@ [self.userHeaderView setHeadIcon:userModel.avatar dress:userModel.dress]; [self.userHeaderView.nobilityImageView sd_setImageWithURL:[NSURL URLWithString:userModel.nobility_image]]; if ([userModel.nickname_color isExist]) { - self.nameLabel.textColor = [UIColor colorWithHexString:userModel.nickname_color]; + self.nameLabel.shimmerColor = [UIColor colorWithHexString:userModel.nickname_color]; + [self.nameLabel startShimmer]; }else{ - self.nameLabel.textColor = RGB16A(0xffffff,0.85); + [self.nameLabel stopShimmer]; } self.nameLabel.text = userModel.nickname; self.idLabel.text = [NSString stringWithFormat:@"ID:%@",userModel.user_code]; diff --git a/QXLive/Mine(音域)/View/QXMineServiceCell.h b/QXLive/Mine(音域)/View/QXMineServiceCell.h index 076a615..936c7b7 100644 --- a/QXLive/Mine(音域)/View/QXMineServiceCell.h +++ b/QXLive/Mine(音域)/View/QXMineServiceCell.h @@ -27,6 +27,10 @@ typedef NS_ENUM(NSInteger) { QXMineServiceTypeReport = 47, /// 个税客服 QXMineServiceTypeCustomerService = 48, + /// 歌手认证 + QXMineServiceTypeSingerAuth = 49, + /// 我的歌单 + QXMineServiceTypeSongList = 50, }QXMineServiceType; @protocol QXMineServiceCellDelegate diff --git a/QXLive/Mine(音域)/View/QXMineServiceCell.m b/QXLive/Mine(音域)/View/QXMineServiceCell.m index 813ca70..a28020b 100644 --- a/QXLive/Mine(音域)/View/QXMineServiceCell.m +++ b/QXLive/Mine(音域)/View/QXMineServiceCell.m @@ -115,6 +115,7 @@ [self.moreArray insertObject:self.inviteModel atIndex:1]; } } + [self.collectionView reloadData]; } -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return self.isMore?self.moreArray.count:self.serviceArray.count; @@ -196,11 +197,23 @@ md4.icon = @"service_customer_service"; md4.type = QXMineServiceTypeCustomerService; + QXServiceModel *md5 = [[QXServiceModel alloc] init]; + md5.title = @"歌手认证"; + md5.icon = @"service_singer_auth"; + md5.type = QXMineServiceTypeSingerAuth; + + QXServiceModel *md6 = [[QXServiceModel alloc] init]; + md6.title = @"我的歌单"; + md6.icon = @"service_songlist"; + md6.type = QXMineServiceTypeSongList; + _moreArray = [NSMutableArray arrayWithArray:@[ md1, md2, md3, md4, + md5, + md6, ]]; } diff --git a/QXLive/Mine(音域)/View/个人主页/QXUserHomeHeaderView.h b/QXLive/Mine(音域)/View/个人主页/QXUserHomeHeaderView.h index 34c12ed..0ecdb75 100644 --- a/QXLive/Mine(音域)/View/个人主页/QXUserHomeHeaderView.h +++ b/QXLive/Mine(音域)/View/个人主页/QXUserHomeHeaderView.h @@ -11,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN @interface QXUserHomeHeaderView : UIView @property (nonatomic,strong)QXUserHomeModel *model; +@property (nonatomic,strong)NSString *userId; @end @interface QXTagImageCell : UICollectionViewCell diff --git a/QXLive/Mine(音域)/View/个人主页/QXUserHomeHeaderView.m b/QXLive/Mine(音域)/View/个人主页/QXUserHomeHeaderView.m index 2d995f0..e11763e 100644 --- a/QXLive/Mine(音域)/View/个人主页/QXUserHomeHeaderView.m +++ b/QXLive/Mine(音域)/View/个人主页/QXUserHomeHeaderView.m @@ -12,24 +12,35 @@ #import "NSString+QX.h" #import "QXDynamicNetwork.h" #import "QXChatViewController.h" +#import "CKShimmerLabel.h" +#import "QXUserCpDressView.h" +#import "QXUserCpCardView.h" +#import "QXGiftWallViewController.h" +#import "QXHeartBeatSpaceViewController.h" @interface QXUserHomeHeaderView() +//@property (nonatomic,strong) CKShimmerLabel * tempName; @property (nonatomic,strong) QXSeatHeaderView* headerView; @property (nonatomic,strong) UIView * whiteBgView; @property (nonatomic,strong) UIView * grayBgView; -@property (nonatomic,strong) UILabel * nameLabel; +@property (nonatomic,strong) CKShimmerLabel * nameLabel; @property (nonatomic,strong) UILabel * idLabel; -@property (nonatomic,strong) UILabel * ageLabel; +//@property (nonatomic,strong) UILabel * ageLabel; +@property (nonatomic,strong) UIImageView * guildBgImageView; @property (nonatomic,strong) UILabel * guildLabel; @property (nonatomic,strong) UICollectionView * collectionView; @property (nonatomic,strong) NSMutableArray * tagArray; @property (nonatomic,strong) UILabel *introduceLabel; @property (nonatomic,strong) UICollectionView *inCollectionView; @property (nonatomic, strong) UIImageView *useCodeImageView; -@property (nonatomic, strong)UIImageView *sexImageView; +//@property (nonatomic, strong)UIImageView *sexImageView; @property (nonatomic,strong) UIButton *followBtn; @property (nonatomic,strong) UIButton *playBtn; +@property (nonatomic,strong) QXUserCpDressView *cpDressView; +@property (nonatomic,strong) QXUserCpCardView *cpCardView; + +@property (nonatomic,strong) UIButton *giftWallBtn; @end @implementation QXUserHomeHeaderView @@ -45,8 +56,8 @@ -(void)initSubviews{ self.backgroundColor = [UIColor clearColor]; + self.headerView = [[QXSeatHeaderView alloc] initWithFrame:CGRectMake(32, 26, 70, 84)]; - self.headerView = [[QXSeatHeaderView alloc] initWithFrame:CGRectMake(32, 46, 70, 70)]; [self.headerView addRoundedCornersWithRadius:35]; [self addSubview:self.headerView]; [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) { @@ -56,34 +67,59 @@ make.top.mas_equalTo(26); }]; - - - self.nameLabel = [[UILabel alloc] init]; + self.nameLabel = [[CKShimmerLabel alloc] initWithFrame:CGRectMake(32, self.headerView.bottom+4, 200, 24)]; +// self.nameLabel.text = @"羽声语音"; + self.nameLabel.shimmerWidth = 20; + self.nameLabel.shimmerRadius = 20; + self.nameLabel.durationTime = 1; + self.nameLabel.repeat = YES; self.nameLabel.textColor = QXConfig.textColor; - self.nameLabel.font = [UIFont boldSystemFontOfSize:16]; +// self.nameLabel.shimmerColor = [UIColor yellowColor]; + self.nameLabel.font = [UIFont boldSystemFontOfSize:18]; +// [self.nameLabel startShimmer]; [self addSubview:self.nameLabel]; [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.headerView); make.height.mas_equalTo(24); make.top.equalTo(self.headerView.mas_bottom).offset(4); + make.width.mas_greaterThanOrEqualTo(200); }]; - self.sexImageView = [[UIImageView alloc] init]; - [self addSubview:self.sexImageView]; - [self.sexImageView mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.nameLabel.mas_right).offset(5); + self.followBtn = [[UIButton alloc] initWithFrame:CGRectMake(self.playBtn.left-6-91, self.whiteBgView.top+10, 91, 12)]; + [self.followBtn setTitle:QXText(@"关注") forState:(UIControlStateNormal)]; + [self.followBtn setTitle:QXText(@"已关注") forState:(UIControlStateSelected)]; + [self.followBtn setTitleColor:QXConfig.btnTextColor forState:(UIControlStateNormal)]; + [self.followBtn setTitleColor:RGB16(0x999999) forState:(UIControlStateSelected)]; + [self.followBtn setBackgroundImage:[UIImage imageWithColor:QXConfig.themeColor] forState:UIControlStateNormal]; + [self.followBtn setBackgroundImage:[UIImage imageWithColor:RGB16(0xF1F2F3)] forState:UIControlStateSelected]; + self.followBtn.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.followBtn addRoundedCornersWithRadius:12]; + self.followBtn.hidden = YES; + [self.followBtn addTarget:self action:@selector(followAction) forControlEvents:(UIControlEventTouchUpInside)]; + [self addSubview:self.followBtn]; + [self.followBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.nameLabel.mas_right).offset(10); + make.width.mas_equalTo(55); + make.height.mas_equalTo(24); make.centerY.equalTo(self.nameLabel); - make.height.width.mas_equalTo(16); }]; +// self.sexImageView = [[UIImageView alloc] init]; +// [self addSubview:self.sexImageView]; +// [self.sexImageView mas_makeConstraints:^(MASConstraintMaker *make) { +// make.left.equalTo(self.nameLabel.mas_right).offset(5); +// make.centerY.equalTo(self.nameLabel); +// make.height.width.mas_equalTo(16); +// }]; + self.idLabel = [[UILabel alloc] init]; self.idLabel.textColor = RGB16(0x999999); self.idLabel.font = [UIFont boldSystemFontOfSize:12]; [self addSubview:self.idLabel]; [self.idLabel mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.sexImageView.mas_right).offset(12); - make.height.mas_equalTo(24); - make.centerY.equalTo(self.nameLabel); + make.left.equalTo(self.nameLabel); + make.height.mas_equalTo(18); + make.top.equalTo(self.nameLabel.mas_bottom).offset(5); }]; self.useCodeImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mine_usercode_isLiang"]]; @@ -96,16 +132,16 @@ make.centerY.equalTo(self.idLabel); }]; - self.ageLabel = [[UILabel alloc] init]; - self.ageLabel.textColor = RGB16(0x999999); - self.ageLabel.font = [UIFont boldSystemFontOfSize:12]; - [self addSubview:self.ageLabel]; - [self.ageLabel mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.headerView); - make.height.mas_equalTo(18); - make.top.equalTo(self.nameLabel.mas_bottom).offset(8); - make.width.mas_greaterThanOrEqualTo(35); - }]; +// self.ageLabel = [[UILabel alloc] init]; +// self.ageLabel.textColor = RGB16(0x999999); +// self.ageLabel.font = [UIFont boldSystemFontOfSize:12]; +// [self addSubview:self.ageLabel]; +// [self.ageLabel mas_makeConstraints:^(MASConstraintMaker *make) { +// make.left.equalTo(self.headerView); +// make.height.mas_equalTo(18); +// make.top.equalTo(self.nameLabel.mas_bottom).offset(8); +// make.width.mas_greaterThanOrEqualTo(35); +// }]; UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.itemSize = CGSizeMake(UserIconWidth, UserIconHeight); @@ -118,25 +154,13 @@ [self.collectionView registerClass:[QXTagImageCell class] forCellWithReuseIdentifier:@"QXTagImageCell"]; [self addSubview:self.collectionView]; [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.ageLabel.mas_right).offset(8); + make.left.equalTo(self.nameLabel); make.height.mas_equalTo(18); - make.centerY.equalTo(self.ageLabel); - make.width.mas_equalTo(300); + make.top.equalTo(self.idLabel.mas_bottom).offset(5); + make.width.mas_equalTo(ScaleWidth(240)); }]; - self.guildLabel = [[UILabel alloc] init]; - self.guildLabel.textColor = RGB16(0x999999); - self.guildLabel.text = @"所属公会"; - self.guildLabel.font = [UIFont boldSystemFontOfSize:12]; - [self addSubview:self.guildLabel]; - [self.guildLabel mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.headerView); - make.height.mas_equalTo(18); - make.top.equalTo(self.ageLabel.mas_bottom).offset(8); - make.width.mas_greaterThanOrEqualTo(35); - }]; - self.introduceLabel = [[UILabel alloc] init]; self.introduceLabel.textColor = QXConfig.textColor; self.introduceLabel.font = [UIFont systemFontOfSize:14]; @@ -144,9 +168,9 @@ [self addSubview:self.introduceLabel]; [self.introduceLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.headerView); - make.top.equalTo(self.guildLabel.mas_bottom).offset(4); + make.top.equalTo(self.collectionView.mas_bottom).offset(6); make.width.mas_equalTo(SCREEN_WIDTH-64); - make.height.mas_greaterThanOrEqualTo(22); + make.height.mas_greaterThanOrEqualTo(17); }]; UICollectionViewFlowLayout *inlayout = [[UICollectionViewFlowLayout alloc] init]; @@ -164,70 +188,113 @@ make.left.equalTo(self.headerView); make.height.mas_equalTo(22); make.top.equalTo(self.introduceLabel.mas_bottom).offset(4); - make.width.mas_equalTo(SCREEN_WIDTH-64); + make.right.mas_equalTo(-32); }]; self.whiteBgView = [[UIView alloc] initWithFrame:CGRectMake(0, 46, self.width, 167)]; - self.whiteBgView.backgroundColor = [UIColor whiteColor]; + self.whiteBgView.backgroundColor = RGB16(0xffffff); [self.whiteBgView addRoundedCornersWithRadius:16]; [self insertSubview:self.whiteBgView belowSubview:self.headerView]; [self.whiteBgView mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.mas_equalTo(16); - make.width.mas_equalTo(SCREEN_WIDTH-32); + make.left.mas_equalTo(0); + make.right.mas_equalTo(0); make.top.equalTo(self.headerView.mas_top).offset(20); - make.bottom.equalTo(self); + make.bottom.equalTo(self.inCollectionView).offset(10); }]; + self.guildBgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"user_home_guild_bg"]]; + [self.whiteBgView addSubview:self.guildBgImageView]; + [self.guildBgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.mas_equalTo(-8); + make.height.mas_equalTo(31); + make.top.mas_equalTo(6); + make.width.mas_equalTo(94); + }]; + + self.guildLabel = [[UILabel alloc] init]; + self.guildLabel.textColor = RGB16(0xffffff); + self.guildLabel.textAlignment = NSTextAlignmentCenter; + self.guildLabel.lineBreakMode = NSLineBreakByClipping; + self.guildLabel.font = [UIFont boldSystemFontOfSize:10]; + [self.whiteBgView addSubview:self.guildLabel]; + [self.guildLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.guildBgImageView).offset(6); + make.height.mas_equalTo(14); + make.top.equalTo(self.guildBgImageView).offset(6); + make.right.equalTo(self.guildBgImageView).offset(-28); + }]; + + self.grayBgView = [[UIView alloc] initWithFrame:CGRectMake(0, self.whiteBgView.top+75, self.width, 92)]; - self.grayBgView.backgroundColor = RGB16(0xF6F6F6); - [self.grayBgView addRoundedCornersWithRadius:16 byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)]; + self.grayBgView.backgroundColor = RGB16(0xF3F3F3); +// [self.grayBgView addRoundedCornersWithRadius:16 byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)]; [self insertSubview:self.grayBgView belowSubview:self.whiteBgView]; [self.grayBgView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.equalTo(self); - make.height.mas_equalTo(92); - make.bottom.equalTo(self.whiteBgView); + make.top.equalTo(self.whiteBgView).offset(16); + make.bottom.equalTo(self); }]; - self.playBtn = [[UIButton alloc] initWithFrame:CGRectMake(self.playBtn.left-6-91, self.whiteBgView.top+10, 91, 35)]; + self.playBtn = [[UIButton alloc] initWithFrame:CGRectMake(self.playBtn.left-6-91, self.whiteBgView.top+10, 91, 24)]; // [self.playBtn setTitle:QXText(@"私信") forState:(UIControlStateNormal)]; // [self.playBtn setTitleColor:UIColor.whiteColor forState:(UIControlStateNormal)]; // self.playBtn.backgroundColor = RGB16(0x333333); self.playBtn.hidden = YES; self.playBtn.titleLabel.font = [UIFont systemFontOfSize:14]; - [self.playBtn addRoundedCornersWithRadius:17.5]; + [self.playBtn addRoundedCornersWithRadius:12]; [self.playBtn addTarget:self action:@selector(playAction) forControlEvents:(UIControlEventTouchUpInside)]; - [self addSubview:self.playBtn]; + [self.whiteBgView addSubview:self.playBtn]; [self.playBtn mas_makeConstraints:^(MASConstraintMaker *make) { - make.right.mas_equalTo(-27); - make.width.mas_equalTo(91); - make.height.mas_equalTo(35); - make.top.equalTo(self.whiteBgView).offset(10); + make.right.equalTo(self.guildBgImageView.mas_left).offset(-6); + make.width.mas_equalTo(59); + make.height.mas_equalTo(24); + make.centerY.equalTo(self.guildBgImageView).offset(-2); }]; - self.followBtn = [[UIButton alloc] initWithFrame:CGRectMake(self.playBtn.left-6-91, self.whiteBgView.top+10, 91, 35)]; - [self.followBtn setTitle:QXText(@"关注") forState:(UIControlStateNormal)]; - [self.followBtn setTitle:QXText(@"已关注") forState:(UIControlStateSelected)]; - [self.followBtn setTitleColor:QXConfig.btnTextColor forState:(UIControlStateNormal)]; - [self.followBtn setTitleColor:RGB16(0x999999) forState:(UIControlStateSelected)]; - [self.followBtn setBackgroundImage:[UIImage imageWithColor:QXConfig.themeColor] forState:UIControlStateNormal]; - [self.followBtn setBackgroundImage:[UIImage imageWithColor:RGB16(0xF1F2F3)] forState:UIControlStateSelected]; - self.followBtn.titleLabel.font = [UIFont systemFontOfSize:14]; - [self.followBtn addRoundedCornersWithRadius:17.5]; - self.followBtn.hidden = YES; - [self.followBtn addTarget:self action:@selector(followAction) forControlEvents:(UIControlEventTouchUpInside)]; - [self addSubview:self.followBtn]; - [self.followBtn mas_makeConstraints:^(MASConstraintMaker *make) { - make.right.equalTo(self.playBtn.mas_left).offset(-6); - make.width.mas_equalTo(91); - make.height.mas_equalTo(35); - make.centerY.equalTo(self.playBtn); - }]; + // self.nameLabel.text = @"张三"; // self.idLabel.text = @"313213213"; // self.ageLabel.text = @"36岁"; // self.introduceLabel.text = @"个人简介个人简介个人简介个人简个人简介"; [self.inCollectionView reloadData]; + + self.cpDressView = [[QXUserCpDressView alloc] initWithFrame:CGRectMake(self.width-15-ScaleWidth(120), 0, ScaleWidth(120), ScaleWidth(194))]; + self.cpDressView.hidden = YES; + [self.whiteBgView addSubview:self.cpDressView]; + + self.cpCardView = [[QXUserCpCardView alloc] init]; + self.cpCardView.hidden = YES; + MJWeakSelf + [self.cpCardView addTapBlock:^(id _Nonnull obj) { + QXHeartBeatSpaceViewController*vc = [[QXHeartBeatSpaceViewController alloc] init]; + vc.userId = weakSelf.userId; + [weakSelf.viewController.navigationController pushViewController:vc animated:YES]; + }]; + [self addSubview:self.cpCardView]; + [self.cpCardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(17); + make.right.mas_equalTo(-17); + make.top.equalTo(self.whiteBgView.mas_bottom).offset(14); + make.height.mas_equalTo(ScaleWidth(100)); + }]; + + self.giftWallBtn = [[UIButton alloc] init]; + [self.giftWallBtn addTarget:self action:@selector(giftWallAction) forControlEvents:(UIControlEventTouchUpInside)]; + [self.giftWallBtn setBackgroundImage:[UIImage imageNamed:@"user_home_gift_wall"] forState:(UIControlStateNormal)]; + [self addSubview:self.giftWallBtn]; + [self.giftWallBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(17); + make.right.mas_equalTo(-17); + make.height.mas_equalTo(ScaleWidth(40)); + make.top.equalTo(self.cpCardView.mas_bottom).offset(8); + }]; +} + +-(void)giftWallAction{ + QXGiftWallViewController *vc = [[QXGiftWallViewController alloc] init]; + vc.userId = self.userId; + [self.viewController.navigationController pushViewController:vc animated:YES]; } -(void)followAction{ @@ -270,16 +337,60 @@ } -(void)setModel:(QXUserHomeModel *)model{ _model = model; +// model.nickname = @"大家好撒客户端撒大厦尽快"; +// self.tempName.text = model.nickname; [self.headerView setHeadIcon:model.avatar dress:model.dress]; [self.headerView.nobilityImageView sd_setImageWithURL:[NSURL URLWithString:model.nobility_image]]; - self.nameLabel.text = model.nickname; + + if ([model.nickname_color isExist]) { - self.nameLabel.textColor = [UIColor colorWithHexString:model.nickname_color]; + self.nameLabel.shimmerColor = [UIColor colorWithHexString:model.nickname_color]; + [self.nameLabel startShimmer]; +// self.tempName.shimmerColor = UIColor.redColor; +// [self.tempName startShimmer]; }else{ - self.nameLabel.textColor = QXConfig.textColor; + [self.nameLabel stopShimmer]; } - self.idLabel.text = [NSString stringWithFormat:@"ID:%@",model.user_code]; - self.ageLabel.text = [NSString stringWithFormat:@"%@|%ld岁",model.sex.intValue==1?QXText(@"男"):QXText(@"女"),[model.birthday ageWithDateOfBirth]]; + self.nameLabel.text = model.nickname; + [self.nameLabel.contentLabel sizeToFit]; + [self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.headerView); + make.height.mas_equalTo(24); + make.top.equalTo(self.headerView.mas_bottom).offset(4); + make.width.mas_equalTo(self.nameLabel.contentLabel.width); + }]; + if (model.cp_info != nil) { + self.cpDressView.hidden = NO; + self.cpCardView.hidden = NO; + self.cpDressView.model = model.cp_info; + self.cpCardView.model = model.cp_info; + [self.giftWallBtn mas_remakeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(17); + make.right.mas_equalTo(-17); + make.height.mas_equalTo(ScaleWidth(40)); + make.top.equalTo(self.cpCardView.mas_bottom).offset(8); + }]; + }else{ + self.cpDressView.hidden = YES; + self.cpCardView.hidden = YES; + [self.giftWallBtn mas_remakeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(17); + make.right.mas_equalTo(-17); + make.height.mas_equalTo(ScaleWidth(40)); + make.top.equalTo(self.whiteBgView.mas_bottom).offset(8); + }]; + } +// self.tempName.text = model.nickname; +// [self.tempName.contentLabel sizeToFit]; +// [self.tempName mas_remakeConstraints:^(MASConstraintMaker *make) { +// make.top.left.mas_equalTo(0); +// make.height.mas_equalTo(24); +// make.width.mas_equalTo(self.tempName.contentLabel.width); +// }]; + +// self.tempName.text = model.nickname; +// self.idLabel.text = [NSString stringWithFormat:@"ID:%@",model.user_code]; + self.idLabel.text = [NSString stringWithFormat:@"%@|%ld岁 ID:%@",model.sex.intValue==1?QXText(@"男"):QXText(@"女"),[model.birthday ageWithDateOfBirth],model.user_code]; self.introduceLabel.text = model.profile; [self.inCollectionView reloadData]; [self.collectionView reloadData]; @@ -299,17 +410,17 @@ } } if ([model.guild isExist]) { - self.guildLabel.text = [NSString stringWithFormat:@"所属公会:%@",model.guild]; + self.guildLabel.text = model.guild; }else{ - self.guildLabel.text = [NSString stringWithFormat:@"所属公会:%@",@"无"]; + self.guildLabel.text = @"无"; } if (model.is_use_code.intValue == 1) { self.useCodeImageView.hidden = NO; }else{ self.useCodeImageView.hidden = YES; } - UIImage *sexImage = [UIImage imageNamed:model.sex.intValue==1?@"user_sex_boy":@"user_sex_girl"]; - self.sexImageView.image = sexImage; +// UIImage *sexImage = [UIImage imageNamed:model.sex.intValue==1?@"user_sex_boy":@"user_sex_girl"]; +// self.sexImageView.image = sexImage; } -(NSMutableArray *)tagArray{ diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateContentView.h b/QXLive/Mine(音域)/View/亲密关系/QXIntimateContentView.h new file mode 100644 index 0000000..ba79256 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateContentView.h @@ -0,0 +1,18 @@ +// +// QXIntimateContentView.h +// QXLive +// +// Created by 启星 on 2025/11/21. +// + +#import +#import "JXPagerView.h" +NS_ASSUME_NONNULL_BEGIN + +@interface QXIntimateContentView : UIView +@property (nonatomic,strong)NSString *userId; +@property (nonatomic, copy) void(^listScrollCallback)(UIScrollView *scrollView); +@property (nonatomic,assign)BOOL isTopFloating; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateContentView.m b/QXLive/Mine(音域)/View/亲密关系/QXIntimateContentView.m new file mode 100644 index 0000000..4313f01 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateContentView.m @@ -0,0 +1,311 @@ +// +// QXIntimateContentView.m +// QXLive +// +// Created by 启星 on 2025/11/21. +// + +#import "QXIntimateContentView.h" +#import "QXRoomBestFriendModel.h" +#import "QXMineNetwork.h" +#import "QXMoreIntimateViewController.h" +#import "QXButton.h" +#import "QXIntimateCpCell.h" +#import "QXIntimateNoCpCell.h" +#import "QXIntimateListCell.h" +#import "QXIntimateMoreListCell.h" +#import "QXUserCpCardView.h" + +@interface QXIntimateContentView() +@property (nonatomic,strong)UIView *tableHeaderView; +@property (nonatomic,strong)UIImageView *topImageView; +@property (nonatomic,strong)QXUserCpCardView *cpCardView; +@property (nonatomic,strong)UIView *noCpView; +@property (nonatomic,strong)UITableView *tableView; +@property (nonatomic,assign)NSInteger page; +@property (nonatomic,strong)NSMutableArray *dataArray; +@property (nonatomic,strong)QXRoomBestFriendModel *model; +@property (nonatomic, copy) void(^scrollCallback)(UIScrollView *scrollView); +@end + +@implementation QXIntimateContentView + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self initSubviews]; + } + return self; +} +-(void)initSubviews{ + self.backgroundColor = RGB16(0xF5E8FF); + + self.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.width, ScaleWidth(188))]; + self.topImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mine_intimate_top_bg"]]; + self.topImageView.frame = CGRectMake(0, 0, self.width, ScaleWidth(241)); + [self.tableHeaderView addSubview:self.topImageView]; + [self.topImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.top.right.equalTo(self.tableHeaderView); + make.height.mas_equalTo(ScaleWidth(241)); + }]; + + UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mine_intimate_title_bg"]]; + UILabel *titleLabel = [[UILabel alloc] init]; + titleLabel.font = [UIFont boldSystemFontOfSize:16]; + titleLabel.textColor = RGB16(0xffffff); + titleLabel.text = @"心动"; + [self.tableHeaderView addSubview:imageView]; + [self.tableHeaderView addSubview:titleLabel]; + [imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(132); + make.height.mas_equalTo(36); + make.centerX.equalTo(self.tableHeaderView); + make.top.mas_equalTo(ScaleWidth(152)); + }]; + [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(imageView); + make.centerY.equalTo(imageView).offset(2); + }]; + self.cpCardView = [[QXUserCpCardView alloc] init]; + self.cpCardView.hidden = YES; + [self.tableHeaderView addSubview:self.cpCardView]; + [self.cpCardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(imageView.mas_bottom).offset(16); + make.height.mas_equalTo(ScaleWidth(100)); + make.left.mas_equalTo(24); + make.right.mas_equalTo(-24); + }]; + + self.noCpView = [[UIView alloc] init]; + self.noCpView.hidden = YES; + [self.tableHeaderView addSubview:self.noCpView]; + [self.noCpView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(24); + make.right.mas_equalTo(-24); + make.height.mas_equalTo(36); + make.top.equalTo(imageView.mas_bottom).offset(16); + }]; + UIImageView *noCpImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mine_intimate_no_cp_bg"]]; + [self.noCpView addSubview:noCpImageView]; + [noCpImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.noCpView); + }]; + + UILabel *noCpLabel = [[UILabel alloc] init]; + noCpLabel.textAlignment = NSTextAlignmentCenter; + noCpLabel.font = [UIFont systemFontOfSize:12]; + noCpLabel.text = @"暂无关系,前往房间互送特殊礼物达成关系吧"; + noCpLabel.textColor = RGB16(0x624E79); + [self.noCpView addSubview:noCpLabel]; + [noCpLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.noCpView); + }]; + self.tableView.tableHeaderView = self.tableHeaderView; + [self addSubview:self.tableView]; +} +-(void)layoutSubviews{ + [super layoutSubviews]; + self.tableView.frame = CGRectMake(0, 0, self.width, self.height); +} +-(void)setIsTopFloating:(BOOL)isTopFloating{ + _isTopFloating = isTopFloating; + if (isTopFloating) { + [self addSubview:self.topImageView]; + }else{ + self.tableView.tableHeaderView = self.topImageView; + } +} + +-(void)setUserId:(NSString *)userId{ + _userId = userId; + self.page = 1; + [self getList]; +} +-(void)getList{ + MJWeakSelf + [QXMineNetwork userBestFriendsListWithUserId:self.userId page:self.page successBlock:^(QXRoomBestFriendModel * _Nonnull model) { + weakSelf.model = model; + if (model.cp == nil) { + self.noCpView.hidden = NO; + self.cpCardView.hidden = YES; + self.tableHeaderView.width = SCREEN_WIDTH; + self.tableHeaderView.height = ScaleWidth(188)+16+ScaleWidth(36); + }else{ + self.noCpView.hidden = YES; + self.cpCardView.hidden = NO; + self.tableHeaderView.width = SCREEN_WIDTH; + self.tableHeaderView.height = ScaleWidth(188)+16+ScaleWidth(100); + self.cpCardView.model = model.cp; + } + if (weakSelf.page == 1) { + [weakSelf.dataArray removeAllObjects]; + } + [weakSelf.dataArray addObjectsFromArray:model.no_cp]; + [weakSelf.tableView reloadData]; + if (model.no_cp.count == 0) { + weakSelf.tableView.mj_footer.state = MJRefreshStateNoMoreData; + }else{ + [weakSelf.tableView.mj_footer endRefreshing]; + } + [weakSelf.tableView.mj_header endRefreshing]; + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + + }]; +} + +-(void)moreAction:(QXButton*)btn{ + QXRoomBestFriendListModel *md = btn.object; + QXMoreIntimateViewController *vc = [[QXMoreIntimateViewController alloc] init]; + vc.userId = self.userId; + vc.relation_id = md.relation_list.firstObject.relation_id; + [self.viewController.navigationController pushViewController:vc animated:YES]; +} + +-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ + return self.dataArray.count; +} + +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ + return 1; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ + QXRoomBestFriendListModel *md = self.dataArray[indexPath.section]; + if (md.relation_list.count > 1) { + QXIntimateListCell*cell = [QXIntimateListCell cellWithTableView:tableView]; + QXRoomBestFriendListModel *md = self.dataArray[indexPath.section]; + cell.model = md; + return cell; + }else{ + MJWeakSelf + QXIntimateMoreListCell *cell = [QXIntimateMoreListCell cellWithTableView:tableView]; + cell.model = md.relation_list.firstObject; + cell.deleteSuccessBlock = ^(QXRelationshipListModel * _Nonnull model) { + weakSelf.page = 1; + [weakSelf getList]; + }; + return cell; + } + +} + +-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ + UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.width, 50)]; + UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mine_intimate_title_bg"]]; + UILabel *titleLabel = [[UILabel alloc] init]; + titleLabel.font = [UIFont boldSystemFontOfSize:16]; + titleLabel.textColor = RGB16(0xffffff); + QXButton *btn = [[QXButton alloc] init]; + [btn setTitle:@"更多>>" forState:(UIControlStateNormal)]; + [btn setTitleColor:RGB16(0xE973FC) forState:(UIControlStateNormal)]; + btn.titleLabel.font = [UIFont systemFontOfSize:12]; + [btn addTarget:self action:@selector(moreAction:) forControlEvents:(UIControlEventTouchUpInside)]; + [header addSubview:btn]; + [header addSubview:imageView]; + [header addSubview:titleLabel]; + [imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(132); + make.height.mas_equalTo(36); + make.centerX.centerY.equalTo(header); + }]; + [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(header); + make.centerY.equalTo(header).offset(2); + }]; + [btn mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.mas_equalTo(-23); + make.top.bottom.equalTo(header); + make.width.mas_equalTo(40); + }]; + + QXRoomBestFriendListModel *md = self.dataArray[section]; + titleLabel.text = md.relation_name; + if (md.relation_list.count>1) { + btn.hidden = NO; + btn.object = md; + }else{ + btn.hidden = YES; + } + return header; +} +-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ + return 50; +} + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ + QXRoomBestFriendListModel *md = self.dataArray[indexPath.section]; + if (md.relation_list.count > 1) { + return ScaleWidth(92)+18; + }else{ + if (md.relation_list.count == 0) { + return 0; + }else{ + return ScaleWidth(125); + } + } + +} + +-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{ + UIView *footer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.width, 15)]; + return footer; +} + +-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ + return 15; +} + +-(UITableView *)tableView{ + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.width, self.height) style:(UITableViewStyleGrouped)]; + _tableView.dataSource = self; + _tableView.delegate = self; + _tableView.backgroundColor = [UIColor clearColor]; + _tableView.tableFooterView = [UIView new]; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + if (@available(iOS 15.0, *)) { + _tableView.sectionHeaderTopPadding = 0; + } else { + // Fallback on earlier versions + } + MJWeakSelf + _tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + weakSelf.page = 1; + [weakSelf getList]; + }]; + _tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{ + weakSelf.page++; + [weakSelf getList]; + }]; + } + return _tableView; +} +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (self.scrollCallback != nil) { + self.scrollCallback(scrollView); + } + if (self.listScrollCallback != nil) { + self.listScrollCallback(scrollView); + } +} +#pragma mark - JXPagingViewListViewDelegate + +- (UIScrollView *)listScrollView { + return self.tableView; +} + +- (void)listViewDidScrollCallback:(void (^)(UIScrollView *))callback { + self.scrollCallback = callback; +} + +- (UIView *)listView { + return self; +} +-(NSMutableArray *)dataArray{ + if (!_dataArray) { + _dataArray = [NSMutableArray array]; + } + return _dataArray; +} +@end diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateCpCell.h b/QXLive/Mine(音域)/View/亲密关系/QXIntimateCpCell.h new file mode 100644 index 0000000..17136e9 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateCpCell.h @@ -0,0 +1,17 @@ +// +// QXIntimateCpCell.h +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface QXIntimateCpCell : UITableViewCell +@property (nonatomic,strong)QXUserCpInfoModel *model; ++(instancetype)cellWithTableView:(UITableView *)tableView; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateCpCell.m b/QXLive/Mine(音域)/View/亲密关系/QXIntimateCpCell.m new file mode 100644 index 0000000..af66643 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateCpCell.m @@ -0,0 +1,58 @@ +// +// QXIntimateCpCell.m +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXIntimateCpCell.h" +#import "QXUserCpCardView.h" +@interface QXIntimateCpCell() +@property (nonatomic,strong)QXUserCpCardView *cardView; +@end +@implementation QXIntimateCpCell ++(instancetype)cellWithTableView:(UITableView *)tableView{ + static NSString *cellId = @"QXIntimateCpCell"; + QXIntimateCpCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; + if (!cell) { + cell = [[QXIntimateCpCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:cellId]; + cell.backgroundColor = [UIColor clearColor]; + } + return cell; +} + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.backgroundColor = [UIColor clearColor]; + self.contentView.backgroundColor = [UIColor clearColor]; + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self initSubviews]; + } + return self; +} +-(void)setModel:(QXUserCpInfoModel *)model{ + _model = model; + self.cardView.model = model; +} + +-(void)initSubviews{ + self.cardView = [[QXUserCpCardView alloc] init]; + [self.contentView addSubview:self.cardView]; + [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(24); + make.right.mas_equalTo(-24); + make.top.bottom.equalTo(self.contentView); + }]; +} +- (void)awakeFromNib { + [super awakeFromNib]; + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateListCell.h b/QXLive/Mine(音域)/View/亲密关系/QXIntimateListCell.h new file mode 100644 index 0000000..2a6f2c3 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateListCell.h @@ -0,0 +1,17 @@ +// +// QXIntimateListCell.h +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import +#import "QXRoomBestFriendModel.h" +NS_ASSUME_NONNULL_BEGIN + +@interface QXIntimateListCell : UITableViewCell +@property (nonatomic,strong)QXRoomBestFriendListModel *model; ++(instancetype)cellWithTableView:(UITableView *)tableView; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateListCell.m b/QXLive/Mine(音域)/View/亲密关系/QXIntimateListCell.m new file mode 100644 index 0000000..2b25cf6 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateListCell.m @@ -0,0 +1,85 @@ +// +// QXIntimateListCell.m +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXIntimateListCell.h" +#import "QXIntimateUserCell.h" + +@interface QXIntimateListCell() +@property (nonatomic,strong)UICollectionView *collectionView; +@end + +@implementation QXIntimateListCell ++(instancetype)cellWithTableView:(UITableView *)tableView{ + static NSString *cellId = @"QXIntimateListCell"; + QXIntimateListCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; + if (!cell) { + cell = [[QXIntimateListCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:cellId]; + cell.backgroundColor = [UIColor clearColor]; + } + return cell; +} + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.backgroundColor = [UIColor clearColor]; + self.contentView.backgroundColor = [UIColor clearColor]; + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self initSubviews]; + } + return self; +} + + +-(void)initSubviews{ + NSInteger maxCount = 3; + NSInteger margin = 14; + CGFloat btnWith = (int)(SCREEN_WIDTH-48-14*2-1)/maxCount; + CGFloat btnHeight = ScaleWidth(125); + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.itemSize = CGSizeMake(btnWith, btnHeight); + layout.minimumLineSpacing = 0; + layout.minimumInteritemSpacing = 14; + layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); + layout.scrollDirection = UICollectionViewScrollDirectionVertical; + self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + [self.collectionView registerNib:[UINib nibWithNibName:@"QXIntimateUserCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:@"QXIntimateUserCell"]; + self.collectionView.delegate = self; + self.collectionView.dataSource = self; + self.collectionView.showsHorizontalScrollIndicator = NO; + self.collectionView.bounces = NO; + self.collectionView.backgroundColor = UIColor.clearColor; + [self.contentView addSubview:self.collectionView]; + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.bottom.equalTo(self.contentView); + make.left.mas_equalTo(24); + make.right.mas_equalTo(-24); + }]; +} +-(void)setModel:(QXRoomBestFriendListModel *)model{ + _model = model; + [self.collectionView reloadData]; +} +-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ + return self.model.relation_list.count; +} +-(__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ + QXIntimateUserCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"QXIntimateUserCell" forIndexPath:indexPath]; + cell.model = self.model.relation_list[indexPath.row]; + return cell; +} +- (void)awakeFromNib { + [super awakeFromNib]; + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateMoreListCell.h b/QXLive/Mine(音域)/View/亲密关系/QXIntimateMoreListCell.h new file mode 100644 index 0000000..bfd71ef --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateMoreListCell.h @@ -0,0 +1,26 @@ +// +// QXIntimateMoreListCell.h +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface QXIntimateMoreListCell : UITableViewCell +@property (weak, nonatomic) IBOutlet QXSeatHeaderView *leftHeaderView; +@property (weak, nonatomic) IBOutlet UIImageView *leftSexImageView; +@property (weak, nonatomic) IBOutlet QXSeatHeaderView *rightHeaderView; +@property (weak, nonatomic) IBOutlet UIImageView *rightSexImageView; +@property (weak, nonatomic) IBOutlet UILabel *leftNameLabel; +@property (weak, nonatomic) IBOutlet UILabel *rightNameLabel; +@property (weak, nonatomic) IBOutlet UILabel *timeLabel; +@property (nonatomic,strong)QXRelationshipListModel *model; +@property (nonatomic,copy)void(^topSuccessBlock)(QXRelationshipListModel*model); +@property (nonatomic,copy)void(^deleteSuccessBlock)(QXRelationshipListModel*model); ++(instancetype)cellWithTableView:(UITableView *)tableView; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateMoreListCell.m b/QXLive/Mine(音域)/View/亲密关系/QXIntimateMoreListCell.m new file mode 100644 index 0000000..b5a9c10 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateMoreListCell.m @@ -0,0 +1,106 @@ +// +// QXIntimateMoreListCell.m +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXIntimateMoreListCell.h" +#import "QXMineNetwork.h" +#import "QXCustomAlertView.h" +@interface QXIntimateMoreListCell() +@property (nonatomic,strong)QXCustomAlertView *alertView; +@end +@implementation QXIntimateMoreListCell ++(instancetype)cellWithTableView:(UITableView *)tableView{ + static NSString *cellId = @"QXIntimateMoreListCell"; + QXIntimateMoreListCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; + if (!cell) { + cell = [[NSBundle mainBundle] loadNibNamed:cellId owner:nil options:nil].lastObject; + cell.backgroundColor = [UIColor clearColor]; + cell.contentView.backgroundColor = [UIColor clearColor]; + [cell.leftHeaderView addRoundedCornersWithRadius:25]; + cell.leftHeaderView.layer.borderWidth = 2; + cell.leftHeaderView.layer.borderColor = RGB16(0xffffff).CGColor; + [cell.timeLabel addRoundedCornersWithRadius:9]; + } + return cell; +} +- (IBAction)deleteAction:(id)sender { + MJWeakSelf + QXCustomAlertView *alertView = [[QXCustomAlertView alloc] init]; + alertView.commitBlock = ^{ + [weakSelf deleteRelation]; + }; + [alertView showInView:self.viewController.view title:@"您确定要解除本关系吗" message:[NSString stringWithFormat:@"解除关系需要%@金币",self.model.delete_me_coin] cancleTitle:@"取消" commitTitle:@"确定"]; +} +- (IBAction)topAction:(id)sender { + MJWeakSelf + QXCustomAlertView *alertView = [[QXCustomAlertView alloc] init]; + alertView.commitBlock = ^{ + [weakSelf topRelation]; + }; + [alertView showInView:self.viewController.view title:@"您确定要置顶本关系吗" message:@"" cancleTitle:@"取消" commitTitle:@"确定"]; +} + + +-(void)deleteRelation{ + MJWeakSelf + [QXMineNetwork deleteRelationWithId:self.model.id successBlock:^(NSDictionary * _Nonnull dict) { + showToast(@"解除成功"); + if (weakSelf.deleteSuccessBlock) { + weakSelf.deleteSuccessBlock(weakSelf.model); + } + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + showToast(msg); + }]; +} +-(void)topRelation{ + MJWeakSelf + [QXMineNetwork topRelationWithId:self.model.id successBlock:^(NSDictionary * _Nonnull dict) { + showToast(@"置顶成功"); + if (weakSelf.topSuccessBlock) { + weakSelf.topSuccessBlock(weakSelf.model); + } + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + showToast(msg); + }]; +} + + + + +-(void)setModel:(QXRelationshipListModel *)model{ + _model = model; + if ([model.user_id1 isEqualToString:QXGlobal.shareGlobal.loginModel.user_id]) { + [self.leftHeaderView setHeadIcon:model.avatar2 dress:@""]; + self.leftNameLabel.text = model.nickname2; + self.leftSexImageView.image = [UIImage imageNamed:model.sex2.intValue == 1?@"user_sex_boy":@"user_sex_girl"]; + [self.rightHeaderView setHeadIcon:model.avatar1 dress:@""]; + self.rightNameLabel.text = model.nickname1; + self.rightSexImageView.image = [UIImage imageNamed:model.sex1.intValue == 1?@"user_sex_boy":@"user_sex_girl"]; + }else{ + [self.leftHeaderView setHeadIcon:model.avatar1 dress:@""]; + self.leftNameLabel.text = model.nickname1; + self.leftSexImageView.image = [UIImage imageNamed:model.sex1.intValue == 1?@"user_sex_boy":@"user_sex_girl"]; + [self.rightHeaderView setHeadIcon:model.avatar2 dress:@""]; + self.rightNameLabel.text = model.nickname2; + self.rightSexImageView.image = [UIImage imageNamed:model.sex2.intValue == 1?@"user_sex_boy":@"user_sex_girl"]; + } + NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970]; + long long milliseconds = (long long)(currentTime); + NSInteger time = model.end_time.longLongValue - milliseconds; + self.timeLabel.text = [NSString stringWithFormat:@" %@ ",[NSString getTimeWithSecond:time]]; +} +- (void)awakeFromNib { + [super awakeFromNib]; + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateMoreListCell.xib b/QXLive/Mine(音域)/View/亲密关系/QXIntimateMoreListCell.xib new file mode 100644 index 0000000..0f6f27d --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateMoreListCell.xib @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateNoCpCell.h b/QXLive/Mine(音域)/View/亲密关系/QXIntimateNoCpCell.h new file mode 100644 index 0000000..d3b8239 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateNoCpCell.h @@ -0,0 +1,16 @@ +// +// QXIntimateNoCpCell.h +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface QXIntimateNoCpCell : UITableViewCell ++(instancetype)cellWithTableView:(UITableView *)tableView; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateNoCpCell.m b/QXLive/Mine(音域)/View/亲密关系/QXIntimateNoCpCell.m new file mode 100644 index 0000000..a09f254 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateNoCpCell.m @@ -0,0 +1,32 @@ +// +// QXIntimateNoCpCell.m +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXIntimateNoCpCell.h" + +@implementation QXIntimateNoCpCell ++(instancetype)cellWithTableView:(UITableView *)tableView{ + static NSString *cellId = @"QXIntimateNoCpCell"; + QXIntimateNoCpCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; + if (!cell) { + cell = [[NSBundle mainBundle] loadNibNamed:cellId owner:nil options:nil].lastObject; + cell.backgroundColor = [UIColor clearColor]; + cell.contentView.backgroundColor = [UIColor clearColor]; + } + return cell; +} +- (void)awakeFromNib { + [super awakeFromNib]; + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateNoCpCell.xib b/QXLive/Mine(音域)/View/亲密关系/QXIntimateNoCpCell.xib new file mode 100644 index 0000000..8a54b83 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateNoCpCell.xib @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateUserCell.h b/QXLive/Mine(音域)/View/亲密关系/QXIntimateUserCell.h new file mode 100644 index 0000000..5990164 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateUserCell.h @@ -0,0 +1,20 @@ +// +// QXIntimateUserCell.h +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import +#import "QXRoomFriendRelationModel.h" +NS_ASSUME_NONNULL_BEGIN + +@interface QXIntimateUserCell : UICollectionViewCell +@property (weak, nonatomic) IBOutlet UILabel *timeLabel; +@property (weak, nonatomic) IBOutlet UILabel *nameLabel; +@property (weak, nonatomic) IBOutlet QXSeatHeaderView *headerView; +@property (weak, nonatomic) IBOutlet UIImageView *sexImageView; +@property (nonatomic,strong)QXRelationshipListModel *model; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateUserCell.m b/QXLive/Mine(音域)/View/亲密关系/QXIntimateUserCell.m new file mode 100644 index 0000000..fd95db2 --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateUserCell.m @@ -0,0 +1,32 @@ +// +// QXIntimateUserCell.m +// QXLive +// +// Created by 启星 on 2025/11/20. +// + +#import "QXIntimateUserCell.h" + +@implementation QXIntimateUserCell +-(void)setModel:(QXRelationshipListModel *)model{ + _model = model; + if ([model.user_id1 isEqualToString:QXGlobal.shareGlobal.loginModel.user_id]) { + [self.headerView setHeadIcon:model.avatar2 dress:@""]; + self.nameLabel.text = model.nickname2; + self.sexImageView.image = [UIImage imageNamed:model.sex2.intValue == 1?@"user_sex_boy":@"user_sex_girl"]; + }else{ + [self.headerView setHeadIcon:model.avatar1 dress:@""]; + self.nameLabel.text = model.nickname1; + self.sexImageView.image = [UIImage imageNamed:model.sex1.intValue == 1?@"user_sex_boy":@"user_sex_girl"]; + } + self.timeLabel.text = [NSString getTimeWithSecond:model.end_time.longLongValue]; + +} +- (void)awakeFromNib { + [super awakeFromNib]; + // Initialization code + self.backgroundColor = [UIColor clearColor]; + self.contentView.backgroundColor = [UIColor clearColor]; +} + +@end diff --git a/QXLive/Mine(音域)/View/亲密关系/QXIntimateUserCell.xib b/QXLive/Mine(音域)/View/亲密关系/QXIntimateUserCell.xib new file mode 100644 index 0000000..d1e2f4b --- /dev/null +++ b/QXLive/Mine(音域)/View/亲密关系/QXIntimateUserCell.xib @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongGiftView.h b/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongGiftView.h new file mode 100644 index 0000000..ab112f5 --- /dev/null +++ b/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongGiftView.h @@ -0,0 +1,25 @@ +// +// QXMineAddSongGiftView.h +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@protocol QXMineAddSongGiftViewDelegate + +@optional +-(void)didSeletedGift:(QXGiftModel*)giftModel giftCount:(NSString*)giftCount; + +@end +@interface QXMineAddSongGiftView : UIView + +@property (nonatomic,weak)iddelegate; +-(void)showInView:(UIView *)view; + +-(void)hide; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongGiftView.m b/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongGiftView.m new file mode 100644 index 0000000..6eea7aa --- /dev/null +++ b/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongGiftView.m @@ -0,0 +1,200 @@ +// +// QXMineAddSongGiftView.m +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import "QXMineAddSongGiftView.h" +#import "QXGiftCell.h" +#import "QXMineNetwork.h" +#import "QXMenuPopView.h" + +@interface QXMineAddSongGiftView() +@property (nonatomic,strong)UIView *bgView; +@property (nonatomic,strong)UIImageView *bgImageView; +@property (nonatomic,strong)UICollectionView *collectionView; +@property (nonatomic,strong)NSMutableArray *dataArray; +@property (nonatomic,assign)NSInteger selectedIndex; +@property (nonatomic,strong)QXGiftModel *model; + +@property (nonatomic,strong)UIView *sendBgView; +@property (nonatomic,strong)UIButton *countBtn; +@property (nonatomic,strong)UIButton *sendBtn; +@property (nonatomic,strong)UIButton *sendAllBtn; +@property (nonatomic,strong)NSString* giftCount; +@end +@implementation QXMineAddSongGiftView +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self initSubviews]; + } + return self; +} +-(void)initSubviews{ + self.giftCount = @"1"; + self.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.3]; + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)]; + tap.delegate = self; + [self addGestureRecognizer:tap]; + + self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, ScaleWidth(429)+kSafeAreaBottom)]; + [self.bgView addRoundedCornersWithRadius:16 byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)]; + [self addSubview:self.bgView]; + + self.bgImageView = [[UIImageView alloc] initWithFrame:self.bounds]; + self.bgImageView.image = [UIImage imageNamed:@"room_sound_bg"]; + [self.bgView addSubview:self.bgImageView]; + + self.selectedIndex = -1; + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.itemSize = CGSizeMake((SCREEN_WIDTH-16*2-12*3)/4, ScaleWidth(119)); + layout.minimumLineSpacing = 12; + layout.minimumInteritemSpacing = 12; + layout.sectionInset = UIEdgeInsetsMake(0, 16, 0, 16); + layout.scrollDirection = UICollectionViewScrollDirectionVertical; + self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 16, self.width, self.bgView.height-12) collectionViewLayout:layout]; + [self.collectionView registerNib:[UINib nibWithNibName:@"QXGiftCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:@"QXGiftCell"]; + self.collectionView.delegate = self; + self.collectionView.dataSource = self; + self.collectionView.showsHorizontalScrollIndicator = NO; + self.collectionView.bounces = NO; + self.collectionView.backgroundColor = [UIColor clearColor]; + [self.bgView addSubview:self.collectionView]; + + + self.sendBgView = [[UIView alloc] init]; + [self.sendBgView addRoundedCornersWithRadius:17.5]; + self.sendBgView.layer.borderColor = QXConfig.themeColor.CGColor; + self.sendBgView.layer.borderWidth = 1; + [self.bgView addSubview:self.sendBgView]; + [self.sendBgView mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.mas_equalTo(-16); + make.width.mas_equalTo(120); + make.height.mas_equalTo(35); + make.bottom.mas_equalTo(-kSafeAreaBottom-12); + }]; + + + self.countBtn = [[UIButton alloc] init]; + [self.countBtn setTitle:@"X1" forState:(UIControlStateNormal)]; + [self.countBtn setTitleColor:RGB16(0xffffff) forState:(UIControlStateNormal)]; + self.countBtn.titleLabel.font = [UIFont systemFontOfSize:12]; + [self.countBtn addTarget:self action:@selector(selectedCount:) forControlEvents:(UIControlEventTouchUpInside)]; + [self.sendBgView addSubview:self.countBtn]; + [self.countBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.top.bottom.equalTo(self.sendBgView); + make.width.equalTo(self.sendBgView.mas_width).multipliedBy(0.5); + }]; + + self.sendBtn = [[UIButton alloc] init]; + [self.sendBtn setTitle:QXText(@"确定") forState:(UIControlStateNormal)]; + [self.sendBtn setTitleColor:QXConfig.btnTextColor forState:(UIControlStateNormal)]; + self.sendBtn.backgroundColor = QXConfig.themeColor; + self.sendBtn.titleLabel.font = [UIFont systemFontOfSize:12]; + [self.sendBtn addTarget:self action:@selector(sendAction) forControlEvents:(UIControlEventTouchUpInside)]; + [self.sendBgView addSubview:self.sendBtn]; + [self.sendBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.top.bottom.equalTo(self.sendBgView); + make.width.equalTo(self.sendBgView.mas_width).multipliedBy(0.5); + }]; + + [self getGiftList]; + +} +-(void)didSelectedIndex:(NSInteger)index menuTitle:(NSString *)menuTitle{ + [self.countBtn setTitle:menuTitle forState:(UIControlStateNormal)]; + NSCharacterSet* nonDigits =[[NSCharacterSet decimalDigitCharacterSet] invertedSet]; + NSInteger count =[[menuTitle stringByTrimmingCharactersInSet:nonDigits] integerValue]; + QXLOG(@"选择了%ld个",count); + self.giftCount = [NSString stringWithFormat:@"%ld",count]; +} +-(void)selectedCount:(UIButton*)sender{ + QXMenuPopView *popView = [[QXMenuPopView alloc] initWithPoint:CGPointMake(SCREEN_WIDTH-16-60-30, SCREEN_HEIGHT-kSafeAreaBottom-50-225) width:88 height:225]; + popView.type = QXMenuPopViewTypeArrowBottom; + popView.dataArray = @[@"X20",@"X15",@"X10",@"X5",@"X1"]; + popView.delegate = self; + [popView showInView:KEYWINDOW]; +} +-(void)sendAction{ + if (self.model == nil) { + showToast(@"请选择礼物"); + return; + } + if (self.delegate && [self.delegate respondsToSelector:@selector(didSeletedGift:giftCount:)]) { + [self.delegate didSeletedGift:self.model giftCount:self.giftCount]; + } + [self hide]; +} + +-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{ + return touch.view == self; +} + +-(void)showInView:(UIView *)view{ + self.bgView.y = SCREEN_HEIGHT; + [view addSubview:self]; + [UIView animateWithDuration:0.3 animations:^{ + self.bgView.y = SCREEN_HEIGHT-ScaleWidth(429)-kSafeAreaBottom; + }]; +} +-(void)hide{ + [UIView animateWithDuration:0.3 animations:^{ + self.bgView.y = SCREEN_HEIGHT; + } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + +-(void)getGiftList{ + MJWeakSelf + [QXMineNetwork giftListWithLabel:@"1" roomId:@"" successBlock:^(NSArray * _Nonnull list) { + [weakSelf.dataArray removeAllObjects]; + [weakSelf.dataArray addObjectsFromArray:list]; + [weakSelf.collectionView reloadData]; + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + + }]; +} + +-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ + return self.dataArray.count; +} + +-(__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ + QXGiftCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"QXGiftCell" forIndexPath:indexPath]; + cell.cellType = QXGiftCellTypeLive; + cell.roomGiftModel = self.dataArray[indexPath.row]; + + + if (self.selectedIndex == indexPath.row) { + cell.selecteBtn.selected = YES; + cell.giftNameLabel.textColor = RGB16(0x333333); + [cell.cornBtn setTitleColor:RGB16(0x333333) forState:(UIControlStateNormal)]; + }else{ + cell.selecteBtn.selected = NO; + cell.giftNameLabel.textColor = RGB16(0xffffff); + [cell.cornBtn setTitleColor:RGB16(0xffffff) forState:(UIControlStateNormal)]; + } + + return cell; +} +-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ + if (indexPath.row == self.selectedIndex) { + return; + } + self.selectedIndex = indexPath.row; + self.model = self.dataArray[indexPath.row]; + [collectionView reloadData]; +} + +-(NSMutableArray *)dataArray{ + if (!_dataArray) { + _dataArray = [NSMutableArray array] ; + } + return _dataArray; +} + +@end diff --git a/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongView.h b/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongView.h new file mode 100644 index 0000000..d9854fe --- /dev/null +++ b/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongView.h @@ -0,0 +1,34 @@ +// +// QXMineAddSongView.h +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import +#import "QXUserSongListModel.h" +NS_ASSUME_NONNULL_BEGIN +@protocol QXMineAddSongViewDelegate + +@optional + +-(void)qx_mineAddSongViewCommitWithSongName:(NSString*)songName giftModel:(QXGiftModel*)giftModel; + +-(void)qx_mineEditSongViewCommitWithSongModel:(QXUserSongListModel*)songModel; + +-(void)qx_mineAddSongViewDidSeleteGift; + +-(void)qx_mineAddSongViewDidRemove; + +@end +@interface QXMineAddSongView : UIView + +@property (nonatomic,strong)QXGiftModel *giftModel; +@property (nonatomic,strong)QXUserSongListModel *songModel; +@property (nonatomic,weak)iddelegate; +-(void)showInView:(UIView *)view; + +-(void)hide; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongView.m b/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongView.m new file mode 100644 index 0000000..707f83a --- /dev/null +++ b/QXLive/Mine(音域)/View/歌单列表/QXMineAddSongView.m @@ -0,0 +1,234 @@ +// +// QXMineAddSongView.m +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import "QXMineAddSongView.h" +@interface QXMineAddSongView() +@property (nonatomic,strong)UIView *bgView; +@property (nonatomic,strong)UILabel *titleLabel; +@property (nonatomic,strong)UIButton *closeBtn; +@property (nonatomic,strong)UIView *songContenView; +@property (nonatomic,strong)UITextField *songTextField; +@property (nonatomic,strong)UIView *giftContenView; +@property (nonatomic,strong)UILabel *giftLabel; +@property (nonatomic,strong)UIImageView *giftArrow; +@property (nonatomic,strong)UIButton *giftBtn; + +@property (nonatomic,strong)UIButton *cancelBtn; +@property (nonatomic,strong)UIButton *commitBtn; +@end +@implementation QXMineAddSongView + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self initSubviews]; + } + return self; +} +-(void)setGiftModel:(QXGiftModel *)giftModel{ + _giftModel = giftModel; + self.giftLabel.text = [NSString stringWithFormat:@"%@x%@",giftModel.gift_name,giftModel.num]; + if (self.songModel) { + self.songModel.gift_num = giftModel.num; + self.songModel.gift_id = giftModel.gift_id; + } +} + +-(void)setSongModel:(QXUserSongListModel *)songModel{ + _songModel = songModel; + self.giftLabel.text = [NSString stringWithFormat:@"%@x%@",songModel.gift_name,songModel.gift_num]; + self.songTextField.text = songModel.song_name; +} + +-(void)initSubviews{ + self.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.3]; + self.bgView = [[UIView alloc] initWithFrame:CGRectMake((SCREEN_WIDTH-ScaleWidth(275))/2, 0, ScaleWidth(275), 300)]; + self.bgView.backgroundColor = RGB16(0xffffff); + [self.bgView addRoundedCornersWithRadius:16]; + [self addSubview:self.bgView]; + + self.titleLabel = [[UILabel alloc] init]; + self.titleLabel.text = @"新增歌单"; + self.titleLabel.font = [UIFont boldSystemFontOfSize:16]; + self.titleLabel.textColor = QXConfig.textColor; + [self.bgView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.bgView); + make.top.equalTo(self.bgView).offset(12); + make.height.mas_equalTo(24); + }]; + + self.closeBtn = [[UIButton alloc] init]; + [self.closeBtn setImage:[UIImage imageNamed:@"wallet_close"] forState:(UIControlStateNormal)]; + [self.closeBtn addTarget:self action:@selector(hide) forControlEvents:(UIControlEventTouchUpInside)]; + [self.bgView addSubview:self.closeBtn]; + [self.closeBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.bgView); + make.height.width.mas_equalTo(40); + make.centerY.equalTo(self.titleLabel); + }]; + + self.songContenView = [[UIView alloc] init]; + [self.songContenView addRoundedCornersWithRadius:11]; + self.songContenView.backgroundColor = RGB16(0xEFF2F8); + [self.bgView addSubview:self.songContenView]; + [self.songContenView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(10); + make.right.mas_equalTo(-10); + make.height.mas_equalTo(41); + make.top.equalTo(self.titleLabel.mas_bottom).offset(36); + }]; + + self.songTextField = [[UITextField alloc] init]; + self.songTextField.font = [UIFont systemFontOfSize:16]; + self.songTextField.textColor = RGB16(0x9B9B9B); + self.songTextField.delegate = self; + self.songTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"请输入歌曲名称" attributes:@{NSForegroundColorAttributeName:RGB16(0x9B9B9B)}]; + [self.songContenView addSubview:self.songTextField]; + [self.songTextField mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(12); + make.right.mas_equalTo(-12); + make.top.bottom.equalTo(self.songContenView); + }]; + + self.giftContenView = [[UIView alloc] init]; + [self.giftContenView addRoundedCornersWithRadius:11]; + self.giftContenView.backgroundColor = RGB16(0xEFF2F8); + [self.bgView addSubview:self.giftContenView]; + [self.giftContenView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(10); + make.right.mas_equalTo(-10); + make.height.mas_equalTo(41); + make.top.equalTo(self.songContenView.mas_bottom).offset(24); + }]; + + + + self.giftArrow = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"arrowRight"] imageByTintColor:RGB16(0x9B9B9B)]]; + [self.giftContenView addSubview:self.giftArrow]; + [self.giftArrow mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.mas_equalTo(-12); + make.width.height.mas_equalTo(24); + make.centerY.equalTo(self.giftContenView); + }]; + + self.giftLabel = [[UILabel alloc] init]; + self.giftLabel.text = @"请选择礼物"; + self.giftLabel.font = [UIFont systemFontOfSize:16]; + self.giftLabel.textColor = RGB16(0x9B9B9B); + [self.giftContenView addSubview:self.giftLabel]; + [self.giftLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(12); + make.right.equalTo(self.giftArrow.mas_left).offset(-12); + make.top.bottom.equalTo(self.giftContenView); + }]; + + self.giftBtn = [[UIButton alloc] init]; + [self.giftBtn addTarget:self action:@selector(giftAction) forControlEvents:(UIControlEventTouchUpInside)]; + [self.giftContenView addSubview:self.giftBtn]; + [self.giftBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.giftContenView); + }]; + + self.cancelBtn = [[UIButton alloc] init]; + [self.bgView addSubview:self.cancelBtn]; + [self.cancelBtn setTitle:@"取消" forState:(UIControlStateNormal)]; + [self.cancelBtn addTarget:self action:@selector(hide) forControlEvents:(UIControlEventTouchUpInside)]; + [self.cancelBtn setTitleColor:RGB16(0x999999) forState:(UIControlStateNormal)]; + self.cancelBtn.titleLabel.font = [UIFont systemFontOfSize:14]; + self.cancelBtn.backgroundColor = RGB16(0xF3F3F3); + [self.cancelBtn addRoundedCornersWithRadius:21]; + [self.cancelBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(19); + make.width.mas_equalTo(110); + make.height.mas_equalTo(42); + make.bottom.mas_equalTo(-20); + }]; + + + self.commitBtn = [[UIButton alloc] init]; + [self.bgView addSubview:self.commitBtn]; + [self.commitBtn setTitle:@"确认" forState:(UIControlStateNormal)]; + [self.commitBtn setTitleColor:RGB16(0xffffff) forState:(UIControlStateNormal)]; + [self.commitBtn addTarget:self action:@selector(commitAction) forControlEvents:(UIControlEventTouchUpInside)]; + self.commitBtn.titleLabel.font = [UIFont systemFontOfSize:14]; + self.commitBtn.backgroundColor = QXConfig.themeColor; + [self.commitBtn addRoundedCornersWithRadius:21]; + [self.commitBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.mas_equalTo(-19); + make.width.mas_equalTo(110); + make.height.mas_equalTo(42); + make.bottom.mas_equalTo(-20); + }]; +} + +-(void)giftAction{ + if (self.delegate && [self.delegate respondsToSelector:@selector(qx_mineAddSongViewDidSeleteGift)]) { + [self.delegate qx_mineAddSongViewDidSeleteGift]; + } +} + +-(void)commitAction{ + if (![self.songTextField.text isExist]) { + showToast(@"请输入歌曲名称"); + return; + } + if (self.songModel == nil) { + if (self.giftModel == nil) { + showToast(@"请选择礼物"); + return; + } + } + if (self.songModel) { + self.songModel.song_name = self.songTextField.text; + if (self.delegate && [self.delegate respondsToSelector:@selector(qx_mineEditSongViewCommitWithSongModel:)]) { + [self.delegate qx_mineEditSongViewCommitWithSongModel:self.songModel]; + } + return; + } + if (self.delegate && [self.delegate respondsToSelector:@selector(qx_mineAddSongViewCommitWithSongName:giftModel:)]) { + [self.delegate qx_mineAddSongViewCommitWithSongName:self.songTextField.text giftModel:self.giftModel]; + } +} + +-(void)textFieldDidBeginEditing:(UITextField *)textField{ + [UIView animateWithDuration:0.3 animations:^{ + self.bgView.top = 100; + }]; +} +-(void)textFieldDidEndEditing:(UITextField *)textField{ + [UIView animateWithDuration:0.3 animations:^{ + self.bgView.y = (SCREEN_HEIGHT-300)/2.0; + }]; +} +-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ + [self endEditing:YES]; +} + +-(void)showInView:(UIView *)view{ + self.bgView.y = -SCREEN_HEIGHT; + [view addSubview:self]; + [UIView animateWithDuration:0.3 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ + self.bgView.y = (SCREEN_HEIGHT-300)/2.0; + } completion:^(BOOL finished) { + + }]; +} + +-(void)hide{ + [UIView animateWithDuration:0.3 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ + self.bgView.y = SCREEN_HEIGHT; + } completion:^(BOOL finished) { + [self removeFromSuperview]; + if (self.delegate && [self.delegate respondsToSelector:@selector(qx_mineAddSongViewDidRemove)]) { + [self.delegate qx_mineAddSongViewDidRemove]; + } + }]; +} + +@end diff --git a/QXLive/Mine(音域)/View/歌单列表/QXMineSongListCell.h b/QXLive/Mine(音域)/View/歌单列表/QXMineSongListCell.h new file mode 100644 index 0000000..809fb38 --- /dev/null +++ b/QXLive/Mine(音域)/View/歌单列表/QXMineSongListCell.h @@ -0,0 +1,21 @@ +// +// QXMineSongListCell.h +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import +#import "QXUserSongListModel.h" +NS_ASSUME_NONNULL_BEGIN + +@interface QXMineSongListCell : UITableViewCell +@property (weak, nonatomic) IBOutlet UILabel *songNameLabel; +@property (weak, nonatomic) IBOutlet UILabel *giftInfoLabel; +@property (weak, nonatomic) IBOutlet UILabel *giftPriceLabel; +@property (nonatomic,strong)QXUserSongListModel *model; +@property (weak, nonatomic) IBOutlet UIImageView *giftImageView; ++(instancetype)cellWithTableView:(UITableView *)tableView; +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/歌单列表/QXMineSongListCell.m b/QXLive/Mine(音域)/View/歌单列表/QXMineSongListCell.m new file mode 100644 index 0000000..96c45b7 --- /dev/null +++ b/QXLive/Mine(音域)/View/歌单列表/QXMineSongListCell.m @@ -0,0 +1,39 @@ +// +// QXMineSongListCell.m +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import "QXMineSongListCell.h" + +@implementation QXMineSongListCell ++(instancetype)cellWithTableView:(UITableView *)tableView{ + static NSString *cellId = @"QXMineSongListCell"; + QXMineSongListCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; + if (!cell) { + cell = [[NSBundle mainBundle] loadNibNamed:cellId owner:nil options:nil].lastObject; + cell.backgroundColor = [UIColor clearColor]; + } + return cell; +} + +-(void)setModel:(QXUserSongListModel *)model{ + _model = model; + [self.giftImageView sd_setImageWithURL:[NSURL URLWithString:model.base_image]]; + self.giftInfoLabel.text = [NSString stringWithFormat:@"x%@%@",model.gift_num,model.gift_name]; + self.songNameLabel.text = model.song_name; + self.giftPriceLabel.text = model.gift_price; +} +- (void)awakeFromNib { + [super awakeFromNib]; + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/QXLive/Mine(音域)/View/歌单列表/QXMineSongListCell.xib b/QXLive/Mine(音域)/View/歌单列表/QXMineSongListCell.xib new file mode 100644 index 0000000..a3ef680 --- /dev/null +++ b/QXLive/Mine(音域)/View/歌单列表/QXMineSongListCell.xib @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.h b/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.h new file mode 100644 index 0000000..9445cf1 --- /dev/null +++ b/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.h @@ -0,0 +1,74 @@ +// +// QXAudioRecorderView.h +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, AudioRecorderState) { + AudioRecorderStateReady, // 准备状态 + AudioRecorderStateRecording, // 录制中 + AudioRecorderStateStopped, // 已停止 + AudioRecorderStatePlaying // 试听中 +}; + +@class QXAudioRecorderView; + +@protocol QXAudioRecorderViewDelegate + +@optional +/// 录音状态改变 +- (void)qxAudioRecorderView:(QXAudioRecorderView *)recorderView didChangeState:(AudioRecorderState)state; + +/// 录音完成 +- (void)qxAudioRecorderView:(QXAudioRecorderView *)recorderView didFinishRecordingWithMP3File:(NSURL *)mp3FileURL duration:(NSTimeInterval)duration; + +/// 录音失败 +- (void)qxAudioRecorderView:(QXAudioRecorderView *)recorderView didFailWithError:(NSError *)error; + +/// 录音进度更新 +- (void)qxAudioRecorderView:(QXAudioRecorderView *)recorderView didUpdateProgress:(NSTimeInterval)progress totalDuration:(NSTimeInterval)totalDuration; + +@end + +@interface QXAudioRecorderView : UIView + +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign, readonly) AudioRecorderState state; +@property (nonatomic, assign, readonly) NSTimeInterval currentDuration; +@property (nonatomic, assign, readonly) NSTimeInterval totalDuration; // 总录制时长(连续录制) +@property (nonatomic, strong, readonly) NSURL *currentAudioFileURL; + +/// 最大录制时长,默认300秒(5分钟) +@property (nonatomic, assign) NSTimeInterval maxDuration; + +/// 是否显示试听按钮,默认YES +@property (nonatomic, assign) BOOL showPlaybackButton; + +/// 初始化 +- (instancetype)initWithFrame:(CGRect)frame maxDuration:(NSTimeInterval)maxDuration; + +/// 开始录制(程序控制) +- (void)startRecording; + +/// 停止录制(程序控制) +- (void)stopRecording; + +/// 试听录音 +- (void)playRecording; + +/// 停止试听 +- (void)stopPlayback; + +/// 重置录音(从0开始) +- (void)resetRecording; + +/// 获取当前录制状态信息 +- (NSString *)getRecordingStatus; + +@end +NS_ASSUME_NONNULL_END diff --git a/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.m b/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.m new file mode 100644 index 0000000..e93340c --- /dev/null +++ b/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.m @@ -0,0 +1,755 @@ +// +// QXAudioRecorderView.m +// QXLive +// +// Created by 启星 on 2025/11/13. +// + +#import "QXAudioRecorderView.h" +#import +#import "UIButton+QX.h" +#import "QXCOSUploadManager.h" +#import "QXMineNetwork.h" + +@interface QXAudioRecorderView() +// UI Components +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UIView *recordContentView; +@property (nonatomic, strong) UIImageView *recordButton; +@property (nonatomic, strong) CAShapeLayer *progressLayer; +@property (nonatomic, strong) UILabel *timeLabel; +@property (nonatomic, strong) UILabel *stateLabel; +@property (nonatomic, strong) UIButton *playButton; +@property (nonatomic, strong) UIButton *resetButton; +@property (nonatomic, strong) UIButton *authBtn; + +// Audio Components +@property (nonatomic, strong) AVAudioRecorder *audioRecorder; +@property (nonatomic, strong) AVAudioPlayer *audioPlayer; +@property (nonatomic, strong) NSURL *originalAudioFileURL; +@property (nonatomic, strong) NSURL *mp3AudioFileURL; +@property (nonatomic, strong) NSURL *tempAudioFileURL; // 临时拼接文件 + +// Recording State +@property (nonatomic, assign) AudioRecorderState state; +@property (nonatomic, assign) NSTimeInterval currentDuration; // 当前段时长 +@property (nonatomic, assign) NSTimeInterval totalDuration; // 总时长 +@property (nonatomic, assign) NSInteger recordingSessionCount; // 录制段数 +@property (nonatomic, strong) NSTimer *recordingTimer; +@property (nonatomic, assign) BOOL isCancelled; +@property (nonatomic, strong) NSMutableArray *recordedSegments; // 录制的音频段 +@end + + +@implementation QXAudioRecorderView + +- (instancetype)initWithFrame:(CGRect)frame { + return [self initWithFrame:frame maxDuration:300.0]; +} + +- (instancetype)initWithFrame:(CGRect)frame maxDuration:(NSTimeInterval)maxDuration { + self = [super initWithFrame:frame]; + if (self) { + _maxDuration = maxDuration; + _showPlaybackButton = YES; + _state = AudioRecorderStateReady; + _recordedSegments = [NSMutableArray array]; + _recordingSessionCount = 0; + [self setupUI]; + [self setupAudioSession]; + [self setupGestureRecognizers]; + } + return self; +} + +- (void)setupUI { + self.backgroundColor = [UIColor whiteColor]; + [self addRoundedCornersWithRadius:16 byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)]; + + self.authBtn = [[UIButton alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-ScaleWidth(57)-16, 16, ScaleWidth(57), ScaleWidth(20))]; + [self.authBtn setImage:[UIImage imageNamed:@"singer_auth_btn"] forState:(UIControlStateNormal)]; + [self.authBtn addTarget:self action:@selector(authAction) forControlEvents:(UIControlEventTouchUpInside)]; + [self addSubview:self.authBtn]; + + + self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake((SCREEN_WIDTH-150)/2, 18, 150, 24)]; + self.titleLabel.textColor = RGB16(0x333333); + self.titleLabel.font = [UIFont boldSystemFontOfSize:16]; + self.titleLabel.text = @"我的认证"; + self.titleLabel.textAlignment = NSTextAlignmentCenter; + [self addSubview:self.titleLabel]; + + self.recordContentView = [[UIView alloc] init]; + [self addSubview:self.recordContentView]; + + // 录制按钮 + self.recordButton = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"singer_record_btn"]]; + self.recordButton.userInteractionEnabled = YES; + [self.recordContentView addSubview:self.recordButton]; + + // 进度圆环 + self.progressLayer = [CAShapeLayer layer]; + self.progressLayer.fillColor = [UIColor clearColor].CGColor; + self.progressLayer.strokeColor = QXConfig.themeColor.CGColor; + self.progressLayer.lineWidth = 4; + self.progressLayer.strokeEnd = 0; + // 确保圆环从顶部开始 + self.progressLayer.strokeStart = 0; // 从起点开始 + self.progressLayer.strokeEnd = 0; // 初始进度为0 + // 如果需要动画效果,可以设置transform + self.progressLayer.transform = CATransform3DIdentity; + self.progressLayer.lineCap = kCALineCapRound; + [self.recordContentView.layer addSublayer:self.progressLayer]; + + // 时间标签 + self.timeLabel = [[UILabel alloc] init]; + self.timeLabel.text = [self formattedTime:0]; + self.timeLabel.textAlignment = NSTextAlignmentCenter; + self.timeLabel.font = [UIFont systemFontOfSize:12]; + self.timeLabel.textColor = RGB16A(0x000000, 0.45); + [self addSubview:self.timeLabel]; + + // 状态标签 + self.stateLabel = [[UILabel alloc] init]; + self.stateLabel.text = @"长按录音"; + self.stateLabel.textAlignment = NSTextAlignmentCenter; + self.stateLabel.font = [UIFont systemFontOfSize:14]; + self.stateLabel.textColor = [UIColor grayColor]; + [self addSubview:self.stateLabel]; +// +// // 录制段数标签 +// self.sessionLabel = [[UILabel alloc] init]; +// self.sessionLabel.text = @""; +// self.sessionLabel.textAlignment = NSTextAlignmentCenter; +// self.sessionLabel.font = [UIFont systemFontOfSize:12]; +// self.sessionLabel.textColor = [UIColor lightGrayColor]; +// [self addSubview:self.sessionLabel]; + + // 试听按钮 + self.playButton = [[UIButton alloc] init]; + [self.playButton setTitle:@"试听" forState:UIControlStateNormal]; + [self.playButton setTitleColor:RGB16A(0x000000, 0.45) forState:(UIControlStateNormal)]; + self.playButton.titleLabel.font = [UIFont systemFontOfSize:12]; + [self.playButton setImage:[UIImage imageNamed:@"singer_try_listen"] forState:(UIControlStateNormal)]; + [self.playButton addTarget:self action:@selector(playButtonTapped) forControlEvents:UIControlEventTouchUpInside]; +// self.playButton.hidden = YES; + [self addSubview:self.playButton]; + + // 重置按钮 + self.resetButton = [[UIButton alloc] init]; + [self.resetButton setTitle:@"重置" forState:UIControlStateNormal]; + [self.resetButton setImage:[UIImage imageNamed:@"singer_reset_record"] forState:(UIControlStateNormal)]; + [self.resetButton setTitleColor:RGB16A(0x000000, 0.45) forState:(UIControlStateNormal)]; + self.resetButton.titleLabel.font = [UIFont systemFontOfSize:12]; + [self.resetButton addTarget:self action:@selector(resetButtonTapped) forControlEvents:UIControlEventTouchUpInside]; +// self.resetButton.hidden = YES; + [self addSubview:self.resetButton]; + [self.recordContentView bringSubviewToFront:self.recordButton]; +} + +- (void)setupAudioSession { +// AVAudioSession *audioSession = [AVAudioSession sharedInstance]; +// NSError *error = nil; +// [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]; +// [audioSession setActive:YES error:&error]; +// +// if (error) { +// NSLog(@"Audio session setup error: %@", error); +// } + AVAudioSession *audioSession = [AVAudioSession sharedInstance]; + NSError *error = nil; + + // 使用 Playback 类别,会自动使用扬声器 + [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error]; + + // 或者使用 PlayAndRecord 但覆盖默认输出 + [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord + withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker + error:&error]; + + [audioSession setActive:YES error:&error]; + + if (error) { + NSLog(@"Audio session setup error: %@", error); + } +} + +- (void)setupGestureRecognizers { + // 长按手势 - 开始录制 + UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; + longPress.minimumPressDuration = 0.3; + longPress.delegate = self; + [self.recordButton addGestureRecognizer:longPress]; +} +-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ + return YES; + +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + CGFloat centerX = CGRectGetWidth(self.bounds) / 2; + // 时间标签 + self.timeLabel.frame = CGRectMake((SCREEN_WIDTH-150)/2, self.titleLabel.bottom+4, 150, 30); + + // 录制按钮 + self.recordContentView.frame = CGRectMake(centerX - 50.5, self.timeLabel.bottom+22, 101, 101); + self.recordButton.frame = CGRectMake(11, 11, 80, 80); + + // 进度圆环 + CGRect progressRect = CGRectInset(self.recordContentView.bounds, 4, 4); + UIBezierPath *progressPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMidX(progressRect), CGRectGetMidY(progressRect)) + radius:progressRect.size.width / 2 + startAngle:-M_PI_2 // 从顶部开始(-90度) + endAngle:-M_PI_2 + M_PI * 2 // 顺时针一圈 + clockwise:YES]; + + self.progressLayer.path = progressPath.CGPath; + + + +// // 状态标签 + self.stateLabel.frame = CGRectMake(0, self.recordContentView.bottom, CGRectGetWidth(self.bounds), 20); +// +// // 段数标签 +// self.sessionLabel.frame = CGRectMake(0, 205, CGRectGetWidth(self.bounds), 20); + + // 按钮 + self.playButton.frame = CGRectMake(SCREEN_WIDTH-38-35, self.recordContentView.top+35, 38, 60); + self.resetButton.frame = CGRectMake(35, self.recordContentView.top+35, 38, 60); + [self.playButton qx_layoutButtonNOSizeToFitWithEdgeInsetsStyle:(QXButtonEdgeInsetsStyleTop) imageTitleSpace:2]; + [self.resetButton qx_layoutButtonNOSizeToFitWithEdgeInsetsStyle:(QXButtonEdgeInsetsStyleTop) imageTitleSpace:2]; +} + +-(void)authAction{ + ///去认证 + ///去认证 + if ((int)self.totalDuration < 5) { + showToast(@"录音时长不得小于60秒"); + return; + } + if (self.originalAudioFileURL==nil) { + showToast(@"录制文件不存在"); + return; + } + NSData *data = [NSData dataWithContentsOfURL:self.originalAudioFileURL]; + @weakify(self) + showLoadingInView(self.viewController.view); + [[QXCOSUploadManager shareManager] audioUploadFile:data withObjectKey:self.originalAudioFileURL.lastPathComponent complete:^(NSString * _Nonnull fileUrl, QXCOSUploadImageState state) { + @strongify(self); + dispatch_async(dispatch_get_main_queue(), ^{ + hideLoadingInView(self.viewController.view); + if ([fileUrl isExist]) { + [QXMineNetwork singerAuthWithSong:fileUrl successBlock:^(NSDictionary * _Nonnull dict) { + showToast(@"上传成功"); + } failBlock:^(NSError * _Nonnull error, NSString * _Nonnull msg) { + showToast(@"上传失败"); + }]; + }else{ + showToast(@"上传失败"); + } + }); + }]; +} + +#pragma mark - Gesture Handlers + +- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture { + CGPoint touchPoint = [gesture locationInView:self]; + + switch (gesture.state) { + case UIGestureRecognizerStateBegan: + [self stopPlayback]; + NSLog(@"开始录制 - 第%ld段", (long)self.recordingSessionCount + 1); + self.isCancelled = NO; + [self startRecording]; + break; + + case UIGestureRecognizerStateChanged: + // 检查是否上滑取消 + if (touchPoint.y < CGRectGetMinY(self.recordButton.frame) - 20) { + if (!self.isCancelled) { + NSLog(@"取消录制"); + self.isCancelled = YES; + [self updateUIForCancelled]; + } + } else { + if (self.isCancelled) { + NSLog(@"恢复录制"); + self.isCancelled = NO; + [self updateUIForRecording]; + } + } + break; + + case UIGestureRecognizerStateEnded: + case UIGestureRecognizerStateCancelled: + NSLog(@"结束录制 - 当前段时长: %.1f秒", self.currentDuration); + if (self.isCancelled) { + [self cancelRecording]; + } else { + [self stopRecording]; + } + break; + + default: + break; + } +} + + + +#pragma mark - Recording Control + +- (void)startRecording { + if (self.state == AudioRecorderStateRecording) return; + + // 配置录音器 + NSURL *audioFileURL = [self generateAudioFileURL]; + NSDictionary *recordSettings = @{ + AVFormatIDKey: @(kAudioFormatLinearPCM), + AVSampleRateKey: @44100.0, + AVNumberOfChannelsKey: @1, + AVEncoderAudioQualityKey: @(AVAudioQualityHigh) + }; + + NSError *error = nil; + self.audioRecorder = [[AVAudioRecorder alloc] initWithURL:audioFileURL settings:recordSettings error:&error]; + self.audioRecorder.delegate = self; + self.audioRecorder.meteringEnabled = YES; + + if (error) { + NSLog(@"录音器初始化失败: %@", error); + if ([self.delegate respondsToSelector:@selector(qxAudioRecorderView:didFailWithError:)]) { + [self.delegate qxAudioRecorderView:self didFailWithError:error]; + } + return; + } + + if ([self.audioRecorder record]) { + self.state = AudioRecorderStateRecording; + self.recordingSessionCount++; + [self startRecordingTimer]; + [self updateUIForRecording]; + + if ([self.delegate respondsToSelector:@selector(qxAudioRecorderView:didChangeState:)]) { + [self.delegate qxAudioRecorderView:self didChangeState:self.state]; + } + } +} + +- (void)stopRecording { + if (self.state != AudioRecorderStateRecording) return; + + [self.recordingTimer invalidate]; + self.recordingTimer = nil; + + NSTimeInterval segmentDuration = self.currentDuration; + [self.audioRecorder stop]; + + // 保存录制的音频段 + if (segmentDuration > 0.5) { // 只保存超过0.5秒的有效录音 + [self.recordedSegments addObject:self.audioRecorder.url]; + self.totalDuration += segmentDuration; + NSLog(@"保存音频段,时长: %.1f秒,总时长: %.1f秒", segmentDuration, self.totalDuration); + } + + self.audioRecorder = nil; + self.currentDuration = 0; + + self.state = AudioRecorderStateStopped; + [self updateUIForStopped]; + + // 如果有录音段,合并音频 + if (self.recordedSegments.count > 0) { + [self mergeAudioSegments]; + } + + if ([self.delegate respondsToSelector:@selector(qxAudioRecorderView:didChangeState:)]) { + [self.delegate qxAudioRecorderView:self didChangeState:self.state]; + } +} + +- (void)cancelRecording { + if (self.state != AudioRecorderStateRecording) return; + + [self.recordingTimer invalidate]; + self.recordingTimer = nil; + + [self.audioRecorder stop]; + [self.audioRecorder deleteRecording]; + self.audioRecorder = nil; + self.currentDuration = 0; + + self.state = AudioRecorderStateStopped; + [self updateUIForStopped]; + + if ([self.delegate respondsToSelector:@selector(qxAudioRecorderView:didChangeState:)]) { + [self.delegate qxAudioRecorderView:self didChangeState:self.state]; + } +} + +#pragma mark - Audio Merging + +- (void)mergeAudioSegments { + if (self.recordedSegments.count == 0) return; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + // 创建合并文件 + NSURL *mergedFileURL = [self generateAudioFileURLWithExtension:@"m4a"]; + + // 创建音频组合 + AVMutableComposition *composition = [AVMutableComposition composition]; + CMTime currentTime = kCMTimeZero; + + for (NSURL *audioURL in self.recordedSegments) { + AVURLAsset *audioAsset = [AVURLAsset assetWithURL:audioURL]; + CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration); + + // 添加音频轨道 + AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; + + AVAssetTrack *sourceAudioTrack = [[audioAsset tracksWithMediaType:AVMediaTypeAudio] firstObject]; + if (sourceAudioTrack) { + [audioTrack insertTimeRange:timeRange ofTrack:sourceAudioTrack atTime:currentTime error:nil]; + currentTime = CMTimeAdd(currentTime, audioAsset.duration); + } + } + + // 导出合并的音频 + AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetAppleM4A]; + exportSession.outputURL = mergedFileURL; + exportSession.outputFileType = AVFileTypeAppleM4A; + + [exportSession exportAsynchronouslyWithCompletionHandler:^{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (exportSession.status == AVAssetExportSessionStatusCompleted) { + self.originalAudioFileURL = mergedFileURL; + NSLog(@"音频合并完成,总时长: %.1f秒", self.totalDuration); + + // 转换为MP3 + [self convertToMP3]; + } else { + NSLog(@"音频合并失败: %@", exportSession.error); + } + }); + }]; + }); +} + +#pragma mark - Reset Function + +- (void)resetRecording { + NSLog(@"重置录音"); + + [self stopPlayback]; + [self cancelRecording]; + + // 清理所有录音段 + for (NSURL *segmentURL in self.recordedSegments) { + [[NSFileManager defaultManager] removeItemAtURL:segmentURL error:nil]; + } + [self.recordedSegments removeAllObjects]; + + // 清理合并文件 + if (self.originalAudioFileURL) { + [[NSFileManager defaultManager] removeItemAtURL:self.originalAudioFileURL error:nil]; + self.originalAudioFileURL = nil; + } + + if (self.mp3AudioFileURL) { + [[NSFileManager defaultManager] removeItemAtURL:self.mp3AudioFileURL error:nil]; + self.mp3AudioFileURL = nil; + } + + // 重置状态 + self.totalDuration = 0; + self.currentDuration = 0; + self.recordingSessionCount = 0; + self.state = AudioRecorderStateReady; + + [self updateUIForReady]; + + if ([self.delegate respondsToSelector:@selector(qxAudioRecorderView:didChangeState:)]) { + [self.delegate qxAudioRecorderView:self didChangeState:self.state]; + } +} + +#pragma mark - Playback Control + +- (void)playButtonTapped { + if (self.state == AudioRecorderStatePlaying) { + [self stopPlayback]; + } else { + [self playRecording]; + } +} + +- (void)playRecording { + if (self.state == AudioRecorderStatePlaying) return; + + NSURL *playbackURL = self.mp3AudioFileURL ?: self.originalAudioFileURL; + if (!playbackURL){ + showToast(@"您还未录制声音"); + return; + } + // 播放前切换到扬声器 +// AVAudioSession *audioSession = [AVAudioSession sharedInstance]; +// NSError *error = nil; +// [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error]; +// [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error]; +// [audioSession setActive:YES error:&error]; + + NSError *playerError = nil; + self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:playbackURL error:&playerError]; + self.audioPlayer.delegate = self; + + if (playerError) { + NSLog(@"播放器初始化失败: %@", playerError); + return; + } + + if ([self.audioPlayer play]) { + self.state = AudioRecorderStatePlaying; + [self updateUIForPlaying]; + + if ([self.delegate respondsToSelector:@selector(qxAudioRecorderView:didChangeState:)]) { + [self.delegate qxAudioRecorderView:self didChangeState:self.state]; + } + } +} + +- (void)stopPlayback { + if (self.state != AudioRecorderStatePlaying) return; + + [self.audioPlayer stop]; + self.audioPlayer = nil; + + self.state = AudioRecorderStateStopped; + [self updateUIForStopped]; + + if ([self.delegate respondsToSelector:@selector(qxAudioRecorderView:didChangeState:)]) { + [self.delegate qxAudioRecorderView:self didChangeState:self.state]; + } +} + +- (void)resetButtonTapped { + [self resetRecording]; +} + +#pragma mark - Timer + +- (void)startRecordingTimer { + self.currentDuration = 0; + self.recordingTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateRecordingProgress) userInfo:nil repeats:YES]; +} + +- (void)updateRecordingProgress { + if (self.state != AudioRecorderStateRecording) return; + + self.currentDuration += 0.1; + + // 更新UI + [self updateProgress]; + [self updateTimeLabel]; + + // 通知代理进度更新 + if ([self.delegate respondsToSelector:@selector(qxAudioRecorderView:didUpdateProgress:totalDuration:)]) { + [self.delegate qxAudioRecorderView:self didUpdateProgress:self.currentDuration totalDuration:self.totalDuration + self.currentDuration]; + } + + // 检查是否达到最大时长 + if ((self.totalDuration + self.currentDuration) >= self.maxDuration) { + [self stopRecording]; + } +} + +#pragma mark - UI Updates + +- (void)updateUIForReady { + self.progressLayer.strokeEnd = 0; + self.timeLabel.text = [self formattedTime:0]; + self.stateLabel.text = @"长按录音"; +// +// self.playButton.hidden = YES; +// self.resetButton.hidden = YES; +} + +- (void)updateUIForRecording { + self.stateLabel.text = self.isCancelled ? @"松开手指取消" : @"录音中...松开结束"; + + +// self.playButton.hidden = YES; +// self.resetButton.hidden = YES; +} + +- (void)updateUIForStopped { + self.stateLabel.text = @"继续录音"; + if (self.totalDuration > 0) { + if (self.showPlaybackButton) { +// self.playButton.hidden = NO; +// self.resetButton.hidden = NO; + [self.playButton setTitle:@"试听" forState:UIControlStateNormal]; + [self.playButton setImage:[UIImage imageNamed:@"singer_try_listen"] forState:UIControlStateNormal]; + } + } else { +// self.playButton.hidden = YES; +// self.resetButton.hidden = YES; + } + +// self.stateLabel.textColor = [UIColor grayColor]; +} + +- (void)updateUIForPlaying { +// self.stateLabel.text = @"试听中..."; +// self.stateLabel.textColor = [UIColor blueColor]; + [self.playButton setTitle:@"停止" forState:UIControlStateNormal]; + [self.playButton setImage:[UIImage imageNamed:@"singer_listen_stop"] forState:UIControlStateNormal]; +} + +- (void)updateUIForCancelled { +// self.stateLabel.text = @"松开手指取消"; +// self.stateLabel.textColor = [UIColor redColor]; +} + +- (void)updateProgress { + CGFloat totalProgress = (self.totalDuration + self.currentDuration) / self.maxDuration; + self.progressLayer.strokeEnd = totalProgress; + +// // 根据进度改变颜色 +// if (totalProgress > 0.8) { +// self.progressLayer.strokeColor = [UIColor redColor].CGColor; +// } else if (totalProgress > 0.6) { +// self.progressLayer.strokeColor = [UIColor orangeColor].CGColor; +// } else { +// self.progressLayer.strokeColor = [UIColor colorWithRed:0.0 green:0.48 blue:1.0 alpha:1.0].CGColor; +// } +} + +- (void)updateTimeLabel { + NSTimeInterval currentTotal = self.totalDuration + self.currentDuration; + self.timeLabel.text = [self formattedTime:currentTotal]; +} + +#pragma mark - MP3 Conversion + +- (void)convertToMP3 { +// if (!self.originalAudioFileURL) return; +// +// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ +// NSString *mp3FileName = [NSString stringWithFormat:@"%@.mp3", [[NSUUID UUID] UUIDString]]; +// NSString *mp3FilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:mp3FileName]; +// self.mp3AudioFileURL = [NSURL fileURLWithPath:mp3FilePath]; +// +// @try { +// int read, write; +// +// FILE *pcm = fopen([[self.originalAudioFileURL path] UTF8String], "rb"); +// FILE *mp3 = fopen([mp3FilePath UTF8String], "wb"); +// +// const int PCM_SIZE = 8192; +// const int MP3_SIZE = 8192; +// short int pcm_buffer[PCM_SIZE * 2]; +// unsigned char mp3_buffer[MP3_SIZE]; +// +// lame_t lame = lame_init(); +// lame_set_in_samplerate(lame, 44100); +// lame_set_VBR(lame, vbr_default); +// lame_init_params(lame); +// +// do { +// read = (int)fread(pcm_buffer, 2 * sizeof(short int), PCM_SIZE, pcm); +// if (read == 0) +// write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE); +// else +// write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE); +// +// fwrite(mp3_buffer, write, 1, mp3); +// +// } while (read != 0); +// +// lame_close(lame); +// fclose(mp3); +// fclose(pcm); +// } +// @catch (NSException *exception) { +// NSLog(@"MP3转换失败: %@", exception); +// self.mp3AudioFileURL = nil; +// } +// @finally { +// dispatch_async(dispatch_get_main_queue(), ^{ +// if (self.mp3AudioFileURL && [self.delegate respondsToSelector:@selector(audioRecorderView:didFinishRecordingWithMP3File:duration:)]) { +// [self.delegate audioRecorderView:self didFinishRecordingWithMP3File:self.mp3AudioFileURL duration:self.totalDuration]; +// } +// }); +// } +// }); +} + +#pragma mark - Utility Methods + +- (NSURL *)generateAudioFileURL { + return [self generateAudioFileURLWithExtension:@"caf"]; +} + +- (NSURL *)generateAudioFileURLWithExtension:(NSString *)extension { + long long time = [[NSDate date] timeIntervalSince1970]; + NSString *fileName = [NSString stringWithFormat:@"%lld.%@", time ,extension]; + NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName]; + return [NSURL fileURLWithPath:filePath]; +} + +- (NSString *)formattedTime:(NSTimeInterval)time { + int minutes = (int)time / 60; + int seconds = (int)time % 60; + int maxMinutes = (int)_maxDuration / 60; + int maxSeconds = (int)_maxDuration % 60; + return [NSString stringWithFormat:@"%02d:%02d | %02d:%02d", minutes, seconds,maxMinutes,maxSeconds]; +} + +- (NSString *)getRecordingStatus { + if (self.totalDuration > 0) { + return [NSString stringWithFormat:@"已录制%.1f秒,共%ld段", self.totalDuration, (long)self.recordingSessionCount]; + } else { + return @"未开始录制"; + } +} + +#pragma mark - AVAudioRecorderDelegate + +- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag { + NSLog(@"录音完成: %@", flag ? @"成功" : @"失败"); +} + +- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error { + NSLog(@"录音编码错误: %@", error); + if ([self.delegate respondsToSelector:@selector(qxAudioRecorderView:didFailWithError:)]) { + [self.delegate qxAudioRecorderView:self didFailWithError:error]; + } +} + +#pragma mark - AVAudioPlayerDelegate + +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { + [self stopPlayback]; +} + +- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error { + NSLog(@"播放解码错误: %@", error); + [self stopPlayback]; +} + +#pragma mark - Public Properties + +- (NSURL *)currentAudioFileURL { + return self.mp3AudioFileURL ?: self.originalAudioFileURL; +} + +- (void)dealloc { + [self.recordingTimer invalidate]; + [self.audioRecorder stop]; + [self.audioPlayer stop]; +} + +@end diff --git a/QXLive/Mine(音域)/View/爵位/QXNobilityHeaderView.m b/QXLive/Mine(音域)/View/爵位/QXNobilityHeaderView.m index e6ad8b5..7f91721 100644 --- a/QXLive/Mine(音域)/View/爵位/QXNobilityHeaderView.m +++ b/QXLive/Mine(音域)/View/爵位/QXNobilityHeaderView.m @@ -101,7 +101,7 @@ [self.currenNobilityImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.right.mas_equalTo(-28); make.height.width.mas_equalTo(ScaleWidth(104)); - make.bottom.mas_equalTo(-34); + make.top.mas_equalTo(13); }]; self.compareImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"nobility_compare_top"]]; @@ -118,6 +118,7 @@ _model = model; [self.userAvatarView setHeadIcon:model.user_info.avatar dress:@""]; self.userNameLabel.text = [NSString stringWithFormat:@"%@的爵位",model.user_info.nickname]; + [self.currenNobilityImageView sd_setImageWithURL:[NSURL URLWithString:model.nobility_info.image]]; if (model.nobility_info.status.intValue == 0) { [self setHaveNobility:NO]; }else{ diff --git a/QXLive/Mine(音域)/View/钱包/QXCornRecordCell.xib b/QXLive/Mine(音域)/View/钱包/QXCornRecordCell.xib index 32fa36c..1018b10 100644 --- a/QXLive/Mine(音域)/View/钱包/QXCornRecordCell.xib +++ b/QXLive/Mine(音域)/View/钱包/QXCornRecordCell.xib @@ -11,36 +11,36 @@ - + - + -