// // JXNetworkManager.m // AICity // // Created by TogetherWatch on 2025-10-13. // #import "JXNetworkManager.h" #import @interface JXNetworkManager () @property (nonatomic, strong) AFHTTPSessionManager *sessionManager; @property (nonatomic, copy) NSString *baseURL; @end @implementation JXNetworkManager + (instancetype)sharedManager { static JXNetworkManager *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; }); return instance; } - (instancetype)init { self = [super init]; if (self) { // Debug 环境使用本地开发服务器,Release 环境使用生产服务器 #ifdef DEBUG // _baseURL = @"http://192.168.110.66:8888/api/v1/"; _baseURL = @"https://backend.jsnoopyay.com/api/v1/"; NSLog(@"[JXNetworkManager] Using DEBUG BaseURL: %@", _baseURL); #else _baseURL = @"https://backend.jsnoopyay.com/api/v1/"; NSLog(@"[JXNetworkManager] Using RELEASE BaseURL: %@", _baseURL); #endif _sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:_baseURL]]; _sessionManager.requestSerializer = [AFJSONRequestSerializer serializer]; _sessionManager.responseSerializer = [AFJSONResponseSerializer serializer]; // 设置超时 _sessionManager.requestSerializer.timeoutInterval = 30.0; // 设置通用 header [_sessionManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; } return self; } - (void)GET:(NSString *)path parameters:(NSDictionary *)parameters success:(JXSuccessBlock)success failure:(JXFailureBlock)failure { // 每次请求时动态更新 token NSString *token = [self getAuthToken]; NSLog(@"[JXNetworkManager.GET] Token: %@", token ? @"YES" : @"NO"); NSLog(@"[JXNetworkManager.GET] Request path: %@", path); NSLog(@"[JXNetworkManager.GET] Request parameters: %@", parameters); NSLog(@"[JXNetworkManager.GET] Base URL: %@", self.baseURL); if (token && token.length > 0) { // 添加 Bearer 前缀 NSString *authHeader = [NSString stringWithFormat:@"Bearer %@", token]; [self.sessionManager.requestSerializer setValue:authHeader forHTTPHeaderField:@"Authorization"]; NSLog(@"[JXNetworkManager.GET] Authorization header set"); } else { NSLog(@"[JXNetworkManager.GET] WARNING: No token, request may be rejected"); } NSString *fullURL = [NSString stringWithFormat:@"%@%@", self.baseURL, path]; NSLog(@"[JXNetworkManager.GET] Full URL: %@", fullURL); [self.sessionManager GET:path parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { if (success) { success(responseObject); } } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"[JXNetworkManager.GET] Error: %@", error.localizedDescription); NSLog(@"[JXNetworkManager.GET] HTTP Status Code: %ld", (long)[(NSHTTPURLResponse *)task.response statusCode]); if (failure) { failure(error); } }]; } - (void)POST:(NSString *)path parameters:(NSDictionary *)parameters success:(JXSuccessBlock)success failure:(JXFailureBlock)failure { // 每次请求时动态更新 token NSString *token = [self getAuthToken]; NSLog(@"[JXNetworkManager.POST] Token: %@", token ? @"YES" : @"NO"); if (token && token.length > 0) { // 添加 Bearer 前缀 NSString *authHeader = [NSString stringWithFormat:@"Bearer %@", token]; [self.sessionManager.requestSerializer setValue:authHeader forHTTPHeaderField:@"Authorization"]; } [self.sessionManager POST:path parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { if (success) { success(responseObject); } } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"POST请求失败: %@, error: %@", path, error.localizedDescription); if (failure) { failure(error); } }]; } #pragma mark - Member API - (void)getMemberStatusWithCompletion:(void(^)(NSDictionary * _Nullable memberStatus, NSError * _Nullable error))completion { [self GET:@"member/status" parameters:nil success:^(id responseObject) { if (completion) { completion(responseObject, nil); } } failure:^(NSError *error) { if (completion) { completion(nil, error); } }]; } - (void)syncMemberStatusWithCompletion:(void(^)(NSDictionary * _Nullable response, NSError * _Nullable error))completion { [self POST:@"member/sync" parameters:nil success:^(id responseObject) { if (completion) { completion(responseObject, nil); } } failure:^(NSError *error) { if (completion) { completion(nil, error); } }]; } - (void)reportAnalyticsWithData:(NSDictionary *)data completion:(nullable void(^)(NSDictionary * _Nullable response, NSError * _Nullable error))completion { [self POST:@"analytics/report" parameters:data success:^(id responseObject) { if (completion) { completion(responseObject, nil); } } failure:^(NSError *error) { if (completion) { completion(nil, error); } }]; } #pragma mark - Private Methods - (NSString *)getAuthToken { // 从 NSUserDefaults 读取登录后保存的 token NSString *token = [[NSUserDefaults standardUserDefaults] stringForKey:@"access_token"]; if (!token || token.length == 0) { if([UserModel shareInstance].token){ return [UserModel shareInstance].token; } NSLog(@"[JXNetworkManager] WARNING: No token found in UserDefaults"); return nil; } return token; } @end