// // EPMomentPublishViewController.m // YuMi // // Created by AI on 2025-10-10. // // NOTE: 话题选择功能未实现 // 旧版本 XPMonentsPublishViewController 包含话题选择 UI (addTopicView) // 但实际业务中话题功能使用率低,新版本暂不实现 // 如需实现参考: YuMi/Modules/YMMonents/View/XPMonentsPublishTopicView #import "EPMomentPublishViewController.h" #import #import #import "DJDKMIMOMColor.h" #import "SZTextView.h" #import "YuMi-Swift.h" #import "EPEmotionColorPicker.h" #import "EPEmotionColorStorage.h" #import "UIView+GradientLayer.h" // 发布成功通知 NSString *const EPMomentPublishSuccessNotification = @"EPMomentPublishSuccessNotification"; @interface EPMomentPublishViewController () @property (nonatomic, strong) UIView *navView; @property (nonatomic, strong) UIButton *backButton; @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UIButton *publishButton; @property (nonatomic, strong) UIView *contentView; @property (nonatomic, strong) SZTextView *textView; @property (nonatomic, strong) UILabel *limitLabel; @property (nonatomic, strong) UIView *lineView; @property (nonatomic, strong) UIButton *emotionButton; @property (nonatomic, strong) UICollectionView *collectionView; @property (nonatomic, strong) NSMutableArray *images; @property (nonatomic, strong) NSMutableArray *selectedAssets; // TZImagePicker 已选资源 @property (nonatomic, copy) NSString *selectedEmotionColor; // 选中的情绪颜色 @property (nonatomic, assign) BOOL hasAddedGradient; // 标记是否已添加渐变背景 @end @implementation EPMomentPublishViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor colorWithRed:0x0C/255.0 green:0x05/255.0 blue:0x27/255.0 alpha:1.0]; [self setupUI]; // 自动加载用户专属颜色 [self loadUserSignatureColor]; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // 添加渐变背景到发布按钮(只添加一次) if (!self.hasAddedGradient && self.publishButton.bounds.size.width > 0) { // 使用与登录页面相同的渐变颜色(EPLoginConfig.Colors) // gradientStart: #F854FC, gradientEnd: #500FFF [self.publishButton addGradientBackgroundWithColors:@[ [UIColor colorWithRed:0xF8/255.0 green:0x54/255.0 blue:0xFC/255.0 alpha:1.0], // #F854FC [UIColor colorWithRed:0x50/255.0 green:0x0F/255.0 blue:0xFF/255.0 alpha:1.0] // #500FFF ] startPoint:CGPointMake(0, 0.5) endPoint:CGPointMake(1, 0.5) cornerRadius:25]; self.hasAddedGradient = YES; } } /// 加载用户专属颜色作为默认选中 - (void)loadUserSignatureColor { NSString *signatureColor = [EPEmotionColorStorage userSignatureColor]; if (signatureColor) { self.selectedEmotionColor = signatureColor; [self updateEmotionButtonAppearance]; NSLog(@"[Publish] 自动选中专属颜色: %@", signatureColor); } } - (void)setupUI { [self.view addSubview:self.navView]; [self.view addSubview:self.contentView]; [self.navView addSubview:self.backButton]; [self.navView addSubview:self.titleLabel]; // 发布按钮移到底部 [self.contentView addSubview:self.textView]; [self.contentView addSubview:self.limitLabel]; [self.contentView addSubview:self.lineView]; [self.contentView addSubview:self.emotionButton]; [self.contentView addSubview:self.collectionView]; [self.contentView addSubview:self.publishButton]; [self.navView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.top.equalTo(self.view); make.height.mas_equalTo(kNavigationHeight); }]; [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.equalTo(self.view).offset(10); make.top.mas_equalTo(statusbarHeight); make.size.mas_equalTo(CGSizeMake(44, 44)); }]; [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.navView); make.centerY.equalTo(self.backButton); }]; // 发布按钮约束移到底部 [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.equalTo(self.view); make.top.equalTo(self.navView.mas_bottom); make.bottom.equalTo(self.view); }]; [self.textView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.equalTo(self.contentView).inset(15); make.top.equalTo(self.contentView).offset(10); make.height.mas_equalTo(150); }]; [self.limitLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.textView.mas_bottom).offset(5); make.trailing.equalTo(self.textView); }]; [self.lineView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.limitLabel.mas_bottom).offset(10); make.leading.trailing.equalTo(self.textView); make.height.mas_equalTo(1); }]; // 情绪按钮 [self.emotionButton mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.equalTo(self.contentView).inset(15); make.top.equalTo(self.lineView.mas_bottom).offset(10); make.height.mas_equalTo(44); }]; // 计算显示3行图片所需的高度 // itemW = (屏幕宽度 - 左右边距30 - 列间距20) / 3 // 总高度 = 3行itemW + 2个行间距(10*2) CGFloat itemW = (KScreenWidth - 15*2 - 10*2)/3.0; CGFloat collectionHeight = itemW * 3 + 10 * 2; [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.equalTo(self.contentView).inset(15); make.top.equalTo(self.emotionButton.mas_bottom).offset(10); make.height.mas_equalTo(collectionHeight); }]; // 底部发布按钮 [self.publishButton mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.trailing.equalTo(self.view).inset(20); make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom).offset(-20); make.height.mas_equalTo(50); }]; } #pragma mark - Actions - (void)onBack { [self dismissViewControllerAnimated:YES completion:nil]; } - (void)onEmotionButtonTapped { EPEmotionColorPicker *picker = [[EPEmotionColorPicker alloc] init]; // 预选中当前颜色(如果有) picker.preselectedColor = self.selectedEmotionColor; __weak typeof(self) weakSelf = self; picker.onColorSelected = ^(NSString *hexColor) { __strong typeof(weakSelf) self = weakSelf; self.selectedEmotionColor = hexColor; [self updateEmotionButtonAppearance]; }; [picker showInView:self.view]; } - (void)updateEmotionButtonAppearance { if (self.selectedEmotionColor) { // 显示选中的颜色 UIColor *color = [self colorFromHex:self.selectedEmotionColor]; // 创建色块视图 UIView *colorDot = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)]; colorDot.backgroundColor = color; colorDot.layer.cornerRadius = 10; colorDot.layer.masksToBounds = YES; colorDot.layer.borderWidth = 2; colorDot.layer.borderColor = [UIColor whiteColor].CGColor; // 转换为 UIImage UIGraphicsBeginImageContextWithOptions(colorDot.bounds.size, NO, 0); [colorDot.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *colorDotImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); [self.emotionButton setImage:colorDotImage forState:UIControlStateNormal]; // 获取情绪名称 NSString *emotionName = [EPEmotionColorStorage emotionNameForColor:self.selectedEmotionColor]; NSString *title = emotionName ? [NSString stringWithFormat:@" Selected Emotion: %@", emotionName] : @" Emotion Selected"; [self.emotionButton setTitle:title forState:UIControlStateNormal]; } else { [self.emotionButton setImage:nil forState:UIControlStateNormal]; [self.emotionButton setTitle:@"🎨 Add Emotion" forState:UIControlStateNormal]; } } - (UIColor *)colorFromHex:(NSString *)hexString { unsigned rgbValue = 0; NSScanner *scanner = [NSScanner scannerWithString:hexString]; [scanner setScanLocation:1]; // 跳过 # [scanner scanHexInt:&rgbValue]; return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0]; } - (void)onPublish { [self.view endEditing:YES]; // 验证:文本或图片至少有一项 if (self.textView.text.length == 0 && self.images.count == 0) { [EPProgressHUD showError:YMLocalizedString(@"publish.content_or_image_required")]; return; } // 创建 Swift API Helper EPMomentAPISwiftHelper *apiHelper = [[EPMomentAPISwiftHelper alloc] init]; // 保存情绪颜色用于发布后关联 NSString *emotionColorToSave = self.selectedEmotionColor; if (self.images.count > 0) { // 有图片:上传后发布(统一入口) [[EPSDKManager shared] uploadImages:self.images progress:^(NSInteger uploaded, NSInteger total) { [EPProgressHUD showProgress:uploaded total:total]; } success:^(NSArray *resList) { [EPProgressHUD dismiss]; [apiHelper publishMomentWithType:@"2" content:self.textView.text ?: @"" resList:resList completion:^{ // 保存临时情绪颜色(等待列表刷新后匹配) if (emotionColorToSave) { [self savePendingEmotionColor:emotionColorToSave]; } // 发送发布成功通知 [[NSNotificationCenter defaultCenter] postNotificationName:EPMomentPublishSuccessNotification object:nil]; [self dismissViewControllerAnimated:YES completion:nil]; } failure:^(NSInteger code, NSString *msg) { // TODO: 显示错误 Toast NSLog(@"发布失败: %ld - %@", (long)code, msg); }]; } failure:^(NSString *errorMsg) { [EPProgressHUD dismiss]; // TODO: 显示错误 Toast NSLog(@"上传失败: %@", errorMsg); }]; } else { // 纯文本:直接发布 [apiHelper publishMomentWithType:@"0" content:self.textView.text resList:@[] completion:^{ // 保存临时情绪颜色(等待列表刷新后匹配) if (emotionColorToSave) { [self savePendingEmotionColor:emotionColorToSave]; } // 发送发布成功通知 [[NSNotificationCenter defaultCenter] postNotificationName:EPMomentPublishSuccessNotification object:nil]; [self dismissViewControllerAnimated:YES completion:nil]; } failure:^(NSInteger code, NSString *msg) { // TODO: 显示错误 Toast NSLog(@"发布失败: %ld - %@", (long)code, msg); }]; } } /// 保存待处理的情绪颜色(临时存储,供列表刷新后匹配) - (void)savePendingEmotionColor:(NSString *)color { [[NSUserDefaults standardUserDefaults] setObject:color forKey:@"EP_Pending_Emotion_Color"]; [[NSUserDefaults standardUserDefaults] setObject:@([[NSDate date] timeIntervalSince1970]) forKey:@"EP_Pending_Emotion_Timestamp"]; [[NSUserDefaults standardUserDefaults] synchronize]; } #pragma mark - UICollectionView - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return self.images.count + 1; // 最后一个是添加按钮 } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ep.publish.cell" forIndexPath:indexPath]; cell.contentView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.06]; cell.contentView.layer.cornerRadius = 12; // 清空复用子视图,避免加号被覆盖 for (UIView *sub in cell.contentView.subviews) { [sub removeFromSuperview]; } BOOL showAdd = (self.images.count < 9) && (indexPath.item == self.images.count); if (showAdd) { UIImageView *iv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"icon_moment_addphoto"]]; iv.contentMode = UIViewContentModeScaleAspectFill; iv.clipsToBounds = YES; [cell.contentView addSubview:iv]; [iv mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(cell.contentView); }]; } else { UIImageView *iv = [[UIImageView alloc] init]; iv.contentMode = UIViewContentModeScaleAspectFill; iv.layer.masksToBounds = YES; [cell.contentView addSubview:iv]; [iv mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(cell.contentView); }]; NSInteger idx = MIN(indexPath.item, (NSInteger)self.images.count - 1); if (idx >= 0 && idx < self.images.count) iv.image = self.images[idx]; } return cell; } - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.item == self.images.count) { TZImagePickerController *picker = [[TZImagePickerController alloc] initWithMaxImagesCount:9 delegate:self]; picker.allowPickingVideo = NO; picker.allowTakeVideo = NO; picker.selectedAssets = self.selectedAssets; // 预选 picker.maxImagesCount = 9; // 总上限 [self presentViewController:picker animated:YES completion:nil]; } } #pragma mark - TZImagePickerControllerDelegate - (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray *)infos { // 合并选择:在已有基础上追加,最多 9 张 for (NSInteger i = 0; i < assets.count; i++) { id asset = assets[i]; UIImage *img = [photos xpSafeObjectAtIndex:i] ?: photos[i]; if (![self.selectedAssets containsObject:asset] && self.images.count < 9) { [self.selectedAssets addObject:asset]; [self.images addObject:img]; } } [self.collectionView reloadData]; } #pragma mark - UITextViewDelegate - (void)textViewDidChange:(UITextView *)textView { if (textView.text.length > 500) { textView.text = [textView.text substringToIndex:500]; } self.limitLabel.text = [NSString stringWithFormat:@"%lu/500", (unsigned long)textView.text.length]; } #pragma mark - Lazy - (UIView *)navView { if (!_navView) { _navView = [UIView new]; _navView.backgroundColor = [UIColor clearColor]; } return _navView; } - (UIButton *)backButton { if (!_backButton) { _backButton = [UIButton buttonWithType:UIButtonTypeCustom]; // 使用系统返回图标 UIImage *backImage = [UIImage systemImageNamed:@"chevron.left"]; UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:20 weight:UIImageSymbolWeightMedium]; backImage = [backImage imageByApplyingSymbolConfiguration:config]; [_backButton setImage:backImage forState:UIControlStateNormal]; [_backButton setTintColor:[UIColor whiteColor]]; // 白色适配深色背景 [_backButton addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside]; } return _backButton; } - (UILabel *)titleLabel { if (!_titleLabel) { _titleLabel = [UILabel new]; _titleLabel.text = YMLocalizedString(@"publish.title"); _titleLabel.textColor = [UIColor whiteColor]; // 白色适配深色背景 _titleLabel.font = [UIFont systemFontOfSize:17]; } return _titleLabel; } - (UIButton *)publishButton { if (!_publishButton) { _publishButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_publishButton setTitle:YMLocalizedString(@"common.publish") forState:UIControlStateNormal]; [_publishButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; _publishButton.titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightMedium]; _publishButton.layer.cornerRadius = 25; _publishButton.layer.masksToBounds = NO; // 改为 NO 以便渐变层正常显示 // 渐变背景将在 viewDidLayoutSubviews 中添加(与登录页面统一) [_publishButton addTarget:self action:@selector(onPublish) forControlEvents:UIControlEventTouchUpInside]; } return _publishButton; } - (UIView *)contentView { if (!_contentView) { _contentView = [UIView new]; _contentView.backgroundColor = [UIColor clearColor]; } return _contentView; } - (SZTextView *)textView { if (!_textView) { _textView = [SZTextView new]; _textView.placeholder = @"Enter Content"; _textView.textColor = [UIColor whiteColor]; // 白色文本适配深色背景 _textView.placeholderTextColor = [[UIColor whiteColor] colorWithAlphaComponent:0.4]; // 半透明白色占位符 _textView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.08]; // 轻微背景色 _textView.layer.cornerRadius = 12; _textView.layer.masksToBounds = YES; _textView.font = [UIFont systemFontOfSize:15]; _textView.delegate = self; } return _textView; } - (UILabel *)limitLabel { if (!_limitLabel) { _limitLabel = [UILabel new]; _limitLabel.text = @"0/500"; _limitLabel.textColor = [[UIColor whiteColor] colorWithAlphaComponent:0.6]; // 浅色适配深色背景 _limitLabel.font = [UIFont systemFontOfSize:12]; } return _limitLabel; } - (UIView *)lineView { if (!_lineView) { _lineView = [UIView new]; _lineView.backgroundColor = [DJDKMIMOMColor dividerColor]; } return _lineView; } - (UIButton *)emotionButton { if (!_emotionButton) { _emotionButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_emotionButton setTitle:@"🎨 Add Emotion" forState:UIControlStateNormal]; [_emotionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; // 白色文本 _emotionButton.titleLabel.font = [UIFont systemFontOfSize:15]; _emotionButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; _emotionButton.contentEdgeInsets = UIEdgeInsetsMake(0, 15, 0, 0); _emotionButton.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.08]; // 稍微提亮背景 _emotionButton.layer.cornerRadius = 8; _emotionButton.layer.masksToBounds = YES; [_emotionButton addTarget:self action:@selector(onEmotionButtonTapped) forControlEvents:UIControlEventTouchUpInside]; } return _emotionButton; } - (UICollectionView *)collectionView { if (!_collectionView) { UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.minimumLineSpacing = 10; layout.minimumInteritemSpacing = 10; CGFloat itemW = (KScreenWidth - 15*2 - 10*2)/3.0; layout.itemSize = CGSizeMake(itemW, itemW); _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; _collectionView.delegate = self; _collectionView.dataSource = self; _collectionView.backgroundColor = [UIColor clearColor]; [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"ep.publish.cell"]; } return _collectionView; } - (NSMutableArray *)images { if (!_images) { _images = [NSMutableArray array]; } return _images; } - (NSMutableArray *)selectedAssets { if (!_selectedAssets) { _selectedAssets = [NSMutableArray array]; } return _selectedAssets; } @end