diff --git a/Shared/Localization/en.lproj/Localizable.strings b/Shared/Localization/en.lproj/Localizable.strings index 7708622..b27bad7 100644 --- a/Shared/Localization/en.lproj/Localizable.strings +++ b/Shared/Localization/en.lproj/Localizable.strings @@ -99,6 +99,9 @@ "E-mail" = "E-mail"; "Agreement" = "Agreement"; "Privacy Policy" = "Privacy Policy"; +"Notice" = "Notice"; +"Feedback" = "Feedback"; + // Search & history "Clear history" = "Clear history"; diff --git a/Shared/Localization/zh-Hans.lproj/Localizable.strings b/Shared/Localization/zh-Hans.lproj/Localizable.strings index 1fad9ef..0a6525c 100644 --- a/Shared/Localization/zh-Hans.lproj/Localizable.strings +++ b/Shared/Localization/zh-Hans.lproj/Localizable.strings @@ -100,6 +100,8 @@ "E-mail" = "邮箱"; "Agreement" = "协议"; "Privacy Policy" = "隐私政策"; +"Notice" = "通知"; +"Feedback" = "反馈"; // 搜索与历史(英文 key) "Clear history" = "清空历史"; diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index 5558b09..e70a9a5 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -48,6 +48,8 @@ 0477BEA22EBCF0000055D639 /* KBTopImageButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BEA12EBCF0000055D639 /* KBTopImageButton.m */; }; 04791F8E2ED469C0004E8522 /* KBHostAppLauncher.m in Sources */ = {isa = PBXBuildFile; fileRef = 04791F8D2ED469C0004E8522 /* KBHostAppLauncher.m */; }; 04791F8F2ED469C0004E8522 /* KBHostAppLauncher.m in Sources */ = {isa = PBXBuildFile; fileRef = 04791F8D2ED469C0004E8522 /* KBHostAppLauncher.m */; }; + 04791F922ED48010004E8522 /* KBNoticeVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04791F912ED48010004E8522 /* KBNoticeVC.m */; }; + 04791F952ED48028004E8522 /* KBFeedBackVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04791F942ED48028004E8522 /* KBFeedBackVC.m */; }; 047C650D2EBC8A840035E841 /* KBPanModalView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650C2EBC8A840035E841 /* KBPanModalView.m */; }; 047C65102EBCA8DD0035E841 /* HomeRankContentVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650F2EBCA8DD0035E841 /* HomeRankContentVC.m */; }; 047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C654F2EBCBA9E0035E841 /* KBShopVC.m */; }; @@ -252,6 +254,10 @@ 0477BEA12EBCF0000055D639 /* KBTopImageButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBTopImageButton.m; sourceTree = ""; }; 04791F8C2ED469C0004E8522 /* KBHostAppLauncher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBHostAppLauncher.h; sourceTree = ""; }; 04791F8D2ED469C0004E8522 /* KBHostAppLauncher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBHostAppLauncher.m; sourceTree = ""; }; + 04791F902ED48010004E8522 /* KBNoticeVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBNoticeVC.h; sourceTree = ""; }; + 04791F912ED48010004E8522 /* KBNoticeVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBNoticeVC.m; sourceTree = ""; }; + 04791F932ED48028004E8522 /* KBFeedBackVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFeedBackVC.h; sourceTree = ""; }; + 04791F942ED48028004E8522 /* KBFeedBackVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFeedBackVC.m; sourceTree = ""; }; 047C650B2EBC8A840035E841 /* KBPanModalView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPanModalView.h; sourceTree = ""; }; 047C650C2EBC8A840035E841 /* KBPanModalView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPanModalView.m; sourceTree = ""; }; 047C650E2EBCA8DD0035E841 /* HomeRankContentVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRankContentVC.h; sourceTree = ""; }; @@ -1056,6 +1062,10 @@ 048908E22EBF821700FABA60 /* KBSkinDetailVC.m */, 049FB2212EC311F900FAB05D /* KBPersonInfoVC.h */, 049FB2222EC311F900FAB05D /* KBPersonInfoVC.m */, + 04791F902ED48010004E8522 /* KBNoticeVC.h */, + 04791F912ED48010004E8522 /* KBNoticeVC.m */, + 04791F932ED48028004E8522 /* KBFeedBackVC.h */, + 04791F942ED48028004E8522 /* KBFeedBackVC.m */, ); path = VC; sourceTree = ""; @@ -1569,6 +1579,7 @@ 049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */, 048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */, 048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */, + 04791F952ED48028004E8522 /* KBFeedBackVC.m in Sources */, 04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */, 04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */, 04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */, @@ -1626,6 +1637,7 @@ 04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */, 049FB2232EC311F900FAB05D /* KBPersonInfoVC.m in Sources */, 048908FE2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m in Sources */, + 04791F922ED48010004E8522 /* KBNoticeVC.m in Sources */, 04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */, 04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */, 049FB2112EC1F72F00FAB05D /* KBMyListCell.m in Sources */, diff --git a/keyBoard/Class/Me/VC/KBFeedBackVC.h b/keyBoard/Class/Me/VC/KBFeedBackVC.h new file mode 100644 index 0000000..c2b9f47 --- /dev/null +++ b/keyBoard/Class/Me/VC/KBFeedBackVC.h @@ -0,0 +1,16 @@ +// +// KBFeedBackVC.h +// keyBoard +// +// Created by Mac on 2025/11/24. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBFeedBackVC : BaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Me/VC/KBFeedBackVC.m b/keyBoard/Class/Me/VC/KBFeedBackVC.m new file mode 100644 index 0000000..fa98f25 --- /dev/null +++ b/keyBoard/Class/Me/VC/KBFeedBackVC.m @@ -0,0 +1,164 @@ +#import "KBFeedBackVC.h" +#import + +@interface KBFeedBackVC () + +/// 输入卡片容器视图 +@property (nonatomic, strong) UIView *inputCardView; +/// 文本输入框 +@property (nonatomic, strong) UITextView *textView; +/// 占位提示标签:“Please Enter The Content” +@property (nonatomic, strong) UILabel *placeholderLabel; +/// 右下角字数统计 “0/100” +@property (nonatomic, strong) UILabel *countLabel; +/// 底部提交按钮 +@property (nonatomic, strong) UIButton *commitButton; + +/// 最大输入字数 +@property (nonatomic, assign) NSInteger maxCount; + +@end + +@implementation KBFeedBackVC + +- (void)viewDidLoad { + [super viewDidLoad]; + // 背景色与其他设置页一致 + self.view.backgroundColor = [UIColor colorWithWhite:0.97 alpha:1.0]; + self.kb_titleLabel.text = KBLocalized(@"Feedback"); + + self.maxCount = 100; + + // 添加子视图 + [self.view addSubview:self.inputCardView]; + [self.inputCardView addSubview:self.textView]; + [self.inputCardView addSubview:self.placeholderLabel]; + [self.inputCardView addSubview:self.countLabel]; + [self.view addSubview:self.commitButton]; + + // 输入卡片布局 + [self.inputCardView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.view).offset(KB_NAV_TOTAL_HEIGHT + 16); + make.left.equalTo(self.view).offset(16); + make.right.equalTo(self.view).offset(-16); + make.height.mas_equalTo(220); + }]; + + // 文本输入框布局 + [self.textView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.inputCardView).offset(16); + make.left.equalTo(self.inputCardView).offset(16); + make.right.equalTo(self.inputCardView).offset(-16); + make.bottom.equalTo(self.inputCardView).offset(-32); + }]; + + // 占位文字布局(叠在 textView 左上) + [self.placeholderLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.textView).offset(2); + make.left.equalTo(self.textView).offset(4); + }]; + + // 字数统计布局(卡片右下角) + [self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.inputCardView).offset(-16); + make.bottom.equalTo(self.inputCardView).offset(-10); + }]; + + // 底部提交按钮布局 + [self.commitButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.view).offset(24); + make.right.equalTo(self.view).offset(-24); + make.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM - 24); + make.height.mas_equalTo(56); + }]; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ + [self.view endEditing:true]; +} + +#pragma mark - Actions + +/// 提交按钮点击(后续在此方法内实现具体提交逻辑) +- (void)onTapCommit { + NSString *content = self.textView.text ?: @""; + // TODO: 在这里处理提交逻辑,例如校验 + 上报接口等 +} + +#pragma mark - UITextViewDelegate + +// 文本变化时更新占位和字数 +- (void)textViewDidChange:(UITextView *)textView { + // 超出最大字数时截断 + if (textView.text.length > self.maxCount) { + textView.text = [textView.text substringToIndex:self.maxCount]; + } + self.placeholderLabel.hidden = textView.text.length > 0; + self.countLabel.text = [NSString stringWithFormat:@"%ld/%ld", + (long)textView.text.length, + (long)self.maxCount]; +} + +#pragma mark - Lazy Load + +- (UIView *)inputCardView { + if (!_inputCardView) { + _inputCardView = [UIView new]; + _inputCardView.backgroundColor = [UIColor whiteColor]; + _inputCardView.layer.cornerRadius = 16.0; + _inputCardView.layer.masksToBounds = YES; + } + return _inputCardView; +} + +- (UITextView *)textView { + if (!_textView) { + _textView = [[UITextView alloc] init]; + _textView.delegate = self; + _textView.backgroundColor = [UIColor clearColor]; + _textView.font = [UIFont systemFontOfSize:16]; + _textView.textColor = [UIColor blackColor]; + _textView.textContainerInset = UIEdgeInsetsZero; + _textView.textContainer.lineFragmentPadding = 0; + _textView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; + } + return _textView; +} + +- (UILabel *)placeholderLabel { + if (!_placeholderLabel) { + _placeholderLabel = [UILabel new]; + _placeholderLabel.textColor = [UIColor colorWithWhite:0.75 alpha:1.0]; + _placeholderLabel.font = [UIFont systemFontOfSize:16]; + _placeholderLabel.text = KBLocalized(@"Please Enter The Content"); + } + return _placeholderLabel; +} + +- (UILabel *)countLabel { + if (!_countLabel) { + _countLabel = [UILabel new]; + _countLabel.textColor = [UIColor colorWithWhite:0.7 alpha:1.0]; + _countLabel.font = [UIFont systemFontOfSize:14]; + _countLabel.textAlignment = NSTextAlignmentRight; + _countLabel.text = @"0/100"; + } + return _countLabel; +} + +- (UIButton *)commitButton { + if (!_commitButton) { + _commitButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_commitButton setTitle:KBLocalized(@"Commit") forState:UIControlStateNormal]; + [_commitButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _commitButton.titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightSemibold]; + // 使用与修改昵称弹窗相近的主色 + _commitButton.backgroundColor = [UIColor colorWithRed:0.02 green:0.75 blue:0.67 alpha:1.0]; + _commitButton.layer.cornerRadius = 28.0; + _commitButton.layer.masksToBounds = YES; // 胶囊按钮 + [_commitButton addTarget:self action:@selector(onTapCommit) forControlEvents:UIControlEventTouchUpInside]; + } + return _commitButton; +} + +@end diff --git a/keyBoard/Class/Me/VC/KBNoticeVC.h b/keyBoard/Class/Me/VC/KBNoticeVC.h new file mode 100644 index 0000000..5acc72b --- /dev/null +++ b/keyBoard/Class/Me/VC/KBNoticeVC.h @@ -0,0 +1,16 @@ +// +// KBNoticeVC.h +// keyBoard +// +// Created by Mac on 2025/11/24. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBNoticeVC : BaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Me/VC/KBNoticeVC.m b/keyBoard/Class/Me/VC/KBNoticeVC.m new file mode 100644 index 0000000..ad10810 --- /dev/null +++ b/keyBoard/Class/Me/VC/KBNoticeVC.m @@ -0,0 +1,107 @@ +#import "KBNoticeVC.h" +#import + +@interface KBNoticeVC () +/// 顶部白色卡片容器 +@property (nonatomic, strong) UIView *cardView; +/// “Notification Setting” 标题 +@property (nonatomic, strong) UILabel *noticeTitleLabel; +/// 通知开关 +@property (nonatomic, strong) UISwitch *noticeSwitch; + +@end + +@implementation KBNoticeVC + +- (void)viewDidLoad { + [super viewDidLoad]; + // 背景色与设置页风格保持一致 + self.view.backgroundColor = [UIColor colorWithHex:0xF8F8F8]; + // 导航标题 + self.kb_titleLabel.text = KBLocalized(@"Notice"); + + // 添加子视图 + [self.view addSubview:self.cardView]; + [self.cardView addSubview:self.noticeTitleLabel]; + [self.cardView addSubview:self.noticeSwitch]; + + // 布局:卡片 + [self.cardView mas_makeConstraints:^(MASConstraintMaker *make) { + // 顶部距离自定义导航栏一定间距 + make.top.equalTo(self.view).offset(KB_NAV_TOTAL_HEIGHT + 16); + make.left.equalTo(self.view).offset(16); + make.right.equalTo(self.view).offset(-16); + make.height.mas_equalTo(64); + }]; + + // 布局:标题 + [self.noticeTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.cardView).offset(20); + make.centerY.equalTo(self.cardView); + }]; + + // 布局:开关 + [self.noticeSwitch mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.cardView).offset(-20); + make.centerY.equalTo(self.cardView); + }]; +} + +#pragma mark - Actions + +/// 通知开关值变化回调(后续在此方法内实现具体业务) +- (void)noticeSwitchChanged:(UISwitch *)sender { + BOOL isOn = sender.isOn; + // TODO: 根据 isOn 处理通知开关逻辑(例如本地存储、上报等) +} + +#pragma mark - Lazy Load + +- (UIView *)cardView { + if (!_cardView) { + _cardView = [UIView new]; + _cardView.backgroundColor = [UIColor whiteColor]; + _cardView.layer.cornerRadius = 16.0; + _cardView.layer.masksToBounds = NO; + // 阴影效果,接近设计稿 + _cardView.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.06].CGColor; + _cardView.layer.shadowOpacity = 1.0; + _cardView.layer.shadowOffset = CGSizeMake(0, 4); + _cardView.layer.shadowRadius = 8.0; + } + return _cardView; +} + +- (UILabel *)noticeTitleLabel { + if (!_noticeTitleLabel) { + _noticeTitleLabel = [UILabel new]; + _noticeTitleLabel.textColor = [UIColor blackColor]; + _noticeTitleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold]; + // 文案可根据需要在 Localizable.strings 中配置多语言 + _noticeTitleLabel.text = KBLocalized(@"Notification Setting"); + } + return _noticeTitleLabel; +} + +- (UISwitch *)noticeSwitch { + if (!_noticeSwitch) { + _noticeSwitch = [[UISwitch alloc] init]; + _noticeSwitch.on = YES; + // 自定义开关主色(可根据设计调整) + if (@available(iOS 13.0, *)) { + _noticeSwitch.onTintColor = [UIColor systemGreenColor]; + } else { + _noticeSwitch.onTintColor = [UIColor colorWithRed:76/255.0 + green:217/255.0 + blue:100/255.0 + alpha:1.0]; + } + // 监听值变化 + [_noticeSwitch addTarget:self + action:@selector(noticeSwitchChanged:) + forControlEvents:UIControlEventValueChanged]; + } + return _noticeSwitch; +} + +@end diff --git a/keyBoard/Class/Me/VC/MyVC.m b/keyBoard/Class/Me/VC/MyVC.m index e712c8f..6d0d0e0 100644 --- a/keyBoard/Class/Me/VC/MyVC.m +++ b/keyBoard/Class/Me/VC/MyVC.m @@ -11,6 +11,8 @@ #import "KBMyHeaderView.h" // 顶部视图独立封装 #import "KBMyListCell.h" #import "KBTestVC.h" +#import "KBNoticeVC.h" +#import "KBFeedBackVC.h" @interface MyVC () @property (nonatomic, strong) BaseTableView *tableView; // 列表 @@ -35,12 +37,12 @@ // 数据源(title + SF Symbols 名称 + 色值),分两组 self.data = @[ - @[@{ @"title": KBLocalized(@"Notice"), @"icon": @"my_notice_icon", @"color": @(0x60A3FF) }], - @[@{ @"title": KBLocalized(@"Share App"), @"icon": @"my_share_icon", @"color": @(0xF5A623) }], - @[@{ @"title": KBLocalized(@"Feedback"), @"icon": @"my_feedback_icon", @"color": @(0xB06AFD) }, - @{ @"title": KBLocalized(@"E-mail"), @"icon": @"my_email_icon", @"color": @(0xFF8A65) }, - @{ @"title": KBLocalized(@"Agreement"), @"icon": @"my_agreement_icon", @"color": @(0x4CD964) }, - @{ @"title": KBLocalized(@"Privacy Policy"), @"icon": @"my_privacy_icon", @"color": @(0x5AC8FA) }] + @[@{ @"title": KBLocalized(@"Notice"), @"icon": @"my_notice_icon", @"color": @(0x60A3FF),@"id":@"1" }], + @[@{ @"title": KBLocalized(@"Share App"), @"icon": @"my_share_icon", @"color": @(0xF5A623),@"id":@"2" }], + @[@{ @"title": KBLocalized(@"Feedback"), @"icon": @"my_feedback_icon", @"color": @(0xB06AFD),@"id":@"3" }, + @{ @"title": KBLocalized(@"E-mail"), @"icon": @"my_email_icon", @"color": @(0xFF8A65),@"id":@"4" }, + @{ @"title": KBLocalized(@"Agreement"), @"icon": @"my_agreement_icon", @"color": @(0x4CD964),@"id":@"5" }, + @{ @"title": KBLocalized(@"Privacy Policy"), @"icon": @"my_privacy_icon", @"color": @(0x5AC8FA),@"id":@"6" }] ]; [self.view addSubview:self.tableView]; @@ -93,8 +95,25 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; - KBTestVC *vc = [[KBTestVC alloc] init]; - [self.navigationController pushViewController:vc animated:true]; + NSDictionary *info = self.data[indexPath.section][indexPath.row]; + NSString *itemID = info[@"id"]; + if ([itemID isEqualToString:@"1"]) { + [self.navigationController pushViewController:[KBNoticeVC new] animated:true]; + + }else if ([itemID isEqualToString:@"2"]){ + + }else if ([itemID isEqualToString:@"3"]){ + [self.navigationController pushViewController:[KBFeedBackVC new] animated:true]; + + }else if ([itemID isEqualToString:@"4"]){ + + }else if ([itemID isEqualToString:@"5"]){ + + }else if ([itemID isEqualToString:@"6"]){ + + } +// KBTestVC *vc = [[KBTestVC alloc] init]; +// [self.navigationController pushViewController:vc animated:true]; } #pragma mark - Lazy