diff --git a/keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/Contents.json new file mode 100644 index 0000000..477ba0d --- /dev/null +++ b/keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "pay_leftline_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "pay_leftline_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@2x.png b/keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@2x.png new file mode 100644 index 0000000..8d9d401 Binary files /dev/null and b/keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@3x.png b/keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@3x.png new file mode 100644 index 0000000..86dd5ba Binary files /dev/null and b/keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@3x.png differ diff --git a/keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/Contents.json new file mode 100644 index 0000000..d9d60cf --- /dev/null +++ b/keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "pay_rightline_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "pay_rightline_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@2x.png b/keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@2x.png new file mode 100644 index 0000000..bded43c Binary files /dev/null and b/keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@3x.png b/keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@3x.png new file mode 100644 index 0000000..bc14597 Binary files /dev/null and b/keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@3x.png differ diff --git a/keyBoard/Class/Pay/M/KBPayProductModel.h b/keyBoard/Class/Pay/M/KBPayProductModel.h index bec536b..f0abae7 100644 --- a/keyBoard/Class/Pay/M/KBPayProductModel.h +++ b/keyBoard/Class/Pay/M/KBPayProductModel.h @@ -33,11 +33,15 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, nullable) NSString *currency; /// 文案描述 @property (nonatomic, copy, nullable) NSString *productDescription; +/// 等级:1=VIP, 2=SVIP +@property (nonatomic, assign) NSInteger level; /// 展示金币(自动拼接单位) - (NSString *)coinsDisplayText; /// 展示价格,保留两位小数 - (NSString *)priceDisplayText; +/// 展示价格数字(不含货币符号) +- (NSString *)priceNumberText; @end diff --git a/keyBoard/Class/Pay/M/KBPayProductModel.m b/keyBoard/Class/Pay/M/KBPayProductModel.m index 9a707cb..5c8c0d7 100644 --- a/keyBoard/Class/Pay/M/KBPayProductModel.m +++ b/keyBoard/Class/Pay/M/KBPayProductModel.m @@ -35,4 +35,8 @@ return [NSString stringWithFormat:@"%.2f", priceValue]; } +- (NSString *)priceNumberText { + return [NSString stringWithFormat:@"%.2f", self.price]; +} + @end diff --git a/keyBoard/Class/Pay/V/KBSvipBenefitCell.m b/keyBoard/Class/Pay/V/KBSvipBenefitCell.m index c16132b..495e8fa 100644 --- a/keyBoard/Class/Pay/V/KBSvipBenefitCell.m +++ b/keyBoard/Class/Pay/V/KBSvipBenefitCell.m @@ -27,7 +27,7 @@ [self.coverView mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.right.equalTo(self.contentView).inset(8); + make.left.right.equalTo(self.contentView).inset(16); make.centerY.equalTo(self.contentView); make.height.mas_equalTo(46); }]; diff --git a/keyBoard/Class/Pay/V/KBSvipFlowLayout.m b/keyBoard/Class/Pay/V/KBSvipFlowLayout.m index 4c9f0d9..3f5e345 100644 --- a/keyBoard/Class/Pay/V/KBSvipFlowLayout.m +++ b/keyBoard/Class/Pay/V/KBSvipFlowLayout.m @@ -70,12 +70,15 @@ static NSString * const kKBSvipBenefitBgKind = @"KBSvipBenefitBgDecoration"; // UIEdgeInsets sectionInset0 = [self insetForSection:0]; UIEdgeInsets sectionInset1 = [self insetForSection:1]; - // 1. 外层大背景(18圆角):从 Section 0 顶部到 Section 1 底部 + // 固定的外层背景边距(不跟随 Section inset) + CGFloat outerPadding = 16; + + // 1. 外层大背景(18圆角):固定距离屏幕左右 16 { CGFloat minY = CGRectGetMinY(firstItemAttr.frame) - sectionInset0.top; CGFloat maxY = CGRectGetMaxY(lastBenefitAttr.frame) + 16; - CGFloat x = sectionInset0.left; - CGFloat width = self.collectionView.bounds.size.width - sectionInset0.left - sectionInset0.right; + CGFloat x = outerPadding; + CGFloat width = self.collectionView.bounds.size.width - outerPadding * 2; CGRect frame = CGRectMake(x, minY, width, maxY - minY); @@ -87,10 +90,11 @@ static NSString * const kKBSvipBenefitBgKind = @"KBSvipBenefitBgDecoration"; // // 2. 内层权益背景(15圆角):从 Section 1 Header 到 Section 1 底部,左右距离外层 8px { + CGFloat innerPadding = 8; // 距离外层背景的边距 CGFloat minY = CGRectGetMinY(benefitHeaderAttr.frame); CGFloat maxY = CGRectGetMaxY(lastBenefitAttr.frame) + 16; - CGFloat x = sectionInset0.left + 8; // 距离外层左边 8px - CGFloat width = self.collectionView.bounds.size.width - sectionInset0.left - sectionInset0.right - 16; // 左右各 8px + CGFloat x = outerPadding + innerPadding; + CGFloat width = self.collectionView.bounds.size.width - (outerPadding + innerPadding) * 2; CGRect frame = CGRectMake(x, minY, width, maxY - minY); diff --git a/keyBoard/Class/Pay/V/KBSvipSubscribeCell.h b/keyBoard/Class/Pay/V/KBSvipSubscribeCell.h index ed7a9cb..373fc27 100644 --- a/keyBoard/Class/Pay/V/KBSvipSubscribeCell.h +++ b/keyBoard/Class/Pay/V/KBSvipSubscribeCell.h @@ -10,7 +10,9 @@ NS_ASSUME_NONNULL_BEGIN @interface KBSvipSubscribeCell : UICollectionViewCell -/// 配置展示文案 +/// 配置展示文案(带货币符号) +- (void)configTitle:(NSString *)title currency:(NSString *)currency price:(NSString *)price strike:(nullable NSString *)strike; +/// 配置展示文案(兼容旧方法) - (void)configTitle:(NSString *)title price:(NSString *)price strike:(nullable NSString *)strike; /// 同步选中态 - (void)applySelected:(BOOL)selected animated:(BOOL)animated; diff --git a/keyBoard/Class/Pay/V/KBSvipSubscribeCell.m b/keyBoard/Class/Pay/V/KBSvipSubscribeCell.m index 0588e18..8b925cf 100644 --- a/keyBoard/Class/Pay/V/KBSvipSubscribeCell.m +++ b/keyBoard/Class/Pay/V/KBSvipSubscribeCell.m @@ -8,10 +8,12 @@ #import "KBSvipSubscribeCell.h" @interface KBSvipSubscribeCell () -@property (nonatomic, strong) UIImageView *bgImageView; // 背景图片 -@property (nonatomic, strong) UILabel *titleLabel; // "1 Week" / "1 Month" / "1 Year" -@property (nonatomic, strong) UILabel *priceLabel; // "$6.90" -@property (nonatomic, strong) UILabel *strikeLabel; // 删除线原价 +@property (nonatomic, strong) UIImageView *bgImageView; // 背景图片 +@property (nonatomic, strong) UILabel *titleLabel; // "1 Week" / "1 Month" / "1 Year" +@property (nonatomic, strong) UIView *priceContainer; // 白色圆角容器 +@property (nonatomic, strong) UILabel *currencyLabel; // "$" 货币符号 +@property (nonatomic, strong) UILabel *priceLabel; // "6.90" 价格数字 +@property (nonatomic, strong) UILabel *strikeLabel; // 删除线原价 @end @implementation KBSvipSubscribeCell @@ -26,19 +28,38 @@ }]; [self.contentView addSubview:self.titleLabel]; - [self.contentView addSubview:self.priceLabel]; - [self.contentView addSubview:self.strikeLabel]; + [self.contentView addSubview:self.priceContainer]; + + // 价格容器内添加货币符号和价格 + [self.priceContainer addSubview:self.currencyLabel]; + [self.priceContainer addSubview:self.priceLabel]; + [self.priceContainer addSubview:self.strikeLabel]; [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.contentView); - make.top.equalTo(self.contentView).offset(12); + make.top.equalTo(self.contentView).offset(10); }]; + + [self.priceContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView).offset(5); + make.right.equalTo(self.contentView).offset(-5); + make.bottom.equalTo(self.contentView).offset(-5); + make.height.mas_equalTo(86); + }]; + + // 货币符号和价格水平居中 + [self.currencyLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.priceLabel.mas_left).offset(-2); + make.bottom.equalTo(self.priceLabel.mas_bottom).offset(-4); // 底部对齐,稍微上移 + }]; + [self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) { - make.centerX.equalTo(self.contentView); - make.top.equalTo(self.titleLabel.mas_bottom).offset(8); + make.centerX.equalTo(self.priceContainer).offset(6); // 稍微右移,给货币符号留空间 + make.centerY.equalTo(self.priceContainer).offset(-8); }]; + [self.strikeLabel mas_makeConstraints:^(MASConstraintMaker *make) { - make.centerX.equalTo(self.contentView); + make.centerX.equalTo(self.priceContainer); make.top.equalTo(self.priceLabel.mas_bottom).offset(4); }]; } @@ -55,9 +76,10 @@ [self applySelected:selected animated:NO]; } -- (void)configTitle:(NSString *)title price:(NSString *)price strike:(nullable NSString *)strike { +- (void)configTitle:(NSString *)title currency:(NSString *)currency price:(NSString *)price strike:(nullable NSString *)strike { self.titleLabel.text = title.length ? title : @"1 Month"; - self.priceLabel.text = price.length ? price : @"$6.90"; + self.currencyLabel.text = currency.length ? currency : @"$"; + self.priceLabel.text = price.length ? price : @"6.90"; self.strikeLabel.hidden = (strike.length == 0); if (strike.length) { NSDictionary *attr = @{ @@ -68,6 +90,11 @@ } } +// 兼容旧方法 +- (void)configTitle:(NSString *)title price:(NSString *)price strike:(nullable NSString *)strike { + [self configTitle:title currency:@"$" price:price strike:strike]; +} + - (void)applySelected:(BOOL)selected animated:(BOOL)animated { NSString *imageName = selected ? @"pay_colorbg_icon" : @"pay_graybg_icon"; void (^changes)(void) = ^{ @@ -101,12 +128,32 @@ return _titleLabel; } +- (UIView *)priceContainer { + if (!_priceContainer) { + _priceContainer = [UIView new]; + _priceContainer.backgroundColor = [UIColor whiteColor]; + _priceContainer.layer.cornerRadius = 14; + _priceContainer.clipsToBounds = YES; + } + return _priceContainer; +} + +- (UILabel *)currencyLabel { + if (!_currencyLabel) { + _currencyLabel = [UILabel new]; + _currencyLabel.text = @"$"; + _currencyLabel.textColor = [UIColor colorWithHex:KBBlackValue]; + _currencyLabel.font = [KBFont medium:14]; // 货币符号字体较小 + } + return _currencyLabel; +} + - (UILabel *)priceLabel { if (!_priceLabel) { _priceLabel = [UILabel new]; - _priceLabel.text = @"$6.90"; + _priceLabel.text = @"6.90"; _priceLabel.textColor = [UIColor colorWithHex:KBBlackValue]; - _priceLabel.font = [KBFont bold:22]; + _priceLabel.font = [KBFont bold:22]; // 价格数字字体较大 } return _priceLabel; } diff --git a/keyBoard/Class/Pay/VC/KBPaySvipVC.m b/keyBoard/Class/Pay/VC/KBPaySvipVC.m index 3d5168f..e998e33 100644 --- a/keyBoard/Class/Pay/VC/KBPaySvipVC.m +++ b/keyBoard/Class/Pay/VC/KBPaySvipVC.m @@ -118,8 +118,15 @@ static NSString * const kKBSvipBenefitHeaderId = @"kKBSvipBenefitHeaderId"; [self.collectionView reloadData]; return; } - self.plans = products ?: @[]; - self.selectedIndex = self.plans.count > 0 ? 1 : NSNotFound; // 默认选中第二个(1 Month) + // 过滤 level=2 的 SVIP 数据 + NSMutableArray *svipProducts = [NSMutableArray array]; + for (KBPayProductModel *product in products) { + if (product.level == 1) { + [svipProducts addObject:product]; + } + } + self.plans = svipProducts.copy; + self.selectedIndex = self.plans.count > 1 ? 1 : (self.plans.count > 0 ? 0 : NSNotFound); // 默认选中第二个(1 Month) [self.collectionView reloadData]; [self selectCurrentPlanAnimated:NO]; [self prepareStoreKitWithPlans:self.plans]; @@ -231,8 +238,9 @@ static NSString * const kKBSvipBenefitHeaderId = @"kKBSvipBenefitHeaderId"; if (indexPath.item < self.plans.count) { KBPayProductModel *plan = self.plans[indexPath.item]; NSString *title = [self displayTitleForPlan:plan]; - NSString *price = [plan priceDisplayText]; - [cell configTitle:title price:price strike:nil]; + NSString *currency = plan.currency ?: @"$"; + NSString *price = [plan priceNumberText]; + [cell configTitle:title currency:currency price:price strike:nil]; [cell applySelected:(indexPath.item == self.selectedIndex) animated:NO]; } return cell; @@ -264,22 +272,22 @@ static NSString * const kKBSvipBenefitHeaderId = @"kKBSvipBenefitHeaderId"; make.center.equalTo(header); }]; // 左右横线 - UIView *leftLine = [UIView new]; - leftLine.backgroundColor = [UIColor colorWithHex:0xE5E5E5]; + UIImageView *leftLine = [UIImageView new]; + leftLine.image = [UIImage imageNamed:@"pay_leftline_icon"]; [header addSubview:leftLine]; [leftLine mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(titleLabel.mas_left).offset(-12); make.centerY.equalTo(header); - make.width.mas_equalTo(40); + make.width.mas_equalTo(53); make.height.mas_equalTo(1); }]; - UIView *rightLine = [UIView new]; - rightLine.backgroundColor = [UIColor colorWithHex:0xE5E5E5]; + UIImageView *rightLine = [UIImageView new]; + rightLine.image = [UIImage imageNamed:@"pay_rightline_icon"]; [header addSubview:rightLine]; [rightLine mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(titleLabel.mas_right).offset(12); make.centerY.equalTo(header); - make.width.mas_equalTo(40); + make.width.mas_equalTo(53); make.height.mas_equalTo(1); }]; return header; @@ -361,7 +369,8 @@ static NSString * const kKBSvipBenefitHeaderId = @"kKBSvipBenefitHeaderId"; - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { if (section == 0) { - return UIEdgeInsetsMake(16, 16, 10, 16); + // 订阅选项:外层背景距屏幕16,Cell距外层背景17,所以 16+17=33 + return UIEdgeInsetsMake(16, 22, 10, 22); } return UIEdgeInsetsMake(0, 16, 20, 16); }