diff --git a/keyBoard/Assets.xcassets/AI/comment_nor_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/AI/comment_nor_icon.imageset/Contents.json new file mode 100644 index 0000000..35f9dbc --- /dev/null +++ b/keyBoard/Assets.xcassets/AI/comment_nor_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "comment_nor_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "comment_nor_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/AI/comment_nor_icon.imageset/comment_nor_icon@2x.png b/keyBoard/Assets.xcassets/AI/comment_nor_icon.imageset/comment_nor_icon@2x.png new file mode 100644 index 0000000..27a3761 Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/comment_nor_icon.imageset/comment_nor_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/AI/comment_nor_icon.imageset/comment_nor_icon@3x.png b/keyBoard/Assets.xcassets/AI/comment_nor_icon.imageset/comment_nor_icon@3x.png new file mode 100644 index 0000000..a5f341d Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/comment_nor_icon.imageset/comment_nor_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/AI/comment_sel_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/AI/comment_sel_icon.imageset/Contents.json new file mode 100644 index 0000000..a7f321d --- /dev/null +++ b/keyBoard/Assets.xcassets/AI/comment_sel_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "comment_sel_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "comment_sel_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/AI/comment_sel_icon.imageset/comment_sel_icon@2x.png b/keyBoard/Assets.xcassets/AI/comment_sel_icon.imageset/comment_sel_icon@2x.png new file mode 100644 index 0000000..dd2091e Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/comment_sel_icon.imageset/comment_sel_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/AI/comment_sel_icon.imageset/comment_sel_icon@3x.png b/keyBoard/Assets.xcassets/AI/comment_sel_icon.imageset/comment_sel_icon@3x.png new file mode 100644 index 0000000..9db05b8 Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/comment_sel_icon.imageset/comment_sel_icon@3x.png differ diff --git a/keyBoard/Class/AiTalk/M/KBAICommentModel.h b/keyBoard/Class/AiTalk/M/KBAICommentModel.h index c87c24e..91786b6 100644 --- a/keyBoard/Class/AiTalk/M/KBAICommentModel.h +++ b/keyBoard/Class/AiTalk/M/KBAICommentModel.h @@ -41,7 +41,7 @@ typedef NS_ENUM(NSInteger, KBAIReplyFooterState) { @property(nonatomic, assign) NSInteger likeCount; /// 是否已点赞 -@property(nonatomic, assign) BOOL isLiked; +@property(nonatomic, assign) BOOL liked; /// 创建时间(时间戳) @property(nonatomic, assign) NSTimeInterval createTime; diff --git a/keyBoard/Class/AiTalk/M/KBAICommentModel.m b/keyBoard/Class/AiTalk/M/KBAICommentModel.m index efcb59d..2e4b312 100644 --- a/keyBoard/Class/AiTalk/M/KBAICommentModel.m +++ b/keyBoard/Class/AiTalk/M/KBAICommentModel.m @@ -26,11 +26,6 @@ return @{@"replies" : [KBAIReplyModel class]}; } -- (void)setLiked:(NSInteger)liked { - // 后端返回的是 NSInteger (0/1),转换为 BOOL - _isLiked = (liked == 1); -} - - (void)setCreatedAt:(NSString *)createdAt { // 后端返回的是字符串时间,转换为时间戳 if (createdAt && createdAt.length > 0) { @@ -44,6 +39,28 @@ } } +#pragma mark - MJExtension Hook + +/// MJExtension 转换完成后的钩子方法,用于处理空值 +- (void)mj_didConvertToObjectWithKeyValues:(NSDictionary *)keyValues { + // 防止后端返回 null,统一设置空字符串为默认值 + if (!_commentId) { + _commentId = @""; + } + if (!_userId) { + _userId = @""; + } + if (!_userName) { + _userName = @""; + } + if (!_avatarUrl) { + _avatarUrl = @""; + } + if (!_content) { + _content = @""; + } +} + - (instancetype)init { self = [super init]; if (self) { @@ -133,7 +150,8 @@ // 内容高度(多行) UIFont *contentFont = [UIFont systemFontOfSize:15]; - CGRect contentRect = [self.content boundingRectWithSize:CGSizeMake(contentWidth, CGFLOAT_MAX) + NSString *contentText = self.content ?: @""; + CGRect contentRect = [contentText boundingRectWithSize:CGSizeMake(contentWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName: contentFont} context:nil]; diff --git a/keyBoard/Class/AiTalk/M/KBAIReplyModel.m b/keyBoard/Class/AiTalk/M/KBAIReplyModel.m index 43ea95b..be29c26 100644 --- a/keyBoard/Class/AiTalk/M/KBAIReplyModel.m +++ b/keyBoard/Class/AiTalk/M/KBAIReplyModel.m @@ -7,7 +7,6 @@ #import "KBAIReplyModel.h" #import -#import "KBAIReplyModel.h" @implementation KBAIReplyModel @@ -40,6 +39,31 @@ } } +#pragma mark - MJExtension Hook + +/// MJExtension 转换完成后的钩子方法,用于处理空值 +- (void)mj_didConvertToObjectWithKeyValues:(NSDictionary *)keyValues { + // 防止后端返回 null,统一设置空字符串为默认值 + if (!_replyId) { + _replyId = @""; + } + if (!_userId) { + _userId = @""; + } + if (!_userName) { + _userName = @""; + } + if (!_avatarUrl) { + _avatarUrl = @""; + } + if (!_content) { + _content = @""; + } + if (!_replyToUserName) { + _replyToUserName = @""; + } +} + - (NSString *)formattedTime { NSDate *date = [NSDate dateWithTimeIntervalSince1970:self.createTime]; NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:date]; @@ -70,7 +94,7 @@ CGFloat contentWidth = maxWidth - 68 - 28 - 8 - 50; // 用户名高度(可能包含 "回复 @xxx") - NSMutableString *userNameText = [NSMutableString stringWithString:self.userName]; + NSMutableString *userNameText = [NSMutableString stringWithString:self.userName ?: @""]; if (self.replyToUserName.length > 0) { [userNameText appendFormat:@" 回复 @%@", self.replyToUserName]; } @@ -83,7 +107,8 @@ // 内容高度 UIFont *contentFont = [UIFont systemFontOfSize:14]; - CGRect contentRect = [self.content boundingRectWithSize:CGSizeMake(contentWidth, CGFLOAT_MAX) + NSString *contentText = self.content ?: @""; + CGRect contentRect = [contentText boundingRectWithSize:CGSizeMake(contentWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName: contentFont} context:nil]; diff --git a/keyBoard/Class/AiTalk/V/KBAICommentFooterView.m b/keyBoard/Class/AiTalk/V/KBAICommentFooterView.m index f58d59f..82ba72b 100644 --- a/keyBoard/Class/AiTalk/V/KBAICommentFooterView.m +++ b/keyBoard/Class/AiTalk/V/KBAICommentFooterView.m @@ -29,7 +29,7 @@ #pragma mark - UI Setup - (void)setupUI { - self.contentView.backgroundColor = [UIColor whiteColor]; + self.contentView.backgroundColor = [UIColor clearColor]; [self.contentView addSubview:self.actionButton]; [self.contentView addSubview:self.lineView]; diff --git a/keyBoard/Class/AiTalk/V/KBAICommentHeaderView.m b/keyBoard/Class/AiTalk/V/KBAICommentHeaderView.m index 15c72f3..3bfa242 100644 --- a/keyBoard/Class/AiTalk/V/KBAICommentHeaderView.m +++ b/keyBoard/Class/AiTalk/V/KBAICommentHeaderView.m @@ -35,7 +35,7 @@ #pragma mark - UI Setup - (void)setupUI { - self.contentView.backgroundColor = [UIColor whiteColor]; + self.contentView.backgroundColor = [UIColor clearColor]; [self.contentView addSubview:self.avatarImageView]; [self.contentView addSubview:self.userNameLabel]; @@ -47,7 +47,7 @@ [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.contentView).offset(16); make.top.equalTo(self.contentView).offset(12); - make.width.height.mas_equalTo(40); + make.width.height.mas_equalTo(28); }]; [self.userNameLabel mas_makeConstraints:^(MASConstraintMaker *make) { @@ -98,12 +98,11 @@ comment.likeCount > 0 ? [self formatLikeCount:comment.likeCount] : @"赞"; self.likeButton.textLabel.text = likeText; - UIImage *likeImage = comment.isLiked - ? [UIImage systemImageNamed:@"heart.fill"] - : [UIImage systemImageNamed:@"heart"]; + UIImage *likeImage = comment.liked + ? [UIImage imageNamed:@"comment_sel_icon"] + : [UIImage imageNamed:@"comment_nor_icon"]; self.likeButton.iconView.image = likeImage; - self.likeButton.iconView.tintColor = - comment.isLiked ? [UIColor systemRedColor] : [UIColor grayColor]; + } - (NSString *)formatLikeCount:(NSInteger)count { @@ -135,7 +134,7 @@ if (!_avatarImageView) { _avatarImageView = [[UIImageView alloc] init]; _avatarImageView.contentMode = UIViewContentModeScaleAspectFill; - _avatarImageView.layer.cornerRadius = 20; + _avatarImageView.layer.cornerRadius = 14; _avatarImageView.layer.masksToBounds = YES; _avatarImageView.backgroundColor = [UIColor systemGray5Color]; } @@ -145,8 +144,9 @@ - (UILabel *)userNameLabel { if (!_userNameLabel) { _userNameLabel = [[UILabel alloc] init]; - _userNameLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; - _userNameLabel.textColor = [UIColor secondaryLabelColor]; + _userNameLabel.text = @"--"; + _userNameLabel.font = [UIFont systemFontOfSize:13 weight:UIFontWeightMedium]; + _userNameLabel.textColor = [UIColor colorWithHex:0x9F9F9F]; } return _userNameLabel; } @@ -154,8 +154,8 @@ - (UILabel *)contentLabel { if (!_contentLabel) { _contentLabel = [[UILabel alloc] init]; - _contentLabel.font = [UIFont systemFontOfSize:15]; - _contentLabel.textColor = [UIColor labelColor]; + _contentLabel.font = [UIFont systemFontOfSize:12]; + _contentLabel.textColor = [UIColor whiteColor]; _contentLabel.numberOfLines = 0; } return _contentLabel; @@ -165,7 +165,7 @@ if (!_timeLabel) { _timeLabel = [[UILabel alloc] init]; _timeLabel.font = [UIFont systemFontOfSize:12]; - _timeLabel.textColor = [UIColor secondaryLabelColor]; + _timeLabel.textColor = [UIColor colorWithHex:0x9F9F9F]; } return _timeLabel; } @@ -175,7 +175,7 @@ _replyButton = [UIButton buttonWithType:UIButtonTypeCustom]; _replyButton.titleLabel.font = [UIFont systemFontOfSize:12]; [_replyButton setTitle:@"回复" forState:UIControlStateNormal]; - [_replyButton setTitleColor:[UIColor secondaryLabelColor] forState:UIControlStateNormal]; + [_replyButton setTitleColor:[UIColor colorWithHex:0x9F9F9F] forState:UIControlStateNormal]; [_replyButton addTarget:self action:@selector(replyButtonTapped) forControlEvents:UIControlEventTouchUpInside]; @@ -188,10 +188,9 @@ _likeButton = [[KBTopImageButton alloc] init]; _likeButton.iconSize = CGSizeMake(20, 20); _likeButton.spacing = 2; - _likeButton.iconView.image = [UIImage systemImageNamed:@"heart"]; - _likeButton.iconView.tintColor = [UIColor grayColor]; - _likeButton.textLabel.font = [UIFont systemFontOfSize:11]; - _likeButton.textLabel.textColor = [UIColor grayColor]; + _likeButton.iconView.image = [UIImage imageNamed:@"comment_nor_icon"]; + _likeButton.textLabel.font = [UIFont systemFontOfSize:10]; + _likeButton.textLabel.textColor = [UIColor colorWithHex:0xC5BEB4]; [_likeButton addTarget:self action:@selector(likeButtonTapped) forControlEvents:UIControlEventTouchUpInside]; diff --git a/keyBoard/Class/AiTalk/V/KBAICommentView.m b/keyBoard/Class/AiTalk/V/KBAICommentView.m index baa196a..2e52175 100644 --- a/keyBoard/Class/AiTalk/V/KBAICommentView.m +++ b/keyBoard/Class/AiTalk/V/KBAICommentView.m @@ -23,6 +23,7 @@ static NSString *const kCommentFooterIdentifier = @"CommentFooter"; @interface KBAICommentView () +@property(nonatomic, strong) UIVisualEffectView *blurBackgroundView; @property(nonatomic, strong) UIView *headerView; @property(nonatomic, strong) UILabel *titleLabel; @property(nonatomic, strong) UIButton *closeButton; @@ -68,11 +69,18 @@ static NSString *const kCommentFooterIdentifier = @"CommentFooter"; #pragma mark - UI Setup - (void)setupUI { - self.backgroundColor = [UIColor whiteColor]; + // 设置背景为透明,让模糊效果可见 + self.backgroundColor = [UIColor clearColor]; self.layer.cornerRadius = 12; self.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner; self.clipsToBounds = YES; + // 添加模糊背景(最底层) + [self addSubview:self.blurBackgroundView]; + [self.blurBackgroundView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); + }]; + [self addSubview:self.headerView]; [self.headerView addSubview:self.titleLabel]; [self.headerView addSubview:self.closeButton]; @@ -293,8 +301,8 @@ static NSString *const kCommentFooterIdentifier = @"CommentFooter"; __weak typeof(self) weakSelf = self; header.onLikeAction = ^{ // TODO: 处理点赞逻辑 - comment.isLiked = !comment.isLiked; - comment.likeCount += comment.isLiked ? 1 : -1; + comment.liked = !comment.liked; + comment.likeCount += comment.liked ? 1 : -1; [weakSelf.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationNone]; }; @@ -449,10 +457,29 @@ static NSInteger const kRepliesLoadCount = 5; #pragma mark - Lazy Loading +- (UIVisualEffectView *)blurBackgroundView { + if (!_blurBackgroundView) { + // 创建模糊效果(43pt 的模糊半径) + // iOS 的 UIBlurEffect 没有直接设置模糊半径的 API,使用系统预设的 dark 效果 + UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; + _blurBackgroundView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; + + // 在模糊效果上叠加一个半透明黑色遮罩来调整透明度和颜色 + // 颜色:#000000,透明度:0.31 + UIView *darkOverlay = [[UIView alloc] init]; + darkOverlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.31]; + [_blurBackgroundView.contentView addSubview:darkOverlay]; + [darkOverlay mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(_blurBackgroundView); + }]; + } + return _blurBackgroundView; +} + - (UIView *)headerView { if (!_headerView) { _headerView = [[UIView alloc] init]; - _headerView.backgroundColor = [UIColor whiteColor]; + _headerView.backgroundColor = [UIColor clearColor]; } return _headerView; } @@ -461,7 +488,7 @@ static NSInteger const kRepliesLoadCount = 5; if (!_titleLabel) { _titleLabel = [[UILabel alloc] init]; _titleLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightMedium]; - _titleLabel.textColor = [UIColor labelColor]; + _titleLabel.textColor = [UIColor whiteColor]; _titleLabel.text = @"0条评论"; } return _titleLabel; @@ -486,7 +513,7 @@ static NSInteger const kRepliesLoadCount = 5; style:UITableViewStyleGrouped]; _tableView.dataSource = self; _tableView.delegate = self; - _tableView.backgroundColor = [UIColor whiteColor]; + _tableView.backgroundColor = [UIColor clearColor]; _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; _tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; diff --git a/keyBoard/Class/AiTalk/V/KBAIReplyCell.m b/keyBoard/Class/AiTalk/V/KBAIReplyCell.m index a3ac551..8234e03 100644 --- a/keyBoard/Class/AiTalk/V/KBAIReplyCell.m +++ b/keyBoard/Class/AiTalk/V/KBAIReplyCell.m @@ -29,7 +29,9 @@ self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.selectionStyle = UITableViewCellSelectionStyleNone; - self.backgroundColor = [UIColor whiteColor]; + self.backgroundColor = [UIColor clearColor]; + self.contentView.backgroundColor = [UIColor clearColor]; + [self setupUI]; } return self; diff --git a/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m b/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m index e671a18..6bc58a4 100644 --- a/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m +++ b/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m @@ -541,6 +541,7 @@ popStyle:LSTPopStyleSmoothFromBottom dismissStyle:LSTDismissStyleSmoothToBottom]; customView.popView = popView; + popView.bgColor = [UIColor clearColor]; self.popView = popView; popView.priority = 1000; popView.isAvoidKeyboard = NO;