Files
5.24BuYu/Assets/MyGame/aa/UI/Home/Sub/UserInfoPanel.cs
T
2026-08-09 17:57:46 +08:00

637 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Assets.Framework.Tool;
using Assets.MyGame.Scripts.Net;
using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass;
using Assets.MyGame.Scripts.Net.APIRequest.Params;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 用户信息面板(设置已分离至 SettingPanel)
/// </summary>
public class UserInfoPanel : SubUIBase
{
public Toggle toggle_BaseUserInfo; //打开默认打开基础信息页面
[Header("基础信息")]
public Image sprite_Avatar; // 显示已保存的用户头像(点使用后更新)
public Image sprite_AvatarK; // 显示已保存的用户头像框(点使用后更新)
public Button btn_ChangeUser;
public TextMeshProUGUI tMPText_Name;
public TextMeshProUGUI tMPText_ID;
public TextMeshProUGUI tMPText_UserNumber;
public TextMeshProUGUI tMPText_IP;
public TextMeshProUGUI tMPText_VIPLeave;
public TextMeshProUGUI tMPText_PhoneNumber;
public TextMeshProUGUI tMPText_UserLevel; //这里显示的是当前等级 显示 LV.N
public TextMeshProUGUI tMPText_Level; //这里显示的是n级奖励 n是下方next和up翻到的指定等级
public Slider slider_UserLevel; //经验进度条
public TextMeshProUGUI tMPText_Exp; //经验进度条的数值显示
public BackPackPropItem backPackPropItemPrefab; //奖励预制体 这里是预览next或者up到指定等级的奖励
public Transform backPackPropItemParent;//奖励预制体的父对象
public Button btn_LevelNext; //翻到下一级奖励
public Button btn_LevelUp; //翻到上一级奖励
[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;
[Header("改个性签名")]
public TMP_InputField tMPText_GeXingQianName;
public Button btn_Change;
[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;
[Header("预览")]
public Image img_ShowAvatar; // 预览头像(选中即更新)
public Image img_ShowAvatarK; // 预览头像框(选中即更新)
public Button btn_UseAvatar; // 确认使用按钮
[Header("头像选择")]
public Transform parent_AvatarList;
[Header("头像框选择")]
public Transform parent_AvatarKList;
public Toggle prefab_AvatarItem; // 头像/头像框选项预制体(child0=Image, child2=选中对号)
GameManager gameManager => GameManager.Instance;
private List<Toggle> _avatarToggles = new List<Toggle>();
private List<Toggle> _avatarFrameToggles = new List<Toggle>();
private string _pendingAvatarName;
private string _pendingAvatarFrameName;
// 等级奖励预览
private int _previewLevel;
private List<UserLevelConfig> _levelConfigs;
public override void Awake()
{
base.Awake();
btn_ChangeUser.onClick.AddListener(() =>
{
gameManager.Logout();
});
btn_UseAvatar.onClick.AddListener(OnClickUseAvatar);
// 换绑手机
btn_ChangePhoneNumber.onClick.AddListener(OnClickChangePhone);
// 改名
btn_ChangeName.onClick.AddListener(OnClickChangeName);
// 修改密码
btn_ChangePassword.onClick.AddListener(OnClickChangePassword);
// 改个性签名
btn_Change.onClick.AddListener(OnClickSaveSignature);
// 等级预览翻页
btn_LevelNext.onClick.AddListener(OnClickLevelNext);
btn_LevelUp.onClick.AddListener(OnClickLevelUp);
}
protected override void OnShow(object args = null)
{
base.OnShow(args);
toggle_BaseUserInfo.isOn = true;
InitInformation();
BuildAvatarList();
BuildAvatarFrameList();
// 监听变更
gameManager.OnAvatarChanged += OnAvatarChanged;
gameManager.OnAvatarFrameChanged += OnAvatarFrameChanged;
}
protected override void OnHide()
{
base.OnHide();
gameManager.OnAvatarChanged -= OnAvatarChanged;
gameManager.OnAvatarFrameChanged -= OnAvatarFrameChanged;
// 清理 toggle 列表
_avatarToggles.Clear();
_avatarFrameToggles.Clear();
}
// ==================== 基础信息 ====================
private void InitInformation()
{
tMPText_Name.color = gameManager.user.BaseInfo.isRedName ? Color.red : Color.white;
// 初始化两个头像(正式 + 预览)
LoadAvatarImage(sprite_Avatar, gameManager.user.BaseInfo.avatarUrl);
LoadAvatarImage(img_ShowAvatar, gameManager.user.BaseInfo.avatarUrl);
// 初始化头像框预览
LoadAvatarFrameImage(img_ShowAvatarK, gameManager.user.BaseInfo.avatarFrame);
LoadAvatarFrameImage(sprite_AvatarK, gameManager.user.BaseInfo.avatarFrame);
tMPText_Name.text = gameManager.user.BaseInfo.userName;
tMPText_ID.text = gameManager.user.BaseInfo.number;
tMPText_UserNumber.text = gameManager.user.BaseInfo.mobile;
// 个性签名输入框
if (tMPText_GeXingQianName != null)
tMPText_GeXingQianName.text = PlayerPrefs.GetString("QM", "我比较懒,什么都没写");
tMPText_IP.text = gameManager.user.@static.lastLoginIp;
tMPText_VIPLeave.text = gameManager.user.assets.vipLevel.ToString();
tMPText_PhoneNumber.text = MaskPhone(gameManager.user.BaseInfo.mobile);
// 换绑手机 & 修改密码页面显示旧手机号
if (tMPText_OldPhoneNumber != null)
tMPText_OldPhoneNumber.text = MaskPhone(gameManager.user.BaseInfo.mobile);
if (tMPText_PhoneNumberXGMM != null)
tMPText_PhoneNumberXGMM.text = MaskPhone(gameManager.user.BaseInfo.mobile);
// 等级信息
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}";
// 初次打开默认预览当前等级(至少 1 级)
if (_previewLevel <= 0)
_previewLevel = Mathf.Max(currentLevel, 1);
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)
{
//slider_UserLevel.minValue = cfg.expMin;
slider_UserLevel.maxValue = cfg.expMax;
//slider_UserLevel.value = Mathf.Clamp(assets.exp, cfg.expMin, cfg.expMax);
slider_UserLevel.value = Mathf.Clamp((float)assets.exp, 0, cfg.expMax);
}
// 经验数值
if (tMPText_Exp != null)
tMPText_Exp.text = $"{FormatLargeNum(assets.exp)}/{FormatLargeNum(cfg.expMax)}";
// 奖励预览
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;
item.Init(new BackPackPropItemData
{
url = APIManager.baseURL + product.imageUrl,
count = product.count,
propEnum = (PropEnum)product.type
});
}
}
}
}
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();
}
}
// ==================== 头像加载 ====================
private void LoadAvatarImage(Image target, string avatarUrl)
{
if (target == null) return;
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);
});
}
}
private void LoadAvatarFrameImage(Image target, string avatarFrameName)
{
if (target == null) return;
var sprite = gameManager.GetAvatarFrameSprite(avatarFrameName);
if (sprite != null)
target.sprite = sprite;
}
// ==================== 头像列表 ====================
/// <summary>当前装备的头像名(从服务器数据读取)</summary>
private string _equippedAvatarName;
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);
_avatarToggles.Clear();
gameManager.InitAvatarCache();
var allSprites = Resources.LoadAll<Sprite>("Avatar");
_equippedAvatarName = gameManager.user.BaseInfo.avatarUrl;
_pendingAvatarName = _equippedAvatarName;
foreach (var sprite in allSprites)
{
var obj = Instantiate(prefab_AvatarItem, parent_AvatarList);
string avatarName = sprite.name;
// child(0) = 头像图片
if (obj.transform.childCount > 0)
{
var img = obj.transform.GetChild(0).GetComponent<Image>();
if (img != null) img.sprite = sprite;
}
// child(2) = 装备中对号(只在已装备的头像上显示,不跟随选中状态)
Transform checkMark = obj.transform.childCount > 2 ? obj.transform.GetChild(2) : null;
if (checkMark != null)
checkMark.gameObject.SetActive(avatarName == _equippedAvatarName);
var toggle = obj.GetComponent<Toggle>();
if (toggle == null) continue;
// 加入父对象的 ToggleGroup 实现单选
toggle.group = parent_AvatarList.GetComponent<ToggleGroup>();
// 禁用 Toggle 自带的过渡效果
toggle.transition = Selectable.Transition.None;
// 初始选中已装备的头像
toggle.isOn = (avatarName == _equippedAvatarName);
_avatarToggles.Add(toggle);
toggle.onValueChanged.AddListener(isOn =>
{
if (!isOn) return;
_pendingAvatarName = avatarName;
// 预览头像实时更新
if (img_ShowAvatar != null)
img_ShowAvatar.sprite = sprite;
});
}
}
// ==================== 头像框列表 ====================
/// <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;
});
}
}
// ==================== 确认使用 ====================
/// <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);
LoadAvatarImage(sprite_Avatar, _pendingAvatarName);
gameManager.ApplyAvatar(_pendingAvatarName);
}
if (frameChanged)
{
LoadAvatarFrameImage(img_ShowAvatarK, _pendingAvatarFrameName);
LoadAvatarFrameImage(sprite_AvatarK, _pendingAvatarFrameName);
gameManager.ApplyAvatarFrame(_pendingAvatarFrameName);
}
if (!avatarChanged && !frameChanged)
{
Debug.Log("[UserInfoPanel] 未改变头像或头像框");
}
}
// ==================== 变更回调 ====================
/// <summary>头像变更回调(服务器返回后),同步预览和列表对号</summary>
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;
_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);
}
}
/// <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);
}
}
// ==================== 换绑手机 ====================
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;
}
UIManager.Instance.ShowTiShi($"确定要将名字改为\"{newName}\"吗?", () =>
{
APIRequestList.UpdateUserName(newName, (result) =>
{
UIManager.Instance.ShowBoardError("改名成功");
tMPText_NewName.text = "";
// 拉取服务器最新用户数据,同步本地并触发全局 UI 更新
APIRequestList.GetUser((user) =>
{
if (user != null)
{
gameManager.UpdataUserData(user);
tMPText_Name.text = user.BaseInfo.userName;
}
});
});
});
}
// ==================== 修改密码 ====================
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 = "";
});
}
// ==================== 改个性签名 ====================
private void OnClickSaveSignature()
{
if (tMPText_GeXingQianName == null) return;
string text = tMPText_GeXingQianName.text.Trim();
if (string.IsNullOrEmpty(text))
{
UIManager.Instance.ShowBoardError("签名不能为空");
return;
}
UIManager.Instance.ShowTiShi("确定要修改个性签名吗?", () =>
{
PlayerPrefs.SetString("QM", text);
PlayerPrefs.Save();
UIManager.Instance.ShowBoardError("签名保存成功");
});
}
// ==================== 工具 ====================
private static string FormatLargeNum(long num)
{
if (num >= 100000000) return $"{(num / 100000000f):F1}亿";
if (num >= 10000) return $"{(num / 10000f):F1}万";
return num.ToString();
}
public static string MaskPhone(string phone)
{
if (string.IsNullOrEmpty(phone) || phone.Length < 7)
return phone;
return phone.Substring(0, 3) + "****" + phone.Substring(phone.Length - 4);
}
}