diff --git a/Shared/KBAPI.h b/Shared/KBAPI.h index ec32be3..65f2f4f 100644 --- a/Shared/KBAPI.h +++ b/Shared/KBAPI.h @@ -34,6 +34,7 @@ #define KB_API_CHARACTER_LISTBYUSER @"/character/listByUser" // 用户人设列表 #define API_CHARACTER_UPDATE_USER_CHARTSORT @"/character/updateUserCharacterSort" // 更新用户人设排序 #define API_CHARACTER_DEL_USER_CHARACTER @"/character/delUserCharacter" // 删除用户人设 +#define API_CHARACTER_ADD_USER_CHARACTER @"/character/addUserCharacter" // 添加用户人设(假定路径,如有不同请按后端实际修改) diff --git a/keyBoard/Class/Home/M/KBCharacter.h b/keyBoard/Class/Home/M/KBCharacter.h index e6afa94..f201421 100644 --- a/keyBoard/Class/Home/M/KBCharacter.h +++ b/keyBoard/Class/Home/M/KBCharacter.h @@ -19,6 +19,8 @@ NS_ASSUME_NONNULL_BEGIN /// "rank" : 899 /// } @interface KBCharacter : NSObject +/// 首页用的ID(也是人设ID) +@property (nonatomic, copy, nullable) NSString *ID; /// 唯一标识,对应后端的 id @property (nonatomic, copy, nullable) NSString *characterId; diff --git a/keyBoard/Class/Home/M/KBCharacter.m b/keyBoard/Class/Home/M/KBCharacter.m index 94a778d..d0fd576 100644 --- a/keyBoard/Class/Home/M/KBCharacter.m +++ b/keyBoard/Class/Home/M/KBCharacter.m @@ -11,7 +11,7 @@ // 后端字段映射到本地属性 return @{ // id -> characterId - @"characterId": @"id", + @"ID": @"id", // 名称字段:优先 characterName,兼容部分接口可能返回 title @"characterName": @[@"characterName", @"title"], }; diff --git a/keyBoard/Class/Home/V/HomeHotCell.h b/keyBoard/Class/Home/V/HomeHotCell.h index f37f6b8..571ca34 100644 --- a/keyBoard/Class/Home/V/HomeHotCell.h +++ b/keyBoard/Class/Home/V/HomeHotCell.h @@ -15,6 +15,9 @@ NS_ASSUME_NONNULL_BEGIN /// 当前展示的排行榜角色模型 @property (nonatomic, strong, nullable) KBCharacter *character; +/// 点击右侧加号/勾选按钮的回调,由外部 VC 处理网络逻辑 +@property (nonatomic, copy, nullable) void (^onTapAction)(void); + /// 旧的配置方法(不再推荐使用),内部会转成 character 赋值 - (void)configWithRank:(NSInteger)rank title:(NSString *)title diff --git a/keyBoard/Class/Home/V/HomeHotCell.m b/keyBoard/Class/Home/V/HomeHotCell.m index 6300c95..38791ef 100644 --- a/keyBoard/Class/Home/V/HomeHotCell.m +++ b/keyBoard/Class/Home/V/HomeHotCell.m @@ -70,6 +70,12 @@ }]; } +- (void)actionButtonTapped { + if (self.onTapAction) { + self.onTapAction(); + } +} + - (void)setCharacter:(KBCharacter *)character { _character = character; @@ -94,6 +100,8 @@ [self.actionButton setTitleColor:[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] forState:UIControlStateNormal]; self.actionButton.backgroundColor = [UIColor colorWithRed:0.88 green:0.97 blue:0.93 alpha:1.0]; } + // 已加入后禁用按钮,避免重复添加或取消 + self.actionButton.enabled = !joined; } // 兼容旧调用:转成一个临时模型再走统一逻辑 @@ -111,6 +119,7 @@ [self.avatarView kb_cancelImageLoad]; self.avatarView.image = nil; self.character = nil; + self.onTapAction = nil; } #pragma mark - Lazy @@ -170,6 +179,7 @@ _actionButton.layer.cornerRadius = 12; _actionButton.layer.masksToBounds = YES; _actionButton.titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightBold]; + [_actionButton addTarget:self action:@selector(actionButtonTapped) forControlEvents:UIControlEventTouchUpInside]; } return _actionButton; } diff --git a/keyBoard/Class/Home/V/HomeRankCardCell.m b/keyBoard/Class/Home/V/HomeRankCardCell.m index 7d0b522..87d3a06 100644 --- a/keyBoard/Class/Home/V/HomeRankCardCell.m +++ b/keyBoard/Class/Home/V/HomeRankCardCell.m @@ -127,6 +127,8 @@ [self.actionBtn setTitle:@"+" forState:UIControlStateNormal]; [self.actionBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; } + // 已添加后禁用按钮(不可再次点击) + self.actionBtn.enabled = !added; } #pragma mark - Lazy UI diff --git a/keyBoard/Class/Home/V/KBTopThreeView.h b/keyBoard/Class/Home/V/KBTopThreeView.h index 6afd63f..3e9d0bd 100644 --- a/keyBoard/Class/Home/V/KBTopThreeView.h +++ b/keyBoard/Class/Home/V/KBTopThreeView.h @@ -16,6 +16,13 @@ NS_ASSUME_NONNULL_BEGIN /// 使用前三名角色模型进行配置(数组元素为 KBCharacter*,最多取前三个) - (void)configWithCharacters:(NSArray *)characters; +/// 中间卡片底部加号按钮点击回调(传入对应角色模型,可能为 nil) +@property (nonatomic, copy, nullable) void (^onCenterPlusTapped)(KBCharacter * _Nullable character); +/// 左侧卡片底部加号按钮点击回调 +@property (nonatomic, copy, nullable) void (^onLeftPlusTapped)(KBCharacter * _Nullable character); +/// 右侧卡片底部加号按钮点击回调 +@property (nonatomic, copy, nullable) void (^onRightPlusTapped)(KBCharacter * _Nullable character); + @end NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/V/KBTopThreeView.m b/keyBoard/Class/Home/V/KBTopThreeView.m index 7c4787e..ee32122 100644 --- a/keyBoard/Class/Home/V/KBTopThreeView.m +++ b/keyBoard/Class/Home/V/KBTopThreeView.m @@ -135,6 +135,10 @@ /// 左右卡片底部也有 plus 按钮 @property (nonatomic, strong) UIButton *leftPlusButton; @property (nonatomic, strong) UIButton *rightPlusButton; +/// 对应的前三名角色模型(用于回调和状态控制) +@property (nonatomic, strong, nullable) KBCharacter *firstCharacter; +@property (nonatomic, strong, nullable) KBCharacter *secondCharacter; +@property (nonatomic, strong, nullable) KBCharacter *thirdCharacter; @end @implementation KBTopThreeView @@ -203,21 +207,78 @@ } - (void)configWithCharacters:(NSArray *)characters { - if (characters.count == 0) { - // 无数据时清空标题与头像 + self.firstCharacter = characters.count > 0 ? characters[0] : nil; + self.secondCharacter = characters.count > 1 ? characters[1] : nil; + self.thirdCharacter = characters.count > 2 ? characters[2] : nil; + + if (self.firstCharacter) { + [self.centerCard renderWithCharacter:self.firstCharacter rank:1]; + } else { [self.centerCard renderWithCharacter:[KBCharacter new] rank:1]; - [self.leftCard renderWithCharacter:[KBCharacter new] rank:2]; - [self.rightCard renderWithCharacter:[KBCharacter new] rank:3]; - return; } - KBCharacter *first = characters.count > 0 ? characters[0] : nil; - KBCharacter *second = characters.count > 1 ? characters[1] : nil; - KBCharacter *third = characters.count > 2 ? characters[2] : nil; + if (self.secondCharacter) { + [self.leftCard renderWithCharacter:self.secondCharacter rank:2]; + } else { + [self.leftCard renderWithCharacter:[KBCharacter new] rank:2]; + } - if (first) [self.centerCard renderWithCharacter:first rank:1]; - if (second) [self.leftCard renderWithCharacter:second rank:2]; - if (third) [self.rightCard renderWithCharacter:third rank:3]; + if (self.thirdCharacter) { + [self.rightCard renderWithCharacter:self.thirdCharacter rank:3]; + } else { + [self.rightCard renderWithCharacter:[KBCharacter new] rank:3]; + } + + // 根据 added 状态刷新三个加号按钮的 UI 和可点击状态 + [self updatePlusButtonsState]; +} + +- (void)onCenterPlusTappedInternal { + if (self.onCenterPlusTapped) { + self.onCenterPlusTapped(self.firstCharacter); + } +} + +- (void)onLeftPlusTappedInternal { + if (self.onLeftPlusTapped) { + self.onLeftPlusTapped(self.secondCharacter); + } +} + +- (void)onRightPlusTappedInternal { + if (self.onRightPlusTapped) { + self.onRightPlusTapped(self.thirdCharacter); + } +} + +/// 根据角色是否已添加,更新三个底部按钮的文案与状态 +- (void)updatePlusButtonsState { + [self updatePlusButton:self.plusButton withCharacter:self.firstCharacter]; + [self updatePlusButton:self.leftPlusButton withCharacter:self.secondCharacter]; + [self updatePlusButton:self.rightPlusButton withCharacter:self.thirdCharacter]; +} + +- (void)updatePlusButton:(UIButton *)button withCharacter:(KBCharacter * _Nullable)character { + if (!character) { + button.hidden = YES; + return; + } + button.hidden = NO; + + BOOL added = character.added; + if (added) { + // 已添加:灰色背景 + 勾选,且禁用点击 + [button setTitle:@"✓" forState:UIControlStateNormal]; + [button setTitleColor:[UIColor colorWithWhite:0.45 alpha:1.0] forState:UIControlStateNormal]; + button.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; + button.enabled = NO; + } else { + // 未添加:绿色加号,可点击 + [button setTitle:@"+" forState:UIControlStateNormal]; + [button setTitleColor:[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] forState:UIControlStateNormal]; + button.backgroundColor = [[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] colorWithAlphaComponent:0.15]; + button.enabled = YES; + } } #pragma mark - Lazy @@ -235,6 +296,7 @@ _plusButton.layer.masksToBounds = YES; // 默认浅色背景,可按需要在外层配置 _plusButton.backgroundColor = [[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] colorWithAlphaComponent:0.15]; + [_plusButton addTarget:self action:@selector(onCenterPlusTappedInternal) forControlEvents:UIControlEventTouchUpInside]; } return _plusButton; } @@ -248,6 +310,7 @@ _leftPlusButton.layer.cornerRadius = 14.0; _leftPlusButton.layer.masksToBounds = YES; _leftPlusButton.backgroundColor = [[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] colorWithAlphaComponent:0.15]; + [_leftPlusButton addTarget:self action:@selector(onLeftPlusTappedInternal) forControlEvents:UIControlEventTouchUpInside]; } return _leftPlusButton; } @@ -261,6 +324,7 @@ _rightPlusButton.layer.cornerRadius = 14.0; _rightPlusButton.layer.masksToBounds = YES; _rightPlusButton.backgroundColor = [[UIColor colorWithRed:0.20 green:0.65 blue:0.50 alpha:1.0] colorWithAlphaComponent:0.15]; + [_rightPlusButton addTarget:self action:@selector(onRightPlusTappedInternal) forControlEvents:UIControlEventTouchUpInside]; } return _rightPlusButton; } diff --git a/keyBoard/Class/Home/VC/HomeHotVC.m b/keyBoard/Class/Home/VC/HomeHotVC.m index 5ab22af..ddc9abc 100644 --- a/keyBoard/Class/Home/VC/HomeHotVC.m +++ b/keyBoard/Class/Home/VC/HomeHotVC.m @@ -17,6 +17,7 @@ #import "LSTPopView.h" #import #import "KBMyVM.h" // 用户人设变更通知 +#import "KBHUD.h" @interface HomeHotVC () @@ -52,6 +53,18 @@ self.topThreeView = [[KBTopThreeView alloc] initWithFrame:CGRectMake(0, 0, KB_SCREEN_WIDTH, headerH)]; self.tableView.tableHeaderView = self.topThreeView; + KBWeakSelf + // 顶部三名区域的三个加号按钮:添加人设 + self.topThreeView.onCenterPlusTapped = ^(KBCharacter * _Nullable character) { + [weakSelf kb_addUserCharacterFromTopViewWithCharacter:character]; + }; + self.topThreeView.onLeftPlusTapped = ^(KBCharacter * _Nullable character) { + [weakSelf kb_addUserCharacterFromTopViewWithCharacter:character]; + }; + self.topThreeView.onRightPlusTapped = ^(KBCharacter * _Nullable character) { + [weakSelf kb_addUserCharacterFromTopViewWithCharacter:character]; + }; + // 请求排行榜数据 self.homeVM = [KBHomeVM new]; [self kb_reloadRankListWithShowHUD:YES]; @@ -79,21 +92,9 @@ } weakSelf.allCharacters = list ?: @[]; - // 顶部前三名数据:直接取前三个模型交给 KBTopThreeView - NSInteger topCount = MIN(3, weakSelf.allCharacters.count); - if (topCount > 0) { - NSRange range = NSMakeRange(0, topCount); - NSArray *topThree = [weakSelf.allCharacters subarrayWithRange:range]; - [weakSelf.topThreeView configWithCharacters:topThree]; - } - - // 列表部分:从第 4 名开始 - if (weakSelf.allCharacters.count > 3) { - NSRange range = NSMakeRange(3, weakSelf.allCharacters.count - 3); - weakSelf.listCharacters = [weakSelf.allCharacters subarrayWithRange:range]; - } else { - weakSelf.listCharacters = @[]; - } + // 根据最新数据刷新顶部前三名与列表部分 + [weakSelf kb_refreshTopThreeView]; + [weakSelf kb_refreshListCharacters]; [weakSelf.tableView reloadData]; // 通知承载 HomeHotVC 的“外层 PanModal 容器”刷新布局。 @@ -129,7 +130,7 @@ BOOL contains = NO; for (KBCharacter *c in self.allCharacters) { - if (c.characterId.integerValue == targetId) { + if (c.ID.integerValue == targetId) { contains = YES; break; } @@ -140,6 +141,52 @@ [self kb_reloadRankListWithShowHUD:NO]; } +/// 根据当前 allCharacters 刷新顶部前三名区域 +- (void)kb_refreshTopThreeView { + NSInteger topCount = MIN(3, self.allCharacters.count); + if (topCount > 0) { + NSRange range = NSMakeRange(0, topCount); + NSArray *topThree = [self.allCharacters subarrayWithRange:range]; + [self.topThreeView configWithCharacters:topThree]; + } else { + [self.topThreeView configWithCharacters:@[]]; + } +} + +/// 根据当前 allCharacters 刷新列表区域(第 4 名及以后) +- (void)kb_refreshListCharacters { + if (self.allCharacters.count > 3) { + NSRange range = NSMakeRange(3, self.allCharacters.count - 3); + self.listCharacters = [self.allCharacters subarrayWithRange:range]; + } else { + self.listCharacters = @[]; + } +} + +/// 顶部三名区域点击“+”添加人设 +- (void)kb_addUserCharacterFromTopViewWithCharacter:(KBCharacter * _Nullable)character { + if (!character || character.added) { return; } + + NSString *cidStr = character.ID ?: @""; + if (cidStr.length == 0) { return; } + NSNumber *cid = @([cidStr integerValue]); + + [self.homeVM addUserCharacterWithId:cid + completion:^(BOOL success, NSError * _Nullable error) { + if (!success) { + NSString *msg = error.localizedDescription ?: KBLocalized(@"Network error"); + [KBHUD showInfo:msg]; + return; + } + + // 添加成功:更新模型状态 + character.added = YES; + // 刷新顶部与列表 UI + [self kb_refreshTopThreeView]; + [self.tableView reloadData]; + }]; +} + #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { @@ -151,6 +198,44 @@ KBCharacter *item = self.listCharacters[indexPath.row]; // 直接把模型交给 cell,由 cell 自己负责展示 cell.character = item; + KBWeakSelf + __weak typeof(cell) weakCell = cell; + cell.onTapAction = ^{ + __strong typeof(weakSelf) self = weakSelf; + HomeHotCell *strongCell = weakCell; + if (!self || !strongCell) { return; } + + NSIndexPath *current = [self.tableView indexPathForCell:strongCell]; + if (!current) { return; } + if (current.row >= self.listCharacters.count) { return; } + + KBCharacter *mc = self.listCharacters[current.row]; + // 已添加状态下不允许再次点击 + if (mc.added) { return; } + + NSString *cidStr = mc.ID ?: @""; + if (cidStr.length == 0) { return; } + NSNumber *cid = @([cidStr integerValue]); + + [self.homeVM addUserCharacterWithId:cid + completion:^(BOOL success, NSError * _Nullable error) { + if (!success) { + NSString *msg = error.localizedDescription ?: KBLocalized(@"Network error"); + [KBHUD showInfo:msg]; + return; + } + + // 添加成功:更新模型状态并刷新当前行(按钮变为已添加且不可再点) + mc.added = YES; + NSMutableArray *m = [self.listCharacters mutableCopy]; + [m replaceObjectAtIndex:current.row withObject:mc]; + self.listCharacters = [m copy]; + [self.tableView reloadRowsAtIndexPaths:@[current] withRowAnimation:UITableViewRowAnimationNone]; + + // 同步更新顶部前三名的展示状态 + [self kb_refreshTopThreeView]; + }]; + }; return cell; } diff --git a/keyBoard/Class/Home/VC/HomeRankContentVC.m b/keyBoard/Class/Home/VC/HomeRankContentVC.m index 9606b43..d338451 100644 --- a/keyBoard/Class/Home/VC/HomeRankContentVC.m +++ b/keyBoard/Class/Home/VC/HomeRankContentVC.m @@ -14,6 +14,7 @@ #import "HomeRankCardCell.h" #import "KBHomeVM.h" #import "KBCharacter.h" +#import "KBHUD.h" #import "KBMyVM.h" // 引入用户人设变更通知 @interface HomeRankContentVC () @@ -88,7 +89,7 @@ BOOL contains = NO; for (KBCharacter *c in self.characters) { - if (c.characterId.integerValue == targetId) { + if (c.ID.integerValue == targetId) { contains = YES; break; } diff --git a/keyBoard/Class/Home/VM/KBHomeVM.h b/keyBoard/Class/Home/VM/KBHomeVM.h index 7f4f3c9..b8ced35 100644 --- a/keyBoard/Class/Home/VM/KBHomeVM.h +++ b/keyBoard/Class/Home/VM/KBHomeVM.h @@ -20,6 +20,10 @@ typedef void(^KBHomeRankCompletion)(NSArray * _Nullable list, typedef void(^KBHomeTagCompletion)(NSArray * _Nullable list, NSError * _Nullable error); +/// 添加用户人设回调 +typedef void(^KBHomeAddUserCharacterCompletion)(BOOL success, + NSError * _Nullable error); + @interface KBHomeVM : NSObject /// 最近一次成功请求到的排行榜数据 @@ -51,6 +55,11 @@ typedef void(^KBHomeTagCompletion)(NSArray * _Nullable list, needShow:(BOOL)needShow completion:(KBHomeTagCompletion)completion; +/// 添加用户人设(例如在首页排行榜中点 “+”) +/// GET /character/addUserCharacter?id={characterId} +- (void)addUserCharacterWithId:(NSNumber *)characterId + completion:(KBHomeAddUserCharacterCompletion)completion; + @end NS_ASSUME_NONNULL_END diff --git a/keyBoard/Class/Home/VM/KBHomeVM.m b/keyBoard/Class/Home/VM/KBHomeVM.m index 058e233..bfd2b5f 100644 --- a/keyBoard/Class/Home/VM/KBHomeVM.m +++ b/keyBoard/Class/Home/VM/KBHomeVM.m @@ -11,6 +11,7 @@ #import "KBNetworkManager.h" #import "KBHUD.h" #import "KBBizCode.h" +#import "KBAPI.h" @interface KBHomeVM () @property (nonatomic, copy, readwrite, nullable) NSArray *rankList; @@ -170,4 +171,36 @@ }]; } +/// 添加用户人设 +- (void)addUserCharacterWithId:(NSNumber *)characterId + completion:(KBHomeAddUserCharacterCompletion)completion { + if (!characterId) { + if (completion) { + NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain + code:KBNetworkErrorInvalidResponse + userInfo:@{NSLocalizedDescriptionKey: KBLocalized(@"Invalid parameter")}]; + completion(NO, e); + } + return; + } + + NSDictionary *params = @{@"characterId": characterId}; +// [[KBNetworkManager shared] GET:API_CHARACTER_ADD_USER_CHARACTER +// parameters:params +// headers:nil +// autoShowBusinessError:YES +// completion:^(NSDictionary *jsonOrData, +// NSURLResponse * _Nullable response, +// NSError * _Nullable error) { +// if (completion) { +// completion(error == nil, error); +// } +// }]; + [[KBNetworkManager shared] POST:API_CHARACTER_ADD_USER_CHARACTER jsonBody:params headers:nil autoShowBusinessError:false completion:^(NSDictionary * _Nullable json, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if (completion) { + completion(error == nil, error); + } + }]; +} + @end diff --git a/keyBoard/Class/Login/VC/KBEmailLoginVC.m b/keyBoard/Class/Login/VC/KBEmailLoginVC.m index e04b385..b155b45 100644 --- a/keyBoard/Class/Login/VC/KBEmailLoginVC.m +++ b/keyBoard/Class/Login/VC/KBEmailLoginVC.m @@ -8,6 +8,9 @@ #import "KBEmailLoginVC.h" #import "KBEmailRegistVC.h" #import "KBForgetPwdVC.h" +#import "KBLoginVM.h" +#import "AppDelegate.h" +#import "BaseTabBarController.h" @interface KBEmailLoginVC () // 背景与顶部装饰 @@ -41,6 +44,7 @@ @property (nonatomic, strong) UITextView *agreementTextView; @property (nonatomic, strong) UILabel *accountTipLabel; // “Don't Have An Account?” @property (nonatomic, strong) UIButton *signUpButton; // “Sign Up” +@property (nonatomic, strong) KBLoginVM *loginVM; // Confirm @end @@ -49,6 +53,7 @@ - (void)viewDidLoad { [super viewDidLoad]; // 与登录/注册页一致:隐藏通用导航栏,使用自定义背景 + 返回按钮 + self.loginVM = [[KBLoginVM alloc] init]; self.kb_enableCustomNavBar = NO; self.view.backgroundColor = [UIColor whiteColor]; [self kb_addTapToDismissKeyboard]; @@ -217,8 +222,27 @@ - (void)onTapSubmit { KBLOG(@"KBEmailLoginVC onTapSubmit, email=%@, pwdLen=%zd", - self.emailTextField.text, + self.emailTextField.text, self.passwordTextField.text.length); + NSString *email = self.emailTextField.text ? self.emailTextField.text : @""; + NSString *password = self.passwordTextField.text ? self.passwordTextField.text : @""; + + [self.loginVM emailLoginEmail:email password:password WithCompletion:^(BOOL success, NSError * _Nullable error) { + if (success) { + id appDelegate = UIApplication.sharedApplication.delegate; + if ([appDelegate respondsToSelector:@selector(setupRootVC)]) { + AppDelegate *delegate = (AppDelegate *)appDelegate; + // [delegate toMainTabbarVC]; + delegate.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + delegate.window.backgroundColor = [UIColor whiteColor]; + [delegate.window makeKeyAndVisible]; + UIViewController *rootVC = nil; + rootVC = [[BaseTabBarController alloc] init]; + delegate.window.rootViewController = rootVC; + } + } + }]; + } - (void)onTapForgotPassword { diff --git a/keyBoard/Class/Login/VC/KBRegistVerEmailVC.m b/keyBoard/Class/Login/VC/KBRegistVerEmailVC.m index 0078142..8b4a173 100644 --- a/keyBoard/Class/Login/VC/KBRegistVerEmailVC.m +++ b/keyBoard/Class/Login/VC/KBRegistVerEmailVC.m @@ -10,6 +10,7 @@ #import "KBLoginVM.h" #import "KBUser.h" #import "AppDelegate.h" +#import "KBEmailLoginVC.h" @interface KBRegistVerEmailVC () @@ -32,6 +33,11 @@ [self kb_addTapToDismissKeyboard]; [self setupUI]; + // 获取验证码 + NSString *email = self.params[@"mailAddress"]; + [self.loginVM sendVerifyMailWithEmail:email withCompletion:^(BOOL success, NSError * _Nullable error) { + + }]; } #pragma mark - UI @@ -88,7 +94,7 @@ return; } KBLOG(@"KBRegistVerEmailVC confirm with code=%@", code); - self.params[@"code"] = code; + self.params[@"verifyCode"] = code; NSNumber *genderNumber = [self kb_localGenderParamIfAvailable]; if (genderNumber != nil) { self.params[@"gender"] = genderNumber; @@ -98,11 +104,20 @@ [KBHUD showInfo:KBLocalized(@"Signed in successfully")]; // 登录成功后切换到主 TabBar dispatch_async(dispatch_get_main_queue(), ^{ - id appDelegate = UIApplication.sharedApplication.delegate; - if ([appDelegate respondsToSelector:@selector(setupRootVC)]) { - AppDelegate *delegate = (AppDelegate *)appDelegate; - [delegate toMainTabbarVC]; - } + KBEmailLoginVC *vc = [[KBEmailLoginVC alloc] init]; + [KB_CURRENT_NAV pushViewController:vc animated:true]; +// id appDelegate = UIApplication.sharedApplication.delegate; +// if ([appDelegate respondsToSelector:@selector(setupRootVC)]) { +// AppDelegate *delegate = (AppDelegate *)appDelegate; +//// [delegate toMainTabbarVC]; +// delegate.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; +// delegate.window.backgroundColor = [UIColor whiteColor]; +// [delegate.window makeKeyAndVisible]; +// UIViewController *rootVC = nil; +// rootVC = [[BaseTabBarController alloc] init]; +// self.window.rootViewController = rootVC; +// } + }); } else { NSString *msg = error.localizedDescription ?: KBLocalized(@"Sign-in failed"); diff --git a/keyBoard/Class/Login/VM/KBLoginVM.h b/keyBoard/Class/Login/VM/KBLoginVM.h index 4e3df36..8dfe69a 100644 --- a/keyBoard/Class/Login/VM/KBLoginVM.h +++ b/keyBoard/Class/Login/VM/KBLoginVM.h @@ -13,6 +13,7 @@ NS_ASSUME_NONNULL_BEGIN /// 登录完成回调 typedef void(^KBLoginCompletion)(BOOL success, NSError * _Nullable error); typedef void(^KBRegisterCompletion)(BOOL success, NSError * _Nullable error); +typedef void(^KBVerifyMailCompletion)(BOOL success, NSError * _Nullable error); @interface KBLoginVM : NSObject @@ -30,6 +31,9 @@ typedef void(^KBRegisterCompletion)(BOOL success, NSError * _Nullable error); - (void)emailLoginEmail:(NSString *)email password:(NSString *)password WithCompletion:(KBLoginCompletion)completion; /// 邮箱注册 - (void)emailRegisterParams:(NSDictionary *)params withCompletion:(KBRegisterCompletion)completion; +/// 发送验证码 +- (void)sendVerifyMailWithEmail:(NSString *)email withCompletion:(KBVerifyMailCompletion)completion; + /// 是否已登录:由 KBAuthManager 判断(是否存在有效 token) - (BOOL)isLoggedIn; diff --git a/keyBoard/Class/Login/VM/KBLoginVM.m b/keyBoard/Class/Login/VM/KBLoginVM.m index 2bb8ddf..8064837 100644 --- a/keyBoard/Class/Login/VM/KBLoginVM.m +++ b/keyBoard/Class/Login/VM/KBLoginVM.m @@ -132,6 +132,20 @@ }]; } +/// 发送验证码 +- (void)sendVerifyMailWithEmail:(NSString *)email withCompletion:(KBVerifyMailCompletion)completion{ + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (email.length) params[@"mailAddress"] = email; +// [[KBNetworkManager shared] POST:API_EMAIL_REGISTER jsonBody:params headers:nil completion:^(NSDictionary * _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) { +// if (error) { if (completion) completion(NO, error); return; } +// []; +// completion(true,nil); +// }]; + [[KBNetworkManager shared] POST:API_EMAIL_REGISTER jsonBody:params headers:nil autoShowBusinessError:true completion:^(NSDictionary * _Nullable json, NSURLResponse * _Nullable response, NSError * _Nullable error) { + + }]; +} + #pragma mark - Helpers // 宽松解析:token / access_token / accessToken,支持顶层或 data/user 层 diff --git a/keyBoard/Class/Me/VC/KBMyKeyBoardVC.m b/keyBoard/Class/Me/VC/KBMyKeyBoardVC.m index cc37686..7b7870d 100644 --- a/keyBoard/Class/Me/VC/KBMyKeyBoardVC.m +++ b/keyBoard/Class/Me/VC/KBMyKeyBoardVC.m @@ -109,7 +109,9 @@ static NSString * const kKBMyKeyboardCellId = @"kKBMyKeyboardCellId"; for (KBCharacter *c in characterArray) { NSString *emoji = c.emoji ?: @""; NSString *title = c.characterName ?: @""; - NSString *identifier = c.characterId ?: @""; + NSString *identifier = c.ID ?: @""; + NSString *characterId = c.characterId ?: @""; + // 如果某条数据既没有 emoji 也没有标题,则忽略 if (emoji.length == 0 && title.length == 0) { continue; @@ -117,6 +119,8 @@ static NSString * const kKBMyKeyboardCellId = @"kKBMyKeyboardCellId"; NSMutableDictionary *item = [NSMutableDictionary dictionary]; item[@"emoji"] = emoji; item[@"title"] = title; + item[@"characterId"] = characterId; + if (identifier.length > 0) { // 用数字类型存储,便于直接作为 sort 数组上送 NSInteger cid = identifier.integerValue; @@ -154,18 +158,21 @@ static NSString * const kKBMyKeyboardCellId = @"kKBMyKeyboardCellId"; if (!tapIndexPath) { return; } // 取出将要删除的人设 id - NSNumber *characterId = nil; + NSNumber *delId = nil; // 要删除的ID + NSString *characterId = @""; // 通知其他页面要刷新的关联ID + if (tapIndexPath.section < self.dataSourceArray.count) { NSArray *section = self.dataSourceArray[tapIndexPath.section]; if (tapIndexPath.item < section.count) { NSDictionary *item = section[tapIndexPath.item]; id cid = item[@"id"]; + characterId = item[@"characterId"]; if ([cid isKindOfClass:[NSNumber class]]) { - characterId = (NSNumber *)cid; + delId = (NSNumber *)cid; } else if ([cid isKindOfClass:[NSString class]]) { NSString *cidStr = (NSString *)cid; if (cidStr.length > 0) { - characterId = @([cidStr integerValue]); + delId = @([cidStr integerValue]); } } } @@ -181,7 +188,7 @@ static NSString * const kKBMyKeyboardCellId = @"kKBMyKeyboardCellId"; if (!ok) { return; } // 若无法获取 id,仅做本地删除以保持 UI 一致 - if (!characterId) { + if (!delId) { if (tapIndexPath.section < self.dataSourceArray.count) { NSMutableArray *section = self.dataSourceArray[tapIndexPath.section]; if (tapIndexPath.item < section.count) { @@ -196,7 +203,7 @@ static NSString * const kKBMyKeyboardCellId = @"kKBMyKeyboardCellId"; // 调用删除接口,成功后刷新界面 __weak typeof(self) weakSelf2 = self; - [self.viewModel deleteUserCharacterWithId:characterId + [self.viewModel deleteUserCharacterWithId:delId completion:^(BOOL success, NSError * _Nullable error) { __strong typeof(weakSelf2) strongSelf = weakSelf2; if (!strongSelf) { return; } @@ -206,7 +213,13 @@ static NSString * const kKBMyKeyboardCellId = @"kKBMyKeyboardCellId"; [KBHUD showInfo:msg]; return; } - + // 通知 App 内其他页面(如 HomeRankContentVC / HomeHotVC)该人设已被删除 + NSDictionary *info = @{@"characterId": characterId ?: @0}; + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:KBUserCharacterDeletedNotification + object:nil + userInfo:info]; + }); // 重新拉取用户人设列表,刷新 UI [strongSelf kb_reloadUserCharacters]; }]; diff --git a/keyBoard/Class/Me/VM/KBMyVM.m b/keyBoard/Class/Me/VM/KBMyVM.m index 0dd3df5..17d5bfc 100644 --- a/keyBoard/Class/Me/VM/KBMyVM.m +++ b/keyBoard/Class/Me/VM/KBMyVM.m @@ -123,13 +123,7 @@ NSString * const KBUserCharacterDeletedNotification = @"KBUserCharacterDeletedNo BOOL success = (error == nil); if (success) { - // 通知 App 内其他页面(如 HomeRankContentVC / HomeHotVC)该人设已被删除 - NSDictionary *info = @{@"characterId": characterId ?: @0}; - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:KBUserCharacterDeletedNotification - object:nil - userInfo:info]; - }); + } if (completion) {