Files
whale-town-front/scripts/ui/UI_Login.gd
lzdFeiFei d623c705b6 feat:实现登录系统和用户认证功能
- 添加登录场景(login_scene.tscn)和主菜单场景(main_menu_scene.tscn)
- 实现认证管理器(AuthManager)用于用户登录和会话管理
- 添加核心服务:加密服务、存储服务、网络服务
- 配置项目主场景为登录场景
- 添加自动加载服务到项目配置
- 添加开发环境配置(VSCode、Claude)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 01:15:33 +08:00

218 lines
6.4 KiB
GDScript

extends Control
## 登录界面控制器
## 处理登录界面的用户交互、输入验证、错误提示等
# UI 节点引用
@onready var passwordLoginTab: Button = $LoginPanel/PasswordLoginTab
@onready var codeLoginTab: Button = $LoginPanel/CodeLoginTab
@onready var usernameInput: LineEdit = $LoginPanel/UsernameInput
@onready var passwordInput: LineEdit = $LoginPanel/PasswordInput
@onready var togglePasswordButton: Button = $LoginPanel/TogglePasswordButton
@onready var rememberPasswordCheckBox: CheckBox = $LoginPanel/RememberPasswordCheckBox
@onready var autoLoginCheckBox: CheckBox = $LoginPanel/AutoLoginCheckBox
@onready var enterButton: TextureButton = $LoginPanel/EnterButton
@onready var forgotPasswordButton: LinkButton = $LoginPanel/ForgotPasswordButton
@onready var registerButton: LinkButton = $LoginPanel/RegisterButton
@onready var statusLabel: Label = $LoginPanel/StatusLabel
@onready var loadingOverlay: ColorRect = $LoadingOverlay
@onready var loadingLabel: Label = $LoadingOverlay/LoadingLabel
# 当前登录模式
enum LoginMode {
PASSWORD, # 密码登录
CODE # 验证码登录
}
var currentMode: LoginMode = LoginMode.PASSWORD
func _ready():
# 连接Tab按钮信号
passwordLoginTab.pressed.connect(_onPasswordTabPressed)
codeLoginTab.pressed.connect(_onCodeTabPressed)
# 连接主要按钮信号
enterButton.pressed.connect(_onEnterButtonPressed)
togglePasswordButton.pressed.connect(_onTogglePasswordPressed)
# 连接底部链接按钮
forgotPasswordButton.pressed.connect(_onForgotPasswordPressed)
registerButton.pressed.connect(_onRegisterPressed)
# 连接 AuthManager 信号
AuthManager.login_success.connect(_onLoginSuccess)
AuthManager.login_failed.connect(_onLoginFailed)
# 连接输入框回车事件
usernameInput.text_submitted.connect(_onUsernameSubmitted)
passwordInput.text_submitted.connect(_onPasswordSubmitted)
# 自动填充记住的账号密码
_loadSavedAccount()
# 初始化状态
_hideLoading()
_clearStatus()
_updateLoginMode()
## Tab切换 - 密码登录
func _onPasswordTabPressed() -> void:
if currentMode != LoginMode.PASSWORD:
currentMode = LoginMode.PASSWORD
codeLoginTab.button_pressed = false
passwordLoginTab.button_pressed = true
_updateLoginMode()
## Tab切换 - 验证码登录
func _onCodeTabPressed() -> void:
if currentMode != LoginMode.CODE:
currentMode = LoginMode.CODE
passwordLoginTab.button_pressed = false
codeLoginTab.button_pressed = true
_updateLoginMode()
## 更新登录模式UI
func _updateLoginMode() -> void:
match currentMode:
LoginMode.PASSWORD:
passwordInput.placeholder_text = "输入密码"
passwordInput.secret = true
togglePasswordButton.visible = true
LoginMode.CODE:
passwordInput.placeholder_text = "输入验证码"
passwordInput.secret = false
togglePasswordButton.visible = false
## 切换密码显示/隐藏
func _onTogglePasswordPressed() -> void:
passwordInput.secret = !passwordInput.secret
togglePasswordButton.text = "👁" if passwordInput.secret else "🔒"
## 加载保存的账号密码
func _loadSavedAccount() -> void:
var savedAccount = StorageService.loadAccount()
var username = savedAccount.get("username", "")
var password = savedAccount.get("password", "")
var rememberPassword = savedAccount.get("remember_password", false)
# 设置用户名
usernameInput.text = username
if rememberPassword and not password.is_empty():
passwordInput.text = password
rememberPasswordCheckBox.button_pressed = true
else:
rememberPasswordCheckBox.button_pressed = false
## 进入小镇按钮点击事件
func _onEnterButtonPressed() -> void:
match currentMode:
LoginMode.PASSWORD:
_handlePasswordLogin()
LoginMode.CODE:
_handleCodeLogin()
## 处理密码登录
func _handlePasswordLogin() -> void:
# 验证输入
var validation = _validateInput()
if not validation.valid:
_showError(validation.error_code)
return
# 显示加载状态
_showLoading("登录中...")
# 获取输入
var username = usernameInput.text.strip_edges()
var password = passwordInput.text
var remember = rememberPasswordCheckBox.button_pressed
# 调用 AuthManager 登录
var result = await AuthManager.login(username, password, remember)
# 隐藏加载状态
_hideLoading()
## 处理验证码登录
func _handleCodeLogin() -> void:
# TODO: 实现验证码登录逻辑
_showError(ErrorCode.SERVER_ERROR, "验证码登录功能暂未开放")
## 用户名输入框回车事件
func _onUsernameSubmitted(_text: String) -> void:
passwordInput.grab_focus()
## 密码输入框回车事件
func _onPasswordSubmitted(_text: String) -> void:
_onEnterButtonPressed()
## 忘记密码按钮点击
func _onForgotPasswordPressed() -> void:
# TODO: 跳转到忘记密码页面
_showError(ErrorCode.SERVER_ERROR, "忘记密码功能暂未开放")
## 注册按钮点击
func _onRegisterPressed() -> void:
# TODO: 跳转到注册页面
_showError(ErrorCode.SERVER_ERROR, "注册功能暂未开放")
## 登录成功回调
func _onLoginSuccess(userData: UserData) -> void:
_hideLoading()
_showSuccess("登录成功!")
# 延迟0.5秒后跳转到主菜单
await get_tree().create_timer(0.5).timeout
get_tree().change_scene_to_file("res://scenes/main_menu_scene.tscn")
## 登录失败回调
func _onLoginFailed(errorCode: int, errorMessage: String) -> void:
_hideLoading()
_showError(errorCode, errorMessage)
## 验证输入
func _validateInput() -> Dictionary:
var username = usernameInput.text.strip_edges()
var password = passwordInput.text
# 检查是否为空
if username.is_empty() or password.is_empty():
return {
"valid": false,
"error_code": ErrorCode.INVALID_INPUT
}
return {"valid": true}
## 显示加载状态
func _showLoading(message: String = "加载中...") -> void:
loadingLabel.text = message
loadingOverlay.visible = true
enterButton.disabled = true
## 隐藏加载状态
func _hideLoading() -> void:
loadingOverlay.visible = false
enterButton.disabled = false
## 显示错误提示
func _showError(errorCode: int, customMessage: String = "") -> void:
var message = customMessage if not customMessage.is_empty() else ErrorCode.getMessage(errorCode)
statusLabel.text = message
statusLabel.modulate = Color.RED
# 3秒后自动清除
await get_tree().create_timer(3.0).timeout
_clearStatus()
## 显示成功提示
func _showSuccess(message: String) -> void:
statusLabel.text = message
statusLabel.modulate = Color.GREEN
## 清除状态提示
func _clearStatus() -> void:
statusLabel.text = " "
statusLabel.modulate = Color.WHITE