diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index cd65e15..a789d64 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -425,7 +425,6 @@ 4C1E98C62E9A45BC0031AE79 /* EPMomentAPISwiftHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E98C52E9A45BC0031AE79 /* EPMomentAPISwiftHelper.swift */; }; 4C1E98C92E9A4DFD0031AE79 /* EPQCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E98C72E9A4DFD0031AE79 /* EPQCloudConfig.swift */; }; 4C1E98CA2E9A4DFD0031AE79 /* EPSDKManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E98C82E9A4DFD0031AE79 /* EPSDKManager.swift */; }; - 4C1E98CD2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E98CC2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m */; }; 4C3475C42DD1FE590099B984 /* CreateEventSelectRoomViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C3475C32DD1FE590099B984 /* CreateEventSelectRoomViewController.m */; }; 4C3851992DD5F4D50089CFCC /* EventConfigModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C3851982DD5F4D50089CFCC /* EventConfigModel.m */; }; 4C38C2AD2D84064400CFA4A8 /* LoginInputItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C38C2AC2D84064300CFA4A8 /* LoginInputItemView.m */; }; @@ -2485,8 +2484,6 @@ 4C1E98C52E9A45BC0031AE79 /* EPMomentAPISwiftHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EPMomentAPISwiftHelper.swift; sourceTree = ""; }; 4C1E98C72E9A4DFD0031AE79 /* EPQCloudConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EPQCloudConfig.swift; sourceTree = ""; }; 4C1E98C82E9A4DFD0031AE79 /* EPSDKManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EPSDKManager.swift; sourceTree = ""; }; - 4C1E98CB2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPMomentAPIHelper_Deprecated.h; sourceTree = ""; }; - 4C1E98CC2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPMomentAPIHelper_Deprecated.m; sourceTree = ""; }; 4C3475C22DD1FE590099B984 /* CreateEventSelectRoomViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CreateEventSelectRoomViewController.h; sourceTree = ""; }; 4C3475C32DD1FE590099B984 /* CreateEventSelectRoomViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CreateEventSelectRoomViewController.m; sourceTree = ""; }; 4C3851972DD5F4D50089CFCC /* EventConfigModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EventConfigModel.h; sourceTree = ""; }; @@ -6459,8 +6456,6 @@ 4C0642952E98F76F00BAF413 /* Services */ = { isa = PBXGroup; children = ( - 4C1E98CB2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.h */, - 4C1E98CC2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m */, 4C1E98C52E9A45BC0031AE79 /* EPMomentAPISwiftHelper.swift */, ); path = Services; @@ -12766,7 +12761,6 @@ E8751E5F28A62A970056EF44 /* XPSailingPresenter.m in Sources */, E84A2E962A5280F900D6AF8A /* XPExchangeDiamondsView.m in Sources */, 23F9636A2BB6919D00F440A6 /* PINobleRebateModel.m in Sources */, - 4C1E98CD2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m in Sources */, E8DAC5AC2858305A00012CFD /* XPRoomMessageBubbleView.m in Sources */, 1427218929A75F6F00C7C423 /* HTTPDataResponse.m in Sources */, E8B9843028AB90200022D026 /* XPMoentsTopicListView.m in Sources */, @@ -13789,6 +13783,7 @@ SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_OBJC_BRIDGING_HEADER = "YuMi/YuMi-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; diff --git a/YuMi.xcodeproj/xcshareddata/xcschemes/YuMi.xcscheme b/YuMi.xcodeproj/xcshareddata/xcschemes/YuMi.xcscheme index ad9a463..9bebfa8 100644 --- a/YuMi.xcodeproj/xcshareddata/xcschemes/YuMi.xcscheme +++ b/YuMi.xcodeproj/xcshareddata/xcschemes/YuMi.xcscheme @@ -56,6 +56,11 @@ value = "disable" isEnabled = "NO"> + + Int { - return 2 // 头像昵称section + 设置项section + return 1 // 只有一个 section } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - return 2 // 头像 + 昵称 - } else { - return settingItems.count - } + let count = settingItems.count + 1 // +1 for nickname row + NSLog("[EPEditSetting] TableView rows count: \(count), settingItems: \(settingItems.count)") + return count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { @@ -331,35 +419,50 @@ extension EPEditSettingViewController: UITableViewDataSource, UITableViewDelegat cell.textLabel?.textColor = .white cell.selectionStyle = .none - if indexPath.section == 0 { - // 头像昵称section - if indexPath.row == 0 { - // 头像行 - cell.textLabel?.text = YMLocalizedString("EPEditSetting.Avatar") - cell.accessoryType = .disclosureIndicator - - // 添加头像图片 - if cell.contentView.subviews.contains(profileImageView) { - profileImageView.removeFromSuperview() - } - cell.contentView.addSubview(profileImageView) - profileImageView.snp.makeConstraints { make in - make.trailing.equalToSuperview().offset(-50) - make.centerY.equalToSuperview() - make.size.equalTo(100) - } - } else { - // 昵称行 - cell.textLabel?.text = YMLocalizedString("EPEditSetting.Nickname") - cell.detailTextLabel?.text = userInfo?.nick ?? "未设置" - cell.detailTextLabel?.textColor = .lightGray - cell.accessoryType = .disclosureIndicator + // 清除之前的自定义视图 + cell.contentView.subviews.forEach { $0.removeFromSuperview() } + + if indexPath.row == 0 { + // 昵称行 + cell.textLabel?.text = YMLocalizedString("EPEditSetting.Nickname") + + // 添加右箭头图标 + let arrowImageView = UIImageView() + arrowImageView.image = UIImage(named: "icon_setting_right_arrow") + arrowImageView.contentMode = .scaleAspectFit + cell.contentView.addSubview(arrowImageView) + arrowImageView.snp.makeConstraints { make in + make.trailing.equalToSuperview().offset(-20) + make.centerY.equalToSuperview() + make.size.equalTo(22) } + + // 添加用户昵称标签 + let nicknameLabel = UILabel() + nicknameLabel.text = userInfo?.nick ?? "未设置" + nicknameLabel.textColor = .lightGray + nicknameLabel.font = UIFont.systemFont(ofSize: 16) + cell.contentView.addSubview(nicknameLabel) + nicknameLabel.snp.makeConstraints { make in + make.trailing.equalTo(arrowImageView.snp.leading).offset(-12) + make.centerY.equalToSuperview() + } + } else { - // 设置项section - let item = settingItems[indexPath.row] + // 其他设置项 + let item = settingItems[indexPath.row - 1] cell.textLabel?.text = item.title - cell.accessoryType = .disclosureIndicator + + // 添加右箭头图标 + let arrowImageView = UIImageView() + arrowImageView.image = UIImage(named: "icon_setting_right_arrow") + arrowImageView.contentMode = .scaleAspectFit + cell.contentView.addSubview(arrowImageView) + arrowImageView.snp.makeConstraints { make in + make.trailing.equalToSuperview().offset(-20) + make.centerY.equalToSuperview() + make.size.equalTo(22) + } if item.style == .default { cell.textLabel?.textColor = .systemRed @@ -372,48 +475,36 @@ extension EPEditSettingViewController: UITableViewDataSource, UITableViewDelegat } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0 && indexPath.row == 0 { - return 120 // 头像行更高 - } - return 60 + return 60 // 所有行都是 60pt 高度 } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) - if indexPath.section == 0 { - if indexPath.row == 0 { - // 头像点击 - showAvatarSelectionSheet() - } else { - // 昵称点击 - showNicknameEditAlert() - } + if indexPath.row == 0 { + // 昵称点击 + showNicknameEditAlert() } else { // 设置项点击 - let item = settingItems[indexPath.row] + let item = settingItems[indexPath.row - 1] item.action() } } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return section == 0 ? 20 : 10 + return 0 } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let view = UIView() - view.backgroundColor = UIColor(hex: "#0C0527") - return view + return nil } func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - return 10 + return 0 } func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { - let view = UIView() - view.backgroundColor = UIColor(hex: "#0C0527") - return view + return nil } } @@ -441,41 +532,75 @@ extension EPEditSettingViewController: UIImagePickerControllerDelegate, UINaviga } private func uploadAvatar(_ image: UIImage) { - // 压缩图片 - guard let imageData = image.jpegData(compressionQuality: 0.5) else { - print("[EPEditSetting] 图片压缩失败") - return - } + // 显示上传进度 + EPProgressHUD.showProgress(0, total: 1) - // 生成文件名 - let format = "jpg" - let name = "image/\(UUID().uuidString).\(format)" - - // 上传到腾讯云 - UploadFile.share().qCloudUploadImage(imageData, named: name, success: { [weak self] (key, resp) in - print("[EPEditSetting] 头像上传成功: \(key)") - - // 调用API更新头像 - self?.updateAvatarAPI(avatarUrl: key) - - }, failure: { (resCode, message) in - print("[EPEditSetting] 头像上传失败: \(message)") - }) + // 使用 EPSDKManager 统一上传接口(避免腾讯云 OCR 配置问题) + EPSDKManager.shared.uploadImages([image], + progress: { uploaded, total in + EPProgressHUD.showProgress(uploaded, total: total) + }, + success: { [weak self] resList in + EPProgressHUD.dismiss() + + guard !resList.isEmpty, + let firstRes = resList.first, + let avatarUrl = firstRes["resUrl"] as? String else { + print("[EPEditSetting] 头像上传成功但无法获取URL") + + return + } + + print("[EPEditSetting] 头像上传成功: \(avatarUrl)") + + // 调用API更新头像 + self?.updateAvatarAPI(avatarUrl: avatarUrl) + }, + failure: { [weak self] errorMsg in + EPProgressHUD.dismiss() + print("[EPEditSetting] 头像上传失败: \(errorMsg)") + + // 显示错误提示 + DispatchQueue.main.async { + let alert = UIAlertController(title: "上传失败", message: errorMsg, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "确定", style: .default)) + self?.present(alert, animated: true) + } + } + ) } private func updateAvatarAPI(avatarUrl: String) { - // 调用API更新头像 - Api.userV2UploadAvatar({ [weak self] (data, code, msg) in + // 使用 API Helper 更新头像 + apiHelper.updateAvatar(withUrl: avatarUrl, completion: { [weak self] in + print("[EPEditSetting] 头像更新成功") + + // 更新本地用户信息 + self?.userInfo?.avatar = avatarUrl + + // 通知父页面头像已更新 + self?.notifyParentAvatarUpdated(avatarUrl) + + }, failure: { [weak self] (code: Int, msg: String?) in + print("[EPEditSetting] 头像更新失败: \(code) - \(msg ?? "未知错误")") + + // 显示错误提示 DispatchQueue.main.async { - if code == 200 { - print("[EPEditSetting] 头像更新成功") - // 更新本地用户信息 - self?.userInfo?.avatar = avatarUrl - } else { - print("[EPEditSetting] 头像更新失败: \(String(describing: msg))") - } + let alert = UIAlertController( + title: "更新失败", + message: msg ?? "头像更新失败,请稍后重试", + preferredStyle: .alert + ) + alert.addAction(UIAlertAction(title: "确定", style: .default)) + self?.present(alert, animated: true) } - }, avatarUrl: avatarUrl, needPay: NSNumber(value: false)) + }) + } + + private func notifyParentAvatarUpdated(_ avatarUrl: String) { + // 发送通知给 EPMineViewController 更新头像 + let userInfo = ["avatarUrl": avatarUrl] + NotificationCenter.default.post(name: NSNotification.Name("EPEditSettingAvatarUpdated"), object: nil, userInfo: userInfo) } } diff --git a/YuMi/E-P/NewMine/Controllers/EPMineViewController.m b/YuMi/E-P/NewMine/Controllers/EPMineViewController.m index 674d2b8..f92631f 100644 --- a/YuMi/E-P/NewMine/Controllers/EPMineViewController.m +++ b/YuMi/E-P/NewMine/Controllers/EPMineViewController.m @@ -41,7 +41,6 @@ - (void)viewDidLoad { [super viewDidLoad]; - [self setupUI]; NSLog(@"[EPMineViewController] viewDidLoad 完成"); @@ -49,10 +48,7 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - - // 隐藏导航栏 [self.navigationController setNavigationBarHidden:YES animated:animated]; - // 每次显示时加载最新数据 [self loadUserDetailInfo]; } @@ -60,8 +56,13 @@ // MARK: - Setup - (void)setupUI { - // 背景渐变色 - self.view.backgroundColor = [UIColor colorWithRed:0.047 green:0.020 blue:0.153 alpha:1.0]; // #0C0527 + UIImageView *bgImageView = [[UIImageView alloc] initWithImage:kImage(@"vc_bg")]; + bgImageView.contentMode = UIViewContentModeScaleAspectFill; + bgImageView.clipsToBounds = YES; + [self.view addSubview:bgImageView]; + [bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.view); + }]; [self setupHeaderView]; [self setupMomentListView]; @@ -73,19 +74,25 @@ self.headerView = [[EPMineHeaderView alloc] initWithFrame:CGRectZero]; [self.view addSubview:self.headerView]; - // 使用约束布局 - self.headerView.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint activateConstraints:@[ - [self.headerView.topAnchor constraintEqualToAnchor:self.view.topAnchor], - [self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], - [self.headerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], - [self.headerView.heightAnchor constraintEqualToConstant:320] - ]]; + // 使用 Masonry 约束布局 + [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.view); + make.leading.mas_equalTo(self.view); + make.trailing.mas_equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(320)); + }]; - // 监听设置按钮点击事件 + // 设置按钮点击回调 + __weak typeof(self) weakSelf = self; + self.headerView.onSettingsButtonTapped = ^{ + __strong typeof(weakSelf) self = weakSelf; + [self openSettings]; + }; + + // 监听头像更新事件 [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(openSettings) - name:@"EPMineHeaderSettingsButtonTapped" + selector:@selector(onAvatarUpdated:) + name:@"EPEditSettingAvatarUpdated" object:nil]; } @@ -93,14 +100,13 @@ self.momentListView = [[EPMomentListView alloc] initWithFrame:CGRectZero]; [self.view addSubview:self.momentListView]; - // 使用约束布局 - self.momentListView.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint activateConstraints:@[ - [self.momentListView.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor], - [self.momentListView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], - [self.momentListView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], - [self.momentListView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] - ]]; + // 使用 Masonry 约束布局 + [self.momentListView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.headerView.mas_bottom); + make.bottom.mas_equalTo(self.view); + make.leading.mas_equalTo(self.view); + make.trailing.mas_equalTo(self.view); + }]; } // MARK: - Data Loading @@ -172,13 +178,37 @@ // MARK: - Actions - (void)openSettings { + // 隐藏返回按钮文字,只保留白色箭头 + self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" + style:UIBarButtonItemStylePlain + target:nil + action:nil]; + EPEditSettingViewController *settingsVC = [[EPEditSettingViewController alloc] init]; + // 传递用户信息到设置页面 + if (self.userInfo) { + [settingsVC updateWithUserInfo:self.userInfo]; + } [self.navigationController pushViewController:settingsVC animated:YES]; - NSLog(@"[EPMineViewController] 打开设置页面"); + NSLog(@"[EPMineViewController] 打开设置页面,已传递用户信息"); +} + +- (void)onAvatarUpdated:(NSNotification *)notification { + NSString *avatarUrl = notification.userInfo[@"avatarUrl"]; + if (avatarUrl && self.userInfo) { + // 更新本地用户信息 + self.userInfo.avatar = avatarUrl; + + // 更新 UI 显示 + [self updateHeaderWithUserInfo:self.userInfo]; + + NSLog(@"[EPMineViewController] 头像已更新: %@", avatarUrl); + } } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; + // 只移除头像更新通知的观察者,设置按钮现在使用 block 回调 + [[NSNotificationCenter defaultCenter] removeObserver:self name:@"EPEditSettingAvatarUpdated" object:nil]; } @end diff --git a/YuMi/E-P/NewMine/Services/EPMineAPIHelper.h b/YuMi/E-P/NewMine/Services/EPMineAPIHelper.h index 9dd770b..8966727 100644 --- a/YuMi/E-P/NewMine/Services/EPMineAPIHelper.h +++ b/YuMi/E-P/NewMine/Services/EPMineAPIHelper.h @@ -24,6 +24,11 @@ NS_ASSUME_NONNULL_BEGIN completion:(void (^)(UserInfoModel * _Nullable userInfo))completion failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure; +/// 更新用户头像 +- (void)updateAvatarWithUrl:(NSString *)avatarUrl + completion:(void (^)(void))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/E-P/NewMine/Services/EPMineAPIHelper.m b/YuMi/E-P/NewMine/Services/EPMineAPIHelper.m index 2d21951..dab86d2 100644 --- a/YuMi/E-P/NewMine/Services/EPMineAPIHelper.m +++ b/YuMi/E-P/NewMine/Services/EPMineAPIHelper.m @@ -38,5 +38,17 @@ } uid:uid page:@"1" pageSize:@"20"]; } +- (void)updateAvatarWithUrl:(NSString *)avatarUrl + completion:(void (^)(void))completion + failure:(void (^)(NSInteger code, NSString * _Nullable msg))failure { + [Api userV2UploadAvatar:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + if (code == 200) { + if (completion) completion(); + } else { + if (failure) failure(code, msg); + } + } avatarUrl:avatarUrl needPay:@NO]; +} + @end diff --git a/YuMi/E-P/NewMine/Views/EPMineHeaderView.h b/YuMi/E-P/NewMine/Views/EPMineHeaderView.h index 38f3048..f9de325 100644 --- a/YuMi/E-P/NewMine/Views/EPMineHeaderView.h +++ b/YuMi/E-P/NewMine/Views/EPMineHeaderView.h @@ -14,6 +14,9 @@ NS_ASSUME_NONNULL_BEGIN /// 大圆形头像 + 渐变背景 + 用户信息展示 @interface EPMineHeaderView : UIView +/// 设置按钮点击回调 +@property (nonatomic, copy, nullable) void(^onSettingsButtonTapped)(void); + /// 更新用户信息 /// @param userInfoDict 用户信息字典 - (void)updateWithUserInfo:(NSDictionary *)userInfoDict; diff --git a/YuMi/E-P/NewMine/Views/EPMineHeaderView.m b/YuMi/E-P/NewMine/Views/EPMineHeaderView.m index e1b9949..b1960f1 100644 --- a/YuMi/E-P/NewMine/Views/EPMineHeaderView.m +++ b/YuMi/E-P/NewMine/Views/EPMineHeaderView.m @@ -24,12 +24,6 @@ /// 设置按钮 @property (nonatomic, strong) UIButton *settingsButton; -/// 关注按钮 -@property (nonatomic, strong) UIButton *followButton; - -/// 粉丝按钮 -@property (nonatomic, strong) UIButton *fansButton; - @end @implementation EPMineHeaderView @@ -97,36 +91,6 @@ make.trailing.equalTo(self).offset(-20); make.size.mas_equalTo(CGSizeMake(40, 40)); }]; - - // 关注按钮 - self.followButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [self.followButton setTitle:@"关注" forState:UIControlStateNormal]; - [self.followButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - self.followButton.titleLabel.font = [UIFont systemFontOfSize:16]; - self.followButton.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2]; - self.followButton.layer.cornerRadius = 20; - [self addSubview:self.followButton]; - - [self.followButton mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(self.idLabel.mas_bottom).offset(20); - make.centerX.equalTo(self).offset(-50); - make.size.mas_equalTo(CGSizeMake(80, 40)); - }]; - - // 粉丝按钮 - self.fansButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [self.fansButton setTitle:@"粉丝" forState:UIControlStateNormal]; - [self.fansButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - self.fansButton.titleLabel.font = [UIFont systemFontOfSize:16]; - self.fansButton.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2]; - self.fansButton.layer.cornerRadius = 20; - [self addSubview:self.fansButton]; - - [self.fansButton mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(self.idLabel.mas_bottom).offset(20); - make.centerX.equalTo(self).offset(50); - make.size.mas_equalTo(CGSizeMake(80, 40)); - }]; } - (void)updateWithUserInfo:(NSDictionary *)userInfoDict { @@ -138,14 +102,6 @@ NSString *uid = userInfoDict[@"uid"] ?: @""; self.idLabel.text = [NSString stringWithFormat:@"ID:%@", uid]; - // 更新关注数 - NSNumber *following = userInfoDict[@"following"] ?: @0; - [self.followButton setTitle:[NSString stringWithFormat:@"关注 %@", following] forState:UIControlStateNormal]; - - // 更新粉丝数 - NSNumber *followers = userInfoDict[@"followers"] ?: @0; - [self.fansButton setTitle:[NSString stringWithFormat:@"粉丝 %@", followers] forState:UIControlStateNormal]; - // 加载头像 NSString *avatarURL = userInfoDict[@"avatar"]; if (avatarURL && avatarURL.length > 0) { @@ -159,8 +115,10 @@ - (void)settingsButtonTapped { NSLog(@"[EPMineHeaderView] 设置按钮点击"); - // 发送通知给父视图 - [[NSNotificationCenter defaultCenter] postNotificationName:@"EPMineHeaderSettingsButtonTapped" object:nil]; + // 使用 block 回调 + if (self.onSettingsButtonTapped) { + self.onSettingsButtonTapped(); + } } -@end \ No newline at end of file +@end diff --git a/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m b/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m index 1ce2a7d..826370f 100644 --- a/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m +++ b/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m @@ -54,9 +54,6 @@ // MARK: - Setup UI - (void)setupUI { - // 先设置纯色背景作为兜底,避免白色闪烁 - self.view.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.97 alpha:1.0]; - UIImageView *bgImageView = [[UIImageView alloc] initWithImage:kImage(@"vc_bg")]; bgImageView.contentMode = UIViewContentModeScaleAspectFill; bgImageView.clipsToBounds = YES; diff --git a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.h b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.h deleted file mode 100644 index bebb1c8..0000000 --- a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// EPMomentAPIHelper_Deprecated.h -// YuMi -// -// Created by AI on 2025-10-10. -// -// ⚠️ DEPRECATED: 已被 EPMomentAPISwiftHelper.swift 替代 -// 原因: -// 1. 继承 BaseMvpPresenter 会引起 Bridging Header 依赖链问题 -// 2. Swift 版本更简洁、类型安全 -// 3. 功能已完整迁移到 Swift 版本 -// -// 保留此文件仅供参考,后续可删除 - -#import -#import "BaseMvpPresenter.h" -#import "MomentsInfoModel.h" -#import "MomentsListInfoModel.h" - -NS_ASSUME_NONNULL_BEGIN - -/// 推荐/我的动态列表数据源类型 -typedef NS_ENUM(NSInteger, EPMomentListSourceType) { - EPMomentListSourceTypeRecommend = 0, - EPMomentListSourceTypeMine = 1 -}; - -/// 统一封装 Moments 列表 API -@interface EPMomentAPIHelper : BaseMvpPresenter - -/// 拉取最新动态列表(默认 types:"0,2" 图片+文字) -- (void)fetchLatestMomentsWithNextID:(NSString *)nextID - completion:(void (^)(NSArray * _Nullable list, NSString *nextMomentID))completion - failure:(void(^)(NSInteger code, NSString * _Nullable msg))failure; - - - -@end - -NS_ASSUME_NONNULL_END - - diff --git a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.m b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.m deleted file mode 100644 index b55af98..0000000 --- a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.m +++ /dev/null @@ -1,44 +0,0 @@ -// -// EPMomentAPIHelper_Deprecated.m -// YuMi -// -// Created by AI on 2025-10-10. -// -// ⚠️ DEPRECATED: 已被 EPMomentAPISwiftHelper.swift 替代 -// 保留此文件仅供参考,后续可删除 - -#import -#import "EPMomentAPIHelper_Deprecated.h" -#import "Api+Moments.h" -#import "AccountInfoStorage.h" -#import "BaseModel.h" - - -@implementation EPMomentAPIHelper -// [Api momentsRecommendList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { -// if (code == 200 && data.data) { -// NSArray *array = [MomentsInfoModel modelsWithArray:data.data]; -// if (completion) completion(array ?: @[], 200, @"success"); -// } else { -// if (completion) completion(@[], code, msg); -// } -// } page:pageStr pageSize:pageSizeStr types:types]; - -- (void)fetchLatestMomentsWithNextID:(NSString *)nextID - completion:(void (^)(NSArray * _Nullable list, NSString *nextMomentID))completion - failure:(void(^)(NSInteger code, NSString * _Nullable msg))failure { - NSString *pageSizeStr = @"20"; - NSString *types = @"0,2"; // 图片+文字 - - [Api momentsLatestList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { - MomentsListInfoModel *listInfo = [MomentsListInfoModel modelWithDictionary:data.data]; - if (completion) completion(listInfo.dynamicList ?: @[], - listInfo.nextDynamicId); - } fail:^(NSInteger code, NSString * _Nullable msg) { - if (failure) failure(code, msg); - }] dynamicId:nextID pageSize:pageSizeStr types:types]; -} - -@end - - diff --git a/YuMi/E-P/NewTabBar/EPTabBarController.swift b/YuMi/E-P/NewTabBar/EPTabBarController.swift index 9a25661..ceda0e7 100644 --- a/YuMi/E-P/NewTabBar/EPTabBarController.swift +++ b/YuMi/E-P/NewTabBar/EPTabBarController.swift @@ -361,8 +361,51 @@ import SnapKit normalImage: normalImage, selectedImage: selectedImage ) + + // 设置 delegate 以监听页面切换 + nav.delegate = self + return nav } + + // MARK: - TabBar Visibility Control + + /// 显示悬浮 TabBar + private func showCustomTabBar(animated: Bool = true) { + guard customTabBarView.isHidden else { return } + + if animated { + customTabBarView.isHidden = false + customTabBarView.alpha = 0 + customTabBarView.transform = CGAffineTransform(translationX: 0, y: 20) + + UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseOut) { + self.customTabBarView.alpha = 1 + self.customTabBarView.transform = .identity + } + } else { + customTabBarView.isHidden = false + customTabBarView.alpha = 1 + } + } + + /// 隐藏悬浮 TabBar + private func hideCustomTabBar(animated: Bool = true) { + guard !customTabBarView.isHidden else { return } + + if animated { + UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseIn, animations: { + self.customTabBarView.alpha = 0 + self.customTabBarView.transform = CGAffineTransform(translationX: 0, y: 20) + }) { _ in + self.customTabBarView.isHidden = true + self.customTabBarView.transform = .identity + } + } else { + customTabBarView.isHidden = true + customTabBarView.alpha = 0 + } + } } // MARK: - UITabBarControllerDelegate @@ -389,6 +432,29 @@ extension EPTabBarController: UITabBarControllerDelegate { } } +// MARK: - UINavigationControllerDelegate + +extension EPTabBarController: UINavigationControllerDelegate { + + func navigationController(_ navigationController: UINavigationController, + willShow viewController: UIViewController, + animated: Bool) { + + // 判断是否是根页面(一级页面) + let isRootViewController = navigationController.viewControllers.count == 1 + + if isRootViewController { + // 一级页面:显示 TabBar + showCustomTabBar(animated: animated) + NSLog("[EPTabBarController] 显示 TabBar - 根页面") + } else { + // 二级及以上页面:隐藏 TabBar + hideCustomTabBar(animated: animated) + NSLog("[EPTabBarController] 隐藏 TabBar - 子页面 (层级: \(navigationController.viewControllers.count))") + } + } +} + // MARK: - OC Compatibility extension EPTabBarController { diff --git a/YuMi/YuMi-Bridging-Header.h b/YuMi/YuMi-Bridging-Header.h index 50760db..f1f15cd 100644 --- a/YuMi/YuMi-Bridging-Header.h +++ b/YuMi/YuMi-Bridging-Header.h @@ -45,6 +45,9 @@ #import "YYUtility.h" #import "SDWebImage.h" +// MARK: - API Helpers +#import "EPMineAPIHelper.h" + // MARK: - Utilities #import "UIImage+Utils.h" #import "NSString+Utils.h"