refactor: 优化密码校验与第三方登录逻辑,新增未设密码引导流程

1. 移除MainScene和UIManager中的首次启动标记逻辑
2. 新增DataManager的HasAnyPassword方法检测用户是否设置过密码
3. 完善HomePage的CheckPasswordPage,新增未设密码引导弹窗
4. 调整SelfVerificationCodePanel支持自定义返回回调
5. 适配苹果第三方登录无需强制设置密码的审核要求
6. 新增多语言词条支持密码引导文案
7. 移除HomePageCtrl在应用暂停时自动锁定按钮的逻辑
This commit is contained in:
“虞渠成” 2026-09-20 14:04:59 +08:00
parent 5791de31f1
commit 10ad83d6b0
15 changed files with 6904 additions and 6375 deletions

View File

@ -1718,6 +1718,26 @@
"key": "100334",
"zh": "蓝牙未开启,如需使用请打开",
"en": "Bluetooth is off. Turn it on if needed."
},
{
"key": "100335",
"zh": "尚未设置密码",
"en": "No Password Set"
},
{
"key": "100336",
"zh": "请先设置密码,用于解锁设备控制权限",
"en": "Please set a password to unlock device controls."
},
{
"key": "100337",
"zh": "暂不设置",
"en": "Not Now"
},
{
"key": "100338",
"zh": "立即设置",
"en": "Set Now"
}

File diff suppressed because it is too large Load Diff

View File

@ -1306,7 +1306,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c20a27a0d37fc6c4286016e1a15a9d25, type: 3}
m_Name:
m_EditorClassIdentifier:
isFirstTime: 1
pages:
- pageName: 1
bundleName: ui_loginpage

View File

@ -170,6 +170,18 @@ namespace Kill.Managers
{
lastUnlockTime = Time.realtimeSinceStartup;
}
#endregion
#region
/// <summary>
/// 用户当前账号是否已设置过任何一种密码(用于 LockButtonPlane 决定显示密码输入还是引导)
/// </summary>
public bool HasAnyPassword()
{
return userInfo != null && (userInfo.has_simple_password || userInfo.has_complex_password);
}
#endregion
public void InitUser()
{

View File

@ -208,7 +208,8 @@ namespace Kill.Managers
Email = user.Email ?? appleIdCredential.Email,
DisplayName = user.DisplayName ?? GetAppleDisplayName(appleIdCredential.FullName),
PhotoUrl = user.PhotoUrl?.ToString(),
IdToken = ""
IdToken = "",
Provider = "apple.com"
};
onSuccess?.Invoke(result);
});
@ -281,7 +282,8 @@ namespace Kill.Managers
Email = user.Email,
DisplayName = user.DisplayName,
PhotoUrl = user.PhotoUrl?.ToString(),
IdToken = ""
IdToken = "",
Provider = providerId
};
onSuccess?.Invoke(result);
});
@ -404,5 +406,6 @@ namespace Kill.Managers
public string DisplayName; // 显示名称
public string PhotoUrl; // 头像URL
public string IdToken; // ID Token
public string Provider; // 登录提供方: "google.com" / "apple.com"
}
}

View File

@ -16,9 +16,48 @@ namespace Kill.UI.Pages
public InputField passwordInput;
public Text errorText;
public GameObject plane;
// 未设置密码时的引导分支(仅在 passwordInput 等组件未挂时强制进入;正常面板同时具备输入与引导能力)
[Header("未设密码引导")]
public GameObject passwordCheckPanel; // 密码输入区域容器(含 InputField / 确认按钮等)
public GameObject passwordGuidePanel; // "引导去设置密码"提示区域容器
public Button setupPasswordBtn; // "立即设置密码" 按钮
public Button remindLaterBtn; // "稍后再说" 按钮
private void Awake()
{
if (setupPasswordBtn != null)
{
setupPasswordBtn.onClick.RemoveAllListeners();
setupPasswordBtn.onClick.AddListener(OnSetupPasswordClick);
}
if (remindLaterBtn != null)
{
remindLaterBtn.onClick.RemoveAllListeners();
remindLaterBtn.onClick.AddListener(OnRemindLaterClick);
}
}
public void OnEnable()
{
UIManager.Instance.RegisterBackAction(OnBack);
errorText.text="";
// 检测当前账号是否已设置过密码,决定显示密码输入面板还是引导面板
RefreshByPasswordState();
}
/// <summary>
/// 根据 userInfo 的密码标记切换显示:
/// 未设密码 → 始终显示引导面板(不显示密码输入框,避免用户输什么都是错的)
/// 已设密码 → 显示密码输入面板
/// 简单策略:未设密码时,每次 LockButtonPlane 激活都弹引导,不再用本地日期去重
/// </summary>
private void RefreshByPasswordState()
{
bool hasPassword = DataManager.Instance != null && DataManager.Instance.HasAnyPassword();
if (passwordGuidePanel != null) passwordGuidePanel.SetActive(!hasPassword);
if (passwordCheckPanel != null) passwordCheckPanel.SetActive(hasPassword);
}
public async void OnConfirm()
{
@ -45,7 +84,6 @@ namespace Kill.UI.Pages
gameObject.SetActive(false);
errorText.text="";
passwordInput.text="";
UIManager.Instance.isFirstTime=false;
// 解锁成功,记录解锁时间(自动锁定倒计时起点)
DataManager.Instance.RecordUnlock();
}
@ -68,6 +106,50 @@ namespace Kill.UI.Pages
}
}
/// <summary>
/// 引导面板 - 立即设置密码
/// 关闭当前 LockButtonPlane 并打开个人中心的 设置密码 流程
/// </summary>
public void OnSetupPasswordClick()
{
OnSetPassword();
}
public SelfVerificationCodePanel verificationCodePanelPrefab;
public SelfSetPasswordPanel setPasswordPanelPrefab;
SelfVerificationCodePanel verificationCodePanel;
public void OnSetPassword()
{
verificationCodePanel = Instantiate(verificationCodePanelPrefab, transform);
verificationCodePanel.Init(OnSureVerificationCode, OnBack);
}
SelfSetPasswordPanel setPasswordPanel;
public void OnSureVerificationCode()
{
Destroy(verificationCodePanel.gameObject);
setPasswordPanel = Instantiate(setPasswordPanelPrefab, transform);
setPasswordPanel.Init(OnSetPasswordSuccess);
}
public void OnSetPasswordSuccess()
{
Destroy(setPasswordPanel.gameObject);
plane.SetActive(false);
gameObject.SetActive(false);
// 解锁成功,记录解锁时间(自动锁定倒计时起点)
DataManager.Instance.RecordUnlock();
}
/// <summary>
/// 引导面板 - 稍后再说
/// 仅关闭 LockButtonPlane下次再激活时仍会再次弹出引导面板未设密码时每次都提示
/// </summary>
public void OnRemindLaterClick()
{
gameObject.SetActive(false);
}
public void OnBack()
{
UIManager.Instance.RegisterBackAction(null);
gameObject.SetActive(false);
}
}
}

View File

@ -116,7 +116,6 @@ namespace Kill.UI.Pages
void OnApplicationPause(bool pause)
{
isAppForeground = !pause;
LockButtonPlane.SetActive(true);
}
void OnApplicationFocus(bool hasFocus)
{

View File

@ -639,13 +639,31 @@ namespace Kill.UI.Pages
onError: (code, message) =>
{
Debug.Log(message);
// 未绑定过第三方帐号 → 进入设置密码流程,绑定同时设置密码(无需验证码)
var setPasswordPanel = GetSubPage(SubPageType.SetPassword) as SetPasswordPanel;
if (setPasswordPanel != null)
// 未绑定过第三方帐号:
// - 苹果登录:按苹果审核要求,不强制用户设置密码,直接绑定即可
// - 其他第三方Google 等):进入设置密码流程,绑定同时设置密码(无需验证码)
if (string.Equals(result.Provider, "apple.com", StringComparison.OrdinalIgnoreCase))
{
setPasswordPanel.SetMode(SetPasswordPanel.SetPasswordMode.ThirdPartyBind);
BindFireBase("",
onSuccess: (data) =>
{
UIManager.Instance.OpenPage(UIManager.PageName.homePage, null, true);
},
onError: (bindCode, bindMsg) =>
{
Debug.Log(bindMsg);
ToastUI.ShowText(bindCode.ToString());
});
}
else
{
var setPasswordPanel = GetSubPage(SubPageType.SetPassword) as SetPasswordPanel;
if (setPasswordPanel != null)
{
setPasswordPanel.SetMode(SetPasswordPanel.SetPasswordMode.ThirdPartyBind);
}
ClearHistoryAndShow(SubPageType.SetPassword);
}
ClearHistoryAndShow(SubPageType.SetPassword);
});
}

View File

@ -127,7 +127,7 @@ namespace Kill.UI.Pages
public void OnSetPassword()
{
verificationCodePanel = Instantiate(verificationCodePanelPrefab, transform);
verificationCodePanel.Init(OnSureVerificationCode);
verificationCodePanel.Init(OnSureVerificationCode, OnBack);
}
SelfSetPasswordPanel setPasswordPanel;
public void OnSureVerificationCode()

View File

@ -31,9 +31,11 @@ namespace Kill.UI.Pages
public Button backButton;
Action onSuccessCallback;
public void Init(Action onsuccess)
Action onBackCallback;
public void Init(Action onsuccess, Action onback)
{
onSuccessCallback=onsuccess;
onBackCallback=onback;
UIManager.Instance.RegisterBackAction(OnBack);
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(OnBack);
@ -155,7 +157,7 @@ namespace Kill.UI.Pages
}
public void OnBack()
{
UIManager.Instance.RegisterBackAction(GetComponentInParent<SelfInfoPage>().OnBack);
UIManager.Instance.RegisterBackAction(onBackCallback);
Destroy(gameObject);
}
/// <summary>

View File

@ -11,7 +11,6 @@ namespace Kill.UI
{
public class UIManager : MonoBehaviour
{
public bool isFirstTime=true;
public enum PageName
{
nullPage = 0,
@ -217,10 +216,6 @@ namespace Kill.UI
prefab = await LoadRes.Instance.LoadAssetAsync<GameObject>(pages[index].bundleName, assetName);
nowPage = Instantiate(prefab, bg);
nowPageName = pageName;
if(isFirstTime)
{
nowPage.GetComponent<HomePageCtrl>().LockButtonPlane.SetActive(true);
}
break;
case PageName.connectDevicePage:
assetName = "connectDevicePage.prefab";
@ -270,10 +265,6 @@ namespace Kill.UI
{
OpenPage(pageName, null, true);
}
void OnApplicationPause(bool pause)
{
isFirstTime=true;
}
}
}