From b556e6841d573c678c0f1530eefe2763409ca14d Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Thu, 29 Jan 2026 16:42:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=BE=E6=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keyBoard.xcodeproj/project.pbxproj | 6 + .../AI/report_nor_icon.imageset/Contents.json | 22 + .../report_nor_icon@2x.png | Bin 0 -> 1511 bytes .../report_nor_icon@3x.png | Bin 0 -> 2853 bytes .../AI/report_sel_icon.imageset/Contents.json | 22 + .../report_sel_icon@2x.png | Bin 0 -> 2528 bytes .../report_sel_icon@3x.png | Bin 0 -> 4572 bytes .../Class/AiTalk/V/Chat/KBPersonaChatCell.m | 6 +- keyBoard/Class/AiTalk/VC/AIPersonInfoVC.m | 8 +- keyBoard/Class/AiTalk/VC/AIReportVC.m | 491 ++++++++++++++++-- keyBoard/Class/AiTalk/VC/KBAIHomeVC.m | 42 ++ 11 files changed, 535 insertions(+), 62 deletions(-) create mode 100644 keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/Contents.json create mode 100644 keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/report_nor_icon@2x.png create mode 100644 keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/report_nor_icon@3x.png create mode 100644 keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/Contents.json create mode 100644 keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/report_sel_icon@2x.png create mode 100644 keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/report_sel_icon@3x.png diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index 54d24fa..20e3648 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -157,6 +157,7 @@ 048FFD422F29F700005D62AE /* KBChatSessionResetModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD412F29F700005D62AE /* KBChatSessionResetModel.m */; }; 048FFD472F2B45D4005D62AE /* AIPersonInfoVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD462F2B45D4005D62AE /* AIPersonInfoVC.m */; }; 048FFD4A2F2B4AE4005D62AE /* KBAICompanionDetailModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD492F2B4AE4005D62AE /* KBAICompanionDetailModel.m */; }; + 048FFD502F2B52E7005D62AE /* AIReportVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD4F2F2B52E7005D62AE /* AIReportVC.m */; }; 0498BD622EDFFC12006CC1D5 /* KBMyVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BD612EDFFC12006CC1D5 /* KBMyVM.m */; }; 0498BD652EE0116D006CC1D5 /* KBEmailLoginVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BD642EE0116D006CC1D5 /* KBEmailLoginVC.m */; }; 0498BD682EE01180006CC1D5 /* KBEmailRegistVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BD672EE01180006CC1D5 /* KBEmailRegistVC.m */; }; @@ -583,6 +584,8 @@ 048FFD462F2B45D4005D62AE /* AIPersonInfoVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIPersonInfoVC.m; sourceTree = ""; }; 048FFD482F2B4AE4005D62AE /* KBAICompanionDetailModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAICompanionDetailModel.h; sourceTree = ""; }; 048FFD492F2B4AE4005D62AE /* KBAICompanionDetailModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAICompanionDetailModel.m; sourceTree = ""; }; + 048FFD4E2F2B52E7005D62AE /* AIReportVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIReportVC.h; sourceTree = ""; }; + 048FFD4F2F2B52E7005D62AE /* AIReportVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIReportVC.m; sourceTree = ""; }; 0498BD5E2EDF2157006CC1D5 /* KBBizCode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBBizCode.h; sourceTree = ""; }; 0498BD602EDFFC12006CC1D5 /* KBMyVM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBMyVM.h; sourceTree = ""; }; 0498BD612EDFFC12006CC1D5 /* KBMyVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyVM.m; sourceTree = ""; }; @@ -1093,6 +1096,8 @@ 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */, 048FFD452F2B45D4005D62AE /* AIPersonInfoVC.h */, 048FFD462F2B45D4005D62AE /* AIPersonInfoVC.m */, + 048FFD4E2F2B52E7005D62AE /* AIReportVC.h */, + 048FFD4F2F2B52E7005D62AE /* AIReportVC.m */, ); path = VC; sourceTree = ""; @@ -2460,6 +2465,7 @@ 0498BD852EE1B255006CC1D5 /* KBSignUtils.m in Sources */, 0477BDF72EBC63A80055D639 /* KBTestVC.m in Sources */, 04122F7E2EC5FC5500EF7AB3 /* KBJfPayCell.m in Sources */, + 048FFD502F2B52E7005D62AE /* AIReportVC.m in Sources */, 049FB2402EC4B6EF00FAB05D /* KBULBridgeNotification.m in Sources */, 04FC95C92EB1E4C9007BD342 /* BaseNavigationController.m in Sources */, 048908DD2EBF67EB00FABA60 /* KBSearchResultVC.m in Sources */, diff --git a/keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/Contents.json new file mode 100644 index 0000000..81e2f09 --- /dev/null +++ b/keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "report_nor_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "report_nor_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/report_nor_icon@2x.png b/keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/report_nor_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ee30e1c45b72d1a41fb80c59b0dd08e35559da09 GIT binary patch literal 1511 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 D0ft{T literal 0 HcmV?d00001 diff --git a/keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/Contents.json new file mode 100644 index 0000000..ed29372 --- /dev/null +++ b/keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "report_sel_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "report_sel_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/report_sel_icon@2x.png b/keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/report_sel_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3e32d198dfb434aeb097eaabd0ba90e680cb1cab GIT binary patch literal 2528 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 +#import "AIReportVC.h" @interface AIPersonInfoVC () @@ -204,9 +204,9 @@ - (void)reportButtonTapped { self.reportPopView.hidden = YES; -// AIReportVC *vc = [[AIReportVC alloc] init]; -// vc.personaId = self.companionId; -// [self.navigationController pushViewController:vc animated:YES]; + AIReportVC *vc = [[AIReportVC alloc] init]; + vc.personaId = self.companionId; + [self.navigationController pushViewController:vc animated:YES]; } - (void)goChatButtonTapped { diff --git a/keyBoard/Class/AiTalk/VC/AIReportVC.m b/keyBoard/Class/AiTalk/VC/AIReportVC.m index 490b2d2..e42e070 100644 --- a/keyBoard/Class/AiTalk/VC/AIReportVC.m +++ b/keyBoard/Class/AiTalk/VC/AIReportVC.m @@ -7,14 +7,112 @@ #import "AIReportVC.h" -@interface AIReportVC () +#pragma mark - AIReportOptionCell +@interface AIReportOptionCell : UITableViewCell + +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UIButton *selectButton; +@property (nonatomic, assign) BOOL isSelectedOption; + +@end + +@implementation AIReportOptionCell + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.backgroundColor = [UIColor clearColor]; + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self setupUI]; + } + return self; +} + +- (void)setupUI { + [self.contentView addSubview:self.titleLabel]; + [self.contentView addSubview:self.selectButton]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView).offset(16); + make.centerY.equalTo(self.contentView); + make.right.lessThanOrEqualTo(self.selectButton.mas_left).offset(-10); + }]; + + [self.selectButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.contentView).offset(-16); + make.centerY.equalTo(self.contentView); + make.width.height.mas_equalTo(24); + }]; +} + +- (void)setIsSelectedOption:(BOOL)isSelectedOption { + _isSelectedOption = isSelectedOption; + self.selectButton.selected = isSelectedOption; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:14]; + _titleLabel.textColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0]; + } + return _titleLabel; +} + +- (UIButton *)selectButton { + if (!_selectButton) { + _selectButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_selectButton setImage:[UIImage imageNamed:@"report_nor_icon"] forState:UIControlStateNormal]; + [_selectButton setImage:[UIImage imageNamed:@"report_sel_icon"] forState:UIControlStateSelected]; + _selectButton.userInteractionEnabled = NO; + } + return _selectButton; +} + +@end + +#pragma mark - AIReportVC + +@interface AIReportVC () + +/// 滚动容器 +@property (nonatomic, strong) UIScrollView *scrollView; +/// 内容容器 +@property (nonatomic, strong) UIView *contentView; + +/// 举报原因卡片 +@property (nonatomic, strong) UIView *reasonCardView; +/// 举报原因标题 +@property (nonatomic, strong) UILabel *reasonTitleLabel; /// 举报原因列表 +@property (nonatomic, strong) UITableView *reasonTableView; +/// 举报原因数据 @property (nonatomic, strong) NSArray *reportReasons; -/// 当前选中的索引 -@property (nonatomic, assign) NSInteger selectedIndex; -/// 举报原因 TableView -@property (nonatomic, strong) UITableView *tableView; +/// 选中的举报原因索引集合 +@property (nonatomic, strong) NSMutableSet *selectedReasonIndexes; + +/// 选择内容卡片 +@property (nonatomic, strong) UIView *contentCardView; +/// 选择内容标题 +@property (nonatomic, strong) UILabel *contentTitleLabel; +/// 选择内容列表 +@property (nonatomic, strong) UITableView *contentTableView; +/// 选择内容数据 +@property (nonatomic, strong) NSArray *contentOptions; +/// 选中的内容索引集合 +@property (nonatomic, strong) NSMutableSet *selectedContentIndexes; + +/// 举报描述卡片 +@property (nonatomic, strong) UIView *descriptionCardView; +/// 举报描述标题 +@property (nonatomic, strong) UILabel *descriptionTitleLabel; +/// 举报描述输入框 +@property (nonatomic, strong) UITextView *descriptionTextView; +/// 占位符标签 +@property (nonatomic, strong) UILabel *placeholderLabel; +/// 字数统计标签 +@property (nonatomic, strong) UILabel *countLabel; + /// 提交按钮 @property (nonatomic, strong) UIButton *submitButton; @@ -27,68 +125,186 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.view.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0]; + self.view.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.0]; self.kb_titleLabel.text = KBLocalized(@"Report"); - self.selectedIndex = -1; /// 1:初始化数据 [self initData]; /// 2:控件初始化 [self setupUI]; + /// 3:绑定事件 + [self bindActions]; } #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") + KBLocalized(@"Pornographic And Vulgar"), + KBLocalized(@"Politically Sensitive"), + KBLocalized(@"Insult Attacks"), + KBLocalized(@"Bloody Violence"), + KBLocalized(@"Suicide And Self Harm"), + KBLocalized(@"Plagiarism Infringement"), + KBLocalized(@"Invasion Of Privacy"), + KBLocalized(@"False Rumor"), + KBLocalized(@"Other Harmful Information") ]; + + self.contentOptions = @[ + KBLocalized(@"Character Name And Description"), + KBLocalized(@"Picture"), + KBLocalized(@"Timbre") + ]; + + self.selectedReasonIndexes = [NSMutableSet set]; + self.selectedContentIndexes = [NSMutableSet set]; } #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); - }]; - + // 先添加提交按钮(因为 scrollView 的约束依赖它) [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.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM - 20); make.height.mas_equalTo(50); }]; + + [self.view addSubview:self.scrollView]; + [self.scrollView addSubview:self.contentView]; + + [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.kb_navView.mas_bottom); + make.left.right.equalTo(self.view); + make.bottom.equalTo(self.submitButton.mas_top).offset(-10); + }]; + + [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.scrollView); + make.width.equalTo(self.scrollView); + }]; + + // 举报原因卡片 + [self.contentView addSubview:self.reasonCardView]; + [self.reasonCardView addSubview:self.reasonTitleLabel]; + [self.reasonCardView addSubview:self.reasonTableView]; + + [self.reasonCardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.contentView).offset(16); + make.left.equalTo(self.contentView).offset(16); + make.right.equalTo(self.contentView).offset(-16); + }]; + + [self.reasonTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.reasonCardView).offset(16); + make.centerX.equalTo(self.reasonCardView); + }]; + + CGFloat reasonTableHeight = self.reportReasons.count * 44; + [self.reasonTableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.reasonTitleLabel.mas_bottom).offset(8); + make.left.right.equalTo(self.reasonCardView); + make.height.mas_equalTo(reasonTableHeight); + make.bottom.equalTo(self.reasonCardView).offset(-8); + }]; + + // 选择内容卡片 + [self.contentView addSubview:self.contentCardView]; + [self.contentCardView addSubview:self.contentTitleLabel]; + [self.contentCardView addSubview:self.contentTableView]; + + [self.contentCardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.reasonCardView.mas_bottom).offset(16); + make.left.equalTo(self.contentView).offset(16); + make.right.equalTo(self.contentView).offset(-16); + }]; + + [self.contentTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.contentCardView).offset(16); + make.centerX.equalTo(self.contentCardView); + }]; + + CGFloat contentTableHeight = self.contentOptions.count * 44; + [self.contentTableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.contentTitleLabel.mas_bottom).offset(8); + make.left.right.equalTo(self.contentCardView); + make.height.mas_equalTo(contentTableHeight); + make.bottom.equalTo(self.contentCardView).offset(-8); + }]; + + // 举报描述卡片 + [self.contentView addSubview:self.descriptionCardView]; + [self.descriptionCardView addSubview:self.descriptionTitleLabel]; + [self.descriptionCardView addSubview:self.descriptionTextView]; + [self.descriptionCardView addSubview:self.placeholderLabel]; + [self.descriptionCardView addSubview:self.countLabel]; + + [self.descriptionCardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.contentCardView.mas_bottom).offset(16); + make.left.equalTo(self.contentView).offset(16); + make.right.equalTo(self.contentView).offset(-16); + make.bottom.equalTo(self.contentView).offset(-16); + }]; + + [self.descriptionTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.descriptionCardView).offset(16); + make.centerX.equalTo(self.descriptionCardView); + }]; + + [self.descriptionTextView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.descriptionTitleLabel.mas_bottom).offset(12); + make.left.equalTo(self.descriptionCardView).offset(12); + make.right.equalTo(self.descriptionCardView).offset(-12); + make.height.mas_equalTo(100); + make.bottom.equalTo(self.descriptionCardView).offset(-30); + }]; + + [self.placeholderLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.descriptionTextView).offset(8); + make.left.equalTo(self.descriptionTextView).offset(5); + make.right.equalTo(self.descriptionTextView).offset(-5); + }]; + + [self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.descriptionCardView).offset(-16); + make.bottom.equalTo(self.descriptionCardView).offset(-8); + }]; +} + +#pragma mark - 3:绑定事件 + +- (void)bindActions { + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)]; + tap.cancelsTouchesInView = NO; + [self.view addGestureRecognizer:tap]; +} + +- (void)dismissKeyboard { + [self.view endEditing:YES]; } #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.reportReasons.count; + if (tableView == self.reasonTableView) { + return self.reportReasons.count; + } else { + return self.contentOptions.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]; + AIReportOptionCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AIReportOptionCell" forIndexPath:indexPath]; - // 选中状态 - if (indexPath.row == self.selectedIndex) { - cell.accessoryType = UITableViewCellAccessoryCheckmark; - cell.tintColor = [UIColor colorWithRed:0.8 green:1.0 blue:0.6 alpha:1.0]; + if (tableView == self.reasonTableView) { + cell.titleLabel.text = self.reportReasons[indexPath.row]; + cell.isSelectedOption = [self.selectedReasonIndexes containsObject:@(indexPath.row)]; } else { - cell.accessoryType = UITableViewCellAccessoryNone; + cell.titleLabel.text = self.contentOptions[indexPath.row]; + cell.isSelectedOption = [self.selectedContentIndexes containsObject:@(indexPath.row)]; } return cell; @@ -97,28 +313,72 @@ #pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - self.selectedIndex = indexPath.row; - [tableView reloadData]; + NSMutableSet *selectedSet; - // 更新提交按钮状态 - self.submitButton.enabled = YES; - self.submitButton.alpha = 1.0; + if (tableView == self.reasonTableView) { + selectedSet = self.selectedReasonIndexes; + } else { + selectedSet = self.selectedContentIndexes; + } + + NSNumber *indexNum = @(indexPath.row); + if ([selectedSet containsObject:indexNum]) { + [selectedSet removeObject:indexNum]; + } else { + [selectedSet addObject:indexNum]; + } + + [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - return 56; + return 44; +} + +#pragma mark - UITextViewDelegate + +- (void)textViewDidChange:(UITextView *)textView { + self.placeholderLabel.hidden = textView.text.length > 0; + + // 限制 200 字 + if (textView.text.length > 200) { + textView.text = [textView.text substringToIndex:200]; + } + + self.countLabel.text = [NSString stringWithFormat:@"%ld/200", (long)textView.text.length]; } #pragma mark - Actions - (void)submitButtonTapped { - if (self.selectedIndex < 0) { - [KBHUD showError:KBLocalized(@"Please select a reason")]; + if (self.selectedReasonIndexes.count == 0) { + [KBHUD showError:KBLocalized(@"Please select at least one report reason")]; return; } - NSString *reason = self.reportReasons[self.selectedIndex]; - NSLog(@"[AIReportVC] 举报人设 ID: %ld, 原因: %@", (long)self.personaId, reason); + if (self.selectedContentIndexes.count == 0) { + [KBHUD showError:KBLocalized(@"Please select at least one content type")]; + return; + } + + // 收集选中的举报原因 + NSMutableArray *selectedReasons = [NSMutableArray array]; + for (NSNumber *index in self.selectedReasonIndexes) { + [selectedReasons addObject:self.reportReasons[index.integerValue]]; + } + + // 收集选中的内容类型 + NSMutableArray *selectedContents = [NSMutableArray array]; + for (NSNumber *index in self.selectedContentIndexes) { + [selectedContents addObject:self.contentOptions[index.integerValue]]; + } + + NSString *description = self.descriptionTextView.text ?: @""; + + NSLog(@"[AIReportVC] 举报人设 ID: %ld", (long)self.personaId); + NSLog(@"[AIReportVC] 举报原因: %@", selectedReasons); + NSLog(@"[AIReportVC] 内容类型: %@", selectedContents); + NSLog(@"[AIReportVC] 描述: %@", description); // TODO: 调用举报接口 [KBHUD showSuccess:KBLocalized(@"Report submitted")]; @@ -130,28 +390,147 @@ #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"]; +- (UIScrollView *)scrollView { + if (!_scrollView) { + _scrollView = [[UIScrollView alloc] init]; + _scrollView.showsVerticalScrollIndicator = NO; + _scrollView.alwaysBounceVertical = YES; } - return _tableView; + return _scrollView; +} + +- (UIView *)contentView { + if (!_contentView) { + _contentView = [[UIView alloc] init]; + } + return _contentView; +} + +- (UIView *)reasonCardView { + if (!_reasonCardView) { + _reasonCardView = [[UIView alloc] init]; + _reasonCardView.backgroundColor = [UIColor whiteColor]; + _reasonCardView.layer.cornerRadius = 12; + } + return _reasonCardView; +} + +- (UILabel *)reasonTitleLabel { + if (!_reasonTitleLabel) { + _reasonTitleLabel = [[UILabel alloc] init]; + _reasonTitleLabel.text = KBLocalized(@"Report reason"); + _reasonTitleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + _reasonTitleLabel.textColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0]; + } + return _reasonTitleLabel; +} + +- (UITableView *)reasonTableView { + if (!_reasonTableView) { + _reasonTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _reasonTableView.backgroundColor = [UIColor clearColor]; + _reasonTableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _reasonTableView.scrollEnabled = NO; + _reasonTableView.delegate = self; + _reasonTableView.dataSource = self; + [_reasonTableView registerClass:[AIReportOptionCell class] forCellReuseIdentifier:@"AIReportOptionCell"]; + } + return _reasonTableView; +} + +- (UIView *)contentCardView { + if (!_contentCardView) { + _contentCardView = [[UIView alloc] init]; + _contentCardView.backgroundColor = [UIColor whiteColor]; + _contentCardView.layer.cornerRadius = 12; + } + return _contentCardView; +} + +- (UILabel *)contentTitleLabel { + if (!_contentTitleLabel) { + _contentTitleLabel = [[UILabel alloc] init]; + _contentTitleLabel.text = KBLocalized(@"selection content"); + _contentTitleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + _contentTitleLabel.textColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0]; + } + return _contentTitleLabel; +} + +- (UITableView *)contentTableView { + if (!_contentTableView) { + _contentTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _contentTableView.backgroundColor = [UIColor clearColor]; + _contentTableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _contentTableView.scrollEnabled = NO; + _contentTableView.delegate = self; + _contentTableView.dataSource = self; + [_contentTableView registerClass:[AIReportOptionCell class] forCellReuseIdentifier:@"AIReportOptionCell"]; + } + return _contentTableView; +} + +- (UIView *)descriptionCardView { + if (!_descriptionCardView) { + _descriptionCardView = [[UIView alloc] init]; + _descriptionCardView.backgroundColor = [UIColor whiteColor]; + _descriptionCardView.layer.cornerRadius = 12; + } + return _descriptionCardView; +} + +- (UILabel *)descriptionTitleLabel { + if (!_descriptionTitleLabel) { + _descriptionTitleLabel = [[UILabel alloc] init]; + _descriptionTitleLabel.text = KBLocalized(@"Report description"); + _descriptionTitleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + _descriptionTitleLabel.textColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0]; + } + return _descriptionTitleLabel; +} + +- (UITextView *)descriptionTextView { + if (!_descriptionTextView) { + _descriptionTextView = [[UITextView alloc] init]; + _descriptionTextView.font = [UIFont systemFontOfSize:14]; + _descriptionTextView.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1.0]; + _descriptionTextView.backgroundColor = [UIColor colorWithRed:0.96 green:0.96 blue:0.96 alpha:1.0]; + _descriptionTextView.layer.cornerRadius = 8; + _descriptionTextView.delegate = self; + _descriptionTextView.textContainerInset = UIEdgeInsetsMake(8, 4, 8, 4); + } + return _descriptionTextView; +} + +- (UILabel *)placeholderLabel { + if (!_placeholderLabel) { + _placeholderLabel = [[UILabel alloc] init]; + _placeholderLabel.text = KBLocalized(@"Please describe the specific reason for your report."); + _placeholderLabel.font = [UIFont systemFontOfSize:14]; + _placeholderLabel.textColor = [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1.0]; + _placeholderLabel.numberOfLines = 0; + } + return _placeholderLabel; +} + +- (UILabel *)countLabel { + if (!_countLabel) { + _countLabel = [[UILabel alloc] init]; + _countLabel.text = @"0/200"; + _countLabel.font = [UIFont systemFontOfSize:12]; + _countLabel.textColor = [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1.0]; + } + return _countLabel; } - (UIButton *)submitButton { if (!_submitButton) { _submitButton = [UIButton buttonWithType:UIButtonTypeCustom]; - _submitButton.backgroundColor = [UIColor colorWithRed:0.8 green:1.0 blue:0.6 alpha:1.0]; + _submitButton.backgroundColor = [UIColor colorWithRed:0.0 green:0.75 blue:0.67 alpha:1.0]; _submitButton.layer.cornerRadius = 25; [_submitButton setTitle:KBLocalized(@"Submit") forState:UIControlStateNormal]; - [_submitButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [_submitButton setTitleColor:[UIColor whiteColor] 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; diff --git a/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m b/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m index c4e9ee7..586248b 100644 --- a/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m +++ b/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m @@ -31,6 +31,8 @@ @property (nonatomic, assign) CGFloat voiceInputBarHeight; @property (nonatomic, assign) CGFloat baseInputBarBottomSpacing; @property (nonatomic, assign) CGFloat currentKeyboardHeight; +/// 仅用于标记“由 KBVoiceInputBar 触发的键盘”是否处于激活态 +@property (nonatomic, assign) BOOL voiceInputKeyboardActive; @property (nonatomic, strong) UITapGestureRecognizer *dismissKeyboardTap; @property (nonatomic, weak) LSTPopView *chatLimitPopView; @@ -76,6 +78,31 @@ @implementation KBAIHomeVC +#pragma mark - Keyboard Gate + +/// 查找当前 view 树里的 firstResponder +- (UIView *)kb_findFirstResponderInView:(UIView *)view { + if ([view isFirstResponder]) { + return view; + } + for (UIView *sub in view.subviews) { + UIView *found = [self kb_findFirstResponderInView:sub]; + if (found) { + return found; + } + } + return nil; +} + +/// 仅允许 KBVoiceInputBar 触发键盘联动(避免评论输入等场景误触发) +- (BOOL)kb_isKeyboardFromVoiceInputBar { + UIView *firstResponder = [self kb_findFirstResponderInView:self.view]; + if (!firstResponder) { + return NO; + } + return [firstResponder isDescendantOfView:self.voiceInputBar]; +} + #pragma mark - Lifecycle - (void)viewDidLoad { @@ -353,6 +380,21 @@ // 将键盘的 frame 转换到当前 view 的坐标系 CGRect convertedFrame = [self.view convertRect:endFrame fromView:nil]; CGFloat keyboardHeight = MAX(0.0, CGRectGetMaxY(self.view.bounds) - CGRectGetMinY(convertedFrame)); + + // Gate:只让 KBVoiceInputBar 触发聊天区域的联动(评论输入等场景会误触发) + if (keyboardHeight > 0.0) { + if (![self kb_isKeyboardFromVoiceInputBar]) { + return; + } + self.voiceInputKeyboardActive = YES; + } else { + // 键盘收起时:只有之前是由 KBVoiceInputBar 触发的,才需要恢复 + if (!self.voiceInputKeyboardActive) { + return; + } + self.voiceInputKeyboardActive = NO; + } + self.currentKeyboardHeight = keyboardHeight; NSLog(@"[KBAIHomeVC] 键盘高度: %.2f, 屏幕高度: %.2f, 键盘 Y: %.2f",