refactor:重构项目架构为分层结构

## 🏗️ 主要变更

### 目录结构重构
- 将 core/ 迁移到 _Core/(框架层)
- 将 scenes/ 重构为 Scenes/(玩法层)和 UI/(界面层)
- 将 data/ 迁移到 Config/(配置层)
- 添加 Assets/ 资源层和 Utils/ 工具层
- 将 scripts/ 迁移到 tools/(开发工具)

### 架构分层
- **_Core/**: 框架层 - 全局单例和管理器
- **Scenes/**: 玩法层 - 游戏场景和实体
- **UI/**: 界面层 - HUD、窗口、对话系统
- **Assets/**: 资源层 - 精灵图、音频、字体
- **Config/**: 配置层 - 游戏配置和本地化
- **Utils/**: 工具层 - 通用辅助脚本

### 文件更新
- 更新 project.godot 中的所有路径引用
- 更新自动加载脚本路径
- 更新测试文件的引用路径
- 添加 REFACTORING.md 详细说明
- 添加 MIGRATION_COMPLETE.md 迁移完成标记
- 更新 README.md 反映新架构

### 设计原则
-  清晰的分层(框架/玩法/界面)
-  场景内聚(脚本紧邻场景文件)
-  组件化设计(可复用组件)
-  职责单一(每个目录职责明确)

## 📋 详细信息
查看 REFACTORING.md 了解完整的重构说明和迁移映射表

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
王浩
2025-12-31 11:36:01 +08:00
parent b1f3c0feff
commit 0b533189ec
93 changed files with 1466 additions and 470 deletions

View 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