Преглед изворни кода

Merge remote-tracking branch 'remotes/origin/master' into GFG

# Conflicts:
#	GameClient/GameClient.sln.DotSettings.user
hexiaojie пре 1 дан
родитељ
комит
6cf8647465
66 измењених фајлова са 1996 додато и 189 уклоњено
  1. 1 1
      GameClient/Assets/Editor/Excel/Template/Config.txt
  2. 3 0
      GameClient/Assets/Game/HotUpdate/AccountData.meta
  3. 27 0
      GameClient/Assets/Game/HotUpdate/AccountData/AccountData.cs
  4. 3 0
      GameClient/Assets/Game/HotUpdate/AccountData/AccountData.cs.meta
  5. 219 0
      GameClient/Assets/Game/HotUpdate/AccountData/AccountManager.cs
  6. 3 0
      GameClient/Assets/Game/HotUpdate/AccountData/AccountManager.cs.meta
  7. 70 0
      GameClient/Assets/Game/HotUpdate/AccountData/AesEncryption.cs
  8. 3 0
      GameClient/Assets/Game/HotUpdate/AccountData/AesEncryption.cs.meta
  9. 2 0
      GameClient/Assets/Game/HotUpdate/Constant/ConstMessage.cs
  10. 11 2
      GameClient/Assets/Game/HotUpdate/Controller/LoginController.cs
  11. 1 1
      GameClient/Assets/Game/HotUpdate/Data/ActivityDataManager.cs
  12. 17 12
      GameClient/Assets/Game/HotUpdate/ETCodes/Hotfix/App/Login/LoginHelper.cs
  13. 3 0
      GameClient/Assets/Game/HotUpdate/ETCodes/Hotfix/App/Security.meta
  14. 185 0
      GameClient/Assets/Game/HotUpdate/ETCodes/Hotfix/App/Security/SecurityHelper.cs
  15. 3 0
      GameClient/Assets/Game/HotUpdate/ETCodes/Hotfix/App/Security/SecurityHelper.cs.meta
  16. 21 15
      GameClient/Assets/Game/HotUpdate/ETCodes/Model/App/Session/SessionComponent.cs
  17. 86 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_BangDingPhoneUI.cs
  18. 11 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_BangDingPhoneUI.cs.meta
  19. 74 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ButAccountItem.cs
  20. 11 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ButAccountItem.cs.meta
  21. 74 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ButAccountItem2.cs
  22. 11 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ButAccountItem2.cs.meta
  23. 80 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ComAccountInputBox.cs
  24. 11 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ComAccountInputBox.cs.meta
  25. 13 6
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_LoginInputUI.cs
  26. 9 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_RegisterUI.cs
  27. 12 3
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_RegisterUIBackup.cs
  28. 86 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_UnbindPhoneUI.cs
  29. 11 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_UnbindPhoneUI.cs.meta
  30. 86 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ZhaoHuiAccountUI.cs
  31. 11 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ZhaoHuiAccountUI.cs.meta
  32. 95 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ZhaoHuiPasswordUI.cs
  33. 11 0
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ZhaoHuiPasswordUI.cs.meta
  34. 6 15
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/RoleInfo/UI_PhoneBindingUI.cs
  35. 6 3
      GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/RoleInfo/UI_SettingUI.cs
  36. 1 1
      GameClient/Assets/Game/HotUpdate/GameConfig.cs
  37. 1 20
      GameClient/Assets/Game/HotUpdate/ServerProxy/RoleInfoSProxy.cs
  38. 128 8
      GameClient/Assets/Game/HotUpdate/Views/Login/LoginInputView.cs
  39. 38 17
      GameClient/Assets/Game/HotUpdate/Views/Login/RegisterView.cs
  40. 163 0
      GameClient/Assets/Game/HotUpdate/Views/Login/ZhaoHuiAccountView.cs
  41. 3 0
      GameClient/Assets/Game/HotUpdate/Views/Login/ZhaoHuiAccountView.cs.meta
  42. 134 0
      GameClient/Assets/Game/HotUpdate/Views/Login/ZhaoHuiPasswordView.cs
  43. 3 0
      GameClient/Assets/Game/HotUpdate/Views/Login/ZhaoHuiPasswordView.cs.meta
  44. 54 50
      GameClient/Assets/Game/HotUpdate/Views/RoleInfo/PhoneBindingView.cs
  45. 63 18
      GameClient/Assets/Game/HotUpdate/Views/RoleInfo/SettingView.cs
  46. 123 0
      GameClient/Assets/Game/HotUpdate/Views/RoleInfo/UnbindPhoneView.cs
  47. 3 0
      GameClient/Assets/Game/HotUpdate/Views/RoleInfo/UnbindPhoneView.cs.meta
  48. 6 17
      GameClient/Assets/Game/HotUpdate/Views/RoleInfoRegister/RoleInfoRegisterView.cs
  49. BIN
      GameClient/Assets/ResIn/UI/Login/Login_atlas0!a.png
  50. BIN
      GameClient/Assets/ResIn/UI/Login/Login_atlas0.png
  51. BIN
      GameClient/Assets/ResIn/UI/Login/Login_fui.bytes
  52. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0!a.png
  53. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0.png
  54. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_1!a.png
  55. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_1.png
  56. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_2!a.png
  57. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_2.png
  58. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_3!a.png
  59. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_3.png
  60. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_4!a.png
  61. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_4.png
  62. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_5!a.png
  63. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_5.png
  64. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_6!a.png
  65. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_6.png
  66. BIN
      GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_fui.bytes

+ 1 - 1
GameClient/Assets/Editor/Excel/Template/Config.txt

@@ -15,7 +15,7 @@ namespace GFGGame
 {variable assignment}
 
 #if UNITY_2017_1_OR_NEWER
-            LogUtil.LogEditor("InitConfig:" + nameof({CfgName}));
+            //LogUtil.LogEditor("InitConfig:" + nameof({CfgName}));
 #endif
 		}
 		

+ 3 - 0
GameClient/Assets/Game/HotUpdate/AccountData.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 3ee4f97ed21a4e22b6db88b8fc602fba
+timeCreated: 1760253919

+ 27 - 0
GameClient/Assets/Game/HotUpdate/AccountData/AccountData.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+
+namespace GFGGame
+{
+    [System.Serializable]
+    public class AccountData
+    {
+        public string username;
+        public string encryptedPassword; // 存储的是加密后的字符串
+        public string timestamp; // 用于记录时间,决定“最近”顺序
+
+        public AccountData(string user, string encryptedPwd)
+        {
+            username = user;
+            encryptedPassword = encryptedPwd;
+            timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss"); // 使用UTC时间避免时区问题
+        }
+    }
+
+    // 可序列化的账号列表包装器,用于JSON处理
+    [System.Serializable]
+    public class AccountDataList
+    {
+        public List<AccountData> accounts = new List<AccountData>();
+    }
+}

+ 3 - 0
GameClient/Assets/Game/HotUpdate/AccountData/AccountData.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 85309bf41e554148acc90779f3114d8d
+timeCreated: 1760251742

+ 219 - 0
GameClient/Assets/Game/HotUpdate/AccountData/AccountManager.cs

@@ -0,0 +1,219 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+namespace GFGGame
+{
+    public sealed class AccountManager
+    {
+        private const string SAVE_KEY = "RecentAccountsData";
+        private const int MAX_ACCOUNT_COUNT = 20;
+        private List<AccountData> _cachedAccounts = new List<AccountData>();
+
+        // 单例实例
+        private static readonly Lazy<AccountManager> _instance = new Lazy<AccountManager>(() => new AccountManager());
+        public static AccountManager Instance => _instance.Value;
+
+        // 私有构造函数,防止外部实例化
+        private AccountManager()
+        {
+            LoadAccounts();
+        }
+
+        /// <summary>
+        /// 登录成功时调用此方法
+        /// </summary>
+        /// <param name="username">用户名</param>
+        /// <param name="plainPassword">明文密码</param>
+        public void SaveAccount(string username, string plainPassword)
+        {
+            // 1. 加密密码
+            string encryptedPwd = null;
+            if (plainPassword != null)
+            {
+                encryptedPwd = AesEncryption.Encrypt(plainPassword);
+            }
+
+            // 2. 检查列表中是否已有该账号
+            AccountData existingAccount = _cachedAccounts.FirstOrDefault(a => a.username == username);
+            if (existingAccount != null)
+            {
+                // 如果存在,更新密码和时间戳,并移到列表最前面(表示最新)
+                existingAccount.encryptedPassword = encryptedPwd;
+                existingAccount.timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
+                _cachedAccounts.Remove(existingAccount);
+                _cachedAccounts.Insert(0, existingAccount);
+            }
+            else
+            {
+                // 如果不存在,创建新账号数据并添加到最前面
+                AccountData newAccount = new AccountData(username, encryptedPwd);
+                _cachedAccounts.Insert(0, newAccount);
+            }
+
+            // 3. 如果超出最大数量,移除最旧的一个(列表最后一个)
+            if (_cachedAccounts.Count > MAX_ACCOUNT_COUNT)
+            {
+                _cachedAccounts.RemoveAt(_cachedAccounts.Count - 1);
+            }
+
+            // 4. 立即保存
+            SaveAccounts();
+        }
+
+        /// <summary>
+        /// 获取存储的所有账号信息(密码已解密)
+        /// </summary>
+        public List<AccountPasswordModel> GetAccounts()
+        {
+            List<AccountPasswordModel> result = new List<AccountPasswordModel>();
+            foreach (var acc in _cachedAccounts)
+            {
+                string decryptedPwd = null;
+                if (acc.encryptedPassword != null)
+                {
+                    decryptedPwd = AesEncryption.Decrypt(acc.encryptedPassword);
+                }
+
+                AccountPasswordModel accountPasswordModel = new AccountPasswordModel()
+                {
+                    Account = acc.username,
+                    Password = decryptedPwd
+                };
+                result.Add(accountPasswordModel);
+            }
+
+            return result;
+        }
+
+        /// <summary>
+        /// 删除指定的账号缓存
+        /// </summary>
+        /// <param name="username">要删除的用户名</param>
+        /// <returns>是否成功删除</returns>
+        public bool DeleteAccount(string username)
+        {
+            // 查找要删除的账号
+            AccountData accountToDelete = _cachedAccounts.FirstOrDefault(a => a.username == username);
+
+            if (accountToDelete != null)
+            {
+                // 从缓存列表中移除
+                _cachedAccounts.Remove(accountToDelete);
+
+                // 立即保存
+                SaveAccounts();
+
+                Debug.Log($"已成功删除账号: {username}");
+                return true;
+            }
+            else
+            {
+                Debug.LogWarning($"未找到账号: {username},删除失败");
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 批量删除多个账号缓存
+        /// </summary>
+        /// <param name="usernames">要删除的用户名列表</param>
+        /// <returns>成功删除的数量</returns>
+        public int DeleteAccounts(List<string> usernames)
+        {
+            int deletedCount = 0;
+
+            foreach (string username in usernames)
+            {
+                if (DeleteAccount(username))
+                {
+                    deletedCount++;
+                }
+            }
+
+            Debug.Log($"成功删除了 {deletedCount} 个账号");
+            return deletedCount;
+        }
+
+        /// <summary>
+        /// 清除所有账号记录
+        /// </summary>
+        public void ClearAllAccounts()
+        {
+            _cachedAccounts.Clear();
+            PlayerPrefs.DeleteKey(SAVE_KEY);
+            PlayerPrefs.Save();
+            Debug.Log("已清除所有账号记录");
+        }
+
+        /// <summary>
+        /// 检查指定账号是否存在
+        /// </summary>
+        public bool HasAccount(string username)
+        {
+            return _cachedAccounts.Any(a => a.username == username);
+        }
+
+        /// <summary>
+        /// 获取缓存的账号数量
+        /// </summary>
+        public int GetAccountCount()
+        {
+            return _cachedAccounts.Count;
+        }
+
+        // 内部方法:从PlayerPrefs加载账号列表
+        private void LoadAccounts()
+        {
+            _cachedAccounts.Clear();
+            string encryptedJson = PlayerPrefs.GetString(SAVE_KEY, null);
+
+            if (!string.IsNullOrEmpty(encryptedJson))
+            {
+                string decryptedJson = AesEncryption.Decrypt(encryptedJson);
+                if (!string.IsNullOrEmpty(decryptedJson))
+                {
+                    try
+                    {
+                        // 反序列化JSON字符串到对象
+                        AccountDataList loadedData = JsonUtility.FromJson<AccountDataList>(decryptedJson);
+                        if (loadedData != null && loadedData.accounts != null)
+                        {
+                            // 按时间戳降序排序,最新的在最前面
+                            _cachedAccounts = loadedData.accounts
+                                .OrderByDescending(a => a.timestamp)
+                                .ToList();
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        Debug.LogError("Failed to parse account data: " + e.Message);
+                    }
+                }
+            }
+        }
+
+        // 内部方法:保存账号列表到PlayerPrefs
+        private void SaveAccounts()
+        {
+            // 包装列表
+            AccountDataList dataToSave = new AccountDataList();
+            dataToSave.accounts = _cachedAccounts;
+
+            // 序列化为JSON
+            string json = JsonUtility.ToJson(dataToSave);
+            // 加密JSON字符串
+            string encryptedJson = AesEncryption.Encrypt(json);
+            // 保存到PlayerPrefs
+            PlayerPrefs.SetString(SAVE_KEY, encryptedJson);
+            PlayerPrefs.Save(); // 确保立即写入磁盘
+        }
+    }
+
+    public class AccountPasswordModel
+    {
+        public string Account { get; set; }
+        public string Password { get; set; }
+    }
+}

+ 3 - 0
GameClient/Assets/Game/HotUpdate/AccountData/AccountManager.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f59ec2b6c1a04b3f987b18314da634ef
+timeCreated: 1760253941

+ 70 - 0
GameClient/Assets/Game/HotUpdate/AccountData/AesEncryption.cs

@@ -0,0 +1,70 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace GFGGame
+{
+    public static class AesEncryption
+    {
+        // !!!重要警告!!!
+        // 硬编码在客户端的密钥并不安全,容易被反编译获取。
+        // 这只能防止简单的窥探,无法抵御专业黑客。
+        // 对于极度敏感的信息,请考虑其他方案(如服务端令牌验证)。
+        private static readonly string Key = "45418100000000000000000000000000"; // 必须恰好是32字节
+        private static readonly string IV = "1234567890123456"; // 必须恰好是16字节
+
+        public static string Encrypt(string plainText)
+        {
+            using (Aes aesAlg = Aes.Create())
+            {
+                aesAlg.Key = Encoding.UTF8.GetBytes(Key);
+                aesAlg.IV = Encoding.UTF8.GetBytes(IV);
+
+                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
+                using (MemoryStream msEncrypt = new MemoryStream())
+                {
+                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
+                    {
+                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
+                        {
+                            swEncrypt.Write(plainText);
+                        }
+                    }
+
+                    return Convert.ToBase64String(msEncrypt.ToArray());
+                }
+            }
+        }
+
+        public static string Decrypt(string cipherText)
+        {
+            try
+            {
+                byte[] buffer = Convert.FromBase64String(cipherText);
+                using (Aes aesAlg = Aes.Create())
+                {
+                    aesAlg.Key = Encoding.UTF8.GetBytes(Key);
+                    aesAlg.IV = Encoding.UTF8.GetBytes(IV);
+
+                    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
+                    using (MemoryStream msDecrypt = new MemoryStream(buffer))
+                    {
+                        using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
+                        {
+                            using (StreamReader srDecrypt = new StreamReader(csDecrypt))
+                            {
+                                return srDecrypt.ReadToEnd();
+                            }
+                        }
+                    }
+                }
+            }
+            catch
+            {
+                // 解密失败(可能数据被篡改或密钥错误)
+                return null;
+            }
+        }
+    }
+}

+ 3 - 0
GameClient/Assets/Game/HotUpdate/AccountData/AesEncryption.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: fe3b0326cee544169590c724b384b766
+timeCreated: 1760254036

+ 2 - 0
GameClient/Assets/Game/HotUpdate/Constant/ConstMessage.cs

@@ -272,5 +272,7 @@ namespace GFGGame
         public const string BlindBox_BuyOne = "BlindBox_BuyOne";
         //盲盒购买所有
         public const string BlindBox_BuyAll = "BlindBox_BuyAll";
+        //手机号变动
+        public const string PhoneChange = "PhoneChange";
     }
 }

+ 11 - 2
GameClient/Assets/Game/HotUpdate/Controller/LoginController.cs

@@ -175,12 +175,21 @@ namespace GFGGame
             return;
         }
 
+        /// <summary>
+        /// 注册
+        /// </summary>
+        /// <param name="account">账号</param>
+        /// <param name="password">密码</param>
+        /// <param name="name">身份证名</param>
+        /// <param name="identityNum">身份证号码</param>
+        /// <param name="code">手机验证码</param>
+        /// <param name="phoneNumber">手机号码</param>
         public static async ETTask Register(string account, string password, string name, string identityNum,
-            string code)
+            string code, string phoneNumber)
         {
             ViewManager.Show<ModalStatusView>("注册中...");
             int errorCode = await LoginHelper.Register(GameGlobal.zoneScene, GameConfig.LoginAddress, account, password,
-                name, identityNum, code);
+                name, identityNum, code, phoneNumber);
 
             if (errorCode == ErrorCode.ERR_Success)
             {

+ 1 - 1
GameClient/Assets/Game/HotUpdate/Data/ActivityDataManager.cs

@@ -445,6 +445,6 @@ namespace GFGGame
         public BlindBoxType typeOne = new BlindBoxType { type = 1, check = false };
         public BlindBoxType typeAll = new BlindBoxType { type = 6, check = false };
         /*****************************************************************/
-        public string PhoneNum = "";
+        public string PhoneNumber = "";
     }
 }

+ 17 - 12
GameClient/Assets/Game/HotUpdate/ETCodes/Hotfix/App/Login/LoginHelper.cs

@@ -37,7 +37,7 @@ namespace ET
                 return (a2CLoginAccount.Error, a2CLoginAccount.DeleteTime);
             }
 
-            OnLoginSuccess(zoneScene, a2CLoginAccount, accountSession, account);
+            OnLoginSuccess(zoneScene, a2CLoginAccount, accountSession, account, null);
 
             return (ErrorCode.ERR_Success, 0);
         }
@@ -47,15 +47,16 @@ namespace ET
         {
             A2C_LoginAccount a2CLoginAccount = null;
             Session accountSession = null;
+            var passwordMD5 = password;
+            //密码禁止明文传输
+            if (!isMD5)
+            {
+                passwordMD5 = MD5Helper.stringMD5(password);
+            }
+
             try
             {
                 accountSession = zoneScene.GetComponent<NetKcpComponent>().Create(NetworkHelper.ToIPEndPoint(address));
-                var passwordMD5 = password;
-                //密码禁止明文传输
-                if (!isMD5)
-                {
-                    passwordMD5 = MD5Helper.stringMD5(password);
-                }
 
                 a2CLoginAccount = (A2C_LoginAccount)await accountSession.Call(new C2A_LoginAccount()
                 {
@@ -80,13 +81,13 @@ namespace ET
                 return (a2CLoginAccount.Error, a2CLoginAccount.DeleteTime);
             }
 
-            OnLoginSuccess(zoneScene, a2CLoginAccount, accountSession, account);
+            OnLoginSuccess(zoneScene, a2CLoginAccount, accountSession, account, password);
 
             return (ErrorCode.ERR_Success, 0);
         }
 
         public static void OnLoginSuccess(Scene zoneScene, A2C_LoginAccount a2CLoginAccount, Session accountSession,
-            string account)
+            string account, string passwordMD5)
         {
             zoneScene.GetComponent<SessionComponent>().AccountSession = accountSession;
             accountSession.AddComponent<PingComponent>();
@@ -97,11 +98,14 @@ namespace ET
             accountInfoComponent.AccountId = a2CLoginAccount.AccountId;
             accountInfoComponent.Account = account;
             accountInfoComponent.Age = a2CLoginAccount.Age;
+            if (account != null)
+            {
+                AccountManager.Instance.SaveAccount(account, passwordMD5);
+            }
         }
 
-
         public static async ETTask<int> Register(Scene zoneScene, string address, string account, string password,
-            string name, string identityNum, string code)
+            string name, string identityNum, string code, string phoneNumber)
         {
             A2C_Register r2C_Register = null;
             Session session = null;
@@ -119,7 +123,8 @@ namespace ET
                         IdentityNum = identityNum,
                         Code = code,
                         PlatformId = LauncherConfig.platformId,
-                        ChannelId = LauncherConfig.ChannelId
+                        ChannelId = LauncherConfig.ChannelId,
+                        PhoneNumber = phoneNumber
                     });
                     if (r2C_Register.Error != ErrorCode.ERR_Success)
                     {

+ 3 - 0
GameClient/Assets/Game/HotUpdate/ETCodes/Hotfix/App/Security.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 9480152ba6194352b5db32d091a0ff1e
+timeCreated: 1761142720

+ 185 - 0
GameClient/Assets/Game/HotUpdate/ETCodes/Hotfix/App/Security/SecurityHelper.cs

@@ -0,0 +1,185 @@
+using System;
+using ET;
+
+namespace GFGGame
+{
+    public static class SecurityHelper
+    {
+        /// <summary>
+        /// 未进入游戏前--请求获取验证码
+        /// </summary>
+        /// <param name="account"></param>
+        /// <param name="reqType"></param>
+        /// <returns></returns>
+        public static async ETTask<S2C_GetMobileVerificationCode> GetMobileVerificationCode(string account,
+            SendCodeType reqType)
+        {
+            S2C_GetMobileVerificationCode s2CGetMobileVerificationCode = null;
+            Session session = null;
+            try
+            {
+                session = GameGlobal.zoneScene.GetComponent<NetKcpComponent>()
+                    .Create(NetworkHelper.ToIPEndPoint(GameConfig.LoginAddress));
+
+                s2CGetMobileVerificationCode = (S2C_GetMobileVerificationCode)await session.Call(
+                    new C2S_GetMobileVerificationCode()
+                    {
+                        PhoneNumber = account,
+                        ReqType = reqType,
+                    });
+            }
+            catch (Exception e)
+            {
+                session?.Dispose();
+                Log.Debug(e.ToString());
+                return s2CGetMobileVerificationCode;
+            }
+            
+            return s2CGetMobileVerificationCode;
+        }
+
+        /// <summary>
+        /// 账号找回
+        /// </summary>
+        /// <param name="code"></param>
+        /// <param name="phoneNumber"></param>
+        /// <returns></returns>
+        public static async ETTask<A2C_GetAccountListByPhone> GetAccountListByPhone(string code,
+            string phoneNumber)
+        {
+            A2C_GetAccountListByPhone res = null;
+            Session session = null;
+            try
+            {
+                session = GameGlobal.zoneScene.GetComponent<NetKcpComponent>()
+                    .Create(NetworkHelper.ToIPEndPoint(GameConfig.LoginAddress));
+
+                res = (A2C_GetAccountListByPhone)await session.Call(
+                    new C2A_GetAccountListByPhone()
+                    {
+                        Code = code,
+                        ChannelId = LauncherConfig.ChannelId,
+                        PhoneNumber = phoneNumber
+                    });
+            }
+            catch (Exception e)
+            {
+                session?.Dispose();
+                Log.Debug(e.ToString());
+                return res;
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// 修改密码
+        /// </summary>
+        /// <param name="code"></param>
+        /// <param name="phoneNumber"></param>
+        /// <param name="account"></param>
+        /// <param name="password"></param>
+        /// <returns></returns>
+        public static async ETTask<A2C_UpPassword> UpPassword(string code,
+            string phoneNumber, string account, string password)
+        {
+            A2C_UpPassword res = null;
+            Session session = null;
+            password = MD5Helper.stringMD5(password);
+            try
+            {
+                session = GameGlobal.zoneScene.GetComponent<NetKcpComponent>()
+                    .Create(NetworkHelper.ToIPEndPoint(GameConfig.LoginAddress));
+
+                res = (A2C_UpPassword)await session.Call(
+                    new C2A_UpPassword()
+                    {
+                        Code = code,
+                        ChannelId = LauncherConfig.ChannelId,
+                        PhoneNumber = phoneNumber,
+                        Account = account,
+                        Password = password,
+                    });
+            }
+            catch (Exception e)
+            {
+                session?.Dispose();
+                Log.Debug(e.ToString());
+                return res;
+            }
+
+            return res;
+        }
+
+
+        /// <summary>
+        /// 游戏内获取验证码
+        /// </summary>
+        /// <param name="phoneNumber"></param>
+        /// <param name="reqType"></param>
+        /// <returns></returns>
+        public static async ETTask<S2C_GetMobileVerificationCodeUnit> GetMobileVerification(string phoneNumber,
+            SendCodeType reqType)
+        {
+            S2C_GetMobileVerificationCodeUnit res = null;
+            try
+            {
+                res = (S2C_GetMobileVerificationCodeUnit)await MessageHelper.SendToServer(
+                    new C2S_GetMobileVerificationCodeUnit() { PhoneNumber = phoneNumber, ReqType = reqType });
+            }
+            catch (Exception e)
+            {
+                Log.Debug(e.ToString());
+                return res;
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// 游戏内绑定手机
+        /// </summary>
+        /// <param name="phoneNumber"></param>
+        /// <param name="code"></param>
+        /// <returns></returns>
+        public static async ETTask<S2C_BindMobilePhoneNumber> BindMobilePhoneNumber(string phoneNumber, string code)
+        {
+            S2C_BindMobilePhoneNumber res = null;
+            try
+            {
+                res = (S2C_BindMobilePhoneNumber)await MessageHelper.SendToServer(new C2S_BindMobilePhoneNumber()
+                    { PhoneNumber = phoneNumber, VerCode = code });
+            }
+            catch (Exception e)
+            {
+                Log.Debug(e.ToString());
+                return res;
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// 游戏内解除手机号绑定
+        /// </summary>
+        /// <param name="phoneNumber"></param>
+        /// <param name="code"></param>
+        /// <returns></returns>
+        public static async ETTask<S2C_UnbindMobilePhoneNumber> UnbindMobilePhoneNumber(string phoneNumber, string code)
+        {
+            S2C_UnbindMobilePhoneNumber res = null;
+            try
+            {
+                res = (S2C_UnbindMobilePhoneNumber)await MessageHelper.SendToServer(new C2S_UnbindMobilePhoneNumber()
+                    { PhoneNumber = phoneNumber, VerCode = code });
+            }
+            catch (Exception e)
+            {
+                Log.Debug(e.ToString());
+                return res;
+            }
+
+            return res;
+        }
+    }
+}

+ 3 - 0
GameClient/Assets/Game/HotUpdate/ETCodes/Hotfix/App/Security/SecurityHelper.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 6540655f580f4f1db3da3e8868778bcc
+timeCreated: 1761142743

+ 21 - 15
GameClient/Assets/Game/HotUpdate/ETCodes/Model/App/Session/SessionComponent.cs

@@ -1,17 +1,23 @@
 namespace ET
 {
-	public enum SessionState
-	{
-		Login,
-		Gate
-	}
-	public class SessionComponent: Entity, IAwake, IDestroy
-	{
-		//登录会话
-		public Session AccountSession;
-		//游戏会话
-		public Session GateSession;
-		//连接状态
-		public SessionState SessionState;
-	}
-}
+    public enum SessionState
+    {
+        Login,
+        Gate
+    }
+
+    public class SessionComponent : Entity, IAwake, IDestroy
+    {
+        //用来请求获取验证码/找回账号/修改密码用的session
+        public Session TempSession;
+
+        //登录会话
+        public Session AccountSession;
+
+        //游戏会话
+        public Session GateSession;
+
+        //连接状态
+        public SessionState SessionState;
+    }
+}

+ 86 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_BangDingPhoneUI.cs

@@ -0,0 +1,86 @@
+/** This is an automatically generated class by FairyGUI. Please do not modify it. **/
+
+using FairyGUI;
+
+namespace UI.Login
+{
+    public partial class UI_BangDingPhoneUI
+    {
+        public GComponent target;
+        public GComponent m_bg;
+        public GButton m_btnSendCode;
+        public GTextInput m_txtPhone;
+        public GTextInput m_txtCode;
+        public GTextField m_txtAccountShow;
+        public GButton m_btnSubmit;
+        public const string URL = "ui://myoktu7pk5ej6a";
+        public const string PACKAGE_NAME = "Login";
+        public const string RES_NAME = "BangDingPhoneUI";
+        private static UI_BangDingPhoneUI _proxy;
+
+        public static UI_BangDingPhoneUI Create(GObject gObject = null)
+        {
+            var ui = new UI_BangDingPhoneUI();
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static UI_BangDingPhoneUI Proxy(GObject gObject = null)
+        {
+            if(_proxy == null)
+            {
+                _proxy = new UI_BangDingPhoneUI();
+            }
+            var ui = _proxy;
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static void ProxyEnd()
+        {
+            if (_proxy != null)
+            {
+                _proxy.Dispose();
+            }
+        }
+
+        public static void ClearProxy()
+        {
+            ProxyEnd();
+            _proxy = null;
+        }
+
+        private void Init(GComponent comp)
+        {
+            m_bg = (GComponent)comp.GetChild("bg");
+            m_btnSendCode = (GButton)comp.GetChild("btnSendCode");
+            m_txtPhone = (GTextInput)comp.GetChild("txtPhone");
+            m_txtCode = (GTextInput)comp.GetChild("txtCode");
+            m_txtAccountShow = (GTextField)comp.GetChild("txtAccountShow");
+            m_btnSubmit = (GButton)comp.GetChild("btnSubmit");
+        }
+        public void Dispose(bool disposeTarget = false)
+        {
+            m_bg = null;
+            m_btnSendCode = null;
+            m_txtPhone = null;
+            m_txtCode = null;
+            m_txtAccountShow = null;
+            m_btnSubmit = null;
+            if(disposeTarget && target != null)
+            {
+                target.RemoveFromParent();
+                target.Dispose();
+            }
+            target = null;
+        }
+    }
+}

+ 11 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_BangDingPhoneUI.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d30893a593fa75542b5948acca1e1dd1
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 74 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ButAccountItem.cs

@@ -0,0 +1,74 @@
+/** This is an automatically generated class by FairyGUI. Please do not modify it. **/
+
+using FairyGUI;
+
+namespace UI.Login
+{
+    public partial class UI_ButAccountItem
+    {
+        public GButton target;
+        public GTextField m_txtAccountItem;
+        public GButton m_btnDel;
+        public const string URL = "ui://myoktu7pk5ej64";
+        public const string PACKAGE_NAME = "Login";
+        public const string RES_NAME = "ButAccountItem";
+        private static UI_ButAccountItem _proxy;
+
+        public static UI_ButAccountItem Create(GObject gObject = null)
+        {
+            var ui = new UI_ButAccountItem();
+            if(gObject == null)
+            	ui.target =  (GButton)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GButton)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static UI_ButAccountItem Proxy(GObject gObject = null)
+        {
+            if(_proxy == null)
+            {
+                _proxy = new UI_ButAccountItem();
+            }
+            var ui = _proxy;
+            if(gObject == null)
+            	ui.target =  (GButton)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GButton)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static void ProxyEnd()
+        {
+            if (_proxy != null)
+            {
+                _proxy.Dispose();
+            }
+        }
+
+        public static void ClearProxy()
+        {
+            ProxyEnd();
+            _proxy = null;
+        }
+
+        private void Init(GComponent comp)
+        {
+            m_txtAccountItem = (GTextField)comp.GetChild("txtAccountItem");
+            m_btnDel = (GButton)comp.GetChild("btnDel");
+        }
+        public void Dispose(bool disposeTarget = false)
+        {
+            m_txtAccountItem = null;
+            m_btnDel = null;
+            if(disposeTarget && target != null)
+            {
+                target.RemoveFromParent();
+                target.Dispose();
+            }
+            target = null;
+        }
+    }
+}

+ 11 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ButAccountItem.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4a849767c55971348837917e5d857a58
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 74 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ButAccountItem2.cs

@@ -0,0 +1,74 @@
+/** This is an automatically generated class by FairyGUI. Please do not modify it. **/
+
+using FairyGUI;
+
+namespace UI.Login
+{
+    public partial class UI_ButAccountItem2
+    {
+        public GButton target;
+        public GTextField m_txtAccountItem;
+        public GButton m_btnPaswordUp;
+        public const string URL = "ui://myoktu7pk5ej68";
+        public const string PACKAGE_NAME = "Login";
+        public const string RES_NAME = "ButAccountItem2";
+        private static UI_ButAccountItem2 _proxy;
+
+        public static UI_ButAccountItem2 Create(GObject gObject = null)
+        {
+            var ui = new UI_ButAccountItem2();
+            if(gObject == null)
+            	ui.target =  (GButton)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GButton)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static UI_ButAccountItem2 Proxy(GObject gObject = null)
+        {
+            if(_proxy == null)
+            {
+                _proxy = new UI_ButAccountItem2();
+            }
+            var ui = _proxy;
+            if(gObject == null)
+            	ui.target =  (GButton)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GButton)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static void ProxyEnd()
+        {
+            if (_proxy != null)
+            {
+                _proxy.Dispose();
+            }
+        }
+
+        public static void ClearProxy()
+        {
+            ProxyEnd();
+            _proxy = null;
+        }
+
+        private void Init(GComponent comp)
+        {
+            m_txtAccountItem = (GTextField)comp.GetChild("txtAccountItem");
+            m_btnPaswordUp = (GButton)comp.GetChild("btnPaswordUp");
+        }
+        public void Dispose(bool disposeTarget = false)
+        {
+            m_txtAccountItem = null;
+            m_btnPaswordUp = null;
+            if(disposeTarget && target != null)
+            {
+                target.RemoveFromParent();
+                target.Dispose();
+            }
+            target = null;
+        }
+    }
+}

+ 11 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ButAccountItem2.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 18bf4725a6f581a45aaeb533005c97a8
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 80 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ComAccountInputBox.cs

@@ -0,0 +1,80 @@
+/** This is an automatically generated class by FairyGUI. Please do not modify it. **/
+
+using FairyGUI;
+
+namespace UI.Login
+{
+    public partial class UI_ComAccountInputBox
+    {
+        public GComponent target;
+        public Controller m_c1;
+        public GList m_list;
+        public GButton m_selBtin;
+        public GTextInput m_txtAccount;
+        public const string URL = "ui://myoktu7pk5ej5x";
+        public const string PACKAGE_NAME = "Login";
+        public const string RES_NAME = "ComAccountInputBox";
+        private static UI_ComAccountInputBox _proxy;
+
+        public static UI_ComAccountInputBox Create(GObject gObject = null)
+        {
+            var ui = new UI_ComAccountInputBox();
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static UI_ComAccountInputBox Proxy(GObject gObject = null)
+        {
+            if(_proxy == null)
+            {
+                _proxy = new UI_ComAccountInputBox();
+            }
+            var ui = _proxy;
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static void ProxyEnd()
+        {
+            if (_proxy != null)
+            {
+                _proxy.Dispose();
+            }
+        }
+
+        public static void ClearProxy()
+        {
+            ProxyEnd();
+            _proxy = null;
+        }
+
+        private void Init(GComponent comp)
+        {
+            m_c1 = comp.GetController("c1");
+            m_list = (GList)comp.GetChild("list");
+            m_selBtin = (GButton)comp.GetChild("selBtin");
+            m_txtAccount = (GTextInput)comp.GetChild("txtAccount");
+        }
+        public void Dispose(bool disposeTarget = false)
+        {
+            m_c1 = null;
+            m_list = null;
+            m_selBtin = null;
+            m_txtAccount = null;
+            if(disposeTarget && target != null)
+            {
+                target.RemoveFromParent();
+                target.Dispose();
+            }
+            target = null;
+        }
+    }
+}

+ 11 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ComAccountInputBox.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 291f430b6aaebde4b8328d577dc05525
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 13 - 6
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_LoginInputUI.cs

@@ -8,12 +8,14 @@ namespace UI.Login
     {
         public GComponent target;
         public GComponent m_bg;
-        public GButton m_btnRegister;
-        public GTextInput m_inputAccount;
         public GTextInput m_inputPassword;
         public GButton m_btnCancel;
         public GButton m_btnSure;
         public GComboBox m_boxChooseCanal;
+        public UI_ComAccountInputBox m_comAccount;
+        public GButton m_btnSkipAccount;
+        public GButton m_btnRegister;
+        public GButton m_btnSkipPasword;
         public const string URL = "ui://myoktu7pq08xc";
         public const string PACKAGE_NAME = "Login";
         public const string RES_NAME = "LoginInputUI";
@@ -62,22 +64,27 @@ namespace UI.Login
         private void Init(GComponent comp)
         {
             m_bg = (GComponent)comp.GetChild("bg");
-            m_btnRegister = (GButton)comp.GetChild("btnRegister");
-            m_inputAccount = (GTextInput)comp.GetChild("inputAccount");
             m_inputPassword = (GTextInput)comp.GetChild("inputPassword");
             m_btnCancel = (GButton)comp.GetChild("btnCancel");
             m_btnSure = (GButton)comp.GetChild("btnSure");
             m_boxChooseCanal = (GComboBox)comp.GetChild("boxChooseCanal");
+            m_comAccount = (UI_ComAccountInputBox)UI_ComAccountInputBox.Create(comp.GetChild("comAccount"));
+            m_btnSkipAccount = (GButton)comp.GetChild("btnSkipAccount");
+            m_btnRegister = (GButton)comp.GetChild("btnRegister");
+            m_btnSkipPasword = (GButton)comp.GetChild("btnSkipPasword");
         }
         public void Dispose(bool disposeTarget = false)
         {
             m_bg = null;
-            m_btnRegister = null;
-            m_inputAccount = null;
             m_inputPassword = null;
             m_btnCancel = null;
             m_btnSure = null;
             m_boxChooseCanal = null;
+            m_comAccount.Dispose();
+            m_comAccount = null;
+            m_btnSkipAccount = null;
+            m_btnRegister = null;
+            m_btnSkipPasword = null;
             if(disposeTarget && target != null)
             {
                 target.RemoveFromParent();

+ 9 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_RegisterUI.cs

@@ -19,6 +19,9 @@ namespace UI.Login
         public GLoader m_loaEventa;
         public GLoader m_loaEventb;
         public GLoader m_loaEventc;
+        public GTextInput m_inputPhone;
+        public GButton m_btnSendCode;
+        public GTextInput m_inputCode;
         public const string URL = "ui://myoktu7pq08xn";
         public const string PACKAGE_NAME = "Login";
         public const string RES_NAME = "RegisterUI";
@@ -78,6 +81,9 @@ namespace UI.Login
             m_loaEventa = (GLoader)comp.GetChild("loaEventa");
             m_loaEventb = (GLoader)comp.GetChild("loaEventb");
             m_loaEventc = (GLoader)comp.GetChild("loaEventc");
+            m_inputPhone = (GTextInput)comp.GetChild("inputPhone");
+            m_btnSendCode = (GButton)comp.GetChild("btnSendCode");
+            m_inputCode = (GTextInput)comp.GetChild("inputCode");
         }
         public void Dispose(bool disposeTarget = false)
         {
@@ -93,6 +99,9 @@ namespace UI.Login
             m_loaEventa = null;
             m_loaEventb = null;
             m_loaEventc = null;
+            m_inputPhone = null;
+            m_btnSendCode = null;
+            m_inputCode = null;
             if(disposeTarget && target != null)
             {
                 target.RemoveFromParent();

+ 12 - 3
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_RegisterUIBackup.cs

@@ -10,7 +10,6 @@ namespace UI.Login
         public GComponent m_bg;
         public GButton m_btnSubmit;
         public GButton m_btnAgree;
-        public GRichTextField m_richTextAgree;
         public GButton m_btnSendCode;
         public GTextInput m_inputPhone;
         public GTextInput m_inputCode;
@@ -18,6 +17,10 @@ namespace UI.Login
         public GTextInput m_inputPassword2;
         public GTextInput m_inputIDNumber;
         public GTextInput m_inputName;
+        public GRichTextField m_richTextAgree;
+        public GLoader m_loaEventa;
+        public GLoader m_loaEventb;
+        public GLoader m_loaEventc;
         public const string URL = "ui://myoktu7pu67n12";
         public const string PACKAGE_NAME = "Login";
         public const string RES_NAME = "RegisterUIBackup";
@@ -68,7 +71,6 @@ namespace UI.Login
             m_bg = (GComponent)comp.GetChild("bg");
             m_btnSubmit = (GButton)comp.GetChild("btnSubmit");
             m_btnAgree = (GButton)comp.GetChild("btnAgree");
-            m_richTextAgree = (GRichTextField)comp.GetChild("richTextAgree");
             m_btnSendCode = (GButton)comp.GetChild("btnSendCode");
             m_inputPhone = (GTextInput)comp.GetChild("inputPhone");
             m_inputCode = (GTextInput)comp.GetChild("inputCode");
@@ -76,13 +78,16 @@ namespace UI.Login
             m_inputPassword2 = (GTextInput)comp.GetChild("inputPassword2");
             m_inputIDNumber = (GTextInput)comp.GetChild("inputIDNumber");
             m_inputName = (GTextInput)comp.GetChild("inputName");
+            m_richTextAgree = (GRichTextField)comp.GetChild("richTextAgree");
+            m_loaEventa = (GLoader)comp.GetChild("loaEventa");
+            m_loaEventb = (GLoader)comp.GetChild("loaEventb");
+            m_loaEventc = (GLoader)comp.GetChild("loaEventc");
         }
         public void Dispose(bool disposeTarget = false)
         {
             m_bg = null;
             m_btnSubmit = null;
             m_btnAgree = null;
-            m_richTextAgree = null;
             m_btnSendCode = null;
             m_inputPhone = null;
             m_inputCode = null;
@@ -90,6 +95,10 @@ namespace UI.Login
             m_inputPassword2 = null;
             m_inputIDNumber = null;
             m_inputName = null;
+            m_richTextAgree = null;
+            m_loaEventa = null;
+            m_loaEventb = null;
+            m_loaEventc = null;
             if(disposeTarget && target != null)
             {
                 target.RemoveFromParent();

+ 86 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_UnbindPhoneUI.cs

@@ -0,0 +1,86 @@
+/** This is an automatically generated class by FairyGUI. Please do not modify it. **/
+
+using FairyGUI;
+
+namespace UI.Login
+{
+    public partial class UI_UnbindPhoneUI
+    {
+        public GComponent target;
+        public GComponent m_bg;
+        public GButton m_btnback;
+        public GButton m_btnSendCode;
+        public GTextInput m_txtCode;
+        public GTextField m_txtPhone;
+        public GButton m_btnSubmit;
+        public const string URL = "ui://myoktu7pobd26b";
+        public const string PACKAGE_NAME = "Login";
+        public const string RES_NAME = "UnbindPhoneUI";
+        private static UI_UnbindPhoneUI _proxy;
+
+        public static UI_UnbindPhoneUI Create(GObject gObject = null)
+        {
+            var ui = new UI_UnbindPhoneUI();
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static UI_UnbindPhoneUI Proxy(GObject gObject = null)
+        {
+            if(_proxy == null)
+            {
+                _proxy = new UI_UnbindPhoneUI();
+            }
+            var ui = _proxy;
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static void ProxyEnd()
+        {
+            if (_proxy != null)
+            {
+                _proxy.Dispose();
+            }
+        }
+
+        public static void ClearProxy()
+        {
+            ProxyEnd();
+            _proxy = null;
+        }
+
+        private void Init(GComponent comp)
+        {
+            m_bg = (GComponent)comp.GetChild("bg");
+            m_btnback = (GButton)comp.GetChild("btnback");
+            m_btnSendCode = (GButton)comp.GetChild("btnSendCode");
+            m_txtCode = (GTextInput)comp.GetChild("txtCode");
+            m_txtPhone = (GTextField)comp.GetChild("txtPhone");
+            m_btnSubmit = (GButton)comp.GetChild("btnSubmit");
+        }
+        public void Dispose(bool disposeTarget = false)
+        {
+            m_bg = null;
+            m_btnback = null;
+            m_btnSendCode = null;
+            m_txtCode = null;
+            m_txtPhone = null;
+            m_btnSubmit = null;
+            if(disposeTarget && target != null)
+            {
+                target.RemoveFromParent();
+                target.Dispose();
+            }
+            target = null;
+        }
+    }
+}

+ 11 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_UnbindPhoneUI.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fcba3c1f4f33bbc41ad466f93f8048a0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 86 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ZhaoHuiAccountUI.cs

@@ -0,0 +1,86 @@
+/** This is an automatically generated class by FairyGUI. Please do not modify it. **/
+
+using FairyGUI;
+
+namespace UI.Login
+{
+    public partial class UI_ZhaoHuiAccountUI
+    {
+        public GComponent target;
+        public GComponent m_bg;
+        public GButton m_btnSendCode;
+        public GTextInput m_txtPhone;
+        public GTextInput m_txtCode;
+        public GButton m_btnSubmit;
+        public GList m_comAccountList;
+        public const string URL = "ui://myoktu7pk5ej67";
+        public const string PACKAGE_NAME = "Login";
+        public const string RES_NAME = "ZhaoHuiAccountUI";
+        private static UI_ZhaoHuiAccountUI _proxy;
+
+        public static UI_ZhaoHuiAccountUI Create(GObject gObject = null)
+        {
+            var ui = new UI_ZhaoHuiAccountUI();
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static UI_ZhaoHuiAccountUI Proxy(GObject gObject = null)
+        {
+            if(_proxy == null)
+            {
+                _proxy = new UI_ZhaoHuiAccountUI();
+            }
+            var ui = _proxy;
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static void ProxyEnd()
+        {
+            if (_proxy != null)
+            {
+                _proxy.Dispose();
+            }
+        }
+
+        public static void ClearProxy()
+        {
+            ProxyEnd();
+            _proxy = null;
+        }
+
+        private void Init(GComponent comp)
+        {
+            m_bg = (GComponent)comp.GetChild("bg");
+            m_btnSendCode = (GButton)comp.GetChild("btnSendCode");
+            m_txtPhone = (GTextInput)comp.GetChild("txtPhone");
+            m_txtCode = (GTextInput)comp.GetChild("txtCode");
+            m_btnSubmit = (GButton)comp.GetChild("btnSubmit");
+            m_comAccountList = (GList)comp.GetChild("comAccountList");
+        }
+        public void Dispose(bool disposeTarget = false)
+        {
+            m_bg = null;
+            m_btnSendCode = null;
+            m_txtPhone = null;
+            m_txtCode = null;
+            m_btnSubmit = null;
+            m_comAccountList = null;
+            if(disposeTarget && target != null)
+            {
+                target.RemoveFromParent();
+                target.Dispose();
+            }
+            target = null;
+        }
+    }
+}

+ 11 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ZhaoHuiAccountUI.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 251d692924a621347ade86d3361f421a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 95 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ZhaoHuiPasswordUI.cs

@@ -0,0 +1,95 @@
+/** This is an automatically generated class by FairyGUI. Please do not modify it. **/
+
+using FairyGUI;
+
+namespace UI.Login
+{
+    public partial class UI_ZhaoHuiPasswordUI
+    {
+        public GComponent target;
+        public Controller m_c1;
+        public GComponent m_bg;
+        public GTextInput m_txtPasword;
+        public GTextInput m_txtPaswrod2;
+        public GTextInput m_txtCode;
+        public GButton m_btnSendCode;
+        public GTextInput m_txtPhone;
+        public GTextInput m_txtAccount;
+        public GButton m_btnSubmit;
+        public const string URL = "ui://myoktu7pk5ej69";
+        public const string PACKAGE_NAME = "Login";
+        public const string RES_NAME = "ZhaoHuiPasswordUI";
+        private static UI_ZhaoHuiPasswordUI _proxy;
+
+        public static UI_ZhaoHuiPasswordUI Create(GObject gObject = null)
+        {
+            var ui = new UI_ZhaoHuiPasswordUI();
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static UI_ZhaoHuiPasswordUI Proxy(GObject gObject = null)
+        {
+            if(_proxy == null)
+            {
+                _proxy = new UI_ZhaoHuiPasswordUI();
+            }
+            var ui = _proxy;
+            if(gObject == null)
+            	ui.target =  (GComponent)UIPackage.CreateObject(PACKAGE_NAME, RES_NAME);
+            else
+            	ui.target =  (GComponent)gObject;
+            ui.Init(ui.target);
+            return ui;
+        }
+
+        public static void ProxyEnd()
+        {
+            if (_proxy != null)
+            {
+                _proxy.Dispose();
+            }
+        }
+
+        public static void ClearProxy()
+        {
+            ProxyEnd();
+            _proxy = null;
+        }
+
+        private void Init(GComponent comp)
+        {
+            m_c1 = comp.GetController("c1");
+            m_bg = (GComponent)comp.GetChild("bg");
+            m_txtPasword = (GTextInput)comp.GetChild("txtPasword");
+            m_txtPaswrod2 = (GTextInput)comp.GetChild("txtPaswrod2");
+            m_txtCode = (GTextInput)comp.GetChild("txtCode");
+            m_btnSendCode = (GButton)comp.GetChild("btnSendCode");
+            m_txtPhone = (GTextInput)comp.GetChild("txtPhone");
+            m_txtAccount = (GTextInput)comp.GetChild("txtAccount");
+            m_btnSubmit = (GButton)comp.GetChild("btnSubmit");
+        }
+        public void Dispose(bool disposeTarget = false)
+        {
+            m_c1 = null;
+            m_bg = null;
+            m_txtPasword = null;
+            m_txtPaswrod2 = null;
+            m_txtCode = null;
+            m_btnSendCode = null;
+            m_txtPhone = null;
+            m_txtAccount = null;
+            m_btnSubmit = null;
+            if(disposeTarget && target != null)
+            {
+                target.RemoveFromParent();
+                target.Dispose();
+            }
+            target = null;
+        }
+    }
+}

+ 11 - 0
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/Login/UI_ZhaoHuiPasswordUI.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d43413dee1050d4429e1015e84f93122
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 6 - 15
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/RoleInfo/UI_PhoneBindingUI.cs

@@ -10,14 +10,11 @@ namespace UI.RoleInfo
         public GImage m_bg;
         public GGraph m_holderLeftTop;
         public GGraph m_holderRightDowm;
-        public GTextInput m_inputName;
+        public GTextInput m_txtCode;
         public GTextInput m_inputPhoneNumber;
         public UI_Button19 m_btnSure;
-        public GTextField m_inputConfirmCode;
-        public GButton m_btnGetCode;
-        public GLoader m_countTime;
         public GButton m_btnClose;
-        public GLoader m_icon;
+        public GButton m_btnSendCode;
         public const string URL = "ui://374k3dwvr8a09fze";
         public const string PACKAGE_NAME = "RoleInfo";
         public const string RES_NAME = "PhoneBindingUI";
@@ -68,29 +65,23 @@ namespace UI.RoleInfo
             m_bg = (GImage)comp.GetChild("bg");
             m_holderLeftTop = (GGraph)comp.GetChild("holderLeftTop");
             m_holderRightDowm = (GGraph)comp.GetChild("holderRightDowm");
-            m_inputName = (GTextInput)comp.GetChild("inputName");
+            m_txtCode = (GTextInput)comp.GetChild("txtCode");
             m_inputPhoneNumber = (GTextInput)comp.GetChild("inputPhoneNumber");
             m_btnSure = (UI_Button19)UI_Button19.Create(comp.GetChild("btnSure"));
-            m_inputConfirmCode = (GTextField)comp.GetChild("inputConfirmCode");
-            m_btnGetCode = (GButton)comp.GetChild("btnGetCode");
-            m_countTime = (GLoader)comp.GetChild("countTime");
             m_btnClose = (GButton)comp.GetChild("btnClose");
-            m_icon = (GLoader)comp.GetChild("icon");
+            m_btnSendCode = (GButton)comp.GetChild("btnSendCode");
         }
         public void Dispose(bool disposeTarget = false)
         {
             m_bg = null;
             m_holderLeftTop = null;
             m_holderRightDowm = null;
-            m_inputName = null;
+            m_txtCode = null;
             m_inputPhoneNumber = null;
             m_btnSure.Dispose();
             m_btnSure = null;
-            m_inputConfirmCode = null;
-            m_btnGetCode = null;
-            m_countTime = null;
             m_btnClose = null;
-            m_icon = null;
+            m_btnSendCode = null;
             if(disposeTarget && target != null)
             {
                 target.RemoveFromParent();

+ 6 - 3
GameClient/Assets/Game/HotUpdate/FairyGUI/GenCode/RoleInfo/UI_SettingUI.cs

@@ -13,7 +13,9 @@ namespace UI.RoleInfo
         public GLoader m_icon;
         public GList m_settingTypeList;
         public GButton m_btnExit;
+        public GTextField m_txtPhoneDes;
         public GButton m_btnBinding;
+        public GButton m_btnUnbind;
         public UI_Slider2 m_musicSlider;
         public GButton m_btnMusic;
         public UI_Slider2 m_soundSlider;
@@ -23,7 +25,6 @@ namespace UI.RoleInfo
         public GRichTextField m_gameProtectAgree;
         public GRichTextField m_privacyAgree;
         public GRichTextField m_childrenAgree;
-        public GRichTextField m_txtDeleteAccount;
         public GGroup m_groupAccount;
         public UI_Button19 m_btnLogout;
         public UI_Button20 m_btnGiftCode;
@@ -82,7 +83,9 @@ namespace UI.RoleInfo
             m_icon = (GLoader)comp.GetChild("icon");
             m_settingTypeList = (GList)comp.GetChild("settingTypeList");
             m_btnExit = (GButton)comp.GetChild("btnExit");
+            m_txtPhoneDes = (GTextField)comp.GetChild("txtPhoneDes");
             m_btnBinding = (GButton)comp.GetChild("btnBinding");
+            m_btnUnbind = (GButton)comp.GetChild("btnUnbind");
             m_musicSlider = (UI_Slider2)UI_Slider2.Create(comp.GetChild("musicSlider"));
             m_btnMusic = (GButton)comp.GetChild("btnMusic");
             m_soundSlider = (UI_Slider2)UI_Slider2.Create(comp.GetChild("soundSlider"));
@@ -92,7 +95,6 @@ namespace UI.RoleInfo
             m_gameProtectAgree = (GRichTextField)comp.GetChild("gameProtectAgree");
             m_privacyAgree = (GRichTextField)comp.GetChild("privacyAgree");
             m_childrenAgree = (GRichTextField)comp.GetChild("childrenAgree");
-            m_txtDeleteAccount = (GRichTextField)comp.GetChild("txtDeleteAccount");
             m_groupAccount = (GGroup)comp.GetChild("groupAccount");
             m_btnLogout = (UI_Button19)UI_Button19.Create(comp.GetChild("btnLogout"));
             m_btnGiftCode = (UI_Button20)UI_Button20.Create(comp.GetChild("btnGiftCode"));
@@ -107,7 +109,9 @@ namespace UI.RoleInfo
             m_icon = null;
             m_settingTypeList = null;
             m_btnExit = null;
+            m_txtPhoneDes = null;
             m_btnBinding = null;
+            m_btnUnbind = null;
             m_musicSlider.Dispose();
             m_musicSlider = null;
             m_btnMusic = null;
@@ -120,7 +124,6 @@ namespace UI.RoleInfo
             m_gameProtectAgree = null;
             m_privacyAgree = null;
             m_childrenAgree = null;
-            m_txtDeleteAccount = null;
             m_groupAccount = null;
             m_btnLogout.Dispose();
             m_btnLogout = null;

+ 1 - 1
GameClient/Assets/Game/HotUpdate/GameConfig.cs

@@ -33,7 +33,7 @@ namespace GFGGame
             LoginAddress = result.loginApiUrl;
             //LoginAddress = "43.139.184.240:10003";
             //LoginAddress = "192.168.1.7:10005";//测试地址
-            //LoginAddress = "192.168.1.191:10005";//测试地址
+           //LoginAddress = "192.168.1.191:10005";//测试地址
             showGM = int.Parse(result.showGM);
             if(!string.IsNullOrEmpty(result.openTime))
             {

+ 1 - 20
GameClient/Assets/Game/HotUpdate/ServerProxy/RoleInfoSProxy.cs

@@ -31,6 +31,7 @@ namespace GFGGame
 
                     RoleDataManager.mainBgID = response.MyMainBgId;
                     RoleDataManager.achievementTaskCollect = response.AchievementTaskCollect;
+                    ActivityDataManager.Instance.PhoneNumber = response.Phone;
 
                     return true;
                 }
@@ -311,25 +312,5 @@ namespace GFGGame
             MainDataManager.Instance.CardBgID = 0;
             return true;
         }
-
-        //绑定获取验证码
-        public static async ETTask<bool> GetMobileVerification(string phoneNumber)
-        {
-            S2C_GetMobileVerificationCodeUnit response =
-                (S2C_GetMobileVerificationCodeUnit)await MessageHelper.SendToServer(
-                    new C2S_GetMobileVerificationCodeUnit() { PhoneNumber = phoneNumber });
-
-            return true;
-        }
-
-        //绑定手机
-        public static async ETTask<bool> BindMobilePhoneNumber(string phoneNumber, string code)
-        {
-            S2C_BindMobilePhoneNumber response =
-                (S2C_BindMobilePhoneNumber)await MessageHelper.SendToServer(new C2S_BindMobilePhoneNumber()
-                    { PhoneNumber = phoneNumber, VerCode = code });
-            BonusController.TryShowBonusList(ItemUtil.CreateItemDataList(response.RewardList));
-            return true;
-        }
     }
 }

+ 128 - 8
GameClient/Assets/Game/HotUpdate/Views/Login/LoginInputView.cs

@@ -11,6 +11,8 @@ namespace GFGGame
     {
         private UI_LoginInputUI _ui;
 
+        private List<AccountPasswordModel> _accountPasswordList;
+
         public override void Dispose()
         {
             if (_ui != null)
@@ -18,6 +20,7 @@ namespace GFGGame
                 _ui.Dispose();
                 _ui = null;
             }
+
             base.Dispose();
         }
 
@@ -33,8 +36,13 @@ namespace GFGGame
             _ui.m_btnSure.onClick.Add(OnClickBtnSure);
             _ui.m_btnCancel.onClick.Add(OnClickBtnCancel);
             _ui.m_btnRegister.onClick.Add(OnClickBtnRegister);
+            _ui.m_btnSkipAccount.onClick.Add(OnClickBtnOpenZhAccount);
+            _ui.m_btnSkipPasword.onClick.Add(OnClickBtnOpenZhUpPassword);
+
+            _ui.m_comAccount.m_selBtin.onClick.Add(OnClickOpenAccountListBtn);
+            _ui.m_comAccount.m_txtAccount.restrict = "[0-9A-Za-z_]";
+            _ui.m_comAccount.m_list.itemRenderer = RenderListItem;
 
-            _ui.m_inputAccount.restrict = "[0-9A-Za-z_]";
             if (LauncherConfig.netType == LauncherConfig.EnumNetType.LOCAL)
             {
                 _ui.m_inputPassword.promptText = "[color=#B8A492]当前支持免密登录[/color]";
@@ -46,11 +54,25 @@ namespace GFGGame
         protected override void OnShown()
         {
             base.OnShown();
-            string account = PlayerPrefs.GetString(GameConst.ACCOUNT_LAST_LOGIN_KEY);
+            _accountPasswordList = AccountManager.Instance.GetAccounts();
+            string account = null;
+            string password = null;
+            if (_accountPasswordList != null && _accountPasswordList.Count > 0)
+            {
+                account = _accountPasswordList[0].Account;
+                password = _accountPasswordList[0].Password;
+            }
+
             if (account != null)
             {
-                _ui.m_inputAccount.text = account;
+                _ui.m_comAccount.m_txtAccount.text = account;
             }
+
+            if (password != null)
+            {
+                _ui.m_inputPassword.text = password;
+            }
+
             UpdateChannelBox(false);
         }
 
@@ -72,22 +94,34 @@ namespace GFGGame
             EventAgent.RemoveEventListener(ConstMessage.LOGIN_FAIL, OnLoginFail);
         }
 
+        private void OnClickBtnOpenZhAccount()
+        {
+            ViewManager.Show<ZhaoHuiAccountView>();
+        }
+
+        private void OnClickBtnOpenZhUpPassword(EventContext context)
+        {
+            string account = context.data as string;
+            ViewManager.Show<ZhaoHuiPasswordView>(account);
+        }
+
         private void OnClickBtnSure()
         {
-            var account = _ui.m_inputAccount.text;
+            var account = _ui.m_comAccount.m_txtAccount.text;
             var password = _ui.m_inputPassword.text;
             if (string.IsNullOrEmpty(account))
             {
                 PromptController.Instance.ShowFloatTextPrompt("请输入账号");
                 return;
             }
+
             if (!string.IsNullOrEmpty(password))
             {
                 LoginController.Login(account, password).Coroutine();
             }
             else if (LauncherConfig.netType == LauncherConfig.EnumNetType.LOCAL)
             {
-                LoginController.LoginTest(account).Coroutine();
+                LoginController.Login(account, password).Coroutine();
             }
             else
             {
@@ -105,10 +139,94 @@ namespace GFGGame
             ViewManager.Show<RegisterView>();
         }
 
+        private void OnClickOpenAccountListBtn()
+        {
+            if (_accountPasswordList.Count == 0)
+            {
+                _ui.m_comAccount.m_list.selectedIndex = 0;
+                return;
+            }
+
+            if (_ui.m_comAccount.m_c1.selectedIndex == 0)
+            {
+                //显示账号缓存列表
+                OnShowAccountList();
+            }
+            else
+            {
+                //隐藏账号缓存列表
+                OnHideAccountList();
+            }
+        }
+
+        //显示账号缓存列表
+        private void OnShowAccountList()
+        {
+            _accountPasswordList = AccountManager.Instance.GetAccounts();
+            _ui.m_comAccount.m_list.numItems = _accountPasswordList.Count;
+            _ui.m_comAccount.m_c1.selectedIndex = 1;
+        }
+
+        //隐藏账号缓存列表
+        private void OnHideAccountList()
+        {
+            _ui.m_comAccount.m_c1.selectedIndex = 0;
+        }
+
+        //绑定数据到账号缓存列表
+        private void RenderListItem(int index, GObject obj)
+        {
+            AccountPasswordModel accountPassword = _accountPasswordList[index];
+            UI_ButAccountItem item = UI_ButAccountItem.Proxy(obj);
+            item.m_txtAccountItem.text = accountPassword.Account;
+            item.target.data = accountPassword;
+            item.target.onClick.Add(OnClickSelAccount);
+
+            item.m_btnDel.data = accountPassword.Account;
+            item.m_btnDel.onClick.Add(OnClickDelAccountCache);
+
+            UI_ButAccountItem.ProxyEnd();
+        }
+
+        //从账号缓存列表中选择账号
+        private void OnClickSelAccount(EventContext context)
+        {
+            GObject obj = context.sender as GObject;
+            AccountPasswordModel accountPassword = obj.data as AccountPasswordModel;
+            _ui.m_comAccount.m_txtAccount.text = accountPassword?.Account;
+            _ui.m_inputPassword.text = accountPassword?.Password;
+            OnHideAccountList();
+        }
+
+        //删除账号缓存列表
+        private void OnClickDelAccountCache(EventContext context)
+        {
+            GObject obj = context.sender as GObject;
+            string account = obj.data.ToString();
+            AccountManager.Instance.DeleteAccount(account);
+            _accountPasswordList = AccountManager.Instance.GetAccounts();
+            _ui.m_comAccount.m_list.numItems = _accountPasswordList.Count;
+            if (_accountPasswordList.Count == 0)
+            {
+                _ui.m_comAccount.m_list.selectedIndex = 0;
+            }
+
+            if (_accountPasswordList.Count == 0)
+            {
+                _ui.m_comAccount.m_txtAccount.text = null;
+                _ui.m_inputPassword.text = null;
+            }
+            else
+            {
+                _ui.m_comAccount.m_txtAccount.text = _accountPasswordList[0].Account;
+                _ui.m_inputPassword.text = _accountPasswordList[0].Password;
+            }
+        }
+
         private void OnLoginFail(EventContext context)
         {
             string account = (string)context.data;
-            _ui.m_inputAccount.text = account;
+            _ui.m_comAccount.m_txtAccount.text = account;
         }
 
         private void InitChanelBox()
@@ -131,11 +249,13 @@ namespace GFGGame
 
                 if (fieldInfo != null && Attribute.IsDefined(fieldInfo, typeof(DescriptionAttribute)))
                 {
-                    DescriptionAttribute attribute = (DescriptionAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(DescriptionAttribute));
+                    DescriptionAttribute attribute =
+                        (DescriptionAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(DescriptionAttribute));
                     items.Add(attribute.Description);
                     numbers.Add(Convert.ToInt32(value).ToString());
                 }
             }
+
             _ui.m_boxChooseCanal.items = items.ToArray();
             _ui.m_boxChooseCanal.values = numbers.ToArray();
             _ui.m_boxChooseCanal.value = LauncherConfig.ChannelId + "";
@@ -163,8 +283,8 @@ namespace GFGGame
             {
                 GameConfig.LoginAddress = "http://10.108.64.127:10005";
             }
+
             ET.Log.Debug($"===选择的渠道=== {_ui.m_boxChooseCanal.value} {GameConfig.LoginAddress}");
         }
-
     }
 }

+ 38 - 17
GameClient/Assets/Game/HotUpdate/Views/Login/RegisterView.cs

@@ -1,3 +1,5 @@
+using System.Text.RegularExpressions;
+using ET;
 using UI.Login;
 using UnityEngine;
 using FairyGUI;
@@ -8,8 +10,6 @@ namespace GFGGame
     {
         private UI_RegisterUI _ui;
 
-        private const string CODE = "";
-
         public override void Dispose()
         {
             if (_ui != null)
@@ -17,6 +17,7 @@ namespace GFGGame
                 _ui.Dispose();
                 _ui = null;
             }
+
             base.Dispose();
         }
 
@@ -34,14 +35,25 @@ namespace GFGGame
             _ui.m_loaEventa.onClick.Add(() => { FullScreenTextController.Show("event:a"); });
             _ui.m_loaEventb.onClick.Add(() => { FullScreenTextController.Show("event:b"); });
             _ui.m_loaEventc.onClick.Add(() => { FullScreenTextController.Show("event:c"); });
-            // _ui.m_btnSendCode.onClick.Add(() => {
-            //     
-            //     _ui.m_btnSendCode.enabled = false;
-            //     _ui.m_inputCode.text = CODE;
-            //     float endTime = Time.time + 60;
-            //     Timers.inst.Add(1,0, timerCallback, endTime);
-            //     timerCallback(endTime);
-            // });
+            _ui.m_btnSendCode.onClick.Add(() =>
+            {
+                if (!Regex.IsMatch(_ui.m_inputPhone.text.Trim(), // 匹配所有中国大陆手机号(11 位,包括物联网和卫星电话)
+                        @"^(?:\+86)?1(?:3\d{3}|4[5-9]\d{2}|5[0-35-9]\d{2}|6[2567]\d{2}|7[0-8]\d{2}|8\d{3}|9[0-35-9]\d{2})\d{6}$"))
+                {
+                    PromptController.Instance.ShowFloatTextPrompt("输入的手机号格式有误");
+                    return;
+                }
+
+                _ui.m_btnSendCode.enabled = false;
+
+                //在此发送验证码
+                SecurityHelper.GetMobileVerificationCode(_ui.m_inputPhone.text, SendCodeType.RegisterAccount)
+                    .Coroutine();
+
+                float endTime = Time.time + 60;
+                Timers.inst.Add(1, 0, timerCallback, endTime);
+                timerCallback(endTime);
+            });
 
             //输入限制
             _ui.m_inputAccount.restrict = "[0-9A-Za-z_]";
@@ -56,13 +68,13 @@ namespace GFGGame
             float remainTime = endTime - Time.time;
             if (remainTime <= 0)
             {
-                // _ui.m_btnSendCode.text = "发送验证码";
-                // _ui.m_btnSendCode.enabled = true;
+                _ui.m_btnSendCode.text = "发送验证码";
+                _ui.m_btnSendCode.enabled = true;
                 Timers.inst.Remove(timerCallback);
             }
             else
             {
-                // _ui.m_btnSendCode.text = (int)remainTime + "s后重发";
+                _ui.m_btnSendCode.text = (int)remainTime + "s后重发";
             }
         }
 
@@ -75,6 +87,7 @@ namespace GFGGame
         protected override void OnHide()
         {
             base.OnHide();
+            Timers.inst.Remove(timerCallback);
         }
 
         private void OnClickBtnSubmit()
@@ -89,31 +102,38 @@ namespace GFGGame
             string passwordSure = _ui.m_inputPassword2.text;
             string realName = _ui.m_inputName.text;
             string idNumberStr = _ui.m_inputIDNumber.text;
+            string phoneNumber = _ui.m_inputPhone.text;
+            string code = _ui.m_inputCode.text;
             if (string.IsNullOrEmpty(account))
             {
                 PromptController.Instance.ShowFloatTextPrompt("请输入账号");
                 return;
             }
-            if(account.Length < 8)//最长输入在UI编辑器中做了限制
+
+            if (account.Length < 8) //最长输入在UI编辑器中做了限制
             {
                 PromptController.Instance.ShowFloatTextPrompt("账号长度最少需要8位");
                 return;
             }
+
             if (string.IsNullOrEmpty(password))
             {
                 PromptController.Instance.ShowFloatTextPrompt("请输入密码");
                 return;
             }
-            if (password.Length < 8)//最长输入在UI编辑器中做了限制
+
+            if (password.Length < 8) //最长输入在UI编辑器中做了限制
             {
                 PromptController.Instance.ShowFloatTextPrompt("密码长度最少需要8位");
                 return;
             }
+
             if (passwordSure != password)
             {
                 PromptController.Instance.ShowFloatTextPrompt("确认密码不一致");
                 return;
             }
+
             GameController.CheckSpecialAccount(account);
             if (GameGlobal.antiAddiction)
             {
@@ -122,11 +142,13 @@ namespace GFGGame
                     PromptController.Instance.ShowFloatTextPrompt("请输入真实姓名");
                     return;
                 }
+
                 if (idNumberStr.Length <= 0)
                 {
                     PromptController.Instance.ShowFloatTextPrompt("请输入身份证号");
                     return;
                 }
+
                 if (!_ui.m_btnAgree.selected)
                 {
                     PromptController.Instance.ShowFloatTextPrompt("请仔细阅读并同意服务协议、隐私政策、保护规则");
@@ -134,8 +156,7 @@ namespace GFGGame
                 }
             }
 
-            LoginController.Register(account, password, realName, idNumberStr, CODE).Coroutine();
+            LoginController.Register(account, password, realName, idNumberStr, code, phoneNumber).Coroutine();
         }
-
     }
 }

+ 163 - 0
GameClient/Assets/Game/HotUpdate/Views/Login/ZhaoHuiAccountView.cs

@@ -0,0 +1,163 @@
+using UI.Login;
+using FairyGUI;
+using UnityEngine;
+using System.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using ET;
+
+namespace GFGGame
+{
+    public class ZhaoHuiAccountView : BaseWindow
+    {
+        private UI_ZhaoHuiAccountUI _ui;
+        private List<AccountDataProto> _accountDataProtoList;
+
+        public override void Dispose()
+        {
+            if (_ui != null)
+            {
+                _ui.Dispose();
+                _ui = null;
+            }
+
+            base.Dispose();
+        }
+
+        protected override void OnInit()
+        {
+            base.OnInit();
+            packageName = UI_ZhaoHuiAccountUI.PACKAGE_NAME;
+            _ui = UI_ZhaoHuiAccountUI.Create();
+            this.viewCom = _ui.target;
+            this.viewCom.Center();
+            this.modal = true;
+
+            _ui.m_btnSendCode.onClick.Add(() =>
+            {
+                if (!Regex.IsMatch(_ui.m_txtPhone.text.Trim(), // 匹配所有中国大陆手机号(11 位,包括物联网和卫星电话)
+                        @"^(?:\+86)?1(?:3\d{3}|4[5-9]\d{2}|5[0-35-9]\d{2}|6[2567]\d{2}|7[0-8]\d{2}|8\d{3}|9[0-35-9]\d{2})\d{6}$"))
+                {
+                    PromptController.Instance.ShowFloatTextPrompt("输入的手机号格式有误");
+                    return;
+                }
+
+                _ui.m_btnSendCode.enabled = false;
+
+                //在此发送验证码
+                SecurityHelper.GetMobileVerificationCode(_ui.m_txtPhone.text, SendCodeType.AccountRecovery)
+                    .Coroutine();
+
+                float endTime = Time.time + 60;
+                Timers.inst.Add(1, 0, timerCallback, endTime);
+                timerCallback(endTime);
+            });
+
+            _ui.m_comAccountList.itemRenderer = RenderListItem;
+
+            _ui.m_btnSubmit.onClick.Add(OnClickBtnSubmit);
+        }
+
+        private async void OnClickBtnSubmit()
+        {
+            if (!Regex.IsMatch(_ui.m_txtPhone.text.Trim(), // 匹配所有中国大陆手机号(11 位,包括物联网和卫星电话)
+                    @"^(?:\+86)?1(?:3\d{3}|4[5-9]\d{2}|5[0-35-9]\d{2}|6[2567]\d{2}|7[0-8]\d{2}|8\d{3}|9[0-35-9]\d{2})\d{6}$"))
+            {
+                PromptController.Instance.ShowFloatTextPrompt("输入的手机号格式有误");
+                return;
+            }
+
+            A2C_GetAccountListByPhone res = await SecurityHelper.GetAccountListByPhone(_ui.m_txtCode.text,
+                _ui.m_txtPhone.text);
+            if (res is { Error: ErrorCode.ERR_Success })
+            {
+                _accountDataProtoList = new List<AccountDataProto>();
+                //查询数据成功
+                foreach (var accountDataProto in res.AccountDataList)
+                {
+                    _accountDataProtoList.Add(accountDataProto);
+                }
+
+                if (_accountDataProtoList.Count == 0)
+                {
+                    PromptController.Instance.ShowFloatTextPrompt("查询不到该手机号绑定的账号");
+                }
+
+                _ui.m_comAccountList.numItems = _accountDataProtoList.Count;
+                if (_accountDataProtoList.Count > 0)
+                {
+                    _ui.m_comAccountList.selectedIndex = 1;
+                }
+            }
+            else
+            {
+                ErrorCodeController.Handler(res.Error);
+            }
+        }
+
+        private void RenderListItem(int index, GObject obj)
+        {
+            AccountDataProto accountPassword = _accountDataProtoList[index];
+            UI_ButAccountItem2 item = UI_ButAccountItem2.Proxy(obj);
+            item.m_txtAccountItem.text = accountPassword.Account;
+            item.m_btnPaswordUp.data = accountPassword;
+            item.m_btnPaswordUp.onClick.Add(OnClickAccountItem);
+            UI_ButAccountItem2.ProxyEnd();
+        }
+
+        private void OnClickAccountItem(EventContext context)
+        {
+            GObject obj = context.sender as GObject;
+            AccountDataProto accountPassword = obj.data as AccountDataProto;
+            if (accountPassword == null)
+            {
+                ViewManager.Show<ZhaoHuiPasswordView>();
+                Hide();
+            }
+            else
+            {
+                ViewManager.Show<ZhaoHuiPasswordView>(accountPassword.Account);
+                Hide();
+            }
+        }
+
+        private void timerCallback(object param)
+        {
+            float endTime = (float)param;
+            float remainTime = endTime - Time.time;
+            if (remainTime <= 0)
+            {
+                _ui.m_btnSendCode.text = "发送验证码";
+                _ui.m_btnSendCode.enabled = true;
+                Timers.inst.Remove(timerCallback);
+            }
+            else
+            {
+                _ui.m_btnSendCode.text = (int)remainTime + "s后重发";
+            }
+        }
+
+        protected override void OnShown()
+        {
+            base.OnShown();
+            //
+        }
+
+        protected override void OnHide()
+        {
+            base.OnHide();
+            Timers.inst.Remove(timerCallback);
+        }
+
+        protected override void AddEventListener()
+        {
+            base.AddEventListener();
+        }
+
+        protected override void RemoveEventListener()
+        {
+            base.RemoveEventListener();
+        }
+    }
+}

+ 3 - 0
GameClient/Assets/Game/HotUpdate/Views/Login/ZhaoHuiAccountView.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: c90b54f22dfd4114a67f03fdb2b4ec69
+timeCreated: 1760974293

+ 134 - 0
GameClient/Assets/Game/HotUpdate/Views/Login/ZhaoHuiPasswordView.cs

@@ -0,0 +1,134 @@
+using UI.Login;
+using FairyGUI;
+using UnityEngine;
+using System.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using ET;
+
+namespace GFGGame
+{
+    public class ZhaoHuiPasswordView : BaseWindow
+    {
+        private UI_ZhaoHuiPasswordUI _ui;
+
+        public override void Dispose()
+        {
+            if (_ui != null)
+            {
+                _ui.Dispose();
+                _ui = null;
+            }
+
+            base.Dispose();
+        }
+
+        protected override void OnInit()
+        {
+            base.OnInit();
+            packageName = UI_ZhaoHuiPasswordUI.PACKAGE_NAME;
+            _ui = UI_ZhaoHuiPasswordUI.Create();
+            this.viewCom = _ui.target;
+            this.viewCom.Center();
+            this.modal = true;
+
+            _ui.m_btnSendCode.onClick.Add(() =>
+            {
+                if (!Regex.IsMatch(_ui.m_txtPhone.text.Trim(), // 匹配所有中国大陆手机号(11 位,包括物联网和卫星电话)
+                        @"^(?:\+86)?1(?:3\d{3}|4[5-9]\d{2}|5[0-35-9]\d{2}|6[2567]\d{2}|7[0-8]\d{2}|8\d{3}|9[0-35-9]\d{2})\d{6}$"))
+                {
+                    PromptController.Instance.ShowFloatTextPrompt("输入的手机号格式有误");
+                    return;
+                }
+
+                _ui.m_btnSendCode.enabled = false;
+
+                //在此发送验证码
+                SecurityHelper.GetMobileVerificationCode(_ui.m_txtPhone.text, SendCodeType.ChangePassword)
+                    .Coroutine();
+
+                float endTime = Time.time + 60;
+                Timers.inst.Add(1, 0, timerCallback, endTime);
+                timerCallback(endTime);
+            });
+
+            _ui.m_btnSubmit.onClick.Add(OnClickBtnSubmit);
+        }
+
+        private async void OnClickBtnSubmit()
+        {
+            if (!Regex.IsMatch(_ui.m_txtPhone.text.Trim(), // 匹配所有中国大陆手机号(11 位,包括物联网和卫星电话)
+                    @"^(?:\+86)?1(?:3\d{3}|4[5-9]\d{2}|5[0-35-9]\d{2}|6[2567]\d{2}|7[0-8]\d{2}|8\d{3}|9[0-35-9]\d{2})\d{6}$"))
+            {
+                PromptController.Instance.ShowFloatTextPrompt("输入的手机号格式有误");
+                return;
+            }
+
+            string code = _ui.m_txtCode.text.Trim();
+            string phoneNumber = _ui.m_txtPhone.text.Trim();
+            string account = _ui.m_txtAccount.text.Trim();
+            string password = _ui.m_txtPasword.text.Trim();
+            string password2 = _ui.m_txtPaswrod2.text.Trim();
+            if (password != password2)
+            {
+                PromptController.Instance.ShowFloatTextPrompt("两次输入的密码不一致");
+            }
+
+            A2C_UpPassword res = await SecurityHelper.UpPassword(code, phoneNumber, account, password);
+            if (res is { Error: ErrorCode.ERR_Success })
+            {
+                LoginController.Login(account, password).Coroutine();
+                Hide();
+            }
+            else
+            {
+                ErrorCodeController.Handler(res.Error);
+            }
+        }
+
+
+        private void timerCallback(object param)
+        {
+            float endTime = (float)param;
+            float remainTime = endTime - Time.time;
+            if (remainTime <= 0)
+            {
+                _ui.m_btnSendCode.text = "发送验证码";
+                _ui.m_btnSendCode.enabled = true;
+                Timers.inst.Remove(timerCallback);
+            }
+            else
+            {
+                _ui.m_btnSendCode.text = (int)remainTime + "s后重发";
+            }
+        }
+
+        protected override void OnShown()
+        {
+            base.OnShown();
+            _ui.m_txtAccount.editable = true;
+            if (viewData != null)
+            {
+                _ui.m_txtAccount.text = (string)viewData;
+                _ui.m_txtAccount.editable = false;
+            }
+        }
+
+        protected override void OnHide()
+        {
+            base.OnHide();
+            Timers.inst.Remove(timerCallback);
+        }
+
+        protected override void AddEventListener()
+        {
+            base.AddEventListener();
+        }
+
+        protected override void RemoveEventListener()
+        {
+            base.RemoveEventListener();
+        }
+    }
+}

+ 3 - 0
GameClient/Assets/Game/HotUpdate/Views/Login/ZhaoHuiPasswordView.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 211594f56dc647d8a44edaab939abe47
+timeCreated: 1760974305

+ 54 - 50
GameClient/Assets/Game/HotUpdate/Views/RoleInfo/PhoneBindingView.cs

@@ -1,4 +1,6 @@
 using System.Collections;
+using System.Text.RegularExpressions;
+using ET;
 using UnityEngine;
 using UI.RoleInfo;
 using FairyGUI;
@@ -7,7 +9,6 @@ namespace GFGGame
 {
     public class PhoneBindingView : BaseWindow
     {
-
         private UI_PhoneBindingUI _ui;
         private float countTimeSpeed = 0.000035f;
         private bool isCountTime = false;
@@ -26,6 +27,7 @@ namespace GFGGame
                 _ui.Dispose();
                 _ui = null;
             }
+
             base.Dispose();
         }
 
@@ -40,81 +42,83 @@ namespace GFGGame
             viewAnimationType = EnumViewAnimationType.ZOOM_CENTER;
 
             _ui.m_btnSure.target.onClick.Add(OnBtnSureClick);
-            _ui.m_icon.url = ResPathUtil.GetIconPath(ItemCfgArray.Instance.GetCfg(ConstItemID.DIAMOND_RED));
-            _ui.m_btnGetCode.onClick.Add(OnBtnGetCode);
             _ui.m_btnClose.onClick.Add(Hide);
 
+            _ui.m_btnSendCode.onClick.Add(() =>
+            {
+                if (!Regex.IsMatch(_ui.m_inputPhoneNumber.text.Trim(), // 匹配所有中国大陆手机号(11 位,包括物联网和卫星电话)
+                        @"^(?:\+86)?1(?:3\d{3}|4[5-9]\d{2}|5[0-35-9]\d{2}|6[2567]\d{2}|7[0-8]\d{2}|8\d{3}|9[0-35-9]\d{2})\d{6}$"))
+                {
+                    PromptController.Instance.ShowFloatTextPrompt("输入的手机号格式有误");
+                    return;
+                }
+
+                _ui.m_btnSendCode.enabled = false;
+
+                //在此发送验证码
+                SecurityHelper.GetMobileVerification(_ui.m_inputPhoneNumber.text, SendCodeType.BindPhone)
+                    .Coroutine();
+
+                float endTime = Time.time + 60;
+                Timers.inst.Add(1, 0, timerCallback, endTime);
+                timerCallback(endTime);
+            });
+
             AddEffect();
         }
 
+        private void timerCallback(object param)
+        {
+            float endTime = (float)param;
+            float remainTime = endTime - Time.time;
+            if (remainTime <= 0)
+            {
+                _ui.m_btnSendCode.text = "发送验证码";
+                _ui.m_btnSendCode.enabled = true;
+
+                Timers.inst.Remove(timerCallback);
+            }
+            else
+            {
+                _ui.m_btnSendCode.text = (int)remainTime + "s后重发";
+            }
+        }
+
         protected override void OnShown()
         {
             base.OnShown();
             _ui.m_inputPhoneNumber.text = "";
-            _ui.m_inputName.text = "";
+            _ui.m_txtCode.text = "";
             isCountTime = false;
-            _ui.m_countTime.visible = false;
         }
 
         protected override void OnHide()
         {
             base.OnHide();
-            Timers.inst.Remove(UpdateCountTime);
-        }
-        private void UpdateCountTime(object param = null)
-        {
-            if (_ui.m_countTime.fillAmount <= 0)
-            {
-                _ui.m_countTime.fillAmount = 0;
-                _ui.m_countTime.visible = false;
-                isCountTime = false;
-                Timers.inst.Remove(UpdateCountTime);
-            }
-            _ui.m_countTime.fillAmount -= countTimeSpeed;
+            Timers.inst.Remove(timerCallback);
         }
+
         private async void OnBtnSureClick()
         {
-            if(ActivityDataManager.Instance.PhoneNum != null && ActivityDataManager.Instance.PhoneNum != "")
+            if (!string.IsNullOrEmpty(ActivityDataManager.Instance.PhoneNumber))
             {
-                PromptController.Instance.ShowFloatTextPrompt(string.Format("号码{0}已绑定!", ActivityDataManager.Instance.PhoneNum));
+                PromptController.Instance.ShowFloatTextPrompt(string.Format("号码{0}已绑定!",
+                    ActivityDataManager.Instance.PhoneNumber));
                 Hide();
             }
-            bool result = await RoleInfoSProxy.BindMobilePhoneNumber(_ui.m_inputPhoneNumber.text ,_ui.m_inputName.text);
-            if(result)
-            {
-                //PromptController.Instance.ShowFloatTextPrompt("绑定成功!");
-                //Hide();
-            }
-            else
-            {
-                //PromptController.Instance.ShowFloatTextPrompt("绑定失败!");
-            }   
-        }
 
-        private  async void OnBtnGetCode()
-        {
-            if (_ui.m_inputPhoneNumber.text == null || _ui.m_inputPhoneNumber.text == "")
-            {
-                PromptController.Instance.ShowFloatTextPrompt("麻烦输入手机号码!");
-                return;
-            }
-            if (isCountTime)
-            {
-                PromptController.Instance.ShowFloatTextPrompt("刷新冷却中,请耐心等待!");
-                return;
-            }
-            isCountTime = true;
-            _ui.m_countTime.visible = true;
-            _ui.m_countTime.fillAmount = 1.0f;
-            Timers.inst.AddUpdate(UpdateCountTime);
-            bool result = await RoleInfoSProxy.GetMobileVerification(_ui.m_inputPhoneNumber.text);
-            if (result)
+            S2C_BindMobilePhoneNumber res =
+                await SecurityHelper.BindMobilePhoneNumber(_ui.m_inputPhoneNumber.text, _ui.m_txtCode.text);
+            if (res is { Error: ErrorCode.ERR_Success })
             {
-                //PromptController.Instance.ShowFloatTextPrompt("获取成功!");
+                PromptController.Instance.ShowFloatTextPrompt("绑定成功!");
+                ActivityDataManager.Instance.PhoneNumber = res.PhoneNumber;
+                Hide();
+                EventAgent.DispatchEvent(ConstMessage.PhoneChange);
             }
             else
             {
-                //PromptController.Instance.ShowFloatTextPrompt("获取失败!麻烦输入正确的手机号码!");
+                ErrorCodeController.Handler(res.Error);
             }
         }
 

+ 63 - 18
GameClient/Assets/Game/HotUpdate/Views/RoleInfo/SettingView.cs

@@ -9,12 +9,10 @@ namespace GFGGame
         private EffectUI _effectUI1;
         private EffectUI _effectUI2;
         private static bool _refresh;
+
         public static bool refresh
         {
-            set
-            {
-                _refresh = value;
-            }
+            set { _refresh = value; }
         }
 
 
@@ -30,6 +28,7 @@ namespace GFGGame
                 _ui.Dispose();
                 _ui = null;
             }
+
             base.Dispose();
         }
 
@@ -53,14 +52,21 @@ namespace GFGGame
             _ui.m_voiceSlider.target.onChanged.Add(OnChangeVoiceVolumn);
             _ui.m_musicSlider.target.onChanged.Add(OnChangeMusicVolumn);
             _ui.m_soundSlider.target.onChanged.Add(OnChangeSoundVolumn);
-            _ui.m_btnBinding.onClick.Add(OnClickPhoneBinding);
+
             _ui.m_btnGiftCode.target.onClick.Add(OnClickGiftCode);
             _ui.m_settingTypeList.itemRenderer = RenderListType;
             _ui.m_settingTypeList.numItems = _ui.m_settingTypeList.numItems;
             _ui.m_gameProtectAgree.onClick.Add(OnGameProtectAgreeClick);
             _ui.m_privacyAgree.onClick.Add(OnPrivacyAgreeClick);
             _ui.m_childrenAgree.onClick.Add(OnChildrenAgreeClick);
-            _ui.m_txtDeleteAccount.onClick.Add(OnClickTxtDeleteAccount);
+
+            _ui.m_btnBinding.onClick.Add(OnClickPhoneBinding);
+            _ui.m_btnBinding.text = "点击绑定";
+            _ui.m_btnBinding.visible = false;
+
+            _ui.m_btnUnbind.onClick.Add(OnClickPhoneUnbind);
+            _ui.m_btnUnbind.text = "解绑";
+            _ui.m_btnUnbind.visible = false;
 
             _ui.m_groupAccount.visible = GameConfig.tsStatus > 0;
         }
@@ -75,10 +81,25 @@ namespace GFGGame
                 _ui.m_suit.Play();
                 _ui.m_c1.SetSelectedIndex(0);
             }
+
             _ui.m_icon.visible = false;
             _ui.m_iconBg.visible = false;
             _ui.m_settingTypeList.visible = false;
             _ui.m_btnGiftCode.target.visible = GameConfig.hCode == 0;
+
+            if (!string.IsNullOrEmpty(ActivityDataManager.Instance.PhoneNumber))
+            {
+                //已经绑定, 需要解绑
+                _ui.m_txtPhoneDes.text = ActivityDataManager.Instance.PhoneNumber;
+                _ui.m_btnBinding.visible = false;
+                _ui.m_btnUnbind.visible = true;
+            }
+            else
+            {
+                _ui.m_txtPhoneDes.text = "手机号绑定";
+                _ui.m_btnBinding.visible = true;
+                _ui.m_btnUnbind.visible = false;
+            }
         }
 
         protected override void OnHide()
@@ -86,25 +107,45 @@ namespace GFGGame
             base.OnHide();
         }
 
+        protected override void AddEventListener()
+        {
+            base.AddEventListener();
+            EventAgent.AddEventListener(ConstMessage.PhoneChange, OnPhoneChange);
+        }
+
+        protected override void RemoveEventListener()
+        {
+            base.RemoveEventListener();
+            EventAgent.RemoveEventListener(ConstMessage.PhoneChange, OnPhoneChange);
+        }
+
+        private void OnPhoneChange()
+        {
+            if (!string.IsNullOrEmpty(ActivityDataManager.Instance.PhoneNumber))
+            {
+                //已经绑定, 需要解绑
+                _ui.m_txtPhoneDes.text = ActivityDataManager.Instance.PhoneNumber;
+                _ui.m_btnBinding.visible = false;
+                _ui.m_btnUnbind.visible = true;
+            }
+            else
+            {
+                _ui.m_txtPhoneDes.text = "手机号绑定";
+                _ui.m_btnBinding.visible = true;
+                _ui.m_btnUnbind.visible = false;
+            }
+        }
+
         private void OnClickBtnBack()
         {
             Hide();
-            //AlertSystem.Show("确认返回登录页吗?")
-            //    .SetLeftButton(true)
-            //    .SetRightButton(true, "确认", (object data) =>
-            //    {
-            //        GameController.QuitToLoginView(false);
-            //    });
         }
 
         private void OnClickBtnLogout()
         {
             AlertSystem.Show("确认注销当前账号吗?")
                 .SetLeftButton(true)
-                .SetRightButton(true, "确认", (object data) =>
-                {
-                    GameController.QuitToLoginView(true);
-                });
+                .SetRightButton(true, "确认", (object data) => { GameController.QuitToLoginView(true); });
         }
 
         private void OnClickBtnSound()
@@ -198,7 +239,12 @@ namespace GFGGame
 
         private void OnClickPhoneBinding()
         {
-            ViewManager.Show<PhoneBindingView>(); 
+            ViewManager.Show<PhoneBindingView>();
+        }
+
+        private void OnClickPhoneUnbind()
+        {
+            ViewManager.Show<UnbindPhoneView>();
         }
 
         private void OnClickGiftCode()
@@ -237,6 +283,5 @@ namespace GFGGame
         {
             ViewManager.Show<DeleteAccountView>();
         }
-
     }
 }

+ 123 - 0
GameClient/Assets/Game/HotUpdate/Views/RoleInfo/UnbindPhoneView.cs

@@ -0,0 +1,123 @@
+using UI.Login;
+using FairyGUI;
+using UnityEngine;
+using System.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using ET;
+
+namespace GFGGame
+{
+    public class UnbindPhoneView : BaseWindow
+    {
+        private UI_UnbindPhoneUI _ui;
+
+        public override void Dispose()
+        {
+            if (_ui != null)
+            {
+                _ui.Dispose();
+                _ui = null;
+            }
+
+            base.Dispose();
+        }
+
+        protected override void OnInit()
+        {
+            base.OnInit();
+            packageName = UI_UnbindPhoneUI.PACKAGE_NAME;
+            _ui = UI_UnbindPhoneUI.Create();
+            this.viewCom = _ui.target;
+            this.viewCom.Center();
+            this.modal = true;
+
+            _ui.m_btnSendCode.onClick.Add(() =>
+            {
+                if (!Regex.IsMatch(_ui.m_txtPhone.text.Trim(), // 匹配所有中国大陆手机号(11 位,包括物联网和卫星电话)
+                        @"^(?:\+86)?1(?:3\d{3}|4[5-9]\d{2}|5[0-35-9]\d{2}|6[2567]\d{2}|7[0-8]\d{2}|8\d{3}|9[0-35-9]\d{2})\d{6}$"))
+                {
+                    PromptController.Instance.ShowFloatTextPrompt("输入的手机号格式有误");
+                    return;
+                }
+
+                _ui.m_btnSendCode.enabled = false;
+
+                //在此发送验证码
+                SecurityHelper.GetMobileVerification(_ui.m_txtPhone.text, SendCodeType.UnbindPhone)
+                    .Coroutine();
+
+                float endTime = Time.time + 60;
+                Timers.inst.Add(1, 0, timerCallback, endTime);
+                timerCallback(endTime);
+            });
+
+            _ui.m_btnSubmit.onClick.Add(OnClickBtnSubmit);
+        }
+
+        private async void OnClickBtnSubmit()
+        {
+            if (!Regex.IsMatch(_ui.m_txtPhone.text.Trim(), // 匹配所有中国大陆手机号(11 位,包括物联网和卫星电话)
+                    @"^(?:\+86)?1(?:3\d{3}|4[5-9]\d{2}|5[0-35-9]\d{2}|6[2567]\d{2}|7[0-8]\d{2}|8\d{3}|9[0-35-9]\d{2})\d{6}$"))
+            {
+                PromptController.Instance.ShowFloatTextPrompt("输入的手机号格式有误");
+                return;
+            }
+
+            string code = _ui.m_txtCode.text.Trim();
+            string phoneNumber = _ui.m_txtPhone.text.Trim();
+
+            S2C_UnbindMobilePhoneNumber res = await SecurityHelper.UnbindMobilePhoneNumber(phoneNumber, code);
+            if (res is { Error: ErrorCode.ERR_Success })
+            {
+                ActivityDataManager.Instance.PhoneNumber = res.PhoneNumber;
+                Hide();
+                EventAgent.DispatchEvent(ConstMessage.PhoneChange);
+            }
+            else
+            {
+                ErrorCodeController.Handler(res.Error);
+            }
+        }
+
+        private void timerCallback(object param)
+        {
+            float endTime = (float)param;
+            float remainTime = endTime - Time.time;
+            if (remainTime <= 0)
+            {
+                _ui.m_btnSendCode.text = "发送验证码";
+                _ui.m_btnSendCode.enabled = true;
+
+                Timers.inst.Remove(timerCallback);
+            }
+            else
+            {
+                _ui.m_btnSendCode.text = (int)remainTime + "s后重发";
+            }
+        }
+
+        protected override void OnShown()
+        {
+            base.OnShown();
+            _ui.m_txtPhone.text = ActivityDataManager.Instance.PhoneNumber;
+        }
+
+        protected override void OnHide()
+        {
+            base.OnHide();
+            Timers.inst.Remove(timerCallback);
+        }
+
+        protected override void AddEventListener()
+        {
+            base.AddEventListener();
+        }
+
+        protected override void RemoveEventListener()
+        {
+            base.RemoveEventListener();
+        }
+    }
+}

+ 3 - 0
GameClient/Assets/Game/HotUpdate/Views/RoleInfo/UnbindPhoneView.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: d8dfc45135a444eca110b5c89280a228
+timeCreated: 1761148397

+ 6 - 17
GameClient/Assets/Game/HotUpdate/Views/RoleInfoRegister/RoleInfoRegisterView.cs

@@ -54,17 +54,6 @@ namespace GFGGame
             CheckToSubmit();
         }
 
-        private async void OnBtnGetCode()
-        {
-            if (_ui.m_inputPhone.text == null || _ui.m_inputPhone.text == "")
-            {
-                PromptController.Instance.ShowFloatTextPrompt("麻烦输入手机号码!");
-                return;
-            }
-
-            bool result = await RoleInfoSProxy.GetMobileVerification(_ui.m_inputPhone.text);
-        }
-
         private void CheckToSubmit()
         {
             //账号
@@ -86,31 +75,31 @@ namespace GFGGame
                 PromptController.Instance.ShowFloatTextPrompt("请输入账号");
                 return;
             }
-            
+
             // if (string.IsNullOrEmpty(code))
             // {
             //     PromptController.Instance.ShowFloatTextPrompt("请输入验证码");
             //     return;
             // }
-            
+
             if (account.Length < 6) //最长输入在UI编辑器中做了限制
             {
                 PromptController.Instance.ShowFloatTextPrompt("账号长度最少需要6位");
                 return;
             }
-            
+
             if (string.IsNullOrEmpty(password))
             {
                 PromptController.Instance.ShowFloatTextPrompt("请输入密码");
                 return;
             }
-            
+
             if (password.Length < 6) //最长输入在UI编辑器中做了限制
             {
                 PromptController.Instance.ShowFloatTextPrompt("密码长度最少需要5位");
                 return;
             }
-            
+
             if (passwordSure != password)
             {
                 PromptController.Instance.ShowFloatTextPrompt("确认密码不一致");
@@ -125,7 +114,7 @@ namespace GFGGame
                     PromptController.Instance.ShowFloatTextPrompt("请输入真实姓名");
                     return;
                 }
-            
+
                 if (idNumberStr.Length <= 0)
                 {
                     PromptController.Instance.ShowFloatTextPrompt("请输入身份证号");

BIN
GameClient/Assets/ResIn/UI/Login/Login_atlas0!a.png


BIN
GameClient/Assets/ResIn/UI/Login/Login_atlas0.png


BIN
GameClient/Assets/ResIn/UI/Login/Login_fui.bytes


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0!a.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_1!a.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_1.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_2!a.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_2.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_3!a.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_3.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_4!a.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_4.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_5!a.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_5.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_6!a.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_atlas0_6.png


BIN
GameClient/Assets/ResIn/UI/RoleInfo/RoleInfo_fui.bytes