From a50d18b486052a07b53cdd2fe4703e1d7b954316 Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Wed, 3 Dec 2025 15:19:03 +0800 Subject: [PATCH] 1 --- keyBoard.xcodeproj/project.pbxproj | 12 + .../login_eye_icon.imageset/Contents.json | 22 + .../login_eye_icon@2x.png | Bin 0 -> 1373 bytes .../login_eye_icon@3x.png | Bin 0 -> 2692 bytes .../Contents.json | 22 + .../login_eyeslash_icon@2x.png | Bin 0 -> 791 bytes .../login_eyeslash_icon@3x.png | Bin 0 -> 1413 bytes keyBoard/Class/Base/VC/BaseTabBarController.h | 2 +- keyBoard/Class/Base/VC/BaseTabBarController.m | 24 + keyBoard/Class/Login/VC/KBEmailLoginVC.h | 16 + keyBoard/Class/Login/VC/KBEmailLoginVC.m | 31 + keyBoard/Class/Login/VC/KBEmailRegistVC.h | 18 + keyBoard/Class/Login/VC/KBEmailRegistVC.m | 682 ++++++++++++++++++ keyBoard/Class/Login/VC/KBLoginVC.m | 5 +- 14 files changed, 832 insertions(+), 2 deletions(-) create mode 100644 keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/Contents.json create mode 100644 keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/login_eye_icon@2x.png create mode 100644 keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/login_eye_icon@3x.png create mode 100644 keyBoard/Assets.xcassets/Login/login_eyeslash_icon.imageset/Contents.json create mode 100644 keyBoard/Assets.xcassets/Login/login_eyeslash_icon.imageset/login_eyeslash_icon@2x.png create mode 100644 keyBoard/Assets.xcassets/Login/login_eyeslash_icon.imageset/login_eyeslash_icon@3x.png create mode 100644 keyBoard/Class/Login/VC/KBEmailLoginVC.h create mode 100644 keyBoard/Class/Login/VC/KBEmailLoginVC.m create mode 100644 keyBoard/Class/Login/VC/KBEmailRegistVC.h create mode 100644 keyBoard/Class/Login/VC/KBEmailRegistVC.m diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index 6fe27a1..72e5c62 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -99,6 +99,8 @@ 04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */; }; 04890B122EC2F00000FABA60 /* KBMyHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890B112EC2F00000FABA60 /* KBMyHeaderView.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 */; }; 049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */; }; 049FB20E2EC1CD2800FAB05D /* KBAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB20D2EC1CD2800FAB05D /* KBAlert.m */; }; 049FB2112EC1F72F00FAB05D /* KBMyListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2102EC1F72F00FAB05D /* KBMyListCell.m */; }; @@ -367,6 +369,10 @@ 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 = ""; }; + 0498BD632EE0116D006CC1D5 /* KBEmailLoginVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBEmailLoginVC.h; sourceTree = ""; }; + 0498BD642EE0116D006CC1D5 /* KBEmailLoginVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBEmailLoginVC.m; sourceTree = ""; }; + 0498BD662EE01180006CC1D5 /* KBEmailRegistVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBEmailRegistVC.h; sourceTree = ""; }; + 0498BD672EE01180006CC1D5 /* KBEmailRegistVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBEmailRegistVC.m; sourceTree = ""; }; 049FB2092EC1C13800FAB05D /* KBSkinBottomActionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinBottomActionView.h; sourceTree = ""; }; 049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinBottomActionView.m; sourceTree = ""; }; 049FB20C2EC1CD2800FAB05D /* KBAlert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAlert.h; sourceTree = ""; }; @@ -1320,6 +1326,10 @@ 04FC96122EB34E00007BD342 /* KBLoginSheetViewController.m */, 047920612EDEEFC7004E8522 /* KBLoginVC.h */, 047920622EDEEFC7004E8522 /* KBLoginVC.m */, + 0498BD662EE01180006CC1D5 /* KBEmailRegistVC.h */, + 0498BD672EE01180006CC1D5 /* KBEmailRegistVC.m */, + 0498BD632EE0116D006CC1D5 /* KBEmailLoginVC.h */, + 0498BD642EE0116D006CC1D5 /* KBEmailLoginVC.m */, ); path = VC; sourceTree = ""; @@ -1687,6 +1697,7 @@ 04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */, 04C6EABE2EAF86530089C901 /* AppDelegate.m in Sources */, 04791FFF2ED830FA004E8522 /* KBKeyboardMaskView.m in Sources */, + 0498BD652EE0116D006CC1D5 /* KBEmailLoginVC.m in Sources */, 04FC95F12EB339A7007BD342 /* LoginViewController.m in Sources */, 048908E92EBF843000FABA60 /* KBSkinDetailHeaderCell.m in Sources */, 04FC96142EB34E00007BD342 /* KBLoginSheetViewController.m in Sources */, @@ -1774,6 +1785,7 @@ A1B2C4002EB4A0A100000004 /* KBAuthManager.m in Sources */, 047C65532EBCBAC60035E841 /* KBCommunityVC.m in Sources */, A1B2C4212EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */, + 0498BD682EE01180006CC1D5 /* KBEmailRegistVC.m in Sources */, 04122FB02EC73C0100EF7AB3 /* KBVipReviewItemCell.m in Sources */, 04122F822EC5FC6F00EF7AB3 /* KBJfPay.m in Sources */, 04122F5D2EC5E5A900EF7AB3 /* KBLoginVM.m in Sources */, diff --git a/keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/Contents.json new file mode 100644 index 0000000..5c62dc1 --- /dev/null +++ b/keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "login_eye_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "login_eye_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/login_eye_icon@2x.png b/keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/login_eye_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..88181e5d6e9674890464b3963e64b689c4927977 GIT binary patch literal 1373 zcmV-j1)}z?V#FLihnanNbyWsB__nB{kVPr?teN4B}|0aOLyIZ7tLZgzs3SYH7hAdI!OwLHXa<}ok=E`hO_ zrz|3oa@N{h(FfSYy6D)Hz{JEvn#|AQWD;!CiU2tYDTU%Q<=mQ5p zw>)H3*mPlIQaNUmu`)m4^Nhabt;dE0$h4-ivhsTrj)I7wIvIqnCrDp&bMtqdot;_M zMF+B6OH0c&k~x4vJs8ACs0wtyzKsE07=;Al#<_uH2XNdjFE4M$*(riA$`I}XCnwm^ z1hb8JUwUR{<{e~Ds3Ww|ma6IRS9w7CMjVS}^luYlm`3p%%2y|stjDw2Y->|f(=V`X^=UqzuQ#?8NbYGd-N0iv;p~~i?gF#)zi@=;`WlwhBEb+h#aVsJ z+4*)KDy5C`@5-3NO_44J8qc8N^+fkxF&%l_lH(A?bI(<(d)oP|3K ze=EjEn2V08s;UzRwgMZ`Z;0duVE-(!2JmUJHQs{LYQRXZtgKvO7optp63`L6G5p!9m+_z-#@#=M6#7roGA(Ds8Lt$uVGfz|P=*`u!O1o$$zPkp$~`0&9yraUA-wmHhTAHf}& zINwc!WGMBEt`m^)1)8T3z4P!MfMh(7$H%LIYJHI~o$0IR^`%eO=-n}vFY;&saVG38F)|A-|1Ajn(nvYN_O0e>G<%kz=JJ`8QN<-SkB2o+-1_x3mz z%lK;;DE{GO5r?lr4gt^GUhviOnqH(Ldn~6i!7j3(aMs8wXJ=<$Be)-$1$0ib^Q14% z>Dw6a3!_khgoDEzyL+2by#kU~O((wLWAw)oJM*(UN}!8i7>vq8_7_zfCulFw#=e-x zPX|7a={t#&%$pKO1Z4Unc!9NV`Xo-m%Y|dB;*ZiU=pJA&n@gTDOv0Gt|2}8St! f00v1!K~w_(2TRdXN<8&&00000NkvXXu0mjf1|P84 literal 0 HcmV?d00001 diff --git a/keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/login_eye_icon@3x.png b/keyBoard/Assets.xcassets/Login/login_eye_icon.imageset/login_eye_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..b1f83748738ddefe31c64d8d7b4cc342a3b89baa GIT binary patch literal 2692 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 literal 0 HcmV?d00001 diff --git a/keyBoard/Assets.xcassets/Login/login_eyeslash_icon.imageset/login_eyeslash_icon@3x.png b/keyBoard/Assets.xcassets/Login/login_eyeslash_icon.imageset/login_eyeslash_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f9f97eb466035d79ee24c658149442fe23d893fb GIT binary patch literal 1413 zcmV;01$z34P)>1=mX3q@~58L2*W8u*QtKHj*capL3UlbWZw{rLN(8a~{8Y&pqed z^Sk$FbUK|wE|)6^rpCv|w@yz_7iuf;H#9V48XFs{BVGsagE?@Uk>7!MJU$nX$5$H+ zhTY+CxNRjSQCL`bFYz6vwyhu+`Lq1|{GW}pv$GDABN!tsjn3%YmU_K(w za=4H?6bf}$RaNTsjaA}Xv^hHVrpvYW`cPK+yXQb^1vUfudknhD^dxF zR99E$BhzP*oj@bwVkYdO_ns2{{{}B?MKl`iWnBv(9K)aR4!_?&08ddW0kJeRH2lO% z-Hm(>s3e%VhZE{`P)b4uu`efPW@d8e`G<(Z#X4r7)@1D;JRZ-dO-)TvY$;llfZOes zsyFkr0Hlb?&#*g3=*QJ5<1z@t!^6daK;RYD+Kc%gxO_fvo+gM00lVhHkFLl_;Mw!@^V@i^Ni6Un{9W#Xt&NS1r+MRFM1KUk zygYJONFr9M(NCZDvaRhnyvyNm?Ye@?OeudYJjwif+uy%VVzLIuuoTl=nf09IeZIbm< zHgrX-@50{(lsik80|NsC9aMM& zvRpRnc-8}s5rk9{@jRg~APs~4$eXC3gEeIjZ;}}kK$Vrm9BYeiaUay=kaxZ+2{$8@ZmRdwt0^)?8RVM(!%P}dY zj6!ylptrNm!*F%p>sdf|0(zV!$M8WW-!Eqqy2#Sw2{p6qKO~@kVLm|uwA@?FaByUH z(;n(XLeDrYO9B#Q@^VbSbi|%%EL#GZ4)ovr{S5#B|Nko @end diff --git a/keyBoard/Class/Base/VC/BaseTabBarController.m b/keyBoard/Class/Base/VC/BaseTabBarController.m index ce5b9e2..ce01af4 100644 --- a/keyBoard/Class/Base/VC/BaseTabBarController.m +++ b/keyBoard/Class/Base/VC/BaseTabBarController.m @@ -23,6 +23,8 @@ - (void)viewDidLoad { [super viewDidLoad]; + self.delegate = self; + [self setupTabbarAppearance]; // 组装 4 个 Tab:首页 / 商城 / 社区 / 我的 @@ -104,6 +106,28 @@ return item; } +#pragma mark - UITabBarControllerDelegate + +- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController { + // 已经是当前选中的 tab,直接允许(避免重复拦截) + if (tabBarController.selectedViewController == viewController) { + return YES; + } + + NSUInteger index = [tabBarController.viewControllers indexOfObject:viewController]; + if (index == NSNotFound) { + return YES; + } + + // “我的” tab 默认为第 4 个(索引 3),未登录时先跳转登录页 + if (index == 3 && ![KBUserSessionManager shared].isLoggedIn) { + [[KBUserSessionManager shared] goLoginVC]; + return NO; + } + + return YES; +} + /* #pragma mark - Navigation diff --git a/keyBoard/Class/Login/VC/KBEmailLoginVC.h b/keyBoard/Class/Login/VC/KBEmailLoginVC.h new file mode 100644 index 0000000..5dd5a25 --- /dev/null +++ b/keyBoard/Class/Login/VC/KBEmailLoginVC.h @@ -0,0 +1,16 @@ +// +// KBEmailLoginVC.h +// keyBoard +// +// Created by Mac on 2025/12/3. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBEmailLoginVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Login/VC/KBEmailLoginVC.m b/keyBoard/Class/Login/VC/KBEmailLoginVC.m new file mode 100644 index 0000000..ed41d7e --- /dev/null +++ b/keyBoard/Class/Login/VC/KBEmailLoginVC.m @@ -0,0 +1,31 @@ +// +// KBEmailLoginVC.m +// keyBoard +// +// Created by Mac on 2025/12/3. +// + +#import "KBEmailLoginVC.h" + +@interface KBEmailLoginVC () + +@end + +@implementation KBEmailLoginVC + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/keyBoard/Class/Login/VC/KBEmailRegistVC.h b/keyBoard/Class/Login/VC/KBEmailRegistVC.h new file mode 100644 index 0000000..0696bc4 --- /dev/null +++ b/keyBoard/Class/Login/VC/KBEmailRegistVC.h @@ -0,0 +1,18 @@ +// +// KBEmailRegistVC.h +// keyBoard +// +// Created by Mac on 2025/12/3. +// + +#import "BaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +/// 邮箱注册/登录表单页(使用邮箱+密码) +/// 仅负责展示 UI 与基础交互,具体注册/登录逻辑后续接入 VM。 +@interface KBEmailRegistVC : BaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Login/VC/KBEmailRegistVC.m b/keyBoard/Class/Login/VC/KBEmailRegistVC.m new file mode 100644 index 0000000..a05ba32 --- /dev/null +++ b/keyBoard/Class/Login/VC/KBEmailRegistVC.m @@ -0,0 +1,682 @@ +// +// KBEmailRegistVC.m +// keyBoard +// +// Created by Mac on 2025/12/3. +// + +#import "KBEmailRegistVC.h" + +@interface KBEmailRegistVC () + +// 背景 +@property (nonatomic, strong) UIImageView *bgImageView; // 整体背景图:login_bg_icon +@property (nonatomic, strong) UIImageView *topRightImageView; // 顶部右侧装饰图:login_jianp_icon +@property (nonatomic, strong) UIButton *backButton; // 顶部左侧返回按钮 + +// 底部白色容器(仅上圆角 26) +@property (nonatomic, strong) UIView *contentContainerView; + +// 可滚动区域(小屏设备内容较多时允许纵向滚动) +@property (nonatomic, strong) UIScrollView *scrollView; +@property (nonatomic, strong) UIView *scrollContentView; + +// 标题 +@property (nonatomic, strong) UILabel *titleLabel; + +// 输入框 +@property (nonatomic, strong) UIView *emailFieldContainer; +@property (nonatomic, strong) UITextField *emailTextField; + +@property (nonatomic, strong) UIView *passwordFieldContainer; +@property (nonatomic, strong) UITextField *passwordTextField; +@property (nonatomic, strong) UIButton *passwordToggleButton; // 显示/隐藏密码 + +@property (nonatomic, strong) UIView *repeatPasswordFieldContainer; +@property (nonatomic, strong) UITextField *repeatPasswordTextField; +@property (nonatomic, strong) UIButton *repeatPasswordToggleButton; + +// 主要提交按钮 +@property (nonatomic, strong) UIButton *submitButton; // 绿色 Login 按钮 + +// 其他登录方式 +@property (nonatomic, strong) UIButton *appleLoginButton; // Continue Through Apple +@property (nonatomic, strong) UIButton *emailLoginButton; // Continue Via Email + +// 协议 & 底部文案 +@property (nonatomic, strong) UITextView *agreementTextView; // 底部协议富文本 +@property (nonatomic, strong) UILabel *accountTipLabel; // “Already Have An Account?” +@property (nonatomic, strong) UIButton *switchAccountButton; // “Sign In” + +@end + +@implementation KBEmailRegistVC + +- (void)viewDidLoad { + [super viewDidLoad]; + // 与 KBLoginVC 一致,使用自定义背景与返回按钮,不展示通用导航栏 + self.kb_enableCustomNavBar = NO; + self.view.backgroundColor = [UIColor whiteColor]; + + [self setupUI]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + // 仅白色容器的左上、右上圆角为 26,跟 KBLoginVC 保持一致 + if (!CGRectIsEmpty(self.contentContainerView.bounds)) { + UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight; + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.contentContainerView.bounds + byRoundingCorners:corners + cornerRadii:CGSizeMake(26, 26)]; + CAShapeLayer *mask = [CAShapeLayer layer]; + mask.frame = self.contentContainerView.bounds; + mask.path = path.CGPath; + self.contentContainerView.layer.mask = mask; + } +} + +#pragma mark - UI + +- (void)setupUI { + // 背景图 + [self.view addSubview:self.bgImageView]; + [self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; + + // 顶部左侧返回按钮 + [self.view addSubview:self.backButton]; + [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.view).offset(16); + make.top.equalTo(self.view).offset(KB_StatusBarHeight() + 8); + make.width.height.mas_equalTo(32); + }]; + + // 顶部右侧装饰图 + [self.view addSubview:self.topRightImageView]; + [self.topRightImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.view).offset(KB_StatusBarHeight() + KBFit(24)); + make.right.equalTo(self.view).offset(KBFit(10)); + make.width.mas_equalTo(KBFit(244)); + make.height.mas_equalTo(KBFit(224)); + }]; + + // 底部白色容器 + [self.view addSubview:self.contentContainerView]; + [self.contentContainerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.equalTo(self.view); + // 顶部位置与 KBLoginVC 大致保持一致 + make.top.equalTo(self.view).offset(KBFit(272)); + }]; + + // 可滚动区域:保证小屏设备能完整展示所有控件 + [self.contentContainerView addSubview:self.scrollView]; + [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.contentContainerView); + }]; + + [self.scrollView addSubview:self.scrollContentView]; + [self.scrollContentView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.scrollView); + make.width.equalTo(self.scrollView); // 只允许纵向滚动 + }]; + + // 标题(Sign Up) + [self.scrollContentView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.scrollContentView).offset(27); + make.centerX.equalTo(self.scrollContentView); + }]; + + // 邮箱输入 + [self.scrollContentView addSubview:self.emailFieldContainer]; + [self.emailFieldContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.titleLabel.mas_bottom).offset(24); + make.left.equalTo(self.scrollContentView).offset(30); + make.right.equalTo(self.scrollContentView).offset(-30); + make.height.mas_equalTo(52); + }]; + + [self.emailFieldContainer addSubview:self.emailTextField]; + [self.emailTextField mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.emailFieldContainer).insets(UIEdgeInsetsMake(0, 16, 0, 16)); + }]; + + // 密码输入 + [self.scrollContentView addSubview:self.passwordFieldContainer]; + [self.passwordFieldContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.emailFieldContainer.mas_bottom).offset(16); + make.left.right.equalTo(self.emailFieldContainer); + make.height.equalTo(self.emailFieldContainer); + }]; + + [self.passwordFieldContainer addSubview:self.passwordToggleButton]; + [self.passwordToggleButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.passwordFieldContainer); + make.right.equalTo(self.passwordFieldContainer).offset(-16); + make.width.height.mas_equalTo(24); + }]; + + [self.passwordFieldContainer addSubview:self.passwordTextField]; + [self.passwordTextField mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.bottom.equalTo(self.passwordFieldContainer); + make.left.equalTo(self.passwordFieldContainer).offset(16); + make.right.equalTo(self.passwordToggleButton.mas_left).offset(-8); + }]; + + // 重复密码输入 + [self.scrollContentView addSubview:self.repeatPasswordFieldContainer]; + [self.repeatPasswordFieldContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.passwordFieldContainer.mas_bottom).offset(16); + make.left.right.height.equalTo(self.emailFieldContainer); + }]; + + [self.repeatPasswordFieldContainer addSubview:self.repeatPasswordToggleButton]; + [self.repeatPasswordToggleButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.repeatPasswordFieldContainer); + make.right.equalTo(self.repeatPasswordFieldContainer).offset(-16); + make.width.height.mas_equalTo(24); + }]; + + [self.repeatPasswordFieldContainer addSubview:self.repeatPasswordTextField]; + [self.repeatPasswordTextField mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.bottom.equalTo(self.repeatPasswordFieldContainer); + make.left.equalTo(self.repeatPasswordFieldContainer).offset(16); + make.right.equalTo(self.repeatPasswordToggleButton.mas_left).offset(-8); + }]; + + // 提交按钮(绿色 Login) + [self.scrollContentView addSubview:self.submitButton]; + [self.submitButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.repeatPasswordFieldContainer.mas_bottom).offset(24); + make.left.right.equalTo(self.emailFieldContainer); + make.height.mas_equalTo(56); + }]; + + // Apple 登录方式 + [self.scrollContentView addSubview:self.appleLoginButton]; + [self.appleLoginButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.submitButton.mas_bottom).offset(24); + make.left.right.equalTo(self.emailFieldContainer); + make.height.mas_equalTo(52); + }]; + + // 邮箱登录方式 + [self.scrollContentView addSubview:self.emailLoginButton]; + [self.emailLoginButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.appleLoginButton.mas_bottom).offset(12); + make.left.right.height.equalTo(self.appleLoginButton); + }]; + + // 协议文案 + [self.scrollContentView addSubview:self.agreementTextView]; + [self.agreementTextView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.emailLoginButton.mas_bottom).offset(16); + make.left.equalTo(self.scrollContentView).offset(30); + make.right.equalTo(self.scrollContentView).offset(-30); + }]; + + // 底部账号切换文案 + UIView *accountLine = [UIView new]; + [self.scrollContentView addSubview:accountLine]; + [accountLine mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.agreementTextView.mas_bottom).offset(16); + make.centerX.equalTo(self.scrollContentView); + make.bottom.equalTo(self.scrollContentView).offset(-KB_SAFE_BOTTOM - 16); + }]; + + [accountLine addSubview:self.accountTipLabel]; + [accountLine addSubview:self.switchAccountButton]; + + [self.accountTipLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.left.bottom.equalTo(accountLine); + }]; + + [self.switchAccountButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.accountTipLabel.mas_right).offset(4); + make.right.equalTo(accountLine); + make.centerY.equalTo(self.accountTipLabel); + }]; +} + +#pragma mark - Actions + +- (void)onTapBack { + // 与 BaseViewController 的返回逻辑保持一致:优先 pop,其次 dismiss + if (self.navigationController && self.navigationController.viewControllers.count > 1) { + [self.navigationController popViewControllerAnimated:YES]; + } else if (self.presentingViewController) { + [self dismissViewControllerAnimated:YES completion:nil]; + } +} + +- (void)onTapSubmit { + // 后续接入具体注册/登录逻辑 + KBLOG(@"onTapSubmit email=%@, password length=%zd", + self.emailTextField.text, + self.passwordTextField.text.length); +} + +- (void)onTapForgotPassword { + KBLOG(@"onTapForgotPassword in KBEmailRegistVC"); +} + +- (void)onTapSwitchAccount { + // 注册页/登录页互跳逻辑后续接入 + KBLOG(@"onTapSwitchAccount"); +} + +- (void)onTapTogglePassword:(UIButton *)sender { + sender.selected = !sender.selected; + BOOL showPassword = sender.selected; + + if (sender == self.passwordToggleButton) { + self.passwordTextField.secureTextEntry = !showPassword; + } else if (sender == self.repeatPasswordToggleButton) { + self.repeatPasswordTextField.secureTextEntry = !showPassword; + } +} + +- (void)onTapAppleLogin { + KBLOG(@"onTapAppleLogin in KBEmailRegistVC"); +} + +- (void)onTapEmailLogin { + KBLOG(@"onTapEmailLogin in KBEmailRegistVC"); +} + +#pragma mark - Agreement Tap + +- (void)kb_handleAgreementTap:(UITapGestureRecognizer *)tap { + UITextView *textView = self.agreementTextView; + CGPoint point = [tap locationInView:textView]; + + // 将点击点转换到 textContainer 坐标系 + CGPoint location = point; + location.x -= textView.textContainerInset.left; + location.y -= textView.textContainerInset.top; + + NSLayoutManager *layoutManager = textView.layoutManager; + NSTextContainer *textContainer = textView.textContainer; + NSUInteger glyphIndex = [layoutManager glyphIndexForPoint:location + inTextContainer:textContainer]; + if (glyphIndex >= textView.textStorage.length) { return; } + + NSUInteger charIndex = [layoutManager characterIndexForGlyphAtIndex:glyphIndex]; + + NSString *lowerFull = textView.text.lowercaseString ?: @""; + NSRange termsRange = [lowerFull rangeOfString:@"terms of service"]; + NSRange privacyRange = [lowerFull rangeOfString:@"privacy policy"]; + + BOOL hitTerms = (termsRange.location != NSNotFound && NSLocationInRange(charIndex, termsRange)); + BOOL hitPrivacy = (privacyRange.location != NSNotFound && NSLocationInRange(charIndex, privacyRange)); + if (hitTerms || hitPrivacy) { + KBLOG(@"tap policy in KBEmailRegistVC"); + // 后续可统一跳转到协议页 + } +} + +#pragma mark - UITextFieldDelegate + +- (BOOL)textFieldShouldReturn:(UITextField *)textField { + if (textField == self.emailTextField) { + [self.passwordTextField becomeFirstResponder]; + } else if (textField == self.passwordTextField) { + [self.repeatPasswordTextField becomeFirstResponder]; + } else if (textField == self.repeatPasswordTextField) { + [textField resignFirstResponder]; + [self onTapSubmit]; + } + return YES; +} + +#pragma mark - Lazy UI + +- (UIImageView *)bgImageView { + if (!_bgImageView) { + _bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"login_bg_icon"]]; + _bgImageView.contentMode = UIViewContentModeScaleAspectFill; + _bgImageView.clipsToBounds = YES; + } + return _bgImageView; +} + +- (UIImageView *)topRightImageView { + if (!_topRightImageView) { + _topRightImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"login_jianp_icon"]]; + _topRightImageView.contentMode = UIViewContentModeScaleAspectFit; + _topRightImageView.clipsToBounds = YES; + } + return _topRightImageView; +} + +- (UIButton *)backButton { + if (!_backButton) { + _backButton = [UIButton buttonWithType:UIButtonTypeCustom]; + UIImage *img = [UIImage imageNamed:@"back"]; + if (!img) { img = [UIImage imageNamed:@"back_black_icon"]; } + if (img) { + [_backButton setImage:img forState:UIControlStateNormal]; + } + _backButton.adjustsImageWhenHighlighted = YES; + _backButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + [_backButton addTarget:self action:@selector(onTapBack) forControlEvents:UIControlEventTouchUpInside]; + } + return _backButton; +} + +- (UIView *)contentContainerView { + if (!_contentContainerView) { + _contentContainerView = [UIView new]; + _contentContainerView.backgroundColor = [UIColor whiteColor]; + } + return _contentContainerView; +} + +- (UIScrollView *)scrollView { + if (!_scrollView) { + _scrollView = [UIScrollView new]; + _scrollView.showsVerticalScrollIndicator = NO; + _scrollView.alwaysBounceVertical = NO; // 内容不超出时不产生多余回弹 + _scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; + } + return _scrollView; +} + +- (UIView *)scrollContentView { + if (!_scrollContentView) { + _scrollContentView = [UIView new]; + _scrollContentView.backgroundColor = [UIColor clearColor]; + } + return _scrollContentView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + // 注册页标题 + _titleLabel.text = KBLocalized(@"Sign Up"); + _titleLabel.textColor = [UIColor colorWithHex:KBBlackValue]; + _titleLabel.font = [KBFont bold:18]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +- (UIView *)emailFieldContainer { + if (!_emailFieldContainer) { + _emailFieldContainer = [UIView new]; + _emailFieldContainer.backgroundColor = [UIColor colorWithHex:0xF7F7F7]; + _emailFieldContainer.layer.cornerRadius = 10.0; + _emailFieldContainer.layer.masksToBounds = YES; + } + return _emailFieldContainer; +} + +- (UITextField *)emailTextField { + if (!_emailTextField) { + _emailTextField = [[UITextField alloc] init]; + _emailTextField.delegate = self; + _emailTextField.keyboardType = UIKeyboardTypeEmailAddress; + _emailTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; + _emailTextField.autocorrectionType = UITextAutocorrectionTypeNo; + _emailTextField.clearButtonMode = UITextFieldViewModeWhileEditing; + _emailTextField.textColor = [UIColor colorWithHex:KBBlackValue]; + _emailTextField.font = [KBFont regular:14]; + _emailTextField.returnKeyType = UIReturnKeyNext; + + NSString *ph = KBLocalized(@"Enter Email Address"); + _emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:ph + attributes:@{ + NSForegroundColorAttributeName : [UIColor colorWithWhite:0.75 alpha:1.0], + NSFontAttributeName : [KBFont regular:14] + }]; + } + return _emailTextField; +} + +- (UIView *)passwordFieldContainer { + if (!_passwordFieldContainer) { + _passwordFieldContainer = [UIView new]; + _passwordFieldContainer.backgroundColor = [UIColor colorWithHex:0xF7F7F7]; + _passwordFieldContainer.layer.cornerRadius = 10.0; + _passwordFieldContainer.layer.masksToBounds = YES; + } + return _passwordFieldContainer; +} + +- (UITextField *)passwordTextField { + if (!_passwordTextField) { + _passwordTextField = [[UITextField alloc] init]; + _passwordTextField.delegate = self; + _passwordTextField.secureTextEntry = YES; + _passwordTextField.textColor = [UIColor colorWithHex:KBBlackValue]; + _passwordTextField.font = [KBFont regular:14]; + _passwordTextField.returnKeyType = UIReturnKeyDone; + + NSString *ph = KBLocalized(@"Enter Password"); + _passwordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:ph + attributes:@{ + NSForegroundColorAttributeName : [UIColor colorWithWhite:0.75 alpha:1.0], + NSFontAttributeName : [KBFont regular:14] + }]; + } + return _passwordTextField; +} + +- (UIButton *)passwordToggleButton { + if (!_passwordToggleButton) { + _passwordToggleButton = [UIButton buttonWithType:UIButtonTypeCustom]; + UIImage *eye = [UIImage imageNamed:@"login_eye_icon"]; + UIImage *eyeSlash = [UIImage imageNamed:@"login_eyeslash_icon"]; + [_passwordToggleButton setImage:eye forState:UIControlStateNormal]; + [_passwordToggleButton setImage:eyeSlash forState:UIControlStateSelected]; + [_passwordToggleButton addTarget:self + action:@selector(onTapTogglePassword:) + forControlEvents:UIControlEventTouchUpInside]; + } + return _passwordToggleButton; +} + +- (UIView *)repeatPasswordFieldContainer { + if (!_repeatPasswordFieldContainer) { + _repeatPasswordFieldContainer = [UIView new]; + _repeatPasswordFieldContainer.backgroundColor = [UIColor colorWithHex:0xF7F7F7]; + _repeatPasswordFieldContainer.layer.cornerRadius = 10.0; + _repeatPasswordFieldContainer.layer.masksToBounds = YES; + } + return _repeatPasswordFieldContainer; +} + +- (UITextField *)repeatPasswordTextField { + if (!_repeatPasswordTextField) { + _repeatPasswordTextField = [[UITextField alloc] init]; + _repeatPasswordTextField.delegate = self; + _repeatPasswordTextField.secureTextEntry = YES; + _repeatPasswordTextField.textColor = [UIColor colorWithHex:KBBlackValue]; + _repeatPasswordTextField.font = [KBFont regular:14]; + _repeatPasswordTextField.returnKeyType = UIReturnKeyDone; + + NSString *ph = KBLocalized(@"Enter Repeat Password"); + _repeatPasswordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:ph + attributes:@{ + NSForegroundColorAttributeName : [UIColor colorWithWhite:0.75 alpha:1.0], + NSFontAttributeName : [KBFont regular:14] + }]; + } + return _repeatPasswordTextField; +} + +- (UIButton *)repeatPasswordToggleButton { + if (!_repeatPasswordToggleButton) { + _repeatPasswordToggleButton = [UIButton buttonWithType:UIButtonTypeCustom]; + UIImage *eye = [UIImage imageNamed:@"login_eye_icon"]; + UIImage *eyeSlash = [UIImage imageNamed:@"login_eyeslash_icon"]; + [_repeatPasswordToggleButton setImage:eye forState:UIControlStateNormal]; + [_repeatPasswordToggleButton setImage:eyeSlash forState:UIControlStateSelected]; + [_repeatPasswordToggleButton addTarget:self + action:@selector(onTapTogglePassword:) + forControlEvents:UIControlEventTouchUpInside]; + } + return _repeatPasswordToggleButton; +} + +- (UIButton *)forgotPasswordButton { + // 注册页当前未使用“忘记密码”,保留方法避免外部引用报错 + return nil; +} + +- (UIButton *)submitButton { + if (!_submitButton) { + _submitButton = [UIButton buttonWithType:UIButtonTypeCustom]; + // 文案可按实际是“Login”还是“Sign Up”调整 + [_submitButton setTitle:KBLocalized(@"Login") forState:UIControlStateNormal]; + [_submitButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + _submitButton.titleLabel.font = [KBFont medium:16]; + _submitButton.backgroundColor = [UIColor colorWithHex:KBColorValue]; + _submitButton.layer.cornerRadius = 28.0; + _submitButton.layer.masksToBounds = YES; + [_submitButton addTarget:self + action:@selector(onTapSubmit) + forControlEvents:UIControlEventTouchUpInside]; + } + return _submitButton; + } + +- (UIButton *)appleLoginButton { + if (!_appleLoginButton) { + _appleLoginButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_appleLoginButton setTitle:KBLocalized(@"Continue Through Apple") forState:UIControlStateNormal]; + [_appleLoginButton setTitleColor:[UIColor colorWithHex:KBBlackValue] forState:UIControlStateNormal]; + _appleLoginButton.titleLabel.font = [KBFont medium:16]; + _appleLoginButton.backgroundColor = [UIColor whiteColor]; + _appleLoginButton.layer.cornerRadius = 10.0; + _appleLoginButton.layer.masksToBounds = YES; + _appleLoginButton.layer.borderColor = [UIColor colorWithHex:0xE5E5E5].CGColor; + _appleLoginButton.layer.borderWidth = 1; + _appleLoginButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; + // 若后续有 Apple 图标资源,可在此设置 imageEdgeInsets 与图标 + [_appleLoginButton addTarget:self + action:@selector(onTapAppleLogin) + forControlEvents:UIControlEventTouchUpInside]; + } + return _appleLoginButton; +} + +- (UIButton *)emailLoginButton { + if (!_emailLoginButton) { + _emailLoginButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_emailLoginButton setTitle:KBLocalized(@"Continue Via Email") forState:UIControlStateNormal]; + [_emailLoginButton setTitleColor:[UIColor colorWithHex:KBBlackValue] forState:UIControlStateNormal]; + _emailLoginButton.titleLabel.font = [KBFont medium:16]; + _emailLoginButton.backgroundColor = [UIColor whiteColor]; + _emailLoginButton.layer.cornerRadius = 10.0; + _emailLoginButton.layer.masksToBounds = YES; + _emailLoginButton.layer.borderColor = [UIColor colorWithHex:0xE5E5E5].CGColor; + _emailLoginButton.layer.borderWidth = 1; + _emailLoginButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; + + UIImage *icon = [UIImage imageNamed:@"login_email_icon"]; + if (icon) { + CGFloat targetHeight = 12; + CGFloat scale = targetHeight / icon.size.height; + CGSize targetSize = CGSizeMake(icon.size.width * scale, targetHeight); + + UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0.0); + [icon drawInRect:CGRectMake(0, 0, targetSize.width, targetSize.height)]; + UIImage *scaledIcon = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + [_emailLoginButton setImage:scaledIcon forState:UIControlStateNormal]; + // 图标与文字间距 + _emailLoginButton.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); + } + + [_emailLoginButton addTarget:self + action:@selector(onTapEmailLogin) + forControlEvents:UIControlEventTouchUpInside]; + } + return _emailLoginButton; +} + +- (UITextView *)agreementTextView { + if (!_agreementTextView) { + _agreementTextView = [UITextView new]; + _agreementTextView.backgroundColor = [UIColor clearColor]; + _agreementTextView.editable = NO; + _agreementTextView.selectable = NO; + _agreementTextView.scrollEnabled = NO; + _agreementTextView.textAlignment = NSTextAlignmentCenter; + _agreementTextView.textContainerInset = UIEdgeInsetsZero; + _agreementTextView.textContainer.lineFragmentPadding = 0; + + NSString *fullText = @"By continuing, you agree to our terms of service and confirm that you have read our privacy policy"; + NSString *termsText = @"terms of service"; + NSString *privacyText = @"privacy policy"; + + NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init]; + paragraph.alignment = NSTextAlignmentCenter; + + NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:fullText + attributes:@{ + NSFontAttributeName : [KBFont regular:10], + NSForegroundColorAttributeName : [UIColor colorWithHex:0x717171], + NSParagraphStyleAttributeName : paragraph + }]; + + NSString *lowerFull = fullText.lowercaseString; + NSRange termsRange = [lowerFull rangeOfString:termsText.lowercaseString]; + if (termsRange.location != NSNotFound) { + [attr addAttributes:@{ + NSForegroundColorAttributeName : [UIColor colorWithHex:KBBlackValue], + NSUnderlineStyleAttributeName : @(NSUnderlineStyleNone) + } range:termsRange]; + } + + NSRange privacyRange = [lowerFull rangeOfString:privacyText.lowercaseString]; + if (privacyRange.location != NSNotFound) { + [attr addAttributes:@{ + NSForegroundColorAttributeName : [UIColor colorWithHex:KBBlackValue], + NSUnderlineStyleAttributeName : @(NSUnderlineStyleNone) + } range:privacyRange]; + } + + _agreementTextView.linkTextAttributes = @{ + NSForegroundColorAttributeName : [UIColor colorWithHex:KBBlackValue], + NSUnderlineStyleAttributeName : @(NSUnderlineStyleNone) + }; + _agreementTextView.attributedText = attr; + + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self + action:@selector(kb_handleAgreementTap:)]; + _agreementTextView.userInteractionEnabled = YES; + [_agreementTextView addGestureRecognizer:tap]; + } + return _agreementTextView; +} + +- (UILabel *)accountTipLabel { + if (!_accountTipLabel) { + _accountTipLabel = [UILabel new]; + _accountTipLabel.text = KBLocalized(@"Already Have An Account?"); + _accountTipLabel.font = [KBFont regular:10]; + _accountTipLabel.textColor = [UIColor colorWithHex:KBBlackValue]; + } + return _accountTipLabel; +} + +- (UIButton *)switchAccountButton { + if (!_switchAccountButton) { + _switchAccountButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_switchAccountButton setTitle:KBLocalized(@"Sign In") forState:UIControlStateNormal]; + [_switchAccountButton setTitleColor:[UIColor colorWithHex:KBColorValue] forState:UIControlStateNormal]; + _switchAccountButton.titleLabel.font = [KBFont medium:10]; + [_switchAccountButton addTarget:self + action:@selector(onTapSwitchAccount) + forControlEvents:UIControlEventTouchUpInside]; + } + return _switchAccountButton; +} + +@end diff --git a/keyBoard/Class/Login/VC/KBLoginVC.m b/keyBoard/Class/Login/VC/KBLoginVC.m index 7676bdf..cef2545 100644 --- a/keyBoard/Class/Login/VC/KBLoginVC.m +++ b/keyBoard/Class/Login/VC/KBLoginVC.m @@ -9,6 +9,7 @@ #import #import "KBLoginVM.h" #import "AppDelegate.h" +#import "KBEmailRegistVC.h" @interface KBLoginVC () @@ -88,7 +89,7 @@ [self.view addSubview:self.topRightImageView]; [self.topRightImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view).offset(KB_StatusBarHeight() + KBFit(24)); - make.right.equalTo(self.view).offset(-KBFit(20)); + make.right.equalTo(self.view).offset(KBFit(10)); make.width.mas_equalTo(KBFit(244)); make.height.mas_equalTo(KBFit(224)); }]; @@ -197,6 +198,8 @@ - (void)onTapSignUp { // 打开注册页 KBLOG(@"onTapSignUp"); + KBEmailRegistVC *vc = [[KBEmailRegistVC alloc] init]; + [KB_CURRENT_NAV pushViewController:vc animated:true]; } - (void)onTapForgotPassword {