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 0000000..ee30e1c Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/report_nor_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/report_nor_icon@3x.png b/keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/report_nor_icon@3x.png new file mode 100644 index 0000000..c51b18c Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/report_nor_icon.imageset/report_nor_icon@3x.png differ 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 0000000..3e32d19 Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/report_sel_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/report_sel_icon@3x.png b/keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/report_sel_icon@3x.png new file mode 100644 index 0000000..f86ac7b Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/report_sel_icon.imageset/report_sel_icon@3x.png differ diff --git a/keyBoard/Class/AiTalk/V/Chat/KBPersonaChatCell.m b/keyBoard/Class/AiTalk/V/Chat/KBPersonaChatCell.m index 87efc61..c49aba7 100644 --- a/keyBoard/Class/AiTalk/V/Chat/KBPersonaChatCell.m +++ b/keyBoard/Class/AiTalk/V/Chat/KBPersonaChatCell.m @@ -717,7 +717,7 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe [self.popView dismiss]; } - CGFloat customViewHeight = KB_SCREEN_HEIGHT * 0.8; + CGFloat customViewHeight = KB_SCREEN_HEIGHT * 0.7; KBAICommentView *customView = [[KBAICommentView alloc] initWithFrame:CGRectMake(0, 0, KB_SCREEN_WIDTH, customViewHeight)]; @@ -745,7 +745,9 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe popView.sweepStyle = LSTSweepStyleY_Positive; popView.swipeVelocity = 1600; popView.sweepDismissStyle = LSTSweepDismissStyleSmooth; - + popView.bgClickBlock = ^{ + [KB_CURRENT_NAV.view endEditing:true]; + }; [popView pop]; } diff --git a/keyBoard/Class/AiTalk/VC/AIPersonInfoVC.m b/keyBoard/Class/AiTalk/VC/AIPersonInfoVC.m index 3e3d2d4..27eb6db 100644 --- a/keyBoard/Class/AiTalk/VC/AIPersonInfoVC.m +++ b/keyBoard/Class/AiTalk/VC/AIPersonInfoVC.m @@ -6,10 +6,10 @@ // #import "AIPersonInfoVC.h" -//#import "AIReportVC.h" #import "AiVM.h" #import "KBAICompanionDetailModel.h" #import +#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",