feature/网络管理和Web部署系统 #2
443
core/managers/NetworkManager.gd
Normal file
443
core/managers/NetworkManager.gd
Normal file
@@ -0,0 +1,443 @@
|
||||
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, headers: PackedStringArray, body: PackedByteArray):
|
||||
_on_request_completed(request_id, result, response_code, headers, 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()
|
||||
1
core/managers/NetworkManager.gd.uid
Normal file
1
core/managers/NetworkManager.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cb040lxcf4smh
|
||||
590
core/managers/ResponseHandler.gd
Normal file
590
core/managers/ResponseHandler.gd
Normal file
@@ -0,0 +1,590 @@
|
||||
extends Node
|
||||
|
||||
# 响应处理器 - 统一处理API响应和错误
|
||||
|
||||
# 响应处理结果
|
||||
class ResponseResult:
|
||||
var success: bool
|
||||
var message: String
|
||||
var toast_type: String # "success" 或 "error"
|
||||
var data: Dictionary
|
||||
var should_show_toast: bool
|
||||
var custom_action: Callable
|
||||
|
||||
func _init():
|
||||
success = false
|
||||
message = ""
|
||||
toast_type = "error"
|
||||
data = {}
|
||||
should_show_toast = true
|
||||
custom_action = Callable()
|
||||
|
||||
# 错误码映射表 - 根据API v1.1.1更新
|
||||
const ERROR_CODE_MESSAGES = {
|
||||
# 登录相关
|
||||
"LOGIN_FAILED": "登录失败",
|
||||
"VERIFICATION_CODE_LOGIN_FAILED": "验证码错误或已过期",
|
||||
"EMAIL_NOT_VERIFIED": "请先验证邮箱",
|
||||
|
||||
# 注册相关
|
||||
"REGISTER_FAILED": "注册失败",
|
||||
|
||||
# 验证码相关
|
||||
"SEND_CODE_FAILED": "发送验证码失败",
|
||||
"SEND_LOGIN_CODE_FAILED": "发送登录验证码失败",
|
||||
"SEND_EMAIL_VERIFICATION_FAILED": "发送邮箱验证码失败",
|
||||
"RESEND_EMAIL_VERIFICATION_FAILED": "重新发送验证码失败",
|
||||
"EMAIL_VERIFICATION_FAILED": "邮箱验证失败",
|
||||
"RESET_PASSWORD_FAILED": "重置密码失败",
|
||||
"CHANGE_PASSWORD_FAILED": "修改密码失败",
|
||||
"VERIFICATION_CODE_EXPIRED": "验证码已过期",
|
||||
"VERIFICATION_CODE_INVALID": "验证码无效",
|
||||
"VERIFICATION_CODE_ATTEMPTS_EXCEEDED": "验证码尝试次数过多",
|
||||
"VERIFICATION_CODE_RATE_LIMITED": "验证码发送过于频繁",
|
||||
"VERIFICATION_CODE_HOURLY_LIMIT": "验证码每小时发送次数已达上限",
|
||||
|
||||
# 用户状态相关
|
||||
"USER_NOT_FOUND": "用户不存在",
|
||||
"INVALID_IDENTIFIER": "请输入有效的邮箱或手机号",
|
||||
"USER_STATUS_UPDATE_FAILED": "用户状态更新失败",
|
||||
|
||||
# 系统状态相关
|
||||
"TEST_MODE_ONLY": "测试模式",
|
||||
"TOO_MANY_REQUESTS": "请求过于频繁,请稍后再试",
|
||||
"SERVICE_UNAVAILABLE": "系统维护中,请稍后再试",
|
||||
|
||||
# 权限相关
|
||||
"UNAUTHORIZED": "未授权访问",
|
||||
"FORBIDDEN": "权限不足",
|
||||
"ADMIN_LOGIN_FAILED": "管理员登录失败",
|
||||
|
||||
# 其他
|
||||
"VALIDATION_FAILED": "参数验证失败",
|
||||
"UNSUPPORTED_MEDIA_TYPE": "不支持的请求格式",
|
||||
"REQUEST_TIMEOUT": "请求超时"
|
||||
}
|
||||
|
||||
# HTTP状态码消息映射 - 根据API v1.1.1更新
|
||||
const HTTP_STATUS_MESSAGES = {
|
||||
200: "请求成功",
|
||||
201: "创建成功",
|
||||
206: "测试模式",
|
||||
400: "请求参数错误",
|
||||
401: "认证失败",
|
||||
403: "权限不足",
|
||||
404: "资源不存在",
|
||||
408: "请求超时",
|
||||
409: "资源冲突",
|
||||
415: "不支持的媒体类型",
|
||||
429: "请求过于频繁",
|
||||
500: "服务器内部错误",
|
||||
503: "服务不可用"
|
||||
}
|
||||
|
||||
# ============ 主要处理方法 ============
|
||||
|
||||
# 处理登录响应
|
||||
static func handle_login_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
result.success = true
|
||||
result.message = "登录成功!正在进入鲸鱼镇..."
|
||||
result.toast_type = "success"
|
||||
result.data = data
|
||||
|
||||
# 自定义动作:延迟发送登录成功信号
|
||||
result.custom_action = func():
|
||||
await Engine.get_main_loop().create_timer(1.0).timeout
|
||||
# 这里可以发送登录成功信号或执行其他逻辑
|
||||
else:
|
||||
result = _handle_login_error(data, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理验证码登录响应
|
||||
static func handle_verification_code_login_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
result.success = true
|
||||
result.message = "验证码登录成功!正在进入鲸鱼镇..."
|
||||
result.toast_type = "success"
|
||||
result.data = data
|
||||
|
||||
result.custom_action = func():
|
||||
await Engine.get_main_loop().create_timer(1.0).timeout
|
||||
# 登录成功后的处理逻辑
|
||||
else:
|
||||
result = _handle_verification_code_login_error(data, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理发送验证码响应 - 支持邮箱冲突检测
|
||||
static func handle_send_verification_code_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
var error_code = data.get("error_code", "")
|
||||
if error_code == "TEST_MODE_ONLY":
|
||||
result.success = true
|
||||
result.message = "🧪 测试模式:验证码已生成,请查看控制台"
|
||||
result.toast_type = "success"
|
||||
|
||||
# 在控制台显示验证码
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 测试模式验证码: ", data.data.verification_code)
|
||||
result.message += "\n验证码: " + str(data.data.verification_code)
|
||||
else:
|
||||
result.success = true
|
||||
result.message = "📧 验证码已发送到您的邮箱,请查收"
|
||||
result.toast_type = "success"
|
||||
|
||||
# 开发环境下显示验证码
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 开发环境验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result = _handle_send_code_error(data, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理发送登录验证码响应
|
||||
static func handle_send_login_code_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
var error_code = data.get("error_code", "")
|
||||
if error_code == "TEST_MODE_ONLY":
|
||||
result.success = true
|
||||
result.message = "测试模式:登录验证码已生成,请查看控制台"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("测试模式登录验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result.success = true
|
||||
result.message = "登录验证码已发送,请查收"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("开发环境登录验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result = _handle_send_login_code_error(data, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理注册响应
|
||||
static func handle_register_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
result.success = true
|
||||
result.message = "注册成功!欢迎加入鲸鱼镇"
|
||||
result.toast_type = "success"
|
||||
result.data = data
|
||||
|
||||
# 自定义动作:清空表单,切换到登录界面
|
||||
result.custom_action = func():
|
||||
# 这里可以执行清空表单、切换界面等操作
|
||||
pass
|
||||
else:
|
||||
result = _handle_register_error(data, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理邮箱验证响应
|
||||
static func handle_verify_email_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
result.success = true
|
||||
result.message = "邮箱验证成功,正在注册..."
|
||||
result.toast_type = "success"
|
||||
result.data = data
|
||||
else:
|
||||
result = _handle_verify_email_error(data, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理重新发送邮箱验证码响应
|
||||
static func handle_resend_email_verification_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
var error_code = data.get("error_code", "")
|
||||
if error_code == "TEST_MODE_ONLY":
|
||||
result.success = true
|
||||
result.message = "🧪 测试模式:验证码已重新生成,请查看控制台"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 测试模式重新发送验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result.success = true
|
||||
result.message = "📧 验证码已重新发送到您的邮箱,请查收"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 开发环境重新发送验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result = _handle_resend_email_verification_error(data, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理忘记密码响应
|
||||
static func handle_forgot_password_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
var error_code = data.get("error_code", "")
|
||||
if error_code == "TEST_MODE_ONLY":
|
||||
result.success = true
|
||||
result.message = "🧪 测试模式:重置验证码已生成,请查看控制台"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 测试模式重置验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result.success = true
|
||||
result.message = "📧 重置验证码已发送,请查收"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 开发环境重置验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result = _handle_forgot_password_error(data, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理重置密码响应
|
||||
static func handle_reset_password_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
result.success = true
|
||||
result.message = "🔒 密码重置成功,请使用新密码登录"
|
||||
result.toast_type = "success"
|
||||
result.data = data
|
||||
else:
|
||||
result = _handle_reset_password_error(data, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# ============ 错误处理方法 ============
|
||||
|
||||
# 处理登录错误
|
||||
static func _handle_login_error(data: Dictionary, error_info: Dictionary) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
var error_code = data.get("error_code", "")
|
||||
var message = data.get("message", "登录失败")
|
||||
|
||||
match error_code:
|
||||
"LOGIN_FAILED":
|
||||
# 根据消息内容进一步判断用户状态
|
||||
if "账户已锁定" in message or "locked" in message.to_lower():
|
||||
result.message = "账户已被锁定,请联系管理员"
|
||||
elif "账户已禁用" in message or "banned" in message.to_lower():
|
||||
result.message = "账户已被禁用,请联系管理员"
|
||||
elif "账户待审核" in message or "pending" in message.to_lower():
|
||||
result.message = "账户待审核,请等待管理员审核"
|
||||
elif "邮箱未验证" in message or "inactive" in message.to_lower():
|
||||
result.message = "请先验证邮箱后再登录"
|
||||
else:
|
||||
result.message = "用户名或密码错误,请检查后重试"
|
||||
_:
|
||||
result.message = _get_error_message(error_code, message, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理验证码登录错误
|
||||
static func _handle_verification_code_login_error(data: Dictionary, error_info: Dictionary) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
var error_code = data.get("error_code", "")
|
||||
var message = data.get("message", "验证码登录失败")
|
||||
|
||||
match error_code:
|
||||
"VERIFICATION_CODE_LOGIN_FAILED":
|
||||
result.message = "验证码错误或已过期"
|
||||
"EMAIL_NOT_VERIFIED":
|
||||
result.message = "邮箱未验证,请先验证邮箱后再使用验证码登录"
|
||||
"USER_NOT_FOUND":
|
||||
result.message = "用户不存在,请先注册"
|
||||
"INVALID_IDENTIFIER":
|
||||
result.message = "请输入有效的邮箱或手机号"
|
||||
_:
|
||||
result.message = _get_error_message(error_code, message, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理发送验证码错误 - 支持邮箱冲突检测和频率限制
|
||||
static func _handle_send_code_error(data: Dictionary, error_info: Dictionary) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
var error_code = data.get("error_code", "")
|
||||
var message = data.get("message", "发送验证码失败")
|
||||
var response_code = error_info.get("response_code", 0)
|
||||
|
||||
match error_code:
|
||||
"SEND_EMAIL_VERIFICATION_FAILED":
|
||||
# 检查是否是邮箱冲突(409状态码)
|
||||
if response_code == 409:
|
||||
result.message = "⚠️ 邮箱已被注册,请使用其他邮箱或直接登录"
|
||||
result.toast_type = "error"
|
||||
elif "邮箱格式" in message:
|
||||
result.message = "📧 请输入有效的邮箱地址"
|
||||
else:
|
||||
result.message = message
|
||||
"TOO_MANY_REQUESTS":
|
||||
# 处理频率限制,提供重试建议
|
||||
result.toast_type = "error"
|
||||
|
||||
# 如果有throttle_info,显示更详细的信息
|
||||
if data.has("throttle_info"):
|
||||
var throttle_info = data.throttle_info
|
||||
var reset_time = throttle_info.get("reset_time", "")
|
||||
if reset_time != "":
|
||||
var relative_time = StringUtils.get_relative_time_until(reset_time)
|
||||
var local_time = StringUtils.format_utc_to_local_time(reset_time)
|
||||
result.message = "⏰ 验证码发送过于频繁"
|
||||
result.message += "\n请" + relative_time + "再试"
|
||||
result.message += "\n重试时间: " + local_time
|
||||
else:
|
||||
result.message = "⏰ 验证码发送过于频繁,请稍后再试"
|
||||
else:
|
||||
result.message = "⏰ 验证码发送过于频繁,请稍后再试"
|
||||
"VERIFICATION_CODE_RATE_LIMITED":
|
||||
result.message = "⏰ 验证码发送过于频繁,请稍后再试"
|
||||
"VERIFICATION_CODE_HOURLY_LIMIT":
|
||||
result.message = "⏰ 每小时发送次数已达上限,请稍后再试"
|
||||
_:
|
||||
result.message = _get_error_message(error_code, message, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理发送登录验证码错误
|
||||
static func _handle_send_login_code_error(data: Dictionary, error_info: Dictionary) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
var error_code = data.get("error_code", "")
|
||||
var message = data.get("message", "发送登录验证码失败")
|
||||
|
||||
match error_code:
|
||||
"SEND_LOGIN_CODE_FAILED":
|
||||
if "用户不存在" in message:
|
||||
result.message = "用户不存在,请先注册"
|
||||
else:
|
||||
result.message = "发送登录验证码失败"
|
||||
"USER_NOT_FOUND":
|
||||
result.message = "用户不存在,请先注册"
|
||||
"INVALID_IDENTIFIER":
|
||||
result.message = "请输入有效的邮箱或手机号"
|
||||
_:
|
||||
result.message = _get_error_message(error_code, message, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理注册错误 - 支持409冲突状态码
|
||||
static func _handle_register_error(data: Dictionary, error_info: Dictionary) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
var error_code = data.get("error_code", "")
|
||||
var message = data.get("message", "注册失败")
|
||||
var response_code = error_info.get("response_code", 0)
|
||||
|
||||
match error_code:
|
||||
"REGISTER_FAILED":
|
||||
# 检查409冲突状态码
|
||||
if response_code == 409:
|
||||
if "邮箱已存在" in message or "邮箱已被使用" in message:
|
||||
result.message = "📧 邮箱已被注册,请使用其他邮箱或直接登录"
|
||||
elif "用户名已存在" in message or "用户名已被使用" in message:
|
||||
result.message = "👤 用户名已被使用,请换一个"
|
||||
else:
|
||||
result.message = "⚠️ 资源冲突:" + message
|
||||
elif "邮箱验证码" in message or "verification_code" in message:
|
||||
result.message = "🔑 请先获取并输入邮箱验证码"
|
||||
elif "用户名" in message:
|
||||
result.message = "👤 用户名格式不正确"
|
||||
elif "邮箱" in message:
|
||||
result.message = "📧 邮箱格式不正确"
|
||||
elif "密码" in message:
|
||||
result.message = "🔒 密码格式不符合要求"
|
||||
elif "验证码" in message:
|
||||
result.message = "🔑 验证码错误或已过期"
|
||||
else:
|
||||
result.message = message
|
||||
_:
|
||||
result.message = _get_error_message(error_code, message, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理邮箱验证错误
|
||||
static func _handle_verify_email_error(data: Dictionary, error_info: Dictionary) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
var error_code = data.get("error_code", "")
|
||||
var message = data.get("message", "邮箱验证失败")
|
||||
|
||||
match error_code:
|
||||
"EMAIL_VERIFICATION_FAILED":
|
||||
if "验证码错误" in message:
|
||||
result.message = "🔑 验证码错误"
|
||||
elif "验证码已过期" in message:
|
||||
result.message = "🔑 验证码已过期,请重新获取"
|
||||
else:
|
||||
result.message = message
|
||||
"VERIFICATION_CODE_INVALID":
|
||||
result.message = "🔑 验证码错误或已过期"
|
||||
"VERIFICATION_CODE_EXPIRED":
|
||||
result.message = "🔑 验证码已过期,请重新获取"
|
||||
_:
|
||||
result.message = _get_error_message(error_code, message, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理网络测试响应
|
||||
static func handle_network_test_response(success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
|
||||
if success:
|
||||
result.success = true
|
||||
result.message = "🌐 网络连接正常"
|
||||
result.toast_type = "success"
|
||||
else:
|
||||
result.success = false
|
||||
result.message = "🌐 网络连接异常"
|
||||
result.toast_type = "error"
|
||||
|
||||
return result
|
||||
|
||||
# 处理重新发送邮箱验证码错误
|
||||
static func _handle_resend_email_verification_error(data: Dictionary, error_info: Dictionary) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
var error_code = data.get("error_code", "")
|
||||
var message = data.get("message", "重新发送验证码失败")
|
||||
|
||||
match error_code:
|
||||
"RESEND_EMAIL_VERIFICATION_FAILED":
|
||||
if "邮箱已验证" in message:
|
||||
result.message = "📧 邮箱已验证,无需重复验证"
|
||||
else:
|
||||
result.message = message
|
||||
_:
|
||||
result.message = _get_error_message(error_code, message, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理忘记密码错误
|
||||
static func _handle_forgot_password_error(data: Dictionary, error_info: Dictionary) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
var error_code = data.get("error_code", "")
|
||||
var message = data.get("message", "发送重置验证码失败")
|
||||
|
||||
match error_code:
|
||||
"SEND_CODE_FAILED":
|
||||
if "用户不存在" in message:
|
||||
result.message = "👤 用户不存在,请检查邮箱或手机号"
|
||||
else:
|
||||
result.message = message
|
||||
"USER_NOT_FOUND":
|
||||
result.message = "👤 用户不存在,请检查邮箱或手机号"
|
||||
_:
|
||||
result.message = _get_error_message(error_code, message, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# 处理重置密码错误
|
||||
static func _handle_reset_password_error(data: Dictionary, error_info: Dictionary) -> ResponseResult:
|
||||
var result = ResponseResult.new()
|
||||
var error_code = data.get("error_code", "")
|
||||
var message = data.get("message", "重置密码失败")
|
||||
|
||||
match error_code:
|
||||
"RESET_PASSWORD_FAILED":
|
||||
if "验证码" in message:
|
||||
result.message = "🔑 验证码错误或已过期"
|
||||
else:
|
||||
result.message = message
|
||||
_:
|
||||
result.message = _get_error_message(error_code, message, error_info)
|
||||
|
||||
return result
|
||||
|
||||
# ============ 工具方法 ============
|
||||
|
||||
# 获取错误消息 - 支持更多状态码和错误处理
|
||||
static func _get_error_message(error_code: String, original_message: String, error_info: Dictionary) -> String:
|
||||
# 优先使用错误码映射
|
||||
if ERROR_CODE_MESSAGES.has(error_code):
|
||||
return ERROR_CODE_MESSAGES[error_code]
|
||||
|
||||
# 处理频率限制
|
||||
if error_code == "TOO_MANY_REQUESTS":
|
||||
return _handle_rate_limit_message(original_message, error_info)
|
||||
|
||||
# 处理维护模式
|
||||
if error_code == "SERVICE_UNAVAILABLE":
|
||||
return _handle_maintenance_message(original_message, error_info)
|
||||
|
||||
# 处理测试模式
|
||||
if error_code == "TEST_MODE_ONLY":
|
||||
return "🧪 测试模式:" + original_message
|
||||
|
||||
# 根据HTTP状态码处理
|
||||
if error_info.has("response_code"):
|
||||
var response_code = error_info.response_code
|
||||
match response_code:
|
||||
409:
|
||||
return "⚠️ 资源冲突:" + original_message
|
||||
206:
|
||||
return "🧪 测试模式:" + original_message
|
||||
429:
|
||||
return "⏰ 请求过于频繁,请稍后再试"
|
||||
_:
|
||||
if HTTP_STATUS_MESSAGES.has(response_code):
|
||||
return HTTP_STATUS_MESSAGES[response_code] + ":" + original_message
|
||||
|
||||
# 返回原始消息
|
||||
return original_message if original_message != "" else "操作失败"
|
||||
|
||||
# 处理频率限制消息
|
||||
static func _handle_rate_limit_message(message: String, error_info: Dictionary) -> String:
|
||||
# 可以根据throttle_info提供更详细的信息
|
||||
return message + ",请稍后再试"
|
||||
|
||||
# 处理维护模式消息
|
||||
static func _handle_maintenance_message(message: String, error_info: Dictionary) -> String:
|
||||
# 可以根据maintenance_info提供更详细的信息
|
||||
return "系统维护中,请稍后再试"
|
||||
|
||||
# 通用响应处理器 - 支持更多操作类型
|
||||
static func handle_response(operation_type: String, success: bool, data: Dictionary, error_info: Dictionary = {}) -> ResponseResult:
|
||||
match operation_type:
|
||||
"login":
|
||||
return handle_login_response(success, data, error_info)
|
||||
"verification_code_login":
|
||||
return handle_verification_code_login_response(success, data, error_info)
|
||||
"send_code":
|
||||
return handle_send_verification_code_response(success, data, error_info)
|
||||
"send_login_code":
|
||||
return handle_send_login_code_response(success, data, error_info)
|
||||
"register":
|
||||
return handle_register_response(success, data, error_info)
|
||||
"verify_email":
|
||||
return handle_verify_email_response(success, data, error_info)
|
||||
"resend_email_verification":
|
||||
return handle_resend_email_verification_response(success, data, error_info)
|
||||
"forgot_password":
|
||||
return handle_forgot_password_response(success, data, error_info)
|
||||
"reset_password":
|
||||
return handle_reset_password_response(success, data, error_info)
|
||||
"network_test":
|
||||
return handle_network_test_response(success, data, error_info)
|
||||
_:
|
||||
# 通用处理
|
||||
var result = ResponseResult.new()
|
||||
if success:
|
||||
result.success = true
|
||||
result.message = "✅ 操作成功"
|
||||
result.toast_type = "success"
|
||||
else:
|
||||
result.success = false
|
||||
result.message = _get_error_message(data.get("error_code", ""), data.get("message", "操作失败"), error_info)
|
||||
result.toast_type = "error"
|
||||
return result
|
||||
1
core/managers/ResponseHandler.gd.uid
Normal file
1
core/managers/ResponseHandler.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ee8i4pdpdlsf
|
||||
Reference in New Issue
Block a user