From fb0570bdb7e73e7d4dca211f365ee67b43628240 Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期五, 03 四月 2026 14:03:52 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into h5version

---
 Main/System/HeroReturn/HeroReturnRankCell.cs                                                         |   76 
 Main/System/HeroReturn/HeroReturnStarUpCell.cs.meta                                                  |    2 
 Main/System/HeroReturn/HeroReturnRankAwardCell.cs.meta                                               |    2 
 Main/System/HeroReturn/HeroReturnCallResultCell.cs.meta                                              |    2 
 Main/System/Battle/BoneFieldBattleWin.cs                                                             |   13 
 Main/System/Redpoint/MainRedDot.cs                                                                   |    1 
 Main/Config/Configs/SkillConfig.cs                                                                   |    9 
 Main/System/HeroReturn/HeroReturnCallChangeCell.cs                                                   |   33 
 Main/System/HeroReturn/HeroReturnStarUpWin.cs                                                        |  159 +
 Main/System/HeroReturn/HeroReturnCallWin.cs                                                          |  417 ++++
 Main/System/HeroReturn/HeroReturnRankWin.cs                                                          |  173 +
 Main/System/HeroDebut/HeroDebutSkinWin.cs                                                            |   10 
 Main/System/HeroReturn/HeroReturnShopLineCell.cs.meta                                                |    2 
 Main/System/HeroReturn/HeroReturnCallChangeItem.cs                                                   |   41 
 Main/System/HeroReturn/HeroReturnPopWin.cs                                                           |   96 
 Main/System/HeroReturn/HeroReturnGiftWin.cs                                                          |   86 
 Main/System/HeroReturn/HeroReturnCallChooseWin.cs.meta                                               |    2 
 Main/System/HeroDebut/HeroDebutCheckInWin.cs                                                         |    2 
 Main/System/HeroReturn/HeroReturnCallHistoryCell.cs.meta                                             |    2 
 Main/Utility/EnumHelper.cs                                                                           |    2 
 Main/System/HeroReturn/HeroReturnCallChangeCell.cs.meta                                              |    2 
 Main/System/HeroReturn/HeroReturnStarUpChangeWin.cs                                                  |  100 
 Main/System/HeroReturn/HeroReturnStarUpCell.cs                                                       |  126 +
 Main/System/HeroReturn/HeroReturnRankWin.cs.meta                                                     |    2 
 Main/System/HeroReturn/HeroReturnWin.cs                                                              |  265 ++
 Main/System/HeroReturn/HeroReturnStarUpPaidItemCell.cs                                               |   17 
 Main/System/Battle/StoryBossBattleWin.cs                                                             |   14 
 Main/System/HeroReturn/HeroReturnCallRateHeroWin.cs                                                  |  119 +
 Main/System/HeroReturn/HeroReturnSkinWin.cs.meta                                                     |    2 
 Main/System/HeroReturn/HeroReturnStarUpChangeCell.cs                                                 |   33 
 Main/System/OpenServerActivity/OperationTimeHepler.cs                                                |    7 
 Main/System/HeroReturn/HeroReturnRankTop3Cell.cs.meta                                                |    2 
 Main/System/HeroReturn/HeroReturnCallBubbleCell.cs.meta                                              |    2 
 Main/System/HeroDebut/HeroDebutRankWin.cs                                                            |    4 
 Main/System/HeroReturn/HeroReturnStarUpChangeItem.cs.meta                                            |    2 
 Main/System/HeroReturn/HeroReturnShopCell.cs.meta                                                    |    2 
 Main/System/HeroReturn/HeroReturnCallRateWin.cs.meta                                                 |    2 
 Main/System/HeroReturn/HeroReturnSkinTabCell.cs.meta                                                 |    2 
 Main/System/HeroReturn/HeroReturnCell.cs                                                             |   30 
 Main/System/HeroDebut/HeroDebutGiftWin.cs                                                            |    4 
 Main/System/HeroReturn/HeroReturnCallButton.cs                                                       |   95 
 Main/System/HeroReturn/HeroReturnCallHistoryWin.cs.meta                                              |    2 
 Main/System/HeroReturn/HeroReturnSkinAwardCell.cs                                                    |   18 
 Main/System/HeroReturn/HeroReturnShopWin.cs                                                          |   80 
 Main/System/HeroReturn/HeroReturnCallChangeWin.cs.meta                                               |    2 
 Main/System/UIBase/UIJumpManager.cs                                                                  |   41 
 Main/System/HeroReturn/HeroReturnSkinTabCell.cs                                                      |   26 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HA0_Sys/DTCA009_tagSCGameRecInfo.cs                      |    1 
 Main/System/HeroReturn/HeroReturnStarUpChangeWin.cs.meta                                             |    2 
 Main/Config/PartialConfigs/ActHeroAppearStarConfig.cs                                                |   34 
 Main/System/HeroReturn/HeroReturnCallRateHeroCell.cs.meta                                            |    2 
 Main/System/HeroReturn/HeroReturnShopWin.cs.meta                                                     |    2 
 Main/System/Battle/UIComp/SkillTips.cs                                                               |   88 
 Main/System/HeroDebut/HeroDebutStarUpWin.cs                                                          |    6 
 Main/System/HeroReturn/HeroReturnSkinWin.cs                                                          |  227 ++
 Main/System/HeroDebut/HeroDebutManager.cs                                                            |   66 
 Main/System/HeroReturn/HeroReturnWin.cs.meta                                                         |    2 
 Main/System/HeroReturn/HeroReturnCell.cs.meta                                                        |    2 
 Main/System/HeroReturn/HeroReturnCheckInWin.cs.meta                                                  |    2 
 Main/System/HeroReturn/HeroReturnManager.cs                                                          | 1153 +++++++++++
 Main/System/HeroDebut/HeroDebutPopWin.cs                                                             |    8 
 Main/System/HeroReturn/HeroReturnCallHistoryOutCell.cs                                               |   21 
 Main/System/HeroReturn.meta                                                                          |    8 
 Main/System/HeroReturn/HeroReturnSkinAwardCell.cs.meta                                               |    2 
 Main/Component/UI/Core/TextLanguageAdapter.cs                                                        |  259 ++
 Main/System/HeroReturn/HeroReturnCallRateItem.cs                                                     |  123 +
 Main/Config/Configs/ActHeroReturnArtConfig.cs                                                        |   71 
 Main/System/HappyXB/HappyXBModel.cs                                                                  |   12 
 Main/System/HeroReturn/HeroReturnRankTop3Cell.cs                                                     |   47 
 Main/System/HeroReturn/HeroReturnCallRateItem.cs.meta                                                |    2 
 Main/System/HeroReturn/HeroReturnCallHistoryCell.cs                                                  |   42 
 Main/System/Language/Language.cs                                                                     |    4 
 Main/Config/Configs/ActHeroAppearConfig.cs                                                           |   37 
 Main/System/HeroReturn/HeroReturnCallChooseCell.cs.meta                                              |    2 
 Main/System/HeroReturn/HeroReturnCallChooseItem.cs.meta                                              |    2 
 Main/Config/Configs/ActHeroReturnArtConfig.cs.meta                                                   |    2 
 Main/System/HeroReturn/HeroReturnShopCell.cs                                                         |  134 +
 Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA22_tagSCActHeroAppearPlayerInfo.cs |    1 
 Main/Config/Configs/ActHeroAppearArtConfig.cs                                                        |   52 
 Main/System/HeroReturn/HeroReturnStarUpWin.cs.meta                                                   |    2 
 Main/System/HeroReturn/HeroReturnRankCell.cs.meta                                                    |    2 
 Main/System/HeroDebut/HeroDebutCell.cs                                                               |    2 
 Main/System/HeroDebut/HeroDebutSkinTabCell.cs                                                        |    4 
 Main/System/HeroReturn/HeroReturnCallChooseWin.cs                                                    |   95 
 Main/System/HeroReturn/HeroReturnCallHistoryOutCell.cs.meta                                          |    2 
 Main/Manager/UIManager.cs                                                                            |   39 
 Main/System/HeroDebut/HeroDebutWin.cs                                                                |   13 
 Main/System/HeroReturn/HeroReturnCallRateWin.cs                                                      |   83 
 Main/System/HeroReturn/HeroReturnGiftWin.cs.meta                                                     |    2 
 Main/System/BoneField/BoneFieldWin.cs                                                                |    8 
 Main/System/HeroReturn/HeroReturnCallRateCell.cs                                                     |   28 
 Main/System/HeroReturn/HeroReturnCallRateCell.cs.meta                                                |    2 
 Main/System/HeroReturn/HeroReturnCallResultWin.cs                                                    |  370 +++
 Main/System/HeroReturn/HeroReturnCallResultWin.cs.meta                                               |    2 
 Main/System/Login/ServerListCenter.cs                                                                |   36 
 Main/System/HeroReturn/HeroReturnCallButton.cs.meta                                                  |    2 
 Main/System/HeroReturn/HeroReturnManager.cs.meta                                                     |    2 
 Main/System/HeroReturn/HeroReturnCallRateHeroWin.cs.meta                                             |    2 
 Main/System/HeroReturn/HeroReturnPopWin.cs.meta                                                      |    2 
 Main/System/HeroReturn/HeroReturnGiftCell.cs                                                         |  165 +
 Main/System/HeroReturn/HeroReturnStarUpChangeItem.cs                                                 |   41 
 Main/System/HeroReturn/HeroReturnCallChangeItem.cs.meta                                              |    2 
 Main/Config/ConfigManager.cs                                                                         |    6 
 Main/System/HeroReturn/HeroReturnCallChooseCell.cs                                                   |   33 
 Main/System/HeroReturn/HeroReturnCallResultCell.cs                                                   |  104 +
 Main/System/HeroReturn/HeroReturnRankAwardCell.cs                                                    |   45 
 Main/System/HeroReturn/HeroReturnCallRateHeroCell.cs                                                 |   28 
 Main/System/Battle/TianziBillboradBattleWin.cs                                                       |   13 
 Main/System/HeroReturn/HeroReturnCallChooseItem.cs                                                   |   41 
 Main/System/HeroReturn/HeroReturnGiftCell.cs.meta                                                    |    2 
 Main/System/Main/HomeWin.cs                                                                          |   24 
 Main/System/HeroReturn/HeroReturnCheckInWin.cs                                                       |   80 
 Main/Main.cs                                                                                         |    1 
 Main/System/HeroReturn/HeroReturnCallChangeWin.cs                                                    |  100 
 Main/System/HeroReturn/HeroReturnCheckInCell.cs                                                      |   60 
 Main/System/HeroDebut/HeroDebutCallWin.cs                                                            |    5 
 Main/System/HeroReturn/HeroReturnStarUpChangeCell.cs.meta                                            |    2 
 /dev/null                                                                                            |   56 
 Main/System/HeroReturn/HeroReturnCallWin.cs.meta                                                     |    2 
 Main/System/HeroReturn/HeroReturnShopLineCell.cs                                                     |   30 
 Main/System/HeroReturn/HeroReturnCheckInCell.cs.meta                                                 |    2 
 Main/Config/PartialConfigs/ActHeroAppearConfig.cs                                                    |   36 
 Main/System/Equip/BlessLVWin.cs                                                                      |    9 
 Main/System/HeroReturn/HeroReturnStarUpPaidItemCell.cs.meta                                          |    2 
 Main/Component/UI/Core/TextLanguageAdapter.cs.meta                                                   |    2 
 Main/System/HeroReturn/HeroReturnCallHistoryWin.cs                                                   |   57 
 Main/System/HeroReturn/HeroReturnCallBubbleCell.cs                                                   |   23 
 127 files changed, 5,851 insertions(+), 365 deletions(-)

diff --git a/Main/Component/UI/Core/TextLanguageAdapter.cs b/Main/Component/UI/Core/TextLanguageAdapter.cs
new file mode 100644
index 0000000..edcd1c2
--- /dev/null
+++ b/Main/Component/UI/Core/TextLanguageAdapter.cs
@@ -0,0 +1,259 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+/// <summary>鏂囨湰缁勪欢绫诲瀷鏋氫妇</summary>
+public enum TextComponentType
+{
+    None = 0,
+    Text = 1,
+    TextEx = 2,
+    GradientText = 3
+}
+
+/// <summary>鍗曚釜璇█鐨勬帓鐗堝拰閫傞厤鏁版嵁鑺傜偣</summary>
+[Serializable]
+public class LanguageConfigItem
+{
+    [Header("RectTransform 閰嶇疆")]
+    public Vector2 anchoredPosition = Vector2.zero;
+    public Vector2 sizeDelta = new Vector2(100f, 30f);
+    public Vector2 anchorMin = new Vector2(0.5f, 0.5f);
+    public Vector2 anchorMax = new Vector2(0.5f, 0.5f);
+    public Vector2 pivot = new Vector2(0.5f, 0.5f);
+    public Vector3 localScale = Vector3.one;
+    public Vector3 localRotation = Vector3.zero;
+
+    [Header("Text 鎺掔増涓庨�傞厤閰嶇疆")]
+    public Font font;
+    public FontStyle fontStyle = FontStyle.Normal;
+    public int fontSize = 14;
+    public float lineSpacing = 1f;
+    public HorizontalWrapMode horizontalOverflow = HorizontalWrapMode.Wrap;
+    public VerticalWrapMode verticalOverflow = VerticalWrapMode.Truncate;
+    public bool resizeTextForBestFit = false;
+    public int resizeTextMinSize = 10;
+    public int resizeTextMaxSize = 40;
+    public TextAnchor alignment = TextAnchor.UpperLeft;
+    public bool alignByGeometry = false;
+
+    public void ApplyToRectTransform(RectTransform rt)
+    {
+        if (rt == null) return;
+        rt.anchorMin = anchorMin;
+        rt.anchorMax = anchorMax;
+        rt.pivot = pivot;
+        rt.anchoredPosition = anchoredPosition;
+        rt.sizeDelta = sizeDelta;
+        rt.localScale = localScale;
+        rt.localRotation = Quaternion.Euler(localRotation);
+    }
+
+    public void ReadFromRectTransform(RectTransform rt)
+    {
+        if (rt == null) return;
+        anchorMin = rt.anchorMin;
+        anchorMax = rt.anchorMax;
+        pivot = rt.pivot;
+        anchoredPosition = rt.anchoredPosition;
+        sizeDelta = rt.sizeDelta;
+        localScale = rt.localScale;
+        localRotation = rt.localRotation.eulerAngles;
+    }
+
+    public void ApplyToText(Text txt)
+    {
+        if (txt == null) return;
+        if (font != null) txt.font = font;
+        
+        txt.fontStyle = fontStyle;
+        txt.fontSize = fontSize;
+        txt.lineSpacing = lineSpacing;
+        txt.horizontalOverflow = horizontalOverflow;
+        txt.verticalOverflow = verticalOverflow;
+        txt.resizeTextForBestFit = resizeTextForBestFit;
+        if (resizeTextForBestFit)
+        {
+            txt.resizeTextMinSize = resizeTextMinSize;
+            txt.resizeTextMaxSize = resizeTextMaxSize;
+        }
+        txt.alignment = alignment;
+        txt.alignByGeometry = alignByGeometry;
+    }
+
+    public void ReadFromText(Text txt)
+    {
+        if (txt == null) return;
+        font = txt.font;
+        fontStyle = txt.fontStyle;
+        fontSize = txt.fontSize;
+        lineSpacing = txt.lineSpacing;
+        horizontalOverflow = txt.horizontalOverflow;
+        verticalOverflow = txt.verticalOverflow;
+        resizeTextForBestFit = txt.resizeTextForBestFit;
+        resizeTextMinSize = txt.resizeTextMinSize;
+        resizeTextMaxSize = txt.resizeTextMaxSize;
+        alignment = txt.alignment;
+        alignByGeometry = txt.alignByGeometry;
+    }
+
+    public LanguageConfigItem Clone() => (LanguageConfigItem)MemberwiseClone();
+}
+
+/// <summary>鏀寔 Unity 搴忓垪鍖栫殑瀛楀吀</summary>
+[Serializable]
+public class LanguageConfigDictionary
+{
+    public List<string> keys = new List<string>();
+    public List<LanguageConfigItem> values = new List<LanguageConfigItem>();
+
+    public LanguageConfigItem Get(string key)
+    {
+        if (string.IsNullOrEmpty(key)) return null;
+        int index = keys.IndexOf(key);
+        return index >= 0 ? values[index] : null;
+    }
+
+    public void Set(string key, LanguageConfigItem value)
+    {
+        int index = keys.IndexOf(key);
+        if (index >= 0) values[index] = value;
+        else
+        {
+            keys.Add(key);
+            values.Add(value);
+        }
+    }
+
+    public bool ContainsKey(string key) => keys.Contains(key);
+
+    public void Remove(string key)
+    {
+        int index = keys.IndexOf(key);
+        if (index >= 0)
+        {
+            keys.RemoveAt(index);
+            values.RemoveAt(index);
+        }
+    }
+}
+
+/// <summary>澶氳瑷�鎺掔増閫傞厤鍣�</summary>
+[RequireComponent(typeof(RectTransform))]
+public class TextLanguageAdapter : MonoBehaviour
+{
+    public const string DefaultLangId = "default";
+
+    [SerializeField, Tooltip("璇█閰嶇疆瀛楀吀")] 
+    private LanguageConfigDictionary m_LanguageConfigs = new LanguageConfigDictionary();
+    
+    [SerializeField, Tooltip("鐩爣鏂囨湰缁勪欢绫诲瀷")] 
+    private TextComponentType m_TargetTextType = TextComponentType.None;
+    
+    [SerializeField, Tooltip("鍏宠仈鐨勬枃鏈粍浠跺紩鐢�")] 
+    private Component m_TargetTextComponent;
+
+    private bool m_IsApplied = false;
+
+    public TextComponentType TargetTextType => m_TargetTextType;
+    public Component TargetTextComponent => m_TargetTextComponent;
+    public LanguageConfigDictionary LanguageConfigs => m_LanguageConfigs;
+
+    private void Awake() => DetectTargetComponent();
+
+    private void OnEnable()
+    {
+        if (!Application.isPlaying || !m_IsApplied)
+        {
+            string langId = Application.isPlaying ? Language.Id : DefaultLangId;
+            ApplyConfig(langId);
+        }
+    }
+
+#if UNITY_EDITOR
+    private void Reset()
+    {
+        DetectTargetComponent();
+        if (!HasConfig(DefaultLangId)) ReadCurrentToConfig(DefaultLangId);
+    }
+#endif
+
+    public LanguageConfigItem GetConfig(string languageId) => m_LanguageConfigs.Get(languageId);
+    public void SetConfig(string languageId, LanguageConfigItem config) => m_LanguageConfigs.Set(languageId, config);
+    public void RemoveConfig(string languageId) => m_LanguageConfigs.Remove(languageId);
+    public bool HasConfig(string languageId) => m_LanguageConfigs.ContainsKey(languageId);
+    public List<string> GetConfiguredLanguages() => new List<string>(m_LanguageConfigs.keys);
+
+    public void ApplyConfig(string languageId)
+    {
+        var config = GetConfig(languageId);
+        if (config == null) return;
+
+        config.ApplyToRectTransform(GetComponent<RectTransform>());
+        if (m_TargetTextComponent is Text txt) config.ApplyToText(txt);
+
+        m_IsApplied = true;
+    }
+
+    public void ReadCurrentToConfig(string languageId)
+    {
+        var config = new LanguageConfigItem();
+        config.ReadFromRectTransform(GetComponent<RectTransform>());
+        if (m_TargetTextComponent is Text txt) config.ReadFromText(txt);
+
+        SetConfig(languageId, config);
+    }
+
+    public static string GetLanguageShowName(string languageId)
+    {
+        if (Language.languageShowDict != null && Language.languageShowDict.TryGetValue(languageId, out string showName))
+            return showName;
+        return languageId;
+    }
+
+    private void DetectTargetComponent()
+    {
+        if (m_TargetTextComponent != null)
+        {
+            DetermineTextType(m_TargetTextComponent);
+            return;
+        }
+
+        m_TargetTextComponent = GetComponent<GradientText>() ?? GetComponentInChildren<GradientText>(true) as Component
+                                ?? GetComponent<TextEx>() ?? GetComponentInChildren<TextEx>(true) as Component
+                                ?? GetComponent<Text>() ?? GetComponentInChildren<Text>(true) as Component;
+
+        DetermineTextType(m_TargetTextComponent);
+    }
+
+    private void DetermineTextType(Component component)
+    {
+        m_TargetTextType = component switch
+        {
+            GradientText _ => TextComponentType.GradientText,
+            TextEx _ => TextComponentType.TextEx,
+            Text _ => TextComponentType.Text,
+            _ => TextComponentType.None
+        };
+    }
+
+#if UNITY_EDITOR
+    [ContextMenu("鍒锋柊缁勪欢妫�娴�")]
+    public void Editor_ForceRefreshDetection()
+    {
+        DetectTargetComponent();
+        UnityEditor.EditorUtility.SetDirty(this);
+    }
+
+    [ContextMenu("璇诲彇褰撳墠閰嶇疆")]
+    public void Editor_ReadCurrentConfig()
+    {
+        ReadCurrentToConfig(DefaultLangId);
+        UnityEditor.EditorUtility.SetDirty(this);
+    }
+
+    [ContextMenu("搴旂敤榛樿閰嶇疆")]
+    public void Editor_ApplyDefaultConfig() => ApplyConfig(DefaultLangId);
+#endif
+}
\ No newline at end of file
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/Component/UI/Core/TextLanguageAdapter.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/Component/UI/Core/TextLanguageAdapter.cs.meta
index 862a125..10a3b48 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/Component/UI/Core/TextLanguageAdapter.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 8cf0191d06fb2924fb79d005580c1918
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/Config/ConfigManager.cs b/Main/Config/ConfigManager.cs
index 982cff8..8759a51 100644
--- a/Main/Config/ConfigManager.cs
+++ b/Main/Config/ConfigManager.cs
@@ -58,8 +58,8 @@
             typeof(ActBillboardAwardConfig),
             typeof(ActHeroAppearArtConfig),
             typeof(ActHeroAppearConfig),
-            typeof(ActHeroAppearSkinArtConfig),
             typeof(ActHeroAppearStarConfig),
+            typeof(ActHeroReturnArtConfig),
             typeof(ActLunhuidianTypeConfig),
             typeof(ActSignAwardConfig),
             typeof(ADAwardConfig),
@@ -393,10 +393,10 @@
         ClearConfigDictionary<ActHeroAppearArtConfig>();
         // 娓呯┖ ActHeroAppearConfig 瀛楀吀
         ClearConfigDictionary<ActHeroAppearConfig>();
-        // 娓呯┖ ActHeroAppearSkinArtConfig 瀛楀吀
-        ClearConfigDictionary<ActHeroAppearSkinArtConfig>();
         // 娓呯┖ ActHeroAppearStarConfig 瀛楀吀
         ClearConfigDictionary<ActHeroAppearStarConfig>();
+        // 娓呯┖ ActHeroReturnArtConfig 瀛楀吀
+        ClearConfigDictionary<ActHeroReturnArtConfig>();
         // 娓呯┖ ActLunhuidianTypeConfig 瀛楀吀
         ClearConfigDictionary<ActLunhuidianTypeConfig>();
         // 娓呯┖ ActSignAwardConfig 瀛楀吀
diff --git a/Main/Config/Configs/ActHeroAppearArtConfig.cs b/Main/Config/Configs/ActHeroAppearArtConfig.cs
index 8e1ef2d..6a2b507 100644
--- a/Main/Config/Configs/ActHeroAppearArtConfig.cs
+++ b/Main/Config/Configs/ActHeroAppearArtConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           2026骞�3鏈�26鏃�
+//    [  Date ]:           Tuesday, March 31, 2026
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -19,23 +19,11 @@
     public int HeroID;
 	public int[][] HeroNameColor;
 	public int[][] CallBubbleItems;
-	public string EntryBgImage;
 	public string EntryTitleText;
-	public string PopBgImage;
-	public string PopTitleBgImage;
-	public string PopTitleImage;
-	public string PopInfoBgImage;
 	public int PopInfoBgUIEffectId;
 	public string PopInfoText;
 	public int[] PopInfoColor;
-	public string MainBgImage;
-	public string MainTitleImage;
 	public int MainSkinID;
-	public string StarUpHeroImage;
-	public string GiftBgImage;
-	public string GiftHeroImage;
-	public string RankAwardHeroImage;
-	public string CheckInBgImage;
 
     public override int LoadKey(string _key)
     {
@@ -53,29 +41,19 @@
 
 			CallBubbleItems = JsonMapper.ToObject<int[][]>(tables[2].Replace("(", "[").Replace(")", "]")); 
 
-			EntryBgImage = tables[3];
+			EntryTitleText = tables[3];
 
-			EntryTitleText = tables[4];
+			int.TryParse(tables[4],out PopInfoBgUIEffectId); 
 
-			PopBgImage = tables[5];
+			PopInfoText = tables[5];
 
-			PopTitleBgImage = tables[6];
-
-			PopTitleImage = tables[7];
-
-			PopInfoBgImage = tables[8];
-
-			int.TryParse(tables[9],out PopInfoBgUIEffectId); 
-
-			PopInfoText = tables[10];
-
-			if (tables[11].Contains("["))
+			if (tables[6].Contains("["))
 			{
-				PopInfoColor = JsonMapper.ToObject<int[]>(tables[11]);
+				PopInfoColor = JsonMapper.ToObject<int[]>(tables[6]);
 			}
 			else
 			{
-				string[] PopInfoColorStringArray = tables[11].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] PopInfoColorStringArray = tables[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				PopInfoColor = new int[PopInfoColorStringArray.Length];
 				for (int i=0;i<PopInfoColorStringArray.Length;i++)
 				{
@@ -83,21 +61,7 @@
 				}
 			}
 
-			MainBgImage = tables[12];
-
-			MainTitleImage = tables[13];
-
-			int.TryParse(tables[14],out MainSkinID); 
-
-			StarUpHeroImage = tables[15];
-
-			GiftBgImage = tables[16];
-
-			GiftHeroImage = tables[17];
-
-			RankAwardHeroImage = tables[18];
-
-			CheckInBgImage = tables[19];
+			int.TryParse(tables[7],out MainSkinID); 
         }
         catch (Exception exception)
         {
diff --git a/Main/Config/Configs/ActHeroAppearConfig.cs b/Main/Config/Configs/ActHeroAppearConfig.cs
index a2d2229..fb2450f 100644
--- a/Main/Config/Configs/ActHeroAppearConfig.cs
+++ b/Main/Config/Configs/ActHeroAppearConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           2026骞�3鏈�9鏃�
+//    [  Date ]:           Thursday, March 26, 2026
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -17,6 +17,7 @@
     }
 
     public int CfgID;
+	public int ActNum;
 	public int[] ActHeroIDList;
 	public int ActTreasureType;
 	public int StarGiftTempID;
@@ -40,13 +41,15 @@
         string[] tables = input.Split('\t');
         int.TryParse(tables[0],out CfgID); 
 
-			if (tables[1].Contains("["))
+			int.TryParse(tables[1],out ActNum); 
+
+			if (tables[2].Contains("["))
 			{
-				ActHeroIDList = JsonMapper.ToObject<int[]>(tables[1]);
+				ActHeroIDList = JsonMapper.ToObject<int[]>(tables[2]);
 			}
 			else
 			{
-				string[] ActHeroIDListStringArray = tables[1].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] ActHeroIDListStringArray = tables[2].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				ActHeroIDList = new int[ActHeroIDListStringArray.Length];
 				for (int i=0;i<ActHeroIDListStringArray.Length;i++)
 				{
@@ -54,17 +57,17 @@
 				}
 			}
 
-			int.TryParse(tables[2],out ActTreasureType); 
+			int.TryParse(tables[3],out ActTreasureType); 
 
-			int.TryParse(tables[3],out StarGiftTempID); 
+			int.TryParse(tables[4],out StarGiftTempID); 
 
-			if (tables[4].Contains("["))
+			if (tables[5].Contains("["))
 			{
-				SkinCTGIDList = JsonMapper.ToObject<int[]>(tables[4]);
+				SkinCTGIDList = JsonMapper.ToObject<int[]>(tables[5]);
 			}
 			else
 			{
-				string[] SkinCTGIDListStringArray = tables[4].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] SkinCTGIDListStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				SkinCTGIDList = new int[SkinCTGIDListStringArray.Length];
 				for (int i=0;i<SkinCTGIDListStringArray.Length;i++)
 				{
@@ -72,13 +75,13 @@
 				}
 			}
 
-			if (tables[5].Contains("["))
+			if (tables[6].Contains("["))
 			{
-				GiftCTGIDList = JsonMapper.ToObject<int[]>(tables[5]);
+				GiftCTGIDList = JsonMapper.ToObject<int[]>(tables[6]);
 			}
 			else
 			{
-				string[] GiftCTGIDListStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] GiftCTGIDListStringArray = tables[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				GiftCTGIDList = new int[GiftCTGIDListStringArray.Length];
 				for (int i=0;i<GiftCTGIDListStringArray.Length;i++)
 				{
@@ -86,15 +89,15 @@
 				}
 			}
 
-			int.TryParse(tables[6],out GiftShopType); 
+			int.TryParse(tables[7],out GiftShopType); 
 
-			int.TryParse(tables[7],out ExShopType); 
+			int.TryParse(tables[8],out ExShopType); 
 
-			int.TryParse(tables[8],out ExShopCostItemID); 
+			int.TryParse(tables[9],out ExShopCostItemID); 
 
-			int.TryParse(tables[9],out SignTempID); 
+			int.TryParse(tables[10],out SignTempID); 
 
-			int.TryParse(tables[10],out BillTempID); 
+			int.TryParse(tables[11],out BillTempID); 
         }
         catch (Exception exception)
         {
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs b/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs
deleted file mode 100644
index 94221ae..0000000
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-锘�//--------------------------------------------------------
-//    [Author]:           YYL
-//    [  Date ]:           2026骞�3鏈�11鏃�
-//--------------------------------------------------------
-
-using System.Collections.Generic;
-using System;
-using UnityEngine;
-using LitJson;
-
-public partial class ActHeroAppearSkinArtConfig : ConfigBase<int, ActHeroAppearSkinArtConfig>
-{
-    static ActHeroAppearSkinArtConfig()
-    {
-        // 璁块棶杩囬潤鎬佹瀯閫犲嚱鏁�
-        visit = true; 
-    }
-
-    public int SkinID;
-	public string MainSkinBuyBgImage;
-	public string BGImage;
-	public string HeroNameImage;
-	public string SkinInfoImage;
-	public string AwardBGImage;
-	public string TabInfoImage;
-
-    public override int LoadKey(string _key)
-    {
-        int key = GetKey(_key);
-        return key;
-    }
-
-    public override void LoadConfig(string input)
-    {
-        try {
-        string[] tables = input.Split('\t');
-        int.TryParse(tables[0],out SkinID); 
-
-			MainSkinBuyBgImage = tables[1];
-
-			BGImage = tables[2];
-
-			HeroNameImage = tables[3];
-
-			SkinInfoImage = tables[4];
-
-			AwardBGImage = tables[5];
-
-			TabInfoImage = tables[6];
-        }
-        catch (Exception exception)
-        {
-            Debug.LogError(exception);
-        }
-    }
-}
diff --git a/Main/Config/Configs/ActHeroReturnArtConfig.cs b/Main/Config/Configs/ActHeroReturnArtConfig.cs
new file mode 100644
index 0000000..de9781b
--- /dev/null
+++ b/Main/Config/Configs/ActHeroReturnArtConfig.cs
@@ -0,0 +1,71 @@
+锘�//--------------------------------------------------------
+//    [Author]:           YYL
+//    [  Date ]:           2026骞�3鏈�31鏃�
+//--------------------------------------------------------
+
+using System.Collections.Generic;
+using System;
+using UnityEngine;
+using LitJson;
+
+public partial class ActHeroReturnArtConfig : ConfigBase<int, ActHeroReturnArtConfig>
+{
+    static ActHeroReturnArtConfig()
+    {
+        // 璁块棶杩囬潤鎬佹瀯閫犲嚱鏁�
+        visit = true; 
+    }
+
+    public int HeroID;
+	public int[][] HeroNameColor;
+	public int[][] CallBubbleItems;
+	public string EntryTitleText;
+	public int PopInfoBgUIEffectId;
+	public string PopInfoText;
+	public int[] PopInfoColor;
+	public int MainSkinID;
+
+    public override int LoadKey(string _key)
+    {
+        int key = GetKey(_key);
+        return key;
+    }
+
+    public override void LoadConfig(string input)
+    {
+        try {
+        string[] tables = input.Split('\t');
+        int.TryParse(tables[0],out HeroID); 
+
+			HeroNameColor = JsonMapper.ToObject<int[][]>(tables[1].Replace("(", "[").Replace(")", "]")); 
+
+			CallBubbleItems = JsonMapper.ToObject<int[][]>(tables[2].Replace("(", "[").Replace(")", "]")); 
+
+			EntryTitleText = tables[3];
+
+			int.TryParse(tables[4],out PopInfoBgUIEffectId); 
+
+			PopInfoText = tables[5];
+
+			if (tables[6].Contains("["))
+			{
+				PopInfoColor = JsonMapper.ToObject<int[]>(tables[6]);
+			}
+			else
+			{
+				string[] PopInfoColorStringArray = tables[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				PopInfoColor = new int[PopInfoColorStringArray.Length];
+				for (int i=0;i<PopInfoColorStringArray.Length;i++)
+				{
+					 int.TryParse(PopInfoColorStringArray[i],out PopInfoColor[i]);
+				}
+			}
+
+			int.TryParse(tables[7],out MainSkinID); 
+        }
+        catch (Exception exception)
+        {
+            Debug.LogError(exception);
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/Config/Configs/ActHeroReturnArtConfig.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/Config/Configs/ActHeroReturnArtConfig.cs.meta
index 862a125..851219f 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/Config/Configs/ActHeroReturnArtConfig.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 010dfd3e7d7da104f8daef3fb34fd922
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/Config/Configs/SkillConfig.cs b/Main/Config/Configs/SkillConfig.cs
index 3ff8a32..6c8de52 100644
--- a/Main/Config/Configs/SkillConfig.cs
+++ b/Main/Config/Configs/SkillConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           2026骞�2鏈�7鏃�
+//    [  Date ]:           Tuesday, March 31, 2026
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -37,7 +37,6 @@
 	public int FightPower;
 	public string IconName;
 	public string BuffIconName;
-	public string SkillTipsName;
 	public int Scattering;
 	public int ClientTriggerTiming;
 
@@ -105,11 +104,9 @@
 
 			BuffIconName = tables[20];
 
-			SkillTipsName = tables[21];
+			int.TryParse(tables[21],out Scattering); 
 
-			int.TryParse(tables[22],out Scattering); 
-
-			int.TryParse(tables[23],out ClientTriggerTiming); 
+			int.TryParse(tables[22],out ClientTriggerTiming); 
         }
         catch (Exception exception)
         {
diff --git a/Main/Config/PartialConfigs/ActHeroAppearConfig.cs b/Main/Config/PartialConfigs/ActHeroAppearConfig.cs
index c258cab..22c36bb 100644
--- a/Main/Config/PartialConfigs/ActHeroAppearConfig.cs
+++ b/Main/Config/PartialConfigs/ActHeroAppearConfig.cs
@@ -1,18 +1,40 @@
 using System.Collections.Generic;
+using System.Linq;
 public partial class ActHeroAppearConfig : ConfigBase<int, ActHeroAppearConfig>
 {
-    private static List<int> actTreasureTypeList;
-    public static List<int> GetActTreasureTypeList()
+    /// <summary>
+    /// 姝﹀皢鐧诲満鐨勬墍鏈夋嫑鍕熷瀹濈被鍨�
+    /// </summary>
+    private static HashSet<int> heroDebutActTreasureTypeList = new();
+    public static List<int> GetHeroDebutActTreasureTypeList()
     {
-        if (actTreasureTypeList == null)
+        if (heroDebutActTreasureTypeList.Count == 0)
         {
-            actTreasureTypeList = new();
             foreach (var item in GetValues())
             {
-                if (!actTreasureTypeList.Contains(item.ActTreasureType))
-                    actTreasureTypeList.Add(item.ActTreasureType);
+                if (item.ActNum != 10)
+                    continue;
+                heroDebutActTreasureTypeList.Add(item.ActTreasureType);
             }
         }
-        return actTreasureTypeList;
+        return heroDebutActTreasureTypeList.ToList();
+    }
+
+    /// <summary>
+    /// 姝﹀皢杩斿満鐨勬墍鏈夋嫑鍕熷瀹濈被鍨�
+    /// </summary>
+    private static HashSet<int> heroReturnActTreasureTypeList = new();
+    public static List<int> GetHeroReturnActTreasureTypeList()
+    {
+        if (heroReturnActTreasureTypeList.Count == 0)
+        {
+            foreach (var item in GetValues())
+            {
+                if (item.ActNum != 11)
+                    continue;
+                heroReturnActTreasureTypeList.Add(item.ActTreasureType);
+            }
+        }
+        return heroReturnActTreasureTypeList.ToList();
     }
 }
diff --git a/Main/Config/PartialConfigs/ActHeroAppearStarConfig.cs b/Main/Config/PartialConfigs/ActHeroAppearStarConfig.cs
index df067a9..31e7621 100644
--- a/Main/Config/PartialConfigs/ActHeroAppearStarConfig.cs
+++ b/Main/Config/PartialConfigs/ActHeroAppearStarConfig.cs
@@ -26,8 +26,40 @@
             sortDict[starTempID] = list;
         }
     }
+    public static List<int> GetHeroReturnAwardIndexSortList(int starTempID)
+    {
+        LoadSortList();
+        sortDict.TryGetValue(starTempID, out var list);
 
-    public static List<int> GetAwardIndexSortList(int starTempID)
+        List<int> res = new List<int>();
+        int heroId = HeroReturnManager.Instance.GetCurrentDisplayStarUpHeroId();
+        int nowStar = HeroReturnManager.Instance.GetNowHeroMaxStarCnt(heroId);
+        for (int i = HeroReturnManager.Instance.seeArr.Length - 1; i >= 0; i--)
+        {
+            int[] info = HeroReturnManager.Instance.seeArr[i];
+            int needStar = info[0];
+            int seeStar = info[1];
+            if (nowStar >= needStar)
+            {
+                for (int j = 0; j < seeStar; j++)
+                {
+                    if (j >= list.Count) continue;
+
+                    var config = GetConfig(starTempID, list[j]);
+                    if (config == null) continue;
+
+                    int tempStar = config.NeedStar;
+                    if (tempStar > seeStar) continue;
+
+                    res.Add(list[j]);
+                }
+                return res;
+            }
+        }
+
+        return null;
+    }
+    public static List<int> GetHeroDebutAwardIndexSortList(int starTempID)
     {
         LoadSortList();
         sortDict.TryGetValue(starTempID, out var list);
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HA0_Sys/DTCA009_tagSCGameRecInfo.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/HA0_Sys/DTCA009_tagSCGameRecInfo.cs
index 290e6a8..cf3c32c 100644
--- a/Main/Core/NetworkPackage/DTCFile/ServerPack/HA0_Sys/DTCA009_tagSCGameRecInfo.cs
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HA0_Sys/DTCA009_tagSCGameRecInfo.cs
@@ -10,5 +10,6 @@
         ArenaManager.Instance.UpdateGameRecInfo(vNetData);
         HeroDebutManager.Instance.UpdateGameRecInfo(vNetData);
         QunyingManager.Instance.UpdateGameRecInfo(vNetData);
+        HeroReturnManager.Instance.UpdateGameRecInfo(vNetData);
     }
 }
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA22_tagSCActHeroAppearPlayerInfo.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA22_tagSCActHeroAppearPlayerInfo.cs
index 4b4846c..66006e9 100644
--- a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA22_tagSCActHeroAppearPlayerInfo.cs
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA22_tagSCActHeroAppearPlayerInfo.cs
@@ -10,5 +10,6 @@
         base.Done(vNetPack);
         HAA22_tagSCActHeroAppearPlayerInfo vNetData = vNetPack as HAA22_tagSCActHeroAppearPlayerInfo;
         HeroDebutManager.Instance.UpdateHeroAppearPlayerInfo(vNetData);
+        HeroReturnManager.Instance.UpdateHeroAppearPlayerInfo(vNetData);
     }
 }
diff --git a/Main/Main.cs b/Main/Main.cs
index d728a81..ef27b78 100644
--- a/Main/Main.cs
+++ b/Main/Main.cs
@@ -122,6 +122,7 @@
         managers.Add(GeneralActInfoManager.Instance);
         managers.Add(QunyingManager.Instance);
         managers.Add(ViewBuffManager.Instance);
+        managers.Add(HeroReturnManager.Instance);
 
         foreach (var manager in managers)
         {
diff --git a/Main/Manager/UIManager.cs b/Main/Manager/UIManager.cs
index 23889f4..862f8b0 100644
--- a/Main/Manager/UIManager.cs
+++ b/Main/Manager/UIManager.cs
@@ -384,7 +384,44 @@
         return false;
     }
 
-    
+    // 妫�鏌ユ槸鍚﹀瓨鍦ㄤ换浣曞悓灞傜骇sortingOrde澶т簬鎴戠殑绐楀彛
+    public bool ExistAnySameLevelWinHigherSortingOrder(UILayer uiLayer, string excludeUIName)
+    {
+        int mySortingOrder = 0;
+        if (uiDict.TryGetValue(excludeUIName, out List<UIBase> excludeList) && excludeList.Count > 0)
+        {
+            foreach (var ui in excludeList)
+            {
+                if (ui.IsActive())
+                {
+                    mySortingOrder = ui.GetSortingOrder();
+                    break;
+                }
+            }
+        }
+
+        if (mySortingOrder == 0)
+            return false;
+
+        foreach (var uiList in uiDict.Values)
+        {
+            foreach (var ui in uiList)
+            {
+                if (!ui.IsActive())
+                    continue;
+                if (ui.uiName == excludeUIName)
+                    continue;
+                if (ui.uiLayer != uiLayer)
+                    continue;
+                if (ui.GetSortingOrder() > mySortingOrder)
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+
     // 鑾峰彇鎸囧畾绫诲瀷鐨勬墍鏈塙I瀹炰緥
     public List<T> GetAllUI<T>() where T : UIBase
     {
diff --git a/Main/System/Battle/BoneFieldBattleWin.cs b/Main/System/Battle/BoneFieldBattleWin.cs
index 647569d..1125396 100644
--- a/Main/System/Battle/BoneFieldBattleWin.cs
+++ b/Main/System/Battle/BoneFieldBattleWin.cs
@@ -14,6 +14,7 @@
     [SerializeField] public List<BattleBuffCell> buffCells;
     [SerializeField] HeroCountryComponent myCountry;
     [SerializeField] HeroCountryComponent enemyCountry;
+    [SerializeField] ButtonEx buffInfoButton;
 
     protected override void OnPreOpen()
     {
@@ -253,6 +254,18 @@
     public void RefreshBuff(List<HB428_tagSCBuffRefresh> datas)
     {
         RefreshBuffCells(buffCells, datas);
+        
+        buffInfoButton.SetListener(() =>
+        {
+            if (bossBattleObject == null ||  datas.IsNullOrEmpty()) return;
+            EventBroadcast.Instance.Broadcast(EventName.BATTLE_CLICK_BUFF, new BattleClickBuffData()
+            {
+                isMySide = false,
+                heroID = (bossBattleObject as HeroBattleObject)?.teamHero?.heroId ?? 0,
+                skinID = (bossBattleObject as HeroBattleObject)?.teamHero?.SkinID ?? 0,
+                datas = datas,
+            });
+        });
     }
 
     bool IsOpenBattleChangeTab()
diff --git a/Main/System/Battle/StoryBossBattleWin.cs b/Main/System/Battle/StoryBossBattleWin.cs
index 10b32b7..53833fe 100644
--- a/Main/System/Battle/StoryBossBattleWin.cs
+++ b/Main/System/Battle/StoryBossBattleWin.cs
@@ -20,6 +20,7 @@
     [SerializeField] public List<BattleBuffCell> buffCells;
     [SerializeField] HeroCountryComponent myCountry;
     [SerializeField] HeroCountryComponent enemyCountry;
+    [SerializeField] ButtonEx buffInfoButton;
 
     protected override void OnPreOpen()
     {
@@ -186,7 +187,7 @@
 
         if (null == bossBattleObject)
             return;
-        
+
         if (null == bossBattleObject || bossBattleObject is not HeroBattleObject)
             return;
 
@@ -233,6 +234,17 @@
     public void RefreshBuff(List<HB428_tagSCBuffRefresh> datas)
     {
         RefreshBuffCells(buffCells, datas);
+        buffInfoButton.SetListener(() =>
+        {
+            if (bossBattleObject == null ||  datas.IsNullOrEmpty()) return;
+            EventBroadcast.Instance.Broadcast(EventName.BATTLE_CLICK_BUFF, new BattleClickBuffData()
+            {
+                isMySide = false,
+                heroID = (bossBattleObject as HeroBattleObject)?.teamHero?.heroId ?? 0,
+                skinID = (bossBattleObject as HeroBattleObject)?.teamHero?.SkinID ?? 0,
+                datas = datas,
+            });
+        });
     }
     List<TeamHero> GetTeamHeroList(List<BattleObject> teams)
     {
diff --git a/Main/System/Battle/TianziBillboradBattleWin.cs b/Main/System/Battle/TianziBillboradBattleWin.cs
index d586287..cc1a606 100644
--- a/Main/System/Battle/TianziBillboradBattleWin.cs
+++ b/Main/System/Battle/TianziBillboradBattleWin.cs
@@ -18,6 +18,7 @@
     [SerializeField] public List<BattleBuffCell> buffCells;
     [SerializeField] RectTransform rectBoxEnd;
     [SerializeField] UIEffectPlayer uiEffectPlayer;
+    [SerializeField] ButtonEx buffInfoButton;
 
 
     protected override void OnPreOpen()
@@ -313,6 +314,18 @@
     public void RefreshBuff(List<HB428_tagSCBuffRefresh> datas)
     {
         RefreshBuffCells(buffCells, datas);
+
+        buffInfoButton.SetListener(() =>
+        {
+            if (bossBattleObject == null ||  datas.IsNullOrEmpty()) return;
+            EventBroadcast.Instance.Broadcast(EventName.BATTLE_CLICK_BUFF, new BattleClickBuffData()
+            {
+                isMySide = false,
+                heroID = (bossBattleObject as HeroBattleObject)?.teamHero?.heroId ?? 0,
+                skinID = (bossBattleObject as HeroBattleObject)?.teamHero?.SkinID ?? 0,
+                datas = datas,
+            });
+        });
     }
 
     bool IsOpenBattleChangeTab()
diff --git a/Main/System/Battle/UIComp/SkillTips.cs b/Main/System/Battle/UIComp/SkillTips.cs
index ac68de4..725489e 100644
--- a/Main/System/Battle/UIComp/SkillTips.cs
+++ b/Main/System/Battle/UIComp/SkillTips.cs
@@ -13,10 +13,10 @@
 
     public const float beginingX = 400f;
 
-    [SerializeField]public Image imgIcon;
+    [SerializeField] public Image imgIcon;
 
-    [SerializeField]public Image imgSkillName;
-
+    [SerializeField] public GradientText txtSkillName;
+    [SerializeField] public CanvasGroup canvasGroup;
     [SerializeField] public Image imageBg;
 
     private Tween tween1;
@@ -36,18 +36,12 @@
         KillAllTweens();
 
         UILoader.LoadSprite("HeroHead", teamHero.skinConfig.SquareIcon, imgIcon).Forget();
-        UILoader.LoadSprite("SkillNameIcon", skillConfig.SkillTipsName, imgSkillName).ContinueWith(() =>
-        {
-            if (this == null || imgSkillName == null)
-            {
-                return;
-            }
-            imgSkillName.SetNativeSize();
-        }).Forget();
+        txtSkillName.text = skillConfig.SkillName;
+
         // 淇濊瘉寮�濮嬫椂鎵�鏈夊浘鐗囦负鍙锛坅lpha=1锛�
         if (imageBg != null) { var c = imageBg.color; c.a = 1f; imageBg.color = c; }
         if (imgIcon != null) { var c = imgIcon.color; c.a = 1f; imgIcon.color = c; }
-        if (imgSkillName != null) { var c = imgSkillName.color; c.a = 1f; imgSkillName.color = c; }
+        if (canvasGroup != null) { var c = canvasGroup.alpha; c = 1f; canvasGroup.alpha = c; }
 
         gameObject.SetActive(true);
         float posY = transform.localPosition.y;
@@ -66,8 +60,8 @@
                     seq.Join(imageBg.DOFade(0f, fadeDuration).SetEase(Ease.InQuad));
                 if (imgIcon != null)
                     seq.Join(imgIcon.DOFade(0f, fadeDuration).SetEase(Ease.InQuad));
-                if (imgSkillName != null)
-                    seq.Join(imgSkillName.DOFade(0f, fadeDuration).SetEase(Ease.InQuad));
+                if (canvasGroup != null)
+                    seq.Join(canvasGroup.DOFade(0f, fadeDuration).SetEase(Ease.InQuad));
 
                 seq.OnComplete(() =>
                 {
@@ -75,7 +69,7 @@
                     // 鎭㈠鍥剧墖 alpha锛屼繚璇佷笅娆℃樉绀烘椂鍙
                     if (imageBg != null) { var cc = imageBg.color; cc.a = 1f; imageBg.color = cc; }
                     if (imgIcon != null) { var cc = imgIcon.color; cc.a = 1f; imgIcon.color = cc; }
-                    if (imgSkillName != null) { var cc = imgSkillName.color; cc.a = 1f; imgSkillName.color = cc; }
+                    if (canvasGroup != null) { var cc = canvasGroup.alpha; cc = 1f; canvasGroup.alpha = cc; }
 
                     transform.localPosition = isRed ? new Vector3(-beginingX, posY, 0f) : new Vector3(beginingX, posY, 0f);
                     gameObject.SetActive(false);
@@ -89,68 +83,6 @@
         battleField.battleTweenMgr.OnPlayTween(tween1);
     }
 
-    public async UniTask PlayMotionAsync(BattleField battleField, bool isRed, TeamHero teamHero, SkillConfig skillConfig)
-    {
-        if (teamHero == null || skillConfig == null)
-        {
-            return;
-        }
-
-        if (skillConfig.FuncType != 2)
-            return;
-
-        KillAllTweens();
-
-        imgIcon.sprite = await UILoader.LoadSpriteAsync("HeroHead", teamHero.skinConfig.SquareIcon);
-        if (this == null) return;
-        imgSkillName.sprite = await UILoader.LoadSpriteAsync("SkillNameIcon", skillConfig.SkillTipsName);
-        if (this == null) return;
-        imgSkillName.SetNativeSize();
-        // 淇濊瘉寮�濮嬫椂鎵�鏈夊浘鐗囦负鍙锛坅lpha=1锛�
-        if (imageBg != null) { var c = imageBg.color; c.a = 1f; imageBg.color = c; }
-        if (imgIcon != null) { var c = imgIcon.color; c.a = 1f; imgIcon.color = c; }
-        if (imgSkillName != null) { var c = imgSkillName.color; c.a = 1f; imgSkillName.color = c; }
-
-        gameObject.SetActive(true);
-        float posY = transform.localPosition.y;
-        transform.localPosition = isRed ? new Vector3(-beginingX, posY, 0f) : new Vector3(beginingX, posY, 0f);
-        tween1 = transform.DOLocalMoveX(0, tweenDuration / battleField.speedRatio, false).SetEase(Ease.Linear).OnComplete(() =>
-        {
-            tween1 = null;
-            tween3 = DOVirtual.DelayedCall(delayDuration / battleField.speedRatio, () =>
-            {
-                tween3 = null;
-
-                // tween2 鏀逛负鍋氬噺娣★紙瀵� imageBg銆乮mgIcon銆乮mgSkillName 鍚屾娣″嚭锛�
-                float fadeDuration = tweenDuration / battleField.speedRatio;
-                Sequence seq = DOTween.Sequence();
-                if (imageBg != null)
-                    seq.Join(imageBg.DOFade(0f, fadeDuration).SetEase(Ease.InQuad));
-                if (imgIcon != null)
-                    seq.Join(imgIcon.DOFade(0f, fadeDuration).SetEase(Ease.InQuad));
-                if (imgSkillName != null)
-                    seq.Join(imgSkillName.DOFade(0f, fadeDuration).SetEase(Ease.InQuad));
-
-                seq.OnComplete(() =>
-                {
-                    tween2 = null;
-                    // 鎭㈠鍥剧墖 alpha锛屼繚璇佷笅娆℃樉绀烘椂鍙
-                    if (imageBg != null) { var cc = imageBg.color; cc.a = 1f; imageBg.color = cc; }
-                    if (imgIcon != null) { var cc = imgIcon.color; cc.a = 1f; imgIcon.color = cc; }
-                    if (imgSkillName != null) { var cc = imgSkillName.color; cc.a = 1f; imgSkillName.color = cc; }
-
-                    transform.localPosition = isRed ? new Vector3(-beginingX, posY, 0f) : new Vector3(beginingX, posY, 0f);
-                    gameObject.SetActive(false);
-                });
-
-                tween2 = seq;
-                battleField.battleTweenMgr.OnPlayTween(tween2);
-            });
-            battleField.battleTweenMgr.OnPlayTween(tween3);
-        });
-        battleField.battleTweenMgr.OnPlayTween(tween1);
-    }
-    
     public void KillAllTweens()
     {
         if (tween1 != null)
@@ -172,7 +104,7 @@
         // 琚己鍒跺仠姝㈡椂涔熼渶瑕佹仮澶� alpha
         if (imageBg != null) { var cc = imageBg.color; cc.a = 1f; imageBg.color = cc; }
         if (imgIcon != null) { var cc = imgIcon.color; cc.a = 1f; imgIcon.color = cc; }
-        if (imgSkillName != null) { var cc = imgSkillName.color; cc.a = 1f; imgSkillName.color = cc; }
+        if (canvasGroup != null) { var cc = canvasGroup.alpha; cc = 1f; canvasGroup.alpha = cc; }
     }
 
 }
diff --git a/Main/System/BoneField/BoneFieldWin.cs b/Main/System/BoneField/BoneFieldWin.cs
index 3699050..02f9480 100644
--- a/Main/System/BoneField/BoneFieldWin.cs
+++ b/Main/System/BoneField/BoneFieldWin.cs
@@ -13,7 +13,7 @@
     [SerializeField] TextEx txtTodayAdsCount;
     [SerializeField] TextEx txtFirstFree;
     [SerializeField] TextEx txtFightPower;
-    [SerializeField] ImageEx imgMaxLineID;
+    [SerializeField] TextEx txtMaxLineID;
     [SerializeField] Transform transChallengeItemCells;
     [SerializeField] List<ItemCell> challengeItemCells1;
     [SerializeField] List<ItemCell> challengeItemCells2;
@@ -30,7 +30,7 @@
     [SerializeField] ImageEx imgSweepRed;
     [SerializeField] UIHeroController bossModel;
     [SerializeField] Button funPresetBtn;
-    
+
     bool isHasNextLineID;
     int adID;
 
@@ -42,7 +42,7 @@
         btnClose.SetListener(OnClickClose);
         btnSweep.SetListener(OnClickSweep);
         btnAds.SetListener(OnClickAds);
-        funPresetBtn.AddListener(()=>
+        funPresetBtn.AddListener(() =>
         {
             FuncPresetManager.Instance.ClickBattlePreset((int)BattlePreSetType.Story);
         });
@@ -188,7 +188,7 @@
 
     public void DisplayFBInfo(NPCConfig nPCConfig, DungeonConfig dungeonConfig, int nowPassLineID)
     {
-        imgMaxLineID.SetActive(!isHasNextLineID);
+        txtMaxLineID.SetActive(!isHasNextLineID);
         transChallengeItemCells.SetActive(isHasNextLineID);
         txtBossName.text = nPCConfig.NPCName;
         txtDifficulty.text = nowPassLineID.ToString();
diff --git a/Main/System/Equip/BlessLVWin.cs b/Main/System/Equip/BlessLVWin.cs
index 84f0c3d..eb14864 100644
--- a/Main/System/Equip/BlessLVWin.cs
+++ b/Main/System/Equip/BlessLVWin.cs
@@ -26,7 +26,7 @@
     [SerializeField] Button upgradeButton;
     [SerializeField] UIEffectPlayer upgradeEffect;
     [SerializeField] UIEffectPlayer btnEffect;
-
+    [SerializeField] ButtonEx tipButton;
 
 
 
@@ -44,6 +44,13 @@
         {
             UIManager.Instance.OpenWindowAsync<BlessLVADWin>().Forget();
         });
+
+        tipButton.AddListener(() =>
+        {
+            SmallTipWin.showText = Language.Get("BlessLVRuleDesc");
+            SmallTipWin.worldPos = tipButton.transform.position;
+            UIManager.Instance.OpenWindow<SmallTipWin>();
+        });
     }
 
 
diff --git a/Main/System/HappyXB/HappyXBModel.cs b/Main/System/HappyXB/HappyXBModel.cs
index 08a6291..54596ec 100644
--- a/Main/System/HappyXB/HappyXBModel.cs
+++ b/Main/System/HappyXB/HappyXBModel.cs
@@ -183,14 +183,24 @@
             {
                 UIManager.Instance.OpenWindowAsync<HeroCallResultWin>().Forget();
             }
+            return;
         }
 
-        if (ActHeroAppearConfig.GetActTreasureTypeList().Contains(type))
+        if (ActHeroAppearConfig.GetHeroDebutActTreasureTypeList().Contains(type))
         {
             if (!UIManager.Instance.IsOpened<HeroDebutCallResultWin>())
             {
                 UIManager.Instance.OpenWindowAsync<HeroDebutCallResultWin>().Forget();
             }
+            return;
+        }
+
+        if (ActHeroAppearConfig.GetHeroReturnActTreasureTypeList().Contains(type))
+        {
+            if (!UIManager.Instance.IsOpened<HeroReturnCallResultWin>())
+            {
+                UIManager.Instance.OpenWindow<HeroReturnCallResultWin>();
+            }
         }
     }
 
diff --git a/Main/System/HeroDebut/HeroDebutCallWin.cs b/Main/System/HeroDebut/HeroDebutCallWin.cs
index cd6e004..2606539 100644
--- a/Main/System/HeroDebut/HeroDebutCallWin.cs
+++ b/Main/System/HeroDebut/HeroDebutCallWin.cs
@@ -79,6 +79,7 @@
         PackManager.Instance.RefreshItemEvent += RefreshItemEvent;
         scroller.OnRefreshCell += OnRefreshCell;
         manager.OnUpdateGameRecInfo += OnUpdateGameRecInfo;
+        manager.OnUpdateHeroAppearPlayerInfoEvent += OnUpdateHeroAppearPlayerInfoEvent;
 
         if (manager.isSendFirst)
         {
@@ -114,7 +115,7 @@
     // 1. 鍦ㄧ被涓0鏄庝竴涓叏灞�鐨� Sequence 鍙橀噺锛岀敤浜庣粺涓�绠℃帶鍔ㄧ敾
     private Sequence heroAnimSeq;
 
-    private void OnUpdateHeroAppearPlayerInfoEvent(int actNum)
+    private void OnUpdateHeroAppearPlayerInfoEvent()
     {
         changeRect.SetActive(false);
 
@@ -250,7 +251,7 @@
         xbTypeInfo = HappyXBModel.Instance.GetXBInfoByType(treasureType);
         if (xbTypeInfo == null) return;
 
-        bgImage.SetSprite(artConfig.MainBgImage);
+        bgImage.SetSprite(StringUtility.Concat("HeroDebutCallBG_", heroID.ToString()));
 
         lhController.Create(skinID, 1, motionName: "", isLh: true).Forget();
         uiHeroController.Create(skinID, modleSize).Forget();
diff --git a/Main/System/HeroDebut/HeroDebutCell.cs b/Main/System/HeroDebut/HeroDebutCell.cs
index b6c858d..fdb69be 100644
--- a/Main/System/HeroDebut/HeroDebutCell.cs
+++ b/Main/System/HeroDebut/HeroDebutCell.cs
@@ -23,7 +23,7 @@
         var skinConfig = HeroSkinConfig.Get(skinID);
         if (skinConfig == null) return;
 
-        bgImage.SetSprite(artConfig.EntryBgImage);
+        bgImage.SetSprite(StringUtility.Concat("HeroDebutEntryBg_", heroID.ToString()));
         manager.SetHeroSquareIcon(heroImage, skinConfig.SquareIcon);
         titleText.text = artConfig.EntryTitleText;
     }
diff --git a/Main/System/HeroDebut/HeroDebutCheckInWin.cs b/Main/System/HeroDebut/HeroDebutCheckInWin.cs
index bac6528..7c42d6a 100644
--- a/Main/System/HeroDebut/HeroDebutCheckInWin.cs
+++ b/Main/System/HeroDebut/HeroDebutCheckInWin.cs
@@ -61,7 +61,7 @@
         var list = ActSignAwardConfig.GetDayNumSortList(templateID);
         if (list == null) return;
         
-        bgImage.SetSprite(artConfig.CheckInBgImage);
+        bgImage.SetSprite(StringUtility.Concat("HeroDebutCheckInBG_", heroID.ToString()));
 
 
         for (int i = 0; i < cells.Length; i++)
diff --git a/Main/System/HeroDebut/HeroDebutGiftWin.cs b/Main/System/HeroDebut/HeroDebutGiftWin.cs
index 4f161b8..ba43fc7 100644
--- a/Main/System/HeroDebut/HeroDebutGiftWin.cs
+++ b/Main/System/HeroDebut/HeroDebutGiftWin.cs
@@ -26,10 +26,10 @@
         var artConfig = ActHeroAppearArtConfig.Get(heroID);
         if (artConfig == null) return;
 
-        bgImage.SetSprite(artConfig.GiftBgImage);
+        bgImage.SetSprite(StringUtility.Concat("HeroDebutGiftBG_", heroID.ToString()));
         heroImage.SetNativeSize();
 
-        heroImage.SetSprite(artConfig.GiftHeroImage);
+        heroImage.SetSprite(StringUtility.Concat("HeroDebutGiftHero_", heroID.ToString()));
         heroImage.SetNativeSize();
 
         OnSecondEvent();
diff --git a/Main/System/HeroDebut/HeroDebutManager.cs b/Main/System/HeroDebut/HeroDebutManager.cs
index dd02e5e..74cb1c8 100644
--- a/Main/System/HeroDebut/HeroDebutManager.cs
+++ b/Main/System/HeroDebut/HeroDebutManager.cs
@@ -78,9 +78,9 @@
     private void OnBeforePlayerDataInitializeEventOnRelogin()
     {
         isSendFirst = true;
-        starHeroIndexDict.Clear();
+        starHeroIndex = 0;
+        callHeroIndex = 0;
         starFreeAwardDict.Clear();
-        callHeroIndexDict.Clear();
     }
 
     private void OnPlayerLoginOk()
@@ -117,6 +117,7 @@
                 UIManager.Instance.CloseWindow<HeroDebutPopWin>();
             if (UIManager.Instance.IsOpened<HeroDebutWin>())
                 UIManager.Instance.CloseWindow<HeroDebutWin>();
+            gameRecDict.Clear();
             UpdateRedpoint();
         }
     }
@@ -237,22 +238,23 @@
             OnNowCallChooseHeroIDChangeEvent?.Invoke();
         }
     }
-    public event Action<int> OnUpdateHeroAppearPlayerInfoEvent;
+    public int starHeroIndex = 0;
+    public int callHeroIndex = 0;
+    //<鍗囨槦璁″垝閫夋嫨鐨勬灏咺D绱㈠紩,鍗囨槦璁″垝鍏嶈垂濂栧姳璁板綍>
+    Dictionary<int, uint> starFreeAwardDict = new();
+
+    public event Action OnUpdateHeroAppearPlayerInfoEvent;
     public void UpdateHeroAppearPlayerInfo(HAA22_tagSCActHeroAppearPlayerInfo vNetData)
     {
         if (vNetData == null) return;
-        int actNum = vNetData.ActNum;
-        starHeroIndexDict[actNum] = vNetData.StarHeroIndex;
-        callHeroIndexDict[actNum] = vNetData.CallHeroIndex;
+        if (vNetData.ActNum != this.actNum) return;
 
-        if (!starFreeAwardDict.TryGetValue(actNum, out var dict))
-        {
-            dict = new Dictionary<int, uint>();
-            starFreeAwardDict[actNum] = dict;
-        }
-        dict[vNetData.StarHeroIndex] = vNetData.StarFreeAward;
+        int actNum = vNetData.ActNum;
+        starHeroIndex = vNetData.StarHeroIndex;
+        callHeroIndex = vNetData.CallHeroIndex;
+        starFreeAwardDict[starHeroIndex] = vNetData.StarFreeAward;
         UpdateRedpoint();
-        OnUpdateHeroAppearPlayerInfoEvent?.Invoke(actNum);
+        OnUpdateHeroAppearPlayerInfoEvent?.Invoke();
     }
 
     public void SendHeroAppearStarHeroSelect(int actNum, int starHeroIndex)
@@ -426,12 +428,6 @@
 
     #region 鍗囨槦璁″垝
 
-    //<娲诲姩缂栧彿,鍗囨槦璁″垝閫夋嫨鐨勬灏咺D绱㈠紩>
-    public Dictionary<int, int> starHeroIndexDict = new();
-
-    //<娲诲姩缂栧彿,<鍗囨槦璁″垝閫夋嫨鐨勬灏咺D绱㈠紩,鍗囨槦璁″垝鍏嶈垂濂栧姳璁板綍>>
-    public Dictionary<int, Dictionary<int, uint>> starFreeAwardDict = new();
-
     /// <summary>
     /// 褰撳墠鍗囨槦璁″垝閫変腑鐨勬灏咺D
     /// </summary>
@@ -439,12 +435,11 @@
     {
         var act = GetOperationHeroAppearInfo();
         if (act == null) return 0;
-        if (!starHeroIndexDict.TryGetValue(actNum, out int index)) return 0;
 
         var config = ActHeroAppearConfig.Get(act.CfgID);
-        if (config == null || config.ActHeroIDList?.Length <= index) return 0;
+        if (config == null || config.ActHeroIDList?.Length <= starHeroIndex) return 0;
 
-        return config.ActHeroIDList[index];
+        return config.ActHeroIDList[starHeroIndex];
     }
 
     private Dictionary<int, Dictionary<int, int[][]>> showHeroGiftItemInfoDict = new();
@@ -502,16 +497,14 @@
         // 娌¤幏寰楁灏嗘湰浣撲笉鍙鍙�
         if (!HeroManager.Instance.HasHero(heroId))return 0;
         
-        if (!starHeroIndexDict.TryGetValue(actNum, out int index)) return 0;
-        if (IsStarUpFreeHave(index, config.AwardIndex)) return 2;
+        if (IsStarUpFreeHave(starHeroIndex, config.AwardIndex)) return 2;
         if (IsHeroStarCntOk(heroConfig.HeroID, config.NeedStar)) return 1;
         return 0;
     }
 
     private bool IsStarUpFreeHave(int starHeroIndex, int awardIndex)
     {
-        if (!starFreeAwardDict.TryGetValue(actNum, out var dict)) return false;
-        if (!dict.TryGetValue(starHeroIndex, out uint freeAward)) return false;
+        if (!starFreeAwardDict.TryGetValue(starHeroIndex, out uint freeAward)) return false;
         return ((freeAward >> awardIndex) & 1u) == 1u;
     }
 
@@ -538,7 +531,7 @@
     public bool TryGetStarUpStateIndex(int starGiftTempID, int tarState, out int index)
     {
         index = 0;
-        var list = ActHeroAppearStarConfig.GetAwardIndexSortList(starGiftTempID);
+        var list = ActHeroAppearStarConfig.GetHeroDebutAwardIndexSortList(starGiftTempID);
         if (list == null) return false;
 
         for (int i = 0; i < list.Count; i++)
@@ -727,7 +720,7 @@
     }
     private string GetCallSkipKey(int cfgID, OperationDate startDate, OperationDate endDate)
     {
-        return string.Concat("HeroDebutManager_CallSkip_", cfgID, ToInt(startDate), ToInt(endDate), PlayerDatas.Instance.PlayerId);
+        return string.Concat("HeroDebutManager_CallSkip_", cfgID, "_", ToInt(startDate), "_", ToInt(endDate), "_", PlayerDatas.Instance.PlayerId);
     }
 
     public bool LoadCallSkipData(int cfgID, OperationDate startDate, OperationDate endDate)
@@ -740,9 +733,6 @@
         LocalSave.SetBool(GetCallSkipKey(cfgID, startDate, endDate), value);
     }
 
-    //<娲诲姩缂栧彿,鎷涘嫙閫夋嫨鐨勬灏咺D绱㈠紩>
-    public Dictionary<int, int> callHeroIndexDict = new();
-
     /// <summary>
     /// 褰撳墠鎷涘嫙閫変腑鐨勬灏咺D
     /// </summary>
@@ -750,12 +740,11 @@
     {
         var act = GetOperationHeroAppearInfo();
         if (act == null) return 0;
-        if (!callHeroIndexDict.TryGetValue(actNum, out int index)) return 0;
 
         var config = ActHeroAppearConfig.Get(act.CfgID);
-        if (config == null || config.ActHeroIDList?.Length <= index) return 0;
+        if (config == null || config.ActHeroIDList?.Length <= callHeroIndex) return 0;
 
-        return config.ActHeroIDList[index];
+        return config.ActHeroIDList[callHeroIndex];
     }
 
 
@@ -954,19 +943,10 @@
     {
         return gameRecDict;
     }
-    public List<HeroDebutGameRec> GetLastFourRecords()
-    {
-        if (gameRecDict == null || gameRecDict.Count == 0) return new List<HeroDebutGameRec>();
-
-        int count = gameRecDict.Count;
-        int takeCount = Math.Min(4, count);
-        return gameRecDict.GetRange(count - takeCount, takeCount);
-    }
 
     public event Action OnUpdateGameRecInfo;
     public void UpdateGameRecInfo(HA009_tagSCGameRecInfo vNetData)
     {
-
         var act = GetOperationHeroAppearInfo();
         if (act == null) return;
 
diff --git a/Main/System/HeroDebut/HeroDebutPopWin.cs b/Main/System/HeroDebut/HeroDebutPopWin.cs
index ee36891..9a04102 100644
--- a/Main/System/HeroDebut/HeroDebutPopWin.cs
+++ b/Main/System/HeroDebut/HeroDebutPopWin.cs
@@ -69,7 +69,7 @@
         uiEffectPlayer.effectId = artConfig.PopInfoBgUIEffectId;
         uiEffectPlayer.Play();
 
-        bgImage.SetSprite(artConfig.PopBgImage);
+        bgImage.SetSprite(StringUtility.Concat("HeroDebutPopBG_", heroID.ToString()));
         bgImage.SetNativeSize();
 
         qaulityBgImage.SetSprite($"HeroDebutPopQaulityBG{heroConfig.Quality}");
@@ -78,13 +78,13 @@
         qaulityImage.SetSprite($"HeroDebutPopQaulity{heroConfig.Quality}");
         qaulityImage.SetNativeSize();
 
-        titleBgImage.SetSprite(artConfig.PopTitleBgImage);
+        titleBgImage.SetSprite(StringUtility.Concat("HeroDebutPopTitleBG_", heroID.ToString()));
         titleBgImage.SetNativeSize();
 
-        titleImage.SetSprite(artConfig.PopTitleImage);
+        titleImage.SetSprite(StringUtility.Concat("HeroDebutPopTitle_", heroID.ToString()));
         titleImage.SetNativeSize();
 
-        infoBgImage.SetSprite(artConfig.PopInfoBgImage);
+        infoBgImage.SetSprite(StringUtility.Concat("HeroDebutPopInfoBG_", heroID.ToString()));
         infoBgImage.SetNativeSize();
 
         infoText.text = artConfig.PopInfoText;
diff --git a/Main/System/HeroDebut/HeroDebutRankWin.cs b/Main/System/HeroDebut/HeroDebutRankWin.cs
index f35f885..ecfc9f8 100644
--- a/Main/System/HeroDebut/HeroDebutRankWin.cs
+++ b/Main/System/HeroDebut/HeroDebutRankWin.cs
@@ -100,8 +100,6 @@
     public void Display()
     {
         int heroID = manager.GetCurrentDisplayCallHeroId();
-        var artConfig = ActHeroAppearArtConfig.Get(heroID);
-        if (artConfig == null) return;
 
         if (functionOrder == 0)
         {
@@ -112,7 +110,7 @@
         else
         {
             CreateAwardScroller();
-            heroImage.SetSprite(artConfig.RankAwardHeroImage);
+            heroImage.SetSprite(StringUtility.Concat("HeroDebutRankAwardHero_", heroID.ToString()));
             heroImage.SetNativeSize();
             DisplayAwardMyRank();
         }
diff --git a/Main/System/HeroDebut/HeroDebutSkinTabCell.cs b/Main/System/HeroDebut/HeroDebutSkinTabCell.cs
index 998d893..386e063 100644
--- a/Main/System/HeroDebut/HeroDebutSkinTabCell.cs
+++ b/Main/System/HeroDebut/HeroDebutSkinTabCell.cs
@@ -13,10 +13,8 @@
         if (list?.Count <= index) return;
 
         var skinID = list[index];
-        var skinArtConfig = ActHeroAppearSkinArtConfig.Get(skinID);
-        if (skinArtConfig == null) return;
 
-        tabBgImage.SetSprite(skinArtConfig.TabInfoImage);
+        tabBgImage.SetSprite(StringUtility.Concat("HeroDebutSkinTabInfo_", skinID.ToString()));
         tabBgImage.SetNativeSize();
         maskRect.SetActive(manager.currentChooseSkinID != skinID);
         chooseRect.SetActive(manager.currentChooseSkinID == skinID);
diff --git a/Main/System/HeroDebut/HeroDebutSkinWin.cs b/Main/System/HeroDebut/HeroDebutSkinWin.cs
index e29eff3..6d21d22 100644
--- a/Main/System/HeroDebut/HeroDebutSkinWin.cs
+++ b/Main/System/HeroDebut/HeroDebutSkinWin.cs
@@ -148,8 +148,6 @@
         if (heroConfig == null) return;
 
         int skinID = manager.currentChooseSkinID;
-        var skinArtConfig = ActHeroAppearSkinArtConfig.Get(skinID);
-        if (skinArtConfig == null) return;
 
         var heroSkinAttrConfig = HeroSkinAttrConfig.Get(skinID);
         if (heroSkinAttrConfig == null) return;
@@ -169,15 +167,15 @@
         if (!RechargeManager.Instance.TryGetRechargeCount(ctgId, out var rechargeCount)) return;
         if (!RechargeManager.Instance.TryGetRechargeItem(ctgId, out var rechargeItemList)) return;
 
-        bgImage.SetTexture2D(skinArtConfig.BGImage);
+        bgImage.SetTexture2D(StringUtility.Concat("HeroDebutSkinBG_", skinID.ToString()));
 
-        heroNameImage.SetSprite(skinArtConfig.HeroNameImage);
+        heroNameImage.SetSprite(StringUtility.Concat("HeroDebutSkinHeroName_", skinID.ToString()));
         heroNameImage.SetNativeSize();
 
-        skinInfoImage.SetSprite(skinArtConfig.SkinInfoImage);
+        skinInfoImage.SetSprite(StringUtility.Concat("HeroDebutSkinInfo_", skinID.ToString()));
         skinInfoImage.SetNativeSize();
 
-        awardBgImage.SetSprite(skinArtConfig.AwardBGImage);
+        awardBgImage.SetSprite(StringUtility.Concat("HeroDebutSkinAwardBG_", skinID.ToString()));
         awardBgImage.SetNativeSize();
 
         uiHeroController.Create(skinID, modelScale).Forget();
diff --git a/Main/System/HeroDebut/HeroDebutStarUpWin.cs b/Main/System/HeroDebut/HeroDebutStarUpWin.cs
index c43280e..93aa082 100644
--- a/Main/System/HeroDebut/HeroDebutStarUpWin.cs
+++ b/Main/System/HeroDebut/HeroDebutStarUpWin.cs
@@ -45,7 +45,7 @@
         manager.OnUpdateHeroAppearPlayerInfoEvent -= OnUpdateHeroAppearPlayerInfoEvent;
     }
 
-    private void OnUpdateHeroAppearPlayerInfoEvent(int obj)
+    private void OnUpdateHeroAppearPlayerInfoEvent()
     {
         scroller.m_Scorller.RefreshActiveCellViews();
     }
@@ -85,7 +85,7 @@
         heroNameText.text = heroConfig.Name;
         manager.SetGradientTextColor(heroNameText, artConfig.HeroNameColor);
         
-        heroImage.SetSprite(artConfig.StarUpHeroImage);
+        heroImage.SetSprite(StringUtility.Concat("HeroDebutStarUpHero_", heroID.ToString()));
         heroImage.SetNativeSize();
 
         CreateScroller(config, heroConfig);
@@ -97,7 +97,7 @@
 
         if (appearConfig == null || heroConfig == null) return;
         int starGiftTempID = appearConfig.StarGiftTempID;
-        var list = ActHeroAppearStarConfig.GetAwardIndexSortList(starGiftTempID);
+        var list = ActHeroAppearStarConfig.GetHeroDebutAwardIndexSortList(starGiftTempID);
         if (list == null) return;
 
         scroller.Refresh();
diff --git a/Main/System/HeroDebut/HeroDebutWin.cs b/Main/System/HeroDebut/HeroDebutWin.cs
index e82e4fd..13fa454 100644
--- a/Main/System/HeroDebut/HeroDebutWin.cs
+++ b/Main/System/HeroDebut/HeroDebutWin.cs
@@ -61,7 +61,7 @@
         manager.OnUpdateHeroAppearPlayerInfoEvent -= OnUpdateHeroAppearPlayerInfoEvent;
     }
 
-    private void OnUpdateHeroAppearPlayerInfoEvent(int obj)
+    private void OnUpdateHeroAppearPlayerInfoEvent()
     {
         Display();
     }
@@ -87,11 +87,6 @@
         if (artConfig == null) return;
 
         int skinID = manager.GetDefaultSkinID(heroID);
-        var skinConfig = HeroSkinConfig.Get(skinID);
-        if (skinConfig == null) return;
-
-        var skinArtConfig = ActHeroAppearSkinArtConfig.Get(artConfig.MainSkinID);
-        if (skinArtConfig == null) return;
 
         uiHeroController.Create(skinID, modleSize).Forget();
         uiHeroController.transform.localScale = new Vector3(-modleSize, modleSize, modleSize);
@@ -99,13 +94,13 @@
 
         callRedImage.SetActive(!manager.IsShopVisitedToday || manager.HasGiftCanHave());
 
-        bgImage.SetSprite(artConfig.MainBgImage);
+        bgImage.SetSprite(StringUtility.Concat("HeroDebutMainBG_", heroID.ToString()));
         bgImage.SetNativeSize();
 
-        titleImage.SetSprite(artConfig.MainTitleImage);
+        titleImage.SetSprite(StringUtility.Concat("HeroDebutMainTitle_", heroID.ToString()));
         titleImage.SetNativeSize();
 
-        skinImage.SetSprite(skinArtConfig.MainSkinBuyBgImage);
+        skinImage.SetSprite(StringUtility.Concat("HeroDebutSkinEnterBG_", artConfig.MainSkinID.ToString()));
         OnSecondEvent();
     }
 
diff --git a/Main/System/HeroReturn.meta b/Main/System/HeroReturn.meta
new file mode 100644
index 0000000..70a9ff5
--- /dev/null
+++ b/Main/System/HeroReturn.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ad40f79e4689d234fac9fc2f4d8be9a7
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroReturn/HeroReturnCallBubbleCell.cs b/Main/System/HeroReturn/HeroReturnCallBubbleCell.cs
new file mode 100644
index 0000000..9b4af0c
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallBubbleCell.cs
@@ -0,0 +1,23 @@
+using UnityEngine;
+
+public class HeroReturnCallBubbleCell : MonoBehaviour
+{
+    [SerializeField] ButtonEx clickButton;
+    [SerializeField] ImageEx bgImage;
+    [SerializeField] ImageEx iconImage;
+    [SerializeField] TextEx countText;
+    public void Display(int itemID, int count)
+    {
+        var config = ItemConfig.Get(itemID);
+        if (config == null) return;
+
+        bgImage.SetSprite($"HeroDebutCallBubbleBG{config.ItemColor}");
+        iconImage.SetItemSprite(itemID);
+        iconImage.SetNativeSize();
+        countText.text = count.ToString();
+
+        clickButton.SetListener(() => ItemTipUtility.Show(itemID));
+    }
+
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallBubbleCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallBubbleCell.cs.meta
index 862a125..4138c02 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallBubbleCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 10ed3265b0279984dbb79382f829567a
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallButton.cs b/Main/System/HeroReturn/HeroReturnCallButton.cs
new file mode 100644
index 0000000..fdd1419
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallButton.cs
@@ -0,0 +1,95 @@
+using UnityEngine;
+
+public class HeroReturnCallButton : MonoBehaviour
+{
+    [SerializeField] ButtonEx clickButton;
+    [SerializeField] TextEx callText;
+    [SerializeField] TextEx needText;
+    [SerializeField] ImageEx needImage;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    HappyXBModel xbManager => HappyXBModel.Instance;
+    int index;
+    int type;
+    int needCostItemCnt;
+    long hasItemCnt;
+    int needCostMoneyCnt;
+    long moneyCount;
+    public void Display(int treasureType, int index)
+    {
+        this.index = index;
+        type = treasureType;
+        var treasureSetConfig = TreasureSetConfig.Get(treasureType);
+        if (treasureSetConfig == null) return;
+        if (treasureSetConfig.TreasureCountList == null || treasureSetConfig.TreasureCountList.Length <= index) return;
+        if (treasureSetConfig.CostItemCountList == null || treasureSetConfig.CostItemCountList.Length <= index) return;
+        if (treasureSetConfig.CostMoneyList == null || treasureSetConfig.CostMoneyList.Length <= index) return;
+
+        XBTypeInfo info = xbManager.GetXBInfoByType(treasureType);
+        if (info == null) return;
+
+        int treasureCnt = treasureSetConfig.TreasureCountList[index];
+
+        callText.text = Language.Get("HeroDebut23", treasureCnt);
+
+        int dailyMaxCountMoney = treasureSetConfig.DailyMaxCountMoney;
+        int nowMoneyCnt = info.treasureCountTodayGold;
+
+        needCostMoneyCnt = treasureSetConfig.CostMoneyList[index];
+        moneyCount = UIHelper.GetMoneyCnt(treasureSetConfig.CostMoneyType);
+
+        needCostItemCnt = treasureSetConfig.CostItemCountList[index];
+        hasItemCnt = PackManager.Instance.GetItemCountByID(PackType.Item, treasureSetConfig.CostItemID);
+
+        // 鐗╁搧涓嶈冻 && 娌¤秴璐у竵鎷涘嫙娆℃暟涓婇檺 
+        if (hasItemCnt < needCostItemCnt &&
+            nowMoneyCnt + treasureCnt <= dailyMaxCountMoney)
+        {
+            DisplayByMoney(treasureSetConfig.CostMoneyType, needCostMoneyCnt, moneyCount);
+            return;
+        }
+        DisplayByItem(treasureSetConfig.CostItemID, treasureCnt);
+    }
+
+    void DisplayByMoney(int moneyType, long needCostMoneyCnt, long moneyCount)
+    {
+
+        bool isEnough = moneyCount >= needCostMoneyCnt;
+        needText.text = Language.Get("L1100", RichTextMsgReplaceConfig.GetRichReplace("MONEY", moneyType), UIHelper.AppendColor(!isEnough ? TextColType.Red : TextColType.LightGreen, needCostMoneyCnt.ToString()));
+        needImage.SetIconWithMoneyType(moneyType);
+
+        clickButton.SetListener(() =>
+        {
+            if (!isEnough)
+            {
+                ItemTipUtility.ShowMoneyTip(moneyType, true);
+                return;
+            }
+            HeroUIManager.Instance.selectCallType = (HappXBTitle)type;
+            HeroUIManager.Instance.selectCallIndex = index;
+            HappyXBModel.Instance.SendXBQuest(type, index, 0);
+        });
+    }
+
+    void DisplayByItem(int itemID, int count)
+    {
+        ItemConfig itemConfig = ItemConfig.Get(itemID);
+        if (itemConfig == null) return;
+        bool isEnough = hasItemCnt >= needCostItemCnt;
+        needText.text = Language.Get("L1100", itemConfig.ItemName, UIHelper.AppendColor(!isEnough ? TextColType.Red : TextColType.LightGreen, count.ToString()));
+        needImage.SetItemSprite(itemID);
+
+        clickButton.SetListener(() =>
+        {
+            if (!isEnough)
+            {
+                ItemTipUtility.Show(itemID, true);
+                return;
+            }
+            HeroUIManager.Instance.selectCallType = (HappXBTitle)type;
+            HeroUIManager.Instance.selectCallIndex = index;
+            HappyXBModel.Instance.SendXBQuest(type, index, 2);
+        });
+
+    }
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallButton.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallButton.cs.meta
index 862a125..f6fdfb8 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallButton.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: d55190ecb673d464f88f4ec0a5425732
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallChangeCell.cs b/Main/System/HeroReturn/HeroReturnCallChangeCell.cs
new file mode 100644
index 0000000..c1cf3e5
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallChangeCell.cs
@@ -0,0 +1,33 @@
+using UnityEngine;
+
+public class HeroReturnCallChangeCell : CellView
+{
+    [SerializeField] HeroReturnCallChangeItem[] items;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    public void Display(int rowIndex)
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        var heroArr = config.ActHeroIDList;
+        if (heroArr.IsNullOrEmpty()) return;
+
+        for (int i = 0; i < items.Length; i++)
+        {
+            int index = rowIndex * HeroReturnCallChangeWin.rowCountMax + i;
+            if (index < heroArr.Length)
+            {
+                items[i].SetActive(true);
+                items[i].Display(index, heroArr, act.CfgID);
+            }
+            else
+            {
+                items[i].SetActive(false);
+            }
+        }
+    }
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallChangeCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallChangeCell.cs.meta
index 862a125..08b9f82 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallChangeCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: e0d034734cb56844cb0216e77c5b3440
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallChangeItem.cs b/Main/System/HeroReturn/HeroReturnCallChangeItem.cs
new file mode 100644
index 0000000..445c6e4
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallChangeItem.cs
@@ -0,0 +1,41 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnCallChangeItem : MonoBehaviour
+{
+
+    [SerializeField] HeroHeadBaseCell heroHeadBaseCell;
+    [SerializeField] Image jobImg;
+    [SerializeField] Text nameText;
+    [SerializeField] Transform select;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    HeroConfig heroConfig;
+    int index;
+    public void Display(int index, int[] heroIds, int cfgId)
+    {
+        this.index = index;
+        if (heroIds?.Length <= index) return;
+
+        int heroId = heroIds[index];
+        heroConfig = HeroConfig.Get(heroId);
+        if (heroConfig == null) return;
+        
+        int skinID = manager.GetDefaultSkinID(heroId);
+        var heroSkinConfig = HeroSkinConfig.Get(skinID);
+        if (heroSkinConfig == null) return;
+
+        heroHeadBaseCell.Init(heroConfig.HeroID, skinID, 0, 0, 0, OnClick);
+        nameText.text = heroConfig.Name;
+        jobImg.SetSprite(HeroUIManager.Instance.GetJobIconName(heroConfig.Class));
+        bool isChoose = manager.nowCallChooseHeroID == heroId;
+        select?.SetActive(isChoose);
+    }
+
+    public void OnClick()
+    {
+        if (heroConfig == null) return;
+
+        manager.nowCallChooseHeroID = heroConfig.HeroID;
+
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallChangeItem.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallChangeItem.cs.meta
index 862a125..d124830 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallChangeItem.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 0720ebe725ea61345a7c09406a98e96e
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallChangeWin.cs b/Main/System/HeroReturn/HeroReturnCallChangeWin.cs
new file mode 100644
index 0000000..0785f57
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallChangeWin.cs
@@ -0,0 +1,100 @@
+using UnityEngine;
+
+public class HeroReturnCallChangeWin : UIBase
+{
+    [SerializeField] ScrollerController scroller;
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] ButtonEx okButton;
+    [SerializeField] ButtonEx previewButton;
+    [SerializeField] UIHeroController uiHeroController;
+    public const int rowCountMax = 4;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+        okButton.SetListener(() =>
+        {
+            var act = manager.GetOperationHeroAppearInfo();
+            if (act == null) return;
+
+            int index = manager.GetHeroIdIndex(act.CfgID, manager.nowCallChooseHeroID);
+            if (index < 0) return;
+
+            if (manager.GetCurrentDisplayCallHeroId() == manager.nowCallChooseHeroID)
+            {
+                SysNotifyMgr.Instance.ShowTip("HeroDebut01");
+                return;
+            }
+
+            manager.SnedHeroAppearCallHeroSelect(manager.actNum, index);
+            CloseWindow();
+        });
+        previewButton.SetListener(() =>
+        {
+            HeroUIManager.Instance.selectForPreviewHeroID = manager.nowCallChooseHeroID;
+            UIManager.Instance.OpenWindow<HeroBestBaseWin>();
+        });
+    }
+
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+        manager.OnNowCallChooseHeroIDChangeEvent += OnNowCallChooseHeroIDChangeEvent;
+        manager.nowCallChooseHeroID = manager.GetCurrentDisplayCallHeroId();
+        Display();
+        CreateScroller();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+        manager.OnNowCallChooseHeroIDChangeEvent -= OnNowCallChooseHeroIDChangeEvent;
+    }
+
+    private void OnNowCallChooseHeroIDChangeEvent()
+    {
+        Display();
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnCallChangeCell;
+        _cell.Display(cell.index);
+    }
+
+    void CreateScroller()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        var arr = config.ActHeroIDList;
+        if (arr.IsNullOrEmpty()) return;
+
+
+        scroller.Refresh();
+        int rowCount = (int)Mathf.Ceil((float)arr.Length / rowCountMax);
+        for (int i = 0; i < rowCount; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, i);
+        }
+        scroller.Restart();
+    }
+
+    void Display()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+
+        int skinID = manager.GetDefaultSkinID(manager.nowCallChooseHeroID);
+        var skinConfig = HeroSkinConfig.Get(skinID);
+        if (skinConfig == null) return;
+
+        uiHeroController.Create(skinID, 1);
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallChangeWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallChangeWin.cs.meta
index 862a125..8ab7665 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallChangeWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 8aa8fd53cfed7704f8a1b6b0b8d75407
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallChooseCell.cs b/Main/System/HeroReturn/HeroReturnCallChooseCell.cs
new file mode 100644
index 0000000..cc3c8f3
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallChooseCell.cs
@@ -0,0 +1,33 @@
+using UnityEngine;
+
+public class HeroReturnCallChooseCell : CellView
+{
+    [SerializeField] HeroReturnCallChooseItem[] items;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    public void Display(int rowIndex)
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        var heroArr = config.ActHeroIDList;
+        if (heroArr.IsNullOrEmpty()) return;
+
+        for (int i = 0; i < items.Length; i++)
+        {
+            int index = rowIndex * HeroReturnCallChangeWin.rowCountMax + i;
+            if (index < heroArr.Length)
+            {
+                items[i].SetActive(true);
+                items[i].Display(index, heroArr, act.CfgID);
+            }
+            else
+            {
+                items[i].SetActive(false);
+            }
+        }
+    }
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallChooseCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallChooseCell.cs.meta
index 862a125..6e708f9 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallChooseCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 0f45542ad2c6a5a4a9b16dacda70e468
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallChooseItem.cs b/Main/System/HeroReturn/HeroReturnCallChooseItem.cs
new file mode 100644
index 0000000..f7fc4bd
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallChooseItem.cs
@@ -0,0 +1,41 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnCallChooseItem : MonoBehaviour
+{
+
+    [SerializeField] HeroHeadBaseCell heroHeadBaseCell;
+    [SerializeField] Image jobImg;
+    [SerializeField] Text nameText;
+    [SerializeField] Transform select;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    HeroConfig heroConfig;
+    int index;
+    public void Display(int index, int[] heroIds, int cfgId)
+    {
+        this.index = index;
+        if (heroIds?.Length <= index) return;
+
+        int heroId = heroIds[index];
+        heroConfig = HeroConfig.Get(heroId);
+        if (heroConfig == null) return;
+        
+        int skinID = manager.GetDefaultSkinID(heroId);
+        var heroSkinConfig = HeroSkinConfig.Get(skinID);
+        if (heroSkinConfig == null) return;
+
+        heroHeadBaseCell.Init(heroConfig.HeroID, skinID, 0, 0, 0, OnClick);
+        nameText.text = heroConfig.Name;
+        jobImg.SetSprite(HeroUIManager.Instance.GetJobIconName(heroConfig.Class));
+        bool isChoose = manager.nowCallChooseHeroID == heroId;
+        select?.SetActive(isChoose);
+    }
+
+    public void OnClick()
+    {
+        if (heroConfig == null) return;
+
+        manager.nowCallChooseHeroID = heroConfig.HeroID;
+
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallChooseItem.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallChooseItem.cs.meta
index 862a125..c59d10d 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallChooseItem.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 05796103e33a5c44b9ab102ee2fde400
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallChooseWin.cs b/Main/System/HeroReturn/HeroReturnCallChooseWin.cs
new file mode 100644
index 0000000..1a9b81d
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallChooseWin.cs
@@ -0,0 +1,95 @@
+using UnityEngine;
+
+public class HeroReturnCallChooseWin : UIBase
+{
+    [SerializeField] ScrollerController scroller;
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] ButtonEx okButton;
+    [SerializeField] ButtonEx previewButton;
+    [SerializeField] UIHeroController uiHeroController;
+    public const int rowCountMax = 4;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+        okButton.SetListener(() =>
+        {
+            var act = manager.GetOperationHeroAppearInfo();
+            if (act == null) return;
+
+            int index = manager.GetHeroIdIndex(act.CfgID, manager.nowCallChooseHeroID);
+            if (index < 0) return;
+
+            manager.SnedHeroAppearCallHeroSelect(manager.actNum, index);
+            manager.SaveCallChooseHeroStateKey(act);
+            CloseWindow();
+        });
+        previewButton.SetListener(() =>
+        {
+            HeroUIManager.Instance.selectForPreviewHeroID = manager.nowCallChooseHeroID;
+            UIManager.Instance.OpenWindow<HeroBestBaseWin>();
+        });
+    }
+
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+        manager.OnNowCallChooseHeroIDChangeEvent += OnNowCallChooseHeroIDChangeEvent;
+        manager.nowCallChooseHeroID = manager.GetCurrentDisplayCallHeroId();
+        Display();
+        CreateScroller();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+        manager.OnNowCallChooseHeroIDChangeEvent -= OnNowCallChooseHeroIDChangeEvent;
+    }
+
+    private void OnNowCallChooseHeroIDChangeEvent()
+    {
+        Display();
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnCallChooseCell;
+        _cell.Display(cell.index);
+    }
+
+    void CreateScroller()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        var arr = config.ActHeroIDList;
+        if (arr.IsNullOrEmpty()) return;
+
+
+        scroller.Refresh();
+        int rowCount = (int)Mathf.Ceil((float)arr.Length / rowCountMax);
+        for (int i = 0; i < rowCount; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, i);
+        }
+        scroller.Restart();
+    }
+
+    void Display()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+
+        int skinID = manager.GetDefaultSkinID(manager.nowCallChooseHeroID);
+        var skinConfig = HeroSkinConfig.Get(skinID);
+        if (skinConfig == null) return;
+
+        uiHeroController.Create(skinID, 1);
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallChooseWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallChooseWin.cs.meta
index 862a125..bcd91e2 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallChooseWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: df583e8bc2fc9ab47ab8db4a977622bc
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallHistoryCell.cs b/Main/System/HeroReturn/HeroReturnCallHistoryCell.cs
new file mode 100644
index 0000000..004969a
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallHistoryCell.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnCallHistoryCell : CellView
+{
+    [SerializeField] Color nameColor;
+    [SerializeField] TextEx infoText;
+    public virtual void Display(int index, List<HeroReturnGameRec> list)
+    {
+        if (list?.Count <= index) return;
+        var rec = list[index];
+
+        var itemconfig = ItemConfig.Get(rec.ItemID);
+        if (itemconfig == null) return;
+
+        //150 鏁翠釜姝﹀皢
+        if (itemconfig.Type == 150)
+        {
+            HeroConfig heroConfig = HeroConfig.Get(rec.ItemID);
+            if (heroConfig == null) return;
+            int quality = heroConfig.Quality;
+
+            infoText.text = Language.Get("HeroDebut29",
+                UIHelper.AppendColor(nameColor, rec.PlayerName),
+                UIHelper.AppendColor(UIHelper.GetUIColorByFunc(quality), Language.Get(StringUtility.Concat("CommonQuality", quality.ToString()))),
+                UIHelper.AppendColor(UIHelper.GetUIColorByFunc(quality), heroConfig.Name.ToString())
+            );
+        }
+        else
+        {
+            int quality = itemconfig.ItemColor;
+
+            infoText.text = Language.Get("HeroDebut30",
+                UIHelper.AppendColor(nameColor, rec.PlayerName),
+                UIHelper.AppendColor(UIHelper.GetUIColorByFunc(quality), itemconfig.ItemName.ToString()),
+                rec.ItemCount.ToString()
+            );
+        }
+
+    }
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallHistoryCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallHistoryCell.cs.meta
index 862a125..2ec4019 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallHistoryCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 38c9c575a3a11064597472dbd5e95a43
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallHistoryOutCell.cs b/Main/System/HeroReturn/HeroReturnCallHistoryOutCell.cs
new file mode 100644
index 0000000..f737547
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallHistoryOutCell.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnCallHistoryOutCell : HeroReturnCallHistoryCell
+{
+    [SerializeField] CanvasGroup canvasGroup;
+  
+    public override void Display(int index, List<HeroReturnGameRec> list)
+    {
+        base.Display(index, list);
+    }
+
+    // 鎻愪緵缁欏閮ㄨ缃�忔槑搴︾殑鏂规硶
+    public void SetAlpha(float alpha)
+    {
+        if (canvasGroup != null)
+        {
+            canvasGroup.alpha = alpha;
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallHistoryOutCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallHistoryOutCell.cs.meta
index 862a125..842da88 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallHistoryOutCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 8239f369fcc315847a4e250422c234d6
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallHistoryWin.cs b/Main/System/HeroReturn/HeroReturnCallHistoryWin.cs
new file mode 100644
index 0000000..61e5a66
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallHistoryWin.cs
@@ -0,0 +1,57 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnCallHistoryWin : UIBase
+{
+    [SerializeField] ScrollerController scroller;
+    [SerializeField] RectTransform noRect;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+
+    protected override void OnPreOpen()
+    {
+        scroller.lockType = EnhanceLockType.LockVerticalBottom;
+
+        scroller.OnRefreshCell += OnRefreshCell;
+        manager.OnUpdateGameRecInfo += OnUpdateGameRecInfo;
+
+        CreateScroller();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+        manager.OnUpdateGameRecInfo -= OnUpdateGameRecInfo;
+    }
+
+    private void OnUpdateGameRecInfo()
+    {
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnCallHistoryCell;
+        _cell.Display(cell.index, list);
+    }
+    public List<HeroReturnGameRec> list;
+
+    void CreateScroller()
+    {
+        list = manager.GetGameRecList();
+        if (list == null)
+        {
+            noRect.SetActive(true);
+            scroller.SetActive(false);
+            return;
+        }
+        noRect.SetActive(false);
+        scroller.SetActive(true);
+
+        scroller.Refresh();
+        for (int i = 0; i < list.Count; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, i);
+        }
+        scroller.Restart();
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallHistoryWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallHistoryWin.cs.meta
index 862a125..0b1ee58 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallHistoryWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 10151abcb0caf394aa8caa2c00f25bbe
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallRateCell.cs b/Main/System/HeroReturn/HeroReturnCallRateCell.cs
new file mode 100644
index 0000000..a99be23
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallRateCell.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnCallRateCell : CellView
+{
+    [SerializeField] HeroReturnCallRateItem[] items;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+
+    public void Display(int rowIndex, Dictionary<int, int> gridRateDict, List<int> gridList, XBGetItemConfig xbConfig)
+    {
+        if (gridList == null) return;
+
+        for (int i = 0; i < items.Length; i++)
+        {
+            int index = rowIndex * HeroReturnCallChangeWin.rowCountMax + i;
+            if (index < gridList.Count)
+            {
+                items[i].SetActive(true);
+                items[i].Display(index, gridRateDict, gridList, xbConfig);
+            }
+            else
+            {
+                items[i].SetActive(false);
+            }
+        }
+    }
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallRateCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallRateCell.cs.meta
index 862a125..6e8fa65 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallRateCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: cc363b85a77d3ce4b92b8f4ce95f524f
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallRateHeroCell.cs b/Main/System/HeroReturn/HeroReturnCallRateHeroCell.cs
new file mode 100644
index 0000000..f6052a4
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallRateHeroCell.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnCallRateHeroCell : CellView
+{
+
+    [SerializeField] ItemCell[] itemCells;
+    public void Display(int rowIndex, List<Item> dataList)
+    {
+        if (dataList == null) return;
+
+        for (int i = 0; i < itemCells.Length; i++)
+        {
+            int dataIndex = rowIndex * HeroReturnCallRateHeroWin.rowCountMax + i;
+
+            if (dataIndex < dataList.Count)
+            {
+                itemCells[i].SetActive(true);
+                itemCells[i].Init(new ItemCellModel(dataList[dataIndex].id, true, dataList[dataIndex].countEx));
+                itemCells[i].button.SetListener(() => ItemTipUtility.Show(dataList[dataIndex].id));
+            }
+            else
+            {
+                itemCells[i].SetActive(false);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallRateHeroCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallRateHeroCell.cs.meta
index 862a125..cdaec55 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallRateHeroCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 75a05dc1b9031fa40b0fea8347aceca7
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallRateHeroWin.cs b/Main/System/HeroReturn/HeroReturnCallRateHeroWin.cs
new file mode 100644
index 0000000..8954cd5
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallRateHeroWin.cs
@@ -0,0 +1,119 @@
+using System.Collections.Generic;
+using Cysharp.Threading.Tasks;
+using UnityEngine;
+
+public class HeroReturnCallRateHeroWin : UIBase
+{
+
+    [SerializeField] RectTransform rectTransform;
+    [SerializeField] RectTransform arrowImage;
+    [SerializeField] RectTransform arrowUpImage;
+    [SerializeField] ScrollerController scroller;
+
+    public static Vector3 worldPos; //涓栫晫鍧愭爣绯讳綅缃�
+    public static bool isDownShow = false;  // 鏄惁鍚戜笅鏄剧ず
+    public static List<Item> dataList;
+    public const int rowCountMax = 4;
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+
+        rectTransform.position = new Vector3(100, 100, 100);   //鍒濆鍖栨椂锛屽睆骞曡寖鍥村
+        arrowImage.SetActive(!isDownShow);
+        arrowUpImage.SetActive(isDownShow);
+        CreateScroller();
+    }
+
+    protected override void OnPreClose()
+    {
+        isDownShow = false;
+        scroller.OnRefreshCell -= OnRefreshCell;
+    }
+    
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnCallRateHeroCell;
+        _cell.Display(cell.index, dataList);
+    }
+
+    void CreateScroller()
+    {
+        if (dataList == null || dataList.Count == 0) return;
+
+        scroller.Refresh();
+        int rowCount = Mathf.CeilToInt((float)dataList.Count / rowCountMax);
+        for (int i = 0; i < rowCount; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, i);
+        }
+        scroller.Restart();
+    }
+
+    protected override void OnOpen()
+    {
+        UpdatePos().Forget();
+    }
+
+    async UniTask UpdatePos()
+    {
+        await UniTask.DelayFrame(3);
+        // 闄愬埗鍦ㄥ睆骞曡寖鍥村唴
+        Vector3[] corners = new Vector3[4];
+        rectTransform.GetWorldCorners(corners);
+
+        float minY = corners[0].y;
+        float maxY = corners[0].y;
+
+        for (int i = 1; i < corners.Length; i++)
+        {
+            if (corners[i].y < minY) minY = corners[i].y;
+            if (corners[i].y > maxY) maxY = corners[i].y;
+        }
+
+
+        float screenHeight = maxY - minY;
+        Vector2 adjustedPos = new Vector2(worldPos.x, worldPos.y + (!isDownShow ? screenHeight * 0.5f : -screenHeight * 0.5f));
+
+        Vector2 screenAdjustedPos = CameraManager.uiCamera.WorldToScreenPoint(adjustedPos);
+        var rectWidth = rectTransform.rect.width * Screen.width / canvasScaler.referenceResolution.x;
+        screenAdjustedPos.x = Mathf.Clamp(screenAdjustedPos.x, rectWidth * 0.5f, Screen.width - rectWidth * 0.5f);
+        screenAdjustedPos.y = Mathf.Clamp(screenAdjustedPos.y, rectTransform.rect.height * 0.5f, Screen.height - rectTransform.rect.height * 0.5f - 15);
+
+        adjustedPos = CameraManager.uiCamera.ScreenToWorldPoint(screenAdjustedPos);
+        rectTransform.position = adjustedPos;
+
+        if (!isDownShow)
+        {
+            rectTransform.localPosition = new Vector3(rectTransform.localPosition.x, rectTransform.localPosition.y + 15, rectTransform.localPosition.z);
+        }
+        else
+        {
+            rectTransform.localPosition = new Vector3(rectTransform.localPosition.x, rectTransform.localPosition.y - 15, rectTransform.localPosition.z);
+        }
+
+        rectTransform.GetWorldCorners(corners);
+        float minX = corners[0].x;
+        float maxX = corners[0].x;
+
+        for (int i = 1; i < corners.Length; i++)
+        {
+            if (corners[i].x < minX) minX = corners[i].x;
+            if (corners[i].x > maxX) maxX = corners[i].x;
+        }
+
+        //鏄剧ずarrowImage 鐨剎杞翠笂鐨勪綅缃紝鍜寃orldPos鍚屾锛屼絾涓嶈秴杩噈inX 鍜� maxX鑼冨洿
+        if (!isDownShow)
+        {
+            Vector3 arrowImagePosition = arrowImage.position;
+            arrowImagePosition.x = Mathf.Clamp(worldPos.x, minX, maxX);
+            arrowImage.position = arrowImagePosition;
+        }
+        else
+        {
+            Vector3 arrowUpImagePosition = arrowUpImage.position;
+            arrowUpImagePosition.x = Mathf.Clamp(worldPos.x, minX, maxX);
+            arrowUpImage.position = arrowUpImagePosition;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallRateHeroWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallRateHeroWin.cs.meta
index 862a125..36c3893 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallRateHeroWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 4488cbc55bbabcf43b390ebb827ec1f8
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallRateItem.cs b/Main/System/HeroReturn/HeroReturnCallRateItem.cs
new file mode 100644
index 0000000..c03223b
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallRateItem.cs
@@ -0,0 +1,123 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnCallRateItem : MonoBehaviour
+{
+    [SerializeField] ButtonEx libButton;
+    [SerializeField] ItemCell itemCell;
+    [SerializeField] Text rateText;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    public void Display(int index, Dictionary<int, int> gridRateDict, List<int> gridList, XBGetItemConfig xbConfig)
+    {
+        if (gridList?.Count <= index || gridRateDict?.Count != gridList?.Count || xbConfig == null) return;
+        if (xbConfig?.GridItemInfo == null || xbConfig?.GridLibInfo == null) return;
+        if (manager.xbGridArr == null) return;
+
+        int grid = gridList[index];
+        int rate = gridRateDict[grid];
+        rateText.text = Language.Get("TimingGift02", (double)rate / (double)100.0);
+        SetItemCell(grid, xbConfig.GridItemInfo, xbConfig.GridLibInfo, manager.xbGridArr);
+    }
+
+    public void SetCountActive(ItemCell itemCell, long count)
+    {
+        itemCell.countText.SetActive(count > 1);
+    }
+
+
+    private void SetItemCell(int grid, Dictionary<int, int[]> gridItemInfo, Dictionary<int, int> gridLibInfo, int[] xbGridArr)
+    {
+        libButton.SetActive(false);
+        itemCell.SetActive(false);
+        if (gridItemInfo.TryGetValue(grid, out var itemInfo))
+        {
+            itemCell.SetActive(true);
+            itemCell.Init(new ItemCellModel(itemInfo[0], true, itemInfo[1]));
+            SetCountActive(itemCell, itemInfo[1]);
+            itemCell.button.SetListener(() => ItemTipUtility.Show(itemInfo[0]));
+            return;
+        }
+
+        if (!gridLibInfo.TryGetValue(grid, out var libID)) return;
+
+        var list = TreasureItemLibConfig.GetItemIDList(libID);
+        if (list == null) return;
+        if (xbGridArr == null) return;
+
+        if (xbGridArr.Contains(grid))
+        {
+            int heroID = manager.GetCurrentDisplayCallHeroId();
+            if (!TryGetHeroItemInfo(heroID, libID, list, out int itemID, out int itemCount)) return;
+            itemCell.SetActive(true);
+            itemCell.Init(new ItemCellModel(itemID, true, itemCount));
+            SetCountActive(itemCell, itemCount);
+            itemCell.button.SetListener(() => ItemTipUtility.Show(itemID));
+        }
+        else
+        {
+            libButton.SetActive(true);
+            libButton.SetListener(() =>
+            {
+                HeroReturnCallRateHeroWin.worldPos = libButton.transform.position;
+                HeroReturnCallRateHeroWin.dataList = GetLibItemList(libID, list);
+                HeroReturnCallRateHeroWin.isDownShow = true;
+                UIManager.Instance.OpenWindow<HeroReturnCallRateHeroWin>();
+            });
+        }
+    }
+    public List<Item> GetLibItemList(int libID, List<int> itemList)
+    {
+        List<Item> res = new();
+        for (int i = 0; i < itemList.Count; i++)
+        {
+            int itemID = itemList[i];
+            var config = ItemConfig.Get(itemID);
+            if (config == null) continue;
+
+            if (!TreasureItemLibConfig.TryGetID(libID, itemID, out int id)) continue;
+            var treasureItemLibConfig = TreasureItemLibConfig.Get(id);
+            if (treasureItemLibConfig == null) continue;
+
+            res.Add(new Item(itemID, treasureItemLibConfig.ItemCount));
+        }
+        return res;
+    }
+
+    public bool TryGetHeroItemInfo(int heroID, int libID, List<int> itemList, out int itemID, out int itemCount)
+    {
+        itemID = 0;
+        itemCount = 0;
+        if (itemList == null) return false;
+
+        for (int i = 0; i < itemList.Count; i++)
+        {
+            itemID = itemList[i];
+            var config = ItemConfig.Get(itemID);
+            if (config == null) continue;
+
+            if (!TreasureItemLibConfig.TryGetID(libID, itemID, out int id)) continue;
+            var treasureItemLibConfig = TreasureItemLibConfig.Get(id);
+            if (treasureItemLibConfig == null) continue;
+
+            //鏈綋
+            if (config.Type == 150)
+            {
+                if (heroID == itemID)
+                {
+                    itemCount = treasureItemLibConfig.ItemCount;
+                    return true;
+                }
+            }
+            else if (config.Type == 151)
+            {
+                if (heroID == config.EffectValueA1)
+                {
+                    itemCount = treasureItemLibConfig.ItemCount;
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallRateItem.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallRateItem.cs.meta
index 862a125..fdd6316 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallRateItem.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: e8caa7644bce7414d9ada3cef9ee1eff
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallRateWin.cs b/Main/System/HeroReturn/HeroReturnCallRateWin.cs
new file mode 100644
index 0000000..7cfdc2b
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallRateWin.cs
@@ -0,0 +1,83 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnCallRateWin : UIBase
+{
+    [SerializeField] ScrollerController scroller;
+    public const int rowCountMax = 4;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+        CreateScroller();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+    }
+
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnCallRateCell;
+        _cell.Display(cell.index, gridRateDict, gridList, xbConfig);
+    }
+
+    Dictionary<int, int> gridRateDict;
+    List<int> gridList;
+    XBGetItemConfig xbConfig;
+    void CreateScroller()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(config.ActTreasureType);
+        if (xbConfig == null || xbConfig.GridItemRateList1 == null) return;
+
+        gridRateDict = GetGridRateDict(xbConfig.GridItemRateList1);
+        if (gridRateDict == null) return;
+
+        gridList = GetSortedGridList();
+        if (gridList == null) return;
+
+        scroller.Refresh();
+        int rowCount = (int)Mathf.Ceil((float)gridList.Count / rowCountMax);
+        for (int i = 0; i < rowCount; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, i);
+        }
+        scroller.Restart();
+    }
+
+    //<鏍煎瓙,涓囧垎鐜�>
+    public Dictionary<int, int> GetGridRateDict(int[][] gridItemRateList1)
+    {
+        Dictionary<int, int> res = new();
+        for (int i = 0; i < gridItemRateList1.Length; i++)
+        {
+            res[gridItemRateList1[i][1]] = i == 0 ?
+                gridItemRateList1[i][0] :
+                gridItemRateList1[i][0] - gridItemRateList1[i - 1][0];
+        }
+        return res;
+    }
+
+    public List<int> GetSortedGridList()
+    {
+        if (gridRateDict == null || gridRateDict.Count == 0) return null;
+        List<int> sortedGrids = new List<int>(gridRateDict.Keys);
+        sortedGrids.Sort();
+        // sortedGrids.Sort((a, b) =>
+        // {
+        //     int rateA = gridRateDict[a];
+        //     int rateB = gridRateDict[b];
+        //     return rateA.CompareTo(rateB);
+        // });
+
+        return sortedGrids;
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallRateWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallRateWin.cs.meta
index 862a125..89864dd 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallRateWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 3dc8fff9b1f118d4682a6541f30741a0
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallResultCell.cs b/Main/System/HeroReturn/HeroReturnCallResultCell.cs
new file mode 100644
index 0000000..d1b00cb
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallResultCell.cs
@@ -0,0 +1,104 @@
+using UnityEngine;
+using DG.Tweening;
+
+public class HeroReturnCallResultCell : MonoBehaviour
+{
+    [SerializeField] public ItemCell itemCell;
+    [SerializeField] UIEffectPlayer orbBaseEffect;    // 鍒濆鐘舵�佺壒鏁�
+    [SerializeField] UIEffectPlayer orbBoomEffect;    // 鐖嗗彂鐬棿鐗规晥
+    [SerializeField] UIEffectPlayer orbQualityEffect; // 鍝佽川搴曡壊鐗规晥
+    [SerializeField] UIEffectPlayer flowEffect;       // 鏈�缁堟祦鍏夌壒鏁�
+
+    [HideInInspector] public Vector3 originalLocalPos;
+
+    void Awake()
+    {
+        // 璁板綍鍒濆鏈湴鍧愭爣锛岀敤浜庡彂鐗屽姩鐢荤殑褰掍綅
+        originalLocalPos = transform.localPosition;
+    }
+
+    /// <summary>
+    /// 鍒濆鍖栨牸瀛愭暟鎹�
+    /// </summary>
+    public void DisplayItemCell(int itemID, int count)
+    {
+        itemCell.Init(new ItemCellModel(itemID, true, count));
+        itemCell.button.SetListener(() => ItemTipUtility.Show(itemID));
+    }
+
+    /// <summary>
+    /// 閲嶇疆鎵�鏈� UI 鍏冪礌鍜岀壒鏁堣嚦鍒濆鐘舵��
+    /// </summary>
+    public void ResetState()
+    {
+        itemCell.gameObject.SetActive(false);
+        orbBaseEffect.SetActive(false);
+        orbBoomEffect.SetActive(false);
+        orbQualityEffect.SetActive(false);
+        flowEffect.SetActive(false);
+    }
+
+    /// <summary>
+    /// 闃舵 1锛氭挱鏀惧垵濮嬪紩瀵煎厜鐐癸紙椋炶闃舵锛�
+    /// </summary>
+    public void PlayInitialOrb()
+    {
+        orbBaseEffect.SetActive(true);
+        orbBoomEffect.SetActive(false);
+        orbQualityEffect.SetActive(false);
+
+        orbBaseEffect.Play(4); // 鎾斁绱㈠紩涓�4鐨勯�氱敤椋炶鏁�
+    }
+
+    /// <summary>
+    /// 闃舵 2 & 3锛氭墽琛岀垎寮�銆佹樉鑹层�佺炕鐗屻�佸睍绀烘祦鍏夌殑缁勫悎搴忓垪
+    /// </summary>
+    /// <param name="qualityIndex">鍝佽川搴曡壊鐗规晥绱㈠紩</param>
+    /// <param name="flowQualityIndex">鏈�缁堟祦鍏夌壒鏁堢储寮�</param>
+    /// <returns>杩斿洖 Sequence 鏂逛究澶栭儴杩涜 Stagger锛堜氦閿欙級鎺掑垪</returns>
+    public Tween PlayExplosionFadeAndFlipReveal(int qualityIndex, int flowQualityIndex)
+    {
+        Sequence seq = DOTween.Sequence();
+
+        // [0.0s] 鍒囨崲鐗规晥锛氬叧闂琛屾�侊紝瑙﹀彂鐖嗗彂鎬�
+        seq.InsertCallback(0f, () =>
+        {
+            orbBaseEffect.SetActive(false);
+            orbBoomEffect.SetActive(true);
+            orbBoomEffect.Play(3);
+        });
+
+        // [0.2s] 灞曠ず鍝佽川鍩鸿壊
+        seq.InsertCallback(0.2f, () =>
+        {
+            orbQualityEffect.transform.localScale = Vector3.zero;
+            orbQualityEffect.SetActive(true);
+            orbQualityEffect.Play(qualityIndex);
+        });
+
+        // 鍝佽川鍏夊洟鐢卞皬鍙樺ぇ鐨勫洖寮瑰姩鐢�
+        seq.Insert(0.2f, orbQualityEffect.transform.DOScale(Vector3.one, 0.2f).SetEase(Ease.OutBack));
+
+        // [0.8s] 鍑嗗缈荤墝锛氭縺娲� ItemCell 骞惰缃� 90 搴︿晶鍚戯紝鍑嗗鏃嬭浆
+        seq.InsertCallback(0.8f, () =>
+        {
+            itemCell.gameObject.SetActive(true);
+            itemCell.transform.localEulerAngles = new Vector3(0, 90f, 0);
+        });
+
+        // [0.8s] 缈昏浆鍔ㄤ綔锛堣�楁椂 0.3s锛夛細浠� 90 搴︽棆杞洖 0 搴�
+        seq.Insert(0.8f, itemCell.transform.DOLocalRotate(Vector3.zero, 0.3f, RotateMode.Fast).SetEase(Ease.OutSine));
+
+        // [1.1s] 搴忓垪瀹岀粨锛氭竻鐞嗕复鏃剁壒鏁堬紝婵�娲绘寔涔呮祦鍏�
+        seq.InsertCallback(1.1f, () =>
+        {
+            orbBoomEffect.SetActive(false);
+            orbQualityEffect.SetActive(false); 
+
+            flowEffect.SetActive(true);
+            flowEffect.Play(flowQualityIndex); 
+        });
+
+        return seq;
+    }
+}
\ No newline at end of file
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallResultCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallResultCell.cs.meta
index 862a125..15b417e 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallResultCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: aa9f5a1a80f17304b84d946832fe6381
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallResultWin.cs b/Main/System/HeroReturn/HeroReturnCallResultWin.cs
new file mode 100644
index 0000000..994a845
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallResultWin.cs
@@ -0,0 +1,370 @@
+using UnityEngine;
+using DG.Tweening;
+using System.Collections.Generic;
+
+public class HeroReturnCallResultWin : UIBase
+{
+    [SerializeField] Transform moneyRect;
+    [SerializeField] OwnItemCell ownItemCell;
+    [SerializeField] ItemCell presentItemCell;         // 鎶藉崱鑾峰緱鐨勮禒閫侀亾鍏�
+    [SerializeField] RectTransform oneRect;             // 鍗曟娊瀹瑰櫒涓績鐐�
+    [SerializeField] HeroReturnCallResultCell oneCell;   // 鍗曟娊鍗曞厓鏍�
+    [SerializeField] RectTransform tenRect;             // 鍗佽繛瀹瑰櫒
+    [SerializeField] HeroReturnCallResultCell[] tenCell; // 鍗佽繛鍗曞厓鏍兼暟缁�
+
+    [SerializeField] UIEffectPlayer firstEffect;        // 寮�灞忓垵濮嬬壒鏁�
+
+    [SerializeField] HeroReturnCallButton callButton;    // 鍐嶆鎶藉彇鎸夐挳
+    [SerializeField] ButtonEx okButton;                 // 纭畾杩斿洖鎸夐挳
+
+
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    HappyXBModel xbManager => HappyXBModel.Instance;
+
+    bool isSkip;            // 鏄惁璺宠繃鍔ㄧ敾
+    int treasureType;       // 鎶藉崱瀹濆簱绫诲瀷
+    bool isOne = false;     // 鏄惁涓哄崟鎶芥ā寮�
+
+    private Sequence animSeq; // 涓诲姩鐢诲簭鍒�
+
+    protected override void InitComponent()
+    {
+        okButton.SetListener(CloseWindow);
+    }
+
+    protected override void OnPreOpen()
+    {
+        animSeq?.Kill();
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        treasureType = config.ActTreasureType;
+        // 鏍规嵁閰嶇疆鍜屾椂闂存埑鍔犺浇鐢ㄦ埛鐨勬槸鍚﹁烦杩囧姩鐢昏缃�
+        isSkip = manager.LoadCallSkipData(config.CfgID, act.startDate, act.endDate);
+
+        // 缁戝畾鏁版嵁鍒锋柊鍥炶皟
+        HappyXBModel.Instance.RefreshXBResultAct += RefreshXBResultAct;
+        HappyXBModel.Instance.RefreshXBTypeInfoAct += OnRefreshXBTypeInfoAct;
+
+        var treasureSetConfig = TreasureSetConfig.Get(config.ActTreasureType);
+        if (treasureSetConfig == null) return;
+        ownItemCell.itemID = treasureSetConfig.CostItemID;
+
+        RefreshXBResultAct();
+    }
+
+    protected override void OnPreClose()
+    {
+        animSeq?.Kill();
+        // 瑙g粦鍥炶皟锛岄槻姝㈠唴瀛樻硠婕�
+        HappyXBModel.Instance.RefreshXBResultAct -= RefreshXBResultAct;
+        HappyXBModel.Instance.RefreshXBTypeInfoAct -= OnRefreshXBTypeInfoAct;
+    }
+
+    /// <summary>
+    /// 鍒锋柊鎶藉崱缁撴灉鐣岄潰
+    /// </summary>
+    void RefreshXBResultAct()
+    {
+        isOne = HeroUIManager.Instance.selectCallIndex == 0;
+
+        // 鍒濆鍖栭《閮ㄨ禒閫佺墿鍝�
+        int itemId = xbManager.addXBAddItemID;
+        long count = xbManager.addXBItemCount;
+        presentItemCell.Init(new ItemCellModel(itemId, true, count));
+        presentItemCell.button.SetListener(() => ItemTipUtility.Show(itemId));
+
+        // 鏍规嵁鍗曟娊鎴栧崄杩炲~鍏呯墿鍝佹暟鎹�
+        if (isOne)
+        {
+            if (!xbManager.xbResultDict.IsNullOrEmpty())
+            {
+                oneCell.DisplayItemCell(xbManager.xbResultDict[0].itemId, xbManager.xbResultDict[0].count);
+            }
+        }
+        else
+        {
+            for (int i = 0; i < tenCell.Length; i++)
+            {
+                if (i < xbManager.xbResultDict?.Count)
+                {
+                    tenCell[i].DisplayItemCell(xbManager.xbResultDict[i].itemId, xbManager.xbResultDict[i].count);
+                }
+            }
+        }
+
+        callButton.Display(treasureType, HeroUIManager.Instance.selectCallIndex);
+
+        if (isSkip)
+        {
+            // 妯″紡锛氳烦杩囧姩鐢伙紝鐩存帴鏄剧ず鏈�缁堢姸鎬�
+            firstEffect.SetActive(false);
+            ShowImmediate();
+        }
+        else
+        {
+            // 妯″紡锛氭挱鏀惧畬鏁村睍绀哄姩鐢�
+            PrepareAnimation();
+            firstEffect.SetActive(true);
+            firstEffect.Play(0);
+
+            // 棰勭暀 1.1s 鐨勫紑灞忓姩鏁堟椂闂村悗锛屽紑濮嬫挱鏀惧彂鐗�/缈荤墝搴忓垪
+            PlayResultAnimation(1.1f);
+        }
+    }
+
+    private void OnRefreshXBTypeInfoAct() { RefreshXBResultAct(); }
+
+    /// <summary>
+    /// 闈欐�佹樉绀猴紙鏃犲姩鐢荤洿鎺ュ睍绀虹粨鏋滐級
+    /// </summary>
+    private void ShowImmediate()
+    {
+        animSeq?.Kill();
+        oneRect.SetActive(isOne);
+        tenRect.SetActive(!isOne);
+
+        ownItemCell.SetActive(true);
+        moneyRect.SetActive(true);
+        presentItemCell.SetActive(true);
+        callButton.SetActive(true);
+        okButton.SetActive(true);
+
+        if (isOne)
+        {
+            oneCell.SetActive(true);
+            oneCell.ResetState();
+            oneCell.itemCell.SetActive(true);
+        }
+        else
+        {
+            for (int i = 0; i < tenCell.Length; i++)
+            {
+                if (i < xbManager.xbResultDict?.Count)
+                {
+                    tenCell[i].SetActive(true);
+                    tenCell[i].transform.localPosition = tenCell[i].originalLocalPos;
+                    tenCell[i].ResetState();
+                    tenCell[i].itemCell.SetActive(true);
+                }
+                else
+                {
+                    tenCell[i].SetActive(false);
+                }
+            }
+        }
+    }
+
+    /// <summary>
+    /// 鍔ㄧ敾鍓嶇疆鍑嗗锛堥殣钘忓厓绱犲苟閲嶇疆鍧愭爣锛�
+    /// </summary>
+    private void PrepareAnimation()
+    {
+        oneRect.SetActive(isOne);
+        tenRect.SetActive(!isOne);
+
+        ownItemCell.SetActive(false);
+        moneyRect.SetActive(false);
+        presentItemCell.SetActive(false);
+        callButton.SetActive(false);
+        okButton.SetActive(false);
+
+        if (isOne)
+        {
+            oneCell.SetActive(true);
+            oneCell.ResetState();
+        }
+        else
+        {
+            for (int i = 0; i < tenCell.Length; i++)
+            {
+                if (i < xbManager.xbResultDict?.Count)
+                {
+                    tenCell[i].SetActive(true);
+                    tenCell[i].ResetState();
+                    tenCell[i].transform.localPosition = tenCell[i].originalLocalPos;
+                }
+                else
+                {
+                    tenCell[i].SetActive(false);
+                }
+            }
+        }
+    }
+
+    /// <summary>
+    /// 鏍稿績閫昏緫锛氱紪鎺掔粨鏋滃睍绀哄姩鐢绘椂闂磋酱
+    /// </summary>
+    private void PlayResultAnimation(float startDelay = 0f)
+    {
+        animSeq?.Kill();
+        animSeq = DOTween.Sequence();
+
+        if (isOne)
+        {
+            // ==================== 鍗曟娊鍔ㄧ敾閫昏緫 ====================
+            float timelineCursor = startDelay;
+
+            // 1. 鎾斁涓績鍏夊洟
+            animSeq.InsertCallback(timelineCursor, () => oneCell.PlayInitialOrb());
+
+            // 棰勭暀鐭殏鐨勫睍绀烘椂闂�
+            float finishShowTime = 0.12f;
+            timelineCursor += finishShowTime;
+
+            // 2. 瑙﹀彂鐖嗗紑涓庣炕鐗岀粍鍚堝姩鐢�
+            int itemId = xbManager.xbResultDict[0].itemId;
+            int quality = GetOrbQuality(itemId);
+            int flowQuality = GetFlowQuality(itemId);
+
+            animSeq.Insert(timelineCursor, oneCell.PlayExplosionFadeAndFlipReveal(quality, flowQuality));
+
+            // 鎺ㄨ繘娓告爣鑷崇粍鍚堝姩鐢荤粨鏉燂紙1.1s鍩虹鏃堕暱 + 0.3s缂撳啿锛�
+            timelineCursor += 1.4f;
+
+            // 3. 寮瑰嚭搴曢儴 UI
+            animSeq.InsertCallback(timelineCursor, ShowBottomUI);
+        }
+        else
+        {
+            // ==================== 鍗佽繛鍔ㄧ敾閫昏緫 ====================
+            int count = xbManager.xbResultDict.Count;
+            float staggerInterval = 0.1f; // 鍙戠墝闂撮殧
+            float moveDuration = 0.12f;    // 椋炶鏃堕棿
+            float timelineCursor = startDelay;
+
+            // 1. 渚濇浠庝腑蹇冪偣鍚戠洰鏍囦綅缃彂灏勫厜鍥紙鍙戠墝闃舵锛�
+            for (int i = 0; i < count; i++)
+            {
+                var cell = tenCell[i];
+                cell.transform.position = oneRect.position; // 璧峰浜庝腑蹇�
+                float delay = timelineCursor + i * staggerInterval;
+
+                animSeq.InsertCallback(delay, () => cell.PlayInitialOrb());
+                animSeq.Insert(delay, cell.transform.DOLocalMove(cell.originalLocalPos, moveDuration).SetEase(Ease.OutCubic));
+            }
+
+            // 璁$畻鎵�鏈夊崱鐗屽畬鎴愰琛岀殑鏃跺埢
+            float finishFlyingTime = ((count - 1) * staggerInterval) + moveDuration;
+            timelineCursor += finishFlyingTime;
+
+            // 2. 渚濇瑙﹀彂鐖嗗紑缈荤墝鍔ㄧ敾锛堝睍绀洪樁娈碉級
+            for (int i = 0; i < count; i++)
+            {
+                int itemId = xbManager.xbResultDict[i].itemId;
+                int quality = GetOrbQuality(itemId);
+                int flowQuality = GetFlowQuality(itemId);
+
+                animSeq.Insert(timelineCursor + i * staggerInterval, tenCell[i].PlayExplosionFadeAndFlipReveal(quality, flowQuality));
+            }
+
+            // 璁$畻鍏ㄩ儴鍗$墝缈昏浆瀹屾垚鐨勬椂闂寸偣骞跺姞鍏ョ紦鍐�
+            float finalFlipDuration = 1.1f + ((count - 1) * staggerInterval) + 0.3f;
+            timelineCursor += finalFlipDuration;
+
+            // 3. 寮瑰嚭搴曢儴 UI
+            animSeq.InsertCallback(timelineCursor, ShowBottomUI);
+        }
+    }
+
+    /// <summary>
+    /// 灞曠ず搴曢儴鎿嶄綔鎸夐挳锛屽苟妫�鏌ユ槸鍚﹁Е鍙戞灏嗙珛缁�
+    /// </summary>
+    private void ShowBottomUI()
+    {
+        ownItemCell.SetActive(true);
+        moneyRect.SetActive(true);
+        presentItemCell.SetActive(true);
+        callButton.SetActive(true);
+        okButton.SetActive(true);
+
+        presentItemCell.transform.localScale = Vector3.zero;
+        callButton.transform.localScale = Vector3.zero;
+        okButton.transform.localScale = Vector3.zero;
+
+        Sequence bottomSeq = DOTween.Sequence();
+        bottomSeq.Append(presentItemCell.transform.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack));
+        bottomSeq.Join(callButton.transform.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack));
+        bottomSeq.Join(okButton.transform.DOScale(Vector3.one, 0.3f).SetEase(Ease.OutBack));
+
+        bottomSeq.OnComplete(() =>
+        {
+            if (!isSkip)
+            {
+                CheckAndShowHeroLH();
+            }
+        });
+        animSeq.Append(bottomSeq);
+    }
+
+    /// <summary>
+    /// 妫�娴嬪苟灞曠ず楂樺搧璐ㄦ灏嗙珛缁橈紙寮圭獥灞曠ず锛�
+    /// </summary>
+    private void CheckAndShowHeroLH()
+    {
+        // 娓呯悊缂撳瓨鍒楄〃
+        ItemLogicUtility.Instance.poplhHeroIdList.Clear();
+
+        List<int> uniqueHeroIds = new List<int>();
+        int count = xbManager.xbResultDict.Count;
+
+        for (int i = 0; i < count; i++)
+        {
+            int itemId = xbManager.xbResultDict[i].itemId;
+
+            // 浠呭 HeroConfig 涓瓨鍦ㄧ殑瀹屾暣姝﹀皢杩涜澶勭悊
+            if (HeroConfig.HasKey(itemId))
+            {
+                // 浠呭睍绀洪珮浜庤瀹氬搧璐ㄧ殑姝﹀皢
+                if (HeroConfig.Get(itemId).Quality < HappyXBModel.Instance.lhQuality) continue;
+
+                if (!uniqueHeroIds.Contains(itemId))
+                {
+                    uniqueHeroIds.Add(itemId);
+                }
+            }
+        }
+
+        // 濡傛灉瀛樺湪绗﹀悎鏉′欢鐨勬灏嗭紝鎵撳紑澶у浘灞曠ず鐣岄潰
+        if (uniqueHeroIds.Count > 0)
+        {
+            ItemLogicUtility.Instance.poplhHeroIdList = uniqueHeroIds;
+
+            if (!UIManager.Instance.IsOpenedInList<HeroShowLHWin>())
+            {
+                UIManager.Instance.OpenWindow<HeroShowLHWin>();
+            }
+        }
+    }
+
+    // --- 杈呭姪鏂规硶锛氭槧灏勯厤缃搧璐ㄥ埌鐗规晥绱㈠紩 ---
+
+    private int GetOrbQuality(int itemId)
+    {
+        int qualityLevel = ItemConfig.Get(itemId).ItemColor;
+        switch (qualityLevel)
+        {
+            case 2: return 5; // 绱壊
+            case 3: return 2; // 榛勮壊
+            case 4: return 0; // 姗欒壊
+            case 5: return 1; // 绾㈣壊
+            default: return 0;
+        }
+    }
+
+    private int GetFlowQuality(int itemId)
+    {
+        int qualityLevel = ItemConfig.Get(itemId).ItemColor;
+        switch (qualityLevel)
+        {
+            case 2: return 3; // 绱壊
+            case 3: return 2; // 榛勮壊
+            case 4: return 0; // 姗欒壊
+            case 5: return 1; // 绾㈣壊
+            default: return 0;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallResultWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallResultWin.cs.meta
index 862a125..4667613 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallResultWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: fafde75987e7b864ea3c2faa42578100
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCallWin.cs b/Main/System/HeroReturn/HeroReturnCallWin.cs
new file mode 100644
index 0000000..5723eac
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCallWin.cs
@@ -0,0 +1,417 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using DG.Tweening;
+using System.Linq;
+using EnhancedUI.EnhancedScroller;
+
+public class HeroReturnCallWin : UIBase
+{
+    [SerializeField] RawImage chooseHeroBgImage;
+    [SerializeField] ButtonEx chooseHeroButton;
+    [SerializeField] ImageEx chooseHeroImage1;
+    [SerializeField] ImageEx chooseHeroImage2;
+    [SerializeField] Transform lhTransform;
+    [SerializeField] Transform heroCallTransform;
+    [SerializeField] Transform topTransform;
+    [SerializeField] Transform heroInfoTransform;
+
+
+    [SerializeField] ImageEx bgImage;
+    [SerializeField] RectTransform changeRect;
+    [SerializeField] UIEffectPlayer changeUIEffect;
+
+    [SerializeField] OwnItemCell ownItemCell;
+    [SerializeField] ButtonEx closeBtn;
+    [SerializeField] Toggle skipToggle;
+    [SerializeField] HeroReturnCallButton xbButton1;
+    [SerializeField] HeroReturnCallButton xbButton10;
+    [SerializeField] TextEx resMoneyCallCntText;
+    [SerializeField] TextEx nextBigAwardCntText;
+    [SerializeField] GradientText heroQualityText;
+    [SerializeField] GradientText heroNameText;
+
+    [SerializeField] TextEx timeText;
+
+    [SerializeField] TextEx nameText;
+    [SerializeField] TextEx descText;
+    [SerializeField] ImageEx countryImage;
+    [SerializeField] ImageEx jobImage;
+    [SerializeField] ButtonEx changeHeroButton;//鏇存崲鑻遍泟
+    [SerializeField] ButtonEx previewButton;//婊$骇棰勮
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] ButtonEx shopButton; // 鍏戞崲鍟嗗簵
+    [SerializeField] RedpointBehaviour shopRedpoint;
+    [SerializeField] ButtonEx giftButton; // 鐨囨潈绀煎寘
+    [SerializeField] RedpointBehaviour giftRedpoint;
+
+    [SerializeField] ButtonEx rankButton;
+    [SerializeField] TextEx[] top3NameText;
+    [SerializeField] TextEx rankTipText;
+    [SerializeField] ButtonEx rateButton;
+    [SerializeField] ScrollerController scroller;
+    [SerializeField] ButtonEx historyButton;
+    [SerializeField] UIHeroController lhController;
+    [SerializeField] UIHeroController uiHeroController;
+    [SerializeField] HeroReturnCallBubbleCell[] bubbleCell;
+
+    [SerializeField] float modleSize = 1f;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+        shopButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnShopWin>());
+        giftButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnGiftWin>());
+        changeHeroButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnCallChangeWin>());
+        rankButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnRankWin>());
+        rateButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnCallRateWin>());
+        historyButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnCallHistoryWin>());
+        chooseHeroButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnCallChooseWin>());
+        previewButton.SetListener(OnClickPreview);
+        skipToggle.AddListener((value) =>
+        {
+            manager.SaveCallSkipData(config.CfgID, act.startDate, act.endDate, value);
+        });
+    }
+
+
+    protected override void OnPreOpen()
+    {
+        scroller.lockType = EnhanceLockType.LockVerticalBottom;
+        RankModel.Instance.ResetQueryParam();
+        RankModel.Instance.QueryRankByPage(manager.sendRankType, watchID: (int)PlayerDatas.Instance.baseData.PlayerID, groupValue1: manager.actNum);
+
+        HappyXBModel.Instance.RefreshXBTypeInfoAct += OnRefreshXBTypeInfoAct;
+        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
+        RankModel.Instance.onRankRefresh += OnRankRefresh;
+        PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefresh;
+        PackManager.Instance.RefreshItemEvent += RefreshItemEvent;
+        scroller.OnRefreshCell += OnRefreshCell;
+        manager.OnUpdateGameRecInfo += OnUpdateGameRecInfo;
+        manager.OnUpdateHeroAppearPlayerInfoEvent += OnUpdateHeroAppearPlayerInfoEvent;
+
+        if (manager.isSendFirst)
+        {
+            act = manager.GetOperationHeroAppearInfo();
+            if (act == null) return;
+
+            config = ActHeroAppearConfig.Get(act.CfgID);
+            if (config == null) return;
+
+            int treasureType = config.ActTreasureType;
+            manager.SendViewGameRecPack(treasureType);
+        }
+
+        InitRedpoint();
+        CreateScroller();
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        HappyXBModel.Instance.RefreshXBTypeInfoAct -= OnRefreshXBTypeInfoAct;
+        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
+        RankModel.Instance.onRankRefresh -= OnRankRefresh;
+        PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefresh;
+        PackManager.Instance.RefreshItemEvent -= RefreshItemEvent;
+        scroller.OnRefreshCell -= OnRefreshCell;
+        manager.OnUpdateGameRecInfo -= OnUpdateGameRecInfo;
+        manager.OnUpdateHeroAppearPlayerInfoEvent -= OnUpdateHeroAppearPlayerInfoEvent;
+    }
+
+
+
+    private Sequence heroAnimSeq;
+
+    private void OnUpdateHeroAppearPlayerInfoEvent()
+    {
+        changeRect.SetActive(false);
+
+        if (heroAnimSeq != null)
+        {
+            heroAnimSeq.Kill();
+            heroAnimSeq = null;
+        }
+
+        Display();
+
+        Transform targetTrans = lhController.transform;
+
+        // 鍋滄 Transform 涓婂彲鑳芥畫鐣欑殑鍗曠嫭鍔ㄧ敾
+        targetTrans.DOKill();
+
+        int heroID = manager.GetCurrentDisplayCallHeroId();
+        int skinID = manager.GetDefaultSkinID(heroID);
+        var skinConfig = HeroSkinConfig.Get(skinID);
+
+        float baseScaleValue = 1f; // 榛樿缂╂斁
+        if (skinConfig != null && skinConfig.TachieParam != null && skinConfig.TachieParam.Length == 4)
+        {
+            baseScaleValue = skinConfig.TachieParam[2];
+        }
+
+        Vector3 baseScale = Vector3.one * baseScaleValue;
+
+        targetTrans.localScale = baseScale;
+
+        CanvasGroup cg = lhController.GetComponent<CanvasGroup>();
+        if (cg == null) cg = lhController.gameObject.AddComponent<CanvasGroup>();
+        cg.DOKill();
+        cg.alpha = 0.8f;
+
+        changeUIEffect.Play();
+
+        heroAnimSeq = DOTween.Sequence();
+
+        heroAnimSeq.Append(targetTrans.DOScale(baseScale * 1.1f, 0.3f).SetEase(Ease.OutQuad));
+        heroAnimSeq.Append(targetTrans.DOScale(baseScale, 0.3f).SetEase(Ease.InQuad));
+
+        heroAnimSeq.Join(cg.DOFade(1f, 0.3f).SetEase(Ease.Linear));
+
+        heroAnimSeq.OnComplete(() =>
+        {
+            changeRect.SetActive(true);
+            heroAnimSeq = null;
+        });
+    }
+
+    private void OnUpdateGameRecInfo()
+    {
+        CreateScroller();
+    }
+
+    public void RefreshItemEvent(PackType packType, int index, int itemID)
+    {
+        if (packType != PackType.Item && treasureSetConfig?.CostItemID != itemID) return;
+        Display();
+    }
+    private void PlayerDataRefresh(PlayerDataType type)
+    {
+        if (type != PlayerDataType.Gold) return;
+        Display();
+    }
+
+    private void OnRankRefresh(int type)
+    {
+        if (type != manager.sendRankType) return;
+        ShowTop3();
+    }
+
+    private void OnSecondEvent()
+    {
+        manager.GetActTimeStr(timeText);
+    }
+
+    private void OnRefreshXBTypeInfoAct()
+    {
+        Display();
+    }
+
+    public void InitRedpoint()
+    {
+        shopRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.Shop);
+        giftRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.Gift);
+    }
+
+    private void OnClickPreview()
+    {
+        if (heroConfig == null) return;
+        HeroUIManager.Instance.selectForPreviewHeroID = heroConfig.HeroID;
+        UIManager.Instance.OpenWindow<HeroBestBaseWin>();
+    }
+    OperationHeroAppearInfo act;
+    ActHeroAppearConfig config;
+    HeroConfig heroConfig;
+    TreasureSetConfig treasureSetConfig;
+    XBTypeInfo xbTypeInfo;
+    private void Display()
+    {
+        act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        int heroID = manager.GetCurrentDisplayCallHeroId();
+        heroConfig = HeroConfig.Get(heroID);
+        if (heroConfig == null) return;
+
+        int skinID = manager.GetDefaultSkinID(heroID);
+        var skinConfig = HeroSkinConfig.Get(skinID);
+        if (skinConfig == null) return;
+
+        var artConfig = ActHeroReturnArtConfig.Get(heroID);
+        if (artConfig == null || artConfig.CallBubbleItems == null) return;
+
+        int treasureType = config.ActTreasureType;
+        treasureSetConfig = TreasureSetConfig.Get(treasureType);
+        if (treasureSetConfig == null) return;
+
+        xbTypeInfo = HappyXBModel.Instance.GetXBInfoByType(treasureType);
+        if (xbTypeInfo == null) return;
+
+        bool canChooseHero = !manager.IsSingleHero(act);
+        bool isChooseHero = manager.LoadCallChooseHeroStateKey(act);
+        chooseHeroBgImage.SetActive(canChooseHero && !isChooseHero);
+        chooseHeroButton.SetActive(canChooseHero && !isChooseHero);
+        chooseHeroImage1.SetActive(canChooseHero && !isChooseHero);
+        chooseHeroImage2.SetActive(canChooseHero && !isChooseHero);
+        lhTransform.SetActive(!canChooseHero || isChooseHero);
+        heroCallTransform.SetActive(!canChooseHero || isChooseHero);
+        topTransform.SetActive(!canChooseHero || isChooseHero);
+        heroInfoTransform.SetActive(!canChooseHero || isChooseHero);
+
+        bgImage.SetSprite(StringUtility.Concat("HeroReturnCallBG_", heroID.ToString()));
+
+        lhController.Create(skinID, 1, motionName: "", isLh: true);
+        uiHeroController.Create(skinID, modleSize);
+        uiHeroController.transform.localScale = new Vector3(modleSize, modleSize, modleSize);
+
+        ownItemCell.itemID = treasureSetConfig.CostItemID;
+        skipToggle.isOn = manager.LoadCallSkipData(config.CfgID, act.startDate, act.endDate);
+
+        xbButton1.Display(config.ActTreasureType, 0);
+        xbButton10.Display(config.ActTreasureType, 1);
+        resMoneyCallCntText.text = Language.Get("HeroDebut24", Mathf.Max(treasureSetConfig.DailyMaxCountMoney - xbTypeInfo.treasureCountTodayGold, 0));
+
+        var needCount = GetNextXBCountForBigAward(treasureType);
+        nextBigAwardCntText.text = Language.Get("HeroDebut08", needCount.ToString());
+
+        heroQualityText.text = Language.Get($"heroCallQaulity{heroConfig.Quality}");
+        manager.SetheroQaulityColor(heroQualityText, heroConfig.Quality);
+
+        nameText.text = heroConfig.Name;
+        nameText.color = UIHelper.GetUIColorByFunc(heroConfig.Quality);
+        descText.text = heroConfig.Desc;
+        countryImage.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
+        jobImage.SetSprite(HeroUIManager.Instance.GetJobIconName(heroConfig.Class));
+
+        heroNameText.text = heroConfig.Name;
+        manager.SetGradientTextColor(heroNameText, artConfig.HeroNameColor);
+
+        for (int i = 0; i < bubbleCell.Length; i++)
+        {
+            if (i < artConfig.CallBubbleItems.Length)
+            {
+                bubbleCell[i].SetActive(true);
+                bubbleCell[i].Display(artConfig.CallBubbleItems[i][0], artConfig.CallBubbleItems[i][1]);
+            }
+            else
+            {
+                bubbleCell[i].SetActive(false);
+            }
+        }
+
+        ShowTop3();
+        OnSecondEvent();
+    }
+
+    public int GetNextXBCountForBigAward(int type)
+    {
+        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
+        if (typeInfo == null) return 0;
+
+        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
+        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
+        luckList.Sort();
+        for (int i = 0; i < luckList.Count; i++)
+        {
+            var luckyValue = typeInfo.luckValue;
+            if (luckyValue < luckList[i])
+            {
+                return luckList[i] - luckyValue;
+            }
+        }
+        return 0;
+    }
+    void ShowTop3()
+    {
+        for (int i = 0; i < top3NameText.Length; i++)
+        {
+            var rankData = RankModel.Instance.GetRankDataByRank(manager.loadRankType, i + 1);
+            top3NameText[i].text = rankData == null ? Language.Get("L1124") : rankData.name1;
+        }
+        int billTempID = config.BillTempID;
+        rankTipText.text = Language.Get("HeroDebut27", ActBillboardAwardConfig.GetTop3MinCalNeedValue(billTempID));
+    }
+    public List<HeroReturnGameRec> list;
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnCallHistoryOutCell;
+        _cell.Display(cell.index, list);
+    }
+
+    float autoScrollInterval = 2f;
+    private float autoScrollTimer = 0f;
+    private int currentScrollerIndex = 0;
+    private bool isScrollerReady = false; // 鍒ゅ畾鏍囧織
+    void CreateScroller()
+    {
+        list = manager.GetGameRecList();
+        scroller.Refresh();
+
+        int listCount = list?.Count ?? 0;
+        if (list != null)
+        {
+            for (int i = 0; i < listCount; i++)
+            {
+                scroller.AddCell(ScrollerDataType.Header, i);
+            }
+        }
+
+
+        bool canScroll = listCount > 4;// 鍙湁鏁伴噺 > 4 鏃舵墠寮�鍚� Loop 鍜岃鏃跺櫒
+        scroller.m_Scorller.Loop = canScroll;
+        isScrollerReady = canScroll;
+
+        scroller.vertical = false;
+        scroller.horizontal = false;
+        scroller.Restart();
+
+        // 濡傛灉鏄惊鐜ā寮忥紝纭繚鍒濆浣嶇疆姝g‘
+        if (canScroll)
+        {
+            scroller.m_Scorller.JumpToDataIndex(0,
+            tweenType: EnhancedScroller.TweenType.immediate);
+        }
+        autoScrollTimer = 0f;
+        currentScrollerIndex = 0;
+    }
+
+    private void LateUpdate()
+    {
+        // 鍙湁鍦ㄦ暟鎹氨缁笖瓒呰繃 4 涓椂锛屾墠鎵ц璁℃椂閫昏緫
+        if (isScrollerReady)
+        {
+            autoScrollTimer += Time.deltaTime;
+            if (autoScrollTimer >= autoScrollInterval)
+            {
+                autoScrollTimer = 0f;
+                AutoScrollNext();
+            }
+        }
+    }
+
+    private void AutoScrollNext()
+    {
+        if (list?.Count <= 4)
+        {
+            isScrollerReady = false;
+            return;
+        }
+
+        // 妫�鏌� scroller 鐨� GameObject 鏄惁澶勪簬婵�娲荤姸鎬�
+        if (scroller == null || scroller.m_Scorller == null || !scroller.m_Scorller.gameObject.activeInHierarchy)
+        {
+            return;
+        }
+
+        currentScrollerIndex++;
+        // 鍦� Loop 妯″紡涓嬭繘琛屽钩婊戣烦杞�
+        scroller.m_Scorller.JumpToDataIndex(
+            currentScrollerIndex % list.Count,
+            tweenType: EnhancedScroller.TweenType.easeInOutQuad,
+            tweenTime: 0.5f);
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCallWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCallWin.cs.meta
index 862a125..80fc047 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCallWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 0774834d6226ea848adedc229e82552f
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCell.cs b/Main/System/HeroReturn/HeroReturnCell.cs
new file mode 100644
index 0000000..2489218
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCell.cs
@@ -0,0 +1,30 @@
+using UnityEngine;
+public class HeroReturnCell : MonoBehaviour
+{
+    [SerializeField] ButtonEx clickButton;
+    [SerializeField] ImageEx bgImage;
+    [SerializeField] ImageEx heroImage;
+    [SerializeField] GradientText titleText;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    public void Display()
+    {
+        clickButton.SetListener(() =>
+        {
+            UIManager.Instance.OpenWindow<HeroReturnWin>();
+        });
+
+        int heroID = manager.GetFirstHeroId();
+        var artConfig = ActHeroReturnArtConfig.Get(heroID);
+        if (artConfig == null) return;
+
+        int skinID = manager.GetDefaultSkinID(heroID);
+        var skinConfig = HeroSkinConfig.Get(skinID);
+        if (skinConfig == null) return;
+
+        bgImage.SetSprite(StringUtility.Concat("HeroReturnEntryBg_", heroID.ToString()));
+        manager.SetHeroSquareIcon(heroImage, skinConfig.SquareIcon);
+        titleText.text = artConfig.EntryTitleText;
+    }
+
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCell.cs.meta
index 862a125..263cbfe 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: dc2b313f9675a0644bd1a684fe9bad47
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCheckInCell.cs b/Main/System/HeroReturn/HeroReturnCheckInCell.cs
new file mode 100644
index 0000000..b4ffe02
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCheckInCell.cs
@@ -0,0 +1,60 @@
+using UnityEngine;
+
+public class HeroReturnCheckInCell : MonoBehaviour
+{
+    [SerializeField] ButtonEx clickButton;
+    [SerializeField] ImageEx bgImage;
+    [SerializeField] TextEx dayText;
+    [SerializeField] TextEx itemNameText;
+    [SerializeField] ItemCell itemCell;
+    [SerializeField] UIEffectPlayer uiEffectPlayer;
+    [SerializeField] Transform imgMask;
+
+    HeroReturnManager manager => HeroReturnManager.Instance;
+
+    private int currentItemId;
+    private int currentState;
+
+    public void Display(int templateID, int dayNum)
+    {
+        uiEffectPlayer.Stop();
+
+        var config = ActSignAwardConfig.GetConfig(templateID, dayNum);
+        if (config == null) return;
+        if (config.SignAwardItemList.IsNullOrEmpty()) return;
+
+        currentItemId = config.SignAwardItemList[0][0];
+        int count = config.SignAwardItemList[0][1];
+
+        var itemConfig = ItemConfig.Get(currentItemId);
+        if (itemConfig == null) return;
+
+        currentState = manager.GetCheckInState(dayNum);
+        imgMask.SetActive(currentState == 2);
+        bgImage.SetSprite(currentState == 1 ? "HeroDebutCheckInDayBG1" : "HeroDebutCheckInDayBG2");
+        if (currentState == 1)
+        {
+            uiEffectPlayer.Play();
+        }
+
+        dayText.text = Language.Get($"SignDay{dayNum}");
+        itemNameText.text = itemConfig.ItemName;
+
+        itemCell.Init(new ItemCellModel(currentItemId, false, count));
+        itemCell.button.AddListener(OnItemClicked);
+
+        clickButton.SetListener(() => manager.SendGetCheckInReward());
+    }
+
+    private void OnItemClicked()
+    {
+        if (currentState == 1)
+        {
+            manager.SendGetCheckInReward();
+        }
+        else
+        {
+            ItemTipUtility.Show(currentItemId);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCheckInCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCheckInCell.cs.meta
index 862a125..72d343f 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCheckInCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 7dc473ad41cdeb049b5ff9072138f709
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnCheckInWin.cs b/Main/System/HeroReturn/HeroReturnCheckInWin.cs
new file mode 100644
index 0000000..a446e04
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnCheckInWin.cs
@@ -0,0 +1,80 @@
+using UnityEngine;
+
+public class HeroReturnCheckInWin : UIBase
+{
+    [SerializeField] ImageEx bgImage;
+    [SerializeField] UIHeroController rolelhShow;
+    [SerializeField] TextEx timeText;
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] HeroReturnCheckInCell[] cells;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+    }
+
+    protected override void OnPreOpen()
+    {
+        GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent += OnUpdateActSignInfosEvent;
+        TimeMgr.Instance.OnDayEvent += OnDayEvent;
+        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
+        Display();
+    }
+    protected override void OnPreClose()
+    {
+        GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent -= OnUpdateActSignInfosEvent;
+        TimeMgr.Instance.OnDayEvent -= OnDayEvent;
+        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
+    }
+    private void OnDayEvent()
+    {
+        Display();
+    }
+    private void OnUpdateActSignInfosEvent(int arg1, int arg2)
+    {
+        Display();
+    }
+
+    private void OnSecondEvent()
+    {
+        manager.GetActTimeStr(timeText);
+    }
+    private void Display()
+    {
+        int heroID = manager.GetFirstHeroId();
+        var artConfig = ActHeroReturnArtConfig.Get(heroID);
+        if (artConfig == null) return;
+
+        var heroConfig = HeroConfig.Get(heroID);
+        if (heroConfig == null) return;
+
+        int skinID = manager.GetDefaultSkinID(heroID);
+
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        int templateID = config.SignTempID;
+        var list = ActSignAwardConfig.GetDayNumSortList(templateID);
+        if (list == null) return;
+
+        bgImage.SetSprite(StringUtility.Concat("HeroReturnCheckInBG_", heroID.ToString()));
+        for (int i = 0; i < cells.Length; i++)
+        {
+            if (i < list.Count)
+            {
+                cells[i].SetActive(true);
+                cells[i].Display(templateID, list[i]);
+            }
+            else
+            {
+                cells[i].SetActive(false);
+            }
+        }
+
+        rolelhShow.Create(skinID, 1, motionName: "", isLh: true);
+        OnSecondEvent();
+    }
+}
\ No newline at end of file
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnCheckInWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnCheckInWin.cs.meta
index 862a125..2879871 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnCheckInWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: d4ec9226f50edd6408ce3f2bdb9821ca
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnGiftCell.cs b/Main/System/HeroReturn/HeroReturnGiftCell.cs
new file mode 100644
index 0000000..bd1fc9a
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnGiftCell.cs
@@ -0,0 +1,165 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnGiftCell : MonoBehaviour
+{
+    [SerializeField] ImageEx vipImage;
+    [SerializeField] TextEx vipText;
+    [SerializeField] OutlineEx vipTextOutline;
+    [SerializeField] ImageEx rateImage;
+    [SerializeField] TextEx rateText;
+
+    [SerializeField] ItemCell[] itemCells;
+    [SerializeField] TextEx titleText;
+    [SerializeField] ButtonEx buyButton;
+    [SerializeField] ImageEx buyImage;
+    [SerializeField] TextEx buyText;
+    [SerializeField] TextEx buyText1;
+    [SerializeField] ImageEx moneyIconImage;
+    [SerializeField] TextEx limitCountText;
+    [SerializeField] ImageEx redImage;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    StoreModel storeModel => StoreModel.Instance;
+
+    public void Display(int index, List<HeroReturnGiftItem> giftItems)
+    {
+        if (giftItems.IsNullOrEmpty() || index < 0 || index >= giftItems.Count) return;
+
+        HeroReturnGiftItem item = giftItems[index];
+        if (item.type == 0)
+        {
+            DisplayStore(item.id);
+            return;
+        }
+
+        DisplayCTG(item.id);
+    }
+
+    private void DisplayCTG(int ctgId)
+    {
+        redImage.SetActive(false);
+        buyText.SetActive(true);
+        buyText1.SetActive(false);
+        moneyIconImage.SetActive(false);
+        rateImage.SetActive(true);
+
+        if (!RechargeManager.Instance.TryGetOrderInfo(ctgId, out var orderConfig)) return;
+        if (!RechargeManager.Instance.TryGetRechargeCount(ctgId, out var rechargeCount)) return;
+        if (!CTGConfig.HasKey(ctgId)) return;
+        if (!RechargeManager.Instance.TryGetRechargeItem(ctgId, out var rechargeItemList)) return;
+
+        CTGConfig config = CTGConfig.Get(ctgId);
+        vipImage.SetActive(config.VipLevel > 0);
+        if (config.VipLevel > 0)
+        {
+            vipImage.SetSprite($"VipLevel{config.VipLevel}");
+            vipText.text = Language.Get($"VipLevelInfo{config.VipLevel}");
+            vipText.color = InvestModel.Instance.GetTextColor(config.VipLevel);
+            vipTextOutline.OutlineColor = InvestModel.Instance.GetOutlineColor(config.VipLevel);
+        }
+
+        rateImage.SetActive(true);
+        rateText.text = Language.Get("DailySpecials07", config.Percentage);
+
+        bool isCanBuy = manager.IsCanBuyToday(ctgId);
+        titleText.text = config.Title;
+        buyImage.SetSprite(isCanBuy ? "DailySpecialsBuy1" : "DailySpecialsBuy2");
+        buyText.text = !isCanBuy ? Language.Get("storename11") : Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderConfig.PayRMBNumOnSale));
+        limitCountText.SetActive(config.DailyBuyCount > 0);
+        limitCountText.text = Language.Get("HeroDebut39", UIHelper.AppendColor(rechargeCount.todayCount >= config.DailyBuyCount ? TextColType.Red : TextColType.LightGreen, Mathf.Max(0, config.DailyBuyCount - rechargeCount.todayCount).ToString()));
+        buyButton.interactable = isCanBuy;
+        buyButton.SetListener(() =>
+        {
+            if (config.VipLevel > 0 && !FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.PrivilegeCard))
+            {
+                SysNotifyMgr.Instance.ShowTip("MinggeAuto8");
+                return;
+            }
+            if (config.VipLevel == 1 && !InvestModel.Instance.IsInvested(InvestModel.monthCardType))
+            {
+                SysNotifyMgr.Instance.ShowTip("MinggeAuto5");
+                UIManager.Instance.OpenWindow<PrivilegeCardWin>();
+                return;
+            }
+            if (config.VipLevel == 2 && !InvestModel.Instance.IsInvested(InvestModel.foreverCardType))
+            {
+                SysNotifyMgr.Instance.ShowTip("MinggeAuto7");
+                UIManager.Instance.OpenWindow<PrivilegeCardWin>();
+                return;
+            }
+            RechargeManager.Instance.CTG(ctgId);
+        });
+
+        for (int i = 0; i < itemCells.Length; i++)
+        {
+            var itemBaisc = itemCells[i];
+            if (i < rechargeItemList.Count)
+            {
+                var itemInfo = rechargeItemList[i];
+                itemBaisc.SetActive(true);
+                itemBaisc.Init(new ItemCellModel((int)itemInfo.id, false, itemInfo.countEx));
+                itemBaisc.button.AddListener(() =>
+                {
+                    ItemTipUtility.Show((int)itemInfo.id);
+                });
+            }
+            else
+            {
+                itemBaisc.SetActive(false);
+            }
+        }
+    }
+
+    private void DisplayStore(int id)
+    {
+        rateImage.SetActive(false);
+        vipImage.SetActive(false);
+        if (!StoreConfig.HasKey(id)) return;
+
+        StoreConfig storeConfig = StoreConfig.Get(id);
+        int remainNum;
+        storeModel.TryGetIsSellOut(storeConfig, out remainNum);
+
+        bool isFree = manager.IsFreeShop(id);
+        titleText.text = storeConfig.Name;
+
+        limitCountText.SetActive(!isFree);
+        limitCountText.text = Language.Get("TimeRush08", UIHelper.AppendColor(remainNum == 0 ? TextColType.Red : TextColType.LightGreen, Mathf.Max(0, remainNum).ToString(), true));
+
+        bool isCanBuy = manager.IsNoSellOutShopID(id);
+
+        redImage.SetActive(isFree && isCanBuy);
+        buyText.SetActive(isFree || !isCanBuy);
+        buyText.text = isFree ? Language.Get("L1127") : Language.Get("storename11");
+        buyText1.SetActive(!isFree && isCanBuy);
+        buyText1.text = UIHelper.GetMoneyFormat(storeConfig.MoneyNum);
+        moneyIconImage.SetActive(!isFree && isCanBuy);
+        moneyIconImage.SetIconWithMoneyType(1);
+        buyImage.SetSprite(isCanBuy ? "DailySpecialsBuy1" : "DailySpecialsBuy2");
+        buyButton.interactable = isCanBuy;
+        buyButton.SetListener(() =>
+        {
+            storeModel.SendBuyShopItemWithPopCheck(storeConfig, 1, (int)BuyStoreItemCheckType.ActGift);
+        });
+
+        var items = storeModel.GetShopItemlistByIndex(storeConfig);
+        for (int i = 0; i < itemCells.Length; i++)
+        {
+            var itemBaisc = itemCells[i];
+            if (i < items.Count)
+            {
+                var itemInfo = items[i];
+                itemBaisc.SetActive(true);
+                itemBaisc.Init(new ItemCellModel(itemInfo.itemId, false, itemInfo.count));
+                itemBaisc.button.AddListener(() =>
+                {
+                    ItemTipUtility.Show(itemInfo.itemId);
+                });
+            }
+            else
+            {
+                itemBaisc.SetActive(false);
+            }
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnGiftCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnGiftCell.cs.meta
index 862a125..abca963 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnGiftCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 4a5a9f2a5a389d24b8e9b1847cf53d35
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnGiftWin.cs b/Main/System/HeroReturn/HeroReturnGiftWin.cs
new file mode 100644
index 0000000..5f59093
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnGiftWin.cs
@@ -0,0 +1,86 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnGiftWin : UIBase
+{
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] ImageEx bgImage;
+    [SerializeField] ImageEx heroImage;
+    [SerializeField] ScrollerController scroller;
+    [SerializeField] TextEx timeText;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    StoreModel storeModel => StoreModel.Instance;
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+    }
+
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
+        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent;
+        storeModel.RefreshBuyShopLimitEvent += RefreshBuyShopLimitEvent;
+
+        int heroID = manager.GetFirstHeroId();
+        var artConfig = ActHeroReturnArtConfig.Get(heroID);
+        if (artConfig == null) return;
+
+        bgImage.SetSprite(StringUtility.Concat("HeroReturnGiftBG_", heroID.ToString()));
+        heroImage.SetNativeSize();
+
+        heroImage.SetSprite(StringUtility.Concat("HeroReturnGiftHero_", heroID.ToString()));
+        heroImage.SetNativeSize();
+
+        OnSecondEvent();
+        CreateGiftScroller();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
+        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent;
+        storeModel.RefreshBuyShopLimitEvent -= RefreshBuyShopLimitEvent;
+    }
+    private void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell.GetComponent<HeroReturnGiftCell>();
+        _cell?.Display(cell.index, giftItems);
+    }
+
+    private void OnSecondEvent()
+    {
+        manager.GetActTimeStr(timeText);
+    }
+
+    private void OnRechargeCountEvent(int obj)
+    {
+        RefreshAll();
+    }
+
+    private void RefreshBuyShopLimitEvent()
+    {
+        RefreshAll();
+    }
+
+    List<HeroReturnGiftItem> giftItems;
+    private void CreateGiftScroller()
+    {
+        giftItems = manager.GetGiftItemList(true);
+        scroller.Refresh();
+        if (!giftItems.IsNullOrEmpty())
+        {
+            for (int i = 0; i < giftItems.Count; i++)
+            {
+                scroller.AddCell(ScrollerDataType.Header, i);
+            }
+        }
+        scroller.Restart();
+    }
+
+    void RefreshAll()
+    {
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnGiftWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnGiftWin.cs.meta
index 862a125..18811ae 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnGiftWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 7cc0cd7de844ca946be560af29b6a17c
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnManager.cs b/Main/System/HeroReturn/HeroReturnManager.cs
new file mode 100644
index 0000000..3aed945
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnManager.cs
@@ -0,0 +1,1153 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using LitJson;
+using UnityEngine;
+
+public class HeroReturnManager : GameSystemManager<HeroReturnManager>, IOpenServerActivity
+{
+    public int[] xbGridArr;
+    public Dictionary<int, int[][]> heroQaulityColor;
+    public int[][] seeArr;
+    public override void Init()
+    {
+        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
+        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk;
+        FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
+        OperationTimeHepler.Instance.operationTimeUpdateEvent += OperationTimeUpdateEvent;
+        OperationTimeHepler.Instance.operationStartEvent += OperationStartEvent;
+        OperationTimeHepler.Instance.operationEndEvent += OperationEndEvent;
+        OperationTimeHepler.Instance.operationAdvanceEvent += OperationAdvanceEvent;
+        StoreModel.Instance.RefreshBuyShopLimitEvent += RefreshBuyShopLimitEvent;
+        GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent += OnUpdateActSignInfosEvent;
+        HeroManager.Instance.onHeroChangeEvent += OnHeroChangeEvent;
+        TimeMgr.Instance.OnDayEvent += OnDayEvent;
+
+        var config = FuncConfigConfig.Get("HeroAppear");
+        xbGridArr = JsonMapper.ToObject<int[]>(config.Numerical1);
+
+        config = FuncConfigConfig.Get("HeroReturn");
+        heroQaulityColor = ConfigParse.ParseIntArray2Dict(config.Numerical1);
+        seeArr = JsonMapper.ToObject<int[][]>(config.Numerical2);
+
+        InitRedPointId();
+    }
+
+    public void SetheroQaulityColor(GradientText text, int qaulity)
+    {
+        if (!heroQaulityColor.TryGetValue(qaulity, out var colors)) return;
+        if (colors?.Length < 2) return;
+        text.SetVerticalGradient(ParseColor32(colors[0]), ParseColor32(colors[1]));
+    }
+
+    public override void Release()
+    {
+        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEventOnRelogin;
+        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk;
+        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
+        OperationTimeHepler.Instance.operationTimeUpdateEvent -= OperationTimeUpdateEvent;
+        OperationTimeHepler.Instance.operationStartEvent -= OperationStartEvent;
+        OperationTimeHepler.Instance.operationEndEvent -= OperationEndEvent;
+        OperationTimeHepler.Instance.operationAdvanceEvent -= OperationAdvanceEvent;
+        StoreModel.Instance.RefreshBuyShopLimitEvent -= RefreshBuyShopLimitEvent;
+        GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent -= OnUpdateActSignInfosEvent;
+        HeroManager.Instance.onHeroChangeEvent -= OnHeroChangeEvent;
+        TimeMgr.Instance.OnDayEvent -= OnDayEvent;
+    }
+
+    private void OnDayEvent()
+    {
+        UpdateRedpoint();
+    }
+
+    private void OnHeroChangeEvent(HeroInfo info)
+    {
+        UpdateRedpoint();
+    }
+
+    private void OnUpdateActSignInfosEvent(int arg1, int arg2)
+    {
+        UpdateRedpoint();
+    }
+
+    private void RefreshBuyShopLimitEvent()
+    {
+        UpdateRedpoint();
+    }
+
+    private void OnBeforePlayerDataInitializeEventOnRelogin()
+    {
+        isSendFirst = true;
+        starHeroIndex = 0;
+        callHeroIndex = 0;
+        starFreeAwardDict.Clear();
+    }
+
+    private void OnPlayerLoginOk()
+    {
+        TryPopWin();
+    }
+
+    private void OnFuncStateChangeEvent(int obj)
+    {
+        if (obj != (int)FuncOpenEnum.HeroReturn)
+            return;
+        TryPopWin();
+    }
+    public readonly int sendRankType = 6;
+    public int loadRankType => actNum * 1000 + sendRankType;
+    public const int activityType = (int)OpenServerActivityCenter.ActivityType.AT_DateActivity;
+    public const int activityID = (int)NewDayActivityID.HeroReturnAct;
+    public static OperationType operaType = OperationType.HeroReturn;
+    public Redpoint redPoint = new Redpoint(MainRedDot.HeroReturnRepoint);
+
+    public bool IsOpen => OperationTimeHepler.Instance.SatisfyOpenCondition(operaType);
+
+    public bool IsAdvance => OperationTimeHepler.Instance.SatisfyAdvanceCondition(operaType);
+
+    public bool priorityOpen => redPoint.state == RedPointState.Simple;
+    public readonly int actNum = 11;
+    public event Action<int> onStateUpdate;
+
+    private void OperationTimeUpdateEvent(OperationType type)
+    {
+        if (type == operaType)
+        {
+            if (UIManager.Instance.IsOpened<HeroReturnPopWin>())
+                UIManager.Instance.CloseWindow<HeroReturnPopWin>();
+            if (UIManager.Instance.IsOpened<HeroReturnWin>())
+                UIManager.Instance.CloseWindow<HeroReturnWin>();
+            gameRecDict.Clear();
+            UpdateRedpoint();
+        }
+    }
+
+    private void OperationStartEvent(OperationType type, int state)
+    {
+        if (type == operaType && state == 0)
+        {
+            onStateUpdate?.Invoke(activityID);
+            TryPopWin();
+            UpdateRedpoint();
+        }
+    }
+
+    private void OperationEndEvent(OperationType type, int state)
+    {
+        if (type == operaType)
+        {
+            onStateUpdate?.Invoke(activityID);
+            if (UIManager.Instance.IsOpened<HeroReturnPopWin>())
+                UIManager.Instance.CloseWindow<HeroReturnPopWin>();
+            if (UIManager.Instance.IsOpened<HeroReturnWin>())
+                UIManager.Instance.CloseWindow<HeroReturnWin>();
+            UpdateRedpoint();
+        }
+    }
+    private void OperationAdvanceEvent(OperationType type)
+    {
+        if (type == operaType)
+        {
+            onStateUpdate?.Invoke(activityID);
+            UpdateRedpoint();
+        }
+    }
+
+    public OperationHeroAppearInfo GetOperationHeroAppearInfo()
+    {
+        OperationTimeHepler.Instance.TryGetOperation(operaType, out OperationHeroAppearInfo act);
+        return act;
+    }
+
+    public void SetHeroSquareIcon(ImageEx image, string name)
+    {
+        var sprite = UILoader.LoadSprite("HeroHead", name);
+        if (sprite != null)
+        {
+            image.overrideSprite = sprite;
+            return;
+        }
+
+        image.SetSprite("herohead_default");
+    }
+
+    public void GetActTimeStr(TextEx timeText, string key = "TimeRush05")
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null)
+        {
+            timeText.text = Language.Get("OSActivity6");
+            return;
+        }
+        timeText.text = Language.Get(key, TimeUtility.SecondsToShortDHMS(act.GetResetSurplusTime()));
+    }
+
+    public void SetGradientTextColor(GradientText text, int[][] colors)
+    {
+        if (colors?.Length < 4) return;
+        text.topLeftColor = ParseColor32(colors[0]);
+        text.topRightColor = ParseColor32(colors[1]);
+        text.bottomLeftColor = ParseColor32(colors[2]);
+        text.bottomRightColor = ParseColor32(colors[3]);
+        text.SetVerticesDirty();
+    }
+
+    public Color32 ParseColor32(int[] colorArr)
+    {
+        return new Color32()
+        {
+            r = (byte)(colorArr.Length > 0 ? colorArr[0] : 0),
+            g = (byte)(colorArr.Length > 1 ? colorArr[1] : 0),
+            b = (byte)(colorArr.Length > 2 ? colorArr[2] : 0),
+            a = (byte)(colorArr.Length > 3 ? colorArr[3] : 255),
+        };
+    }
+
+
+    public int GetDefaultSkinID(int heroID)
+    {
+        HeroConfig heroConfig = HeroConfig.Get(heroID);
+        if (heroConfig == null || heroConfig.SkinIDList.IsNullOrEmpty()) return 0;
+        return heroConfig.SkinIDList[0];
+    }
+
+    public bool IsHeroReturnOpen()
+    {
+        if (!IsOpen) return false;
+        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.HeroReturn)) return false;
+        return true;
+    }
+
+
+    public int GetHeroIdIndex(int cfgID, int heroID)
+    {
+        var config = ActHeroAppearConfig.Get(cfgID);
+        if (config == null) return 0;
+
+        var heroArr = config.ActHeroIDList;
+        if (heroArr.IsNullOrEmpty()) return 0;
+
+        int index = Array.IndexOf(heroArr, heroID);
+        return index;
+    }
+
+
+
+    public event Action OnNowCallChooseHeroIDChangeEvent;
+    private int m_heroAppearActNum = 0;
+    public int nowCallChooseHeroID
+    {
+        get { return m_heroAppearActNum; }
+        set
+        {
+            if (m_heroAppearActNum == value) return;
+            m_heroAppearActNum = value;
+            OnNowCallChooseHeroIDChangeEvent?.Invoke();
+        }
+    }
+
+    public event Action OnNowStarUpChooseHeroIDChangeEvent;
+    private int m_nowStarUpChooseHeroID = 0;
+    public int nowStarUpChooseHeroID
+    {
+        get { return m_nowStarUpChooseHeroID; }
+        set
+        {
+            if (m_nowStarUpChooseHeroID == value) return;
+            m_nowStarUpChooseHeroID = value;
+            OnNowStarUpChooseHeroIDChangeEvent?.Invoke();
+        }
+    }
+
+    public int starHeroIndex = 0;
+    public int callHeroIndex = 0;
+    //<鍗囨槦璁″垝閫夋嫨鐨勬灏咺D绱㈠紩,鍗囨槦璁″垝鍏嶈垂濂栧姳璁板綍>
+    Dictionary<int, uint> starFreeAwardDict = new();
+
+    public event Action OnUpdateHeroAppearPlayerInfoEvent;
+    public void UpdateHeroAppearPlayerInfo(HAA22_tagSCActHeroAppearPlayerInfo vNetData)
+    {
+        if (vNetData == null) return;
+        if (vNetData.ActNum != this.actNum) return;
+
+        int actNum = vNetData.ActNum;
+        starHeroIndex = vNetData.StarHeroIndex;
+        callHeroIndex = vNetData.CallHeroIndex;
+        starFreeAwardDict[starHeroIndex] = vNetData.StarFreeAward;
+        UpdateRedpoint();
+        OnUpdateHeroAppearPlayerInfoEvent?.Invoke();
+    }
+
+    public void SendHeroAppearStarHeroSelect(int actNum, int starHeroIndex)
+    {
+        var pack = new CAA01_tagCSActHeroAppearStarHeroSelect();
+        pack.ActNum = (byte)actNum;                 // 娲诲姩缂栧彿
+        pack.StarHeroIndex = (byte)starHeroIndex;   // 鍗囨槦璁″垝閫夋嫨鐨勬灏咺D绱㈠紩
+        GameNetSystem.Instance.SendInfo(pack);
+    }
+
+    public void SnedHeroAppearCallHeroSelect(int actNum, int callHeroIndex)
+    {
+        var pack = new CAA02_tagCSActHeroAppearCallHeroSelect();
+        pack.ActNum = (byte)actNum;                 // 娲诲姩缂栧彿
+        pack.CallHeroIndex = (byte)callHeroIndex;   // 鎷涘嫙閫夋嫨鐨勬灏咺D绱㈠紩
+        GameNetSystem.Instance.SendInfo(pack);
+    }
+
+    public void SendGetStarReward()
+    {
+        var pack = new CA504_tagCMPlayerGetReward();
+        pack.RewardType = 10;
+        pack.DataEx = (uint)actNum;
+        GameNetSystem.Instance.SendInfo(pack);
+    }
+
+    #region 绾㈢偣
+    public int GetRedPointId(HeroReturnRedPointType type)
+    {
+        return MainRedDot.HeroReturnRepoint * 10 + (int)type;
+    }
+    public Redpoint checkInRedpoint;
+    public Redpoint starUpRedpoint;
+    public Redpoint shopRedpoint;
+    public Redpoint giftRedpoint;
+    public void InitRedPointId()
+    {
+        checkInRedpoint ??= new Redpoint(MainRedDot.HeroReturnRepoint, GetRedPointId(HeroReturnRedPointType.CheckIn));
+        starUpRedpoint ??= new Redpoint(MainRedDot.HeroReturnRepoint, GetRedPointId(HeroReturnRedPointType.StarUp));
+        shopRedpoint ??= new Redpoint(MainRedDot.HeroReturnRepoint, GetRedPointId(HeroReturnRedPointType.Shop));
+        giftRedpoint ??= new Redpoint(MainRedDot.HeroReturnRepoint, GetRedPointId(HeroReturnRedPointType.Gift));
+    }
+
+    public void UpdateRedpoint()
+    {
+        redPoint.state = RedPointState.None;
+        checkInRedpoint.state = RedPointState.None;
+        starUpRedpoint.state = RedPointState.None;
+        shopRedpoint.state = RedPointState.None;
+        giftRedpoint.state = RedPointState.None;
+
+        if (!IsHeroReturnOpen()) return;
+
+        if (HasCheckInCanHave()) //绛惧埌璧犵ぜ 
+        {
+            checkInRedpoint.state = RedPointState.Simple;
+        }
+
+        if (HasStarUpCanHave())//鏄熺骇鎻愬崌 
+        {
+            starUpRedpoint.state = RedPointState.Simple;
+        }
+
+        //鍏戞崲鍟嗗簵姣忓ぉ0鐐规樉绀虹孩鐐癸紝鐐瑰嚮杩涘叆涓�娆$晫闈㈠悗娑堝け
+        if (!IsShopVisitedToday) //鍏戞崲鍟嗗簵
+        {
+            shopRedpoint.state = RedPointState.Simple;
+        }
+
+        if (HasGiftCanHave())//鐨囨潈绀煎寘
+        {
+            giftRedpoint.state = RedPointState.Simple;
+        }
+    }
+    #endregion
+
+    #region 鎷嶈劯鐣岄潰
+    public bool IsTodayPop
+    {
+        get
+        {
+            int lastPopTime = LoadPopTimeData();
+            int todayStartTime = TimeUtility.GetTodayStartTick();
+            return lastPopTime < todayStartTime;
+        }
+    }
+    private string PopTimeDataKey { get { return $"HeroReturnManager_PopTimeData_{PlayerDatas.Instance.PlayerId}"; } }
+
+    private int LoadPopTimeData()
+    {
+        return LocalSave.GetInt(PopTimeDataKey);
+    }
+
+    public void SavePopTimeData()
+    {
+        LocalSave.SetInt(PopTimeDataKey, TimeUtility.AllSeconds);
+    }
+
+    private void TryPopWin()
+    {
+        if (!IsHeroReturnOpen()) return;
+        if (!IsTodayPop) return;
+        if (UIManager.Instance.IsOpened<HeroReturnPopWin>()) return;
+        if (UIManager.Instance.IsOpened<HeroReturnWin>()) return;
+        PopupWindowsProcessor.Instance.Add("HeroReturnPopWin");
+    }
+    #endregion
+
+    #region 绛惧埌
+    private int GetNowDayNum()
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return 0;
+
+        int dayNum = act.IndexOfDays(TimeUtility.ServerNow);
+        return dayNum < 0 ? 0 : dayNum + 1;
+    }
+
+    private bool IsCheckInGridUnlock(int gridDayNum)
+    {
+        int nowDayNum = GetNowDayNum();
+        if (nowDayNum <= 0) return false;
+
+        return nowDayNum >= gridDayNum;
+    }
+
+    /// <summary>
+    /// 0-鏈В閿� 1-鍙 2-宸茬
+    /// </summary>
+    public int GetCheckInState(int gridDayNum)
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return 0;
+
+        int actType = act.ActType;
+        if (GeneralActInfoManager.Instance.IsDaySigned(actType, actNum, gridDayNum)) return 2;
+        if (IsCheckInGridUnlock(gridDayNum)) return 1;
+        return 0;
+    }
+
+    public void SendGetCheckInReward()
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        int actType = act.ActType;
+        GeneralActInfoManager.Instance.SendGetSignReward(actType, actNum);
+    }
+
+    public bool HasCheckInCanHave()
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return false;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return false;
+
+        int templateID = config.SignTempID;
+        var list = ActSignAwardConfig.GetDayNumSortList(templateID);
+        if (list == null) return false;
+
+        for (int i = 0; i < list.Count; i++)
+        {
+            int dayNum = list[i];
+            int state = GetCheckInState(dayNum);
+            if (state == 1) return true;
+        }
+        return false;
+    }
+    #endregion
+
+    #region 鍗囨槦璁″垝
+
+    public bool IsSingleHero(OperationHeroAppearInfo act)
+    {
+        var appearConfig = ActHeroAppearConfig.Get(act.CfgID);
+        return appearConfig?.ActHeroIDList?.Length == 1;
+    }
+
+    public bool IsLockStarHero(OperationHeroAppearInfo act)
+    {
+        // 濡傛灉鍙湁涓�涓彲閫夋灏嗭紝瑙嗕负閿佸畾
+        if (IsSingleHero(act)) return true;
+        if (!starFreeAwardDict.TryGetValue(starHeroIndex, out uint freeAward)) return false;
+        //棰嗗彇浜嗕换鎰忎竴妗e厤璐瑰鍔辫涓洪攣瀹�
+        if (freeAward > 0) return true;
+        //璐拱浜嗕换鎰忎竴妗gぜ鍖呰涓洪攣瀹�
+        if (IsAnyStarGiftPurchased(act)) return true;
+        return LoadStarUpLockState(act);
+    }
+
+    /// <summary>
+    /// 妫�鏌ユ槸鍚﹁喘涔颁簡浠绘剰涓�妗e崌鏄熺ぜ鍖�
+    /// </summary>
+    private bool IsAnyStarGiftPurchased(OperationHeroAppearInfo act)
+    {
+        var appearConfig = ActHeroAppearConfig.Get(act.CfgID);
+        if (appearConfig == null) return false;
+
+        int starGiftTempID = appearConfig.StarGiftTempID;
+        var list = ActHeroAppearStarConfig.GetHeroReturnAwardIndexSortList(starGiftTempID);
+        if (list.IsNullOrEmpty()) return false;
+
+        for (int i = 0; i < list.Count; i++)
+        {
+            var config = ActHeroAppearStarConfig.GetConfig(starGiftTempID, list[i]);
+            if (config == null) continue;
+
+            if (RechargeManager.Instance.TryGetRechargeCount(config.StarGiftCTGID, out var rechargeCount))
+            {
+                if (rechargeCount.totalCount > 0)
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private string GetStarUpChooseHeroStateKey(OperationHeroAppearInfo act)
+    {
+        if (act == null) return string.Empty;
+        return string.Concat("HeroReturnManager_StarUpChooseHero_", act.CfgID, "_", ToInt(act.startDate), "_", ToInt(act.startDate), "_", PlayerDatas.Instance.PlayerId);
+    }
+
+    public bool LoadStarUpChooseHeroStateKey(OperationHeroAppearInfo act)
+    {
+        return LocalSave.GetBool(GetStarUpChooseHeroStateKey(act));
+    }
+
+    public void SaveStarUpChooseHeroStateKey(OperationHeroAppearInfo act)
+    {
+        LocalSave.SetBool(GetStarUpChooseHeroStateKey(act), true);
+    }
+
+    private string GetStarUpLockStateKey(OperationHeroAppearInfo act)
+    {
+        if (act == null) return string.Empty;
+        return string.Concat("HeroReturnManager_StarUpLockState_", act.CfgID, "_", ToInt(act.startDate), "_", ToInt(act.startDate), "_", PlayerDatas.Instance.PlayerId);
+    }
+
+    public bool LoadStarUpLockState(OperationHeroAppearInfo act)
+    {
+        return LocalSave.GetBool(GetStarUpLockStateKey(act));
+    }
+
+    public void SaveStarUpLockState(OperationHeroAppearInfo act)
+    {
+        LocalSave.SetBool(GetStarUpLockStateKey(act), true);
+    }
+
+    /// <summary>
+    /// 褰撳墠鍗囨槦璁″垝閫変腑鐨勬灏咺D
+    /// </summary>
+    public int GetCurrentDisplayStarUpHeroId()
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return 0;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null || config.ActHeroIDList?.Length <= starHeroIndex) return 0;
+
+        return config.ActHeroIDList[starHeroIndex];
+    }
+
+    private Dictionary<int, Dictionary<int, int[][]>> showHeroGiftItemInfoDict = new();
+    public bool TryGetStarUpAwardArr(int id, int heroID, out int[][] arr)
+    {
+        arr = null;
+        var config = ActHeroAppearStarConfig.Get(id);
+        if (config == null) return false;
+
+        var ctgConfig = CTGConfig.Get(config.StarGiftCTGID);
+        if (ctgConfig == null) return false;
+
+        if (!showHeroGiftItemInfoDict.TryGetValue(id, out var dict))
+        {
+            dict = new Dictionary<int, int[][]>();
+            showHeroGiftItemInfoDict[id] = dict;
+        }
+
+        if (!dict.TryGetValue(heroID, out arr))
+        {
+            // 濡傛灉缂撳瓨閲屾病鏈夊綋鍓嶆灏嗙殑鏁版嵁锛屾墠杩涜瑙f瀽
+            var giftdict = ConfigParse.ParseIntArray2Dict(config.HeroGiftItemInfo);
+            int[][] ctgArray = ctgConfig.GainItemList;
+
+            foreach (var kvp in giftdict)
+            {
+                int hId = kvp.Key;
+                int[][] hGift = kvp.Value ?? Array.Empty<int[]>();
+                dict[hId] = hGift.Concat(ctgArray).ToArray();
+            }
+
+            // 濡傛灉閬嶅巻瀹屽彂鐜伴厤琛ㄩ噷鏍规湰娌℃湁杩欎釜 heroID
+            if (!dict.TryGetValue(heroID, out arr))
+            {
+                arr = ctgArray;
+                dict[heroID] = arr;
+            }
+        }
+
+        return true;
+    }
+
+    /// <summary>
+    /// 0 - 鏈В閿� 1 - 鍙鍙� 2 - 宸查鍙�
+    /// </summary>
+    public int GetStarUpFreeState(int id)
+    {
+        var config = ActHeroAppearStarConfig.Get(id);
+        if (config == null) return 0;
+
+        int heroId = GetCurrentDisplayStarUpHeroId();
+        var heroConfig = HeroConfig.Get(heroId);
+        if (heroConfig == null) return 0;
+        // 娌¢攣瀹氱殑姝﹀皢瑙嗕负鏈В閿�
+        if (!IsLockStarHero(GetOperationHeroAppearInfo())) return 0;
+
+        // 娌¤幏寰楁灏嗘湰浣撲笉鍙鍙�
+        if (!HeroManager.Instance.HasHero(heroId)) return 0;
+        if (IsStarUpFreeHave(starHeroIndex, config.AwardIndex)) return 2;
+        if (IsHeroStarCntOk(heroConfig.HeroID, config.NeedStar)) return 1;
+        return 0;
+    }
+
+    private bool IsStarUpFreeHave(int starHeroIndex, int awardIndex)
+    {
+        if (!starFreeAwardDict.TryGetValue(starHeroIndex, out uint freeAward)) return false;
+        return ((freeAward >> awardIndex) & 1u) == 1u;
+    }
+
+    public bool IsHeroStarCntOk(int heroId, int needStar)
+    {
+        return GetNowHeroMaxStarCnt(heroId) >= needStar;
+    }
+
+    public int GetNowHeroMaxStarCnt(int heroId)
+    {
+        int res = 0;
+        foreach (var item in HeroManager.Instance.GetHeroList())
+        {
+            if (item == null) continue;
+            if (item.heroId == heroId)
+            {
+                if (res < item.heroStar)
+                    res = item.heroStar;
+            }
+        }
+        return res;
+    }
+
+    public bool TryGetStarUpStateIndex(int starGiftTempID, int tarState, out int index)
+    {
+        index = 0;
+        var list = ActHeroAppearStarConfig.GetHeroReturnAwardIndexSortList(starGiftTempID);
+        if (list == null) return false;
+
+        for (int i = 0; i < list.Count; i++)
+        {
+            var awardIndex = list[i];
+            var config = ActHeroAppearStarConfig.GetConfig(starGiftTempID, awardIndex);
+            if (config == null) continue;
+
+            int state = GetStarUpFreeState(config.ID);
+            if (state == tarState)
+            {
+                index = i;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public int GetStarUpJumpIndex(int starGiftTempID)
+    {
+        // 浼樺厛鏌ユ壘鍙鍙栫殑濂栧姳
+        if (TryGetStarUpStateIndex(starGiftTempID, 1, out int index)) return index;
+
+        // 鑻ユ病鏈夊彲棰嗗彇鐨勶紝鍒欐煡鎵炬湭杈惧埌鏉′欢鐨勫鍔�
+        if (TryGetStarUpStateIndex(starGiftTempID, 0, out index)) return index;
+
+        // 閮芥病鏈�
+        return 0;
+    }
+
+    public bool HasStarUpCanHave()
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return false;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return false;
+
+        int starGiftTempID = config.StarGiftTempID;
+        return TryGetStarUpStateIndex(starGiftTempID, 1, out _);
+    }
+    #endregion
+
+    #region 鍏戞崲鍟嗗簵
+
+
+    private string ShopVisitTimeDataKey { get { return $"HeroReturnManager_ShopVisitTime_{PlayerDatas.Instance.PlayerId}"; } }
+
+    private int LoadShopVisitTimeData()
+    {
+        return LocalSave.GetInt(ShopVisitTimeDataKey);
+    }
+
+    public void SaveShopVisitTimeData()
+    {
+        LocalSave.SetInt(ShopVisitTimeDataKey, TimeUtility.AllSeconds);
+    }
+    public bool IsShopVisitedToday
+    {
+        get
+        {
+            int lastVisitTime = LoadShopVisitTimeData();
+            int todayStartTime = TimeUtility.GetTodayStartTick();
+            return lastVisitTime >= todayStartTime;
+        }
+    }
+    #endregion
+
+    #region 鐨囨潈绀煎寘
+    //娌″敭缃�
+    public bool IsCanBuyToday(int ctgID)
+    {
+        CTGConfig config = CTGConfig.Get(ctgID);
+        if (config == null) return false;
+        if (!RechargeManager.Instance.TryGetRechargeCount(ctgID, out var rechargeCount)) return false;
+
+        if (config.DailyBuyCount == 0) return true;
+        return rechargeCount.todayCount < config.DailyBuyCount;
+    }
+
+    public bool IsNoSellOutCTGID(int ctgID)
+    {
+        CTGConfig config = CTGConfig.Get(ctgID);
+        if (config == null) return false;
+        if (!RechargeManager.Instance.TryGetRechargeCount(ctgID, out var rechargeCount)) return false;
+        return rechargeCount.totalCount < config.TotalBuyCount;
+    }
+
+    // 鍏嶈垂鍟嗗搧
+    public bool IsFreeShop(int shopID)
+    {
+        StoreConfig config = StoreConfig.Get(shopID);
+        if (config == null) return false;
+        return config.MoneyNum == 0;
+    }
+
+    //娌″敭缃�
+    public bool IsNoSellOutShopID(int shopID)
+    {
+        StoreConfig config = StoreConfig.Get(shopID);
+        if (config == null) return false;
+
+        StoreModel.Instance.TryGetIsSellOut(config, out int remainNum);
+        return remainNum > 0;
+    }
+
+    public List<HeroReturnGiftItem> GetGiftItemList(bool isSort = false)
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return null;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return null;
+
+        List<HeroReturnGiftItem> res = new List<HeroReturnGiftItem>();
+
+        var list = StoreModel.Instance.storeTypeDict[config.GiftShopType];
+        if (!list.IsNullOrEmpty())
+        {
+            for (int i = 0; i < list.Count; i++)
+            {
+                var item = list[i];
+                if (item.storeConfig == null)
+                    continue;
+                res.Add(new HeroReturnGiftItem
+                {
+                    type = 0,
+                    id = item.storeConfig.ID,
+                });
+            }
+        }
+
+        if (config.GiftCTGIDList != null)
+        {
+            for (int i = 0; i < config.GiftCTGIDList.Length; i++)
+            {
+                var item = config.GiftCTGIDList[i];
+                res.Add(new HeroReturnGiftItem
+                {
+                    type = 1,
+                    id = item,
+                });
+            }
+        }
+
+        if (isSort)
+        {
+            res = res.OrderBy(item =>
+            {
+                bool isCanBuy = item.type == 0 ? IsNoSellOutShopID(item.id) : IsCanBuyToday(item.id);
+                return !isCanBuy;
+            })
+            .ThenBy(item => item.type)
+            .ThenBy(item => item.id)
+            .ToList();
+        }
+
+        return res;
+    }
+
+    public bool HasGiftCanHave()
+    {
+        var list = GetGiftItemList(false);
+        if (list.IsNullOrEmpty())
+            return false;
+
+        for (int i = 0; i < list.Count; i++)
+        {
+            var item = list[i];
+            if (item.type == 0)
+            {
+                bool isFree = IsFreeShop(item.id);
+                bool isCanBuy = IsNoSellOutShopID(item.id);
+                if (isFree && isCanBuy)
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    #endregion
+    #region 鎷涘嫙
+    public int ToInt(OperationDate date)
+    {
+        return date.year * 10000 + date.month * 100 + date.day;
+    }
+    private string GetCallSkipKey(int cfgID, OperationDate startDate, OperationDate endDate)
+    {
+        return string.Concat("HeroReturnManager_CallSkip_", cfgID, "_", ToInt(startDate), "_", ToInt(endDate), "_", PlayerDatas.Instance.PlayerId);
+    }
+
+    public bool LoadCallSkipData(int cfgID, OperationDate startDate, OperationDate endDate)
+    {
+        return LocalSave.GetBool(GetCallSkipKey(cfgID, startDate, endDate));
+    }
+
+    public void SaveCallSkipData(int cfgID, OperationDate startDate, OperationDate endDate, bool value)
+    {
+        LocalSave.SetBool(GetCallSkipKey(cfgID, startDate, endDate), value);
+    }
+
+
+    /// <summary>
+    /// 褰撳墠鎷涘嫙閫変腑鐨勬灏咺D
+    /// </summary>
+    public int GetCurrentDisplayCallHeroId()
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return 0;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null || config.ActHeroIDList?.Length <= callHeroIndex) return 0;
+
+        return config.ActHeroIDList[callHeroIndex];
+    }
+
+    public int GetFirstHeroId()
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return 0;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null || config.ActHeroIDList.IsNullOrEmpty()) return 0;
+
+        return config.ActHeroIDList.First();
+    }
+
+    private string GetCallChooseHeroStateKey(OperationHeroAppearInfo act)
+    {
+        if (act == null) return string.Empty;
+        return string.Concat("HeroReturnManager_CallChooseHero_", act.CfgID, "_", ToInt(act.startDate), "_", ToInt(act.startDate), "_", PlayerDatas.Instance.PlayerId);
+    }
+
+    public bool LoadCallChooseHeroStateKey(OperationHeroAppearInfo act)
+    {
+        return LocalSave.GetBool(GetCallChooseHeroStateKey(act));
+    }
+
+    public void SaveCallChooseHeroStateKey(OperationHeroAppearInfo act)
+    {
+        LocalSave.SetBool(GetCallChooseHeroStateKey(act), true);
+    }
+
+    #endregion
+
+    #region 鏃惰鐗瑰崠
+
+    public event Action OnCurrentChooseSkinIDChangeEevent;
+    private int m_currentChooseSkinID = 0;
+
+    public int currentChooseSkinID
+    {
+        get
+        {
+            return m_currentChooseSkinID;
+        }
+        set
+        {
+            if (m_currentChooseSkinID == value) return;
+            m_currentChooseSkinID = value;
+            OnCurrentChooseSkinIDChangeEevent?.Invoke();
+        }
+    }
+
+    /// <summary>
+    /// 閫氳繃skinID鑾峰彇瀵瑰簲鐨刪eroID
+    /// </summary>
+    public int GetHeroIDBySkinID(int skinID)
+    {
+        foreach (var heroConfig in HeroConfig.GetValues())
+        {
+            if (heroConfig.SkinIDList != null && heroConfig.SkinIDList.Contains(skinID))
+            {
+                return heroConfig.HeroID;
+            }
+        }
+        return 0;
+    }
+
+    /// <summary>
+    /// 鑾峰彇skinID鍦℉eroConfig.SkinIDList涓殑绱㈠紩
+    /// </summary>
+    public int GetSkinIndexInHeroConfig(int heroID, int skinID)
+    {
+        var heroConfig = HeroConfig.Get(heroID);
+        if (heroConfig?.SkinIDList == null) return int.MaxValue;
+
+        for (int i = 0; i < heroConfig.SkinIDList.Length; i++)
+        {
+            if (heroConfig.SkinIDList[i] == skinID)
+                return i;
+        }
+        return int.MaxValue;
+    }
+
+    //<skinID,ctgID>
+    Dictionary<int, int> ctgDict = new();
+    public int GetCtgIDBySkinID(int skinID)
+    {
+        if (ctgDict.IsNullOrEmpty())
+        {
+            GetSkinIDToCtgIDDict();
+        }
+
+        int ctgID;
+        ctgDict.TryGetValue(skinID, out ctgID);
+        return ctgID;
+    }
+
+    Dictionary<int, int> GetSkinIDToCtgIDDict()
+    {
+        if (!ctgDict.IsNullOrEmpty())
+        {
+            return ctgDict;
+        }
+
+        foreach (var config in ActHeroAppearConfig.GetValues())
+        {
+            if (config == null || config.SkinCTGIDList == null) return null;
+
+            for (int i = 0; i < config.SkinCTGIDList.Length; i++)
+            {
+                var ctgID = config.SkinCTGIDList[i];
+                var ctgConfig = CTGConfig.Get(ctgID);
+                if (ctgConfig == null || ctgConfig.GainItemList == null) continue;
+
+                for (int j = 0; j < ctgConfig.GainItemList.Length; j++)
+                {
+                    var itemID = ctgConfig.GainItemList[j][0];
+                    var itemConfig = ItemConfig.Get(itemID);
+
+                    if (itemConfig == null) continue;
+                    if (!HeroSkinAttrConfig.TryGetSkinIDByItemID(itemID, out var skinID)) continue;
+                    if (ctgDict.ContainsKey(skinID)) continue;
+                    ctgDict[skinID] = ctgID;
+                }
+            }
+        }
+
+        return ctgDict;
+    }
+
+    public bool HasItemInSkinCTGIDList(int cfgID, int findItemID)
+    {
+        var config = ActHeroAppearConfig.Get(cfgID);
+        if (config == null || config.SkinCTGIDList == null) return false;
+
+        for (int i = 0; i < config.SkinCTGIDList.Length; i++)
+        {
+            var ctgID = config.SkinCTGIDList[i];
+            var ctgConfig = CTGConfig.Get(ctgID);
+            if (ctgConfig == null || ctgConfig.GainItemList == null) continue;
+
+            for (int j = 0; j < ctgConfig.GainItemList.Length; j++)
+            {
+                var itemID = ctgConfig.GainItemList[j][0];
+                if (itemID == findItemID) return true;
+            }
+        }
+        return false;
+    }
+
+
+    public List<int> GetSkinIDList(int cfgID, int heroID, int mainSkinID)
+    {
+        var config = ActHeroAppearConfig.Get(cfgID);
+        if (config == null || config.SkinCTGIDList == null) return null;
+
+        var res = new List<int>();
+        for (int i = 0; i < config.SkinCTGIDList.Length; i++)
+        {
+            var ctgID = config.SkinCTGIDList[i];
+            var ctgConfig = CTGConfig.Get(ctgID);
+            if (ctgConfig == null || ctgConfig.GainItemList == null) continue;
+
+            for (int j = 0; j < ctgConfig.GainItemList.Length; j++)
+            {
+                var itemID = ctgConfig.GainItemList[j][0];
+                var itemConfig = ItemConfig.Get(itemID);
+
+                if (itemConfig == null) continue;
+                if (!HeroSkinAttrConfig.TryGetSkinIDByItemID(itemID, out var skinID)) continue;
+                if (res.Contains(skinID)) continue;
+
+                res.Add(skinID);
+            }
+        }
+        // 鑷畾涔夋帓搴�
+        res.Sort((a, b) =>
+        {
+            // 1. 鍒ゆ柇鏄惁鏄紶鍏eroID鐨勭毊鑲わ紝浼樺厛鎺掑墠闈�
+            int heroIDA = GetHeroIDBySkinID(a);
+            int heroIDB = GetHeroIDBySkinID(b);
+
+            bool isPriorityA = (heroIDA == heroID);
+            bool isPriorityB = (heroIDB == heroID);
+
+            if (isPriorityA != isPriorityB)
+                return isPriorityA ? -1 : 1;
+
+            // 2. 鐩稿悓姝﹀皢鐨勫涓毊鑲よ繛缁尐鍦ㄤ竴璧�
+            if (heroIDA != heroIDB)
+                return heroIDA.CompareTo(heroIDB);
+
+            // 3. 濡傛灉heroid鐩稿悓锛屽拰MainSkinID鐩稿悓鐨勬帓鍦ㄦ渶鍓嶉潰
+            if (a == mainSkinID) return -1;
+            if (b == mainSkinID) return 1;
+
+            // 4. 鍏朵粬鎸塖kinIDList绱㈠紩鎺掑簭
+            int indexA = GetSkinIndexInHeroConfig(heroIDA, a);
+            int indexB = GetSkinIndexInHeroConfig(heroIDB, b);
+
+            return indexA.CompareTo(indexB);
+        });
+        return res;
+    }
+
+    #endregion
+
+    #region 鑾峰璁板綍
+    public static readonly int RecordType = 311;
+
+    public void SendViewGameRecPack(int treasureType)
+    {
+        CA008_tagCSViewGameRec pack = new CA008_tagCSViewGameRec();
+        pack.RecType = (ushort)RecordType;
+        pack.RecID = (uint)treasureType;
+        GameNetSystem.Instance.SendInfo(pack);
+    }
+
+    public bool isSendFirst = true;
+
+    List<HeroReturnGameRec> gameRecDict = new();
+
+    public List<HeroReturnGameRec> GetGameRecList()
+    {
+        return gameRecDict;
+    }
+
+    public event Action OnUpdateGameRecInfo;
+    public void UpdateGameRecInfo(HA009_tagSCGameRecInfo vNetData)
+    {
+
+        var act = GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        int treasureType = config.ActTreasureType;
+        if (vNetData.RecType != RecordType || treasureType != (int)vNetData.RecID) return;
+
+        if (vNetData.RecList.IsNullOrEmpty()) return;
+
+        if (isSendFirst)
+        {
+            gameRecDict.Clear();
+        }
+
+        foreach (var rec in vNetData.RecList)
+        {
+            try
+            {
+                var playerName = JsonMapper.ToObject(rec.UserData)["Name"].ToString();
+                var arenaGameRec = new HeroReturnGameRec
+                {
+                    Time = (int)rec.Time,
+                    ItemID = (int)rec.Value1,
+                    ItemCount = rec.Value2,
+                    PlayerID = (int)rec.Value3,
+                    ServerID = (int)rec.Value4,
+                    PlayerName = playerName,
+                };
+                gameRecDict.Add(arenaGameRec);
+            }
+            catch (Exception ex)
+            {
+                Debug.LogError($"JSON瑙f瀽閿欒: {ex.Message}, UserData: {rec.UserData}");
+                continue;
+            }
+        }
+
+        if (isSendFirst)
+        {
+            isSendFirst = !isSendFirst;
+            gameRecDict.Sort((x, y) => x.Time.CompareTo(y.Time));
+        }
+
+        OnUpdateGameRecInfo?.Invoke();
+
+    }
+
+    #endregion
+}
+
+
+public class HeroReturnGiftItem
+{
+    public int type;//0 鍟嗗簵id 1 鍏呭�糹d
+    public int id;
+}
+
+public enum HeroReturnRedPointType
+{
+    CheckIn = 1,
+    StarUp = 2,
+    Shop = 3,
+    Gift = 4,
+}
+
+public class HeroReturnGameRec
+{
+    public int Time;
+    public int ItemID;
+    public long ItemCount;
+    public int PlayerID;
+    public int ServerID;
+    public string PlayerName;
+}
\ No newline at end of file
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnManager.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnManager.cs.meta
index 862a125..106f3a9 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnManager.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: b509add974a70944ea78b2739e505c32
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnPopWin.cs b/Main/System/HeroReturn/HeroReturnPopWin.cs
new file mode 100644
index 0000000..95bb254
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnPopWin.cs
@@ -0,0 +1,96 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnPopWin : UIBase
+{
+    [SerializeField] ImageEx bgImage;
+    [SerializeField] UIHeroController rolelhShow;
+    [SerializeField] ImageEx qaulityBgImage;
+    [SerializeField] ImageEx qaulityImage;
+    [SerializeField] ButtonEx goButton;
+    [SerializeField] ImageEx titleBgImage;
+    [SerializeField] ImageEx titleImage;
+    [SerializeField] ImageEx infoBgImage;
+    [SerializeField] UIEffectPlayer uiEffectPlayer;
+    [SerializeField] TextEx infoText;
+    [SerializeField] TextEx timeText;
+    [SerializeField] Toggle todayPopToggle;
+    [SerializeField] ButtonEx closeButton;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+        goButton.SetListener(() =>
+        {
+            UIManager.Instance.CloseWindow<HeroReturnPopWin>();
+            if (!UIManager.Instance.IsOpened<HeroReturnWin>())
+                UIManager.Instance.OpenWindow<HeroReturnWin>();
+        });
+        todayPopToggle.AddListener((bool value) =>
+        {
+            if (value)
+                manager.SavePopTimeData();
+        });
+    }
+
+    protected override void OnPreOpen()
+    {
+        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
+    }
+
+    private void OnSecondEvent()
+    {
+        manager.GetActTimeStr(timeText, "HeroDebutPop02");
+    }
+
+    private void Display()
+    {
+        uiEffectPlayer.Stop();
+        todayPopToggle.isOn = !manager.IsTodayPop;
+
+        int heroID = manager.GetFirstHeroId();
+        var artConfig = ActHeroReturnArtConfig.Get(heroID);
+        if (artConfig == null) return;
+
+        var heroConfig = HeroConfig.Get(heroID);
+        if (heroConfig == null) return;
+
+        int skinID = manager.GetDefaultSkinID(heroID);
+        var skinConfig = HeroSkinConfig.Get(skinID);
+        if (skinConfig == null) return;
+
+        uiEffectPlayer.effectId = artConfig.PopInfoBgUIEffectId;
+        uiEffectPlayer.Play();
+
+        bgImage.SetSprite(StringUtility.Concat("HeroReturnPopBG_", heroID.ToString()));
+        bgImage.SetNativeSize();
+
+        qaulityBgImage.SetSprite($"HeroDebutPopQaulityBG{heroConfig.Quality}");
+        qaulityBgImage.SetNativeSize();
+
+        qaulityImage.SetSprite($"HeroDebutPopQaulity{heroConfig.Quality}");
+        qaulityImage.SetNativeSize();
+
+        titleBgImage.SetSprite(StringUtility.Concat("HeroReturnPopTitleBG_", heroID.ToString()));
+        titleBgImage.SetNativeSize();
+
+        titleImage.SetSprite(StringUtility.Concat("HeroReturnPopTitle_", heroID.ToString()));
+        titleImage.SetNativeSize();
+
+        infoBgImage.SetSprite(StringUtility.Concat("HeroReturnPopInfoBG_", heroID.ToString()));
+        infoBgImage.SetNativeSize();
+
+        infoText.text = artConfig.PopInfoText;
+        infoText.color = manager.ParseColor32(artConfig.PopInfoColor);
+
+        rolelhShow.Create(skinID, 1, motionName: "", isLh: true);
+
+        OnSecondEvent();
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnPopWin.cs.meta
similarity index 83%
rename from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
rename to Main/System/HeroReturn/HeroReturnPopWin.cs.meta
index 862a125..ccb00d2 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnPopWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 2ec133afd45ed6548bf892a3179cba58
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnRankAwardCell.cs b/Main/System/HeroReturn/HeroReturnRankAwardCell.cs
new file mode 100644
index 0000000..493ad95
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnRankAwardCell.cs
@@ -0,0 +1,45 @@
+using UnityEngine;
+
+public class HeroReturnRankAwardCell : CellView
+{
+    [SerializeField] ImageEx imgRank;
+    [SerializeField] TextEx txtRank;
+    [SerializeField] ItemCell[] itemCells;
+    public void Display(int rankA, int templateID)
+    {
+        var config = ActBillboardAwardConfig.GetConfig(templateID, rankA);
+        if (config == null) return;
+
+
+        if (rankA <= 3)
+        {
+            imgRank.SetActive(true);
+            txtRank.SetActive(false);
+            imgRank.SetSprite(StringUtility.Concat("Rank", rankA.ToString()));
+            txtRank.text = rankA.ToString();
+        }
+        else
+        {
+            imgRank.SetActive(false);
+            txtRank.SetActive(true);
+            txtRank.text = Language.Get("Arena15", rankA, config.RankB);
+        }
+
+        int[][] rewardArr = config.AwardItemList;
+        for (int i = 0; i < itemCells.Length; i++)
+        {
+            var itemCell = itemCells[i];
+            if (!rewardArr.IsNullOrEmpty() && i < rewardArr.Length)
+            {
+                int itemCellIndex = i;
+                itemCell.SetActive(true);
+                itemCell.Init(new ItemCellModel(rewardArr[i][0], true, rewardArr[i][1]));
+                itemCell.button.SetListener(() => ItemTipUtility.Show(rewardArr[itemCellIndex][0], true));
+            }
+            else
+            {
+                itemCell.SetActive(false);
+            }
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnRankAwardCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnRankAwardCell.cs.meta
index 862a125..291d287 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnRankAwardCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 31c2c107b8558ce4db4c8208a7019236
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnRankCell.cs b/Main/System/HeroReturn/HeroReturnRankCell.cs
new file mode 100644
index 0000000..2b748bb
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnRankCell.cs
@@ -0,0 +1,76 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnRankCell : MonoBehaviour
+{
+    [SerializeField] AvatarCell avatarCell;
+    [SerializeField] Text rankText;
+    [SerializeField] Text rankValueText;    //鎺掑悕姣旇緝鍐呭
+    [SerializeField] Text nameText;
+    [SerializeField] OfficialTitleCell officialTitleCell;
+    [SerializeField] Button queryPlayerBtn; //鍚庣画娣诲姞鐐瑰嚮鏌ョ湅鐜╁璇︽儏
+
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    // rank 涓�0 浠h〃鐜╁鑷繁
+    public void Display(int rankType, int rank, string valueFormat)
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        int billTempID = config.BillTempID;
+        var awardConfig = ActBillboardAwardConfig.GetConfig(billTempID, rank);
+
+        RankData rankData = null;
+        int viewPlayerId = (int)PlayerDatas.Instance.baseData.PlayerID;
+        if (rank != 0)
+        {
+            rankData = RankModel.Instance.GetRankDataByRank(rankType, rank);
+        }
+        else
+        {
+            rankData = RankModel.Instance.GetMyRank(rankType);
+            if (rankData == null)
+            {
+                //鍙栫帺瀹惰嚜宸辩殑鏁版嵁
+                avatarCell.InitUI(AvatarHelper.GetAvatarModel((int)PlayerDatas.Instance.baseData.PlayerID,
+                                                PlayerDatas.Instance.baseData.face,
+                                                PlayerDatas.Instance.baseData.facePic));
+                rankText.text = Language.Get("L1045");
+                rankValueText.text = awardConfig == null || awardConfig.NeedValue == 0 ? "0" : Language.Get("HeroDebut27", awardConfig.NeedValue);
+                nameText.text = PlayerDatas.Instance.baseData.PlayerName;
+                officialTitleCell.InitUI(PlayerDatas.Instance.baseData.realmLevel, PlayerDatas.Instance.baseData.TitleID);
+                return;
+            }
+            rank = rankData.rank;
+        }
+        if (rankData == null)
+        {
+            officialTitleCell.SetActive(false);
+            avatarCell.SetActive(false);
+            nameText.text = Language.Get("L1124");
+            rankValueText.text = awardConfig == null || awardConfig.NeedValue == 0 ? "0" : Language.Get("HeroDebut27", awardConfig.NeedValue);
+        }
+        else
+        {
+            officialTitleCell.SetActive(true);
+            officialTitleCell.InitUI((int)rankData.value1, (int)rankData.value2);
+            avatarCell.SetActive(true);
+            avatarCell.InitUI(AvatarHelper.GetAvatarModel((int)rankData.id, (int)rankData.value3, (int)rankData.value4));
+            viewPlayerId = (int)rankData.id;
+            nameText.text = rankData.name1;
+            rankValueText.text = string.Format(valueFormat, UIHelper.ReplaceLargeNum(rankData.cmpValue));
+        }
+
+        rankText.text = rank.ToString();
+        if (queryPlayerBtn != null)
+        {
+            queryPlayerBtn.AddListener(() =>
+            {
+                AvatarHelper.TryViewOtherPlayerInfo(viewPlayerId);
+            });
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnRankCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnRankCell.cs.meta
index 862a125..da17daf 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnRankCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: a9a73b5eecf896f46a562a01b9102ba6
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnRankTop3Cell.cs b/Main/System/HeroReturn/HeroReturnRankTop3Cell.cs
new file mode 100644
index 0000000..4ec37af
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnRankTop3Cell.cs
@@ -0,0 +1,47 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnRankTop3Cell : MonoBehaviour
+{
+    //[SerializeField] Model 鏄剧ずNPC 姝﹀皢妯″瀷
+    [SerializeField] Text rankValueText;    //鎺掑悕姣旇緝鍐呭
+    [SerializeField] Text nameText;
+    [SerializeField] OfficialTitleCell officialTitleCell;
+    [SerializeField] Button queryPlayerBtn; //鍚庣画娣诲姞鐐瑰嚮鏌ョ湅鐜╁璇︽儏
+    [SerializeField] HorseController model;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    public void Display(int rankType, int rank, string valueFormat = "{0}")
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        int billTempID = config.BillTempID;
+        var awardConfig = ActBillboardAwardConfig.GetConfig(billTempID, rank);
+
+
+        var rankData = RankModel.Instance.GetRankDataByRank(rankType, rank);
+        if (rankData == null)
+        {
+            rankValueText.text = awardConfig == null || awardConfig.NeedValue == 0 ? "0" : Language.Get("HeroDebut40", awardConfig.NeedValue);
+            nameText.text = Language.Get("L1124");
+            officialTitleCell.SetActive(false);
+            model.SetActive(false);
+            return;
+        }
+        officialTitleCell.SetActive(true);
+        rankValueText.text = string.Format(valueFormat, UIHelper.ReplaceLargeNum(rankData.cmpValue));
+        nameText.text = rankData.name1;
+        officialTitleCell.InitUI((int)rankData.value1, (int)rankData.value2);
+        model.SetActive(true);
+        model.Create(HorseManager.Instance.GetOtherPlayerHorseSkinID((int)rankData.value6), (int)rankData.value5, rank == 1 ? 1f : 0.8f);
+        queryPlayerBtn.SetListener(() =>
+        {
+            AvatarHelper.TryViewOtherPlayerInfo((int)rankData.id);
+        });
+    }
+
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnRankTop3Cell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnRankTop3Cell.cs.meta
index 862a125..5a00fb5 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnRankTop3Cell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: e3f3dcdd709d3ab4e918517695fb715a
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnRankWin.cs b/Main/System/HeroReturn/HeroReturnRankWin.cs
new file mode 100644
index 0000000..d9fc5da
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnRankWin.cs
@@ -0,0 +1,173 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnRankWin : FunctionsBaseWin
+{
+    [SerializeField] ButtonEx btnClose;
+    [SerializeField] RectTransform rankRect;
+    [SerializeField] RectTransform awardRect;
+    [SerializeField] TextEx timeText;
+
+
+
+    [Header("鎺掕")]
+    [SerializeField] ScrollerController rankScroller;
+    [SerializeField] List<HeroReturnRankTop3Cell> playerTop3Cells;
+    [SerializeField] HeroReturnRankCell myRankCell;
+    [HideInInspector] public string valueFormat = "{0}";
+    [Header("濂栧姳")]
+    // [SerializeField] TextEx txtCountdown;
+    [SerializeField] ScrollerController awardScroller;
+    [SerializeField] ImageEx heroImage;
+    [SerializeField] TextEx myRankNumText;
+    [SerializeField] TextEx myCallCntText;
+    [SerializeField] TextEx timeText1;
+
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    protected override void InitComponent()
+    {
+        base.InitComponent();
+        btnClose.SetListener(CloseWindow);
+    }
+
+    protected override void OnPreOpen()
+    {
+        base.OnPreOpen();
+        RankModel.Instance.ResetQueryParam();
+        RankModel.Instance.QueryRankByPage(manager.sendRankType, watchID: (int)PlayerDatas.Instance.baseData.PlayerID, groupValue1: manager.actNum);
+
+        RankModel.Instance.onRankRefresh += OnRankRefresh;
+        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
+        rankScroller.OnRefreshCell += OnRefreshCell;
+        awardScroller.OnRefreshCell += OnRefreshAwardCell;
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        base.OnPreClose();
+        RankModel.Instance.onRankRefresh -= OnRankRefresh;
+        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
+        rankScroller.OnRefreshCell -= OnRefreshCell;
+        awardScroller.OnRefreshCell -= OnRefreshAwardCell;
+    }
+
+    void OnRankRefresh(int type)
+    {
+        RankRefresh();
+    }
+
+    void RankRefresh()
+    {
+        ShowTop3();
+        rankScroller.m_Scorller.RefreshActiveCellViews();
+        DisplayMyRank();
+        DisplayAwardMyRank();
+    }
+
+    void CreateRankScroller()
+    {
+        rankScroller.Refresh();
+        var cnt = RankModel.Instance.GetRankShowMaxCnt(manager.sendRankType);
+        for (int i = 3; i < cnt; i++)
+        {
+            rankScroller.AddCell(ScrollerDataType.Header, i);
+        }
+        rankScroller.Restart();
+    }
+
+
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell.GetComponent<HeroReturnRankCell>();
+        _cell.Display(manager.loadRankType, cell.index + 1, valueFormat);
+        RankModel.Instance.ListenRankPage(manager.sendRankType, cell.index, groupValue1: manager.actNum);
+    }
+
+    private void OnSecondEvent()
+    {
+        manager.GetActTimeStr(timeText);
+        manager.GetActTimeStr(timeText1);
+    }
+
+    protected override void OpenSubUIByTabIndex()
+    {
+        rankRect.SetActive(functionOrder == 0);
+        awardRect.SetActive(functionOrder == 1);
+        Display();
+    }
+
+    public void Display()
+    {
+        int heroID = manager.GetFirstHeroId();
+
+        if (functionOrder == 0)
+        {
+            ShowTop3();
+            CreateRankScroller();
+            DisplayMyRank();
+        }
+        else
+        {
+            CreateAwardScroller();
+            heroImage.SetSprite(StringUtility.Concat("HeroReturnRankAwardHero_", heroID.ToString()));
+            heroImage.SetNativeSize();
+            DisplayAwardMyRank();
+        }
+        OnSecondEvent();
+    }
+
+    private void DisplayMyRank()
+    {
+        myRankCell.Display(manager.loadRankType, 0, valueFormat);
+    }
+
+    void ShowTop3()
+    {
+        for (int i = 0; i < playerTop3Cells.Count; i++)
+        {
+            playerTop3Cells[i].Display(manager.loadRankType, i + 1);
+        }
+    }
+
+    void DisplayAwardMyRank()
+    {
+
+        RankData rankData = RankModel.Instance.GetMyRank(manager.loadRankType);
+        if (rankData == null)
+        {
+            myRankNumText.text = Language.Get("L1045");
+            myCallCntText.text = "0";
+            return;
+        }
+        myRankNumText.text = Language.Get("WarlordPavilion12", rankData.rank);
+        myCallCntText.text = string.Format(valueFormat, UIHelper.ReplaceLargeNum(rankData.cmpValue));
+    }
+
+    int billTempID;
+    private void CreateAwardScroller()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        billTempID = config.BillTempID;
+        var list = ActBillboardAwardConfig.GetRankASortList(billTempID);
+        if (list == null) return;
+
+        awardScroller.Refresh();
+        for (int i = 0; i < list.Count; i++)
+        {
+            awardScroller.AddCell(ScrollerDataType.Header, list[i]);
+        }
+        awardScroller.Restart();
+    }
+
+    private void OnRefreshAwardCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell.GetComponent<HeroReturnRankAwardCell>();
+        _cell?.Display(cell.index, billTempID);
+    }
+}
\ No newline at end of file
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnRankWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnRankWin.cs.meta
index 862a125..ea39169 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnRankWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 564897474a653594fbb6f294779e17c1
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnShopCell.cs b/Main/System/HeroReturn/HeroReturnShopCell.cs
new file mode 100644
index 0000000..1dcedfb
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnShopCell.cs
@@ -0,0 +1,134 @@
+锘縰sing UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnShopCell : MonoBehaviour
+{
+    [SerializeField] Transform saleRect;
+    [SerializeField] Text saleText;
+    [SerializeField] Text itemName;
+    [SerializeField] ItemCell itemCell;
+    [SerializeField] Text limitText;
+    [SerializeField] Text lockTip;
+
+    [SerializeField] Transform priceRect;
+    [SerializeField] Image priceIcon;
+    [SerializeField] Text priceText;
+
+    [SerializeField] Transform priceRect1;//灞呬腑浣嶇疆鐨勪环鏍�
+    [SerializeField] Image priceIcon1;
+    [SerializeField] Text priceText1;
+
+    [SerializeField] Transform salePriceRect;
+    [SerializeField] Text salePriceText;
+    [SerializeField] Button buyButton;
+    [SerializeField] Image freeRedPoint;
+    [SerializeField] Text freeText;
+    [SerializeField] Image exclusiveImage;//涓撳睘
+    [SerializeField] Image sellOutImage;//鍞絼
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    public void Display(int index)
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        if (!StoreModel.Instance.storeTypeDict.TryGetValue(config.ExShopType, out var list)) return;
+
+        var storeData = list[index];
+        int shopID = storeData.shopId;
+        var itemID = storeData.storeConfig.ItemID;
+        var itemCount = storeData.storeConfig.ItemCnt;
+        exclusiveImage.SetActive(storeData.storeConfig.IsExclusive == 1);
+        itemCell.Init(new ItemCellModel(itemID, false, itemCount));
+        itemCell.button.AddListener(() =>
+        {
+            ItemTipUtility.Show(itemID);
+        });
+        var itemConfig = ItemConfig.Get(itemID);
+        itemName.text = itemConfig.ItemName;
+
+        //鎶樻墸
+        if (storeData.storeConfig.MoneyOriginal != 0)
+        {
+            saleRect.SetActive(true);
+            saleText.text = Language.Get("storename5", (storeData.storeConfig.MoneyNum * 10 / (float)storeData.storeConfig.MoneyOriginal).ToString("0.#"));
+        }
+        else
+        {
+            saleRect.SetActive(false);
+        }
+
+
+        var buyCnt = StoreModel.Instance.GetShopLimitBuyCount(shopID);
+        string limitStr = "";
+        if (storeData.storeConfig.MoneyNum == 0)
+        {
+            //鍏嶈垂
+            limitStr = "";
+        }
+        else if (storeData.storeConfig.ResetType == 0)
+        {
+            //闄愯喘
+            limitStr = storeData.storeConfig.LimitCnt > 0 ? Language.Get("storename8", storeData.storeConfig.LimitCnt - buyCnt, storeData.storeConfig.LimitCnt) : "";
+        }
+        else if (storeData.storeConfig.ResetType == 1)
+        {
+            //姣忔棩闄愯喘
+            limitStr = Language.Get("storename6", storeData.storeConfig.LimitCnt - buyCnt, storeData.storeConfig.LimitCnt);
+        }
+        else if (storeData.storeConfig.ResetType == 2)
+        {
+            //姣忓懆闄愯喘
+            limitStr = Language.Get("storename7", storeData.storeConfig.LimitCnt - buyCnt, storeData.storeConfig.LimitCnt);
+        }
+
+        limitText.text = buyCnt >= storeData.storeConfig.LimitCnt ? UIHelper.AppendColor(TextColType.Gray, limitStr) : limitStr;
+        buyButton.AddListener(() => { BuyGoods(shopID); });
+
+
+        //0鍙喘涔� 1宸插敭缃� 2鍏嶈垂 3鏈В閿�
+        var state = StoreModel.Instance.GetShopIDState(shopID);
+        sellOutImage.SetActive(state == 1);
+        freeRedPoint.SetActive(state == 2);
+        lockTip.text = state == 2 ? Language.Get("storename10", storeData.storeConfig.UnlockValue) : string.Empty;
+
+        priceRect.SetActive(state != 2 && storeData.storeConfig.MoneyOriginal != 0);
+        priceRect1.SetActive(state != 2 && storeData.storeConfig.MoneyOriginal == 0);
+        freeText.SetActive(state == 2);
+        salePriceRect.SetActive(state != 2 && storeData.storeConfig.MoneyOriginal != 0);
+
+        priceText.text = storeData.storeConfig.MoneyNum.ToString();
+        priceText1.text = storeData.storeConfig.MoneyNum.ToString();
+
+        if (storeData.storeConfig.MoneyType <= 0)
+        {
+            priceIcon.SetItemSprite(storeData.storeConfig.CostItemID);
+            priceIcon1.SetItemSprite(storeData.storeConfig.CostItemID);
+        }
+        else
+        {
+            priceIcon.SetIconWithMoneyType(storeData.storeConfig.MoneyType);
+            priceIcon1.SetIconWithMoneyType(storeData.storeConfig.MoneyType);
+        }
+
+        salePriceText.text = storeData.storeConfig.MoneyOriginal.ToString();
+    }
+
+    void BuyGoods(int shopID)
+    {
+        var state = StoreModel.Instance.GetShopIDState(shopID);
+        if (state == 1) return;
+
+        if (state == 2)
+        {
+            StoreModel.Instance.SendBuyShopItem(StoreConfig.Get(shopID), 1);
+        }
+        else
+        {
+            StoreModel.Instance.buyShopID = shopID;
+            UIManager.Instance.OpenWindow<BuyItemWin>();
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnShopCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnShopCell.cs.meta
index 862a125..e2e7aa9 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnShopCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 9f3fa1a06f369cd43bfeed05c9fc78da
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnShopLineCell.cs b/Main/System/HeroReturn/HeroReturnShopLineCell.cs
new file mode 100644
index 0000000..70c2d9b
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnShopLineCell.cs
@@ -0,0 +1,30 @@
+锘縰sing UnityEngine;
+
+public class HeroReturnShopLineCell : CellView
+{
+    [SerializeField] HeroReturnShopCell[] storeCells;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    public void Display(int index)
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        if (!StoreModel.Instance.storeTypeDict.TryGetValue(config.ExShopType, out var list)) return;
+
+        for (int i = 0; i < storeCells.Length; i++)
+        {
+            if (index + i < list.Count)
+            {
+                storeCells[i].SetActive(true);
+                storeCells[i].Display(index + i);
+            }
+            else
+            {
+                storeCells[i].SetActive(false);
+            }
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnShopLineCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnShopLineCell.cs.meta
index 862a125..72c39b5 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnShopLineCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 7dbf46352446602458ece7d5acde3f20
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnShopWin.cs b/Main/System/HeroReturn/HeroReturnShopWin.cs
new file mode 100644
index 0000000..b0a13f5
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnShopWin.cs
@@ -0,0 +1,80 @@
+using UnityEngine;
+
+public class HeroReturnShopWin : UIBase
+{
+    [SerializeField] OwnItemCell ownItemCell;
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] TextEx timeText;
+    [SerializeField] ScrollerController scroller;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+    }
+
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+        StoreModel.Instance.RefreshShopEvent += CreateScroller;
+        StoreModel.Instance.RefreshBuyShopLimitEvent += CreateScroller;
+        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
+        if (!manager.IsShopVisitedToday)
+        {
+            HeroReturnManager.Instance.SaveShopVisitTimeData();
+            manager.UpdateRedpoint();
+        }
+
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        ownItemCell.itemID = config.ExShopCostItemID;
+        CreateScroller();
+        OnSecondEvent();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+        StoreModel.Instance.RefreshShopEvent -= CreateScroller;
+        StoreModel.Instance.RefreshBuyShopLimitEvent -= CreateScroller;
+        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
+        StoreModel.Instance.selectStoreFuncType = StoreFunc.Normal;
+    }
+
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnShopLineCell;
+        _cell.Display(cell.index);
+    }
+
+    private void OnSecondEvent()
+    {
+        manager.GetActTimeStr(timeText);
+    }
+
+    void CreateScroller()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        if (!StoreModel.Instance.storeTypeDict.TryGetValue(config.ExShopType, out var list)) return;
+
+        scroller.Refresh();
+        for (int i = 0; i < list.Count; i++)
+        {
+            if (i % 3 == 0)
+            {
+                scroller.AddCell(ScrollerDataType.Header, i);
+            }
+        }
+        scroller.Restart();
+        scroller.lockType = EnhanceLockType.KeepVertical;
+    }
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnShopWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnShopWin.cs.meta
index 862a125..00eb07b 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnShopWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: fceb72924bf0d6c418f2128afc294a52
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnSkinAwardCell.cs b/Main/System/HeroReturn/HeroReturnSkinAwardCell.cs
new file mode 100644
index 0000000..dfa3ffe
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnSkinAwardCell.cs
@@ -0,0 +1,18 @@
+using UnityEngine;
+
+public class HeroReturnSkinAwardCell : CellView
+{
+    [SerializeField] ItemCell itemCell;
+    public void Display(int index, int[][] arr)
+    {
+        if (arr == null || arr.Length <= index) return;
+        int itemID = arr[index][0];
+        long itemCount = arr[index][1];
+        
+        itemCell.Init(new ItemCellModel(itemID, false, itemCount));
+        itemCell.button.AddListener(() =>
+        {
+            ItemTipUtility.Show(itemID);
+        });
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnSkinAwardCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnSkinAwardCell.cs.meta
index 862a125..acabbe0 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnSkinAwardCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: f6b0d10c152793d4f81f3b5fe4182937
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnSkinTabCell.cs b/Main/System/HeroReturn/HeroReturnSkinTabCell.cs
new file mode 100644
index 0000000..1474d76
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnSkinTabCell.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroReturnSkinTabCell : CellView
+{
+    [SerializeField] ImageEx tabBgImage;
+    [SerializeField] ButtonEx tabButton;
+    [SerializeField] RectTransform chooseRect;
+    [SerializeField] RectTransform maskRect;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    public void Display(int index, List<int> list)
+    {
+        if (list?.Count <= index) return;
+
+        var skinID = list[index];
+
+        tabBgImage.SetSprite(StringUtility.Concat("HeroReturnSkinTabInfo_", skinID.ToString()));
+        tabBgImage.SetNativeSize();
+        maskRect.SetActive(manager.currentChooseSkinID != skinID);
+        chooseRect.SetActive(manager.currentChooseSkinID == skinID);
+        tabButton.SetListener(() =>
+        {
+            manager.currentChooseSkinID = skinID;
+        });
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnSkinTabCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnSkinTabCell.cs.meta
index 862a125..88fa8b3 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnSkinTabCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 4f356ffc491c15044879e4d6601e5726
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnSkinWin.cs b/Main/System/HeroReturn/HeroReturnSkinWin.cs
new file mode 100644
index 0000000..aef3ab3
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnSkinWin.cs
@@ -0,0 +1,227 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnSkinWin : UIBase
+{
+    [SerializeField] float modelScale = 1f;
+    [SerializeField] RawImage bgImage;
+    [SerializeField] ImageEx heroNameImage;
+    [SerializeField] ImageEx skinInfoImage;
+    [SerializeField] ImageEx awardBgImage;
+    [SerializeField] TextEx timeText;
+    [SerializeField] ButtonEx buyButton;
+    [SerializeField] ImageEx buyImage;
+    [SerializeField] ImageEx countryImage;
+    [SerializeField] TextEx buyText;
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] UIHeroController uiHeroController;
+    [SerializeField] UIHeroController lhController;
+    [SerializeField] ScrollerController awardScroller;
+    [SerializeField] ScrollerController tabScroller;
+    [SerializeField] Color numColor;
+    [SerializeField] TextEx[] wearAttrText;
+    [SerializeField] TextEx[] roleAttrText;
+    [SerializeField] ButtonEx infoButton;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+        infoButton.SetListener(() =>
+        {
+            int heroID = manager.GetHeroIDBySkinID(manager.currentChooseSkinID);
+            HeroUIManager.Instance.selectForPreviewHeroID = heroID;
+            HeroUIManager.Instance.selectSkinIndex = manager.GetSkinIndexInHeroConfig(heroID, manager.currentChooseSkinID);
+            UIManager.Instance.OpenWindow<HeroBestBaseWin>(1);
+        });
+    }
+
+    protected override void OnPreOpen()
+    {
+        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
+        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent;
+        awardScroller.OnRefreshCell += OnRefreshAwardCell;
+        tabScroller.OnRefreshCell += OnRefreshTabCell;
+        manager.OnCurrentChooseSkinIDChangeEevent += OnCurrentChooseSkinIDChange;
+        CreateTabScroller();
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
+        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent;
+        awardScroller.OnRefreshCell -= OnRefreshAwardCell;
+        tabScroller.OnRefreshCell -= OnRefreshTabCell;
+        manager.OnCurrentChooseSkinIDChangeEevent -= OnCurrentChooseSkinIDChange;
+    }
+
+    private void OnCurrentChooseSkinIDChange()
+    {
+        tabScroller.m_Scorller.RefreshActiveCellViews();
+        Display();
+    }
+
+    void OnRefreshTabCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnSkinTabCell;
+        _cell.Display(cell.index, skinIDList);
+    }
+
+    List<int> skinIDList;
+    void CreateTabScroller()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        int heroID = manager.GetFirstHeroId();
+        var artConfig = ActHeroReturnArtConfig.Get(heroID);
+        if (artConfig == null) return;
+
+        skinIDList = manager.GetSkinIDList(act.CfgID, heroID, artConfig.MainSkinID);
+        if (skinIDList.IsNullOrEmpty()) return;
+        manager.currentChooseSkinID = skinIDList[0];
+
+        tabScroller.Refresh();
+        for (int i = 0; i < skinIDList.Count; i++)
+        {
+            tabScroller.AddCell(ScrollerDataType.Header, i);
+        }
+        tabScroller.Restart();
+    }
+
+    int[][] arr = null;
+    void OnRefreshAwardCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnSkinAwardCell;
+        _cell.Display(cell.index, arr);
+    }
+
+    void CreateAwardScroller(int[][] sourceArr)
+    {
+        if (sourceArr == null) return;
+
+        // 1. 鑾峰彇宸叉嫢鏈夌殑 ID 闆嗗悎 (浣跨敤 LINQ 绠�娲佹槑浜�)
+        var ownedItems = HeroSkinAttrConfig.GetItemList();
+        var itemIds = ownedItems != null ? new HashSet<int>(ownedItems) : new HashSet<int>();
+
+        // 2. 杩囨护鎺� items 涓凡鏈夌殑椤癸紝骞剁洿鎺ヨ祴鍊肩粰鎴愬憳鍙橀噺
+        // arr[i][0] 鍋囪涓哄垽鏂槸鍚﹀瓨鍦ㄤ簬 items 涓殑 ID
+        this.arr = System.Array.FindAll(sourceArr, row => !itemIds.Contains(row[0]));
+
+        // 3. 鍒锋柊 UI
+        awardScroller.Refresh();
+        for (int i = 0; i < this.arr.Length; i++)
+        {
+            awardScroller.AddCell(ScrollerDataType.Header, i);
+        }
+        awardScroller.Restart();
+    }
+
+    private void OnSecondEvent()
+    {
+        manager.GetActTimeStr(timeText);
+    }
+
+    private void OnRechargeCountEvent(int obj)
+    {
+        Display();
+    }
+
+    public void Display()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        int heroID = manager.GetFirstHeroId();
+        var artConfig = ActHeroReturnArtConfig.Get(heroID);
+        if (artConfig == null) return;
+
+        var heroConfig = HeroConfig.Get(heroID);
+        if (heroConfig == null) return;
+
+        int skinID = manager.currentChooseSkinID;
+
+        var heroSkinAttrConfig = HeroSkinAttrConfig.Get(skinID);
+        if (heroSkinAttrConfig == null) return;
+        if (heroSkinAttrConfig.WearAttrIDList == null) return;
+        if (heroSkinAttrConfig.WearAttrValueList == null) return;
+        if (heroSkinAttrConfig.RoleAttrIDList == null) return;
+        if (heroSkinAttrConfig.RoleAttrValueList == null) return;
+
+        var skinIDList = manager.GetSkinIDList(act.CfgID, heroID, skinID);
+        if (skinIDList.IsNullOrEmpty()) return;
+
+        int ctgId = manager.GetCtgIDBySkinID(skinID);
+        var ctgConfig = CTGConfig.Get(ctgId);
+        if (ctgConfig == null) return;
+
+        if (!RechargeManager.Instance.TryGetOrderInfo(ctgId, out var orderConfig)) return;
+        if (!RechargeManager.Instance.TryGetRechargeCount(ctgId, out var rechargeCount)) return;
+        if (!RechargeManager.Instance.TryGetRechargeItem(ctgId, out var rechargeItemList)) return;
+
+        bgImage.SetTexture2D(StringUtility.Concat("HeroReturnSkinBG_", skinID.ToString()));
+
+        heroNameImage.SetSprite(StringUtility.Concat("HeroReturnSkinHeroName_", skinID.ToString()));
+        heroNameImage.SetNativeSize();
+
+        skinInfoImage.SetSprite(StringUtility.Concat("HeroReturnSkinInfo_", skinID.ToString()));
+        skinInfoImage.SetNativeSize();
+
+        awardBgImage.SetSprite(StringUtility.Concat("HeroReturnSkinAwardBG_", skinID.ToString()));
+        awardBgImage.SetNativeSize();
+
+        uiHeroController.Create(skinID, modelScale);
+        lhController.Create(skinID, 1, motionName: "", isLh: true);
+        countryImage.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
+        OnSecondEvent();
+
+        CreateAwardScroller(ctgConfig.GainItemList);
+
+        bool isCanBuy = manager.IsNoSellOutCTGID(ctgId);
+        //buyImage.gray = !isCanBuy;
+        buyText.text = !isCanBuy ? Language.Get("storename11") : Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderConfig.PayRMBNumOnSale));
+
+        buyButton.interactable = isCanBuy;
+        buyButton.SetListener(() =>
+        {
+            RechargeManager.Instance.CTG(ctgId);
+        });
+
+        for (int i = 0; i < wearAttrText.Length; i++)
+            SetAttrInfo(0, i, heroSkinAttrConfig, wearAttrText[i]);
+
+        for (int i = 0; i < roleAttrText.Length; i++)
+            SetAttrInfo(1, i, heroSkinAttrConfig, roleAttrText[i]);
+
+    }
+
+    // type 0 绌挎埓灞炴�у�� 1 涓诲叕灞炴��
+    public void SetAttrInfo(int type, int index, HeroSkinAttrConfig heroSkinAttrConfig, TextEx info)
+    {
+        if (heroSkinAttrConfig == null) return;
+
+        int[] arrID = type == 0 ? heroSkinAttrConfig.WearAttrIDList : heroSkinAttrConfig.RoleAttrIDList;
+        int[] arrValue = type == 0 ? heroSkinAttrConfig.WearAttrValueList : heroSkinAttrConfig.RoleAttrValueList;
+        if (arrID?.Length <= index || arrValue?.Length <= index)
+        {
+            info.text = string.Empty;
+            return;
+        }
+
+        info.text = GetFullDescription(arrID[index], arrValue[index]);
+    }
+
+    string GetFullDescription(int id, long value)
+    {
+        var config = PlayerPropertyConfig.Get(id);
+        if (config == null) return string.Empty;
+        return Language.Get("HeroDebut33", config.ShowName, PlayerPropertyConfig.GetValueDescription(id, value));
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnSkinWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnSkinWin.cs.meta
index 862a125..c0d4190 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnSkinWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: a583b7b333d69584792f6aef8834bfcd
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnStarUpCell.cs b/Main/System/HeroReturn/HeroReturnStarUpCell.cs
new file mode 100644
index 0000000..5a56186
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnStarUpCell.cs
@@ -0,0 +1,126 @@
+using System.Linq;
+using UnityEngine;
+
+public class HeroReturnStarUpCell : CellView
+{
+    [SerializeField] ItemCell freeAwardItemCell;
+    [SerializeField] Transform freeAwardHaveTransform;//宸查鍙�
+    [SerializeField] Transform freeAwardCanHaveTransform;//鍙鍙�
+
+    [SerializeField] Transform upProcssBGTransform;
+    [SerializeField] Transform upProcessTransform;
+    [SerializeField] Transform downProcssBGTransform;
+    [SerializeField] Transform downProcessTransform;
+    [SerializeField] TextEx starCntText;
+    [SerializeField] TextEx limitText;
+    [SerializeField] ButtonEx buyButton;
+    [SerializeField] ImageEx buyImage;
+    [SerializeField] TextEx buyText;
+    [SerializeField] ImageEx rateImage;
+    [SerializeField] TextEx rateText;
+    [SerializeField] ScrollerController scroller;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    int id;
+    public void Display(int id, CellView cell)
+    {
+        this.id = id;
+
+        int heroID = cell.info.Value.infoInt1;
+        bool isFrist = cell.info.Value.infoInt2 == 1;
+        bool isEnd = cell.info.Value.infoInt3 == 1;
+
+        var config = ActHeroAppearStarConfig.Get(id);
+        if (config == null) return;
+
+        var heroConfig = HeroConfig.Get(heroID);
+        if (heroConfig == null) return;
+
+        if (config.FreeAwardItemList.IsNullOrEmpty()) return;
+        int ctgId = config.StarGiftCTGID;
+        int awardIndex = config.AwardIndex;
+        if (!manager.TryGetStarUpAwardArr(id, heroID, out int[][] list)) return;
+        if (!RechargeManager.Instance.TryGetOrderInfo(ctgId, out var orderConfig)) return;
+        if (!RechargeManager.Instance.TryGetRechargeCount(ctgId, out var rechargeCount)) return;
+        if (!RechargeManager.Instance.TryGetRechargeItem(ctgId, out var rechargeItemList)) return;
+        CTGConfig ctgConfig = CTGConfig.Get(ctgId);
+        if (ctgConfig == null) return;
+
+        rateImage.SetActive(true);
+        rateText.text = Language.Get("DailySpecials07", ctgConfig.Percentage);
+
+        int state = manager.GetStarUpFreeState(id);//0 - 鏈В閿� 1 - 鍙鍙� 2 - 宸查鍙�
+        freeAwardHaveTransform.SetActive(state == 2);
+        freeAwardCanHaveTransform.SetActive(state == 1);
+
+        bool isNoSellOut = manager.IsNoSellOutCTGID(ctgId);
+        buyButton.interactable = state != 0 && isNoSellOut;
+        buyButton.SetListener(() =>
+        {
+            if (isNoSellOut && state != 0)
+            {
+                RechargeManager.Instance.CTG(ctgId);
+            }
+        });
+        //buyImage.gray = state == 0 || !isNoSellOut;
+        buyText.text = !isNoSellOut ? Language.Get("storename11") : Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderConfig.PayRMBNumOnSale));
+        limitText.text = Language.Get("TimeRush08", UIHelper.AppendColor(rechargeCount.totalCount >= ctgConfig.TotalBuyCount ? TextColType.Red : TextColType.DarkGreen, $"{rechargeCount.totalCount}/{ctgConfig.TotalBuyCount}"));
+        bool isHeroStarOk = manager.IsHeroStarCntOk(heroConfig.HeroID, config.NeedStar) && HeroManager.Instance.HasHero(heroConfig.HeroID) && manager.IsLockStarHero(manager.GetOperationHeroAppearInfo());
+        upProcssBGTransform.SetActive(!isFrist);
+        downProcssBGTransform.SetActive(!isEnd);
+
+        upProcessTransform.SetActive(isHeroStarOk);
+        downProcessTransform.SetActive(isHeroStarOk);
+
+        CreateScroller(list);
+
+        int[] arr = config.FreeAwardItemList.First();
+        int itemID = arr[0];
+        int itemCount = arr[1];
+        freeAwardItemCell.SetActive(true);
+        freeAwardItemCell.Init(new ItemCellModel(itemID, false, itemCount));
+        freeAwardItemCell.button.AddListener(() =>
+        {
+            if (state == 1)
+            {
+                manager.SendGetStarReward();
+            }
+            else
+            {
+                ItemTipUtility.Show(itemID);
+            }
+        });
+
+        starCntText.text = Language.Get("HeroDebut20", config.NeedStar);
+    }
+
+    private void CreateScroller(int[][] list)
+    {
+        if (list == null) return;
+        var config = ActHeroAppearStarConfig.Get(id);
+        if (config == null) return;
+
+        scroller.OnRefreshCell += OnRefreshCell;
+        scroller.Refresh();
+        for (int i = 0; i < list.Length; i++)
+        {
+            var item = list[i];
+            var itemID = item[0];
+            var itemCount = item[1];
+            CellInfo cellInfo = new()
+            {
+                infoInt1 = itemID,
+                infoInt2 = itemCount,
+                infoInt3 = manager.IsNoSellOutCTGID(config.StarGiftCTGID) ? 1 : 0,
+            };
+            scroller.AddCell(ScrollerDataType.Header, i, cellInfo);
+        }
+        scroller.Restart();
+        scroller.OnRefreshCell -= OnRefreshCell;
+    }
+
+    private void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell.GetComponent<HeroReturnStarUpPaidItemCell>();
+        _cell?.Display(cell.index, cell);
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnStarUpCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnStarUpCell.cs.meta
index 862a125..c62b946 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnStarUpCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 98c3340ec72bd5b46935ede657bae2b3
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnStarUpChangeCell.cs b/Main/System/HeroReturn/HeroReturnStarUpChangeCell.cs
new file mode 100644
index 0000000..1bcafcc
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnStarUpChangeCell.cs
@@ -0,0 +1,33 @@
+using UnityEngine;
+
+public class HeroReturnStarUpChangeCell : CellView
+{
+    [SerializeField] HeroReturnStarUpChangeItem[] items;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    public void Display(int rowIndex)
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        var heroArr = config.ActHeroIDList;
+        if (heroArr.IsNullOrEmpty()) return;
+
+        for (int i = 0; i < items.Length; i++)
+        {
+            int index = rowIndex * HeroReturnCallChangeWin.rowCountMax + i;
+            if (index < heroArr.Length)
+            {
+                items[i].SetActive(true);
+                items[i].Display(index, heroArr);
+            }
+            else
+            {
+                items[i].SetActive(false);
+            }
+        }
+    }
+
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnStarUpChangeCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnStarUpChangeCell.cs.meta
index 862a125..065806b 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnStarUpChangeCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 24e8dba4fdfc18547bd908c4906c29bc
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnStarUpChangeItem.cs b/Main/System/HeroReturn/HeroReturnStarUpChangeItem.cs
new file mode 100644
index 0000000..d5d9a2a
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnStarUpChangeItem.cs
@@ -0,0 +1,41 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnStarUpChangeItem : MonoBehaviour
+{
+
+    [SerializeField] HeroHeadBaseCell heroHeadBaseCell;
+    [SerializeField] Image jobImg;
+    [SerializeField] Text nameText;
+    [SerializeField] Transform select;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    HeroConfig heroConfig;
+    int index;
+    public void Display(int index, int[] heroIds)
+    {
+        this.index = index;
+        if (heroIds?.Length <= index) return;
+
+        int heroId = heroIds[index];
+        heroConfig = HeroConfig.Get(heroId);
+        if (heroConfig == null) return;
+        
+        int skinID = manager.GetDefaultSkinID(heroId);
+        var heroSkinConfig = HeroSkinConfig.Get(skinID);
+        if (heroSkinConfig == null) return;
+
+        heroHeadBaseCell.Init(heroConfig.HeroID, skinID, 0, 0, 0, OnClick);
+        nameText.text = heroConfig.Name;
+        jobImg.SetSprite(HeroUIManager.Instance.GetJobIconName(heroConfig.Class));
+        bool isChoose = manager.nowStarUpChooseHeroID == heroId;
+        select?.SetActive(isChoose);
+    }
+
+    public void OnClick()
+    {
+        if (heroConfig == null) return;
+
+        manager.nowStarUpChooseHeroID = heroConfig.HeroID;
+
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnStarUpChangeItem.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnStarUpChangeItem.cs.meta
index 862a125..4440d4a 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnStarUpChangeItem.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: f8d8ae1944679f64abb94301a00e6938
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnStarUpChangeWin.cs b/Main/System/HeroReturn/HeroReturnStarUpChangeWin.cs
new file mode 100644
index 0000000..664893a
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnStarUpChangeWin.cs
@@ -0,0 +1,100 @@
+using UnityEngine;
+
+public class HeroReturnStarUpChangeWin : UIBase
+{
+    [SerializeField] ScrollerController scroller;
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] ButtonEx okButton;
+    [SerializeField] ButtonEx previewButton;
+    [SerializeField] UIHeroController uiHeroController;
+    public const int rowCountMax = 4;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+        okButton.SetListener(() =>
+        {
+            var act = manager.GetOperationHeroAppearInfo();
+            if (act == null) return;
+
+            int index = manager.GetHeroIdIndex(act.CfgID, manager.nowStarUpChooseHeroID);
+            if (index < 0) return;
+
+            manager.SendHeroAppearStarHeroSelect(manager.actNum, index);
+            manager.SaveStarUpChooseHeroStateKey(act);
+            CloseWindow();
+
+        });
+        previewButton.SetListener(() =>
+        {
+            HeroUIManager.Instance.selectForPreviewHeroID = manager.nowStarUpChooseHeroID;
+            UIManager.Instance.OpenWindow<HeroBestBaseWin>();
+        });
+    }
+
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+        manager.OnNowStarUpChooseHeroIDChangeEvent += OnNowStarUpChooseHeroIDChangeEvent;
+        manager.nowStarUpChooseHeroID = manager.GetCurrentDisplayStarUpHeroId();
+        Display();
+        CreateScroller();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+        manager.OnNowStarUpChooseHeroIDChangeEvent -= OnNowStarUpChooseHeroIDChangeEvent;
+        if (!UIManager.Instance.IsOpened<HeroReturnStarUpWin>() && manager.LoadStarUpChooseHeroStateKey(manager.GetOperationHeroAppearInfo()))
+        {
+            UIManager.Instance.OpenWindow<HeroReturnStarUpWin>();
+        }
+    }
+
+    private void OnNowStarUpChooseHeroIDChangeEvent()
+    {
+        Display();
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnStarUpChangeCell;
+        _cell.Display(cell.index);
+    }
+
+    void CreateScroller()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        var arr = config.ActHeroIDList;
+        if (arr.IsNullOrEmpty()) return;
+
+
+        scroller.Refresh();
+        int rowCount = (int)Mathf.Ceil((float)arr.Length / rowCountMax);
+        for (int i = 0; i < rowCount; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, i);
+        }
+        scroller.Restart();
+    }
+
+    void Display()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+
+        int skinID = manager.GetDefaultSkinID(manager.nowStarUpChooseHeroID);
+        var skinConfig = HeroSkinConfig.Get(skinID);
+        if (skinConfig == null) return;
+
+        uiHeroController.Create(skinID, 1);
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnStarUpChangeWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnStarUpChangeWin.cs.meta
index 862a125..adca8da 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnStarUpChangeWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 509bac132ac2a424fbed7f0aa2ef09de
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnStarUpPaidItemCell.cs b/Main/System/HeroReturn/HeroReturnStarUpPaidItemCell.cs
new file mode 100644
index 0000000..54d32aa
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnStarUpPaidItemCell.cs
@@ -0,0 +1,17 @@
+using UnityEngine;
+
+public class HeroReturnStarUpPaidItemCell : CellView
+{
+    [SerializeField] ItemCell itemCell;
+    [SerializeField] Transform soldOutTransform;
+    public void Display(int index, CellView cell)
+    {
+        int itemID = cell.info.Value.infoInt1;
+        int count = cell.info.Value.infoInt2;
+        bool isSoldOut = cell.info.Value.infoInt3 == 0;
+        soldOutTransform.SetActive(isSoldOut);
+        itemCell.SetActive(true);
+        itemCell.Init(new ItemCellModel((int)itemID, false, count));
+        itemCell.button.AddListener(() => ItemTipUtility.Show(itemID));
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnStarUpPaidItemCell.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnStarUpPaidItemCell.cs.meta
index 862a125..f912ba1 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnStarUpPaidItemCell.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: dd781838fa949c54cafb8db9df042715
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnStarUpWin.cs b/Main/System/HeroReturn/HeroReturnStarUpWin.cs
new file mode 100644
index 0000000..7d345a6
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnStarUpWin.cs
@@ -0,0 +1,159 @@
+using UnityEngine;
+
+public class HeroReturnStarUpWin : UIBase
+{
+    [SerializeField] HeroHeadBaseCell heroHeadBaseCell;
+    [SerializeField] ImageEx jobImg;
+    [SerializeField] TextEx nameText;
+    [SerializeField] ButtonEx changeButton;
+    [SerializeField] ButtonEx lockButton;
+    [SerializeField] GradientText heroNameText;
+    [SerializeField] TextEx timeText;
+    [SerializeField] ImageEx heroImage;
+    [SerializeField] ButtonEx goCallButton;
+    [SerializeField] ButtonEx goInfoButton;
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] ScrollerController scroller;
+    HeroReturnManager manager => HeroReturnManager.Instance;
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(CloseWindow);
+        goCallButton.SetListener(() =>
+        {
+            UIManager.Instance.CloseWindow<HeroReturnStarUpWin>();
+            UIManager.Instance.OpenWindow<HeroReturnCallWin>();
+        });
+        goInfoButton.SetListener(() =>
+        {
+            if (heroConfig == null) return;
+            UIManager.Instance.CloseWindow<HeroReturnStarUpWin>();
+            HeroUIManager.Instance.selectForPreviewHeroID = heroConfig.HeroID;
+            UIManager.Instance.OpenWindow<HeroBestBaseWin>();
+        });
+        changeButton.SetListener(() =>
+        {
+            UIManager.Instance.OpenWindow<HeroReturnStarUpChangeWin>();
+        });
+        lockButton.SetListener(() =>
+        {
+            manager.SaveStarUpLockState(manager.GetOperationHeroAppearInfo());
+            Display();
+            manager.UpdateRedpoint();
+        });
+    }
+
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
+        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent;
+        manager.OnUpdateHeroAppearPlayerInfoEvent += OnUpdateHeroAppearPlayerInfoEvent;
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
+        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent;
+        manager.OnUpdateHeroAppearPlayerInfoEvent -= OnUpdateHeroAppearPlayerInfoEvent;
+    }
+
+    private void OnUpdateHeroAppearPlayerInfoEvent()
+    {
+        scroller.m_Scorller.RefreshActiveCellViews();
+        Display();
+    }
+
+    private void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell.GetComponent<HeroReturnStarUpCell>();
+        _cell?.Display(cell.index, cell);
+    }
+
+    private void OnSecondEvent()
+    {
+        manager.GetActTimeStr(timeText);
+    }
+
+    private void OnRechargeCountEvent(int obj)
+    {
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+
+    HeroConfig heroConfig;
+    private void Display()
+    {
+        int heroID = manager.GetCurrentDisplayStarUpHeroId();
+        heroConfig = HeroConfig.Get(heroID);
+        if (heroConfig == null) return;
+
+        var artConfig = ActHeroReturnArtConfig.Get(heroID);
+        if (artConfig == null) return;
+
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+
+        var heroArr = config.ActHeroIDList;
+        if (heroArr.Length <= manager.starHeroIndex) return;
+
+        int heroId = heroArr[manager.starHeroIndex];
+        heroConfig = HeroConfig.Get(heroId);
+        if (heroConfig == null) return;
+
+        int skinID = manager.GetDefaultSkinID(heroId);
+        var heroSkinConfig = HeroSkinConfig.Get(skinID);
+        if (heroSkinConfig == null) return;
+
+        bool isLockStarHero = manager.IsLockStarHero(act);
+        changeButton.SetActive(!isLockStarHero);
+        lockButton.interactable = !isLockStarHero;
+
+        heroHeadBaseCell.Init(heroConfig.HeroID, skinID, 0, 0, 0, () =>
+        {
+            if (isLockStarHero) return;
+            UIManager.Instance.OpenWindow<HeroReturnStarUpChangeWin>();
+        });
+        nameText.text = heroConfig.Name;
+        jobImg.SetSprite(HeroUIManager.Instance.GetJobIconName(heroConfig.Class));
+
+
+        heroNameText.text = heroConfig.Name;
+        manager.SetGradientTextColor(heroNameText, artConfig.HeroNameColor);
+
+        heroImage.SetSprite(StringUtility.Concat("HeroReturnStarUpHero_", heroID.ToString()));
+        heroImage.SetNativeSize();
+
+        CreateScroller(config, heroConfig);
+    }
+
+    private void CreateScroller(ActHeroAppearConfig appearConfig, HeroConfig heroConfig)
+    {
+        if (appearConfig == null || heroConfig == null) return;
+        int starGiftTempID = appearConfig.StarGiftTempID;
+        var list = ActHeroAppearStarConfig.GetHeroReturnAwardIndexSortList(starGiftTempID);
+        if (list == null) return;
+
+        scroller.Refresh();
+        for (int i = 0; i < list.Count; i++)
+        {
+            var awardIndex = list[i];
+
+            var config = ActHeroAppearStarConfig.GetConfig(starGiftTempID, awardIndex);
+            if (config == null) continue;
+
+            CellInfo cellInfo = new()
+            {
+                infoInt1 = heroConfig.HeroID,
+                infoInt2 = i == 0 ? 1 : 0,
+                infoInt3 = i == list.Count - 1 ? 1 : 0
+            };
+            scroller.AddCell(ScrollerDataType.Header, config.ID, cellInfo);
+        }
+        scroller.Restart();
+        scroller.JumpIndex(manager.GetStarUpJumpIndex(starGiftTempID));
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnStarUpWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnStarUpWin.cs.meta
index 862a125..8b82deb 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnStarUpWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: dae38759f25f7eb4ab53165ca393cd2e
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/HeroReturn/HeroReturnWin.cs b/Main/System/HeroReturn/HeroReturnWin.cs
new file mode 100644
index 0000000..19c9f61
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnWin.cs
@@ -0,0 +1,265 @@
+using System;
+using UnityEngine;
+using UnityEngine.UI;
+using DG.Tweening;
+
+public class HeroReturnWin : UIBase
+{
+    [SerializeField] RectTransform activeRect;
+    [SerializeField] RectTransform moveRect;
+    [SerializeField] RectTransform startRect;
+    [SerializeField] RectTransform endRect;
+
+    [SerializeField] ImageEx bgImage;
+    [SerializeField] ImageEx titleImage;
+    [SerializeField] TextEx timeText;
+    [SerializeField] ButtonEx animationButton;
+    [SerializeField] ButtonEx checkInButton; // 绛惧埌璧犵ぜ
+    [SerializeField] RedpointBehaviour checkInRedpoint;
+    [SerializeField] ButtonEx starUpButton; // 鍗囨槦璁″垝
+    [SerializeField] RedpointBehaviour starUpRedpoint;
+    [SerializeField] ButtonEx shopButton; // 鍏戞崲鍟嗗簵
+    [SerializeField] RedpointBehaviour shopRedpoint;
+    [SerializeField] ImageEx skinImage;
+    [SerializeField] ButtonEx skinButton; // 鏃惰鐗瑰崠
+    [SerializeField] ButtonEx giftButton; // 鐨囨潈绀煎寘
+    [SerializeField] RedpointBehaviour giftRedpoint;
+    [SerializeField] ButtonEx callButton; // 鐨囨潈鎷涘嫙
+    [SerializeField] UIHeroController uiHeroController;
+    [SerializeField] UIHeroController lhController;
+    [SerializeField] Image callRedImage;
+    [SerializeField] ButtonEx closeButton;
+    [SerializeField] float modleSize = 0.8f;
+
+    // 杞挱鐩稿叧
+    private const float CarouselInterval = 5f;       // 杞挱闂撮殧5绉�
+    private const float FadeDuration = 0.4f;          // 娓愬彉鏃堕暱
+    private int[] heroIdList;                         // 姝﹀皢ID鍒楄〃
+    private int currentHeroIndex;                      // 褰撳墠姝﹀皢绱㈠紩
+    private bool isCarouselActive;                    // 鏄惁姝e湪杞挱
+    private Tween carouselTween;                       // 杞挱娣″叆娣″嚭tween
+    private float carouselTimer;                       // 杞挱璁℃椂鍣�
+
+    HeroReturnManager manager => HeroReturnManager.Instance;
+
+    protected override void InitComponent()
+    {
+        closeButton.SetListener(() => UIManager.Instance.CloseWindow<HeroReturnWin>());
+        checkInButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnCheckInWin>());
+        starUpButton.SetListener(() =>
+        {
+
+            if (manager.IsLockStarHero(manager.GetOperationHeroAppearInfo()))
+            {
+                UIManager.Instance.OpenWindow<HeroReturnStarUpWin>();
+                return;
+            }
+
+            if (!manager.LoadStarUpChooseHeroStateKey(manager.GetOperationHeroAppearInfo()))
+            {
+                UIManager.Instance.OpenWindow<HeroReturnStarUpChangeWin>();
+                return;
+            }
+            UIManager.Instance.OpenWindow<HeroReturnStarUpWin>();
+        });
+        shopButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnShopWin>());
+        skinButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnSkinWin>());
+        giftButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnGiftWin>());
+        callButton.SetListener(() => UIManager.Instance.OpenWindow<HeroReturnCallWin>());
+    }
+
+    protected override void OnPreOpen()
+    {
+        InitRedpoint();
+
+        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
+        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent;
+        StoreModel.Instance.RefreshBuyShopLimitEvent += Display;
+        manager.OnUpdateHeroAppearPlayerInfoEvent += OnUpdateHeroAppearPlayerInfoEvent;
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        StopCarousel();
+        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
+        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent;
+        StoreModel.Instance.RefreshBuyShopLimitEvent -= Display;
+        manager.OnUpdateHeroAppearPlayerInfoEvent -= OnUpdateHeroAppearPlayerInfoEvent;
+    }
+
+    private void OnUpdateHeroAppearPlayerInfoEvent()
+    {
+        Display();
+    }
+
+    private void OnRechargeCountEvent(int obj)
+    {
+        Display();
+    }
+
+    public void InitRedpoint()
+    {
+        checkInRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.CheckIn);
+        starUpRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.StarUp);
+        shopRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.Shop);
+        giftRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.Gift);
+    }
+
+    private void Display()
+    {
+        var act = manager.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null || config.ActHeroIDList.IsNullOrEmpty()) return;
+
+        // 鑾峰彇姝﹀皢鍒楄〃
+        heroIdList = config.ActHeroIDList;
+        currentHeroIndex = 0;
+
+        // 濡傛灉鍙湁涓�涓灏嗭紝涓嶈疆鎾紝鐩存帴鏄剧ず
+        if (heroIdList.Length <= 1)
+        {
+            StopCarousel();
+            DisplayHero(heroIdList[0], false);
+        }
+        else
+        {
+            // 澶氫釜姝﹀皢锛屽紑鍚疆鎾�
+            carouselTimer = 0f;
+            DisplayHero(heroIdList[currentHeroIndex], false);
+            StartCarousel();
+        }
+
+        callRedImage.SetActive(!manager.IsShopVisitedToday || manager.HasGiftCanHave());
+        OnSecondEvent();
+    }
+
+    private void LateUpdate()
+    {
+        if (!isCarouselActive) return;
+        if (heroIdList == null || heroIdList.Length <= 1) return;
+
+        // 妫�鏌ユ槸鍚﹀瓨鍦ㄦ洿楂樺眰绾х殑绐楀彛锛屽鏋滄湁鍒欎笉鎾斁杞挱
+        if (UIManager.Instance.ExistAnySameLevelWinHigherSortingOrder(uiLayer, uiName))
+        {
+            return;
+        }
+
+        carouselTimer += Time.deltaTime;
+        if (carouselTimer >= CarouselInterval)
+        {
+            carouselTimer = 0f;
+            // 鍒囨崲鍒颁笅涓�涓灏�
+            currentHeroIndex = (currentHeroIndex + 1) % heroIdList.Length;
+            int nextHeroID = heroIdList[currentHeroIndex];
+            // 甯﹀姩鐢诲垏鎹�
+            DisplayHero(nextHeroID, true);
+        }
+    }
+
+    /// <summary>
+    /// 鏄剧ず鎸囧畾姝﹀皢鐨勮儗鏅拰绔嬬粯
+    /// </summary>
+    private void DisplayHero(int heroID, bool withAnimation)
+    {
+        var artConfig = ActHeroReturnArtConfig.Get(heroID);
+        if (artConfig == null) return;
+
+        int skinID = manager.GetDefaultSkinID(heroID);
+        var skinConfig = HeroSkinConfig.Get(skinID);
+        if (skinConfig == null) return;
+
+        int mainSkinID = artConfig.MainSkinID;
+
+        if (withAnimation)
+        {
+            carouselTween?.Kill();
+
+            Sequence seq = DOTween.Sequence();
+            seq.Append(bgImage.DOFade(0.7f, FadeDuration));
+
+            CanvasGroup lhCanvasGroup = lhController.GetComponent<CanvasGroup>();
+            if (lhCanvasGroup == null)
+            {
+                lhCanvasGroup = lhController.gameObject.AddComponent<CanvasGroup>();
+            }
+            seq.Join(lhCanvasGroup.DOFade(0f, FadeDuration));
+
+            seq.OnComplete(() =>
+            {
+                UpdateHeroDisplay(heroID, skinID, artConfig, mainSkinID);
+                // 娣″叆
+                bgImage.DOFade(1f, FadeDuration);
+                lhCanvasGroup.DOFade(1f, FadeDuration);
+            });
+
+            carouselTween = seq;
+        }
+        else
+        {
+            UpdateHeroDisplay(heroID, skinID, artConfig, mainSkinID);
+            CanvasGroup lhCanvasGroup = lhController.GetComponent<CanvasGroup>();
+            if (lhCanvasGroup != null)
+            {
+                lhCanvasGroup.alpha = 1f;
+            }
+        }
+    }
+
+    /// <summary>
+    /// 鏇存柊姝﹀皢鏄剧ず璧勬簮
+    /// </summary>
+    private void UpdateHeroDisplay(int heroID, int skinID, ActHeroReturnArtConfig artConfig, int mainSkinID)
+    {
+        int chosenHeroSkinID = manager.GetDefaultSkinID(
+            manager.LoadCallChooseHeroStateKey(manager.GetOperationHeroAppearInfo()) ?
+            manager.GetCurrentDisplayCallHeroId() :
+            manager.GetFirstHeroId());
+        uiHeroController.Create(chosenHeroSkinID, modleSize);
+
+        uiHeroController.transform.localScale = new Vector3(-modleSize, modleSize, modleSize);
+        lhController.Create(skinID, 1, motionName: "", isLh: true);
+
+        // 鏇存柊鑳屾櫙
+        bgImage.SetSprite(StringUtility.Concat("HeroReturnMainBG_", heroID.ToString()));
+        bgImage.SetNativeSize();
+
+        // 鏇存柊鏍囬
+        titleImage.SetSprite(StringUtility.Concat("HeroReturnMainTitle_", heroID.ToString()));
+        titleImage.SetNativeSize();
+
+        // 鏇存柊鐨偆鍥剧墖
+        int firstHeroID = manager.GetFirstHeroId();
+        var firstHeroIDArtConfig = ActHeroReturnArtConfig.Get(firstHeroID);
+        if (firstHeroIDArtConfig == null) return;
+        skinImage.SetSprite(StringUtility.Concat("HeroReturnSkinEnterBG_", firstHeroIDArtConfig.MainSkinID.ToString()));
+    }
+
+    /// <summary>
+    /// 寮�濮嬭疆鎾�
+    /// </summary>
+    private void StartCarousel()
+    {
+        if (isCarouselActive) return;
+        isCarouselActive = true;
+        carouselTimer = 0f;
+    }
+
+    /// <summary>
+    /// 鍋滄杞挱
+    /// </summary>
+    private void StopCarousel()
+    {
+        isCarouselActive = false;
+        carouselTimer = 0f;
+        carouselTween?.Kill();
+        carouselTween = null;
+    }
+
+    private void OnSecondEvent()
+    {
+        manager.GetActTimeStr(timeText);
+    }
+}
diff --git a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta b/Main/System/HeroReturn/HeroReturnWin.cs.meta
similarity index 83%
copy from Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
copy to Main/System/HeroReturn/HeroReturnWin.cs.meta
index 862a125..96415d9 100644
--- a/Main/Config/Configs/ActHeroAppearSkinArtConfig.cs.meta
+++ b/Main/System/HeroReturn/HeroReturnWin.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 1eaa4cc2eb8e0c84eb8519d6b09adf67
+guid: 264e7ec58915d6243902eadabc46eee9
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/Main/System/Language/Language.cs b/Main/System/Language/Language.cs
index efc781f..23549e6 100644
--- a/Main/System/Language/Language.cs
+++ b/Main/System/Language/Language.cs
@@ -37,6 +37,10 @@
     public static void InitDefaultLanguage()
     {
         //鍒濆鍖�, 璇ヨ〃鏄殢鍖呭畨瑁呯殑濡傛灉鐑洿闇�瑕佷簩娆℃墠鐢熸晥
+        if (!InitialFunctionConfig.HasKey("LanguageEx"))
+        {
+            return;
+        }
         var config = InitialFunctionConfig.Get("LanguageEx");
         if (config.Numerical1 == null || config.Numerical2 == null || config.Numerical3 == null)
         {
diff --git a/Main/System/Login/ServerListCenter.cs b/Main/System/Login/ServerListCenter.cs
index 57fff87..3eabde4 100644
--- a/Main/System/Login/ServerListCenter.cs
+++ b/Main/System/Login/ServerListCenter.cs
@@ -91,6 +91,7 @@
     //浠庢湁鏁版嵁鐨勬湇鍔″櫒鍒楄〃 鎴栬�� 鎬诲垪琛ㄨ幏鍙�
     public ServerData GetServerData(int _id)
     {
+        //鍘嗗彶鐧诲綍鍒楄〃 鍙兘瀛樺湪涓嶅瓨鍦ㄧ殑鏈嶅姟鍣�
         if (serverInfoPlayer != null && serverInfoPlayer.player != null && serverInfoPlayer.player.group_list != null)
         {
             var serverGroup = serverInfoPlayer.player;
@@ -146,28 +147,35 @@
     //浠庢�绘湇鍔″櫒鍒楄〃鑾峰彇
     public ServerData GetServerDataEx(int _id)
     {
-        if (serverInfoCommon == null)
+        if (serverInfoCommon != null && serverInfoCommon.common != null)
         {
-            return default(ServerData);
-        }
-        else
-        {
-            if (serverInfoCommon.common != null)
+            for (int i = 0; i < serverInfoCommon.common.Length; i++)
             {
-                for (int i = 0; i < serverInfoCommon.common.Length; i++)
+                var group = serverInfoCommon.common[i];
+                for (int j = 0; j < group.group_list.Length; j++)
                 {
-                    var group = serverInfoCommon.common[i];
-                    for (int j = 0; j < group.group_list.Length; j++)
+                    var serverData = group.group_list[j];
+                    if (serverData.region_flag == _id)
                     {
-                        var serverData = group.group_list[j];
-                        if (serverData.region_flag == _id)
-                        {
-                            return serverData;
-                        }
+                        return serverData;
                     }
                 }
             }
         }
+        
+        //浠庣櫧鍚嶅崟鐨勬湇鍔″櫒琛ㄤ腑鏌ユ壘锛堟祴璇曠敤锛�
+        if (serverInfoPlayer != null && serverInfoPlayer.gametest != null && serverInfoPlayer.gametest.group_list != null)
+        {
+            var serverGroup = serverInfoPlayer.gametest;
+            for (int i = 0; i < serverGroup.group_list.Length; i++)
+            {
+                var serverData = serverGroup.group_list[i];
+                if (serverData.region_flag == _id)
+                {
+                    return serverData;
+                }
+            }
+        }
 
         return default(ServerData);
     }
diff --git a/Main/System/Main/HomeWin.cs b/Main/System/Main/HomeWin.cs
index 45cd75c..50b0424 100644
--- a/Main/System/Main/HomeWin.cs
+++ b/Main/System/Main/HomeWin.cs
@@ -73,6 +73,7 @@
     [SerializeField] Button osMinggeBtn;
     [SerializeField] TimeRushCell timeRushCell;
     [SerializeField] HeroDebutCell heroDebutCell;
+    [SerializeField] HeroReturnCell heroReturnCell;
 
     //鍧愰獞
     [SerializeField] Image horseBGImg;
@@ -296,6 +297,7 @@
 
         DisplayTimeRush();
         DisplayHeroDebut();
+        DisplayHeroReturn();
         DelayPlayMusic().Forget();
 
     }
@@ -336,6 +338,10 @@
         {
             DisplayHeroDebut();
         }
+        else if (type == OperationType.HeroReturn)
+        {
+            DisplayHeroReturn();
+        }
 
     }
 
@@ -343,6 +349,7 @@
     {
         DisplayTimeRush();
         DisplayHeroDebut();
+        DisplayHeroReturn();
     }
 
     private void OnShowGiftIdListAddEvent()
@@ -840,8 +847,8 @@
             DisplayHorse();
         }
         else if (funcId == (int)FuncOpenEnum.OSMainLevl || funcId == (int)FuncOpenEnum.OSHeroCall
-        || funcId == (int)FuncOpenEnum.OSGala|| funcId == (int)FuncOpenEnum.OSHeroTrain
-        || funcId == (int)FuncOpenEnum.OSBeautyMM  || funcId == (int)FuncOpenEnum.OSMingge)
+        || funcId == (int)FuncOpenEnum.OSGala || funcId == (int)FuncOpenEnum.OSHeroTrain
+        || funcId == (int)FuncOpenEnum.OSBeautyMM || funcId == (int)FuncOpenEnum.OSMingge)
         {
             DisplayOSActivity();
         }
@@ -860,6 +867,10 @@
         else if (funcId == (int)FuncOpenEnum.HeroDebut)
         {
             DisplayHeroDebut();
+        }
+        else if (funcId == (int)FuncOpenEnum.HeroReturn)
+        {
+            DisplayHeroReturn();
         }
     }
 
@@ -937,6 +948,15 @@
             return;
         heroDebutCell.Display();
     }
+
+    void DisplayHeroReturn()
+    {
+        bool isOpen = HeroReturnManager.Instance.IsHeroReturnOpen();
+        heroReturnCell.SetActive(isOpen);
+        if (!isOpen)
+            return;
+        heroReturnCell.Display();
+    }
 }
 
 
diff --git a/Main/System/OpenServerActivity/OperationTimeHepler.cs b/Main/System/OpenServerActivity/OperationTimeHepler.cs
index b4ef7bc..18a98ec 100644
--- a/Main/System/OpenServerActivity/OperationTimeHepler.cs
+++ b/Main/System/OpenServerActivity/OperationTimeHepler.cs
@@ -469,9 +469,9 @@
             case 10:
                 opreationType = OperationType.HeroDebut;
                 break;
-            // case 11:
-            //     opreationType = OperationType.HeroBack;
-            //     break;
+            case 11:
+                opreationType = OperationType.HeroReturn;
+                break;
         }
 
         if (string.IsNullOrEmpty(package.StartDate) || string.IsNullOrEmpty(package.EndtDate))
@@ -1084,5 +1084,6 @@
 {
     TimeRush = 1,  //鏃ユ湡鍨嬫椿鍔� - 杞洖娈�
     HeroDebut = 2,  //鏃ユ湡鍨嬫椿鍔� - 姝﹀皢鐧诲満
+    HeroReturn = 3, //鏃ユ湡鍨嬫椿鍔� - 姝﹀皢杩斿満
     max,
 }
\ No newline at end of file
diff --git a/Main/System/Redpoint/MainRedDot.cs b/Main/System/Redpoint/MainRedDot.cs
index 645f78e..2365d68 100644
--- a/Main/System/Redpoint/MainRedDot.cs
+++ b/Main/System/Redpoint/MainRedDot.cs
@@ -155,6 +155,7 @@
     public const int RedPoint_OSHeroTrain = 481;
     public const int RedPoint_OSBeautyMM = 482;
     public const int RedPoint_OSMingge = 483;
+    public const int HeroReturnRepoint = 484; //姝﹀皢杩斿満
     public void Register()
     {
 
diff --git a/Main/System/UIBase/UIJumpManager.cs b/Main/System/UIBase/UIJumpManager.cs
index 09c5160..4ee0d2d 100644
--- a/Main/System/UIBase/UIJumpManager.cs
+++ b/Main/System/UIBase/UIJumpManager.cs
@@ -62,10 +62,9 @@
 				}
 			}
 		}
-		else if (config.WinName == "HeroDebutCallWin" ||
-				config.WinName == "HeroDebutSkinWin" ||
-				config.WinName == "HeroDebutCheckInWin" ||
-				config.WinName == "HeroDebutGiftWin" ||
+		//姝﹀皢鐧诲満鐩稿叧
+		else if (config.WinName == "HeroDebutCallWin" || config.WinName == "HeroDebutSkinWin" ||
+				config.WinName == "HeroDebutCheckInWin" || config.WinName == "HeroDebutGiftWin" ||
 				config.WinName == "HeroDebutShopWin")
 		{
 			var heroDebutAct = HeroDebutManager.Instance.GetOperationHeroAppearInfo();
@@ -97,6 +96,40 @@
 				UIManager.Instance.OpenWindowAsync(config.WinName).Forget();
 			}
 		}
+		//姝﹀皢杩斿満鐩稿叧
+		else if (config.WinName == "HeroReturnCallWin" || config.WinName == "HeroReturnSkinWin" ||
+				config.WinName == "HeroReturnCheckInWin" || config.WinName == "HeroReturnGiftWin" ||
+				config.WinName == "HeroReturnShopWin")
+		{
+			var heroDebutAct = HeroReturnManager.Instance.GetOperationHeroAppearInfo();
+			if (heroDebutAct == null)
+			{
+				SysNotifyMgr.Instance.ShowTip("ActivityNoOpen");
+				return;
+			}
+			var actHeroAppearConfig = ActHeroAppearConfig.Get(heroDebutAct.CfgID);
+			if (actHeroAppearConfig == null)
+			{
+				SysNotifyMgr.Instance.ShowTip("ActivityNoOpen");
+				return;
+			}
+
+			// 鐨偆鍟嗗簵闇�瑕佸垽鏂墿鍝両D
+			if (config.WinName == "HeroReturnSkinWin")
+			{
+				if (!HeroReturnManager.Instance.HasItemInSkinCTGIDList(heroDebutAct.CfgID, int.Parse(config.Extra)))
+				{
+					SysNotifyMgr.Instance.ShowTip("ActivityNoOpen");
+					return;
+				}
+			}
+
+			if (UIManager.Instance.IsOpened(config.WinName))
+			{
+				UIManager.Instance.CloseWindow(config.WinName);
+				UIManager.Instance.OpenWindow(config.WinName);
+			}
+		}
 
 		if (!UIManager.Instance.IsOpened(config.WinName))
 		{
diff --git a/Main/Utility/EnumHelper.cs b/Main/Utility/EnumHelper.cs
index af301c5..4096fc4 100644
--- a/Main/Utility/EnumHelper.cs
+++ b/Main/Utility/EnumHelper.cs
@@ -858,6 +858,7 @@
     OSMingge = 61, //寮�鏈嶅懡鏍煎煿鍏绘娲诲姩
     Qunying = 62, //缇よ嫳姒�
     HeroDebut = 63,//姝﹀皢鐧诲満
+    HeroReturn = 64,  //姝﹀皢杩斿満
 }
 
 
@@ -1813,6 +1814,7 @@
 {
     TimeRushAct = 200,  //杞洖娈�(姝﹀皢鍐插埡)
     HeroDebutAct = 201,  //鑻遍泟鐧诲満娲诲姩
+    HeroReturnAct = 202,  //鑻遍泟杩斿満娲诲姩
 }
 
 //浠欑帀璐拱鐨勪簩娆$‘璁ゆ绫诲瀷

--
Gitblit v1.8.0