extends Node # 网络请求管理器 - 统一处理所有HTTP请求 # 信号定义 signal request_completed(request_id: String, success: bool, data: Dictionary) signal request_failed(request_id: String, error_type: String, message: String) # API配置 const API_BASE_URL = "https://whaletownend.xinghangee.icu" const DEFAULT_TIMEOUT = 30.0 # 请求类型枚举 enum RequestType { GET, POST, PUT, DELETE, PATCH } # 错误类型枚举 enum ErrorType { NETWORK_ERROR, # 网络连接错误 TIMEOUT_ERROR, # 请求超时 PARSE_ERROR, # JSON解析错误 HTTP_ERROR, # HTTP状态码错误 BUSINESS_ERROR # 业务逻辑错误 } # 请求状态 class RequestInfo: var id: String var url: String var method: RequestType var headers: PackedStringArray var body: String var timeout: float var start_time: float var http_request: HTTPRequest var callback: Callable func _init(request_id: String, request_url: String, request_method: RequestType, request_headers: PackedStringArray = [], request_body: String = "", request_timeout: float = DEFAULT_TIMEOUT): id = request_id url = request_url method = request_method headers = request_headers body = request_body timeout = request_timeout start_time = Time.get_time_dict_from_system().hour * 3600 + Time.get_time_dict_from_system().minute * 60 + Time.get_time_dict_from_system().second # 活动请求管理 var active_requests: Dictionary = {} var request_counter: int = 0 func _ready(): print("NetworkManager 已初始化") # ============ 公共API接口 ============ # 发送GET请求 func get_request(endpoint: String, callback: Callable = Callable(), timeout: float = DEFAULT_TIMEOUT) -> String: return send_request(endpoint, RequestType.GET, [], "", callback, timeout) # 发送POST请求 func post_request(endpoint: String, data: Dictionary, callback: Callable = Callable(), timeout: float = DEFAULT_TIMEOUT) -> String: var body = JSON.stringify(data) var headers = ["Content-Type: application/json"] return send_request(endpoint, RequestType.POST, headers, body, callback, timeout) # 发送PUT请求 func put_request(endpoint: String, data: Dictionary, callback: Callable = Callable(), timeout: float = DEFAULT_TIMEOUT) -> String: var body = JSON.stringify(data) var headers = ["Content-Type: application/json"] return send_request(endpoint, RequestType.PUT, headers, body, callback, timeout) # 发送DELETE请求 func delete_request(endpoint: String, callback: Callable = Callable(), timeout: float = DEFAULT_TIMEOUT) -> String: return send_request(endpoint, RequestType.DELETE, [], "", callback, timeout) # ============ 认证相关API ============ # 用户登录 func login(identifier: String, password: String, callback: Callable = Callable()) -> String: var data = { "identifier": identifier, "password": password } return post_request("/auth/login", data, callback) # 验证码登录 func verification_code_login(identifier: String, verification_code: String, callback: Callable = Callable()) -> String: var data = { "identifier": identifier, "verification_code": verification_code } return post_request("/auth/verification-code-login", data, callback) # 发送登录验证码 func send_login_verification_code(identifier: String, callback: Callable = Callable()) -> String: var data = {"identifier": identifier} return post_request("/auth/send-login-verification-code", data, callback) # 用户注册 func register(username: String, password: String, nickname: String, email: String = "", email_verification_code: String = "", callback: Callable = Callable()) -> String: var data = { "username": username, "password": password, "nickname": nickname } if email != "": data["email"] = email if email_verification_code != "": data["email_verification_code"] = email_verification_code return post_request("/auth/register", data, callback) # 发送邮箱验证码 func send_email_verification(email: String, callback: Callable = Callable()) -> String: var data = {"email": email} return post_request("/auth/send-email-verification", data, callback) # 验证邮箱 func verify_email(email: String, verification_code: String, callback: Callable = Callable()) -> String: var data = { "email": email, "verification_code": verification_code } return post_request("/auth/verify-email", data, callback) # 获取应用状态 func get_app_status(callback: Callable = Callable()) -> String: return get_request("/", callback) # 重新发送邮箱验证码 func resend_email_verification(email: String, callback: Callable = Callable()) -> String: var data = {"email": email} return post_request("/auth/resend-email-verification", data, callback) # 忘记密码 - 发送重置验证码 func forgot_password(identifier: String, callback: Callable = Callable()) -> String: var data = {"identifier": identifier} return post_request("/auth/forgot-password", data, callback) # 重置密码 func reset_password(identifier: String, verification_code: String, new_password: String, callback: Callable = Callable()) -> String: var data = { "identifier": identifier, "verification_code": verification_code, "new_password": new_password } return post_request("/auth/reset-password", data, callback) # 修改密码 func change_password(user_id: String, old_password: String, new_password: String, callback: Callable = Callable()) -> String: var data = { "user_id": user_id, "old_password": old_password, "new_password": new_password } return put_request("/auth/change-password", data, callback) # GitHub OAuth登录 func github_login(github_id: String, username: String, nickname: String, email: String, avatar_url: String = "", callback: Callable = Callable()) -> String: var data = { "github_id": github_id, "username": username, "nickname": nickname, "email": email } if avatar_url != "": data["avatar_url"] = avatar_url return post_request("/auth/github", data, callback) # ============ 核心请求处理 ============ # 发送请求的核心方法 func send_request(endpoint: String, method: RequestType, headers: PackedStringArray, body: String, callback: Callable, timeout: float) -> String: # 生成请求ID request_counter += 1 var request_id = "req_" + str(request_counter) # 构建完整URL var full_url = API_BASE_URL + endpoint # 创建HTTPRequest节点 var http_request = HTTPRequest.new() add_child(http_request) # 设置超时 http_request.timeout = timeout # 创建请求信息 var request_info = RequestInfo.new(request_id, full_url, method, headers, body, timeout) request_info.http_request = http_request request_info.callback = callback # 存储请求信息 active_requests[request_id] = request_info # 连接信号 http_request.request_completed.connect(func(result: int, response_code: int, response_headers: PackedStringArray, response_body: PackedByteArray): _on_request_completed(request_id, result, response_code, response_headers, response_body) ) # 发送请求 var godot_method = _convert_to_godot_method(method) var error = http_request.request(full_url, headers, godot_method, body) print("=== 发送网络请求 ===") print("请求ID: ", request_id) print("URL: ", full_url) print("方法: ", RequestType.keys()[method]) print("Headers: ", headers) print("Body: ", body if body.length() < 200 else body.substr(0, 200) + "...") print("发送结果: ", error) if error != OK: print("请求发送失败,错误代码: ", error) _handle_request_error(request_id, ErrorType.NETWORK_ERROR, "网络请求发送失败: " + str(error)) return "" return request_id # 请求完成回调 func _on_request_completed(request_id: String, result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray): print("=== 网络请求完成 ===") print("请求ID: ", request_id) print("结果: ", result) print("状态码: ", response_code) print("响应头: ", headers) # 获取请求信息 if not active_requests.has(request_id): print("警告: 未找到请求ID ", request_id) return var _request_info = active_requests[request_id] var response_text = body.get_string_from_utf8() print("响应体长度: ", body.size(), " 字节") print("响应内容: ", response_text if response_text.length() < 500 else response_text.substr(0, 500) + "...") # 处理网络连接失败 if response_code == 0: _handle_request_error(request_id, ErrorType.NETWORK_ERROR, "网络连接失败,请检查网络连接") return # 解析JSON响应 var json = JSON.new() var parse_result = json.parse(response_text) if parse_result != OK: _handle_request_error(request_id, ErrorType.PARSE_ERROR, "服务器响应格式错误") return var response_data = json.data # 处理响应 _handle_response(request_id, response_code, response_data) # 处理响应 - 支持API v1.1.1的状态码 func _handle_response(request_id: String, response_code: int, data: Dictionary): var request_info = active_requests[request_id] # 检查业务成功标志 var success = data.get("success", true) # 默认true保持向后兼容 var error_code = data.get("error_code", "") var message = data.get("message", "") # 判断请求是否成功 var is_success = false # HTTP成功状态码且业务成功 if (response_code >= 200 and response_code < 300) and success: is_success = true # 特殊情况:206测试模式 - 根据API文档,这是成功的测试模式响应 elif response_code == 206 and error_code == "TEST_MODE_ONLY": is_success = true print("🧪 测试模式响应: ", message) # 201创建成功 elif response_code == 201: is_success = true if is_success: print("✅ 请求成功: ", request_id) # 发送成功信号 request_completed.emit(request_id, true, data) # 调用回调函数 if request_info.callback.is_valid(): request_info.callback.call(true, data, {}) else: print("❌ 请求失败: ", request_id, " - HTTP:", response_code, " 错误码:", error_code, " 消息:", message) # 确定错误类型 var error_type = _determine_error_type(response_code, error_code) # 发送失败信号 request_failed.emit(request_id, ErrorType.keys()[error_type], message) # 调用回调函数 if request_info.callback.is_valid(): var error_info = { "response_code": response_code, "error_code": error_code, "message": message, "error_type": error_type } request_info.callback.call(false, data, error_info) # 清理请求 _cleanup_request(request_id) # 处理请求错误 func _handle_request_error(request_id: String, error_type: ErrorType, message: String): print("❌ 请求错误: ", request_id, " - ", message) # 发送错误信号 request_failed.emit(request_id, ErrorType.keys()[error_type], message) # 调用回调函数 if active_requests.has(request_id): var request_info = active_requests[request_id] if request_info.callback.is_valid(): var error_info = { "error_type": error_type, "message": message } request_info.callback.call(false, {}, error_info) # 清理请求 _cleanup_request(request_id) # 确定错误类型 - 支持更多状态码 func _determine_error_type(response_code: int, error_code: String) -> ErrorType: # 根据错误码判断 match error_code: "SERVICE_UNAVAILABLE": return ErrorType.BUSINESS_ERROR "TOO_MANY_REQUESTS": return ErrorType.BUSINESS_ERROR "TEST_MODE_ONLY": return ErrorType.BUSINESS_ERROR "SEND_EMAIL_VERIFICATION_FAILED", "REGISTER_FAILED": # 这些可能是409冲突或其他业务错误 return ErrorType.BUSINESS_ERROR _: # 根据HTTP状态码判断 match response_code: 409: # 资源冲突 return ErrorType.BUSINESS_ERROR 206: # 测试模式 return ErrorType.BUSINESS_ERROR 429: # 频率限制 return ErrorType.BUSINESS_ERROR _: if response_code >= 400 and response_code < 500: return ErrorType.HTTP_ERROR elif response_code >= 500: return ErrorType.HTTP_ERROR else: return ErrorType.BUSINESS_ERROR # 清理请求资源 func _cleanup_request(request_id: String): if active_requests.has(request_id): var request_info = active_requests[request_id] # 移除HTTPRequest节点 if is_instance_valid(request_info.http_request): request_info.http_request.queue_free() # 从活动请求中移除 active_requests.erase(request_id) print("🧹 清理请求: ", request_id) # 转换请求方法 func _convert_to_godot_method(method: RequestType) -> HTTPClient.Method: match method: RequestType.GET: return HTTPClient.METHOD_GET RequestType.POST: return HTTPClient.METHOD_POST RequestType.PUT: return HTTPClient.METHOD_PUT RequestType.DELETE: return HTTPClient.METHOD_DELETE RequestType.PATCH: return HTTPClient.METHOD_PATCH _: return HTTPClient.METHOD_GET # ============ 工具方法 ============ # 取消请求 func cancel_request(request_id: String) -> bool: if active_requests.has(request_id): print("🚫 取消请求: ", request_id) _cleanup_request(request_id) return true return false # 取消所有请求 func cancel_all_requests(): print("🚫 取消所有请求") var request_ids = active_requests.keys() for request_id in request_ids: cancel_request(request_id) # 获取活动请求数量 func get_active_request_count() -> int: return active_requests.size() # 检查请求是否活动 func is_request_active(request_id: String) -> bool: return active_requests.has(request_id) # 获取请求信息 func get_request_info(request_id: String) -> Dictionary: if active_requests.has(request_id): var info = active_requests[request_id] return { "id": info.id, "url": info.url, "method": RequestType.keys()[info.method], "start_time": info.start_time, "timeout": info.timeout } return {} func _notification(what): if what == NOTIFICATION_WM_CLOSE_REQUEST: # 应用关闭时取消所有请求 cancel_all_requests()