lcy
2025-12-08 e44283cd0ae9234f05b3300dd13e0b8c11cde122
348 【配套功能】功能预告-客户端
5个文件已修改
5个文件已添加
330 ■■■■ 已修改文件
Main/Component/UI/Common/FuncOpen.cs 179 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FuncOpenLVConfig.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FunctionPreview.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FunctionPreview/FunctionPreviewCell.cs 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FunctionPreview/FunctionPreviewCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FunctionPreview/FunctionPreviewWin.cs 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FunctionPreview/FunctionPreviewWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Main/RightFuncInHome.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Redpoint/MainRedDot.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/EnumHelper.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Common/FuncOpen.cs
@@ -1,8 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LitJson;
using System.Linq;
public class FuncOpen
{
@@ -109,6 +109,10 @@
                funcOpenState[funcState.FuncID] = funcState.State == 1;
                bAfterFuncIsOpen = funcOpenState[funcState.FuncID];
            }
            awardStateDict[funcState.FuncID] = funcState.AwardState == 1;
            UpdatePreviewRedpoint();
            if (OnFuncStateChangeEvent != null)
            {
                OnFuncStateChangeEvent(funcState.FuncID);
@@ -225,48 +229,6 @@
        }
    }
    public string GetErrorTip(int key)
    {
        if (!FuncOpenLVConfig.HasKey(key))
            return string.Empty;
        FuncOpenLVConfig config = FuncOpenLVConfig.Get(key);
        if (!IsFuncOpen(key, out int errorCode))
        {
            switch (errorCode)
            {
                case 1:
                    return Language.Get("FuncLimit_Level", config.LimitLV);
                case 2:
                    //开服多少天 一般是组合
                    if (config.LimitLV != 0)
                    {
                        return Language.Get("FuncLimit_OpenDay_LV", config.LimitLV, TimeUtility.OpenDay + 1, config.OpenDay);
                    }
                    else if (config.LimitMissionID != 0)
                    {
                        return Language.Get("FuncLimit_OpenDay_Mission", TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID), TimeUtility.OpenDay + 1, config.OpenDay);
                    }
                    else if (config.LimiRealmLV != 0)
                    {
                        return Language.Get("FuncLimit_OpenDay_Realm", RealmConfig.Get(config.LimiRealmLV).Name, TimeUtility.OpenDay + 1, config.OpenDay);
                    }
                    else
                    {
                        return Language.Get("FuncLimit_OpenDay", config.OpenDay);
                    }
                case 3:
                    return Language.Get("FuncLimit_Realm", RealmConfig.Get(config.LimiRealmLV).Name);
                case 4:
                    return Language.Get("FuncLimit_Mission", TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID));
                case 5:
                    return Language.Get("FuncLimit_ManLevel", config.ManLevel/10000, config.ManLevel/100%100, config.ManLevel%100);
            }
        }
        return string.Empty;
    }
    public int GetLimitLv(int key)
    {
        // FuncOpenLVConfig tagFuncOpenLVModel = FuncOpenLVConfig.Get(key);
@@ -300,6 +262,137 @@
        }
        return true;
    }
    #region 功能预告
    Dictionary<int, bool> awardStateDict = new Dictionary<int, bool>();
    Dictionary<int, int> funcIndexDict = new Dictionary<int, int>();
    public Dictionary<int, int> GetFuncIndexDict()
    {
        if (funcIndexDict.IsNullOrEmpty())
        {
            foreach (var funcId in FuncOpenLVConfig.GetKeys())
            {
                FuncOpenLVConfig config = FuncOpenLVConfig.Get(funcId);
                if (config.PreviewIndex > 0)
                {
                    funcIndexDict[config.FuncId] = config.PreviewIndex;
                }
            }
        }
        return funcIndexDict;
    }
    public List<int> GetSortShowList()
    {
        List<int> sortShowList = new List<int>();
        Dictionary<int, int> indexDict = GetFuncIndexDict();
        // 按状态优先级排序:状态1(可领取)> 状态0(未解锁)> 状态2(已领取)
        // 每种状态内按 PreviewIndex 升序,相同则按 FuncId 升序
        sortShowList = indexDict
            .Select(kv => new { FuncId = kv.Key, PreviewIndex = kv.Value, State = GetState(kv.Key) })
                .OrderBy(x => x.State == 1 ? 0 : (x.State == 0 ? 1 : 2)) // 映射优先级:1→0, 0→1, 2→2
                .ThenBy(x => x.PreviewIndex)
                .ThenBy(x => x.FuncId)
                .Select(x => x.FuncId)
                .ToList();
        return sortShowList;
    }
    //第一个可领取的物品所在行索引
    public bool TryGetJumpIndex(out int index)
    {
        index = 0;
        List<int> list = GetSortShowList();
        if (list.IsNullOrEmpty())
            return false;
        for (int i = 0; i < list.Count; i++)
        {
            if (GetState(list[i]) == 1)
            {
                index = i;
                return true;
            }
        }
        return false;
    }
    private bool IsAwardHave(int funcId)
    {
        return !awardStateDict.TryGetValue(funcId, out bool state) ? false : state;
    }
    // 0-未解锁 1-可领取 2-已领取
    public int GetState(int funcId)
    {
        if (IsAwardHave(funcId))
            return 2;
        return IsFuncOpen(funcId) ? 1 : 0;
    }
    public string GetErrorStr(int funcId)
    {
        if (!FuncOpenLVConfig.HasKey(funcId))
            return string.Empty;
        FuncOpenLVConfig config = FuncOpenLVConfig.Get(funcId);
        List<string> conditionStrs = new List<string>();
        if (config.LimitLV > 0)
        {
            conditionStrs.Add(Language.Get("FunctionPreviewErr01", config.LimitLV));
        }
        if (config.LimiRealmLV > 0)
        {
            conditionStrs.Add(Language.Get("FunctionPreviewErr02", RealmConfig.Get(config.LimiRealmLV).Name));
        }
        if (config.LimitMissionID > 0)
        {
            conditionStrs.Add(Language.Get("FunctionPreviewErr03", TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID)));
        }
        if (config.OpenDay > 0)
        {
            conditionStrs.Add(Language.Get("FunctionPreviewErr04", config.OpenDay));
        }
        if (config.ManLevel > 0)
        {
            conditionStrs.Add(Language.Get("FunctionPreviewErr05", config.ManLevel / 10000, config.ManLevel / 100 % 100, config.ManLevel % 100));
        }
        if (conditionStrs.Count == 0)
        {
            return string.Empty;
        }
        string connector = Language.Get("FunctionPreview01"); // "且"
        string unlockStr = Language.Get("FunctionPreview02"); // "解锁"
        string result = string.Join(connector, conditionStrs) + unlockStr;
        return result;
    }
    public void SendGetAward(int funcId)
    {
        var pack = new CA504_tagCMPlayerGetReward();
        pack.RewardType = 17;
        pack.DataEx = (uint)funcId;
        GameNetSystem.Instance.SendInfo(pack);
    }
    Redpoint redpoint = new Redpoint(MainRedDot.RightFuncRedpoint, MainRedDot.FunctionPreviewRepoint);
    public void UpdatePreviewRedpoint()
    {
        redpoint.state = RedPointState.None;
        if (!TryGetJumpIndex(out int index))
            return;
        redpoint.state = RedPointState.Simple;
    }
    #endregion
}
public interface ICheckFuncOpen
Main/Config/Configs/FuncOpenLVConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Thursday, November 27, 2025
//    [  Date ]:           2025年12月8日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -25,7 +25,8 @@
    public string Name;
    public string Desc;
    public string Icon;
    public Dictionary<int, int[][]> Award;
    public int PreviewIndex;
    public int[][] AwardList;
    public override int LoadKey(string _key)
    {
@@ -55,7 +56,9 @@
            Icon = tables[8];
            Award = ConfigParse.ParseIntArray2Dict(tables[9].Replace("(", "[").Replace(")", "]"));
            int.TryParse(tables[9],out PreviewIndex);
            AwardList = JsonMapper.ToObject<int[][]>(tables[10].Replace("(", "[").Replace(")", "]"));
        }
        catch (Exception exception)
        {
Main/System/FunctionPreview.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e7acf37249ff26f4f85a11d0e3e8f65a
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/FunctionPreview/FunctionPreviewCell.cs
New file
@@ -0,0 +1,53 @@
using UnityEngine;
public class FunctionPreviewCell : MonoBehaviour
{
    [SerializeField] ImageEx imgIcon;
    [SerializeField] TextEx txtName;
    [SerializeField] TextEx txtDesc;
    [SerializeField] ItemCell itemCell;
    [SerializeField] Transform transItemCellMask;
    [SerializeField] ImageEx imgRed;
    [SerializeField] Transform transOpenInfo;
    [SerializeField] RichText txtOpenInfo;
    [SerializeField] Transform transMask;
    public void Display(int index, CellView cell)
    {
        int funcId = cell.info.Value.infoInt1;
        if (!FuncOpenLVConfig.HasKey(funcId))
            return;
        FuncOpenLVConfig config = FuncOpenLVConfig.Get(funcId);
        // 0-未解锁 1-可领取 2-已领取
        int state = FuncOpen.Instance.GetState(funcId);
        imgRed.SetActive(state == 1);
        transOpenInfo.SetActive(state == 0);
        transMask.SetActive(state != 1);
        transItemCellMask.SetActive(state == 2);
        imgIcon.SetSprite(config.Icon);
        imgIcon.SetNativeSize();
        txtName.text = config.Name;
        txtDesc.text = config.Desc;
        int[][] awardList = config.AwardList;
        itemCell.SetActive(!awardList.IsNullOrEmpty() && state != 0);
        if (!awardList.IsNullOrEmpty())
        {
            itemCell.Init(new ItemCellModel(awardList[0][0], true, awardList[0][1]));
            itemCell.button.SetListener(() =>
            {
                if (state == 1)
                {
                    FuncOpen.Instance.SendGetAward(funcId);
                }
                else
                {
                    ItemTipUtility.Show(awardList[0][0]);
                }
            });
        }
        txtOpenInfo.text = FuncOpen.Instance.GetErrorStr(funcId);
    }
}
Main/System/FunctionPreview/FunctionPreviewCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 807ec470632e30e4fbebaad0c81ba631
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/FunctionPreview/FunctionPreviewWin.cs
New file
@@ -0,0 +1,48 @@
using UnityEngine;
public class FunctionPreviewWin : UIBase
{
    [SerializeField] ScrollerController scroller;
    protected override void OnPreOpen()
    {
        scroller.lockType = EnhanceLockType.KeepVertical;
        scroller.OnRefreshCell += OnRefreshCell;
        FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
        CreateScoller();
    }
    protected override void OnPreClose()
    {
        scroller.OnRefreshCell -= OnRefreshCell;
        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
    }
    private void OnFuncStateChangeEvent(int obj)
    {
        CreateScoller();
    }
    private void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell.GetComponent<FunctionPreviewCell>();
        _cell?.Display(cell.index, cell);
    }
    private void CreateScoller()
    {
        scroller.Refresh();
        var list = FuncOpen.Instance.GetSortShowList();
        if (!list.IsNullOrEmpty())
        {
            for (int i = 0; i < list.Count; i++)
            {
                CellInfo info = new CellInfo();
                info.infoInt1 = list[i];
                scroller.AddCell(ScrollerDataType.Header, i, info);
            }
        }
        scroller.Restart();
    }
}
Main/System/FunctionPreview/FunctionPreviewWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e7c6142d362c8194c9cbe93b1d76f904
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Main/RightFuncInHome.cs
@@ -17,6 +17,7 @@
    [SerializeField] Button battlePassBtn;
    [SerializeField] Button llmjBtn; //历练秘笈
    [SerializeField] Button signBtn;
    [SerializeField] Button previewBtn;
    static string listenWindowName = "";   //监听关闭时再显示
@@ -79,6 +80,13 @@
            ListenWindow("SignWin");
            UIManager.Instance.OpenWindow<SignWin>();
        });
        previewBtn.AddListener(() =>
        {
            //用于监听界面,打开时缩进右边功能栏,关闭时显示
            ListenWindow("FunctionPreviewWin");
            UIManager.Instance.OpenWindow<FunctionPreviewWin>();
        });
    }
    void ShowBtns()
@@ -89,6 +97,7 @@
        llmjBtn.SetActive(FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.LLMJ));
        signBtn.SetActive(FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.DaySign));
        monthCardBtn.SetActive(FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.PrivilegeCard));
        previewBtn.SetActive(FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.FunctionPreview));
    }
Main/System/Redpoint/MainRedDot.cs
@@ -131,6 +131,7 @@
    public const int TianziBillboradRepoint = 471; //天子的考验
    public const int PhantasmPavilionRepoint = 472; //幻境阁
    public const int LineupRecommendRepoint = 473; //阵容推荐
     public const int FunctionPreviewRepoint = 474; //功能预告
    public void Register()
    {
Main/Utility/EnumHelper.cs
@@ -837,6 +837,7 @@
    Horse = 37,  //坐骑
    BattlePass = 40, //基金(战令)
    LLMJ = 41,  //历练秘笈
    FunctionPreview = 48, //功能预览
}