diff --git a/keyBoard/Assets.xcassets/My/my_vip_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/My/my_vip_icon.imageset/Contents.json new file mode 100644 index 0000000..ea7c6de --- /dev/null +++ b/keyBoard/Assets.xcassets/My/my_vip_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "my_vip_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "my_vip_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/My/my_vip_icon.imageset/my_vip_icon@2x.png b/keyBoard/Assets.xcassets/My/my_vip_icon.imageset/my_vip_icon@2x.png new file mode 100644 index 0000000..7e2f992 Binary files /dev/null and b/keyBoard/Assets.xcassets/My/my_vip_icon.imageset/my_vip_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/My/my_vip_icon.imageset/my_vip_icon@3x.png b/keyBoard/Assets.xcassets/My/my_vip_icon.imageset/my_vip_icon@3x.png new file mode 100644 index 0000000..2bd88f9 Binary files /dev/null and b/keyBoard/Assets.xcassets/My/my_vip_icon.imageset/my_vip_icon@3x.png differ diff --git a/keyBoard/Class/Login/M/KBUser.h b/keyBoard/Class/Login/M/KBUser.h index f76cc93..2849ed9 100644 --- a/keyBoard/Class/Login/M/KBUser.h +++ b/keyBoard/Class/Login/M/KBUser.h @@ -23,6 +23,10 @@ typedef NS_ENUM(NSInteger, UserSex) { @property (nonatomic, copy, nullable) NSString *email; /// 邮箱是否验证 @property (nonatomic, assign) BOOL emailVerified; +/// VIP 到期日(yyyy-MM-dd) +@property (nonatomic, copy, nullable) NSString *vipExpiry; +/// 是否是 VIP +@property (nonatomic, assign) BOOL isVip; // token @property (nonatomic, copy, nullable) NSString *token; // token/access_token/accessToken @@ -30,4 +34,3 @@ typedef NS_ENUM(NSInteger, UserSex) { @end NS_ASSUME_NONNULL_END - diff --git a/keyBoard/Class/Me/V/KBMyHeaderView.m b/keyBoard/Class/Me/V/KBMyHeaderView.m index da8673d..2f75ade 100644 --- a/keyBoard/Class/Me/V/KBMyHeaderView.m +++ b/keyBoard/Class/Me/V/KBMyHeaderView.m @@ -18,10 +18,15 @@ @property (nonatomic, strong) UIButton *keyboardBtn; @property (nonatomic, strong) UIImageView *avatarView; @property (nonatomic, strong) UILabel *nameLabel; +@property (nonatomic, strong) UIImageView *vipIconView; +@property (nonatomic, strong) UILabel *vipExpiryLabel; @property (nonatomic, strong) UIImageView *cardLeft; @property (nonatomic, strong) UIImageView *cardRight; @property (nonatomic, strong) UIImageView *avatarEditIcon; // 头像右下角的编辑图标 @property (nonatomic, strong) KBUser *userModel; +//@property (nonatomic, strong) MASConstraint *vipIconWidthConstraint; +//@property (nonatomic, strong) MASConstraint *nameRightToVipConstraint; +//@property (nonatomic, strong) MASConstraint *nameRightToSuperviewConstraint; @end @@ -36,6 +41,8 @@ [self addSubview:self.avatarView]; [self addSubview:self.avatarEditIcon]; // 头像右下角编辑图标 [self addSubview:self.nameLabel]; + [self addSubview:self.vipIconView]; + [self addSubview:self.vipExpiryLabel]; [self addSubview:self.cardLeft]; [self addSubview:self.cardRight]; @@ -61,10 +68,30 @@ make.bottom.equalTo(self.avatarView.mas_bottom); }]; [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.avatarView.mas_right).offset(16); make.centerY.equalTo(self.avatarView); - make.left.equalTo(self.avatarView.mas_right).offset(12); - make.right.lessThanOrEqualTo(self).offset(-20); }]; + + [self.vipIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.nameLabel); + make.left.equalTo(self.nameLabel.mas_right).offset(10); + make.right.lessThanOrEqualTo(self).offset(-16); + make.width.mas_equalTo(51); + make.height.mas_equalTo(20); + }]; + + [self.vipExpiryLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.nameLabel.mas_bottom).offset(6); + make.left.equalTo(self.nameLabel); + make.right.lessThanOrEqualTo(self).offset(-16); + }]; + + [self.nameLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow + forAxis:UILayoutConstraintAxisHorizontal]; + [self.vipIconView setContentCompressionResistancePriority:UILayoutPriorityRequired + forAxis:UILayoutConstraintAxisHorizontal]; + + // 166 99 // w ? CGFloat height = 99 * (KB_SCREEN_WIDTH - 2 * 16 - 10) * 0.5 / 166; @@ -102,6 +129,31 @@ // 头像:使用通用占位图 [self.avatarView kb_setAvatarURL:user.avatarUrl placeholder:KBPlaceholderImage]; + + BOOL isVip = user.isVip; + self.vipIconView.hidden = !isVip; + self.vipExpiryLabel.hidden = !isVip; + self.vipExpiryLabel.text = isVip ? [self vipExpiryDisplayTextFrom:user.vipExpiry] : nil; +} + +- (NSString *)vipExpiryDisplayTextFrom:(NSString *)rawDate { + NSString *prefix = KBLocalized(@"Due On"); + if (rawDate.length == 0) { + return prefix; + } + + NSDateFormatter *input = [self.class vipExpiryInputFormatter]; + NSDate *date = [input dateFromString:rawDate]; + if (!date) { + return [NSString stringWithFormat:@"%@ %@", prefix, rawDate]; + } + + NSDateFormatter *output = [self.class vipExpiryOutputFormatter]; + NSString *formatted = [output stringFromDate:date]; + if (formatted.length == 0) { + formatted = rawDate; + } + return [NSString stringWithFormat:@"%@ %@", prefix, formatted]; } + (void)kb_applyGradientTo:(UIView *)view colors:(NSArray *)colors { @@ -120,6 +172,28 @@ [view.layer insertSublayer:g atIndex:0]; } ++ (NSDateFormatter *)vipExpiryInputFormatter { + static NSDateFormatter *formatter; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [NSDateFormatter new]; + formatter.dateFormat = @"yyyy-MM-dd"; + formatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + }); + return formatter; +} + ++ (NSDateFormatter *)vipExpiryOutputFormatter { + static NSDateFormatter *formatter; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [NSDateFormatter new]; + formatter.dateStyle = NSDateFormatterLongStyle; + formatter.timeStyle = NSDateFormatterNoStyle; + }); + return formatter; +} + #pragma mark - Lazy UI - (UILabel *)titleLabel { if (!_titleLabel) { @@ -183,10 +257,37 @@ _nameLabel.text = @"Notice"; _nameLabel.font = [KBFont medium:20]; _nameLabel.textColor = [UIColor colorWithHex:KBBlackValue]; + _nameLabel.lineBreakMode = NSLineBreakByTruncatingTail; + [_nameLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal]; + [_nameLabel setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal]; } return _nameLabel; } +- (UIImageView *)vipIconView { + if (!_vipIconView) { + _vipIconView = [UIImageView new]; + _vipIconView.contentMode = UIViewContentModeScaleAspectFit; + _vipIconView.image = [UIImage imageNamed:@"my_vip_icon"]; + _vipIconView.hidden = YES; + [_vipIconView setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; + [_vipIconView setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; + } + return _vipIconView; +} + +- (UILabel *)vipExpiryLabel { + if (!_vipExpiryLabel) { + _vipExpiryLabel = [UILabel new]; + _vipExpiryLabel.font = [KBFont regular:12]; + _vipExpiryLabel.textColor = [UIColor colorWithHex:0x9FA5B5]; + _vipExpiryLabel.numberOfLines = 1; + _vipExpiryLabel.lineBreakMode = NSLineBreakByTruncatingTail; + _vipExpiryLabel.hidden = YES; + } + return _vipExpiryLabel; +} + - (UIImageView *)cardLeft { if (!_cardLeft) { _cardLeft = [UIImageView new];