From 597d72e828d880b475e2441dcf0731dfc3417126 Mon Sep 17 00:00:00 2001
From: lcy <1459594991@qq.com>
Date: 星期三, 10 十二月 2025 16:26:47 +0800
Subject: [PATCH] 385 战斗系统 战斗结算详情界面

---
 Main/System/BattleDetail/BattleDetailHeroInfoItem.cs      |  107 ++++++++++
 Main/System/Settlement/BattleFailWin.cs                   |   11 
 Main/System/Arena/ArenaBattleVictoryWin.cs                |   76 +------
 Main/System/Arena/ArenaBattleFailWin.cs                   |    8 
 Main/System/BattleDetail/BattleDetailHeroInfoItem.cs.meta |   11 +
 Main/System/BattleDetail/BattleDetailWin.cs.meta          |   11 +
 Main/System/BattleDetail/BattleDetailWin.cs               |  124 ++++++++++++
 Main/System/Settlement/BoneBattleVictoryWin.cs            |   12 +
 Main/System/Settlement/BattleSettlementManager.cs         |  150 +++++++++++++++
 Main/System/Settlement/TianziBillboradVictoryWin.cs       |   10 +
 Main/System/BattleDetail.meta                             |    8 
 Main/System/Settlement/BoneBattleFailWin.cs               |   10 
 Main/System/Settlement/BattleVictoryWin.cs                |   12 
 13 files changed, 470 insertions(+), 80 deletions(-)

diff --git a/Main/System/Arena/ArenaBattleFailWin.cs b/Main/System/Arena/ArenaBattleFailWin.cs
index f0dd663..c728f54 100644
--- a/Main/System/Arena/ArenaBattleFailWin.cs
+++ b/Main/System/Arena/ArenaBattleFailWin.cs
@@ -12,13 +12,17 @@
     [SerializeField] TextEx txtEnemyName;
     [SerializeField] TextEx txtMyScore;
     [SerializeField] TextEx txtEnemyScore;
-     [SerializeField] TextEx txtFuncName;
+    [SerializeField] TextEx txtFuncName;
     [SerializeField] ScrollerController scroller;
+    [SerializeField] ButtonEx detailBtn;
     JsonData jsonData;
     string battleName = BattleConst.ArenaBattleField;
     protected override void InitComponent()
     {
-
+        detailBtn.SetListener(() =>
+        {
+            BattleSettlementManager.Instance.OpenBattleDetailWin(battleName);
+        });
     }
 
     protected override void OnPreOpen()
diff --git a/Main/System/Arena/ArenaBattleVictoryWin.cs b/Main/System/Arena/ArenaBattleVictoryWin.cs
index 443f8c9..092b65c 100644
--- a/Main/System/Arena/ArenaBattleVictoryWin.cs
+++ b/Main/System/Arena/ArenaBattleVictoryWin.cs
@@ -3,71 +3,6 @@
 using LitJson;
 using UnityEngine;
 
-// 銆愭垬鏂楃粨绠椼��
-// 褰撴敹鍒� // B4 20 鍥炲悎鍒舵垬鏂楃姸鎬� #tagMCTurnFightState    State 涓� 4-缁撶畻锛屾椂锛屼唬琛ㄦ湰鍦烘垬鏂楀凡缁撴潫骞剁粨绠�
-// char Msg[Len]; //size = Len   Msg淇℃伅涓�
-// {"winFaction":鑾疯儨闃佃惀, "statInfo":缁熻淇℃伅, 鈥渋temInfo鈥�:[濂栧姳鐗╁搧淇℃伅鍒楄〃]}
-// 鑾疯儨闃佃惀:   涓�鑸负1鎴栬��2锛屽綋鐜╁鍙戣捣鐨勬垬鏂楁椂锛屽鏋滆幏鑳滈樀钀ヤ笉绛変簬1浠h〃鐜╁澶辫触浜�
-// 缁熻淇℃伅锛� 鏍煎紡  {"闃佃惀缂栧彿":{"闃靛缂栧彿":{"绔欎綅缂栧彿":{璇ユ灏嗙粺璁′俊鎭瓧鍏竲, ...}, ...}, ...}
-// 闃佃惀缂栧彿锛� 涓�鑸椂1鎴�2锛� 瀵瑰簲 B424 鍚屾涓嬪幓鐨勯樀钀�
-// 闃靛缂栧彿锛� 闅跺睘浜庢煇涓樀钀ョ殑闃靛缂栧彿锛屼竴鑸槸浠�1寮�濮嬶紝涓�涓樀钀ュ湪澶歏澶氱殑鎯呭喌涓嬪彲浠ユ湁澶氫釜闃靛
-// 绔欎綅缂栧彿锛� 鏌愪釜闃靛涓灏嗘垬鏂楀疄渚嬬殑绔欎綅缂栧彿锛屼竴鑸粠1寮�濮嬶紝浠h〃绔欎綅1
-// 姝﹀皢缁熻淇℃伅瀛楀吀锛� 鏍煎紡锛� {"ObjID":瀹炰緥ID, "HeroID":鐜╁闃靛姝﹀皢ID, "NPCID":npc琛↖D, "AtkHurt":鎬昏緭鍑�, "DefHurt":鎬绘壙浼�, "CureHP":鎬绘不鐤梷
-
-// 澶勭悊鎴樻枟缁撴潫閫昏緫
-// IsBattleFinish = true;
-// 缁撶畻閫昏緫
-
-// {
-// "itemInfo": [],
-// "winFaction": 1,//鑾疯儨闃佃惀:   涓�鑸负1鎴栬��2锛屽綋鐜╁鍙戣捣鐨勬垬鏂楁椂锛屽鏋滆幏鑳滈樀钀ヤ笉绛変簬1浠h〃鐜╁澶辫触浜�
-// "statInfo": {
-//     "1": {
-//     "1": {
-//         "5": {
-//         "NPCID": 0,
-//         "DefHurt": 633,
-//         "CureHP": 0,
-//         "AtkHurt": 169247,
-//         "ObjID": 1,
-//         "HeroID": 510006
-//         }
-//     }
-//     },
-//     "2": {
-//     "1": {
-//         "2": {
-//         "NPCID": 10101001,
-//         "DefHurt": 169246,
-//         "CureHP": 143096,
-//         "AtkHurt": 999952,
-//         "ObjID": 2,
-//         "HeroID": 0
-//         },
-//         "4": {
-//         "NPCID": 10101001,
-//         "DefHurt": 0,
-//         "CureHP": 0,
-//         "AtkHurt": 0,
-//         "ObjID": 3,
-//         "HeroID": 0
-//         },
-//         "6": {
-//         "NPCID": 10101001,
-//         "DefHurt": 1,
-//         "CureHP": 0,
-//         "AtkHurt": 0,
-//         "ObjID": 4,
-//         "HeroID": 0
-//         }
-//     }
-//     }
-// }
-// }
-
-//"Msg":{"itemInfo":[{"ItemID":5,"Count":2},{"ItemID":3,"Count":40}],"winFaction":1,"statInfo":{"1":{"1":{"1":{"NPCID":0,"DefHurt":727,"CureHP":0,"AtkHurt":1891,"ObjID":1,"HeroID":530004},"3":{"NPCID":0,"DefHurt":483,"CureHP":1511,"AtkHurt":782,"ObjID":6,"HeroID":520001},"2":{"NPCID":0,"DefHurt":953,"CureHP":0,"AtkHurt":1712,"ObjID":5,"HeroID":510003}}},"2":{"1":{"1":{"NPCID":10101091,"DefHurt":638,"CureHP":0,"AtkHurt":140,"ObjID":2,"HeroID":610001},"3":{"NPCID":10101092,"DefHurt":625,"CureHP":0,"AtkHurt":126,"ObjID":3,"HeroID":610001},"5":{"NPCID":10101093,"DefHurt":3122,"CureHP":0,"AtkHurt":1897,"ObjID":4,"HeroID":510003}}}}}
-
-//鎴樺満缁撶畻鐣岄潰锛屽瓨鍦ㄥ涓殑鎯呭喌
 public class ArenaBattleVictoryWin : UIBase
 {
     [SerializeField] AvatarCell myAvatarCell;
@@ -78,8 +13,18 @@
     [SerializeField] TextEx txtEnemyScore;
     [SerializeField] TextEx txtFuncName;
     [SerializeField] ScrollerController scroller;
+    [SerializeField] ButtonEx detailBtn;
     JsonData jsonData;
     string battleName = BattleConst.ArenaBattleField;
+    
+    protected override void InitComponent()
+    {
+        detailBtn.SetListener(() =>
+        {
+            BattleSettlementManager.Instance.OpenBattleDetailWin(battleName);
+        });
+    }
+
     protected override void OnPreOpen()
     {
         scroller.OnRefreshCell += OnRefreshCell;
@@ -92,7 +37,6 @@
         Display();
         CreateScroller();
     }
-
 
     protected override void OnPreClose()
     {
diff --git a/Main/System/BattleDetail.meta b/Main/System/BattleDetail.meta
new file mode 100644
index 0000000..1eed7ed
--- /dev/null
+++ b/Main/System/BattleDetail.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4bbbbe8703e9deb48b7dac26a1186b93
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/BattleDetail/BattleDetailHeroInfoItem.cs b/Main/System/BattleDetail/BattleDetailHeroInfoItem.cs
new file mode 100644
index 0000000..5e856ee
--- /dev/null
+++ b/Main/System/BattleDetail/BattleDetailHeroInfoItem.cs
@@ -0,0 +1,107 @@
+
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class BattleDetailHeroInfoItem : MonoBehaviour
+{
+    [SerializeField] ImageEx imgHeadBg;
+    [SerializeField] ImageEx imgHead;
+    [SerializeField] TextEx txtLV;
+    [SerializeField] ImageEx imgCountry;
+    [SerializeField] List<Image> starImgList;
+    [SerializeField] ImageEx imgMask;
+    [SerializeField] TextEx txtHeroName;
+    [SerializeField] ImageEx imgMVP;
+
+    [SerializeField] ImageEx imgAtkHurt;
+    [SerializeField] TextEx txtAtkHurt;
+
+    [SerializeField] ImageEx imgDefHurt;
+    [SerializeField] TextEx txtDefHurt;
+
+    [SerializeField] ImageEx imgCureHP;
+    [SerializeField] TextEx txtCureHP;
+
+    public void Display(BattleDetailHeroInfoItemData data)
+    {
+        if (data == null || data.info == null)
+            return;
+        BattleDetailHeroInfo info = data.info;
+
+        int heroID = info.HeroID;
+        if (!HeroConfig.HasKey(heroID))
+            return;
+        HeroConfig heroConfig = HeroConfig.Get(heroID);
+
+
+        int skinID = info.Skin;
+        if (!HeroSkinConfig.HasKey(skinID))
+            return;
+        HeroSkinConfig skinConfig = HeroSkinConfig.Get(skinID);
+
+        bool isDead = info.Dead == 1;
+        imgMask.SetActive(isDead);
+        imgMVP.SetActive(data.index == data.mvpIndex);
+
+        imgHeadBg.SetSprite("heroheadBG" + heroConfig.Quality);
+
+        var sprite = UILoader.LoadSprite("HeroHead", skinConfig.SquareIcon);
+        if (sprite == null)
+        {
+            imgHead.SetSprite("herohead_default");
+        }
+        else
+        {
+            imgHead.overrideSprite = sprite;
+        }
+
+        imgCountry.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
+        txtHeroName.text = heroConfig.Name;
+        txtLV.text = StringUtility.Concat(Language.Get("L1094"), info.LV.ToString());
+        DisplayStars(info.Star);
+
+        DisplaySlider(imgAtkHurt, txtAtkHurt, info.AtkHurt, data.maxAtk);
+        DisplaySlider(imgDefHurt, txtDefHurt, info.DefHurt, data.maxDef);
+        DisplaySlider(imgCureHP, txtCureHP, info.CureHP, data.maxCure);
+    }
+
+
+
+    private void DisplaySlider(ImageEx imgSlider, TextEx txtSlider, ulong value, ulong maxValue)
+    {
+        if (maxValue > 0)
+        {
+            ulong safeValue = value > maxValue ? maxValue : value;
+            double ratioDouble = (double)safeValue / maxValue;
+            imgSlider.fillAmount = (float)ratioDouble;
+        }
+        else
+        {
+            imgSlider.fillAmount = 0.0f;
+        }
+        txtSlider.text = UIHelper.ReplaceLargeNum(value);
+    }
+
+    void DisplayStars(int starCnt)
+    {
+        for (int i = 0; i < starImgList.Count; i++)
+        {
+            if (starCnt == 0 && i == 0)
+            {
+                // 鏃犳槦绾� 鐗规畩澶勭悊
+                starImgList[i].SetActive(true);
+                starImgList[i].SetSprite("herostar" + starCnt);
+            }
+            else if ((starCnt - 1) % starImgList.Count >= i)
+            {
+                starImgList[i].SetActive(true);
+                starImgList[i].SetSprite("herostar" + (((starCnt - 1) / starImgList.Count) + 1) * starImgList.Count);
+            }
+            else
+            {
+                starImgList[i].SetActive(false);
+            }
+        }
+    }
+}
diff --git a/Main/System/BattleDetail/BattleDetailHeroInfoItem.cs.meta b/Main/System/BattleDetail/BattleDetailHeroInfoItem.cs.meta
new file mode 100644
index 0000000..afe3f16
--- /dev/null
+++ b/Main/System/BattleDetail/BattleDetailHeroInfoItem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a54f54c7e7fc54c4394cb08bc22034dd
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/BattleDetail/BattleDetailWin.cs b/Main/System/BattleDetail/BattleDetailWin.cs
new file mode 100644
index 0000000..92f1378
--- /dev/null
+++ b/Main/System/BattleDetail/BattleDetailWin.cs
@@ -0,0 +1,124 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class BattleDetailWin : UIBase
+{
+    [SerializeField] TextEx redName;
+    [SerializeField] TextEx blueName;
+    [SerializeField] List<BattleDetailHeroInfoItem> redList = new List<BattleDetailHeroInfoItem>();
+    [SerializeField] List<BattleDetailHeroInfoItem> blueList = new List<BattleDetailHeroInfoItem>();
+    BattleSettlementManager manager { get { return BattleSettlementManager.Instance; } }
+    protected override void OnPreOpen()
+    {
+        Display();
+    }
+
+    public void Display()
+    {
+        bool isMyStart = manager.isMyStartBattleDetail;
+        BattleDetailMsg msg = manager.msg;
+        string battleName = manager.BattleDetailBattleName;
+
+        if (msg == null)
+            return;
+
+        if (isMyStart)
+        {
+            // 鐩墠鐜╁涓诲姩鍙戣捣鐨勯樀瀹逛竴瀹氭槸1锛屽鏂规槸 2, 濡傛灉鏄偅绉嶇郴缁熻嚜鍔ㄦ墦鐨勶紝涓�鑸�1-宸︼紝2-鍙�
+            int myWinFaction = 1;
+            string myName = PlayerDatas.Instance.baseData.PlayerName;
+            string enemyName = manager.GetBattleDetailEnemyNameByMyStart(battleName);
+            if (battleName == BattleConst.TianziBillboradBattleField)
+            {
+                redName.text = myWinFaction == msg.winFaction ? enemyName : myName;
+                blueName.text = myWinFaction == msg.winFaction ? myName : enemyName;
+            }
+            else
+            {
+                redName.text = myWinFaction == msg.winFaction ? myName : enemyName;
+                blueName.text = myWinFaction == msg.winFaction ? enemyName : myName;
+            }
+
+        }
+
+        List<BattleDetailHeroInfo> redBattleDetailHeroInfoList = manager.GetHeroInfo(msg, isMyStart, battleName, true);
+        List<BattleDetailHeroInfo> blueBattleDetailHeroInfoList = manager.GetHeroInfo(msg, isMyStart, battleName, false);
+        DisplayDetail(redList, redBattleDetailHeroInfoList);
+        DisplayDetail(blueList, blueBattleDetailHeroInfoList);
+    }
+
+    public void DisplayDetail(List<BattleDetailHeroInfoItem> teamItemList, List<BattleDetailHeroInfo> infoList)
+    {
+        int mvpIndex = GetMvpIndex(infoList);
+        GetMaxAttr(infoList, out ulong maxAtk, out ulong maxDef, out ulong maxCure);
+
+        for (int i = 0; i < teamItemList.Count; i++)
+        {
+            if (i < infoList.Count)
+            {
+                teamItemList[i].SetActive(true);
+                teamItemList[i].Display(new BattleDetailHeroInfoItemData()
+                {
+                    index = i,
+                    mvpIndex = mvpIndex,
+                    maxAtk = maxAtk,
+                    maxDef = maxDef,
+                    maxCure = maxCure,
+                    info = infoList[i],
+                });
+            }
+            else
+            {
+                teamItemList[i].SetActive(false);
+            }
+        }
+    }
+
+    public int GetMvpIndex(List<BattleDetailHeroInfo> infos)
+    {
+        if (infos.IsNullOrEmpty())
+            return -1;
+        int mvpIndex = -1;
+        ulong mvpScore = 0;
+        for (int i = 0; i < infos.Count; i++)
+        {
+            BattleDetailHeroInfo nowInfo = infos[i];
+            ulong nowValue = nowInfo.AtkHurt + nowInfo.DefHurt + nowInfo.CureHP;
+            if (nowValue > mvpScore)
+            {
+                mvpIndex = i;
+                mvpScore = nowValue;
+            }
+        }
+        return mvpIndex;
+    }
+
+    public void GetMaxAttr(List<BattleDetailHeroInfo> infos, out ulong maxAtk, out ulong maxDef, out ulong maxCure)
+    {
+        maxAtk = 0;
+        maxDef = 0;
+        maxCure = 0;
+        if (infos.IsNullOrEmpty())
+            return;
+
+        for (int i = 0; i < infos.Count; i++)
+        {
+            BattleDetailHeroInfo nowInfo = infos[i];
+            if (nowInfo.AtkHurt > maxAtk)
+                maxAtk = nowInfo.AtkHurt;
+            if (nowInfo.DefHurt > maxDef)
+                maxDef = nowInfo.DefHurt;
+            if (nowInfo.CureHP > maxCure)
+                maxCure = nowInfo.CureHP;
+        }
+    }
+}
+public class BattleDetailHeroInfoItemData
+{
+    public int index;
+    public int mvpIndex;
+    public ulong maxAtk;
+    public ulong maxDef;
+    public ulong maxCure;
+    public BattleDetailHeroInfo info;
+}
\ No newline at end of file
diff --git a/Main/System/BattleDetail/BattleDetailWin.cs.meta b/Main/System/BattleDetail/BattleDetailWin.cs.meta
new file mode 100644
index 0000000..ccc472e
--- /dev/null
+++ b/Main/System/BattleDetail/BattleDetailWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f3d38bd1b83265f4bafa8bb7de20f856
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Settlement/BattleFailWin.cs b/Main/System/Settlement/BattleFailWin.cs
index 0c1a11e..a376208 100644
--- a/Main/System/Settlement/BattleFailWin.cs
+++ b/Main/System/Settlement/BattleFailWin.cs
@@ -1,7 +1,3 @@
-using System;
-using System.Collections.Generic;
-using Cysharp.Threading.Tasks;
-using LitJson;
 using UnityEngine;
 using UnityEngine.UI;
 
@@ -11,7 +7,9 @@
 
     [SerializeField] Button tipEquipBtn;
     [SerializeField] Button tipHeroPosBtn;
+    [SerializeField] ButtonEx detailBtn;
     string battleName = BattleConst.StoryBossBattleField;
+    
     protected override void InitComponent()
     {
         tipEquipBtn.AddListener(() =>
@@ -24,6 +22,11 @@
             CloseWindow();
             UIManager.Instance.OpenWindow<HeroPosWin>();
         });
+
+        detailBtn.SetListener(() =>
+        {
+            BattleSettlementManager.Instance.OpenBattleDetailWin(battleName);
+        });
     }
 
     protected override void OnPreOpen()
diff --git a/Main/System/Settlement/BattleSettlementManager.cs b/Main/System/Settlement/BattleSettlementManager.cs
index d477cf8..a11396b 100644
--- a/Main/System/Settlement/BattleSettlementManager.cs
+++ b/Main/System/Settlement/BattleSettlementManager.cs
@@ -264,7 +264,157 @@
 
     }
 
+    #region 鎴樻枟缁撴灉璇︽儏
+    public BattleDetailMsg msg = new BattleDetailMsg();
+    public string BattleDetailBattleName = string.Empty;
+    public string BattleDetailMyName = string.Empty;
+    public string BattleDetailEnemyName = string.Empty;
+    public bool isMyStartBattleDetail = false;  // 鏄惁鏄垜鏂瑰彂璧风殑鎴樻枟
 
+    // isMyStart 鏄惁鏄垜鏂瑰彂璧风殑鎴樻枟
+    public void OpenBattleDetailWin(string battleName, bool isMyStart = true)
+    {
+        if (UIManager.Instance.IsOpened<BattleDetailWin>())
+            return;
+
+        JsonData battleSettlement = GetBattleSettlement(battleName);
+        if (battleSettlement == null)
+            return;
+
+        msg = ParserBattleDetail(battleSettlement);
+        if (msg == null)
+            return;
+
+        BattleDetailBattleName = battleName;
+        this.isMyStartBattleDetail = isMyStart;
+        UIManager.Instance.OpenWindow<BattleDetailWin>();
+    }
+
+    //鎴樻枟缁撴灉璇︽儏鐣岄潰鑾峰彇 鎴戞柟鍙戣捣鐨勬垬鏂楃殑涓晫鏂瑰悕瀛�
+    public string GetBattleDetailEnemyNameByMyStart(string battleName)
+    {
+        string detailName = string.Empty;
+        BattleField battleField = BattleManager.Instance.GetActiveBattleFieldByName(battleName);
+        if (battleField == null)
+            return detailName;
+
+        switch (battleName)
+        {
+            // 鏁屾柟鍚嶅瓧鏄疊oss鍚嶅瓧
+            case BattleConst.StoryBossBattleField:
+            case BattleConst.BoneBattleField:
+            case BattleConst.TianziBillboradBattleField:
+                BattleObject bossBattleObject = battleField.FindBoss();
+                if (bossBattleObject == null || bossBattleObject.teamHero == null)
+                    return detailName;
+                detailName = bossBattleObject.teamHero.name;
+                break;
+            // 鏁屾柟鍚嶅瓧鏄鏂圭帺瀹跺悕瀛�
+            case BattleConst.ArenaBattleField:
+                if (!ArenaManager.Instance.TryGetPlayerInfo(ArenaManager.Instance.atkPlayerId, out ArenaMatchInfo info) || info == null)
+                    return detailName;
+                detailName = info.PlayerName;
+                break;
+        }
+        return detailName;
+    }
+
+    public BattleDetailMsg ParserBattleDetail(JsonData jsonMsg)
+    {
+        if (jsonMsg == null)
+            return null;
+        try
+        {
+            string jsonStr = jsonMsg.ToJson();
+            BattleDetailMsg result = JsonMapper.ToObject<BattleDetailMsg>(jsonStr);
+            return result;
+        }
+        catch (Exception ex)
+        {
+            Debug.Log("瑙f瀽鎴樻枟鏁版嵁寮傚父: " + ex.Message);
+        }
+        return null;
+    }
+
+    public List<BattleDetailHeroInfo> GetHeroInfo(BattleDetailMsg msg, bool isMyStart, string battleName, bool isWin)
+    {
+        if (msg == null || msg.statInfo.IsNullOrEmpty())
+            return null;
+
+        int winFaction = msg.winFaction;    // 鑾疯儨闃佃惀
+        Dictionary<string, Dictionary<string, BattleDetailHeroInfo>> lineupInfo = new Dictionary<string, Dictionary<string, BattleDetailHeroInfo>>();
+        string statInfoKey = string.Empty;
+
+        if (isMyStart)
+        {
+            // 澶╁瓙鎴樺満鐜╁涓嶄細杈�
+            if (battleName == BattleConst.TianziBillboradBattleField)
+            {
+                statInfoKey = isWin ? msg.statInfo.Keys.FirstOrDefault(key => key != winFaction.ToString()) : winFaction.ToString();
+            }
+            else
+            {
+                statInfoKey = isWin ? winFaction.ToString() : msg.statInfo.Keys.FirstOrDefault(key => key != winFaction.ToString());
+            }
+        }
+
+        if (!msg.statInfo.TryGetValue(statInfoKey, out lineupInfo) || lineupInfo.IsNullOrEmpty())
+            return null;
+        var lineupInfoKeyList = lineupInfo.Keys.ToList();
+        if (lineupInfoKeyList.IsNullOrEmpty())
+            return null;
+
+        // 鐩墠鍙彇绗竴涓樀瀹圭殑淇℃伅
+        string key = lineupInfoKeyList[0];
+        if (!lineupInfo.TryGetValue(key, out var heroInfoDict) || heroInfoDict.IsNullOrEmpty())
+            return null;
+
+        var heroInfoKeyList = heroInfoDict.Keys.ToList();
+        heroInfoKeyList = heroInfoKeyList
+            .OrderBy(key => int.Parse(key)) // 灏嗗瓧绗︿覆閿В鏋愪负鏁存暟鍚庤繘琛屾帓搴�
+            .ToList(); // 灏嗘帓搴忓悗鐨勭粨鏋滆浆鍥� List<string>
+
+        List<BattleDetailHeroInfo> res = new List<BattleDetailHeroInfo>();
+        foreach (var heroInfoKey in heroInfoKeyList)
+        {
+            if (!heroInfoDict.TryGetValue(heroInfoKey, out var heroInfo))
+                continue;
+            res.Add(heroInfo);
+        }
+        return res;
+    }
+
+    #endregion
 
 }
 
+public class BattleDetailMsg
+{
+    public List<BattleDetailRewardItem> itemInfo;
+
+    public int winFaction;
+
+    // 瀵瑰簲 "statInfo"
+    // 缁撴瀯锛�<闃佃惀缂栧彿, <闃靛缂栧彿, <绔欎綅缂栧彿, 姝﹀皢鏁版嵁>>>
+    // 娉ㄦ剰锛欽SON涓殑閿� "1", "2" 鏄瓧绗︿覆锛屾墍浠ュ瓧鍏� Key 鐢� string
+    public Dictionary<string, Dictionary<string, Dictionary<string, BattleDetailHeroInfo>>> statInfo;
+}
+public class BattleDetailHeroInfo
+{
+    public int ObjID;   // 瀹炰緥ID
+    public int HeroID;  // 鐜╁闃靛姝﹀皢ID
+    public int NPCID;   // NPCID
+    public int LV;      // 姝﹀皢绛夌骇
+    public int Star;      // 姝﹀皢鏄熺骇
+    public int Skin;      // 姝﹀皢鐨偆ID
+    public ulong DefHurt; // 鎬绘壙浼�
+    public ulong CureHP;  // 鎬绘不鐤�
+    public ulong AtkHurt; // 鎬昏緭鍑�
+    public int Dead;      // 鏄惁闃典骸
+}
+
+public class BattleDetailRewardItem
+{
+    public int ItemID;
+    public int Count;
+}
\ No newline at end of file
diff --git a/Main/System/Settlement/BattleVictoryWin.cs b/Main/System/Settlement/BattleVictoryWin.cs
index e6b3f8e..fc93fd1 100644
--- a/Main/System/Settlement/BattleVictoryWin.cs
+++ b/Main/System/Settlement/BattleVictoryWin.cs
@@ -1,9 +1,6 @@
-using System;
 using System.Collections.Generic;
 using Cysharp.Threading.Tasks;
-using LitJson;
 using UnityEngine;
-using UnityEngine.UI;
 
 // 銆愭垬鏂楃粨绠椼��
 // 褰撴敹鍒� // B4 20 鍥炲悎鍒舵垬鏂楃姸鎬� #tagMCTurnFightState    State 涓� 4-缁撶畻锛屾椂锛屼唬琛ㄦ湰鍦烘垬鏂楀凡缁撴潫骞剁粨绠�
@@ -74,8 +71,17 @@
 {
 
     [SerializeField] ScrollerController scroller;
+    [SerializeField] ButtonEx detailBtn;
 
     string battleName = BattleConst.StoryBossBattleField;   //缁戞鎴樺満灏变笉閫氱敤浜嗘牴鎹儏鍐典慨鏀�
+    protected override void InitComponent()
+    {
+        detailBtn.SetListener(() =>
+        {
+            BattleSettlementManager.Instance.OpenBattleDetailWin(battleName);
+        });
+    }
+
     protected override void OnPreOpen()
     {
         scroller.OnRefreshCell += OnRefreshCell;
diff --git a/Main/System/Settlement/BoneBattleFailWin.cs b/Main/System/Settlement/BoneBattleFailWin.cs
index 0f2ff50..48ea591 100644
--- a/Main/System/Settlement/BoneBattleFailWin.cs
+++ b/Main/System/Settlement/BoneBattleFailWin.cs
@@ -1,7 +1,3 @@
-using System;
-using System.Collections.Generic;
-using Cysharp.Threading.Tasks;
-using LitJson;
 using UnityEngine;
 using UnityEngine.UI;
 
@@ -11,6 +7,7 @@
     [SerializeField] TextEx txtFuncName;
     [SerializeField] Button tipEquipBtn;
     [SerializeField] Button tipHeroPosBtn;
+    [SerializeField] ButtonEx detailBtn;
     string battleName = BattleConst.BoneBattleField;
     protected override void InitComponent()
     {
@@ -24,6 +21,11 @@
             CloseWindow();
             UIManager.Instance.OpenWindow<HeroPosWin>();
         });
+
+        detailBtn.SetListener(() =>
+        {
+            BattleSettlementManager.Instance.OpenBattleDetailWin(battleName);
+        });
     }
 
     protected override void OnPreOpen()
diff --git a/Main/System/Settlement/BoneBattleVictoryWin.cs b/Main/System/Settlement/BoneBattleVictoryWin.cs
index 4623c16..765321f 100644
--- a/Main/System/Settlement/BoneBattleVictoryWin.cs
+++ b/Main/System/Settlement/BoneBattleVictoryWin.cs
@@ -4,10 +4,20 @@
 
 public class BoneBattleVictoryWin : UIBase
 {
+    [SerializeField] ButtonEx detailBtn;
     [SerializeField] TextEx txtFuncName;
     [SerializeField] ScrollerController scroller;
-
+    
     string battleName = BattleConst.BoneBattleField;
+
+    protected override void InitComponent()
+    {
+        detailBtn.SetListener(() =>
+        {
+            BattleSettlementManager.Instance.OpenBattleDetailWin(battleName);
+        });
+    }
+
     protected override void OnPreOpen()
     {
         scroller.OnRefreshCell += OnRefreshCell;
diff --git a/Main/System/Settlement/TianziBillboradVictoryWin.cs b/Main/System/Settlement/TianziBillboradVictoryWin.cs
index 4d81bd0..a1d154d 100644
--- a/Main/System/Settlement/TianziBillboradVictoryWin.cs
+++ b/Main/System/Settlement/TianziBillboradVictoryWin.cs
@@ -6,8 +6,18 @@
 {
     [SerializeField] ScrollerController scroller;
     [SerializeField] TextEx txtHunt;
+    [SerializeField] ButtonEx detailBtn;
     bool isSweepVictory = false;
     string battleName = BattleConst.TianziBillboradBattleField;
+
+    protected override void InitComponent()
+    {
+        detailBtn.SetListener(() =>
+        {
+            BattleSettlementManager.Instance.OpenBattleDetailWin(battleName);
+        });
+    }
+
     protected override void OnPreOpen()
     {
         base.OnPreOpen();

--
Gitblit v1.8.0