From 298a7e80c47b2fba237f14825cbefd8d87c7c373 Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Wed, 21 May 2025 18:59:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=86=85=E8=B4=AD=E4=BA=A4?= =?UTF-8?q?=E6=98=93=E9=87=8D=E8=AF=95=E6=9C=BA=E5=88=B6=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BA=A4=E6=98=93=E9=87=8D=E8=AF=95=E6=AC=A1=E6=95=B0?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=EF=BC=8C=E5=AE=8C=E5=96=84=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=A4=84=E7=90=86=EF=BC=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=9B=B8=E5=85=B3API=E6=8E=A5=E5=8F=A3=EF=BC=8C=E8=B0=83?= =?UTF-8?q?=E6=95=B4UI=E7=BB=84=E4=BB=B6=E7=BA=A6=E6=9D=9F=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86UI=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0=E6=9C=AC=E5=9C=B0=E5=8C=96=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=B8=B2=E3=80=82=E7=89=88=E6=9C=AC=E5=8F=B7=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E8=87=B320.20.63=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YuMi/Modules/YMMine/Api/Api+Mine.m | 1 - .../View/Cell/XPMineBlackListTableViewCell.m | 8 +- .../Modules/YMMine/View/Recharge/IAPManager.m | 235 ++++++++++++++---- YuMi/Modules/YMNewHome/Api/Api+EventCenter.h | 2 + YuMi/Modules/YMNewHome/Api/Api+EventCenter.m | 4 + .../Presenter/CreateEventPresenter.h | 6 +- .../Presenter/CreateEventPresenter.m | 14 +- .../View/Cell/EventCenterEventCell.m | 5 +- .../View/CreateEventViewControllerV2.m | 33 ++- .../View/EventCenterViewController.m | 18 +- .../YMNewHome/View/MyEventsViewController.m | 4 + .../YMRoom/View/UserCard/Api/Api+UserCard.h | 6 + .../YMRoom/View/UserCard/Api/Api+UserCard.m | 5 + .../UserCard/Presenter/XPUserCardPresenter.h | 2 +- .../UserCard/Presenter/XPUserCardPresenter.m | 6 +- .../View/UserRoomCardViewController.m | 4 +- .../UserCard/View/XPUserCardViewController.m | 2 +- YuMi/Modules/YMWeb/MSRoomGameWebVC.m | 3 +- YuMi/ar.lproj/Localizable.strings | 2 +- YuMi/en.lproj/Localizable.strings | 2 +- YuMi/tr.lproj/Localizable.strings | 2 +- YuMi/zh-Hant.lproj/Localizable.strings | 2 +- 22 files changed, 291 insertions(+), 75 deletions(-) diff --git a/YuMi/Modules/YMMine/Api/Api+Mine.m b/YuMi/Modules/YMMine/Api/Api+Mine.m index 666b5a7d..f892fd3b 100644 --- a/YuMi/Modules/YMMine/Api/Api+Mine.m +++ b/YuMi/Modules/YMMine/Api/Api+Mine.m @@ -188,7 +188,6 @@ /// @param uid 用户uid /// @param ticket ticket + (void)checkReceipt:(HttpRequestHelperCompletion)completion chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId transcationId:(NSString *)transcationId uid:(NSString *)uid ticket:(NSString *)ticket { - [self makeRequest:@"storeKitV2/verifyOrder" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, chooseEnv, chargeRecordId, transcationId, uid, ticket, nil]; } diff --git a/YuMi/Modules/YMMine/View/Cell/XPMineBlackListTableViewCell.m b/YuMi/Modules/YMMine/View/Cell/XPMineBlackListTableViewCell.m index a7647039..f34be363 100644 --- a/YuMi/Modules/YMMine/View/Cell/XPMineBlackListTableViewCell.m +++ b/YuMi/Modules/YMMine/View/Cell/XPMineBlackListTableViewCell.m @@ -57,7 +57,7 @@ [self.removeButton mas_makeConstraints:^(MASConstraintMaker *make) { make.trailing.mas_equalTo(self.contentView).offset(-8); make.centerY.mas_equalTo(self.contentView); - make.height.mas_equalTo(30); + make.height.mas_equalTo(25); make.width.mas_greaterThanOrEqualTo(60); }]; } @@ -103,11 +103,11 @@ _removeButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_removeButton.titleLabel setFont:kFontRegular(13)]; [_removeButton setTitle:YMLocalizedString(@"XPMineBlackListViewController1") forState:UIControlStateNormal]; - [_removeButton setTitleColor:UIColorFromRGB(0xfcc074) forState:UIControlStateNormal]; - [_removeButton setCornerRadius:15 + [_removeButton setTitleColor:UIColorFromRGB(0xff8c03) forState:UIControlStateNormal]; + [_removeButton setCornerRadius:25/2 corners:kCALayerMaxXMaxYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner | kCALayerMinXMinYCorner borderWidth:1 - borderColor:UIColorFromRGB(0xfcc074)]; + borderColor:UIColorFromRGB(0xff8c03)]; _removeButton.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 10); _removeButton.titleLabel.lineBreakMode = NSLineBreakByClipping; _removeButton.clipsToBounds = NO; diff --git a/YuMi/Modules/YMMine/View/Recharge/IAPManager.m b/YuMi/Modules/YMMine/View/Recharge/IAPManager.m index 8635f537..09da92a5 100644 --- a/YuMi/Modules/YMMine/View/Recharge/IAPManager.m +++ b/YuMi/Modules/YMMine/View/Recharge/IAPManager.m @@ -6,11 +6,13 @@ // #import "IAPManager.h" - +#import #import "Api+Mine.h" #import "YuMi-swift.h" #import "RechargeStorage.h" +#define MAX_RETRY_COUNT 10 + @interface IAPManager() @property (nonatomic, assign) BOOL isLogin; @@ -28,6 +30,9 @@ @property (nonatomic, copy) void(^failurePurchase)(NSError *error); @property (nonatomic, copy) void(^contactCustomerService)(NSString *uid); +// 记录交易重试次数 +@property (nonatomic, strong) NSMutableDictionary *retryCountMap; + @end @implementation IAPManager @@ -41,6 +46,7 @@ proxy.recheckIndex = 0; proxy.recheckInterval = 1.0; + proxy.retryCountMap = [NSMutableDictionary dictionary]; }); return proxy; @@ -84,15 +90,27 @@ // 定时轮训未完成的订单并进行验单 - (void)retryCheckAllReceipt { - self.recheckTimer = [NSTimer scheduledTimerWithTimeInterval:self.recheckInterval - target:self - selector:@selector(handleRetryCheckReceipt) - userInfo:nil - repeats:NO]; + // 先清理旧定时器 + if (self.recheckTimer) { + [self.recheckTimer invalidate]; + self.recheckTimer = nil; + } + + // 设置最大重试间隔 + NSTimeInterval interval = MIN(self.recheckInterval, 300.0); + + // 使用传统定时器创建方式,避免在旧版iOS上的兼容性问题 + self.recheckTimer = [NSTimer scheduledTimerWithTimeInterval:interval + target:self + selector:@selector(handleRetryCheckReceipt) + userInfo:nil + repeats:NO]; } // 验单逻辑 - (void)handleRetryCheckReceipt { +// NSLog(@"[YuMi IAP] 用户触发补单检查 - Retry checking receipts"); + NSArray *array = [RechargeStorage getAllReceiptsWithUid:[AccountInfoStorage instance].getUid]; // NSLog(@" ------------.------------ 尝试:%@", array); @synchronized (array) { @@ -107,21 +125,46 @@ if (self.recheckIndex >= array.count) { self.recheckIndex = 0; } - +#if DEBUG // [self requestAPPOrderData:@"com.hflighting.yumi.gold.1_7000" isFroRecheck:YES]; - +#endif self.isProcessing = YES; NSDictionary *dic = [array xpSafeObjectAtIndex:self.recheckIndex]; NSString *transactionId = dic[@"transactionId"]; + + [self _logToBugly:transactionId oID:dic[@"orderId"] status:0]; + + NSInteger retryCount = [self getRetryCountForTransaction:transactionId]; + + if (retryCount > MAX_RETRY_COUNT) { + // 超过最大重试次数,记录并清理 + [self _logToBugly:transactionId oID:dic[@"orderId"] status:4]; // 新状态:重试次数过多 + [RechargeStorage delegateTransactionId:transactionId uid:[AccountInfoStorage instance].getUid]; + self.isProcessing = NO; + return; + } + + // 增加重试计数 + [self incrementRetryCountForTransaction:transactionId]; + + @kWeakify(self); [self backgroundCheckReceiptWithTransactionID:transactionId orderID:dic[@"orderId"] next:^(BOOL isSuccess){ + @kStrongify(self); if (isSuccess) { [RechargeStorage delegateTransactionId:transactionId uid:[AccountInfoStorage instance].getUid]; - self.recheckInterval = 1.0; + self.recheckInterval = MIN(self.recheckInterval * 2, 300.0); + + [self _logToBugly:transactionId oID:dic[@"orderId"] status:1]; + + // 成功后移除重试记录 + [self removeRetryCountForTransaction:transactionId]; + } else { self.recheckInterval = self.recheckInterval * 2; + [self _logToBugly:transactionId oID:dic[@"orderId"] status:2]; } self.recheckIndex += 1; @@ -134,6 +177,51 @@ } } +- (void)_logToBugly:(NSString *)tid oID:(NSString *)oid status:(NSInteger)status { + + NSMutableDictionary *logDic = [NSMutableDictionary dictionary]; + [logDic setObject:tid forKey:@"内购 transactionId"]; + [logDic setObject:oid forKey:@"内购 orderId"]; + [logDic setObject:[AccountInfoStorage instance].getUid forKey:@"内购 用户id"]; + + NSString *statusMsg = @""; + NSInteger code = -20000; + switch (status) { + case 0: + statusMsg = [NSString stringWithFormat:@"UID: %@, 尝试验单", + [AccountInfoStorage instance].getUid]; + break; + case 1: + statusMsg = [NSString stringWithFormat:@"UID: %@, 验单-补单成功", + [AccountInfoStorage instance].getUid]; + code = -20001; + break; + case 2: + statusMsg = [NSString stringWithFormat:@"UID: %@, 验单-补单失败", + [AccountInfoStorage instance].getUid]; + code = -20002; + break; + case 3: + statusMsg = [NSString stringWithFormat:@"UID: %@, 验单-补单 id 异常", + [AccountInfoStorage instance].getUid]; + code = -20002; + break; + case 4: + statusMsg = [NSString stringWithFormat:@"UID: %@, 重试次数过多", + [AccountInfoStorage instance].getUid]; + code = -20003; + break; + default: + break; + } + + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + [Bugly reportError:[NSError errorWithDomain:statusMsg + code:code + userInfo:logDic]]; + }); +} + // 内购成功并通知外部 - (void)handleSuccessPurchase:(NSString *)tID order:(NSString *)orderID { if (self.successPurchase) { @@ -312,27 +400,20 @@ // 内购付款成功后保存收据 id 到钥匙串 - (void)saveTransactionID { NSString *encodedReceipt = [self fetchEncodedReceipt]; - // 初始化字典并逐步填充 NSMutableDictionary *receiptInfo = [NSMutableDictionary dictionary]; - - // 使用通用方法添加字典键值对,减少冗余代码 + [self addValueIfNotNil:self.transactionID forKey:@"transactionId" toDictionary:receiptInfo]; [self addValueIfNotNil:encodedReceipt forKey:@"receipt" toDictionary:receiptInfo]; [self addValueIfNotNil:self.orderID forKey:@"orderId" toDictionary:receiptInfo]; - - // 如果字典为空,直接返回 - if (receiptInfo.count == 0) { - return; - } - - // 保存数据到 RechargeStorage + + // 添加时间戳便于后续判断过期交易 + [receiptInfo setObject:[[NSDate date] description] forKey:@"timestamp"]; + @synchronized (self.transactionID) { [RechargeStorage saveTransactionId:self.transactionID - receipt:[receiptInfo toJSONString] - uid:[AccountInfoStorage instance].getUid]; + receipt:[receiptInfo toJSONString] + uid:[AccountInfoStorage instance].getUid]; } - - // NSLog(@" ------------.------------ 保存账单内容:%@ ", receiptInfo); } // 通过苹果收据与后端订单进行验单与发货 @@ -368,31 +449,26 @@ orderID:(NSString *)orderID next:(void(^)(BOOL isSuccess))next { - // NSLog(@" ------------.------------ 尝试后端验单:%@ | %@", tID, orderID); - - if (![self isValidTransactionID:tID orderID:orderID]) { - // 本地数据异常,不重试 - [self handleCheckReceiptSuccess:tID isFromRecheck:YES]; - next(NO); - return; - } + // 创建后台任务标识 + UIBackgroundTaskIdentifier backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"VerifyReceipt" + expirationHandler:^{ + // 超时处理 + if (next) { + next(NO); + } + [[UIApplication sharedApplication] endBackgroundTask:backgroundTask]; + }]; + // 原验证代码... + // 完成后务必结束后台任务 @kWeakify(self); [Api checkReceipt:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); - if (code == 200) { - [self handleCheckReceiptSuccess:tID isFromRecheck:YES]; - } else if (code == 1701) { - // 交易已完成,無需重複請求 - [self handleCheckReceiptSuccess:tID isFromRecheck:YES]; - } + // 原有验证代码... - // NSLog(@" ------------.------------ 尝试后端验单结果:%ld, %@ ", (long)code, msg); - - if (next) { - next(code == 200 || code == 1701); - } + // 结束后台任务 + [[UIApplication sharedApplication] endBackgroundTask:backgroundTask]; } chooseEnv:@"true" chargeRecordId:orderID @@ -414,6 +490,8 @@ // 流程完成,移除本地缓存账单 [RechargeStorage delegateTransactionId:tID uid:[AccountInfoStorage instance].getUid]; + // 成功后移除重试记录 + [self removeRetryCountForTransaction:tID]; } else { // 出现异常 // NSLog(@" ------------.------------ apple 验单成功:%@ ",error); @@ -421,6 +499,8 @@ // 该订单在 appstore 已无法找到,不必再重试 [RechargeStorage delegateTransactionId:tID uid:[AccountInfoStorage instance].getUid]; + // 清理不存在的交易记录 + [self removeRetryCountForTransaction:tID]; } else { [self retryCheckAllReceipt]; } @@ -443,4 +523,75 @@ } } +// 添加 dealloc 方法确保定时器释放 +- (void)dealloc { + if (self.recheckTimer) { + [self.recheckTimer invalidate]; + self.recheckTimer = nil; + } +} + +// 在应用进入后台时暂停定时器 +- (void)applicationDidEnterBackground { + if (self.recheckTimer) { + [self.recheckTimer invalidate]; + self.recheckTimer = nil; + } +} + +// 在应用恢复活动时重新启动定时器 +- (void)applicationWillEnterForeground { + if (self.isLogin) { + [self retryCheckAllReceipt]; + } +} + +// 清理长时间未处理的交易记录 +- (void)cleanupStaleTransactions { + NSArray *receipts = [RechargeStorage getAllReceiptsWithUid:[AccountInfoStorage instance].getUid]; + NSDate *now = [NSDate date]; + + for (NSDictionary *receipt in receipts) { + // 检查交易时间,如果超过7天还未成功,则清理 + NSString *timestamp = receipt[@"timestamp"]; + if (timestamp) { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"]; // 根据实际时间格式调整 + NSDate *transactionDate = [dateFormatter dateFromString:timestamp]; + + if (transactionDate && [now timeIntervalSinceDate:transactionDate] > 70 * 24 * 60 * 60) { + NSString *tID = receipt[@"transactionId"]; + [RechargeStorage delegateTransactionId:tID uid:[AccountInfoStorage instance].getUid]; + [self _logToBugly:tID oID:receipt[@"orderId"] status:5]; // 新状态:过期清理 + + // 清理过期交易的重试记录 + [self removeRetryCountForTransaction:tID]; + } + } + } +} + +// 获取交易的重试次数 +- (NSInteger)getRetryCountForTransaction:(NSString *)transactionId { + NSNumber *countNumber = self.retryCountMap[transactionId]; + return countNumber ? [countNumber integerValue] : 0; +} + +// 增加交易的重试次数 +- (void)incrementRetryCountForTransaction:(NSString *)transactionId { + NSInteger currentCount = [self getRetryCountForTransaction:transactionId]; + self.retryCountMap[transactionId] = @(currentCount + 1); +} + +// 移除交易的重试记录 +- (void)removeRetryCountForTransaction:(NSString *)transactionId { + [self.retryCountMap removeObjectForKey:transactionId]; +} + +// 清理所有重试记录 +- (void)cleanAllRetryCount { + [self.retryCountMap removeAllObjects]; +} + @end + diff --git a/YuMi/Modules/YMNewHome/Api/Api+EventCenter.h b/YuMi/Modules/YMNewHome/Api/Api+EventCenter.h index d9ab2498..fe77223c 100644 --- a/YuMi/Modules/YMNewHome/Api/Api+EventCenter.h +++ b/YuMi/Modules/YMNewHome/Api/Api+EventCenter.h @@ -75,6 +75,8 @@ NS_ASSUME_NONNULL_BEGIN /// 删除活动 + (void)usereventDel:(HttpRequestHelperCompletion)complection eventId:(NSNumber *)eventId; ++ (void)homeBanner:(HttpRequestHelperCompletion)complection uid:(NSString *)uid type:(NSString *)type activityShow:(NSNumber *)activityShow; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMNewHome/Api/Api+EventCenter.m b/YuMi/Modules/YMNewHome/Api/Api+EventCenter.m index 44171355..68728519 100644 --- a/YuMi/Modules/YMNewHome/Api/Api+EventCenter.m +++ b/YuMi/Modules/YMNewHome/Api/Api+EventCenter.m @@ -83,4 +83,8 @@ completion:complection, __FUNCTION__, eventId, nil]; } ++ (void)homeBanner:(HttpRequestHelperCompletion)complection uid:(NSString *)uid type:(NSString *)type activityShow:(NSNumber *)activityShow { + [self makeRequest:@"home/banner" method:HttpRequestHelperMethodGET completion:complection, __FUNCTION__, uid, type, activityShow, nil]; +} + @end diff --git a/YuMi/Modules/YMNewHome/Presenter/CreateEventPresenter.h b/YuMi/Modules/YMNewHome/Presenter/CreateEventPresenter.h index 6b7ff7a8..5ec21bb9 100644 --- a/YuMi/Modules/YMNewHome/Presenter/CreateEventPresenter.h +++ b/YuMi/Modules/YMNewHome/Presenter/CreateEventPresenter.h @@ -41,12 +41,16 @@ NS_ASSUME_NONNULL_BEGIN - (void)deleteEventSuccess:(NSInteger)eventId; - (void)deleteEventFailure:(NSString *)msg; +- (void)officialEventListSuccess:(EventRoomListModel *)listModel; +- (void)officialEventListFailure:(NSString *)msg; + + @end @interface CreateEventPresenter : BaseMvpPresenter - (void)loadConfig; - +- (void)loadOfficialEvents; - (void)loadEventSquare:(NSInteger)page; - (void)loadMyCreateEvents:(NSInteger)page; - (void)loadMySubEvents:(NSInteger)page; diff --git a/YuMi/Modules/YMNewHome/Presenter/CreateEventPresenter.m b/YuMi/Modules/YMNewHome/Presenter/CreateEventPresenter.m index 400a8759..e3ddbd83 100644 --- a/YuMi/Modules/YMNewHome/Presenter/CreateEventPresenter.m +++ b/YuMi/Modules/YMNewHome/Presenter/CreateEventPresenter.m @@ -7,7 +7,6 @@ #import "CreateEventPresenter.h" #import "Api+EventCenter.h" - #import @interface CreateEventPresenter() @@ -30,6 +29,19 @@ uid:[AccountInfoStorage instance].getUid]; } +- (void)loadOfficialEvents { + // TODO: 补充官方活动数据 / 调整创建活动时,选择开始时间的 bug + [Api homeBanner:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + if ([[self getView] respondsToSelector:@selector(officialEventListSuccess:)]) { + [[self getView] officialEventListSuccess:[EventConfigModel modelWithJSON:data.data]]; + } + } fail:^(NSInteger code, NSString * _Nullable msg) { + if ([[self getView] respondsToSelector:@selector(officialEventListFailure:)]) { + [[self getView] officialEventListFailure:msg]; + } + } showLoading:YES errorToast:YES] uid:[AccountInfoStorage instance].getUid type:@"1" activityShow:@(1)]; +} + - (void)loadEventSquare:(NSInteger)page { [Api usereventSquare:[self createHttpCompletion:^(BaseModel * _Nonnull data) { if ([[self getView] respondsToSelector:@selector(eventSquareListSuccess:)]) { diff --git a/YuMi/Modules/YMNewHome/View/Cell/EventCenterEventCell.m b/YuMi/Modules/YMNewHome/View/Cell/EventCenterEventCell.m index 9940ce64..3a7f5d34 100644 --- a/YuMi/Modules/YMNewHome/View/Cell/EventCenterEventCell.m +++ b/YuMi/Modules/YMNewHome/View/Cell/EventCenterEventCell.m @@ -345,7 +345,7 @@ NetImageConfig *config = [[NetImageConfig alloc] init]; config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; _avatarImageView = [[NetImageView alloc] initWithConfig:config]; - [_avatarImageView setCornerRadius:12 + [_avatarImageView setCornerRadius:35/2 corners:kCALayerMaxXMaxYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner | kCALayerMinXMinYCorner borderWidth:1 borderColor:[UIColor whiteColor]]; @@ -422,8 +422,7 @@ - (UIView *)blackMask { UIView *v = [[UIView alloc] init]; - v.backgroundColor = [UIColor colorWithWhite:0 alpha:0.6]; -// [v setCornerRadius:8]; + v.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5]; return v; } diff --git a/YuMi/Modules/YMNewHome/View/CreateEventViewControllerV2.m b/YuMi/Modules/YMNewHome/View/CreateEventViewControllerV2.m index 3c429700..9fa5f143 100644 --- a/YuMi/Modules/YMNewHome/View/CreateEventViewControllerV2.m +++ b/YuMi/Modules/YMNewHome/View/CreateEventViewControllerV2.m @@ -295,11 +295,12 @@ static const CGFloat kSectionSpacing = 20.0; TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self]; imagePickerVc.allowCrop = YES; - // 获取eventBannerImageView的实际尺寸比例 - CGFloat viewWidth = self.view.frame.size.width - (kHorizontalPadding * 2 - 2); - CGFloat viewHeight = kGetScaleWidth(118); - CGFloat cropWidth = MIN(viewWidth, KScreenWidth); - CGFloat cropHeight = (viewHeight / viewWidth) * cropWidth; + // 调整裁剪比例为 690:236 + CGFloat aspectRatio = 690.0 / 236.0; // 约为2.92:1 + + // 计算裁剪框宽度,限制在屏幕宽度内 + CGFloat cropWidth = MIN(self.view.frame.size.width - (kHorizontalPadding * 2 - 2), KScreenWidth); + CGFloat cropHeight = cropWidth / aspectRatio; // 设置裁剪框的尺寸 imagePickerVc.cropRect = CGRectMake((KScreenWidth-cropWidth)/2, (KScreenHeight - cropHeight) / 2, cropWidth, cropHeight); @@ -392,6 +393,21 @@ static const CGFloat kSectionSpacing = 20.0; notifyFans:notifyFans]; }]; } cancelHandler:^{ }]; + } else { + @kWeakify(self); + [self uploadCover:bannerImage + finish:^(NSString *path) { + @kStrongify(self); + [self.presenter createEventWithTitle:title + image:path + uploadToHome:uploadToHomepage + startTime:startTime + duration:self.durationMinutes + content:content + gold:uploadToHomepage ? self.configModel.goldNum : 0 + roomUid:self.selectRoomModel.roomUid + notifyFans:notifyFans]; + }]; } } @@ -508,8 +524,9 @@ static const CGFloat kSectionSpacing = 20.0; UIImage *selectedImage = info[UIImagePickerControllerOriginalImage]; if (selectedImage) { // 对于iOS 14以下版本,选择图片后手动裁剪 + CGFloat aspectRatio = 690.0 / 236.0; // 约为2.92:1 CGFloat viewWidth = self.view.frame.size.width - (kHorizontalPadding * 2 - 2); - CGFloat viewHeight = kGetScaleWidth(118); + CGFloat viewHeight = viewWidth / aspectRatio; CGSize cropSize = CGSizeMake(viewWidth, viewHeight); UIImage *croppedImage = [selectedImage cutImage:cropSize]; @@ -587,7 +604,9 @@ static const CGFloat kSectionSpacing = 20.0; [self.eventBannerImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.eventBannerLabel.mas_bottom).offset(kVerticalPadding); make.leading.trailing.equalTo(self.contentView).inset(kHorizontalPadding-1); - make.height.mas_equalTo(kGetScaleWidth(118)); // Adjust height as needed + + // 设置高度为宽度除以690:236的比例 + make.height.equalTo(self.eventBannerImageView.mas_width).multipliedBy(236.0/690.0); }]; [self.eventBannerCamearImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.bottom.trailing.equalTo(self.eventBannerImageView); diff --git a/YuMi/Modules/YMNewHome/View/EventCenterViewController.m b/YuMi/Modules/YMNewHome/View/EventCenterViewController.m index 805177c7..e8c7990a 100644 --- a/YuMi/Modules/YMNewHome/View/EventCenterViewController.m +++ b/YuMi/Modules/YMNewHome/View/EventCenterViewController.m @@ -179,11 +179,11 @@ static UIEdgeInsets kOfficialTableViewContentInset(void) { #pragma mark - Setup Data - (void)setOfficialEventModels:(NSArray *)officialEventModels { _officialDatasource = officialEventModels.mutableCopy; -#if DEBUG -#else - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"activityShow == %@", @(1)]; - [_officialDatasource filterUsingPredicate:predicate]; -#endif +//#if DEBUG +//#else +// NSPredicate *predicate = [NSPredicate predicateWithFormat:@"activityShow == %@", @(1)]; +// [_officialDatasource filterUsingPredicate:predicate]; +//#endif // 处理空数据状态 if (_officialDatasource.count == 0) { @@ -323,7 +323,7 @@ static UIEdgeInsets kOfficialTableViewContentInset(void) { }]; if (section == 0) { - UIImageView *arrow = [[UIImageView alloc] initWithImage:kImage(@"event_arrow_black")]; + UIImageView *arrow = [[UIImageView alloc] initWithImage:[kImage(@"event_arrow_black") ms_SetImageForRTL]]; arrow.userInteractionEnabled = YES; [v addSubview:arrow]; [arrow mas_makeConstraints:^(MASConstraintMaker *make) { @@ -619,9 +619,12 @@ static UIEdgeInsets kOfficialTableViewContentInset(void) { } - (void)eventSubActionSuccess:(BOOL)isSub eventId:(NSInteger)eventId { + NSInteger count = 0; if (isSub) { + count += 1; [XNDJTDDLoadingTool showSuccessWithMessage:YMLocalizedString(@"20.20.59_text_35")]; } else { + count -= 1; [XNDJTDDLoadingTool showSuccessWithMessage:YMLocalizedString(@"20.20.59_text_36")]; } @@ -630,6 +633,7 @@ static UIEdgeInsets kOfficialTableViewContentInset(void) { for (EventItemModel *m in self.eventSquareDatasource) { if (m.id == eventId) { m.subStatus = isSub; + m.subNum += count; break; } } @@ -639,12 +643,14 @@ static UIEdgeInsets kOfficialTableViewContentInset(void) { for (EventItemModel *m in self.mySubEventDatasource) { if (m.id == eventId) { m.subStatus = isSub; + m.subNum += count; break; } } for (EventItemModel *m in self.myCreateEventDatasource) { if (m.id == eventId) { m.subStatus = isSub; + m.subNum += count; break; } } diff --git a/YuMi/Modules/YMNewHome/View/MyEventsViewController.m b/YuMi/Modules/YMNewHome/View/MyEventsViewController.m index 1005c387..3a3facbf 100644 --- a/YuMi/Modules/YMNewHome/View/MyEventsViewController.m +++ b/YuMi/Modules/YMNewHome/View/MyEventsViewController.m @@ -129,15 +129,19 @@ } - (void)eventSubActionSuccess:(BOOL)isSub eventId:(NSInteger)eventId { + NSInteger count = 0; if (isSub) { + count += 1; [XNDJTDDLoadingTool showSuccessWithMessage:YMLocalizedString(@"20.20.59_text_35")]; } else { + count -= 1; [XNDJTDDLoadingTool showSuccessWithMessage:YMLocalizedString(@"20.20.59_text_36")]; } for (EventItemModel *m in self.datasource) { if (m.id == eventId) { m.subStatus = isSub; + m.subNum += count; break; } } diff --git a/YuMi/Modules/YMRoom/View/UserCard/Api/Api+UserCard.h b/YuMi/Modules/YMRoom/View/UserCard/Api/Api+UserCard.h index 1e258176..3dcba9fc 100644 --- a/YuMi/Modules/YMRoom/View/UserCard/Api/Api+UserCard.h +++ b/YuMi/Modules/YMRoom/View/UserCard/Api/Api+UserCard.h @@ -60,6 +60,12 @@ NS_ASSUME_NONNULL_BEGIN /// @param completion 完成 /// @param roomUid 房主的uid + (void)checkManageNum:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid; + +/// 添加移除管理员(后段管理的用户关系) +/// Long roomUid, +/// Long uid, +/// Integer opt, //1添加,2移除 ++ (void)updateRoleToServer:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid uid:(NSString *)uid opt:(NSString *)opt ; @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/UserCard/Api/Api+UserCard.m b/YuMi/Modules/YMRoom/View/UserCard/Api/Api+UserCard.m index f880aeb0..e7d410aa 100644 --- a/YuMi/Modules/YMRoom/View/UserCard/Api/Api+UserCard.m +++ b/YuMi/Modules/YMRoom/View/UserCard/Api/Api+UserCard.m @@ -63,4 +63,9 @@ [self makeRequest:@"room/checkManageNum" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, roomUid, nil]; } ++ (void)updateRoleToServer:(HttpRequestHelperCompletion)completion roomUid:(NSString *)roomUid uid:(NSString *)uid opt:(NSString *)opt { + [self makeRequest:@"roomrole/manageOpt" method:HttpRequestHelperMethodPOST completion:completion, + __FUNCTION__, roomUid, uid, opt, nil]; +} + @end diff --git a/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.h b/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.h index 0f82c853..a9497691 100644 --- a/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.h +++ b/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.h @@ -40,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN /// @param targetUid 目标用户的id /// @param roomId 房间的id /// @param enable YES设置 NO取消 -- (void)makeUserManager:(NSString *)targetUid roomId:(NSString *)roomId enable:(BOOL)enable; +- (void)makeUserManager:(NSString *)targetUid roomId:(NSString *)roomId roomUid:(NSString *)roomUid enable:(BOOL)enable; /// 踢出房间 /// @param targetUid 用户的uid diff --git a/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.m b/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.m index 7424cfb8..a4554408 100644 --- a/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.m +++ b/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.m @@ -527,7 +527,7 @@ /// @param targetUid 目标用户的id /// @param roomId 房间的id /// @param enable YES设置 NO取消 -- (void)makeUserManager:(NSString *)targetUid roomId:(NSString *)roomId enable:(BOOL)enable{ +- (void)makeUserManager:(NSString *)targetUid roomId:(NSString *)roomId roomUid:(NSString *)roomUid enable:(BOOL)enable{ NIMChatroomMemberUpdateRequest *request = [[NIMChatroomMemberUpdateRequest alloc]init]; request.roomId = roomId; request.userId = targetUid; @@ -537,6 +537,10 @@ @kStrongify(self); if (error == nil) { self.managerItem.isSelect = enable; + [Api updateRoleToServer:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + // 不用处理返回 + NSLog(@"%@", data); + }] roomUid:roomUid uid:targetUid opt:enable ? @"1" : @"2"]; } [[self getView] markUserManagerFinish:self.managerItem error:error]; }]; diff --git a/YuMi/Modules/YMRoom/View/UserCard/View/UserRoomCardViewController.m b/YuMi/Modules/YMRoom/View/UserCard/View/UserRoomCardViewController.m index 101090b0..5dfbc2d2 100644 --- a/YuMi/Modules/YMRoom/View/UserCard/View/UserRoomCardViewController.m +++ b/YuMi/Modules/YMRoom/View/UserCard/View/UserRoomCardViewController.m @@ -1228,7 +1228,7 @@ if ([self isSuperUser]) { [self.presenter superAdminHandleUser:self.cardInfo.uid opt:@"1" roomUid:roomUid isSet:!item.isSelect]; } else { - [self.presenter makeUserManager:self.cardInfo.uid roomId:roomId enable:!item.isSelect]; + [self.presenter makeUserManager:self.cardInfo.uid roomId:roomId roomUid:roomUid enable:!item.isSelect]; } } else { @kWeakify(self); @@ -1237,7 +1237,7 @@ if ([self isSuperUser]) { [self.presenter superAdminHandleUser:self.cardInfo.uid opt:@"1" roomUid:roomUid isSet:!item.isSelect]; } else { - [self.presenter makeUserManager:self.cardInfo.uid roomId:roomId enable:!item.isSelect]; + [self.presenter makeUserManager:self.cardInfo.uid roomId:roomId roomUid:roomUid enable:!item.isSelect]; } } failure:^(NSError * _Nonnull error) { if (error.code == 20504) { // 管理员数量已达上限 diff --git a/YuMi/Modules/YMRoom/View/UserCard/View/XPUserCardViewController.m b/YuMi/Modules/YMRoom/View/UserCard/View/XPUserCardViewController.m index 4c9986a6..d25c637e 100644 --- a/YuMi/Modules/YMRoom/View/UserCard/View/XPUserCardViewController.m +++ b/YuMi/Modules/YMRoom/View/UserCard/View/XPUserCardViewController.m @@ -1114,7 +1114,7 @@ if (meIsSuperAdmin) { [self.presenter superAdminHandleUser:self.cardInfo.uid opt:@"1" roomUid:roomUid isSet:!model.isSelect]; } else { - [self.presenter makeUserManager:self.cardInfo.uid roomId:roomId enable:!model.isSelect]; + [self.presenter makeUserManager:self.cardInfo.uid roomId:roomId roomUid:roomUid enable:!model.isSelect]; } } break; diff --git a/YuMi/Modules/YMWeb/MSRoomGameWebVC.m b/YuMi/Modules/YMWeb/MSRoomGameWebVC.m index 4c4d476f..fb02c538 100644 --- a/YuMi/Modules/YMWeb/MSRoomGameWebVC.m +++ b/YuMi/Modules/YMWeb/MSRoomGameWebVC.m @@ -75,6 +75,7 @@ NSString * const kJPClose = @"newTppClose"; - (void)dealloc { [self cleanupWebView]; + [self hideHUD]; [self.loadingTimer invalidate]; self.loadingTimer = nil; [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -277,7 +278,7 @@ NSString * const kJPClose = @"newTppClose"; } - (BOOL)isValidGameURL:(NSString *)urlString { - if (!urlString || ![urlString isKindOfClass:[NSString class]] || urlString.length == 0) { + if ([NSString isEmpty:urlString]) { return NO; } diff --git a/YuMi/ar.lproj/Localizable.strings b/YuMi/ar.lproj/Localizable.strings index 5145d05b..fff7d5b2 100644 --- a/YuMi/ar.lproj/Localizable.strings +++ b/YuMi/ar.lproj/Localizable.strings @@ -4178,7 +4178,7 @@ ineHeadView12" = "الحمل"; "20.20.59_text_7" = " شارك"; "20.20.59_text_8" = "إنشاء الحدث"; "20.20.59_text_9" = "عنوان الحدث"; -"20.20.59_text_10" = "بنر الفعالية"; +"20.20.59_text_10" = "بنر الفعالية(Best size:690*236)"; "20.20.59_text_11" = "رفع بنر إلى الصفحة الرئيسية(%@التكاليف )"; "20.20.59_text_12" = "نعم"; "20.20.59_text_13" = "لا "; diff --git a/YuMi/en.lproj/Localizable.strings b/YuMi/en.lproj/Localizable.strings index 5fee48d2..72603dce 100644 --- a/YuMi/en.lproj/Localizable.strings +++ b/YuMi/en.lproj/Localizable.strings @@ -3963,7 +3963,7 @@ "20.20.59_text_7" = " Participate"; "20.20.59_text_8" = "Create Event"; "20.20.59_text_9" = "Event Title"; -"20.20.59_text_10" = "Event Banner"; +"20.20.59_text_10" = "Event Banner(Best size:690*236)"; "20.20.59_text_11" = "Upload Banner to Homepage(Costs %@)"; "20.20.59_text_12" = "YES"; "20.20.59_text_13" = "NO"; diff --git a/YuMi/tr.lproj/Localizable.strings b/YuMi/tr.lproj/Localizable.strings index 6e68e52a..8c3ec017 100644 --- a/YuMi/tr.lproj/Localizable.strings +++ b/YuMi/tr.lproj/Localizable.strings @@ -3756,7 +3756,7 @@ "20.20.59_text_7" = " Katılmak"; "20.20.59_text_8" = "Etkinlik Oluştur"; "20.20.59_text_9" = "Etkinlik Başlığı"; -"20.20.59_text_10" = "Etkinlik Afişi"; +"20.20.59_text_10" = "Etkinlik Afişi(Best size:690*236)"; "20.20.59_text_11" = "Ana Sayfaya Banner Yükleyin(Maliyet %@)"; "20.20.59_text_12" = "Evet"; "20.20.59_text_13" = "Hayır"; diff --git a/YuMi/zh-Hant.lproj/Localizable.strings b/YuMi/zh-Hant.lproj/Localizable.strings index bb1f05c8..180168c0 100644 --- a/YuMi/zh-Hant.lproj/Localizable.strings +++ b/YuMi/zh-Hant.lproj/Localizable.strings @@ -3628,7 +3628,7 @@ "20.20.59_text_7" = " 參與活動"; "20.20.59_text_8" = "建立活動"; "20.20.59_text_9" = "活動標題"; -"20.20.59_text_10" = "活動橫幅"; +"20.20.59_text_10" = "活動橫幅(Best size:690*236)"; "20.20.59_text_11" = "上傳橫幅至首頁(成本 %@)"; "20.20.59_text_12" = "有"; "20.20.59_text_13" = "無";