2026-06-21 18:20:55 +08:00
|
|
|
|
using Assets.Framework.Tool;
|
|
|
|
|
|
using Assets.MyGame.Scripts.Net;
|
2026-07-07 17:10:00 +08:00
|
|
|
|
using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass;
|
2026-07-07 02:22:31 +08:00
|
|
|
|
using Assets.MyGame.Scripts.Net.APIRequest.Params;
|
2026-04-16 18:31:04 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using TMPro;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
|
2026-06-21 18:20:55 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 用户信息面板(设置已分离至 SettingPanel)
|
|
|
|
|
|
/// </summary>
|
2026-04-16 18:31:04 +08:00
|
|
|
|
public class UserInfoPanel : SubUIBase
|
|
|
|
|
|
{
|
2026-07-06 03:04:08 +08:00
|
|
|
|
public Toggle toggle_BaseUserInfo; //打开默认打开基础信息页面
|
2026-06-21 18:20:55 +08:00
|
|
|
|
[Header("基础信息")]
|
2026-06-30 23:57:40 +08:00
|
|
|
|
public Image sprite_Avatar; // 显示已保存的用户头像(点使用后更新)
|
2026-07-06 02:08:18 +08:00
|
|
|
|
public Image sprite_AvatarK; // 显示已保存的用户头像框(点使用后更新)
|
2026-06-28 16:48:18 +08:00
|
|
|
|
public Button btn_ChangeUser;
|
2026-04-16 18:31:04 +08:00
|
|
|
|
public TextMeshProUGUI tMPText_Name;
|
|
|
|
|
|
public TextMeshProUGUI tMPText_ID;
|
|
|
|
|
|
public TextMeshProUGUI tMPText_UserNumber;
|
|
|
|
|
|
public TextMeshProUGUI tMPText_IP;
|
|
|
|
|
|
public TextMeshProUGUI tMPText_VIPLeave;
|
|
|
|
|
|
public TextMeshProUGUI tMPText_PhoneNumber;
|
2026-07-07 16:17:25 +08:00
|
|
|
|
|
|
|
|
|
|
public TextMeshProUGUI tMPText_UserLevel; //这里显示的是当前等级 显示 LV.N
|
|
|
|
|
|
public TextMeshProUGUI tMPText_Level; //这里显示的是n级奖励 n是下方next和up翻到的指定等级
|
|
|
|
|
|
public Slider slider_UserLevel; //经验进度条
|
2026-07-07 18:33:16 +08:00
|
|
|
|
public TextMeshProUGUI tMPText_Exp; //经验进度条的数值显示
|
2026-07-07 16:17:25 +08:00
|
|
|
|
public BackPackPropItem backPackPropItemPrefab; //奖励预制体 这里是预览next或者up到指定等级的奖励
|
|
|
|
|
|
public Transform backPackPropItemParent;//奖励预制体的父对象
|
|
|
|
|
|
public Button btn_LevelNext; //翻到下一级奖励
|
|
|
|
|
|
public Button btn_LevelUp; //翻到上一级奖励
|
|
|
|
|
|
|
2026-07-07 02:22:31 +08:00
|
|
|
|
[Header("换绑手机")]
|
|
|
|
|
|
public TextMeshProUGUI tMPText_OldPhoneNumber;
|
|
|
|
|
|
public TMP_InputField tMPText_NewPhoneNumber;
|
|
|
|
|
|
public TMP_InputField tMPText_NewPhoneNumberQueRen;
|
|
|
|
|
|
public TMP_InputField tMPText_YZM;
|
|
|
|
|
|
public Button btn_GetYZM; //先不写获取验证码
|
|
|
|
|
|
public Button btn_ChangePhoneNumber;
|
2026-07-07 03:20:30 +08:00
|
|
|
|
[Header("改个性签名")]
|
|
|
|
|
|
public TMP_InputField tMPText_GeXingQianName;
|
|
|
|
|
|
public Button btn_Change;
|
2026-07-07 02:22:31 +08:00
|
|
|
|
[Header("改名")]
|
|
|
|
|
|
public TMP_InputField tMPText_NewName;
|
|
|
|
|
|
public Button btn_ChangeName;
|
|
|
|
|
|
[Header("修改密码")]
|
|
|
|
|
|
public TextMeshProUGUI tMPText_PhoneNumberXGMM;
|
|
|
|
|
|
public TMP_InputField tMPText_NewPassword;
|
|
|
|
|
|
public TMP_InputField tMPText_NewPasswordQueRen;
|
|
|
|
|
|
public TMP_InputField tMPText_YZMXGMM;
|
|
|
|
|
|
public Button btn_GetYZMXGMM; //先不写获取验证码
|
|
|
|
|
|
public Button btn_ChangePassword;
|
2026-07-05 02:10:44 +08:00
|
|
|
|
[Header("预览")]
|
2026-06-30 23:57:40 +08:00
|
|
|
|
public Image img_ShowAvatar; // 预览头像(选中即更新)
|
2026-07-05 02:10:44 +08:00
|
|
|
|
public Image img_ShowAvatarK; // 预览头像框(选中即更新)
|
2026-06-30 23:57:40 +08:00
|
|
|
|
public Button btn_UseAvatar; // 确认使用按钮
|
2026-07-05 02:10:44 +08:00
|
|
|
|
[Header("头像选择")]
|
2026-06-21 18:20:55 +08:00
|
|
|
|
public Transform parent_AvatarList;
|
2026-07-05 02:10:44 +08:00
|
|
|
|
[Header("头像框选择")]
|
|
|
|
|
|
public Transform parent_AvatarKList;
|
|
|
|
|
|
|
|
|
|
|
|
public Toggle prefab_AvatarItem; // 头像/头像框选项预制体(child0=Image, child2=选中对号)
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
2026-07-07 02:22:31 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-04-16 18:31:04 +08:00
|
|
|
|
GameManager gameManager => GameManager.Instance;
|
2026-06-30 23:57:40 +08:00
|
|
|
|
private List<Toggle> _avatarToggles = new List<Toggle>();
|
2026-07-05 02:10:44 +08:00
|
|
|
|
private List<Toggle> _avatarFrameToggles = new List<Toggle>();
|
2026-07-07 17:10:00 +08:00
|
|
|
|
private string _pendingAvatarName;
|
|
|
|
|
|
private string _pendingAvatarFrameName;
|
|
|
|
|
|
|
|
|
|
|
|
// 等级奖励预览
|
|
|
|
|
|
private int _previewLevel;
|
|
|
|
|
|
private List<UserLevelConfig> _levelConfigs;
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
2026-04-16 18:31:04 +08:00
|
|
|
|
public override void Awake()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Awake();
|
2026-06-28 16:48:18 +08:00
|
|
|
|
btn_ChangeUser.onClick.AddListener(() =>
|
|
|
|
|
|
{
|
2026-06-30 23:57:40 +08:00
|
|
|
|
gameManager.Logout();
|
2026-06-28 16:48:18 +08:00
|
|
|
|
});
|
2026-06-30 23:57:40 +08:00
|
|
|
|
btn_UseAvatar.onClick.AddListener(OnClickUseAvatar);
|
2026-07-07 02:22:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 换绑手机
|
|
|
|
|
|
btn_ChangePhoneNumber.onClick.AddListener(OnClickChangePhone);
|
|
|
|
|
|
// 改名
|
|
|
|
|
|
btn_ChangeName.onClick.AddListener(OnClickChangeName);
|
|
|
|
|
|
// 修改密码
|
|
|
|
|
|
btn_ChangePassword.onClick.AddListener(OnClickChangePassword);
|
2026-07-07 03:20:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 改个性签名
|
|
|
|
|
|
btn_Change.onClick.AddListener(OnClickSaveSignature);
|
2026-07-07 17:10:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 等级预览翻页
|
|
|
|
|
|
btn_LevelNext.onClick.AddListener(OnClickLevelNext);
|
|
|
|
|
|
btn_LevelUp.onClick.AddListener(OnClickLevelUp);
|
2026-04-16 18:31:04 +08:00
|
|
|
|
}
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
2026-04-16 18:31:04 +08:00
|
|
|
|
protected override void OnShow(object args = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnShow(args);
|
2026-07-06 03:04:08 +08:00
|
|
|
|
toggle_BaseUserInfo.isOn = true;
|
2026-04-16 18:31:04 +08:00
|
|
|
|
InitInformation();
|
2026-06-21 18:20:55 +08:00
|
|
|
|
BuildAvatarList();
|
2026-07-05 02:10:44 +08:00
|
|
|
|
BuildAvatarFrameList();
|
|
|
|
|
|
// 监听变更
|
2026-06-30 23:57:40 +08:00
|
|
|
|
gameManager.OnAvatarChanged += OnAvatarChanged;
|
2026-07-05 02:10:44 +08:00
|
|
|
|
gameManager.OnAvatarFrameChanged += OnAvatarFrameChanged;
|
2026-06-30 23:57:40 +08:00
|
|
|
|
}
|
2026-06-28 16:48:18 +08:00
|
|
|
|
|
2026-06-30 23:57:40 +08:00
|
|
|
|
protected override void OnHide()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnHide();
|
|
|
|
|
|
gameManager.OnAvatarChanged -= OnAvatarChanged;
|
2026-07-05 02:10:44 +08:00
|
|
|
|
gameManager.OnAvatarFrameChanged -= OnAvatarFrameChanged;
|
2026-06-30 23:57:40 +08:00
|
|
|
|
// 清理 toggle 列表
|
|
|
|
|
|
_avatarToggles.Clear();
|
2026-07-05 02:10:44 +08:00
|
|
|
|
_avatarFrameToggles.Clear();
|
2026-04-16 18:31:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-21 18:20:55 +08:00
|
|
|
|
// ==================== 基础信息 ====================
|
|
|
|
|
|
|
2026-04-16 18:31:04 +08:00
|
|
|
|
private void InitInformation()
|
|
|
|
|
|
{
|
2026-06-21 18:20:55 +08:00
|
|
|
|
tMPText_Name.color = gameManager.user.BaseInfo.isRedName ? Color.red : Color.white;
|
|
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
// 初始化两个头像(正式 + 预览)
|
2026-06-21 18:20:55 +08:00
|
|
|
|
LoadAvatarImage(sprite_Avatar, gameManager.user.BaseInfo.avatarUrl);
|
2026-06-30 23:57:40 +08:00
|
|
|
|
LoadAvatarImage(img_ShowAvatar, gameManager.user.BaseInfo.avatarUrl);
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
// 初始化头像框预览
|
|
|
|
|
|
LoadAvatarFrameImage(img_ShowAvatarK, gameManager.user.BaseInfo.avatarFrame);
|
2026-07-06 02:08:18 +08:00
|
|
|
|
LoadAvatarFrameImage(sprite_AvatarK, gameManager.user.BaseInfo.avatarFrame);
|
2026-07-05 02:10:44 +08:00
|
|
|
|
|
2026-04-16 18:31:04 +08:00
|
|
|
|
tMPText_Name.text = gameManager.user.BaseInfo.userName;
|
|
|
|
|
|
tMPText_ID.text = gameManager.user.BaseInfo.number;
|
|
|
|
|
|
tMPText_UserNumber.text = gameManager.user.BaseInfo.mobile;
|
2026-07-07 03:20:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 个性签名输入框
|
|
|
|
|
|
if (tMPText_GeXingQianName != null)
|
|
|
|
|
|
tMPText_GeXingQianName.text = PlayerPrefs.GetString("QM", "我比较懒,什么都没写");
|
2026-04-16 18:31:04 +08:00
|
|
|
|
tMPText_IP.text = gameManager.user.@static.lastLoginIp;
|
|
|
|
|
|
tMPText_VIPLeave.text = gameManager.user.assets.vipLevel.ToString();
|
|
|
|
|
|
tMPText_PhoneNumber.text = MaskPhone(gameManager.user.BaseInfo.mobile);
|
2026-07-07 02:22:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 换绑手机 & 修改密码页面显示旧手机号
|
|
|
|
|
|
if (tMPText_OldPhoneNumber != null)
|
|
|
|
|
|
tMPText_OldPhoneNumber.text = MaskPhone(gameManager.user.BaseInfo.mobile);
|
|
|
|
|
|
if (tMPText_PhoneNumberXGMM != null)
|
|
|
|
|
|
tMPText_PhoneNumberXGMM.text = MaskPhone(gameManager.user.BaseInfo.mobile);
|
2026-07-07 17:10:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 等级信息
|
|
|
|
|
|
RefreshLevelUI();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 等级奖励预览 ====================
|
|
|
|
|
|
|
|
|
|
|
|
private void RefreshLevelUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
_levelConfigs = GameManager.Instance?.gameConfig?.userLevelConfigs;
|
|
|
|
|
|
if (_levelConfigs == null || _levelConfigs.Count == 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
var assets = gameManager.user.assets;
|
|
|
|
|
|
int currentLevel = assets.level;
|
|
|
|
|
|
|
|
|
|
|
|
if (tMPText_UserLevel != null)
|
|
|
|
|
|
tMPText_UserLevel.text = $"LV.{currentLevel}";
|
|
|
|
|
|
|
2026-07-07 18:33:16 +08:00
|
|
|
|
// 初次打开默认预览当前等级(至少 1 级)
|
2026-07-07 17:10:00 +08:00
|
|
|
|
if (_previewLevel <= 0)
|
2026-07-07 18:33:16 +08:00
|
|
|
|
_previewLevel = Mathf.Max(currentLevel, 1);
|
2026-07-07 17:10:00 +08:00
|
|
|
|
UpdateLevelPreview();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdateLevelPreview()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_levelConfigs == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
var cfg = _levelConfigs.Find(c => c.level == _previewLevel);
|
|
|
|
|
|
if (cfg == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
var assets = gameManager.user.assets;
|
|
|
|
|
|
|
|
|
|
|
|
if (tMPText_Level != null)
|
|
|
|
|
|
tMPText_Level.text = $"{cfg.level}级奖励";
|
|
|
|
|
|
|
|
|
|
|
|
// 进度条
|
|
|
|
|
|
if (slider_UserLevel != null)
|
|
|
|
|
|
{
|
2026-07-07 18:33:16 +08:00
|
|
|
|
//slider_UserLevel.minValue = cfg.expMin;
|
2026-07-07 17:10:00 +08:00
|
|
|
|
slider_UserLevel.maxValue = cfg.expMax;
|
2026-07-07 18:33:16 +08:00
|
|
|
|
//slider_UserLevel.value = Mathf.Clamp(assets.exp, cfg.expMin, cfg.expMax);
|
2026-08-09 17:57:46 +08:00
|
|
|
|
slider_UserLevel.value = Mathf.Clamp((float)assets.exp, 0, cfg.expMax);
|
2026-07-07 17:10:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-07 18:33:16 +08:00
|
|
|
|
// 经验数值
|
|
|
|
|
|
if (tMPText_Exp != null)
|
|
|
|
|
|
tMPText_Exp.text = $"{FormatLargeNum(assets.exp)}/{FormatLargeNum(cfg.expMax)}";
|
|
|
|
|
|
|
|
|
|
|
|
// 奖励预览
|
2026-07-07 17:10:00 +08:00
|
|
|
|
if (backPackPropItemParent != null && backPackPropItemPrefab != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = backPackPropItemParent.childCount - 1; i >= 0; i--)
|
|
|
|
|
|
Destroy(backPackPropItemParent.GetChild(i).gameObject);
|
|
|
|
|
|
|
|
|
|
|
|
if (cfg.productList != null && cfg.productList.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var product in cfg.productList)
|
|
|
|
|
|
{
|
|
|
|
|
|
var obj = Instantiate(backPackPropItemPrefab.gameObject, backPackPropItemParent);
|
|
|
|
|
|
obj.SetActive(true);
|
|
|
|
|
|
var item = obj.GetComponent<BackPackPropItem>();
|
|
|
|
|
|
if (item == null) continue;
|
2026-07-09 19:35:25 +08:00
|
|
|
|
item.Init(new BackPackPropItemData
|
|
|
|
|
|
{
|
|
|
|
|
|
url = APIManager.baseURL + product.imageUrl,
|
|
|
|
|
|
count = product.count,
|
|
|
|
|
|
propEnum = (PropEnum)product.type
|
|
|
|
|
|
});
|
2026-07-07 17:10:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnClickLevelNext()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_levelConfigs == null) return;
|
|
|
|
|
|
int maxLevel = _levelConfigs[_levelConfigs.Count - 1].level;
|
|
|
|
|
|
if (_previewLevel < maxLevel)
|
|
|
|
|
|
{
|
|
|
|
|
|
_previewLevel++;
|
|
|
|
|
|
UpdateLevelPreview();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnClickLevelUp()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_previewLevel > 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
_previewLevel--;
|
|
|
|
|
|
UpdateLevelPreview();
|
|
|
|
|
|
}
|
2026-04-16 18:31:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-21 18:20:55 +08:00
|
|
|
|
// ==================== 头像加载 ====================
|
2026-04-16 18:31:04 +08:00
|
|
|
|
|
2026-06-21 18:20:55 +08:00
|
|
|
|
private void LoadAvatarImage(Image target, string avatarUrl)
|
|
|
|
|
|
{
|
2026-06-21 22:38:18 +08:00
|
|
|
|
if (target == null) return;
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
|
|
|
|
|
var sprite = gameManager.GetAvatarSprite(avatarUrl);
|
|
|
|
|
|
if (sprite != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
target.sprite = sprite;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!int.TryParse(avatarUrl, out _))
|
|
|
|
|
|
{
|
|
|
|
|
|
WebTool.DownImage(avatarUrl, (texture) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (texture != null && target != null)
|
|
|
|
|
|
target.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.one * 0.5f);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-04-16 18:31:04 +08:00
|
|
|
|
}
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
private void LoadAvatarFrameImage(Image target, string avatarFrameName)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (target == null) return;
|
|
|
|
|
|
var sprite = gameManager.GetAvatarFrameSprite(avatarFrameName);
|
|
|
|
|
|
if (sprite != null)
|
|
|
|
|
|
target.sprite = sprite;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-21 18:20:55 +08:00
|
|
|
|
// ==================== 头像列表 ====================
|
|
|
|
|
|
|
2026-07-01 14:40:41 +08:00
|
|
|
|
/// <summary>当前装备的头像名(从服务器数据读取)</summary>
|
|
|
|
|
|
private string _equippedAvatarName;
|
|
|
|
|
|
|
2026-06-21 18:20:55 +08:00
|
|
|
|
private void BuildAvatarList()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (prefab_AvatarItem == null || parent_AvatarList == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = parent_AvatarList.childCount - 1; i >= 0; i--)
|
|
|
|
|
|
Destroy(parent_AvatarList.GetChild(i).gameObject);
|
2026-06-30 23:57:40 +08:00
|
|
|
|
_avatarToggles.Clear();
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
|
|
|
|
|
gameManager.InitAvatarCache();
|
|
|
|
|
|
var allSprites = Resources.LoadAll<Sprite>("Avatar");
|
2026-07-01 14:40:41 +08:00
|
|
|
|
_equippedAvatarName = gameManager.user.BaseInfo.avatarUrl;
|
|
|
|
|
|
_pendingAvatarName = _equippedAvatarName;
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
|
|
|
|
|
foreach (var sprite in allSprites)
|
|
|
|
|
|
{
|
|
|
|
|
|
var obj = Instantiate(prefab_AvatarItem, parent_AvatarList);
|
2026-07-01 14:40:41 +08:00
|
|
|
|
string avatarName = sprite.name;
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
2026-07-01 14:40:41 +08:00
|
|
|
|
// child(0) = 头像图片
|
2026-06-30 23:57:40 +08:00
|
|
|
|
if (obj.transform.childCount > 0)
|
2026-06-21 18:20:55 +08:00
|
|
|
|
{
|
2026-06-30 23:57:40 +08:00
|
|
|
|
var img = obj.transform.GetChild(0).GetComponent<Image>();
|
|
|
|
|
|
if (img != null) img.sprite = sprite;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-01 14:40:41 +08:00
|
|
|
|
// child(2) = 装备中对号(只在已装备的头像上显示,不跟随选中状态)
|
|
|
|
|
|
Transform checkMark = obj.transform.childCount > 2 ? obj.transform.GetChild(2) : null;
|
|
|
|
|
|
if (checkMark != null)
|
|
|
|
|
|
checkMark.gameObject.SetActive(avatarName == _equippedAvatarName);
|
2026-06-30 23:57:40 +08:00
|
|
|
|
|
|
|
|
|
|
var toggle = obj.GetComponent<Toggle>();
|
2026-07-01 14:40:41 +08:00
|
|
|
|
if (toggle == null) continue;
|
|
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
// 加入父对象的 ToggleGroup 实现单选
|
|
|
|
|
|
toggle.group = parent_AvatarList.GetComponent<ToggleGroup>();
|
|
|
|
|
|
|
|
|
|
|
|
// 禁用 Toggle 自带的过渡效果
|
2026-07-01 14:40:41 +08:00
|
|
|
|
toggle.transition = Selectable.Transition.None;
|
|
|
|
|
|
// 初始选中已装备的头像
|
|
|
|
|
|
toggle.isOn = (avatarName == _equippedAvatarName);
|
|
|
|
|
|
|
|
|
|
|
|
_avatarToggles.Add(toggle);
|
|
|
|
|
|
|
|
|
|
|
|
toggle.onValueChanged.AddListener(isOn =>
|
2026-06-30 23:57:40 +08:00
|
|
|
|
{
|
2026-07-01 14:40:41 +08:00
|
|
|
|
if (!isOn) return;
|
2026-06-30 23:57:40 +08:00
|
|
|
|
|
2026-07-01 14:40:41 +08:00
|
|
|
|
_pendingAvatarName = avatarName;
|
2026-06-30 23:57:40 +08:00
|
|
|
|
|
2026-07-01 14:40:41 +08:00
|
|
|
|
// 预览头像实时更新
|
|
|
|
|
|
if (img_ShowAvatar != null)
|
|
|
|
|
|
img_ShowAvatar.sprite = sprite;
|
|
|
|
|
|
});
|
2026-06-21 18:20:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
// ==================== 头像框列表 ====================
|
2026-06-21 18:20:55 +08:00
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
/// <summary>当前装备的头像框名(从服务器数据读取)</summary>
|
|
|
|
|
|
private string _equippedAvatarFrameName;
|
|
|
|
|
|
|
|
|
|
|
|
private void BuildAvatarFrameList()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (prefab_AvatarItem == null || parent_AvatarKList == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = parent_AvatarKList.childCount - 1; i >= 0; i--)
|
|
|
|
|
|
Destroy(parent_AvatarKList.GetChild(i).gameObject);
|
|
|
|
|
|
_avatarFrameToggles.Clear();
|
|
|
|
|
|
|
|
|
|
|
|
gameManager.InitAvatarFrameCache();
|
|
|
|
|
|
var allSprites = Resources.LoadAll<Sprite>("AvatarK");
|
|
|
|
|
|
_equippedAvatarFrameName = gameManager.user.BaseInfo.avatarFrame;
|
|
|
|
|
|
_pendingAvatarFrameName = _equippedAvatarFrameName;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var sprite in allSprites)
|
|
|
|
|
|
{
|
|
|
|
|
|
var obj = Instantiate(prefab_AvatarItem, parent_AvatarKList);
|
|
|
|
|
|
string frameName = sprite.name;
|
|
|
|
|
|
|
|
|
|
|
|
// child(0) = 头像框图片
|
|
|
|
|
|
if (obj.transform.childCount > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var img = obj.transform.GetChild(0).GetComponent<Image>();
|
|
|
|
|
|
if (img != null) img.sprite = sprite;
|
|
|
|
|
|
// 头像框可以设置 SetNativeSize 保持比例
|
|
|
|
|
|
//if (img != null) img.SetNativeSize();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// child(2) = 装备中对号(只在已装备的头像框上显示)
|
|
|
|
|
|
Transform checkMark = obj.transform.childCount > 2 ? obj.transform.GetChild(2) : null;
|
|
|
|
|
|
if (checkMark != null)
|
|
|
|
|
|
checkMark.gameObject.SetActive(frameName == _equippedAvatarFrameName);
|
|
|
|
|
|
|
|
|
|
|
|
var toggle = obj.GetComponent<Toggle>();
|
|
|
|
|
|
if (toggle == null) continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 加入父对象的 ToggleGroup 实现单选
|
|
|
|
|
|
toggle.group = parent_AvatarKList.GetComponent<ToggleGroup>();
|
|
|
|
|
|
|
|
|
|
|
|
// 禁用 Toggle 自带的过渡效果
|
|
|
|
|
|
toggle.transition = Selectable.Transition.None;
|
|
|
|
|
|
// 初始选中已装备的头像框
|
|
|
|
|
|
toggle.isOn = (frameName == _equippedAvatarFrameName);
|
|
|
|
|
|
|
|
|
|
|
|
_avatarFrameToggles.Add(toggle);
|
|
|
|
|
|
|
|
|
|
|
|
toggle.onValueChanged.AddListener(isOn =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!isOn) return;
|
|
|
|
|
|
|
|
|
|
|
|
_pendingAvatarFrameName = frameName;
|
|
|
|
|
|
|
|
|
|
|
|
// 预览头像框实时更新
|
|
|
|
|
|
if (img_ShowAvatarK != null)
|
|
|
|
|
|
img_ShowAvatarK.sprite = sprite;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-06-30 23:57:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
// ==================== 确认使用 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>点击"使用"按钮 → 确认切换装备头像/头像框</summary>
|
|
|
|
|
|
private void OnClickUseAvatar()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 优先判断是否有头像更改
|
|
|
|
|
|
bool avatarChanged = !string.IsNullOrEmpty(_pendingAvatarName)
|
|
|
|
|
|
&& _pendingAvatarName != _equippedAvatarName;
|
|
|
|
|
|
|
|
|
|
|
|
// 判断是否有头像框更改
|
|
|
|
|
|
bool frameChanged = !string.IsNullOrEmpty(_pendingAvatarFrameName)
|
|
|
|
|
|
&& _pendingAvatarFrameName != _equippedAvatarFrameName;
|
|
|
|
|
|
|
|
|
|
|
|
if (avatarChanged)
|
|
|
|
|
|
{
|
|
|
|
|
|
LoadAvatarImage(sprite_Avatar, _pendingAvatarName);
|
2026-07-06 02:08:18 +08:00
|
|
|
|
LoadAvatarImage(sprite_Avatar, _pendingAvatarName);
|
|
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
gameManager.ApplyAvatar(_pendingAvatarName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (frameChanged)
|
|
|
|
|
|
{
|
|
|
|
|
|
LoadAvatarFrameImage(img_ShowAvatarK, _pendingAvatarFrameName);
|
2026-07-06 02:08:18 +08:00
|
|
|
|
LoadAvatarFrameImage(sprite_AvatarK, _pendingAvatarFrameName);
|
|
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
gameManager.ApplyAvatarFrame(_pendingAvatarFrameName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!avatarChanged && !frameChanged)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("[UserInfoPanel] 未改变头像或头像框");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 变更回调 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>头像变更回调(服务器返回后),同步预览和列表对号</summary>
|
2026-06-30 23:57:40 +08:00
|
|
|
|
private void OnAvatarChanged(Sprite sprite)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (sprite_Avatar != null && sprite != null)
|
|
|
|
|
|
sprite_Avatar.sprite = sprite;
|
|
|
|
|
|
if (img_ShowAvatar != null && sprite != null)
|
|
|
|
|
|
img_ShowAvatar.sprite = sprite;
|
2026-07-01 14:40:41 +08:00
|
|
|
|
|
|
|
|
|
|
_equippedAvatarName = _pendingAvatarName;
|
|
|
|
|
|
|
|
|
|
|
|
// 切换对号:隐藏旧的、显示新的
|
|
|
|
|
|
foreach (var t in _avatarToggles)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (t == null || t.transform.childCount <= 2) continue;
|
|
|
|
|
|
var img = t.transform.GetChild(0).GetComponent<Image>();
|
|
|
|
|
|
bool isEquipped = img != null && img.sprite != null && img.sprite.name == _equippedAvatarName;
|
|
|
|
|
|
t.transform.GetChild(2).gameObject.SetActive(isEquipped);
|
|
|
|
|
|
}
|
2026-06-21 18:20:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-05 02:10:44 +08:00
|
|
|
|
/// <summary>头像框变更回调(服务器返回后),同步预览和列表对号</summary>
|
|
|
|
|
|
private void OnAvatarFrameChanged(Sprite sprite)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (img_ShowAvatarK != null && sprite != null)
|
|
|
|
|
|
img_ShowAvatarK.sprite = sprite;
|
|
|
|
|
|
|
|
|
|
|
|
_equippedAvatarFrameName = _pendingAvatarFrameName;
|
|
|
|
|
|
|
|
|
|
|
|
// 切换对号:隐藏旧的、显示新的
|
|
|
|
|
|
foreach (var t in _avatarFrameToggles)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (t == null || t.transform.childCount <= 2) continue;
|
|
|
|
|
|
var img = t.transform.GetChild(0).GetComponent<Image>();
|
|
|
|
|
|
bool isEquipped = img != null && img.sprite != null && img.sprite.name == _equippedAvatarFrameName;
|
|
|
|
|
|
t.transform.GetChild(2).gameObject.SetActive(isEquipped);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-07 02:22:31 +08:00
|
|
|
|
// ==================== 换绑手机 ====================
|
|
|
|
|
|
|
|
|
|
|
|
private void OnClickChangePhone()
|
|
|
|
|
|
{
|
|
|
|
|
|
string oldPhone = gameManager.user.BaseInfo.mobile;
|
|
|
|
|
|
string newPhone = tMPText_NewPhoneNumber?.text?.Trim();
|
|
|
|
|
|
string newPhoneConfirm = tMPText_NewPhoneNumberQueRen?.text?.Trim();
|
|
|
|
|
|
string code = tMPText_YZM?.text?.Trim();
|
|
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(newPhone))
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("请输入新手机号");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (newPhone != newPhoneConfirm)
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("两次输入的新手机号不一致");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrEmpty(code))
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("请输入验证码");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
APIRequestList.BindMobile(newPhone, code, (result) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("手机号换绑成功");
|
|
|
|
|
|
// 刷新本地数据
|
|
|
|
|
|
gameManager.user.BaseInfo.mobile = newPhone;
|
|
|
|
|
|
tMPText_OldPhoneNumber.text = MaskPhone(newPhone);
|
|
|
|
|
|
tMPText_PhoneNumber.text = MaskPhone(newPhone);
|
|
|
|
|
|
tMPText_NewPhoneNumber.text = "";
|
|
|
|
|
|
tMPText_NewPhoneNumberQueRen.text = "";
|
|
|
|
|
|
tMPText_YZM.text = "";
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnClickChangeName()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 检查是否有改名卡
|
|
|
|
|
|
var props = gameManager.user.props;
|
|
|
|
|
|
bool hasNameCard = false;
|
|
|
|
|
|
if (props != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var p in props)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (p.count > 0 && (PropEnum)p.type == PropEnum.改名卡)
|
|
|
|
|
|
{
|
|
|
|
|
|
hasNameCard = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!hasNameCard)
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("没有改名卡");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string newName = tMPText_NewName?.text?.Trim();
|
|
|
|
|
|
if (string.IsNullOrEmpty(newName))
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("请输入新名字");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-10 00:46:23 +08:00
|
|
|
|
UIManager.Instance.ShowTiShi($"确定要将名字改为\"{newName}\"吗?", () =>
|
2026-07-07 02:22:31 +08:00
|
|
|
|
{
|
2026-07-10 00:46:23 +08:00
|
|
|
|
APIRequestList.UpdateUserName(newName, (result) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("改名成功");
|
|
|
|
|
|
tMPText_NewName.text = "";
|
2026-07-23 01:51:07 +08:00
|
|
|
|
// 拉取服务器最新用户数据,同步本地并触发全局 UI 更新
|
|
|
|
|
|
APIRequestList.GetUser((user) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (user != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
gameManager.UpdataUserData(user);
|
|
|
|
|
|
tMPText_Name.text = user.BaseInfo.userName;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-07-10 00:46:23 +08:00
|
|
|
|
});
|
2026-07-07 02:22:31 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 修改密码 ====================
|
|
|
|
|
|
|
|
|
|
|
|
private void OnClickChangePassword()
|
|
|
|
|
|
{
|
|
|
|
|
|
string mobile = gameManager.user.BaseInfo.mobile;
|
|
|
|
|
|
string newPwd = tMPText_NewPassword?.text?.Trim();
|
|
|
|
|
|
string newPwdConfirm = tMPText_NewPasswordQueRen?.text?.Trim();
|
|
|
|
|
|
string code = tMPText_YZMXGMM?.text?.Trim();
|
|
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(newPwd))
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("请输入新密码");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (newPwd != newPwdConfirm)
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("两次输入的密码不一致");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (string.IsNullOrEmpty(code))
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("请输入验证码");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
APIRequestList.ResetPassword(new ReSetPassWordParam
|
|
|
|
|
|
{
|
|
|
|
|
|
mobile = mobile,
|
|
|
|
|
|
password = newPwd,
|
|
|
|
|
|
code = code
|
|
|
|
|
|
}, (result) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("密码修改成功");
|
|
|
|
|
|
tMPText_NewPassword.text = "";
|
|
|
|
|
|
tMPText_NewPasswordQueRen.text = "";
|
|
|
|
|
|
tMPText_YZMXGMM.text = "";
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-07 03:20:30 +08:00
|
|
|
|
// ==================== 改个性签名 ====================
|
|
|
|
|
|
|
|
|
|
|
|
private void OnClickSaveSignature()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (tMPText_GeXingQianName == null) return;
|
|
|
|
|
|
string text = tMPText_GeXingQianName.text.Trim();
|
|
|
|
|
|
if (string.IsNullOrEmpty(text))
|
|
|
|
|
|
{
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("签名不能为空");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-07-10 00:46:23 +08:00
|
|
|
|
UIManager.Instance.ShowTiShi("确定要修改个性签名吗?", () =>
|
|
|
|
|
|
{
|
|
|
|
|
|
PlayerPrefs.SetString("QM", text);
|
|
|
|
|
|
PlayerPrefs.Save();
|
|
|
|
|
|
UIManager.Instance.ShowBoardError("签名保存成功");
|
|
|
|
|
|
});
|
2026-07-07 03:20:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-21 18:20:55 +08:00
|
|
|
|
// ==================== 工具 ====================
|
|
|
|
|
|
|
2026-07-07 18:33:16 +08:00
|
|
|
|
private static string FormatLargeNum(long num)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (num >= 100000000) return $"{(num / 100000000f):F1}亿";
|
|
|
|
|
|
if (num >= 10000) return $"{(num / 10000f):F1}万";
|
|
|
|
|
|
return num.ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-16 18:31:04 +08:00
|
|
|
|
public static string MaskPhone(string phone)
|
|
|
|
|
|
{
|
2026-07-07 02:22:31 +08:00
|
|
|
|
if (string.IsNullOrEmpty(phone) || phone.Length < 7)
|
2026-04-16 18:31:04 +08:00
|
|
|
|
return phone;
|
2026-07-07 02:22:31 +08:00
|
|
|
|
return phone.Substring(0, 3) + "****" + phone.Substring(phone.Length - 4);
|
2026-04-16 18:31:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|