Files
5.24BuYu/Assets/MyGame/aa/UI/Home/Sub/UIHome_BY_BackPackPanel.cs
T

385 lines
14 KiB
C#
Raw Normal View History

2026-06-26 17:26:10 +08:00
using Assets.Framework.Tool;
2026-04-13 18:30:55 +08:00
using Assets.MyGame.Scripts.Net;
2026-03-27 15:18:35 +08:00
using Assets.MyGame.Scripts.Net.API.UserData_SubClass;
using System.Collections;
2025-12-13 18:18:28 +08:00
using System.Collections.Generic;
2026-03-27 15:18:35 +08:00
using TMPro;
2025-12-13 18:18:28 +08:00
using UnityEngine;
2026-03-27 15:18:35 +08:00
using UnityEngine.UI;
2025-12-13 18:18:28 +08:00
2025-12-26 11:15:56 +08:00
public class UIHome_BY_BackPackPanel : SubUIBase
2025-12-13 18:18:28 +08:00
{
2026-03-27 15:18:35 +08:00
public List<BaseProductCount> props;
2026-06-26 17:26:10 +08:00
public Dictionary<string, BaseProductCount> propsID_Dic = new Dictionary<string, BaseProductCount>();
public Dictionary<int, BaseProductCount> propsObjHashCode_Dic = new Dictionary<int, BaseProductCount>();
public Transform pageParent;
2026-06-25 01:48:07 +08:00
public BackPackPropItem prefabItem;
2026-03-27 15:18:35 +08:00
2026-06-25 16:18:07 +08:00
public TextMeshProUGUI tMP_Gold;
public TextMeshProUGUI tMP_Diamond;
2026-06-25 01:48:07 +08:00
[Header("道具详情")]
2026-03-27 15:18:35 +08:00
public TextMeshProUGUI tMP_Name;
public TextMeshProUGUI tMP_Description;
2026-06-25 01:48:07 +08:00
public Image img_Prop;
2026-06-26 17:26:10 +08:00
public string propID;
2026-07-25 01:32:54 +08:00
public string propName; // 当前选中道具名称(数量选择面板用)
2026-06-26 17:26:10 +08:00
public PropEnum propType;
2026-03-27 15:18:35 +08:00
public ScrollRect scrollRect;
2026-06-25 01:48:07 +08:00
public Button btn_Use;
2026-06-26 17:26:10 +08:00
2026-07-07 02:22:31 +08:00
[Header("改名")]//使用改名卡后,弹出输入框,输入新名字,点击确定按钮,发送请求修改名字
public GameObject changNamePanel;
public TMP_InputField tMPText_NewName;
public Button btn_ChangeName;
2026-07-09 14:29:17 +08:00
[Header("大喇叭")]//使用大喇叭后,弹出输入框,输入弹幕,点击确定按钮,发送请求
public GameObject DaLaBaPanel;
public TMP_InputField tMPText_DaLaBaLabel;
public Button btn_FaSong;
2026-07-25 01:11:49 +08:00
[Header("使用提示(带数量)")]
2026-07-25 01:32:54 +08:00
public GameObject useObj;
2026-07-25 01:11:49 +08:00
public Slider slider_UseNum;
public TextMeshProUGUI tMPText_ShiyongLabel;//确认使用道具 propname*<color=yellow>数量</color>
public Button btn_Add;
public Button btn_Subtract;
public Button btn_QueRen;
2026-07-09 14:29:17 +08:00
2026-07-25 01:32:54 +08:00
/// <summary>当前选中道具的拥有数量(用于数量选择面板上限)</summary>
private int _curPropOwnedCount;
/// <summary>当前选中数量选择面板对应道具的回调(确认使用时调用)</summary>
private System.Action<int> _curUseCountAction;
2026-06-26 17:26:10 +08:00
// 刷新时保存的状态
2026-07-06 03:04:08 +08:00
//private Vector2 savedScrollPos;
2026-06-26 17:26:10 +08:00
private string savedPropID;
2026-03-27 15:18:35 +08:00
public override void Awake()
2025-12-13 18:18:28 +08:00
{
2026-03-27 15:18:35 +08:00
base.Awake();
2026-06-26 17:26:10 +08:00
GameManager.Instance.OnUserDataChanged += OnUserDataChanged;
2026-07-07 02:22:31 +08:00
// 改名确认按钮
if (btn_ChangeName != null)
btn_ChangeName.onClick.AddListener(OnClickConfirmChangeName);
// 改名面板默认关闭
if (changNamePanel != null)
changNamePanel.SetActive(false);
2026-07-09 14:29:17 +08:00
// 大喇叭
if (DaLaBaPanel != null)
DaLaBaPanel.SetActive(false);
2026-10-10 08:59:44 +08:00
// 大喇叭正文限长:后端整条广播≤20字,标识占1字,输入框直接限制19字
if (tMPText_DaLaBaLabel != null)
tMPText_DaLaBaLabel.characterLimit = APIRequestList.BroadcastMaxContentLength;
2026-07-09 14:29:17 +08:00
if (btn_FaSong != null)
2026-10-08 17:04:24 +08:00
{
// ⭐ 先清再绑:防止面板重复 Show 叠加监听器(点一次发 N 次 = 多扣 N 个大喇叭)
btn_FaSong.onClick.RemoveAllListeners();
2026-07-09 14:29:17 +08:00
btn_FaSong.onClick.AddListener(OnClickFaSong);
2026-10-08 17:04:24 +08:00
}
2026-07-25 01:32:54 +08:00
// 数量选择面板(默认隐藏)
if (useObj != null) useObj.SetActive(false);
if (slider_UseNum != null)
slider_UseNum.onValueChanged.AddListener(v => UpdateUseNumLabel());
if (btn_Add != null)
btn_Add.onClick.AddListener(() =>
{
if (slider_UseNum != null)
slider_UseNum.value = Mathf.Min((int)slider_UseNum.value + 1, (int)slider_UseNum.maxValue);
});
if (btn_Subtract != null)
btn_Subtract.onClick.AddListener(() =>
{
if (slider_UseNum != null)
slider_UseNum.value = Mathf.Max((int)slider_UseNum.value - 1, (int)slider_UseNum.minValue);
});
if (btn_QueRen != null)
btn_QueRen.onClick.AddListener(OnClickConfirmUseNum);
}
/// <summary>刷新数量选择标签</summary>
private void UpdateUseNumLabel()
{
if (tMPText_ShiyongLabel == null) return;
int n = slider_UseNum != null ? Mathf.RoundToInt(slider_UseNum.value) : 1;
tMPText_ShiyongLabel.text = $"确认使用道具 <color=yellow>{propName}</color> * <color=yellow>{n}</color>";
}
/// <summary>确认使用按钮:执行当前数量回调</summary>
private void OnClickConfirmUseNum()
{
int n = slider_UseNum != null ? Mathf.RoundToInt(slider_UseNum.value) : 1;
if (n <= 0)
{
UIManager.Instance.ShowBoardError("数量必须大于0");
return;
}
var cb = _curUseCountAction;
HideUseNumPanel();
cb?.Invoke(n);
}
/// <summary>显示数量选择面板</summary>
/// <param name="ownedCount">当前拥有数量(滑块上限)</param>
/// <param name="onConfirm">确认使用回调(参数=使用数量)</param>
private void ShowUseNumPanel(int ownedCount, System.Action<int> onConfirm)
{
_curPropOwnedCount = ownedCount;
_curUseCountAction = onConfirm;
if (useObj != null) useObj.SetActive(true);
if (slider_UseNum != null)
{
slider_UseNum.minValue = 1;
slider_UseNum.maxValue = Mathf.Max(1, ownedCount);
slider_UseNum.value = 1;
slider_UseNum.wholeNumbers = true;
}
UpdateUseNumLabel();
}
/// <summary>隐藏数量选择面板</summary>
private void HideUseNumPanel()
{
if (useObj != null) useObj.SetActive(false);
_curUseCountAction = null;
2026-07-09 14:29:17 +08:00
}
2026-10-08 17:04:24 +08:00
/// <summary>大喇叭发送中标志:防止回调返回前连点发送按钮导致多发多扣道具</summary>
private bool _isSendingFaSong;
2026-10-10 07:52:12 +08:00
/// <summary>大喇叭发送超时协程:APIManager在code!=0时只弹错误不走成功回调,
/// 若只在成功回调复位标志,失败一次(如字数超限)后标志永久卡死,发送按钮失效</summary>
private Coroutine _faSongTimeoutRoutine;
/// <summary>发送超时秒数:超过后自动复位防重入标志,允许重试</summary>
private const float FaSongTimeoutSeconds = 3f;
2026-10-08 17:04:24 +08:00
2026-07-09 14:29:17 +08:00
private void OnClickFaSong()
{
2026-10-08 17:04:24 +08:00
// ⭐ 防重入:上次请求回调还没回来时连点直接忽略
if (_isSendingFaSong) return;
// ⭐ 先取文本判空再拼前缀(原"广播:"+text 判空永远不成立,空内容也会发送扣道具)
string content = tMPText_DaLaBaLabel?.text?.Trim();
if (string.IsNullOrEmpty(content))
2026-07-09 14:29:17 +08:00
{
UIManager.Instance.ShowBoardError("请输入广播内容");
return;
}
2026-10-10 08:59:44 +08:00
// ⭐ 后端整条广播限制20字,标识字符占1字,正文最多19字
if (content.Length > APIRequestList.BroadcastMaxContentLength)
{
UIManager.Instance.ShowBoardError($"广播内容不能超过{APIRequestList.BroadcastMaxContentLength}个字");
return;
}
2026-07-09 14:29:17 +08:00
2026-10-08 17:04:24 +08:00
_isSendingFaSong = true;
2026-10-10 07:52:12 +08:00
// ⭐ 超时兜底:后端拒绝(字数超限等)时没有回调,靠超时复位防重入标志
if (_faSongTimeoutRoutine != null) StopCoroutine(_faSongTimeoutRoutine);
_faSongTimeoutRoutine = StartCoroutine(ResetFaSongFlagAfterTimeout());
2026-10-10 08:59:44 +08:00
// ⭐ 只发"标识字符+正文":喇叭图标与打码昵称由接收端(LoginBroadcast)统一补上
APIRequestList.SendBroadcast(APIRequestList.BroadcastMarker + content, (result) =>
2026-07-09 14:29:17 +08:00
{
2026-10-10 07:52:12 +08:00
// 成功:停掉超时协程并复位标志
if (_faSongTimeoutRoutine != null)
{
StopCoroutine(_faSongTimeoutRoutine);
_faSongTimeoutRoutine = null;
}
2026-10-08 17:04:24 +08:00
_isSendingFaSong = false;
2026-07-09 14:29:17 +08:00
tMPText_DaLaBaLabel.text = "";
DaLaBaPanel.SetActive(false);
2026-10-08 17:04:24 +08:00
// ⭐ 发送成功=服务端已扣大喇叭:拉最新用户数据刷新背包数量
APIRequestList.GetUser((user) =>
{
if (user != null)
GameManager.Instance.UpdataUserData(user);
});
2026-07-09 14:29:17 +08:00
});
2026-07-07 02:22:31 +08:00
}
2026-10-10 07:52:12 +08:00
/// <summary>超时复位防重入标志:后端返回错误码时APIManager不走成功回调,靠此协程兜底解锁发送按钮</summary>
private IEnumerator ResetFaSongFlagAfterTimeout()
{
yield return new WaitForSeconds(FaSongTimeoutSeconds);
_isSendingFaSong = false;
_faSongTimeoutRoutine = null;
}
2026-07-07 02:22:31 +08:00
private void OnClickConfirmChangeName()
{
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 = "";
changNamePanel.SetActive(false);
2026-07-23 01:51:07 +08:00
// 拉取服务器最新用户数据,同步本地并触发全局 UI 更新
APIRequestList.GetUser((user) =>
{
if (user != null)
GameManager.Instance.UpdataUserData(user);
});
2026-07-10 00:46:23 +08:00
});
2026-07-07 02:22:31 +08:00
});
2025-12-13 18:18:28 +08:00
}
2026-06-26 17:26:10 +08:00
2026-10-07 23:05:51 +08:00
private void OnDestroy()
{
// 兜底:防止面板被销毁后仍留在事件里(否则之后任何 UpdataUserData 都会调到已销毁的面板,
// 抛 MissingReferenceException 并中断整个事件链,导致其他面板的用户数据无法刷新)
if (GameManager.Instance != null)
GameManager.Instance.OnUserDataChanged -= OnUserDataChanged;
}
2026-06-26 17:26:10 +08:00
private void OnUserDataChanged()
{
// 刷新前保存状态
2026-07-06 03:04:08 +08:00
//if (scrollRect != null) savedScrollPos = scrollRect.normalizedPosition;
2026-06-26 17:26:10 +08:00
savedPropID = propID;
RefreshUI();
RebuildPropsList();
// 刷新后恢复状态
2026-07-06 03:04:08 +08:00
//if (scrollRect != null) scrollRect.normalizedPosition = savedScrollPos;
2026-06-26 17:26:10 +08:00
}
2026-03-27 15:18:35 +08:00
protected override void OnShow(object args = null)
2025-12-13 18:18:28 +08:00
{
2026-03-27 15:18:35 +08:00
base.OnShow(args);
2026-06-26 17:26:10 +08:00
RefreshUI();
RebuildPropsList();
}
2026-04-17 18:30:51 +08:00
2026-06-26 17:26:10 +08:00
private void RefreshUI()
{
if (GameManager.Instance?.user?.assets == null) return;
tMP_Gold.text = GameManager.Instance.user.assets.gold.ToString();
tMP_Diamond.text = GameManager.Instance.user.assets.diamond.ToString();
}
private void RebuildPropsList()
{
props = GameManager.Instance.user.props;
// 构建字典,过滤数量 ≤0 的
propsID_Dic.Clear();
if (props != null)
{
foreach (BaseProductCount product in props)
{
if (product.count > 0)
propsID_Dic[product.number] = product;
2026-03-27 15:18:35 +08:00
}
}
2026-06-25 01:48:07 +08:00
2026-06-26 17:26:10 +08:00
// 清空旧列表
for (int j = pageParent.childCount - 1; j >= 0; j--)
Destroy(pageParent.GetChild(j).gameObject);
propsObjHashCode_Dic.Clear();
2026-07-25 21:04:58 +08:00
Toggle firstToggle = null;
Toggle savedToggle = null;
2026-03-27 15:18:35 +08:00
foreach (BaseProductCount product in propsID_Dic.Values)
{
2026-06-25 01:48:07 +08:00
GameObject obj = Instantiate(prefabItem.gameObject, pageParent);
var tempItem = obj.GetComponent<BackPackPropItem>();
2026-07-09 19:35:25 +08:00
tempItem.Init(new BackPackPropItemData
{
url = APIManager.baseURL + product.imageUrl,
count = product.count,
propEnum = (PropEnum)product.type
});
2026-06-25 01:48:07 +08:00
2026-07-25 21:04:58 +08:00
var toggle = obj.GetComponent<Toggle>();
2026-06-26 17:26:10 +08:00
propsObjHashCode_Dic[obj.GetHashCode()] = product;
2026-07-25 21:04:58 +08:00
if (firstToggle == null) firstToggle = toggle;
if (!string.IsNullOrEmpty(savedPropID) && product.number == savedPropID)
savedToggle = toggle;
2026-03-27 15:18:35 +08:00
obj.GetComponent<Toggle>().onValueChanged.AddListener((value) =>
{
2026-06-26 17:26:10 +08:00
if (value) ShowPropDetail(product);
2026-03-27 15:18:35 +08:00
});
}
2026-06-27 21:12:04 +08:00
2026-07-25 21:04:58 +08:00
// 优先选中刷新前的道具;若已用完则选中第一个
var target = savedToggle ?? firstToggle;
if (target != null) target.isOn = true;
2026-06-26 17:26:10 +08:00
}
2026-03-27 15:18:35 +08:00
2026-06-26 17:26:10 +08:00
private void ShowPropDetail(BaseProductCount product)
{
if (product == null) return;
tMP_Name.text = product.name;
tMP_Description.text = product.desc;
propID = product.number;
2026-07-25 01:32:54 +08:00
propName = product.name;
2026-06-26 17:26:10 +08:00
propType = (PropEnum)product.type;
WebTool.DownImage(APIManager.baseURL + product.imageUrl, (texture) =>
{
if (texture != null && img_Prop != null)
img_Prop.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.one * 0.5f);
});
btn_Use.onClick.RemoveAllListeners();
btn_Use.onClick.AddListener(() =>
{
switch (propType)
{
case PropEnum.none: break;
case PropEnum.炮塔碎片: break;
case PropEnum.翅膀碎片: break;
case PropEnum.战神碎片: break;
case PropEnum.刮刮卡:
uIManager.ShowAsync(UIPanel.GuaGuaKa);
break;
2026-07-07 02:22:31 +08:00
case PropEnum.改名卡:
if (changNamePanel != null)
changNamePanel.SetActive(true);
break;
2026-07-09 14:29:17 +08:00
case PropEnum.大喇叭:
if (DaLaBaPanel != null)
DaLaBaPanel.SetActive(true);
break;
2026-06-26 17:26:10 +08:00
case PropEnum.技能: break;
case PropEnum.召唤卡: break;
2026-07-16 20:16:05 +08:00
case PropEnum.VIP经验:
2026-07-25 01:32:54 +08:00
// 数量选择面板:滑块上限=当前拥有数量
ShowUseNumPanel(product.count, n =>
2026-07-16 20:16:05 +08:00
{
2026-07-25 01:32:54 +08:00
APIRequestList.UseVipExp(n, (result) =>
2026-07-16 20:16:05 +08:00
{
UIManager.Instance.ShowBoardError("使用成功");
APIRequestList.GetUser(GameManager.Instance.user.id, (user) =>
{
GameManager.Instance.UpdataUserData(user);
});
});
});
break;
2026-06-26 17:26:10 +08:00
default: break;
}
});
2025-12-13 18:18:28 +08:00
}
}