557 lines
16 KiB
C#
557 lines
16 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Threading.Tasks;
|
||
using UnityEngine;
|
||
using Kill.Utils;
|
||
using Kill.Managers;
|
||
using Kill.Network;
|
||
using Kill.UI.Components;
|
||
|
||
namespace Kill.UI.Pages
|
||
{
|
||
public class LoginPageCtrl : MonoBehaviour
|
||
{
|
||
public enum SubPageType
|
||
{
|
||
Login, // 登录-邮箱输入页
|
||
LoginPassword, // 登录-密码输入页
|
||
Register,
|
||
VerificationCode,
|
||
SetPassword,
|
||
ThirdPartyBind
|
||
}
|
||
|
||
public LoginSubPageBase[] subPages;
|
||
public GameObject PrivacyAgreementTip;
|
||
public GameObject[] PrivacyAgreementPlane;
|
||
|
||
private SubPageType currentSubPage = SubPageType.Login;
|
||
private Stack<SubPageType> pageHistory = new Stack<SubPageType>();
|
||
|
||
public static LoginPageCtrl Instance { get; private set; }
|
||
|
||
private void Awake()
|
||
{
|
||
Instance = this;
|
||
InitializeSubPages();
|
||
foreach(LoginSubPageBase page in subPages)
|
||
{
|
||
if(page.pageType==SubPageType.Login)
|
||
{
|
||
page.gameObject.SetActive(true);
|
||
}
|
||
else
|
||
{
|
||
page.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void OnEnable()
|
||
{
|
||
ShowSubPage(SubPageType.Login, false);
|
||
RegisterBackEvent();
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
UnregisterBackEvent();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注册返回事件到UIManager
|
||
/// </summary>
|
||
private void RegisterBackEvent()
|
||
{
|
||
if (UIManager.Instance != null)
|
||
{
|
||
UIManager.Instance.RegisterBackAction(OnBackPressed);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取消注册返回事件
|
||
/// </summary>
|
||
private void UnregisterBackEvent()
|
||
{
|
||
if (UIManager.Instance != null)
|
||
{
|
||
UIManager.Instance.ClearBackAction();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回键处理
|
||
/// </summary>
|
||
private void OnBackPressed()
|
||
{
|
||
// 如果隐私协议提示正在显示,先关闭它
|
||
if (PrivacyAgreementTip != null && PrivacyAgreementTip.activeSelf)
|
||
{
|
||
PrivacyAgreementTip.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
// 如果隐私协议面板正在显示,先关闭它
|
||
if (PrivacyAgreementPlane != null)
|
||
{
|
||
foreach (var plane in PrivacyAgreementPlane)
|
||
{
|
||
if (plane != null && plane.activeSelf)
|
||
{
|
||
plane.SetActive(false);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果当前在登录页,让UIManager处理退出(不注销事件,只是不拦截)
|
||
if (currentSubPage == SubPageType.Login)
|
||
{
|
||
UnregisterBackEvent();
|
||
return;
|
||
}
|
||
|
||
// 返回上一页
|
||
GoBack();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化所有子页面
|
||
/// </summary>
|
||
private void InitializeSubPages()
|
||
{
|
||
if (subPages == null) return;
|
||
|
||
foreach (var page in subPages)
|
||
{
|
||
if (page != null)
|
||
{
|
||
page.Initialize(this);
|
||
page.Hide();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示指定子页面
|
||
/// </summary>
|
||
public void ShowSubPage(SubPageType pageType, bool recordHistory = true)
|
||
{
|
||
if( UIManager.Instance.GetBackAction() == null)
|
||
{
|
||
RegisterBackEvent();
|
||
}
|
||
// 隐藏当前页面
|
||
var currentPage = GetSubPage(currentSubPage);
|
||
if (currentPage != null)
|
||
{
|
||
currentPage.Hide();
|
||
}
|
||
|
||
// 记录历史
|
||
if (recordHistory && currentSubPage != pageType)
|
||
{
|
||
pageHistory.Push(currentSubPage);
|
||
}
|
||
|
||
// 显示新页面
|
||
var nextPage = GetSubPage(pageType);
|
||
if (nextPage != null)
|
||
{
|
||
nextPage.Show();
|
||
}
|
||
|
||
currentSubPage = pageType;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回上一页
|
||
/// </summary>
|
||
public void GoBack()
|
||
{
|
||
if (pageHistory.Count > 0)
|
||
{
|
||
SubPageType previousPage = pageHistory.Pop();
|
||
ShowSubPage(previousPage, false);
|
||
}
|
||
else
|
||
{
|
||
ShowSubPage(SubPageType.Login, false);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清空历史并跳转到指定页面
|
||
/// </summary>
|
||
public void ClearHistoryAndShow(SubPageType pageType)
|
||
{
|
||
pageHistory.Clear();
|
||
ShowSubPage(pageType, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取子页面控制器
|
||
/// </summary>
|
||
public LoginSubPageBase GetSubPage(SubPageType pageType)
|
||
{
|
||
if (subPages == null) return null;
|
||
|
||
foreach (var page in subPages)
|
||
{
|
||
if (page != null && page.PageType == pageType)
|
||
{
|
||
return page;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前页面类型
|
||
/// </summary>
|
||
public SubPageType GetCurrentPageType()
|
||
{
|
||
return currentSubPage;
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
Instance = null;
|
||
}
|
||
|
||
public void ShowPrivacyAgreementTip(Action onAgreementClick)
|
||
{
|
||
PrivacyAgreementTip.SetActive(true);
|
||
PrivacyTipPanel privacyTipPanel = PrivacyAgreementTip.GetComponent<PrivacyTipPanel>();
|
||
privacyTipPanel.Init(onAgreementClick);
|
||
}
|
||
|
||
public void ShowPrivacyAgreementPlane()
|
||
{
|
||
var currentLang = LanguageManager.Instance.languageType;
|
||
if (currentLang == LanguageManager.LanguageType.English)
|
||
{
|
||
PrivacyAgreementPlane[1].SetActive(true);
|
||
}
|
||
else
|
||
{
|
||
PrivacyAgreementPlane[0].SetActive(true);
|
||
}
|
||
}
|
||
|
||
#region 登录接口
|
||
|
||
/// <summary>
|
||
/// 调用登录接口(自定义错误版)
|
||
/// </summary>
|
||
public async void Login(string email, string password, Action<LoginData> onSuccess, Action<int, string> onError)
|
||
{
|
||
await LoginWithError(email, password, onSuccess, onError);
|
||
}
|
||
|
||
private async Task LoginWithError(string email, string password, Action<LoginData> onSuccess, Action<int, string> onError)
|
||
{
|
||
var requestData = new LoginRequest
|
||
{
|
||
email = email,
|
||
password = password
|
||
};
|
||
|
||
LoadingUI.Show();
|
||
|
||
try
|
||
{
|
||
var response = await NetworkCtrl.Instance.Post<LoginResponse>("/api/v1/auth/login", requestData);
|
||
|
||
LoadingUI.Hide();
|
||
|
||
if(response.Data.code==200)
|
||
{
|
||
onSuccess?.Invoke(response.Data.data);
|
||
DataManager.Instance.SetToken(response.Data.data.token,response.Data.data.user);
|
||
}
|
||
else
|
||
{
|
||
onError?.Invoke(response.Data.code, response.Data.message);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LoadingUI.Hide();
|
||
Debug.LogError("登录异常: " + ex.Message);
|
||
onError?.Invoke(-1, "登录异常");
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 当前登录邮箱
|
||
|
||
private string currentEmail = "";
|
||
|
||
/// <summary>
|
||
/// 设置当前登录邮箱
|
||
/// </summary>
|
||
public void SetCurrentEmail(string email)
|
||
{
|
||
currentEmail = email;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前登录邮箱
|
||
/// </summary>
|
||
public string GetCurrentEmail()
|
||
{
|
||
return currentEmail;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 验证邮箱是否已注册
|
||
|
||
/// <summary>
|
||
/// 验证邮箱是否已注册(模拟接口)
|
||
/// </summary>
|
||
public async Task CheckEmailRegistered(string email, Action<bool> onSuccess, Action<int, string> onError)
|
||
{
|
||
LoadingUI.Show();
|
||
|
||
var requestData = new EmailCodeRequest
|
||
{
|
||
email = email
|
||
};
|
||
|
||
var response = await NetworkCtrl.Instance.Post<BoolResponse>("/api/v1/auth/email/check", requestData);
|
||
|
||
LoadingUI.Hide();
|
||
|
||
ResponseCodeHandler.HandleResponse(response,
|
||
onSuccess: (data) =>
|
||
{
|
||
Debug.Log(data.data.registered);
|
||
// 安全访问,防止 data 或 data.data 为 null
|
||
bool isRegistered = data?.data?.registered ?? false;
|
||
onSuccess?.Invoke(isRegistered);
|
||
},
|
||
onError: onError
|
||
);
|
||
|
||
|
||
}
|
||
|
||
#endregion
|
||
#region 发送验证码
|
||
|
||
|
||
public async Task SendCode(string email, Action onSuccess)
|
||
{
|
||
LoadingUI.Show();
|
||
|
||
var requestData = new EmailCodeRequest
|
||
{
|
||
email = email
|
||
};
|
||
|
||
try
|
||
{
|
||
var response = await NetworkCtrl.Instance.Post<NoDataResponse>("/api/v1/auth/email/code", requestData);
|
||
|
||
LoadingUI.Hide();
|
||
|
||
ResponseCodeHandler.HandleResponse(response,
|
||
onSuccess: (data) =>
|
||
{
|
||
Debug.Log("验证码发送成功");
|
||
onSuccess?.Invoke();
|
||
},
|
||
onError: null
|
||
);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LoadingUI.Hide();
|
||
Debug.LogError("发送验证码异常: " + ex.Message);
|
||
}
|
||
}
|
||
#endregion
|
||
#region 校验验证码
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 校验验证码
|
||
/// </summary>
|
||
public async void VerifyCode(string email, string code, Action onSuccess, Action<int, string> onError)
|
||
{
|
||
LoadingUI.Show();
|
||
|
||
var requestData = new VerifyCodeRequest
|
||
{
|
||
email = email,
|
||
code = code
|
||
};
|
||
try
|
||
{
|
||
var response = await NetworkCtrl.Instance.Post<NoDataResponse>("/api/v1/auth/email/verify", requestData);
|
||
|
||
LoadingUI.Hide();
|
||
|
||
ResponseCodeHandler.HandleResponse(response,
|
||
onSuccess: (data) =>
|
||
{
|
||
Debug.Log("验证码校验成功");
|
||
onSuccess?.Invoke();
|
||
},
|
||
onError: onError
|
||
);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LoadingUI.Hide();
|
||
Debug.LogError("校验验证码异常: " + ex.Message);
|
||
onError?.Invoke(-1, ex.Message);
|
||
}
|
||
}
|
||
#endregion
|
||
#region 注册账号
|
||
/// <summary>
|
||
/// 注册账号
|
||
/// </summary>
|
||
public async void Register(string email, string password, int password_type, Action onSuccess, Action<int, string> onError)
|
||
{
|
||
LoadingUI.Show();
|
||
var requestData = new RegisterRequest
|
||
{
|
||
email = email,
|
||
password = password,
|
||
password_type = password_type
|
||
};
|
||
try
|
||
{
|
||
var response = await NetworkCtrl.Instance.Post<LoginResponse>("/api/v1/auth/register", requestData);
|
||
LoadingUI.Hide();
|
||
ResponseCodeHandler.HandleResponse(response,
|
||
onSuccess: (data) =>
|
||
{
|
||
Debug.Log("注册成功");
|
||
onSuccess?.Invoke();
|
||
},
|
||
onError: onError
|
||
);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LoadingUI.Hide();
|
||
Debug.LogError("注册异常: " + ex.Message);
|
||
onError?.Invoke(-1, ex.Message);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 重置密码
|
||
|
||
|
||
/// <summary>
|
||
/// 重置密码(忘记密码)
|
||
/// </summary>
|
||
public async void ResetPassword(string email, string password, int password_type, Action onSuccess, Action<int, string> onError)
|
||
{
|
||
LoadingUI.Show();
|
||
var requestData = new ResetPasswordRequest
|
||
{
|
||
email = email,
|
||
password = password,
|
||
password_type = password_type
|
||
};
|
||
try
|
||
{
|
||
var response = await NetworkCtrl.Instance.Post<NoDataResponse>("/api/v1/auth/reset-password", requestData);
|
||
LoadingUI.Hide();
|
||
ResponseCodeHandler.HandleResponse(response,
|
||
onSuccess: (data) =>
|
||
{
|
||
Debug.Log("重置密码成功");
|
||
onSuccess?.Invoke();
|
||
},
|
||
onError: onError
|
||
);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LoadingUI.Hide();
|
||
Debug.LogError("重置密码异常: " + ex.Message);
|
||
onError?.Invoke(-1, ex.Message);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 第三方账号登录
|
||
/// <summary>
|
||
/// 谷歌登录
|
||
/// </summary>
|
||
public void OnGoogleLogin()
|
||
{
|
||
Debug.Log("开始谷歌登录...");
|
||
|
||
LoadingUI.Show();
|
||
|
||
FirebaseAuthManager.Instance.SignInWithGoogle(
|
||
onSuccess: (result) =>
|
||
{
|
||
LoadingUI.Hide();
|
||
Debug.Log($"谷歌登录成功: {result.DisplayName}, FirebaseID: {result.FirebaseUserId}");
|
||
FireBaseLogin(result.FirebaseUserId, onSuccess:(response) =>
|
||
{
|
||
Debug.Log(response.token);
|
||
|
||
},onError:(code,message)=>
|
||
{
|
||
Debug.Log(message);
|
||
});
|
||
},
|
||
onError: (error) =>
|
||
{
|
||
LoadingUI.Hide();
|
||
Debug.LogError($"谷歌登录失败: {error}");
|
||
ToastUI.Show("100036"); // 登录失败提示
|
||
}
|
||
);
|
||
}
|
||
/// <summary>
|
||
/// Firebase登录
|
||
/// </summary>
|
||
public async void FireBaseLogin(string firebaseUserId, Action<LoginData> onSuccess, Action<int, string> onError)
|
||
{
|
||
LoadingUI.Show();
|
||
var requestData = new FireBaseLoginRequest
|
||
{
|
||
firebase_token = firebaseUserId
|
||
};
|
||
try
|
||
{
|
||
var response = await NetworkCtrl.Instance.Post<LoginResponse>("/api/v1/auth/firebase/login", requestData);
|
||
LoadingUI.Hide();
|
||
ResponseCodeHandler.HandleResponse(response,
|
||
onSuccess: (data) =>
|
||
{
|
||
Debug.Log("Firebase登录成功");
|
||
onSuccess?.Invoke(response.Data.data);
|
||
},
|
||
onError: onError
|
||
);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LoadingUI.Hide();
|
||
Debug.LogError("Firebase登录异常: " + ex.Message);
|
||
onError?.Invoke(-1, ex.Message);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
#endregion
|
||
}
|
||
}
|
||
|