Files
keyboard/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m
2026-01-26 16:53:41 +08:00

225 lines
7.0 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// KBPersonaChatCell.m
// keyBoard
//
// Created by Kiro on 2026/1/26.
//
#import "KBPersonaChatCell.h"
#import "KBChatTableView.h"
#import "KBAiChatMessage.h"
#import <Masonry/Masonry.h>
#import <SDWebImage/SDWebImage.h>
@interface KBPersonaChatCell () <UITableViewDelegate, UITableViewDataSource>
/// 背景图
@property (nonatomic, strong) UIImageView *backgroundImageView;
/// 头像
@property (nonatomic, strong) UIImageView *avatarImageView;
/// 人设名称
@property (nonatomic, strong) UILabel *nameLabel;
/// 开场白
@property (nonatomic, strong) UILabel *openingLabel;
/// 聊天列表
@property (nonatomic, strong) UITableView *tableView;
/// 聊天消息
@property (nonatomic, strong) NSMutableArray<KBAiChatMessage *> *messages;
/// 是否已加载数据
@property (nonatomic, assign) BOOL hasLoadedData;
@end
@implementation KBPersonaChatCell
#pragma mark - Lifecycle
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setupUI];
}
return self;
}
#pragma mark - 1控件初始化
- (void)setupUI {
// 背景图
[self.contentView addSubview:self.backgroundImageView];
[self.backgroundImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.contentView);
}];
// 半透明遮罩
UIView *maskView = [[UIView alloc] init];
maskView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.3];
[self.contentView addSubview:maskView];
[maskView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.contentView);
}];
// 头像
[self.contentView addSubview:self.avatarImageView];
[self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentView).offset(80);
make.centerX.equalTo(self.contentView);
make.size.mas_equalTo(CGSizeMake(80, 80));
}];
// 人设名称
[self.contentView addSubview:self.nameLabel];
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.avatarImageView.mas_bottom).offset(12);
make.centerX.equalTo(self.contentView);
}];
// 开场白
[self.contentView addSubview:self.openingLabel];
[self.openingLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.nameLabel.mas_bottom).offset(8);
make.left.equalTo(self.contentView).offset(40);
make.right.equalTo(self.contentView).offset(-40);
}];
// 聊天列表
[self.contentView addSubview:self.tableView];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.openingLabel.mas_bottom).offset(30);
make.left.right.bottom.equalTo(self.contentView);
}];
}
#pragma mark - Setter
- (void)setPersona:(KBPersonaModel *)persona {
_persona = persona;
// 重置状态
self.hasLoadedData = NO;
self.messages = [NSMutableArray array];
// 设置 UI
[self.backgroundImageView sd_setImageWithURL:[NSURL URLWithString:persona.coverImageUrl]
placeholderImage:[UIImage imageNamed:@"placeholder_bg"]];
[self.avatarImageView sd_setImageWithURL:[NSURL URLWithString:persona.avatarUrl]
placeholderImage:[UIImage imageNamed:@"placeholder_avatar"]];
self.nameLabel.text = persona.name;
self.openingLabel.text = persona.shortDesc.length > 0 ? persona.shortDesc : persona.introText;
[self.tableView reloadData];
}
#pragma mark - 2数据加载
- (void)preloadDataIfNeeded {
if (self.hasLoadedData) {
return;
}
// TODO: 这里后续需要用 chatId 去请求聊天记录
// 目前先添加开场白作为第一条消息
self.hasLoadedData = YES;
if (self.persona.introText.length > 0) {
KBAiChatMessage *openingMsg = [KBAiChatMessage assistantMessageWithText:self.persona.introText];
openingMsg.isComplete = YES;
[self.messages addObject:openingMsg];
[self.tableView reloadData];
}
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.messages.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.numberOfLines = 0;
}
KBAiChatMessage *message = self.messages[indexPath.row];
cell.textLabel.text = message.text;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
#pragma mark - Lazy Load
- (UIImageView *)backgroundImageView {
if (!_backgroundImageView) {
_backgroundImageView = [[UIImageView alloc] init];
_backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
_backgroundImageView.clipsToBounds = YES;
}
return _backgroundImageView;
}
- (UIImageView *)avatarImageView {
if (!_avatarImageView) {
_avatarImageView = [[UIImageView alloc] init];
_avatarImageView.contentMode = UIViewContentModeScaleAspectFill;
_avatarImageView.layer.cornerRadius = 40;
_avatarImageView.layer.borderWidth = 3;
_avatarImageView.layer.borderColor = [UIColor whiteColor].CGColor;
_avatarImageView.clipsToBounds = YES;
}
return _avatarImageView;
}
- (UILabel *)nameLabel {
if (!_nameLabel) {
_nameLabel = [[UILabel alloc] init];
_nameLabel.font = [UIFont boldSystemFontOfSize:20];
_nameLabel.textColor = [UIColor whiteColor];
_nameLabel.textAlignment = NSTextAlignmentCenter;
}
return _nameLabel;
}
- (UILabel *)openingLabel {
if (!_openingLabel) {
_openingLabel = [[UILabel alloc] init];
_openingLabel.font = [UIFont systemFontOfSize:14];
_openingLabel.textColor = [[UIColor whiteColor] colorWithAlphaComponent:0.9];
_openingLabel.textAlignment = NSTextAlignmentCenter;
_openingLabel.numberOfLines = 2;
}
return _openingLabel;
}
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_tableView.backgroundColor = [UIColor clearColor];
_tableView.showsVerticalScrollIndicator = NO;
_tableView.estimatedRowHeight = 60;
_tableView.rowHeight = UITableViewAutomaticDimension;
if (@available(iOS 11.0, *)) {
_tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
}
return _tableView;
}
@end