using Assets.Framework.Tool; using Assets.MyGame.Scripts.Net; using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass; using Assets.MyGame.Scripts.Net.APIRequest.Objs; using Assets.MyGame.Scripts.Net.APIRequest.Params; using Assets.MyGame.Scripts.Net.APIResponses; using System.Collections.Generic; using System.Linq; using TMPro; using UnityEngine; using UnityEngine.UI; public class ZhanLing_Panel : SubUIBase { public Toggle toggle_MoRenShowZhnaLingJiangLi; [Header("战令等级奖励页面")] public TextMeshProUGUI tmp_Level; public TextMeshProUGUI tmp_Exp; public Slider slider_LevelExp; public LevelGiftitem levelGiftitemPrefab; public Transform levelGiftitemParent; public LevelGiftitem levelGiftitem_100; public Button btn_GetAllGift; public Button btn_BuyJinJieZhanLing; public TextMeshProUGUI btn_BuyZhanLing_Label; public TextMeshProUGUI tmp_ActiveTime; //战令刷新时间 30天10:01:50 [Header("任务页面")] public RenWuItem renWuItemPrefab; public Transform renWuItemParent; [Header("购买等级礼包页面")] public BackPackPropItem buyLevelGiftitemPrefab; public Transform buyLevelGiftitemMianFeiParent; public Transform buyLevelGiftitemJingYingParent; public Transform buyLevelGiftitemZhiZunParent; public Slider slider_BuyLevelExpCount; public Button btn_Buy; public TextMeshProUGUI tmp_PriceNum; public TextMeshProUGUI tmp_BuyLabel; //购买 99999 点经验值升至 100 级 [Header("活动切换项")] public GameObject huoDongToggleItemPrefab; public Transform huoDongToggleItemParent; [Header("购买进阶战令页面")] public Button btn_JinJie; public Button btn_ZhiZun; public Button btn_ZhiZunAndJinJie; private BattleOrderConfigInfo _config; private UserBattleOrderInfo _userData; private int _selectedBuyLevel; private List _buyLevelConfigs; // 含 payType/payCount public Toggle toggle_HD; public Toggle toggle_GG; // ==================== 生命周期 ==================== public override void Awake() { base.Awake(); btn_CloseGG.onClick.AddListener(() => uIManager.Hide(this)); } protected override void OnShow(object args = null) { base.OnShow(args); RefreshAll(); LoadNoticeList(); switch (PanelType) { case UIPanel.ActivityPenel: toggle_HD.isOn = true; toggle_MoRenShowZhnaLingJiangLi.isOn = true; break; case UIPanel.AnnouncementPanel: toggle_GG.isOn = true; break; } } private void RefreshAll() { APIRequestList.GetBattleOrder(res => { if (res == null || !res.isOpen) return; _config = res.config; _userData = res.userBattleOrder; RefreshLevelPage(); RefreshTasksPage(); RefreshBuyPage(); RefreshBtnLabels(); }); APIRequestList.GetBattleOrderConfig(cfg => { if (cfg != null) _buyLevelConfigs = cfg.levelConfig; }); } // ==================== 等级奖励页面 ==================== private int _maxLevel = 100; private void RefreshLevelPage() { if (_config?.levelConfig == null || _userData == null) return; int level = _userData.level; int exp = _userData.exp; var lvCfg = _config.levelConfig.Find(c => c.level == level); int expNeeded = lvCfg?.exp ?? 100; tmp_Level.text = $"Lv.{level}"; tmp_Exp.text = $"{exp}/{expNeeded}"; slider_LevelExp.maxValue = expNeeded; slider_LevelExp.value = Mathf.Clamp(exp, 0, expNeeded); // 战令剩余时间 RefreshActiveTime(); // 清空旧列表 for (int i = levelGiftitemParent.childCount - 1; i >= 0; i--) Destroy(levelGiftitemParent.GetChild(i).gameObject); // 已领取的等级集合 var claimedSet = _userData.receivedLevels != null ? new HashSet(_userData.receivedLevels) : new HashSet(); // 构建等级礼包列表(1-99级显示礼包内容,100级占位) foreach (var lv in _config.levelConfig) { if (lv.level > _maxLevel) continue; if (lv.level == _maxLevel) { // 100级占位:创建一个空对象保持布局对齐 var placeholder = new GameObject("Placeholder_Lv100", typeof(RectTransform)); placeholder.transform.SetParent(levelGiftitemParent, false); var rt = placeholder.GetComponent(); var prefabRt = levelGiftitemPrefab.GetComponent(); if (rt != null && prefabRt != null) { rt.sizeDelta = prefabRt.sizeDelta; rt.anchorMin = prefabRt.anchorMin; rt.anchorMax = prefabRt.anchorMax; rt.pivot = prefabRt.pivot; } // 如果 prefab 有 LayoutElement,也复制 var prefabLE = levelGiftitemPrefab.GetComponent(); if (prefabLE != null) { var le = placeholder.AddComponent(); le.preferredWidth = prefabLE.preferredWidth; le.preferredHeight = prefabLE.preferredHeight; le.minWidth = prefabLE.minWidth; le.minHeight = prefabLE.minHeight; } continue; } var item = Instantiate(levelGiftitemPrefab, levelGiftitemParent); item.gameObject.SetActive(true); bool isClaimed = claimedSet.Contains(lv.level); var nf = FirstGift(lv.normalGiftList); var lx = FirstGift(lv.luxuryGiftList); var sz = FirstGift(lv.supremeGiftList); LevelGiftType giftType = 0; if (nf != null) giftType |= LevelGiftType.MianFei; if (lx != null && _userData.isLuxury) giftType |= LevelGiftType.JingYing; if (sz != null && _userData.isSupreme) giftType |= LevelGiftType.ZhiZun; item.Init( nf?.product?.imageUrl ?? "", nf?.count ?? 0, lx?.product?.imageUrl ?? "", lx?.count ?? 0, sz?.product?.imageUrl ?? "", sz?.count ?? 0, lv.level, giftType, isClaimed, nf?.type ?? 0, lx?.type ?? 0, sz?.type ?? 0); } // 100级礼包 var lv100 = _config.levelConfig.Find(c => c.level == _maxLevel); if (lv100 != null && levelGiftitem_100 != null) { bool isClaimed = claimedSet.Contains(_maxLevel); var nf100 = FirstGift(lv100.normalGiftList); var lx100 = FirstGift(lv100.luxuryGiftList); var sz100 = FirstGift(lv100.supremeGiftList); LevelGiftType giftType100 = LevelGiftType.MianFei; if (lx100 != null && _userData.isLuxury) giftType100 |= LevelGiftType.JingYing; if (sz100 != null && _userData.isSupreme) giftType100 |= LevelGiftType.ZhiZun; levelGiftitem_100.Init( nf100?.product?.imageUrl ?? "", nf100?.count ?? 0, lx100?.product?.imageUrl ?? "", lx100?.count ?? 0, sz100?.product?.imageUrl ?? "", sz100?.count ?? 0, _maxLevel, giftType100, isClaimed, nf100?.type ?? 0, lx100?.type ?? 0, sz100?.type ?? 0); levelGiftitem_100.gameObject.SetActive(true); } } // ==================== 任务页面 ==================== private void RefreshTasksPage() { if (renWuItemPrefab == null || renWuItemParent == null) return; for (int i = renWuItemParent.childCount - 1; i >= 0; i--) Destroy(renWuItemParent.GetChild(i).gameObject); APIRequestList.GetUserTaskList(tasks => { if (tasks == null) return; foreach (var t in tasks) { int curr = (int)t.count; float progress = t.taskCount > 0 ? (float)t.count / t.taskCount : 0f; CreateTaskItem(t.exp, curr, t.taskCount, t.remark, progress, UIPanel.None); } }); } private void CreateTaskItem(int expCount, int currJinDu, int maxJinDu, string label, float progress, UIPanel targetPanel) { var item = Instantiate(renWuItemPrefab, renWuItemParent); item.gameObject.SetActive(true); item.Init(expCount, currJinDu, maxJinDu, label, progress, targetPanel, uIManager); } // ==================== 购买等级页面 ==================== private void RefreshBuyPage() { if (_config?.levelConfig == null) return; slider_BuyLevelExpCount.minValue = 1; slider_BuyLevelExpCount.maxValue = _maxLevel; slider_BuyLevelExpCount.value = _userData.level; slider_BuyLevelExpCount.wholeNumbers = true; slider_BuyLevelExpCount.onValueChanged.RemoveAllListeners(); slider_BuyLevelExpCount.onValueChanged.AddListener(OnBuyLevelSliderChanged); _selectedBuyLevel = _userData.level; UpdateBuyLevelGifts(_selectedBuyLevel); UpdateBuyPrice(); } private void OnBuyLevelSliderChanged(float value) { _selectedBuyLevel = Mathf.RoundToInt(value); UpdateBuyLevelGifts(_selectedBuyLevel); UpdateBuyPrice(); } private void UpdateBuyLevelGifts(int level) { ClearBuyGiftParent(buyLevelGiftitemMianFeiParent); ClearBuyGiftParent(buyLevelGiftitemJingYingParent); ClearBuyGiftParent(buyLevelGiftitemZhiZunParent); var cfg = _config?.levelConfig?.Find(c => c.level == level); if (cfg == null) return; AddBuyGiftList(buyLevelGiftitemMianFeiParent, cfg.normalGiftList); AddBuyGiftList(buyLevelGiftitemJingYingParent, cfg.luxuryGiftList); AddBuyGiftList(buyLevelGiftitemZhiZunParent, cfg.supremeGiftList); } private void ClearBuyGiftParent(Transform parent) { if (parent == null) return; for (int i = parent.childCount - 1; i >= 0; i--) Destroy(parent.GetChild(i).gameObject); } private void AddBuyGiftList(Transform parent, List gifts) { if (parent == null || gifts == null) return; foreach (var gift in gifts) { var obj = Instantiate(buyLevelGiftitemPrefab, parent); string url = !string.IsNullOrEmpty(gift.product?.imageUrl) ? APIManager.baseURL + gift.product.imageUrl : ""; int type = gift.type; PropEnum pe = type switch { 3 => (PropEnum)(gift.product?.type ?? 0), _ => PropEnum.none }; int count = gift.isRandom ? gift.minCount : gift.count; obj.Init(url, count, pe); } } private void UpdateBuyPrice() { int levelsToBuy = _selectedBuyLevel - _userData.level; if (levelsToBuy <= 0) { tmp_PriceNum.text = "已达成"; if (tmp_BuyLabel != null) tmp_BuyLabel.text = ""; btn_Buy.interactable = false; } else { // 计算从当前等级到目标等级所需总经验和总花费 int totalExp = 0; int totalCost = 0; int costPayType = 2; // 默认钻石 if (_buyLevelConfigs != null) { for (int lv = _userData.level + 1; lv <= _selectedBuyLevel; lv++) { var cfg = _buyLevelConfigs.Find(c => c.level == lv); if (cfg != null) { totalExp += cfg.exp; totalCost += cfg.payCount; if (cfg.payType > 0) costPayType = cfg.payType; } } } tmp_PriceNum.text = costPayType switch { 1 => $"{totalCost}", 3 => $"¥{totalCost}", _ => $"{totalCost}", }; if (tmp_BuyLabel != null) tmp_BuyLabel.text = $"购买 {totalExp} 点经验值升至 {_selectedBuyLevel} 级"; btn_Buy.interactable = true; } } // ==================== 按钮事件 ==================== private void RefreshBtnLabels() { if (btn_BuyZhanLing_Label != null) { btn_BuyZhanLing_Label.text = (_userData.isLuxury || _userData.isSupreme) ? "已购买" : "购买战令"; } btn_GetAllGift.onClick.RemoveAllListeners(); btn_GetAllGift.onClick.AddListener(() => { APIRequestList.ReceiveAllBattleOrderRewards(res => { // 立即标记当前可达等级为已领取 if (_userData.receivedLevels == null) _userData.receivedLevels = new List(); for (int lv = 1; lv <= _userData.level; lv++) { if (!_userData.receivedLevels.Contains(lv)) _userData.receivedLevels.Add(lv); } RefreshAll(); }); }); btn_Buy.onClick.RemoveAllListeners(); btn_Buy.onClick.AddListener(() => { int levelsToBuy = _selectedBuyLevel - _userData.level; if (levelsToBuy <= 0) return; APIRequestList.BuyBattleOrderLevel(new BuyBattleOrderLevelParam { levelCount = levelsToBuy }, res => { Debug.Log($"[ZhanLing] 购买等级完成: 新等级={res.newLevel}, 花费={res.cost}"); RefreshAll(); }); }); btn_JinJie.onClick.RemoveAllListeners(); btn_JinJie.onClick.AddListener(() => BuyAdvance(1)); btn_ZhiZun.onClick.RemoveAllListeners(); btn_ZhiZun.onClick.AddListener(() => BuyAdvance(2)); btn_ZhiZunAndJinJie.onClick.RemoveAllListeners(); btn_ZhiZunAndJinJie.onClick.AddListener(() => BuyAdvance(3)); // 三个按钮的 child(0) 显示购买价格 RefreshAdvanceBtnLabels(); } private void RefreshAdvanceBtnLabels() { if (_config?.advanceGift == null) return; var jinJie = _config.advanceGift.Find(a => a.type == 1); var zhiZun = _config.advanceGift.Find(a => a.type == 2); var all = _config.advanceGift.Find(a => a.type == 3); SetBtnPrice(btn_JinJie, jinJie, _userData.isLuxury); SetBtnPrice(btn_ZhiZun, zhiZun, _userData.isSupreme); SetBtnPrice(btn_ZhiZunAndJinJie, all, _userData.isLuxury && _userData.isSupreme); } private void SetBtnPrice(Button btn, BattleOrderAdvanceInfo info, bool isBought) { if (btn == null || info == null) return; // 已购买则显示"已购买",否则显示价格 if (isBought) { var label = btn.transform.childCount > 0 ? btn.transform.GetChild(0).GetComponent() : null; if (label != null) label.text = "已购买"; } else { SetBtnText(btn, info.payType, info.payCount); } } private void SetBtnText(Button btn, int payType, int price) { if (btn == null) return; var label = btn.transform.childCount > 0 ? btn.transform.GetChild(0).GetComponent() : null; if (label == null) return; label.text = payType switch { 1 => $"{price}", 2 => $"{price}", _ => $"¥{price}", }; } private void BuyAdvance(int type) { APIRequestList.BuyBattleOrderAdvance(new BuyBattleOrderAdvanceParam { type = type }, res => { // 立即更新本地状态,避免服务器延迟导致锁不消失 if (type == 1 || type == 3) _userData.isLuxury = true; if (type == 2 || type == 3) _userData.isSupreme = true; RefreshAll(); }); } // ==================== 工具 ==================== /// 取礼物列表第一项(列表为空返回 null) private static GiftConfig FirstGift(List list) { return (list != null && list.Count > 0) ? list[0] : null; } /// HTML 转 TextMeshPro 兼容格式 private static string HtmlToTMP(string html) { if (string.IsNullOrEmpty(html)) return html; string result = html; //
/
→
result = System.Text.RegularExpressions.Regex.Replace(result, @"", "
"); //

→ 去标签,末尾加换行 result = System.Text.RegularExpressions.Regex.Replace(result, @"

", "\n"); result = System.Text.RegularExpressions.Regex.Replace(result, @"]*>", ""); // \n 转义 result = result.Replace("\\n", "\n"); //
result = System.Text.RegularExpressions.Regex.Replace(result, @"", "\n"); result = System.Text.RegularExpressions.Regex.Replace(result, @"]*>", ""); // → 去掉标签保留内容(TMP 不支持动态切换字体) result = System.Text.RegularExpressions.Regex.Replace(result, @"", ""); result = System.Text.RegularExpressions.Regex.Replace(result, @"]*>", ""); // → 去标签保留内容 result = System.Text.RegularExpressions.Regex.Replace(result, @"]*>", ""); //   result = result.Replace(" ", " "); // 多余空行 result = System.Text.RegularExpressions.Regex.Replace(result, @"\n{3,}", "\n\n"); return result; } /// 刷新战令剩余时间(格式:30天10:01:50) private void RefreshActiveTime() { if (tmp_ActiveTime == null || _config == null) return; long now = BeijingTimeManager.Instance.CurrentTimestampMs / 1000; long remain = _config.endTime - now; if (remain <= 0) { tmp_ActiveTime.text = "已结束"; return; } int days = (int)(remain / 86400); int hours = (int)((remain % 86400) / 3600); int mins = (int)((remain % 3600) / 60); int secs = (int)(remain % 60); tmp_ActiveTime.text = $"{days}天{hours:D2}:{mins:D2}:{secs:D2}"; } [Header("公告")] public Button btn_CloseGG; //------------公告------------------ public AnnouncementItem announcementItemPrefab; public Transform announcementItemParent; public TextMeshProUGUI tmp_TitleLabel; public TextMeshProUGUI tmp_Content; public Image img_TopImg; private List noticeList; private void LoadNoticeList() { APIRequestList.GetNoticeList(new NoticeListObj { keyWord = "", pageIndex = 0, pageSize = 50 }, list => { if (list == null) return; noticeList = list; // 清除旧列表 for (int i = announcementItemParent.childCount - 1; i >= 0; i--) Destroy(announcementItemParent.GetChild(i).gameObject); foreach (var item in list) { var obj = Instantiate(announcementItemPrefab.gameObject, announcementItemParent); var tempItem = obj.GetComponent(); tempItem.Init(item.title, item.createTime); tempItem.tMP_Header.text = item.title; string noticeId = item.id; obj.GetComponent().onValueChanged.RemoveAllListeners(); obj.GetComponent().onValueChanged.AddListener((isOn) => { if (isOn) OnNoticeClick(noticeId); }); } // 默认选中第一条公告 if (list.Count > 0) { var firstToggle = announcementItemParent.GetChild(0).GetComponent(); firstToggle.isOn = true; OnNoticeClick(list[0].id); } }); } private void OnNoticeClick(string noticeId) { APIRequestList.GetNotice(new NoticeIdParam { id = noticeId }, notice => { if (notice == null) return; if (tmp_TitleLabel != null) tmp_TitleLabel.text = notice.title; if (tmp_Content != null) tmp_Content.text = HtmlToTMP(notice.content); // 加载顶部图片 if (img_TopImg != null && !string.IsNullOrEmpty(notice.topImage)) { WebTool.DownImage(APIManager.baseURL + notice.topImage, texture => { if (texture != null && img_TopImg != null) img_TopImg.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.one * 0.5f); }); } }); } }