This commit is contained in:
2026-01-29 15:53:26 +08:00
parent 07a77149fc
commit 766c62f3c0
10 changed files with 890 additions and 18 deletions

View File

@@ -0,0 +1,25 @@
//
// AIPersonInfoVC.h
// keyBoard
//
// Created by Mac on 2026/1/29.
//
#import "BaseViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface AIPersonInfoVC : BaseViewController
/// 背景图 URL
@property (nonatomic, copy) NSString *backgroundImageURL;
/// 人设名称
@property (nonatomic, copy) NSString *personaName;
/// 人设介绍
@property (nonatomic, copy) NSString *personaIntroduction;
/// 人设 ID用于举报等
@property (nonatomic, assign) NSInteger personaId;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,313 @@
//
// AIPersonInfoVC.m
// keyBoard
//
// Created by Mac on 2026/1/29.
//
#import "AIPersonInfoVC.h"
#import "AIReportVC.h"
#import <SDWebImage/SDWebImage.h>
@interface AIPersonInfoVC ()
///
@property (nonatomic, strong) UIImageView *backgroundImageView;
///
@property (nonatomic, strong) UIVisualEffectView *blurEffectView;
///
@property (nonatomic, strong) CAGradientLayer *gradientMaskLayer;
///
@property (nonatomic, strong) UIButton *closeButton;
///
@property (nonatomic, strong) UIButton *moreButton;
///
@property (nonatomic, strong) UIView *reportPopView;
///
@property (nonatomic, strong) UILabel *nameLabel;
///
@property (nonatomic, strong) UILabel *introLabel;
/// Go Chatting
@property (nonatomic, strong) UIButton *goChatButton;
@end
@implementation AIPersonInfoVC
#pragma mark - Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.kb_navView.hidden = YES;
self.view.backgroundColor = [UIColor blackColor];
/// 1
[self setupUI];
/// 2
[self bindActions];
/// 3
[self loadData];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// frame
self.gradientMaskLayer.frame = self.blurEffectView.bounds;
}
#pragma mark - 1
- (void)setupUI {
//
[self.view addSubview:self.backgroundImageView];
[self.backgroundImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
//
[self.view addSubview:self.blurEffectView];
[self.blurEffectView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.equalTo(self.view);
make.height.mas_equalTo(KB_SCREEN_HEIGHT * 0.75);
}];
//
[self.view addSubview:self.closeButton];
[self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(16);
make.top.equalTo(self.view).offset(KB_STATUSBAR_HEIGHT + 10);
make.width.height.mas_equalTo(32);
}];
//
[self.view addSubview:self.moreButton];
[self.moreButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.view).offset(-16);
make.centerY.equalTo(self.closeButton);
make.width.height.mas_equalTo(32);
}];
//
[self.view addSubview:self.nameLabel];
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(20);
make.right.equalTo(self.view).offset(-20);
make.centerY.equalTo(self.view).offset(20);
}];
//
[self.view addSubview:self.introLabel];
[self.introLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(20);
make.right.equalTo(self.view).offset(-20);
make.top.equalTo(self.nameLabel.mas_bottom).offset(16);
}];
// Go Chatting
[self.view addSubview:self.goChatButton];
[self.goChatButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(40);
make.right.equalTo(self.view).offset(-40);
make.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM - 30);
make.height.mas_equalTo(50);
}];
//
[self.view addSubview:self.reportPopView];
self.reportPopView.hidden = YES;
[self.reportPopView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.moreButton.mas_left).offset(8);
make.top.equalTo(self.moreButton.mas_bottom).offset(4);
make.width.mas_equalTo(100);
make.height.mas_equalTo(40);
}];
}
#pragma mark - 2
- (void)bindActions {
//
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBackgroundTap:)];
tap.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tap];
}
#pragma mark - 3
- (void)loadData {
//
if (self.backgroundImageURL.length > 0) {
[self.backgroundImageView sd_setImageWithURL:[NSURL URLWithString:self.backgroundImageURL]
placeholderImage:KBPlaceholderImage];
}
//
self.nameLabel.text = self.personaName ?: @"";
//
self.introLabel.text = self.personaIntroduction ?: @"";
}
#pragma mark - Actions
- (void)closeButtonTapped {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)moreButtonTapped {
self.reportPopView.hidden = !self.reportPopView.hidden;
}
- (void)reportButtonTapped {
self.reportPopView.hidden = YES;
AIReportVC *vc = [[AIReportVC alloc] init];
vc.personaId = self.personaId;
[self.navigationController pushViewController:vc animated:YES];
}
- (void)goChatButtonTapped {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)handleBackgroundTap:(UITapGestureRecognizer *)tap {
CGPoint point = [tap locationInView:self.view];
// moreButton reportPopView
if (!CGRectContainsPoint(self.moreButton.frame, point) &&
!CGRectContainsPoint(self.reportPopView.frame, point)) {
self.reportPopView.hidden = YES;
}
}
#pragma mark - Lazy Load
- (UIImageView *)backgroundImageView {
if (!_backgroundImageView) {
_backgroundImageView = [[UIImageView alloc] init];
_backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
_backgroundImageView.clipsToBounds = YES;
}
return _backgroundImageView;
}
- (UIVisualEffectView *)blurEffectView {
if (!_blurEffectView) {
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
_blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
_blurEffectView.layer.mask = self.gradientMaskLayer;
}
return _blurEffectView;
}
- (CAGradientLayer *)gradientMaskLayer {
if (!_gradientMaskLayer) {
_gradientMaskLayer = [CAGradientLayer layer];
// ->
_gradientMaskLayer.colors = @[
(__bridge id)[UIColor clearColor].CGColor,
(__bridge id)[UIColor whiteColor].CGColor
];
_gradientMaskLayer.startPoint = CGPointMake(0.5, 0);
_gradientMaskLayer.endPoint = CGPointMake(0.5, 0.4);
_gradientMaskLayer.locations = @[@0, @1];
}
return _gradientMaskLayer;
}
- (UIButton *)closeButton {
if (!_closeButton) {
_closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_closeButton setImage:[UIImage imageNamed:@"comment_close_icon"] forState:UIControlStateNormal];
[_closeButton addTarget:self action:@selector(closeButtonTapped) forControlEvents:UIControlEventTouchUpInside];
}
return _closeButton;
}
- (UIButton *)moreButton {
if (!_moreButton) {
_moreButton = [UIButton buttonWithType:UIButtonTypeCustom];
// 使
[_moreButton setImage:[UIImage imageNamed:@"ai_more_icon"] forState:UIControlStateNormal];
if (![UIImage imageNamed:@"ai_more_icon"]) {
// 使
[_moreButton setTitle:@"•••" forState:UIControlStateNormal];
[_moreButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_moreButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightBold];
}
[_moreButton addTarget:self action:@selector(moreButtonTapped) forControlEvents:UIControlEventTouchUpInside];
}
return _moreButton;
}
- (UIView *)reportPopView {
if (!_reportPopView) {
_reportPopView = [[UIView alloc] init];
_reportPopView.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.9];
_reportPopView.layer.cornerRadius = 8;
_reportPopView.clipsToBounds = YES;
//
UIButton *reportBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[reportBtn setImage:[UIImage imageNamed:@"ai_report_icon"] forState:UIControlStateNormal];
[reportBtn setTitle:KBLocalized(@"Report") forState:UIControlStateNormal];
[reportBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
reportBtn.titleLabel.font = [UIFont systemFontOfSize:14];
reportBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
reportBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 8, 0, 0);
reportBtn.titleEdgeInsets = UIEdgeInsetsMake(0, 16, 0, 0);
[reportBtn addTarget:self action:@selector(reportButtonTapped) forControlEvents:UIControlEventTouchUpInside];
[_reportPopView addSubview:reportBtn];
[reportBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(_reportPopView);
}];
}
return _reportPopView;
}
- (UILabel *)nameLabel {
if (!_nameLabel) {
_nameLabel = [[UILabel alloc] init];
_nameLabel.font = [UIFont systemFontOfSize:28 weight:UIFontWeightBold];
_nameLabel.textColor = [UIColor whiteColor];
_nameLabel.textAlignment = NSTextAlignmentLeft;
}
return _nameLabel;
}
- (UILabel *)introLabel {
if (!_introLabel) {
_introLabel = [[UILabel alloc] init];
_introLabel.font = [UIFont systemFontOfSize:14];
_introLabel.textColor = [UIColor colorWithWhite:1.0 alpha:0.8];
_introLabel.textAlignment = NSTextAlignmentLeft;
_introLabel.numberOfLines = 0;
}
return _introLabel;
}
- (UIButton *)goChatButton {
if (!_goChatButton) {
_goChatButton = [UIButton buttonWithType:UIButtonTypeCustom];
//
UIImage *bgImage = [UIImage imageNamed:@"ai_go_chat_bg"];
if (bgImage) {
[_goChatButton setBackgroundImage:bgImage forState:UIControlStateNormal];
} else {
// 使
_goChatButton.backgroundColor = [UIColor colorWithRed:0.8 green:1.0 blue:0.6 alpha:1.0];
_goChatButton.layer.cornerRadius = 25;
}
[_goChatButton setTitle:KBLocalized(@"Go Chatting") forState:UIControlStateNormal];
[_goChatButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_goChatButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
[_goChatButton addTarget:self action:@selector(goChatButtonTapped) forControlEvents:UIControlEventTouchUpInside];
}
return _goChatButton;
}
@end

View File

@@ -0,0 +1,19 @@
//
// AIReportVC.h
// keyBoard
//
// Created by Mac on 2026/1/29.
//
#import "BaseViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface AIReportVC : BaseViewController
/// 被举报的人设 ID
@property (nonatomic, assign) NSInteger personaId;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,160 @@
//
// AIReportVC.m
// keyBoard
//
// Created by Mac on 2026/1/29.
//
#import "AIReportVC.h"
@interface AIReportVC ()
///
@property (nonatomic, strong) NSArray<NSString *> *reportReasons;
///
@property (nonatomic, assign) NSInteger selectedIndex;
/// TableView
@property (nonatomic, strong) UITableView *tableView;
///
@property (nonatomic, strong) UIButton *submitButton;
@end
@implementation AIReportVC
#pragma mark - Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0];
self.kb_titleLabel.text = KBLocalized(@"Report");
self.selectedIndex = -1;
/// 1
[self initData];
/// 2
[self setupUI];
}
#pragma mark - 1
- (void)initData {
self.reportReasons = @[
KBLocalized(@"Inappropriate content"),
KBLocalized(@"Spam or advertising"),
KBLocalized(@"Harassment or bullying"),
KBLocalized(@"False information"),
KBLocalized(@"Intellectual property violation"),
KBLocalized(@"Other")
];
}
#pragma mark - 2
- (void)setupUI {
[self.view addSubview:self.tableView];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.kb_navView.mas_bottom).offset(20);
make.left.right.equalTo(self.view);
make.bottom.equalTo(self.submitButton.mas_top).offset(-20);
}];
[self.view addSubview:self.submitButton];
[self.submitButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(40);
make.right.equalTo(self.view).offset(-40);
make.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM - 30);
make.height.mas_equalTo(50);
}];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.reportReasons.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ReportCell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor clearColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.text = self.reportReasons[indexPath.row];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.font = [UIFont systemFontOfSize:16];
//
if (indexPath.row == self.selectedIndex) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
cell.tintColor = [UIColor colorWithRed:0.8 green:1.0 blue:0.6 alpha:1.0];
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedIndex = indexPath.row;
[tableView reloadData];
//
self.submitButton.enabled = YES;
self.submitButton.alpha = 1.0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 56;
}
#pragma mark - Actions
- (void)submitButtonTapped {
if (self.selectedIndex < 0) {
[KBHUD showError:KBLocalized(@"Please select a reason")];
return;
}
NSString *reason = self.reportReasons[self.selectedIndex];
NSLog(@"[AIReportVC] 举报人设 ID: %ld, 原因: %@", (long)self.personaId, reason);
// TODO:
[KBHUD showSuccess:KBLocalized(@"Report submitted")];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.navigationController popViewControllerAnimated:YES];
});
}
#pragma mark - Lazy Load
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_tableView.backgroundColor = [UIColor clearColor];
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"ReportCell"];
}
return _tableView;
}
- (UIButton *)submitButton {
if (!_submitButton) {
_submitButton = [UIButton buttonWithType:UIButtonTypeCustom];
_submitButton.backgroundColor = [UIColor colorWithRed:0.8 green:1.0 blue:0.6 alpha:1.0];
_submitButton.layer.cornerRadius = 25;
[_submitButton setTitle:KBLocalized(@"Submit") forState:UIControlStateNormal];
[_submitButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_submitButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
_submitButton.enabled = NO;
_submitButton.alpha = 0.5;
[_submitButton addTarget:self action:@selector(submitButtonTapped) forControlEvents:UIControlEventTouchUpInside];
}
return _submitButton;
}
@end