// // YMCaptchaPopupView.m // MSYOUPAI // // Created by macmini on 2025/6/7. // Copyright © 2025 MS. All rights reserved. // #import "YMCaptchaPopupView.h" @interface YMCaptchaPopupView () @property (nonatomic, strong) UIView *backgroundMaskView; @property (nonatomic, strong) UIView *contentView; @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UITextField *inputTextField; @property (nonatomic, strong) UIImageView *captchaImageView; @property (nonatomic, strong) UIButton *cancelButton; @property (nonatomic, strong) UIButton *confirmButton; @end @implementation YMCaptchaPopupView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setupUI]; [self loadCaptchaImage]; } return self; } - (void)setupUI { self.backgroundColor = [UIColor clearColor]; // Background Mask self.backgroundMaskView = [[UIView alloc] initWithFrame:self.bounds]; self.backgroundMaskView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5]; self.backgroundMaskView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self addSubview:self.backgroundMaskView]; UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)]; [self.backgroundMaskView addGestureRecognizer:tapGesture]; // Content View self.contentView = [[UIView alloc] init]; self.contentView.backgroundColor = [UIColor whiteColor]; self.contentView.layer.cornerRadius = 10.0; self.contentView.clipsToBounds = YES; [self.contentView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithActionBlock:^(id _Nonnull sender) { }]]; [self addSubview:self.contentView]; // Title Label self.titleLabel = [[UILabel alloc] init]; self.titleLabel.text = @"图形验证"; self.titleLabel.font = [UIFont boldSystemFontOfSize:18.0]; self.titleLabel.textAlignment = NSTextAlignmentCenter; [self.contentView addSubview:self.titleLabel]; // Input TextField self.inputTextField = [[UITextField alloc] init]; self.inputTextField.font = [UIFont systemFontOfSize:14 weight:(UIFontWeightRegular)]; self.inputTextField.placeholder = @"请输入验证码(不区分大小写)"; self.inputTextField.borderStyle = UITextBorderStyleRoundedRect; self.inputTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; self.inputTextField.delegate = self; [self.contentView addSubview:self.inputTextField]; // Captcha ImageView self.captchaImageView = [[UIImageView alloc] init]; self.captchaImageView.backgroundColor = [UIColor lightGrayColor]; // Placeholder color self.captchaImageView.contentMode = UIViewContentModeScaleToFill; self.captchaImageView.userInteractionEnabled = YES; self.captchaImageView.clipsToBounds = YES; self.captchaImageView.layer.cornerRadius = 5; // Approximate from image // You might want to add a tap gesture to refresh the captcha // For example: UITapGestureRecognizer *captchaTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(refreshCaptcha)]; [self.captchaImageView addGestureRecognizer:captchaTap]; [self.contentView addSubview:self.captchaImageView]; // Cancel Button self.cancelButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.cancelButton setTitle:@"取消" forState:UIControlStateNormal]; [self.cancelButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; self.cancelButton.titleLabel.font = [UIFont systemFontOfSize:16.0]; self.cancelButton.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.0]; // Light gray background self.cancelButton.layer.cornerRadius = 25; // Approximate from image [self.cancelButton addTarget:self action:@selector(cancelButtonTapped) forControlEvents:UIControlEventTouchUpInside]; [self.contentView addSubview:self.cancelButton]; // Confirm Button self.confirmButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.confirmButton setTitle:@"确定" forState:UIControlStateNormal]; [self.confirmButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; self.confirmButton.titleLabel.font = [UIFont systemFontOfSize:16.0]; self.confirmButton.backgroundColor = [UIColor colorWithRed:1.0 green:0.4 blue:0.5 alpha:1.0]; // Pinkish color self.confirmButton.layer.cornerRadius = 25; // Approximate from image [self.confirmButton addTarget:self action:@selector(confirmButtonTapped) forControlEvents:UIControlEventTouchUpInside]; [self.contentView addSubview:self.confirmButton]; [self setupLayoutConstraints]; } - (void)setupLayoutConstraints { self.contentView.translatesAutoresizingMaskIntoConstraints = NO; self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; self.inputTextField.translatesAutoresizingMaskIntoConstraints = NO; self.captchaImageView.translatesAutoresizingMaskIntoConstraints = NO; self.cancelButton.translatesAutoresizingMaskIntoConstraints = NO; self.confirmButton.translatesAutoresizingMaskIntoConstraints = NO; CGFloat contentWidth = CGRectGetWidth(UIScreen.mainScreen.bounds) - 60; CGFloat contentHeight = adapt(220); // Adjusted height [NSLayoutConstraint activateConstraints:@[ [self.contentView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor], [self.contentView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor], [self.contentView.widthAnchor constraintEqualToConstant:contentWidth], [self.contentView.heightAnchor constraintEqualToConstant:contentHeight], [self.titleLabel.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:20], [self.titleLabel.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:20], [self.titleLabel.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-20], [self.inputTextField.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:40], [self.inputTextField.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:20], [self.inputTextField.heightAnchor constraintEqualToConstant:50], [self.captchaImageView.leadingAnchor constraintEqualToAnchor:self.inputTextField.trailingAnchor constant:10], [self.captchaImageView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-20], [self.captchaImageView.centerYAnchor constraintEqualToAnchor:self.inputTextField.centerYAnchor], [self.captchaImageView.widthAnchor constraintEqualToConstant:100], // Adjust as needed [self.captchaImageView.heightAnchor constraintEqualToConstant:49], [self.inputTextField.trailingAnchor constraintEqualToAnchor:self.captchaImageView.leadingAnchor constant:-10], [self.cancelButton.topAnchor constraintEqualToAnchor:self.inputTextField.bottomAnchor constant:30], [self.cancelButton.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:20], [self.cancelButton.heightAnchor constraintEqualToConstant:50], [self.cancelButton.trailingAnchor constraintEqualToAnchor:self.contentView.centerXAnchor constant:-10], [self.confirmButton.topAnchor constraintEqualToAnchor:self.inputTextField.bottomAnchor constant:30], [self.confirmButton.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-20], [self.confirmButton.heightAnchor constraintEqualToConstant:50], [self.confirmButton.leadingAnchor constraintEqualToAnchor:self.contentView.centerXAnchor constant:10], ]]; } - (void)loadCaptchaImage { [self getCaptchaImageCompletion:^(UIImage *image) { if (image) { self.captchaImageView.image = image; } else { self.captchaImageView.image = ImageByName(@"ym_sound_showcase_refresh_icon"); } }]; } - (void)inputTextChanged:(UITextField *)textField { NSString *text = textField.text; if (text.length > 4) { textField.text = [text substringToIndex:3]; } } #pragma mark - UITextFieldDelegate - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { // 如果是删除操作,允许 if (string.length == 0) { return YES; } // 使用正则表达式判断是否只包含字母和数字 NSString *pattern = @"^[a-zA-Z0-9]+$"; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern]; return [predicate evaluateWithObject:string]; } #pragma mark - Actions - (void)cancelButtonTapped { // if ([self.delegate respondsToSelector:@selector(captchaViewDidCancel)]) { // [self.delegate captchaViewDidCancel]; // } if (self.cancelButtonTappedBlock) { self.cancelButtonTappedBlock(); } [self dismiss]; } - (void)confirmButtonTapped { if (self.confirmButtonTappedBlock) { self.confirmButtonTappedBlock(self.inputTextField.text); } [self dismiss]; // if ([self.delegate respondsToSelector:@selector(captchaViewDidConfirmWithInput:)]) { // [self.delegate captchaViewDidConfirmWithInput:self.inputTextField.text]; // } // Optionally dismiss after confirm, or let the delegate handle it // [self dismiss]; } #pragma mark - Public Methods - (void)showInView:(UIView *)view { self.frame = view.bounds; [view addSubview:self]; self.alpha = 0; self.contentView.transform = CGAffineTransformMakeScale(0.5, 0.5); [UIView animateWithDuration:0.3 animations:^{ self.alpha = 1; self.contentView.transform = CGAffineTransformIdentity; }]; } - (void)dismiss { [UIView animateWithDuration:0.3 animations:^{ self.alpha = 0; self.contentView.transform = CGAffineTransformMakeScale(0.5, 0.5); } completion:^(BOOL finished) { [self removeFromSuperview]; }]; } - (void)setCaptchaImage:(UIImage *)image { self.captchaImageView.image = image; } - (void)refreshCaptcha { NSLog(@"Refresh captcha tapped"); [self loadCaptchaImage]; } - (void)getCaptchaImageCompletion:(void(^)(UIImage *image))completion { NSString * urlstr=[NSString stringWithFormat:@"%@%@",[LCSaveData getBaseURL]?[LCSaveData getBaseURL]:BaseURL,GetCaptcha]; NSURL *url = [NSURL URLWithString:urlstr]; if (!url) { NSLog(@"Captcha URL is nil"); return; } NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"Error fetching captcha image: %@", error.localizedDescription); } else if (data) { UIImage *image = [UIImage imageWithData:data]; if (image) { dispatch_async(dispatch_get_main_queue(), ^{ completion(image); //self.captchaImageView.image = image; }); } else { NSLog(@"Failed to convert data to image"); } } else { NSLog(@"No data received for captcha image"); } }]; [task resume]; } @end