diff --git a/Config/Binary/BaitConfigData.bytes b/Config/Binary/BaitConfigData.bytes
new file mode 100644
index 0000000..0bffa4c
--- /dev/null
+++ b/Config/Binary/BaitConfigData.bytes
@@ -0,0 +1,5 @@
+
+ ��baits/worm_01/worm_01(�
+��
baits/fly/fly(x
+'��baits/black_leech/black_leech(x
+��baits/bread/bread(x
\ No newline at end of file
diff --git a/Config/Binary/BobberConfigData.bytes b/Config/Binary/BobberConfigData.bytes
new file mode 100644
index 0000000..fd77b45
--- /dev/null
+++ b/Config/Binary/BobberConfigData.bytes
@@ -0,0 +1,5 @@
+
+6�*bobbers/expressfishing/bob_25003/bob_25003 ((
+:�0bobbers/expressfishing/bob_25162_25163/bob_25162 ((
+:�0bobbers/expressfishing/bob_25166_25167/bob_25166 ((
+4�*bobbers/expressfishing/bob_25001/bob_25001 ((
\ No newline at end of file
diff --git a/Config/Binary/FeederConfigData.bytes b/Config/Binary/FeederConfigData.bytes
new file mode 100644
index 0000000..7512fc4
--- /dev/null
+++ b/Config/Binary/FeederConfigData.bytes
@@ -0,0 +1,2 @@
+
+&��6Feeders/Feeder 1/FeedTrash 1 d(
\ No newline at end of file
diff --git a/Config/Binary/FishConfigData.bytes b/Config/Binary/FishConfigData.bytes
new file mode 100644
index 0000000..cfe7aeb
--- /dev/null
+++ b/Config/Binary/FishConfigData.bytes
@@ -0,0 +1,6 @@
+
+���Burbot_B 
+(0"8���
+£�CarpCommon_B (0"8���
+ã�CarpGrass_B (0"8���
+ģ�
CarpCrucian_B (0"8���
\ No newline at end of file
diff --git a/Config/Binary/HookConfigData.bytes b/Config/Binary/HookConfigData.bytes
new file mode 100644
index 0000000..66b9ce3
--- /dev/null
+++ b/Config/Binary/HookConfigData.bytes
@@ -0,0 +1,3 @@
+
+:��*.hooks/alliance/c_hook_20789_20794/c_hook_20789 0
+?��*3hooks/berserk_hooks/triple_20569_20577/triple_20569 0
\ No newline at end of file
diff --git a/Config/Binary/LineConfigData.bytes b/Config/Binary/LineConfigData.bytes
new file mode 100644
index 0000000..1ede551
--- /dev/null
+++ b/Config/Binary/LineConfigData.bytes
@@ -0,0 +1,3 @@
+
+(��Lines/UFE Mono/UFE monoClear ((0
+4��(rods/syberia/bolo_10021/bolo_10021_LB400 ((0
\ No newline at end of file
diff --git a/Config/Binary/LureConfigData.bytes b/Config/Binary/LureConfigData.bytes
new file mode 100644
index 0000000..656c402
--- /dev/null
+++ b/Config/Binary/LureConfigData.bytes
@@ -0,0 +1,5 @@
+
+D��$5lures/express_fishing/crankbaits_1/775/crankbaits_775��* 20�
+E��$7lures/express_fishing/poppers_1/poppers_590/poppers_590��* 20x
+M��$Clures/express_fishing/softplastic/ef_supergrab_6/softplastic_g_1622 20x
+O��$Elures/express_fishing/softplastic/ef_superminnow_6/softplastic_m_1634 20x
\ No newline at end of file
diff --git a/Config/Binary/ReelConfigData.bytes b/Config/Binary/ReelConfigData.bytes
new file mode 100644
index 0000000..4b7686f
Binary files /dev/null and b/Config/Binary/ReelConfigData.bytes differ
diff --git a/Config/Binary/RingConfigData.bytes b/Config/Binary/RingConfigData.bytes
new file mode 100644
index 0000000..833eed4
--- /dev/null
+++ b/Config/Binary/RingConfigData.bytes
@@ -0,0 +1,3 @@
+
+(�C"rod_rings/rumoi/rumoi_oxiline_spin
+)�C#rod_rings/smt/smt_pure_ceramic_bolo
\ No newline at end of file
diff --git a/Config/Binary/RodConfigData.bytes b/Config/Binary/RodConfigData.bytes
new file mode 100644
index 0000000..4d30fd5
--- /dev/null
+++ b/Config/Binary/RodConfigData.bytes
@@ -0,0 +1,4 @@
+
+7��&rods/syberia/tele_10037/tele_10037_t13(0�8(@C
+:��(rods/syberia/bolo_10021/bolo_10021_LB400 �C(0x8(@
+9��'rods/syberia/spin_10034/spin_10034_S60H �C(0x8(@
\ No newline at end of file
diff --git a/Config/Binary/WeightConfigData.bytes b/Config/Binary/WeightConfigData.bytes
new file mode 100644
index 0000000..c7da2d8
--- /dev/null
+++ b/Config/Binary/WeightConfigData.bytes
@@ -0,0 +1,2 @@
+
+��0Weights/Weight2_5g 
\ No newline at end of file
diff --git a/Config/Excel/BaitConfig.xlsx b/Config/Excel/BaitConfig.xlsx
new file mode 100644
index 0000000..b01335f
Binary files /dev/null and b/Config/Excel/BaitConfig.xlsx differ
diff --git a/Config/Excel/BobberConfig.xlsx b/Config/Excel/BobberConfig.xlsx
new file mode 100644
index 0000000..7d1cc15
Binary files /dev/null and b/Config/Excel/BobberConfig.xlsx differ
diff --git a/Config/Excel/FeederConfig.xlsx b/Config/Excel/FeederConfig.xlsx
new file mode 100644
index 0000000..c253564
Binary files /dev/null and b/Config/Excel/FeederConfig.xlsx differ
diff --git a/Config/Excel/FishConfig.xlsx b/Config/Excel/FishConfig.xlsx
new file mode 100644
index 0000000..ae840be
Binary files /dev/null and b/Config/Excel/FishConfig.xlsx differ
diff --git a/Config/Excel/HookConfig.xlsx b/Config/Excel/HookConfig.xlsx
new file mode 100644
index 0000000..546c175
Binary files /dev/null and b/Config/Excel/HookConfig.xlsx differ
diff --git a/Config/Excel/LineConfig.xlsx b/Config/Excel/LineConfig.xlsx
new file mode 100644
index 0000000..b8dcd5c
Binary files /dev/null and b/Config/Excel/LineConfig.xlsx differ
diff --git a/Config/Excel/LureConfig.xlsx b/Config/Excel/LureConfig.xlsx
new file mode 100644
index 0000000..97925e9
Binary files /dev/null and b/Config/Excel/LureConfig.xlsx differ
diff --git a/Config/Excel/ReelConfig.xlsx b/Config/Excel/ReelConfig.xlsx
new file mode 100644
index 0000000..b52d8da
Binary files /dev/null and b/Config/Excel/ReelConfig.xlsx differ
diff --git a/Config/Excel/RingConfig.xlsx b/Config/Excel/RingConfig.xlsx
new file mode 100644
index 0000000..e457fc5
Binary files /dev/null and b/Config/Excel/RingConfig.xlsx differ
diff --git a/Config/Excel/RodConfig.xlsx b/Config/Excel/RodConfig.xlsx
new file mode 100644
index 0000000..f62055c
Binary files /dev/null and b/Config/Excel/RodConfig.xlsx differ
diff --git a/Config/Excel/Version.txt b/Config/Excel/Version.txt
deleted file mode 100644
index 8fa6e75..0000000
--- a/Config/Excel/Version.txt
+++ /dev/null
@@ -1 +0,0 @@
-{"WorksheetNames":[-8419147776733210060,-3495952183970875596,1720330851179383898,5812538452563588342],"Tables":{"-3495952183970875596":1757296589391,"-1088042625810372120":1748918712210,"1720330851179383898":1753770985781,"3730651590607244245":1748918712210,"5812538452563588342":1751250727840}}
\ No newline at end of file
diff --git a/Config/Excel/WeightConfig.xlsx b/Config/Excel/WeightConfig.xlsx
new file mode 100644
index 0000000..13782d9
Binary files /dev/null and b/Config/Excel/WeightConfig.xlsx differ
diff --git a/Config/Json/Server/BaitConfigData.Json b/Config/Json/Server/BaitConfigData.Json
new file mode 100644
index 0000000..a5d4897
--- /dev/null
+++ b/Config/Json/Server/BaitConfigData.Json
@@ -0,0 +1,6 @@
+{"List":[
+{"Id":500001,"Model":"baits/worm_01/worm_01","EfficacyBase":15,"Length":0,"Weight":250},
+{"Id":500002,"Model":"baits/fly/fly","EfficacyBase":15,"Length":0,"Weight":120},
+{"Id":500003,"Model":"baits/black_leech/black_leech","EfficacyBase":15,"Length":0,"Weight":120},
+{"Id":500004,"Model":"baits/bread/bread","EfficacyBase":15,"Length":0,"Weight":120}
+]}
diff --git a/Config/Json/Server/BobberConfigData.Json b/Config/Json/Server/BobberConfigData.Json
new file mode 100644
index 0000000..6b660e3
--- /dev/null
+++ b/Config/Json/Server/BobberConfigData.Json
@@ -0,0 +1,6 @@
+{"List":[
+{"Id":300001,"Model":"bobbers/expressfishing/bob_25003/bob_25003","Type":2,"Weight":1,"Displacement":40,"NightLight":0},
+{"Id":300002,"Model":"bobbers/expressfishing/bob_25162_25163/bob_25162","Type":0,"Weight":1,"Displacement":40,"NightLight":0},
+{"Id":300003,"Model":"bobbers/expressfishing/bob_25166_25167/bob_25166","Type":0,"Weight":1,"Displacement":40,"NightLight":0},
+{"Id":300004,"Model":"bobbers/expressfishing/bob_25001/bob_25001","Type":0,"Weight":1,"Displacement":40,"NightLight":0}
+]}
diff --git a/Config/Json/Server/FeederConfigData.Json b/Config/Json/Server/FeederConfigData.Json
new file mode 100644
index 0000000..f6c86fa
--- /dev/null
+++ b/Config/Json/Server/FeederConfigData.Json
@@ -0,0 +1,3 @@
+{"List":[
+{"Id":900001,"Model":"Feeders/Feeder 1/FeedTrash 1","Type":0,"Capacity":100,"Weight":5}
+]}
diff --git a/Config/Json/Server/FishConfigData.Json b/Config/Json/Server/FishConfigData.Json
new file mode 100644
index 0000000..9c79c1c
--- /dev/null
+++ b/Config/Json/Server/FishConfigData.Json
@@ -0,0 +1,6 @@
+{"List":[
+{"Id":2200001,"Model":["Burbot_B"],"Type":0,"SpeciesName":10,"MinWeight":1,"MaxWeight":34,"Accept":2100001},
+{"Id":2200002,"Model":["CarpCommon_B"],"Type":0,"SpeciesName":11,"MinWeight":1,"MaxWeight":34,"Accept":2100001},
+{"Id":2200003,"Model":["CarpGrass_B"],"Type":0,"SpeciesName":14,"MinWeight":1,"MaxWeight":34,"Accept":2100001},
+{"Id":2200004,"Model":["CarpCrucian_B"],"Type":0,"SpeciesName":16,"MinWeight":1,"MaxWeight":34,"Accept":2100001}
+]}
diff --git a/Config/Json/Server/HookConfigData.Json b/Config/Json/Server/HookConfigData.Json
new file mode 100644
index 0000000..61293c5
--- /dev/null
+++ b/Config/Json/Server/HookConfigData.Json
@@ -0,0 +1,4 @@
+{"List":[
+{"Id":700001,"Model":"hooks/alliance/c_hook_20789_20794/c_hook_20789","Type":1,"Zadzior":1,"Length":0,"Weight":1},
+{"Id":700002,"Model":"hooks/berserk_hooks/triple_20569_20577/triple_20569","Type":1,"Zadzior":1,"Length":0,"Weight":1}
+]}
diff --git a/Config/Json/Server/LineConfigData.Json b/Config/Json/Server/LineConfigData.Json
new file mode 100644
index 0000000..7b62059
--- /dev/null
+++ b/Config/Json/Server/LineConfigData.Json
@@ -0,0 +1,4 @@
+{"List":[
+{"Id":400001,"Model":"Lines/UFE Mono/UFE monoClear","Type":0,"Length":7,"Strength":40,"Size":1},
+{"Id":400002,"Model":"rods/syberia/bolo_10021/bolo_10021_LB400","Type":0,"Length":5,"Strength":40,"Size":1}
+]}
diff --git a/Config/Json/Server/LureConfigData.Json b/Config/Json/Server/LureConfigData.Json
new file mode 100644
index 0000000..709dffb
--- /dev/null
+++ b/Config/Json/Server/LureConfigData.Json
@@ -0,0 +1,6 @@
+{"List":[
+{"Id":600001,"Model":"lures/express_fishing/crankbaits_1/775/crankbaits_775","Hook":[700102],"EfficacyBase":50,"Length":0,"Weight":250},
+{"Id":600002,"Model":"lures/express_fishing/poppers_1/poppers_590/poppers_590","Hook":[700102],"EfficacyBase":50,"Length":0,"Weight":120},
+{"Id":600003,"Model":"lures/express_fishing/softplastic/ef_supergrab_6/softplastic_g_1622","Hook":[],"EfficacyBase":50,"Length":0,"Weight":120},
+{"Id":600004,"Model":"lures/express_fishing/softplastic/ef_superminnow_6/softplastic_m_1634","Hook":[],"EfficacyBase":50,"Length":0,"Weight":120}
+]}
diff --git a/Config/Json/Server/ReelConfigData.Json b/Config/Json/Server/ReelConfigData.Json
new file mode 100644
index 0000000..31d27e5
--- /dev/null
+++ b/Config/Json/Server/ReelConfigData.Json
@@ -0,0 +1,4 @@
+{"List":[
+{"Id":200001,"Model":"reels/syberia/spin_5002/spin_5002","Type":0,"GearRatio":[7.0],"Size":250,"Strength":40},
+{"Id":200002,"Model":"reels/syberia/spin_5036/spin_5036","Type":0,"GearRatio":[5.0],"Size":120,"Strength":40}
+]}
diff --git a/Config/Json/Server/RingConfigData.Json b/Config/Json/Server/RingConfigData.Json
new file mode 100644
index 0000000..6ce7186
--- /dev/null
+++ b/Config/Json/Server/RingConfigData.Json
@@ -0,0 +1,4 @@
+{"List":[
+{"Id":1100001,"Model":"rod_rings/rumoi/rumoi_oxiline_spin"},
+{"Id":1100002,"Model":"rod_rings/smt/smt_pure_ceramic_bolo"}
+]}
diff --git a/Config/Json/Server/RodConfigData.Json b/Config/Json/Server/RodConfigData.Json
new file mode 100644
index 0000000..d677526
--- /dev/null
+++ b/Config/Json/Server/RodConfigData.Json
@@ -0,0 +1,5 @@
+{"List":[
+{"Id":100001,"Model":"rods/syberia/tele_10037/tele_10037_t13","Type":1,"Ring":0,"Length":7,"Weight":250,"Strength":40,"MaxRange":67,"ConstructionType":0},
+{"Id":100002,"Model":"rods/syberia/bolo_10021/bolo_10021_LB400","Type":0,"Ring":1100002,"Length":5,"Weight":120,"Strength":40,"MaxRange":30,"ConstructionType":0},
+{"Id":100003,"Model":"rods/syberia/spin_10034/spin_10034_S60H","Type":0,"Ring":1100001,"Length":5,"Weight":120,"Strength":40,"MaxRange":30,"ConstructionType":0}
+]}
diff --git a/Config/Json/Server/WeightConfigData.Json b/Config/Json/Server/WeightConfigData.Json
new file mode 100644
index 0000000..a356320
--- /dev/null
+++ b/Config/Json/Server/WeightConfigData.Json
@@ -0,0 +1,3 @@
+{"List":[
+{"Id":800001,"Model":"Weights/Weight2_5g","Type":0,"Weight":3}
+]}
diff --git a/Entity/Generate/ConfigTable/Entity/BaitConfig.cs b/Entity/Generate/ConfigTable/Entity/BaitConfig.cs
new file mode 100644
index 0000000..54a1f1c
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/BaitConfig.cs
@@ -0,0 +1,101 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class BaitConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<BaitConfig> List { get; set; } = new List<BaitConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, BaitConfig> _configs = new ConcurrentDictionary<uint, BaitConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, BaitConfig> _configs = new Dictionary<uint, BaitConfig>();
+#endif
+        private static BaitConfigData _instance = null;
+
+        public static BaitConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<BaitConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public BaitConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"BaitConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out BaitConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class BaitConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型
+		[ProtoMember(3)]
+		public uint EfficacyBase { get; set; } // 吸引力
+		[ProtoMember(4)]
+		public uint Length { get; set; } // 长度（毫米）
+		[ProtoMember(5)]
+		public uint Weight { get; set; } // 重量(克)  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/BobberConfig.cs b/Entity/Generate/ConfigTable/Entity/BobberConfig.cs
new file mode 100644
index 0000000..8afe79f
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/BobberConfig.cs
@@ -0,0 +1,103 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class BobberConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<BobberConfig> List { get; set; } = new List<BobberConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, BobberConfig> _configs = new ConcurrentDictionary<uint, BobberConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, BobberConfig> _configs = new Dictionary<uint, BobberConfig>();
+#endif
+        private static BobberConfigData _instance = null;
+
+        public static BobberConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<BobberConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public BobberConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"BobberConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out BobberConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class BobberConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型
+		[ProtoMember(3)]
+		public uint Type { get; set; } // 类型
+		[ProtoMember(4)]
+		public uint Weight { get; set; } // 重量(克)
+		[ProtoMember(5)]
+		public uint Displacement { get; set; } // 位移
+		[ProtoMember(6)]
+		public uint NightLight { get; set; } // 是否夜光  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/FeederConfig.cs b/Entity/Generate/ConfigTable/Entity/FeederConfig.cs
new file mode 100644
index 0000000..7d092aa
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/FeederConfig.cs
@@ -0,0 +1,101 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class FeederConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<FeederConfig> List { get; set; } = new List<FeederConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, FeederConfig> _configs = new ConcurrentDictionary<uint, FeederConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, FeederConfig> _configs = new Dictionary<uint, FeederConfig>();
+#endif
+        private static FeederConfigData _instance = null;
+
+        public static FeederConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<FeederConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public FeederConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"FeederConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out FeederConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class FeederConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型
+		[ProtoMember(3)]
+		public uint Type { get; set; } // 类型
+		[ProtoMember(4)]
+		public uint Capacity { get; set; } // 能力
+		[ProtoMember(5)]
+		public uint Weight { get; set; } // 重量(克)  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/FishConfig.cs b/Entity/Generate/ConfigTable/Entity/FishConfig.cs
new file mode 100644
index 0000000..2ed0c08
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/FishConfig.cs
@@ -0,0 +1,105 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class FishConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<FishConfig> List { get; set; } = new List<FishConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, FishConfig> _configs = new ConcurrentDictionary<uint, FishConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, FishConfig> _configs = new Dictionary<uint, FishConfig>();
+#endif
+        private static FishConfigData _instance = null;
+
+        public static FishConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<FishConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public FishConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"FishConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out FishConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class FishConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string[] Model { get; set; } = Array.Empty<string>(); // 模型
+		[ProtoMember(3)]
+		public uint Type { get; set; } // 类型
+		[ProtoMember(4)]
+		public uint SpeciesName { get; set; } // 鱼类型Id
+		[ProtoMember(5)]
+		public uint MinWeight { get; set; } // 最小重量(克)
+		[ProtoMember(6)]
+		public uint MaxWeight { get; set; } // 最大重量(克)
+		[ProtoMember(7)]
+		public uint Accept { get; set; } // 接受饵  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/HookConfig.cs b/Entity/Generate/ConfigTable/Entity/HookConfig.cs
new file mode 100644
index 0000000..98722e1
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/HookConfig.cs
@@ -0,0 +1,103 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class HookConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<HookConfig> List { get; set; } = new List<HookConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, HookConfig> _configs = new ConcurrentDictionary<uint, HookConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, HookConfig> _configs = new Dictionary<uint, HookConfig>();
+#endif
+        private static HookConfigData _instance = null;
+
+        public static HookConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<HookConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public HookConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"HookConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out HookConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class HookConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型
+		[ProtoMember(3)]
+		public uint Type { get; set; } // 类型
+		[ProtoMember(4)]
+		public uint Zadzior { get; set; } // 长钉
+		[ProtoMember(5)]
+		public uint Length { get; set; } // 长度（毫米）
+		[ProtoMember(6)]
+		public uint Weight { get; set; } // 重量(克)  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/LineConfig.cs b/Entity/Generate/ConfigTable/Entity/LineConfig.cs
new file mode 100644
index 0000000..1399198
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/LineConfig.cs
@@ -0,0 +1,103 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class LineConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<LineConfig> List { get; set; } = new List<LineConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, LineConfig> _configs = new ConcurrentDictionary<uint, LineConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, LineConfig> _configs = new Dictionary<uint, LineConfig>();
+#endif
+        private static LineConfigData _instance = null;
+
+        public static LineConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<LineConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public LineConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"LineConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out LineConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class LineConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型
+		[ProtoMember(3)]
+		public uint Type { get; set; } // 类型
+		[ProtoMember(4)]
+		public uint Length { get; set; } // 长度（毫米）
+		[ProtoMember(5)]
+		public uint Strength { get; set; } // 强度
+		[ProtoMember(6)]
+		public uint Size { get; set; } // 尺寸  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/LureConfig.cs b/Entity/Generate/ConfigTable/Entity/LureConfig.cs
new file mode 100644
index 0000000..764f5d2
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/LureConfig.cs
@@ -0,0 +1,103 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class LureConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<LureConfig> List { get; set; } = new List<LureConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, LureConfig> _configs = new ConcurrentDictionary<uint, LureConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, LureConfig> _configs = new Dictionary<uint, LureConfig>();
+#endif
+        private static LureConfigData _instance = null;
+
+        public static LureConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<LureConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public LureConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"LureConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out LureConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class LureConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型
+		[ProtoMember(3)]
+		public uint[] Hook { get; set; } = Array.Empty<uint>(); // 勾
+		[ProtoMember(4)]
+		public uint EfficacyBase { get; set; } // 吸引力
+		[ProtoMember(5)]
+		public uint Length { get; set; } // 长度（毫米）
+		[ProtoMember(6)]
+		public uint Weight { get; set; } // 重量(克)  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/ReelConfig.cs b/Entity/Generate/ConfigTable/Entity/ReelConfig.cs
new file mode 100644
index 0000000..16e0839
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/ReelConfig.cs
@@ -0,0 +1,103 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class ReelConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<ReelConfig> List { get; set; } = new List<ReelConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, ReelConfig> _configs = new ConcurrentDictionary<uint, ReelConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, ReelConfig> _configs = new Dictionary<uint, ReelConfig>();
+#endif
+        private static ReelConfigData _instance = null;
+
+        public static ReelConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<ReelConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public ReelConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"ReelConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out ReelConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class ReelConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型
+		[ProtoMember(3)]
+		public uint Type { get; set; } // 类型
+		[ProtoMember(4)]
+		public float[] GearRatio { get; set; } = Array.Empty<float>(); // 组件比
+		[ProtoMember(5)]
+		public uint Size { get; set; } // 尺寸
+		[ProtoMember(6)]
+		public uint Strength { get; set; } // 强度  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/RingConfig.cs b/Entity/Generate/ConfigTable/Entity/RingConfig.cs
new file mode 100644
index 0000000..a0e39c6
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/RingConfig.cs
@@ -0,0 +1,95 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class RingConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<RingConfig> List { get; set; } = new List<RingConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, RingConfig> _configs = new ConcurrentDictionary<uint, RingConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, RingConfig> _configs = new Dictionary<uint, RingConfig>();
+#endif
+        private static RingConfigData _instance = null;
+
+        public static RingConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<RingConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public RingConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"RingConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out RingConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class RingConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/RodConfig.cs b/Entity/Generate/ConfigTable/Entity/RodConfig.cs
new file mode 100644
index 0000000..2fabc5e
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/RodConfig.cs
@@ -0,0 +1,109 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class RodConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<RodConfig> List { get; set; } = new List<RodConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, RodConfig> _configs = new ConcurrentDictionary<uint, RodConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, RodConfig> _configs = new Dictionary<uint, RodConfig>();
+#endif
+        private static RodConfigData _instance = null;
+
+        public static RodConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<RodConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public RodConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"RodConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out RodConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class RodConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型
+		[ProtoMember(3)]
+		public uint Type { get; set; } // 类型
+		[ProtoMember(4)]
+		public uint Ring { get; set; } // 导线圈
+		[ProtoMember(5)]
+		public uint Length { get; set; } // 长度（毫米）
+		[ProtoMember(6)]
+		public uint Weight { get; set; } // 重量(克)
+		[ProtoMember(7)]
+		public uint Strength { get; set; } // 强度
+		[ProtoMember(8)]
+		public uint MaxRange { get; set; } // 最大范围
+		[ProtoMember(9)]
+		public uint ConstructionType { get; set; } // 结构类型  
+    } 
+}  
\ No newline at end of file
diff --git a/Entity/Generate/ConfigTable/Entity/WeightConfig.cs b/Entity/Generate/ConfigTable/Entity/WeightConfig.cs
new file mode 100644
index 0000000..c372e52
--- /dev/null
+++ b/Entity/Generate/ConfigTable/Entity/WeightConfig.cs
@@ -0,0 +1,99 @@
+using System;
+using ProtoBuf;
+using Fantasy;
+using System.Linq;
+using System.Reflection;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using Fantasy.ConfigTable;
+using Fantasy.Serialize;
+// ReSharper disable CollectionNeverUpdated.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0169
+#pragma warning disable CS8618
+#pragma warning disable CS8625
+#pragma warning disable CS8603
+
+namespace Fantasy
+{
+    [ProtoContract]
+    public sealed partial class WeightConfigData : ASerialize, IConfigTable, IProto
+    {
+        [ProtoMember(1)]
+        public List<WeightConfig> List { get; set; } = new List<WeightConfig>();
+#if FANTASY_NET
+        [ProtoIgnore]
+        private readonly ConcurrentDictionary<uint, WeightConfig> _configs = new ConcurrentDictionary<uint, WeightConfig>();
+#else 
+        [ProtoIgnore]
+        private readonly Dictionary<uint, WeightConfig> _configs = new Dictionary<uint, WeightConfig>();
+#endif
+        private static WeightConfigData _instance = null;
+
+        public static WeightConfigData Instance
+        {
+            get { return _instance ??= ConfigTableHelper.Load<WeightConfigData>(); } 
+            private set => _instance = value;
+        }
+
+        public WeightConfig Get(uint id, bool check = true)
+        {
+            if (_configs.ContainsKey(id))
+            {
+                return _configs[id];
+            }
+    
+            if (check)
+            {
+                throw new Exception($"WeightConfig not find {id} Id");
+            }
+            
+            return null;
+        }
+        public bool TryGet(uint id, out WeightConfig config)
+        {
+            config = null;
+            
+            if (!_configs.ContainsKey(id))
+            {
+                return false;
+            }
+                
+            config = _configs[id];
+            return true;
+        }
+        public override void AfterDeserialization()
+        {
+            foreach (var config in List)
+            {
+#if FANTASY_NET
+                _configs.TryAdd(config.Id, config);
+#else
+                _configs.Add(config.Id, config);
+#endif
+                config.AfterDeserialization();
+            }
+    
+            EndInit();
+        }
+        
+        public override void Dispose()
+        {
+            Instance = null;
+        }
+    }
+    
+    [ProtoContract]
+    public sealed partial class WeightConfig : ASerialize, IProto
+    {
+		[ProtoMember(1)]
+		public uint Id { get; set; } // Id
+		[ProtoMember(2)]
+		public string Model { get; set; } // 模型
+		[ProtoMember(3)]
+		public uint Type { get; set; } // 类型
+		[ProtoMember(4)]
+		public uint Weight { get; set; } // 重量(克)  
+    } 
+}  
\ No newline at end of file
diff --git a/Server.sln.DotSettings.user b/Server.sln.DotSettings.user
index 9a3aa0f..de40ef4 100644
--- a/Server.sln.DotSettings.user
+++ b/Server.sln.DotSettings.user
@@ -61,6 +61,7 @@
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APipeWriter_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb12a8c0984934a8b9a488164bdec50312ec00_003Ff6_003F9d6126fa_003FPipeWriter_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APriorityQueue_00602_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F46b03cd429344aac8ead6cde395f2ffd51918_003Fea_003Ff041a5cb_003FPriorityQueue_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APriorityQueue_00602_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fd8a0b92db29b4e8f99b8db03b74e165943600_003F8e_003F0782b53d_003FPriorityQueue_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
+	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProtoMemberAttribute_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003F1ad39110987b317aa178f528f27d9c837589269676a6a2ccc7fbf6b59b7d9_003FProtoMemberAttribute_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProtoMemberAttribute_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ff4d74acca13b4111aaa523ebe15f4f3348800_003F51_003Fa2613704_003FProtoMemberAttribute_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProtoMemberAttribute_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F1ad39110987b317aa178f528f27d9c837589269676a6a2ccc7fbf6b59b7d9_003FProtoMemberAttribute_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProtoWriter_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ff4d74acca13b4111aaa523ebe15f4f3348800_003Fa9_003F36ff0954_003FProtoWriter_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
diff --git a/Tools/ConfigBuilder/ConfigBuilder.sln b/Tools/ConfigBuilder/ConfigBuilder.sln
new file mode 100644
index 0000000..ff5bae9
--- /dev/null
+++ b/Tools/ConfigBuilder/ConfigBuilder.sln
@@ -0,0 +1,25 @@
+﻿
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36408.4 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NBConfigBuilder", "NBConfigBuilder\NBConfigBuilder.csproj", "{A6264F0E-870D-401D-B1BF-698695AC674C}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A6264F0E-870D-401D-B1BF-698695AC674C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A6264F0E-870D-401D-B1BF-698695AC674C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A6264F0E-870D-401D-B1BF-698695AC674C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A6264F0E-870D-401D-B1BF-698695AC674C}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {F223241C-FF74-4903-8F47-8A5A5A0FAC99}
+	EndGlobalSection
+EndGlobal
diff --git a/Tools/ConfigBuilder/ConfigBuilder.sln.DotSettings.user b/Tools/ConfigBuilder/ConfigBuilder.sln.DotSettings.user
new file mode 100644
index 0000000..bc0585f
--- /dev/null
+++ b/Tools/ConfigBuilder/ConfigBuilder.sln.DotSettings.user
@@ -0,0 +1,3 @@
+﻿<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALogManager_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fc5462be99aec4b8dbd0143c73a99d4d1e0000_003F10_003Fa592ee39_003FLogManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
+	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANativeWindow_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F257c19112c5249f9bf699efc998471b6cef910_003F44_003Fcc810871_003FNativeWindow_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/App.cs b/Tools/ConfigBuilder/NBConfigBuilder/App.cs
new file mode 100644
index 0000000..dde37af
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/App.cs
@@ -0,0 +1,20 @@
+namespace NBConfigBuilder;
+
+// 添加配置类
+public class AppConfig
+{
+    public string ExcelPath { get; set; }
+    public string ClientPath { get; set; }
+    public string ClientJsonPath { get; set; }
+    public string ServerPath { get; set; }
+    public string ServerJsonPath { get; set; }
+    public bool GenClient { get; set; }
+    public bool GenServer { get; set; }
+
+    public string ExcelVersionPath => Path.Combine(ExcelPath, "Version.txt");
+}
+
+public static class App
+{
+    public static AppConfig Config;
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Core/IPool.cs b/Tools/ConfigBuilder/NBConfigBuilder/Core/IPool.cs
new file mode 100644
index 0000000..808a332
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Core/IPool.cs
@@ -0,0 +1,17 @@
+namespace NBConfigBuilder;
+
+/// <summary>
+/// 实现了这个接口代表支持对象池
+/// </summary>
+public interface IPool
+{
+    /// <summary>
+    /// 是否从池里创建的
+    /// </summary>
+    bool IsPool();
+    /// <summary>
+    /// 设置是否从池里创建的
+    /// </summary>
+    /// <param name="isPool"></param>
+    void SetIsPool(bool isPool);
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Core/IntDictionaryConfig.cs b/Tools/ConfigBuilder/NBConfigBuilder/Core/IntDictionaryConfig.cs
new file mode 100644
index 0000000..7d8a06a
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Core/IntDictionaryConfig.cs
@@ -0,0 +1,25 @@
+namespace NBConfigBuilder;
+
+public partial class IntDictionaryConfig
+{
+    public Dictionary<int, int> Dic;
+    public int this[int key] => GetValue(key);
+
+    public bool TryGetValue(int key, out int value)
+    {
+        value = default;
+
+        if (!Dic.ContainsKey(key))
+        {
+            return false;
+        }
+
+        value = Dic[key];
+        return true;
+    }
+
+    private int GetValue(int key)
+    {
+        return Dic.TryGetValue(key, out var value) ? value : 0;
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Core/MemoryStreamBuffer.cs b/Tools/ConfigBuilder/NBConfigBuilder/Core/MemoryStreamBuffer.cs
new file mode 100644
index 0000000..ddc6998
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Core/MemoryStreamBuffer.cs
@@ -0,0 +1,77 @@
+using System.Buffers;
+
+namespace NBConfigBuilder;
+
+public enum MemoryStreamBufferSource
+{
+    None = 0,
+    Pack = 1,
+    UnPack = 2,
+}
+
+public sealed class MemoryStreamBuffer : MemoryStream, IBufferWriter<byte>
+{
+    public MemoryStreamBufferSource MemoryStreamBufferSource;
+
+    public MemoryStreamBuffer()
+    {
+    }
+
+    public MemoryStreamBuffer(MemoryStreamBufferSource memoryStreamBufferSource, int capacity) : base(capacity)
+    {
+        MemoryStreamBufferSource = memoryStreamBufferSource;
+    }
+
+    public MemoryStreamBuffer(byte[] buffer) : base(buffer)
+    {
+    }
+
+    public void Advance(int count)
+    {
+        if (count < 0)
+        {
+            throw new ArgumentOutOfRangeException(nameof(count), count, "The value of 'count' cannot be negative.");
+        }
+
+        var newLength = Position + count;
+
+        if (newLength != Length)
+        {
+            SetLength(newLength);
+        }
+
+        Position = newLength;
+    }
+
+    public Memory<byte> GetMemory(int sizeHint = 0)
+    {
+        if (sizeHint < 0)
+        {
+            throw new ArgumentOutOfRangeException(nameof(sizeHint), sizeHint,
+                "The value of 'count' cannot be negative.");
+        }
+
+        if (Length - Position <= sizeHint)
+        {
+            SetLength(Position + sizeHint);
+        }
+
+        return new Memory<byte>(GetBuffer(), (int)Position, (int)(Length - Position));
+    }
+
+    public Span<byte> GetSpan(int sizeHint = 0)
+    {
+        if (sizeHint < 0)
+        {
+            throw new ArgumentOutOfRangeException(nameof(sizeHint), sizeHint,
+                "The value of 'count' cannot be negative.");
+        }
+
+        if (Length - Position <= sizeHint)
+        {
+            SetLength(Position + sizeHint);
+        }
+
+        return new Span<byte>(GetBuffer(), (int)Position, (int)(Length - Position));
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Core/OneToManyList.cs b/Tools/ConfigBuilder/NBConfigBuilder/Core/OneToManyList.cs
new file mode 100644
index 0000000..f6a1203
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Core/OneToManyList.cs
@@ -0,0 +1,217 @@
+namespace NBConfigBuilder;
+
+/// <summary>
+/// 可回收的、一对多关系的列表池。
+/// </summary>
+/// <typeparam name="TKey">键的类型。</typeparam>
+/// <typeparam name="TValue">值的类型。</typeparam>
+public class OneToManyListPool<TKey, TValue> : OneToManyList<TKey, TValue>, IDisposable, IPool where TKey : notnull
+{
+    private bool _isPool;
+    private bool _isDispose;
+
+    /// <summary>
+    /// 创建一个 <see cref="OneToManyListPool{TKey, TValue}"/> 一对多关系的列表池的实例。
+    /// </summary>
+    /// <returns>创建的实例。</returns>
+    public static OneToManyListPool<TKey, TValue> Create()
+    {
+        var list = Pool<OneToManyListPool<TKey, TValue>>.Rent();
+        list._isDispose = false;
+        list._isPool = true;
+        return list;
+    }
+
+    /// <summary>
+    /// 释放当前对象所占用的资源，并将对象回收到对象池中。
+    /// </summary>
+    public void Dispose()
+    {
+        if (_isDispose)
+        {
+            return;
+        }
+
+        _isDispose = true;
+        Clear();
+        Pool<OneToManyListPool<TKey, TValue>>.Return(this);
+    }
+
+    /// <summary>
+    /// 获取一个值，该值指示当前实例是否为对象池中的实例。
+    /// </summary>
+    /// <returns></returns>
+    public bool IsPool()
+    {
+        return _isPool;
+    }
+
+    /// <summary>
+    /// 设置一个值，该值指示当前实例是否为对象池中的实例。
+    /// </summary>
+    /// <param name="isPool"></param>
+    public void SetIsPool(bool isPool)
+    {
+        _isPool = isPool;
+    }
+}
+
+/// <summary>
+/// 一对多关系的列表字典。
+/// </summary>
+/// <typeparam name="TKey">键的类型。</typeparam>
+/// <typeparam name="TValue">值的类型。</typeparam>
+public class OneToManyList<TKey, TValue> : Dictionary<TKey, List<TValue>> where TKey : notnull
+{
+    private readonly int _recyclingLimit = 120;
+    private static readonly List<TValue> Empty = new List<TValue>();
+    private readonly Queue<List<TValue>> _queue = new Queue<List<TValue>>();
+
+    /// <summary>
+    /// 初始化一个新的 <see cref="OneToManyList{TKey, TValue}"/> 实例。
+    /// </summary>
+    public OneToManyList()
+    {
+    }
+
+    /// <summary>
+    /// 设置最大缓存数量
+    /// </summary>
+    /// <param name="recyclingLimit">
+    /// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
+    /// 2:设置成0不控制数量，全部缓存
+    /// </param>
+    public OneToManyList(int recyclingLimit)
+    {
+        _recyclingLimit = recyclingLimit;
+    }
+
+    /// <summary>
+    /// 判断给定的键和值是否存在于列表中。
+    /// </summary>
+    /// <param name="key">要搜索的键。</param>
+    /// <param name="value">要搜索的值。</param>
+    /// <returns>如果存在则为 <see langword="true"/>，否则为 <see langword="false"/>。</returns>
+    public bool Contains(TKey key, TValue value)
+    {
+        TryGetValue(key, out var list);
+
+        return list != null && list.Contains(value);
+    }
+
+    /// <summary>
+    /// 向列表中添加指定键和值。
+    /// </summary>
+    /// <param name="key">要添加值的键。</param>
+    /// <param name="value">要添加的值。</param>
+    public void Add(TKey key, TValue value)
+    {
+        if (!TryGetValue(key, out var list))
+        {
+            list = Fetch();
+            list.Add(value);
+            Add(key, list);
+
+            return;
+        }
+
+        list.Add(value);
+    }
+
+    /// <summary>
+    /// 获取指定键对应的列表中的第一个值。
+    /// </summary>
+    /// <param name="key">要获取值的键。</param>
+    /// <returns>键对应的列表中的第一个值。</returns>
+    public TValue First(TKey key)
+    {
+        return !TryGetValue(key, out var list) ? default : list.FirstOrDefault();
+    }
+
+    /// <summary>
+    /// 从列表中移除指定键和值。
+    /// </summary>
+    /// <param name="key">要移除值的键。</param>
+    /// <param name="value">要移除的值。</param>
+    /// <returns>如果成功移除则为 <see langword="true"/>，否则为 <see langword="false"/>。</returns>
+    public bool RemoveValue(TKey key, TValue value)
+    {
+        if (!TryGetValue(key, out var list))
+        {
+            return true;
+        }
+
+        var isRemove = list.Remove(value);
+
+        if (list.Count == 0)
+        {
+            isRemove = RemoveByKey(key);
+        }
+
+        return isRemove;
+    }
+
+    /// <summary>
+    /// 从列表中移除指定键及其关联的所有值。
+    /// </summary>
+    /// <param name="key">要移除的键。</param>
+    /// <returns>如果成功移除则为 <see langword="true"/>，否则为 <see langword="false"/>。</returns>
+    public bool RemoveByKey(TKey key)
+    {
+        if (!TryGetValue(key, out var list))
+        {
+            return false;
+        }
+
+        Remove(key);
+        Recycle(list);
+        return true;
+    }
+
+    /// <summary>
+    /// 获取指定键关联的所有值的列表。
+    /// </summary>
+    /// <param name="key">要获取值的键。</param>
+    /// <returns>键关联的所有值的列表。</returns>
+    public List<TValue> GetValues(TKey key)
+    {
+        if (TryGetValue(key, out List<TValue> list))
+        {
+            return list;
+        }
+
+        return Empty;
+    }
+
+    /// <summary>
+    /// 清除字典中的所有键值对，并回收相关的值集合。
+    /// </summary>
+    public new void Clear()
+    {
+        foreach (var keyValuePair in this) Recycle(keyValuePair.Value);
+
+        base.Clear();
+    }
+
+    /// <summary>
+    /// 从空闲值集合队列中获取一个值集合，如果队列为空则创建一个新的值集合。
+    /// </summary>
+    /// <returns>从队列中获取的值集合。</returns>
+    private List<TValue> Fetch()
+    {
+        return _queue.Count <= 0 ? new List<TValue>() : _queue.Dequeue();
+    }
+
+    /// <summary>
+    /// 回收一个不再使用的值集合到空闲值集合队列中。
+    /// </summary>
+    /// <param name="list">要回收的值集合。</param>
+    private void Recycle(List<TValue> list)
+    {
+        list.Clear();
+
+        if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
+
+        _queue.Enqueue(list);
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Core/Pool.cs b/Tools/ConfigBuilder/NBConfigBuilder/Core/Pool.cs
new file mode 100644
index 0000000..989ac54
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Core/Pool.cs
@@ -0,0 +1,72 @@
+namespace NBConfigBuilder;
+
+/// <summary>
+/// 静态的对象池系统，不支持多线程。
+/// </summary>
+/// <typeparam name="T"></typeparam>
+public static class Pool<T> where T : IPool, new()
+{
+    private static readonly Queue<T> PoolQueue = new Queue<T>();
+
+    /// <summary>
+    /// 池子里可用的数量
+    /// </summary>
+    public static int Count => PoolQueue.Count;
+
+    /// <summary>
+    /// 租借
+    /// </summary>
+    /// <returns></returns>
+    public static T Rent()
+    {
+        return PoolQueue.Count == 0 ? new T() : PoolQueue.Dequeue();
+    }
+
+    /// <summary>
+    /// 租借
+    /// </summary>
+    /// <param name="generator">如果池子里没有，会先执行这个委托。</param>
+    /// <returns></returns>
+    public static T Rent(Func<T> generator)
+    {
+        return PoolQueue.Count == 0 ? generator() : PoolQueue.Dequeue();
+    }
+
+    /// <summary>
+    /// 返还
+    /// </summary>
+    /// <param name="t"></param>
+    public static void Return(T t)
+    {
+        if (t == null)
+        {
+            return;
+        }
+
+        PoolQueue.Enqueue(t);
+    }
+
+    /// <summary>
+    /// 返还
+    /// </summary>
+    /// <param name="t">返还的东西</param>
+    /// <param name="reset">返还后执行的委托</param>
+    public static void Return(T t, Action<T> reset)
+    {
+        if (t == null)
+        {
+            return;
+        }
+
+        reset(t);
+        PoolQueue.Enqueue(t);
+    }
+
+    /// <summary>
+    /// 清空池子
+    /// </summary>
+    public static void Clear()
+    {
+        PoolQueue.Clear();
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Core/Serialize/ASerialize.cs b/Tools/ConfigBuilder/NBConfigBuilder/Core/Serialize/ASerialize.cs
new file mode 100644
index 0000000..67e7671
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Core/Serialize/ASerialize.cs
@@ -0,0 +1,20 @@
+using System.ComponentModel;
+
+namespace Fantasy.Serialize;
+
+public abstract class ASerialize : ISupportInitialize, IDisposable
+{
+    public virtual void Dispose()
+    {
+    }
+
+    public virtual void BeginInit()
+    {
+    }
+
+    public virtual void EndInit()
+    {
+    }
+
+    public virtual void AfterDeserialization() => EndInit();
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Core/StringDictionaryConfig.cs b/Tools/ConfigBuilder/NBConfigBuilder/Core/StringDictionaryConfig.cs
new file mode 100644
index 0000000..bf8ae75
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Core/StringDictionaryConfig.cs
@@ -0,0 +1,25 @@
+namespace NBConfigBuilder;
+
+public sealed partial class StringDictionaryConfig
+{
+    public Dictionary<int, string> Dic;
+    public string this[int key] => GetValue(key);
+
+    public bool TryGetValue(int key, out string value)
+    {
+        value = default;
+
+        if (!Dic.ContainsKey(key))
+        {
+            return false;
+        }
+
+        value = Dic[key];
+        return true;
+    }
+
+    private string GetValue(int key)
+    {
+        return Dic.TryGetValue(key, out var value) ? value : null;
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/DynamicAssembly/DynamicAssembly.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/DynamicAssembly/DynamicAssembly.cs
new file mode 100644
index 0000000..66a3272
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/DynamicAssembly/DynamicAssembly.cs
@@ -0,0 +1,169 @@
+using System.Reflection;
+using Fantasy.Serialize;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using ProtoBuf;
+
+namespace NBConfigBuilder;
+
+
+/// <summary>
+/// 动态程序集类，用于加载动态生成的程序集并获取动态信息。
+/// </summary>
+public static class DynamicAssembly
+{
+    private static void MetadataReference(out string assemblyName, out List<MetadataReference> metadataReferenceList)
+    {
+        AssemblyMetadata assemblyMetadata;
+        MetadataReference metadataReference;
+        var currentDomain = AppDomain.CurrentDomain;
+        assemblyName = Path.GetRandomFileName();
+        var assemblyArray = currentDomain.GetAssemblies();
+        metadataReferenceList = new List<MetadataReference>();
+
+        // 注册引用
+
+        foreach (var domainAssembly in assemblyArray)
+        {
+            if (string.IsNullOrEmpty(domainAssembly.Location))
+            {
+                continue;
+            }
+
+            assemblyMetadata = AssemblyMetadata.CreateFromFile(domainAssembly.Location);
+            metadataReference = assemblyMetadata.GetReference();
+            metadataReferenceList.Add(metadataReference);
+        }
+        
+        // 添加Proto支持
+        
+        assemblyMetadata = AssemblyMetadata.CreateFromFile(typeof(ProtoMemberAttribute).Assembly.Location);
+        metadataReference = assemblyMetadata.GetReference();
+        metadataReferenceList.Add(metadataReference);
+        
+        // 添加Fantasy支持
+
+        assemblyMetadata = AssemblyMetadata.CreateFromFile(typeof(ASerialize).Assembly.Location);
+        metadataReference = assemblyMetadata.GetReference();
+        metadataReferenceList.Add(metadataReference);
+    }
+    
+    /// <summary>
+    /// 加载指定路径下的动态程序集。
+    /// </summary>
+    /// <param name="path">程序集文件路径。</param>
+    /// <returns>加载的动态程序集。</returns>
+    public static Assembly Load(string path)
+    {
+        var fileList = new List<string>();
+        
+        // 找到所有需要加载的CS文件
+        
+        foreach (string file in Directory.GetFiles(path))
+        {
+            if (Path.GetExtension(file) != ".cs")
+            {
+                continue;
+            }
+        
+            fileList.Add(file);
+        }
+        
+        var syntaxTreeList = new List<SyntaxTree>();
+        
+        foreach (var file in fileList)
+        {
+            using var fileStream = new StreamReader(file);
+            var cSharp = CSharpSyntaxTree.ParseText(fileStream.ReadToEnd());
+            syntaxTreeList.Add(cSharp);
+        }
+        
+        // 注册程序集
+        MetadataReference(out var assemblyName, out var metadataReferenceList);
+        var compilation = CSharpCompilation.Create(assemblyName, syntaxTreeList, metadataReferenceList, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
+        using var ms = new MemoryStream();
+        var result = compilation.Emit(ms);
+        if (!result.Success)
+        {
+            foreach (var resultDiagnostic in result.Diagnostics)
+            {
+                Log.Error(resultDiagnostic.GetMessage());
+            }
+        
+            throw new Exception("failures");
+        }
+
+        ms.Seek(0, SeekOrigin.Begin);
+        return Assembly.Load(ms.ToArray());
+    }
+
+    /// <summary>
+    /// 获取动态程序集中指定表格的动态信息。
+    /// </summary>
+    /// <param name="dynamicAssembly">动态程序集。</param>
+    /// <param name="tableName">表格名称。</param>
+    /// <returns>动态信息对象。</returns>
+    public static DynamicConfigDataType GetDynamicInfo(Assembly dynamicAssembly, string tableName)
+    {
+        var dynamicConfigDataType = new DynamicConfigDataType
+        {
+            ConfigDataType = GetConfigType(dynamicAssembly, $"{tableName}Data"),
+            ConfigType = GetConfigType(dynamicAssembly, $"{tableName}")
+        };
+        
+        dynamicConfigDataType.ConfigData = CreateInstance(dynamicConfigDataType.ConfigDataType);
+       
+        var listPropertyType = dynamicConfigDataType.ConfigDataType.GetProperty("List");
+
+        if (listPropertyType == null)
+        {
+            throw new Exception("No Property named Add was found");
+        }
+
+        dynamicConfigDataType.Obj = listPropertyType.GetValue(dynamicConfigDataType.ConfigData);
+        dynamicConfigDataType.Method = listPropertyType.PropertyType.GetMethod("Add");
+
+        if (dynamicConfigDataType.Method == null)
+        {
+            throw new Exception("No method named Add was found");
+        }
+
+        return dynamicConfigDataType;
+    }
+
+    /// <summary>
+    /// 根据类型名称获取动态类型。
+    /// </summary>
+    /// <param name="dynamicAssembly">动态程序集。</param>
+    /// <param name="typeName">类型名称。</param>
+    /// <returns>动态类型。</returns>
+    private static Type GetConfigType(Assembly dynamicAssembly, string typeName)
+    {
+        var configType = dynamicAssembly.GetType($"Fantasy.{typeName}");
+        
+        if (configType == null)
+        {
+            throw new FileNotFoundException($"Fantasy.{typeName} not found");
+        }
+        
+        return configType;
+        // return dynamicAssembly.GetType($"Fantasy.{typeName}");
+    }
+
+    /// <summary>
+    /// 创建动态实例。
+    /// </summary>
+    /// <param name="configType">动态类型。</param>
+    /// <returns>动态实例。</returns>
+    public static object CreateInstance(Type configType)
+    {
+        var config = Activator.CreateInstance(configType);
+        
+        if (config == null)
+        {
+            throw new Exception($"{configType.Name} is Activator.CreateInstance error");
+        }
+
+        return config;
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/DynamicAssembly/DynamicConfigDataType.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/DynamicAssembly/DynamicConfigDataType.cs
new file mode 100644
index 0000000..0d808d0
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/DynamicAssembly/DynamicConfigDataType.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Text;
+
+namespace NBConfigBuilder;
+
+/// <summary>
+/// 动态配置数据类型类，用于存储动态配置数据的相关信息。
+/// </summary>
+public class DynamicConfigDataType
+{
+    /// <summary>
+    /// 配置数据对象，继承自 AProto 基类。
+    /// </summary>
+    public object ConfigData;
+    /// <summary>
+    /// 配置数据类型。
+    /// </summary>
+    public Type ConfigDataType;
+    /// <summary>
+    /// 配置类型。
+    /// </summary>
+    public Type ConfigType;
+    /// <summary>
+    /// 反射方法信息，用于调用特定方法。
+    /// </summary>
+    public MethodInfo Method;
+    /// <summary>
+    /// 配置数据对象实例。
+    /// </summary>
+    public object Obj;
+    /// <summary>
+    /// 用于生成 JSON 格式数据的字符串构建器。
+    /// </summary>
+    public StringBuilder Json = new StringBuilder();
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/DynamicAssembly/OneDynamicAssembly.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/DynamicAssembly/OneDynamicAssembly.cs
new file mode 100644
index 0000000..03b7a99
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/DynamicAssembly/OneDynamicAssembly.cs
@@ -0,0 +1,69 @@
+using System.Reflection;
+using Fantasy.Serialize;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using ProtoBuf;
+
+namespace NBConfigBuilder;
+
+public class OneDynamicAssembly
+{
+    private readonly List<SyntaxTree> _syntaxTreeList = new List<SyntaxTree>();
+
+    public void Load(string file)
+    {
+        using var fileStream = new StreamReader(file);
+        var cSharp = CSharpSyntaxTree.ParseText(fileStream.ReadToEnd());
+        _syntaxTreeList.Add(cSharp);
+    }
+    
+    public Assembly Assembly
+    {
+        get
+        {
+            AssemblyMetadata assemblyMetadata;
+            MetadataReference metadataReference;
+            var currentDomain = AppDomain.CurrentDomain;
+            var assemblyName = Path.GetRandomFileName();
+            var assemblyArray = currentDomain.GetAssemblies();
+            var metadataReferenceList = new List<MetadataReference>();
+            // 注册引用
+            foreach (var domainAssembly in assemblyArray)
+            {
+                if (string.IsNullOrEmpty(domainAssembly.Location))
+                {
+                    continue;
+                }
+                
+                assemblyMetadata = AssemblyMetadata.CreateFromFile(domainAssembly.Location);
+                metadataReference = assemblyMetadata.GetReference();
+                metadataReferenceList.Add(metadataReference);
+            }
+            // 添加ProtoEntity支持
+            assemblyMetadata = AssemblyMetadata.CreateFromFile(typeof(ASerialize).Assembly.Location);
+            metadataReference = assemblyMetadata.GetReference();
+            metadataReferenceList.Add(metadataReference);
+            // 添加MessagePack支持
+            assemblyMetadata = AssemblyMetadata.CreateFromFile(typeof(ProtoMemberAttribute).Assembly.Location);
+            metadataReference = assemblyMetadata.GetReference();
+            metadataReferenceList.Add(metadataReference);
+            CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, _syntaxTreeList, metadataReferenceList, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
+
+            using var ms = new MemoryStream();
+            var result = compilation.Emit(ms);
+            
+            if (!result.Success)
+            {
+                foreach (var resultDiagnostic in result.Diagnostics)
+                {
+                    Log.Error(resultDiagnostic.GetMessage());
+                }
+
+                throw new Exception("failures");
+            }
+
+            ms.Seek(0, SeekOrigin.Begin);
+            return Assembly.Load(ms.ToArray());
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelExporter.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelExporter.cs
new file mode 100644
index 0000000..b021e9f
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelExporter.cs
@@ -0,0 +1,950 @@
+using System.Collections.Concurrent;
+using System.Reflection;
+using System.Runtime.Loader;
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.RegularExpressions;
+using Microsoft.VisualBasic.ApplicationServices;
+using Newtonsoft.Json;
+using OfficeOpenXml;
+using static System.String;
+
+namespace NBConfigBuilder;
+
+using TableDictionary = SortedDictionary<string, List<int>>;
+
+/// <summary>
+/// Excel 数据导出器，用于从 Excel 文件导出数据到二进制格式和生成 C# 类文件。
+/// </summary>
+public sealed class ExcelExporter
+{
+    public ExportType ExportType;
+    private readonly string _excelProgramPath;
+    private readonly string _versionFilePath;
+
+    // private readonly string _excelClientFileDirectory;
+    // private readonly string _excelServerFileDirectory;
+    // private readonly string _excelServerJsonDirectory;
+    // private readonly string _excelClientJsonDirectory;
+
+    public VersionInfo VersionInfo; // 存储 Excel 文件的版本信息。
+    private readonly Regex _regexName = new Regex("^[a-zA-Z][a-zA-Z0-9_]*$"); // 用于验证 Excel 表名的正则表达式。
+    private readonly HashSet<string> _loadFiles = [".xlsx", ".xlsm", ".csv"]; // 加载的支持文件扩展名。
+
+    private readonly OneToManyList<string, ExportInfo>
+        _tables = new OneToManyList<string, ExportInfo>(); // 存储 Excel 表及其导出信息。
+
+    private readonly ConcurrentDictionary<string, ExcelTable> _excelTables =
+        new ConcurrentDictionary<string, ExcelTable>(); // 存储解析后的 Excel 表。
+
+    public readonly ConcurrentDictionary<string, ExcelWorksheet> Worksheets =
+        new ConcurrentDictionary<string, ExcelWorksheet>(); // 存储已加载的 Excel 工作表。
+
+    public readonly Dictionary<string, string> IgnoreTable = new Dictionary<string, string>(); // 存储以#开头的的表和路径
+
+    /// <summary>
+    /// 导表支持的数据类型集合。
+    /// </summary>
+    public static readonly HashSet<string> ColTypeSet =
+    [
+        "", "0", "bool", "byte", "short", "ushort", "int", "uint", "long", "ulong", "float", "string",
+        "IntDictionaryConfig", "StringDictionaryConfig",
+        "short[]", "int[]", "long[]", "float[]", "string[]", "uint[]"
+    ];
+
+    static ExcelExporter()
+    {
+        ExcelPackage.License.SetNonCommercialOrganization("Fantasy");
+    }
+
+    /// <summary>
+    /// 根据指定的 exportType 初始化 ExcelExporter 类的新实例。
+    /// </summary>
+    /// <param name="exportType">要执行的导出类型（AllExcel 或 AllExcelIncrement）。</param>
+    public ExcelExporter(ExportType exportType)
+    {
+        ExportType = exportType;
+
+        if (App.Config.ExcelVersionPath == null || App.Config.ExcelVersionPath.Trim() == "")
+        {
+            Log.Info($"ExcelVersionFile Can not be empty!");
+            return;
+        }
+
+        if (App.Config.ExcelPath == null || App.Config.ExcelPath.Trim() == "")
+        {
+            Log.Info($"ExcelProgramPath Can not be empty!");
+            return;
+        }
+
+        _excelProgramPath = FileHelper.GetFullPath(App.Config.ExcelPath);
+        _versionFilePath = FileHelper.GetFullPath(App.Config.ExcelVersionPath);
+
+        if (App.Config.GenClient)
+        {
+            if (App.Config.ClientJsonPath == null ||
+                App.Config.ClientJsonPath.Trim() == "")
+            {
+                Log.Info($"ExcelClientJsonDirectory Can not be empty!");
+                return;
+            }
+
+            if (App.Config.ClientPath == null ||
+                App.Config.ClientPath.Trim() == "")
+            {
+                Log.Info($"ExcelServerFileDirectory Can not be empty!");
+                return;
+            }
+        }
+
+        if (App.Config.GenServer)
+        {
+            if (App.Config.ServerPath == null ||
+                App.Config.ServerPath.Trim() == "")
+            {
+                Log.Info($"ExcelServerFileDirectory Can not be empty!");
+                return;
+            }
+
+            if (App.Config.ServerJsonPath == null ||
+                App.Config.ServerJsonPath.Trim() == "")
+            {
+                Log.Info($"ExcelServerJsonDirectory Can not be empty!");
+                return;
+            }
+        }
+
+        switch (ExportType)
+        {
+            case ExportType.AllExcelIncrement:
+            {
+                break;
+            }
+            case ExportType.AllExcel:
+            {
+                if (File.Exists(_versionFilePath))
+                {
+                    File.Delete(_versionFilePath);
+                }
+
+                break;
+            }
+        }
+
+        // SerializerManager.Initialize();
+    }
+
+    public void Run()
+    {
+        Find();
+        Parsing();
+        ExportToBinary();
+        File.WriteAllText(_versionFilePath, JsonConvert.SerializeObject(VersionInfo));
+    }
+
+    /// <summary>
+    /// 查找配置文件
+    /// </summary>
+    private void Find()
+    {
+        VersionInfo = File.Exists(_versionFilePath)
+            ? JsonConvert.DeserializeObject<VersionInfo>(File.ReadAllText(_versionFilePath))
+            : new VersionInfo();
+
+        var dir = new DirectoryInfo(_excelProgramPath);
+        var excelFiles = dir.GetFiles("*", SearchOption.AllDirectories);
+
+        if (excelFiles.Length <= 0)
+        {
+            return;
+        }
+
+        foreach (var excelFile in excelFiles)
+        {
+            // 过滤掉非指定后缀的文件
+
+            if (!_loadFiles.Contains(excelFile.Extension))
+            {
+                continue;
+            }
+
+            var lastIndexOf = excelFile.Name.LastIndexOf(".", StringComparison.Ordinal);
+
+            if (lastIndexOf < 0)
+            {
+                continue;
+            }
+
+            var fullName = excelFile.FullName;
+            var excelName = excelFile.Name.Substring(0, lastIndexOf);
+            var path = fullName.Substring(0, fullName.Length - excelFile.Name.Length);
+
+            // 过滤~开头文件
+
+            if (excelName.StartsWith("~", StringComparison.Ordinal))
+            {
+                continue;
+            }
+
+            // 如果文件名以#开头，那么这个文件夹下的所有文件都不导出
+
+            if (excelName.StartsWith("#", StringComparison.Ordinal))
+            {
+                IgnoreTable.Add(excelName, fullName);
+                continue;
+            }
+
+            // 如果文件夹名包含#，那么这个文件夹下的所有文件都不导出
+
+            if (path.Contains("#", StringComparison.Ordinal))
+            {
+                continue;
+            }
+
+            if (!_regexName.IsMatch(excelName))
+            {
+                Log.Info($"{excelName} 配置文件名非法");
+                continue;
+            }
+
+            var exportInfo = new ExportInfo()
+            {
+                Name = excelName, FileInfo = excelFile
+            };
+
+            _tables.Add(excelName.Split('_')[0], exportInfo);
+        }
+
+        var removeTables = new List<string>();
+
+        foreach (var (tableName, tableList) in _tables)
+        {
+            var isNeedExport = false;
+
+            foreach (var exportInfo in tableList)
+            {
+                var key = HashCodeHelper.ComputeHash64(exportInfo.Name);
+                var timer = TimeHelper.Transition(exportInfo.FileInfo.LastWriteTime);
+
+                if (!isNeedExport)
+                {
+                    if (VersionInfo.Tables.TryGetValue(key, out var lastWriteTime))
+                    {
+                        isNeedExport = lastWriteTime != timer;
+                    }
+                    else
+                    {
+                        isNeedExport = true;
+                    }
+                }
+
+                VersionInfo.Tables[key] = timer;
+            }
+
+            if (!isNeedExport)
+            {
+                removeTables.Add(tableName);
+            }
+        }
+
+        foreach (var removeTable in removeTables)
+        {
+            _tables.Remove(removeTable);
+        }
+
+        foreach (var (_, exportInfo) in _tables)
+        {
+            exportInfo.Sort((x, y) => Compare(x.Name, y.Name, StringComparison.Ordinal));
+        }
+    }
+
+    /// <summary>
+    /// 生成配置文件
+    /// </summary>
+    private void Parsing()
+    {
+        var generateTasks = new List<Task>();
+
+        foreach (var (tableName, tableList) in _tables)
+        {
+            var task = Task.Run(() =>
+            {
+                var writeToClassTask = new List<Task>();
+                var excelTable = new ExcelTable(tableName);
+
+                // 筛选需要导出的列
+                foreach (var exportInfo in tableList)
+                {
+                    try
+                    {
+                        var serverColInfoList = new List<int>();
+                        var clientColInfoList = new List<int>();
+                        var worksheet = LoadExcel(exportInfo.FileInfo.FullName, true);
+
+                        for (var col = 3; col <= worksheet.Columns.EndColumn; col++)
+                        {
+                            // 列名字第一个字符是#不参与导出
+
+                            var colName = worksheet.GetCellValue(5, col);
+                            if (colName.StartsWith("#", StringComparison.Ordinal))
+                            {
+                                continue;
+                            }
+
+                            // 数值列不参与导出
+
+                            var numericalCol = worksheet.GetCellValue(3, col);
+                            if (numericalCol != "" && numericalCol != "0")
+                            {
+                                continue;
+                            }
+
+                            var serverType = worksheet.GetCellValue(1, col);
+                            var clientType = worksheet.GetCellValue(2, col);
+                            var isExportServer = !IsNullOrEmpty(serverType) && serverType != "0";
+                            var isExportClient = !IsNullOrEmpty(clientType) && clientType != "0";
+
+                            if (!isExportServer && !isExportClient)
+                            {
+                                continue;
+                            }
+
+                            if (isExportServer && isExportClient & serverType != clientType)
+                            {
+                                Log.Info(
+                                    $"配置表 {exportInfo.Name} {col} 列 [{colName}] 客户端类型 {clientType} 和 服务端类型 {serverType} 不一致");
+                                continue;
+                            }
+
+                            if (!ColTypeSet.Contains(serverType) || !ColTypeSet.Contains(clientType))
+                            {
+                                Log.Info(
+                                    $"配置表 {exportInfo.Name} {col} 列 [{colName}] 客户端类型 {clientType}, 服务端类型 {serverType} 不合法");
+                                continue;
+                            }
+
+                            if (!_regexName.IsMatch(colName))
+                            {
+                                Log.Info($"配置表 {exportInfo.Name} {col} 列 [{colName}] 列名非法");
+                                continue;
+                            }
+
+                            serverColInfoList.Add(col);
+
+                            if (isExportClient)
+                            {
+                                clientColInfoList.Add(col);
+                            }
+                        }
+
+                        if (clientColInfoList.Count > 0)
+                        {
+                            excelTable.ClientColInfos.Add(exportInfo.FileInfo.FullName, clientColInfoList);
+                        }
+
+                        if (serverColInfoList.Count > 0)
+                        {
+                            excelTable.ServerColInfos.Add(exportInfo.FileInfo.FullName, serverColInfoList);
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        Log.Error($"Config : {tableName}, Name : {exportInfo.Name}, Error : {e}");
+                    }
+                }
+
+                // 生成cs文件
+
+                if (App.Config.GenServer)
+                {
+                    writeToClassTask.Add(Task.Run(() =>
+                    {
+                        WriteToClass(excelTable.ServerColInfos, App.Config.ServerPath, true);
+                    }));
+                }
+
+                if (App.Config.GenClient)
+                {
+                    writeToClassTask.Add(Task.Run(() =>
+                    {
+                        WriteToClass(excelTable.ClientColInfos, App.Config.ClientPath, false);
+                    }));
+                }
+
+                Task.WaitAll(writeToClassTask.ToArray());
+                _excelTables.TryAdd(tableName, excelTable);
+            });
+
+            generateTasks.Add(task);
+        }
+
+        Task.WaitAll(generateTasks.ToArray());
+        Console.WriteLine("build success===");
+    }
+
+    /// <summary>
+    /// 把数据和实体类转换二进制导出到文件中
+    /// </summary>
+    private void ExportToBinary()
+    {
+        System.Reflection.Assembly dynamicServerAssembly = null;
+        System.Reflection.Assembly dynamicClientAssembly = null;
+        var exportToBinaryTasks = new List<Task>();
+
+        if (App.Config.GenServer &&
+            Directory.Exists(App.Config.ServerPath))
+        {
+            dynamicServerAssembly = DynamicAssembly.Load(App.Config.ServerPath);
+        }
+
+        if (App.Config.GenClient &&
+            Directory.Exists(App.Config.ClientPath))
+        {
+            dynamicClientAssembly = DynamicAssembly.Load(App.Config.ClientPath);
+        }
+
+        foreach (var (tableName, tableList) in _tables)
+        {
+            var task = Task.Run(() =>
+            {
+                DynamicConfigDataType serverDynamicInfo = null;
+                DynamicConfigDataType clientDynamicInfo = null;
+
+                var idCheck = new HashSet<string>();
+                var excelTable = _excelTables[tableName];
+                var csName = Path.GetFileNameWithoutExtension(tableName);
+
+                if (App.Config.GenServer)
+                {
+                    var serverColInfoCount = excelTable.ServerColInfos.Sum(d => d.Value.Count);
+                    serverDynamicInfo = serverColInfoCount == 0
+                        ? null
+                        : DynamicAssembly.GetDynamicInfo(dynamicServerAssembly, csName);
+                }
+
+                if (App.Config.GenClient)
+                {
+                    var clientColInfoCount = excelTable.ClientColInfos.Sum(d => d.Value.Count);
+                    clientDynamicInfo = clientColInfoCount == 0
+                        ? null
+                        : DynamicAssembly.GetDynamicInfo(dynamicClientAssembly, csName);
+                }
+
+                for (var i = 0; i < tableList.Count; i++)
+                {
+                    var tableListName = tableList[i];
+
+                    try
+                    {
+                        var fileInfoFullName = tableListName.FileInfo.FullName;
+                        var excelWorksheet = LoadExcel(fileInfoFullName, false);
+                        var rows = excelWorksheet.Dimension.Rows;
+                        excelTable.ServerColInfos.TryGetValue(fileInfoFullName, out var serverCols);
+                        excelTable.ClientColInfos.TryGetValue(fileInfoFullName, out var clientCols);
+
+                        for (var row = 7; row <= rows; row++)
+                        {
+                            if (excelWorksheet.GetCellValue(row, 1).StartsWith("#", StringComparison.Ordinal))
+                            {
+                                continue;
+                            }
+
+                            var id = excelWorksheet.GetCellValue(row, 3);
+
+                            if (idCheck.Contains(id))
+                            {
+                                Log.Info($"{tableListName.Name} 存在重复Id {id} 行号 {row}");
+                                continue;
+                            }
+
+                            idCheck.Add(id);
+                            var isLast = row == rows && (i == tableList.Count - 1);
+
+                            if (App.Config.GenServer)
+                            {
+                                GenerateBinary(fileInfoFullName, excelWorksheet, serverDynamicInfo, serverCols, id, row,
+                                    isLast, true);
+                            }
+
+                            if (App.Config.GenClient)
+                            {
+                                GenerateBinary(fileInfoFullName, excelWorksheet, clientDynamicInfo, clientCols, id, row,
+                                    isLast, false);
+                            }
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        Log.Error($"Table:{tableListName} error! \n{e}");
+                        throw;
+                    }
+                }
+
+                if (serverDynamicInfo?.ConfigData != null)
+                {
+                    // var memoryStream = new MemoryStreamBuffer();
+                    // SerializerManager.GetSerializer(FantasySerializerType.ProtoBuf)
+                    //     .Serialize(serverDynamicInfo.ConfigData, memoryStream);
+                    // if (!Directory.Exists(_excelServerBinaryDirectory))
+                    // {
+                    //     Directory.CreateDirectory(_excelServerBinaryDirectory);
+                    // }
+
+                    // var asSpan = memoryStream.GetBuffer().AsSpan(0, (int)memoryStream.Position);
+                    // File.WriteAllBytes(Path.Combine(_excelServerBinaryDirectory, $"{csName}Data.bytes"),
+                    //     asSpan.ToArray());
+
+                    if (serverDynamicInfo.Json.Length > 0)
+                    {
+                        if (!Directory.Exists(App.Config.ServerJsonPath))
+                        {
+                            Directory.CreateDirectory(App.Config.ServerJsonPath);
+                        }
+
+                        using var sw = new StreamWriter(Path.Combine(App.Config.ServerJsonPath, $"{csName}Data.Json"));
+                        sw.WriteLine("{\"List\":[");
+                        sw.Write(serverDynamicInfo.Json.ToString());
+                        sw.WriteLine("]}");
+                    }
+                }
+
+                if (clientDynamicInfo?.ConfigData != null)
+                {
+                    // var memoryStream = new MemoryStreamBuffer();
+                    // SerializerManager.GetSerializer(FantasySerializerType.ProtoBuf)
+                    //     .Serialize(clientDynamicInfo.ConfigData, memoryStream);
+                    // if (!Directory.Exists(_excelClientBinaryDirectory))
+                    // {
+                    //     Directory.CreateDirectory(_excelClientBinaryDirectory);
+                    // }
+                    //
+                    // var asSpan = memoryStream.GetBuffer().AsSpan(0, (int)memoryStream.Position);
+                    // File.WriteAllBytes(Path.Combine(_excelClientBinaryDirectory, $"{csName}Data.bytes"),
+                    //     asSpan.ToArray());
+
+                    if (clientDynamicInfo.Json.Length > 0)
+                    {
+                        if (!Directory.Exists(App.Config.ClientJsonPath))
+                        {
+                            Directory.CreateDirectory(App.Config.ClientJsonPath);
+                        }
+
+                        using var sw = new StreamWriter(Path.Combine(App.Config.ClientJsonPath, $"{csName}Data.Json"));
+                        sw.WriteLine("{\"List\":[");
+                        sw.Write(clientDynamicInfo.Json.ToString());
+                        sw.WriteLine("]}");
+                    }
+                }
+            });
+            exportToBinaryTasks.Add(task);
+        }
+
+        Task.WaitAll(exportToBinaryTasks.ToArray());
+    }
+
+    private void GenerateBinary(string fileInfoFullName, ExcelWorksheet excelWorksheet,
+        DynamicConfigDataType dynamicInfo, List<int> cols, string id, int row, bool isLast, bool isServer)
+    {
+        if (cols == null || IsNullOrEmpty(id) || cols.Count <= 0 || dynamicInfo?.ConfigType == null)
+        {
+            return;
+        }
+
+        var config = DynamicAssembly.CreateInstance(dynamicInfo.ConfigType);
+
+        for (var i = 0; i < cols.Count; i++)
+        {
+            string colType;
+            var colIndex = cols[i];
+            var colName = excelWorksheet.GetCellValue(5, colIndex);
+            var value = excelWorksheet.GetCellValue(row, colIndex);
+
+            if (isServer)
+            {
+                colType = excelWorksheet.GetCellValue(1, colIndex);
+
+                if (IsNullOrEmpty(colType) || colType == "0")
+                {
+                    colType = excelWorksheet.GetCellValue(2, colIndex);
+                }
+            }
+            else
+            {
+                colType = excelWorksheet.GetCellValue(2, colIndex);
+            }
+
+            try
+            {
+                SetNewValue(dynamicInfo.ConfigType.GetProperty(colName), config, colType, value);
+            }
+            catch (Exception e)
+            {
+                Log.Error(
+                    $"Error Table {fileInfoFullName} Col:{colName} colType:{colType} Row:{row} value:{value} {e}");
+                throw;
+            }
+        }
+
+        dynamicInfo.Method.Invoke(dynamicInfo.Obj, new object[] { config });
+
+        var json = JsonConvert.SerializeObject(config);
+
+        if (isLast)
+        {
+            dynamicInfo.Json.AppendLine(json);
+        }
+        else
+        {
+            dynamicInfo.Json.AppendLine($"{json},");
+        }
+    }
+
+
+    /// <summary>
+    /// 从 Excel 文件加载工作表并返回 ExcelWorksheet 对象。
+    /// </summary>
+    /// <param name="name">工作表的名称或文件路径。</param>
+    /// <param name="isAddToDic">是否将加载的工作表添加到缓存字典中。</param>
+    /// <returns>表示 Excel 工作表的 ExcelWorksheet 对象。</returns>
+    public ExcelWorksheet LoadExcel(string name, bool isAddToDic)
+    {
+        if (Worksheets.TryGetValue(name, out var worksheet))
+        {
+            return worksheet;
+        }
+
+        var workbookWorksheets = ExcelHelper.LoadExcel(name).Workbook.Worksheets;
+        worksheet = workbookWorksheets[0];
+
+        if (isAddToDic)
+        {
+            Worksheets.TryAdd(name, worksheet);
+
+            foreach (var workbookWorksheet in workbookWorksheets)
+            {
+                try
+                {
+                    var hash = HashCodeHelper.ComputeHash64(workbookWorksheet.Name);
+                    VersionInfo.WorksheetNames.Add(hash);
+                }
+                catch (Exception e)
+                {
+                    Console.WriteLine(e);
+                }
+
+                Worksheets.TryAdd(workbookWorksheet.Name, workbookWorksheet);
+            }
+        }
+
+        Log.Info(name);
+        return workbookWorksheets[0];
+    }
+
+    /// <summary>
+    /// 写入到cs
+    /// </summary>
+    /// <param name="colInfos"></param>
+    /// <param name="exportPath"></param>
+    /// <param name="isServer"></param>
+    private void WriteToClass(TableDictionary colInfos, string exportPath, bool isServer)
+    {
+        if (colInfos.Count <= 0)
+        {
+            return;
+        }
+
+        var index = 0;
+        var fileBuilder = new StringBuilder();
+        var colNameSet = new HashSet<string>();
+
+        if (colInfos.Count == 0)
+        {
+            return;
+        }
+
+        var csName = Path.GetFileNameWithoutExtension(colInfos.First().Key)?.Split('_')[0];
+
+        foreach (var (tableName, cols) in colInfos)
+        {
+            if (cols == null || cols.Count == 0)
+            {
+                continue;
+            }
+
+            var excelWorksheet = LoadExcel(tableName, false);
+
+            foreach (var colIndex in cols)
+            {
+                var colName = excelWorksheet.GetCellValue(5, colIndex);
+
+                if (colNameSet.Contains(colName))
+                {
+                    continue;
+                }
+
+                colNameSet.Add(colName);
+
+                string colType;
+
+                if (isServer)
+                {
+                    colType = excelWorksheet.GetCellValue(1, colIndex);
+
+                    if (IsNullOrEmpty(colType) || colType == "0")
+                    {
+                        colType = excelWorksheet.GetCellValue(2, colIndex);
+                    }
+                }
+                else
+                {
+                    colType = excelWorksheet.GetCellValue(2, colIndex);
+                }
+
+                var remarks = excelWorksheet.GetCellValue(4, colIndex);
+
+                // 解决不同平台换行符不一致的问题
+
+                switch (Environment.OSVersion.Platform)
+                {
+                    case PlatformID.Win32NT:
+                    case PlatformID.Win32S:
+                    case PlatformID.Win32Windows:
+                    case PlatformID.WinCE:
+                    {
+                        fileBuilder.Append($"\r\n\t\t[ProtoMember({++index})]\r\n");
+                        break;
+                    }
+                    default:
+                    {
+                        fileBuilder.Append($"\n\t\t[ProtoMember({++index})]\n");
+                        break;
+                    }
+                }
+
+                fileBuilder.Append(
+                    IsArray(colType, out var t)
+                        ? $"\t\tpublic {colType} {colName} {{ get; set; }} = Array.Empty<{t}>(); // {remarks}"
+                        : $"\t\tpublic {colType} {colName} {{ get; set; }} // {remarks}");
+            }
+        }
+
+        var template = ExcelTemplate.Template;
+
+        if (fileBuilder.Length > 0)
+        {
+            if (!Directory.Exists(exportPath))
+            {
+                FileHelper.CreateDirectory(exportPath);
+            }
+
+            var content = template.Replace("(namespace)", "Fantasy")
+                .Replace("(ConfigName)", csName)
+                .Replace("(Fields)", fileBuilder.ToString());
+            File.WriteAllText(Path.Combine(exportPath, $"{csName}.cs"), content);
+        }
+    }
+
+    private void SetNewValue(PropertyInfo propertyInfo, object config, string type, string value)
+    {
+        if (IsNullOrWhiteSpace(value))
+        {
+            return;
+        }
+
+        switch (type)
+        {
+            case "short":
+            {
+                propertyInfo.SetValue(config, Convert.ToInt16(value));
+                return;
+            }
+            case "ushort":
+            {
+                propertyInfo.SetValue(config, Convert.ToUInt16(value));
+                return;
+            }
+            case "uint":
+            {
+                propertyInfo.SetValue(config, Convert.ToUInt32(value));
+                return;
+            }
+            case "int":
+            {
+                propertyInfo.SetValue(config, Convert.ToInt32(value));
+                return;
+            }
+            case "decimal":
+            {
+                propertyInfo.SetValue(config, Convert.ToDecimal(value));
+                return;
+            }
+            case "string":
+            {
+                try
+                {
+                    propertyInfo.SetValue(config, value);
+                }
+                catch (Exception e)
+                {
+                    Console.WriteLine(e);
+                    throw;
+                }
+
+                return;
+            }
+            case "bool":
+            {
+                // 空字符串
+
+                value = value.ToLower();
+
+                if (IsNullOrEmpty(value))
+                {
+                    propertyInfo.SetValue(config, false);
+                }
+                else if (bool.TryParse(value, out bool b))
+                {
+                    propertyInfo.SetValue(config, b);
+                }
+                else if (int.TryParse(value, out int v))
+                {
+                    propertyInfo.SetValue(config, v != 0);
+                }
+                else
+                {
+                    propertyInfo.SetValue(config, false);
+                }
+
+                return;
+            }
+            case "ulong":
+            {
+                propertyInfo.SetValue(config, Convert.ToUInt64(value));
+                return;
+            }
+            case "long":
+            {
+                propertyInfo.SetValue(config, Convert.ToInt64(value));
+                return;
+            }
+            case "double":
+            {
+                propertyInfo.SetValue(config, Convert.ToDouble(value));
+                return;
+            }
+            case "float":
+            {
+                propertyInfo.SetValue(config, Convert.ToSingle(value));
+                return;
+            }
+            case "int32[]":
+            case "int[]":
+            {
+                if (value != "0")
+                {
+                    propertyInfo.SetValue(config, value.Split(",").Select(d => Convert.ToInt32(d)).ToArray());
+                }
+
+                return;
+            }
+            case "uint[]":
+            {
+                if (value != "0")
+                {
+                    propertyInfo.SetValue(config, value.Split(",").Select(d => Convert.ToUInt32(d)).ToArray());
+                }
+
+                return;
+            }
+            case "long[]":
+            {
+                if (value != "0")
+                {
+                    propertyInfo.SetValue(config, value.Split(",").Select(d => Convert.ToInt64(d)).ToArray());
+                }
+
+                return;
+            }
+            case "double[]":
+            {
+                if (value != "0")
+                {
+                    propertyInfo.SetValue(config, value.Split(",").Select(d => Convert.ToDouble(d)).ToArray());
+                }
+
+                return;
+            }
+            case "string[]":
+            {
+                if (value == "0")
+                {
+                    return;
+                }
+
+                var list = value.Split(",").ToArray();
+
+                for (var i = 0; i < list.Length; i++)
+                {
+                    list[i] = list[i].Replace("\"", "");
+                }
+
+                propertyInfo.SetValue(config, value.Split(",").ToArray());
+
+                return;
+            }
+            case "float[]":
+            {
+                if (value != "0")
+                {
+                    propertyInfo.SetValue(config, value.Split(",").Select(d => Convert.ToSingle(d)).ToArray());
+                }
+
+                return;
+            }
+            case "IntDictionaryConfig":
+            {
+                if (value.Trim() == "" || value.Trim() == "{}")
+                {
+                    propertyInfo.SetValue(config, null);
+                    return;
+                }
+
+                var attr = new IntDictionaryConfig { Dic = JsonConvert.DeserializeObject<Dictionary<int, int>>(value) };
+
+                propertyInfo.SetValue(config, attr);
+
+                return;
+            }
+            case "StringDictionaryConfig":
+            {
+                if (value.Trim() == "" || value.Trim() == "{}")
+                {
+                    propertyInfo.SetValue(config, null);
+                    return;
+                }
+
+                var attr = new StringDictionaryConfig
+                    { Dic = JsonConvert.DeserializeObject<Dictionary<int, string>>(value) };
+
+                propertyInfo.SetValue(config, attr);
+
+                return;
+            }
+            default:
+                throw new NotSupportedException($"不支持此类型: {type}");
+        }
+    }
+
+    private bool IsArray(string type, out string t)
+    {
+        t = null;
+        var index = type.IndexOf("[]", StringComparison.Ordinal);
+
+        if (index >= 0)
+        {
+            t = type.Remove(index, 2);
+        }
+
+        return index >= 0;
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelHelper.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelHelper.cs
new file mode 100644
index 0000000..3ef64d4
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelHelper.cs
@@ -0,0 +1,47 @@
+using OfficeOpenXml;
+
+namespace NBConfigBuilder;
+
+/// <summary>
+/// 提供操作 Excel 文件的辅助方法。
+/// </summary>
+public static class ExcelHelper
+{
+    /// <summary>
+    /// 加载 Excel 文件并返回 ExcelPackage 实例。
+    /// </summary>
+    /// <param name="name">Excel 文件的路径。</param>
+    /// <returns>ExcelPackage 实例。</returns>
+    public static ExcelPackage LoadExcel(string name)
+    {
+        return new ExcelPackage(name);
+    }
+
+    /// <summary>
+    /// 获取指定工作表中指定行列位置的单元格值。
+    /// </summary>
+    /// <param name="sheet">Excel 工作表。</param>
+    /// <param name="row">行索引。</param>
+    /// <param name="column">列索引。</param>
+    /// <returns>单元格值。</returns>
+    public static string GetCellValue(this ExcelWorksheet sheet, int row, int column)
+    {
+        ExcelRange cell = sheet.Cells[row, column];
+            
+        try
+        {
+            if (cell.Value == null)
+            {
+                return "";
+            }
+
+            string s = cell.GetValue<string>();
+                
+            return s.Trim();
+        }
+        catch (Exception e)
+        {
+            throw new Exception($"Rows {row} Columns {column} Content {cell.Text} {e}");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelTable.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelTable.cs
new file mode 100644
index 0000000..20f0558
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelTable.cs
@@ -0,0 +1,28 @@
+namespace NBConfigBuilder;
+
+/// <summary>
+/// Excel表格类，用于存储表格的名称和列信息。
+/// </summary>
+public sealed class ExcelTable
+{
+    /// <summary>
+    /// 表格的名称。
+    /// </summary>
+    public readonly string Name;
+    /// <summary>
+    /// 客户端列信息，使用排序字典存储列名和列索引列表。
+    /// </summary>
+    public readonly SortedDictionary<string, List<int>> ClientColInfos = new();
+    /// <summary>
+    /// 服务器端列信息，使用排序字典存储列名和列索引列表。
+    /// </summary>
+    public readonly SortedDictionary<string, List<int>> ServerColInfos = new();
+    /// <summary>
+    /// 构造函数，初始化Excel表格对象并设置表格名称。
+    /// </summary>
+    /// <param name="name">表格名称。</param>
+    public ExcelTable(string name)
+    {
+        Name = name;
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelTemplate.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelTemplate.cs
new file mode 100644
index 0000000..c3f67ff
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelTemplate.cs
@@ -0,0 +1,98 @@
+namespace NBConfigBuilder;
+
+public static class ExcelTemplate
+{
+    public static readonly string Template = """
+                                             using System;
+                                             using ProtoBuf;
+                                             using Fantasy;
+                                             using System.Linq;
+                                             using System.Reflection;
+                                             using System.Collections.Generic;
+                                             using System.Collections.Concurrent;
+                                             using Fantasy.ConfigTable;
+                                             using Fantasy.Serialize;
+                                             // ReSharper disable CollectionNeverUpdated.Global
+                                             // ReSharper disable UnusedAutoPropertyAccessor.Global
+                                             #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+                                             #pragma warning disable CS0169
+                                             #pragma warning disable CS8618
+                                             #pragma warning disable CS8625
+                                             #pragma warning disable CS8603
+                                             
+                                             namespace (namespace)
+                                             {
+                                                 [ProtoContract]
+                                                 public sealed partial class (ConfigName)Data : ASerialize, IConfigTable, IProto
+                                                 {
+                                                     [ProtoMember(1)]
+                                                     public List<(ConfigName)> List { get; set; } = new List<(ConfigName)>();
+                                             #if FANTASY_NET
+                                                     [ProtoIgnore]
+                                                     private readonly ConcurrentDictionary<uint, (ConfigName)> _configs = new ConcurrentDictionary<uint, (ConfigName)>();
+                                             #else 
+                                                     [ProtoIgnore]
+                                                     private readonly Dictionary<uint, (ConfigName)> _configs = new Dictionary<uint, (ConfigName)>();
+                                             #endif
+                                                     private static (ConfigName)Data _instance = null;
+                                             
+                                                     public static (ConfigName)Data Instance
+                                                     {
+                                                         get { return _instance ??= ConfigTableHelper.Load<(ConfigName)Data>(); } 
+                                                         private set => _instance = value;
+                                                     }
+                                             
+                                                     public (ConfigName) Get(uint id, bool check = true)
+                                                     {
+                                                         if (_configs.ContainsKey(id))
+                                                         {
+                                                             return _configs[id];
+                                                         }
+                                                 
+                                                         if (check)
+                                                         {
+                                                             throw new Exception($"(ConfigName) not find {id} Id");
+                                                         }
+                                                         
+                                                         return null;
+                                                     }
+                                                     public bool TryGet(uint id, out (ConfigName) config)
+                                                     {
+                                                         config = null;
+                                                         
+                                                         if (!_configs.ContainsKey(id))
+                                                         {
+                                                             return false;
+                                                         }
+                                                             
+                                                         config = _configs[id];
+                                                         return true;
+                                                     }
+                                                     public override void AfterDeserialization()
+                                                     {
+                                                         foreach (var config in List)
+                                                         {
+                                             #if FANTASY_NET
+                                                             _configs.TryAdd(config.Id, config);
+                                             #else
+                                                             _configs.Add(config.Id, config);
+                                             #endif
+                                                             config.AfterDeserialization();
+                                                         }
+                                                 
+                                                         EndInit();
+                                                     }
+                                                     
+                                                     public override void Dispose()
+                                                     {
+                                                         Instance = null;
+                                                     }
+                                                 }
+                                                 
+                                                 [ProtoContract]
+                                                 public sealed partial class (ConfigName) : ASerialize, IProto
+                                                 {(Fields)  
+                                                 } 
+                                             }  
+                                             """;
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelWorksheets.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelWorksheets.cs
new file mode 100644
index 0000000..cf4277a
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExcelWorksheets.cs
@@ -0,0 +1,22 @@
+using OfficeOpenXml;
+
+namespace NBConfigBuilder;
+
+public sealed class ExcelWorksheets(ExcelExporter excelExporter)
+{
+    public bool TryGetValue(string worksheetName, out ExcelWorksheet excelWorksheet)
+    {
+        if (excelExporter.Worksheets.TryGetValue(worksheetName, out excelWorksheet))
+        {
+            return true;
+        }
+
+        var computeHash64 = HashCodeHelper.ComputeHash64(worksheetName);
+        if (!excelExporter.VersionInfo.WorksheetNames.Contains(computeHash64))
+        {
+            Log.Info($"{worksheetName} is not exist!");
+        }
+        
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExportInfo.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExportInfo.cs
new file mode 100644
index 0000000..d9d7b91
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExportInfo.cs
@@ -0,0 +1,17 @@
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+namespace NBConfigBuilder;
+
+/// <summary>
+/// 导出信息类，用于存储导出操作的名称和文件信息。
+/// </summary>
+public class ExportInfo
+{
+    /// <summary>
+    /// 导出操作的名称。
+    /// </summary>
+    public string Name;
+    /// <summary>
+    /// 导出操作生成的文件信息。
+    /// </summary>
+    public FileInfo FileInfo;
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExportType.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExportType.cs
new file mode 100644
index 0000000..348a9e6
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/ExportType.cs
@@ -0,0 +1,24 @@
+namespace NBConfigBuilder;
+
+/// <summary>
+/// 导出类型枚举，用于标识不同类型的导出操作。
+/// </summary>
+public enum ExportType
+{
+    /// <summary>
+    /// 无导出类型。
+    /// </summary>
+    None = 0, 
+    /// <summary>
+    /// 所有数据的增量导出Excel类型。
+    /// </summary>
+    AllExcelIncrement = 1,
+    /// <summary>
+    /// 所有数据的全量导出Excel类型。
+    /// </summary>
+    AllExcel = 2,
+    /// <summary>
+    /// 导出类型枚举的最大值，一定要放在最后。
+    /// </summary>
+    Max,
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Exporter/VersionInfo.cs b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/VersionInfo.cs
new file mode 100644
index 0000000..c04cd9f
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Exporter/VersionInfo.cs
@@ -0,0 +1,7 @@
+namespace NBConfigBuilder;
+
+public class VersionInfo
+{
+    public SortedSet<long> WorksheetNames = [];
+    public SortedDictionary<long, long> Tables = new();
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Form1.Designer.cs b/Tools/ConfigBuilder/NBConfigBuilder/Form1.Designer.cs
new file mode 100644
index 0000000..b1a50ee
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Form1.Designer.cs
@@ -0,0 +1,265 @@
+﻿namespace NBConfigBuilder
+{
+    partial class Form1
+    {
+        /// <summary>
+        ///  Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        ///  Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        ///  Required method for Designer support - do not modify
+        ///  the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            textBoxExcelPath = new TextBox();
+            buttonSelectExcelPath = new Button();
+            label1 = new Label();
+            textBoxClientGenPath = new TextBox();
+            buttonSelectClientPath = new Button();
+            checkBoxGenClient = new CheckBox();
+            label2 = new Label();
+            textBoxServerGenPath = new TextBox();
+            label3 = new Label();
+            checkBoxGenServer = new CheckBox();
+            buttonSelectServerPath = new Button();
+            buttonRun = new Button();
+            textBoxClientGenJsonPath = new TextBox();
+            label4 = new Label();
+            buttonSelectClientJsonPath = new Button();
+            textBoxServerGenJsonPath = new TextBox();
+            label5 = new Label();
+            buttonSelectServerJsonPath = new Button();
+            SuspendLayout();
+            // 
+            // textBoxExcelPath
+            // 
+            textBoxExcelPath.Location = new Point(84, 13);
+            textBoxExcelPath.Name = "textBoxExcelPath";
+            textBoxExcelPath.Size = new Size(322, 23);
+            textBoxExcelPath.TabIndex = 0;
+            // 
+            // buttonSelectExcelPath
+            // 
+            buttonSelectExcelPath.Location = new Point(412, 13);
+            buttonSelectExcelPath.Name = "buttonSelectExcelPath";
+            buttonSelectExcelPath.Size = new Size(75, 23);
+            buttonSelectExcelPath.TabIndex = 1;
+            buttonSelectExcelPath.Text = "选择";
+            buttonSelectExcelPath.UseVisualStyleBackColor = true;
+            buttonSelectExcelPath.Click += buttonSelectExcelPath_Click;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Location = new Point(7, 17);
+            label1.Name = "label1";
+            label1.Size = new Size(68, 17);
+            label1.TabIndex = 2;
+            label1.Text = "配置表路径";
+            // 
+            // textBoxClientGenPath
+            // 
+            textBoxClientGenPath.Location = new Point(84, 42);
+            textBoxClientGenPath.Name = "textBoxClientGenPath";
+            textBoxClientGenPath.Size = new Size(318, 23);
+            textBoxClientGenPath.TabIndex = 3;
+            // 
+            // buttonSelectClientPath
+            // 
+            buttonSelectClientPath.Location = new Point(412, 42);
+            buttonSelectClientPath.Name = "buttonSelectClientPath";
+            buttonSelectClientPath.Size = new Size(75, 23);
+            buttonSelectClientPath.TabIndex = 4;
+            buttonSelectClientPath.Text = "选择";
+            buttonSelectClientPath.UseVisualStyleBackColor = true;
+            buttonSelectClientPath.Click += buttonSelectClientPath_Click;
+            // 
+            // checkBoxGenClient
+            // 
+            checkBoxGenClient.AutoSize = true;
+            checkBoxGenClient.Checked = true;
+            checkBoxGenClient.CheckState = CheckState.Checked;
+            checkBoxGenClient.Location = new Point(495, 44);
+            checkBoxGenClient.Name = "checkBoxGenClient";
+            checkBoxGenClient.Size = new Size(87, 21);
+            checkBoxGenClient.TabIndex = 5;
+            checkBoxGenClient.Text = "生产服务端";
+            checkBoxGenClient.UseVisualStyleBackColor = true;
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Location = new Point(7, 47);
+            label2.Name = "label2";
+            label2.Size = new Size(68, 17);
+            label2.TabIndex = 6;
+            label2.Text = "客户端代码";
+            // 
+            // textBoxServerGenPath
+            // 
+            textBoxServerGenPath.Location = new Point(84, 100);
+            textBoxServerGenPath.Name = "textBoxServerGenPath";
+            textBoxServerGenPath.Size = new Size(318, 23);
+            textBoxServerGenPath.TabIndex = 7;
+            // 
+            // label3
+            // 
+            label3.AutoSize = true;
+            label3.Location = new Point(7, 103);
+            label3.Name = "label3";
+            label3.Size = new Size(68, 17);
+            label3.TabIndex = 8;
+            label3.Text = "服务端代码";
+            // 
+            // checkBoxGenServer
+            // 
+            checkBoxGenServer.AutoSize = true;
+            checkBoxGenServer.Checked = true;
+            checkBoxGenServer.CheckState = CheckState.Checked;
+            checkBoxGenServer.Location = new Point(495, 16);
+            checkBoxGenServer.Name = "checkBoxGenServer";
+            checkBoxGenServer.Size = new Size(87, 21);
+            checkBoxGenServer.TabIndex = 9;
+            checkBoxGenServer.Text = "生产客户端";
+            checkBoxGenServer.UseVisualStyleBackColor = true;
+            // 
+            // buttonSelectServerPath
+            // 
+            buttonSelectServerPath.Location = new Point(412, 100);
+            buttonSelectServerPath.Name = "buttonSelectServerPath";
+            buttonSelectServerPath.Size = new Size(75, 23);
+            buttonSelectServerPath.TabIndex = 10;
+            buttonSelectServerPath.Text = "选择";
+            buttonSelectServerPath.UseVisualStyleBackColor = true;
+            buttonSelectServerPath.Click += buttonSelectServerPath_Click;
+            // 
+            // buttonRun
+            // 
+            buttonRun.Location = new Point(495, 71);
+            buttonRun.Name = "buttonRun";
+            buttonRun.Size = new Size(80, 81);
+            buttonRun.TabIndex = 12;
+            buttonRun.Text = "执行";
+            buttonRun.UseVisualStyleBackColor = true;
+            buttonRun.Click += buttonRun_Click;
+            // 
+            // textBoxClientGenJsonPath
+            // 
+            textBoxClientGenJsonPath.Location = new Point(84, 71);
+            textBoxClientGenJsonPath.Name = "textBoxClientGenJsonPath";
+            textBoxClientGenJsonPath.Size = new Size(318, 23);
+            textBoxClientGenJsonPath.TabIndex = 13;
+            // 
+            // label4
+            // 
+            label4.AutoSize = true;
+            label4.Location = new Point(7, 77);
+            label4.Name = "label4";
+            label4.Size = new Size(68, 17);
+            label4.TabIndex = 14;
+            label4.Text = "客户端配置";
+            // 
+            // buttonSelectClientJsonPath
+            // 
+            buttonSelectClientJsonPath.Location = new Point(412, 71);
+            buttonSelectClientJsonPath.Name = "buttonSelectClientJsonPath";
+            buttonSelectClientJsonPath.Size = new Size(75, 23);
+            buttonSelectClientJsonPath.TabIndex = 15;
+            buttonSelectClientJsonPath.Text = "选择";
+            buttonSelectClientJsonPath.UseVisualStyleBackColor = true;
+            buttonSelectClientJsonPath.Click += buttonSelectClientJsonPath_Click;
+            // 
+            // textBoxServerGenJsonPath
+            // 
+            textBoxServerGenJsonPath.Location = new Point(85, 129);
+            textBoxServerGenJsonPath.Name = "textBoxServerGenJsonPath";
+            textBoxServerGenJsonPath.Size = new Size(317, 23);
+            textBoxServerGenJsonPath.TabIndex = 16;
+            // 
+            // label5
+            // 
+            label5.AutoSize = true;
+            label5.Location = new Point(7, 132);
+            label5.Name = "label5";
+            label5.Size = new Size(68, 17);
+            label5.TabIndex = 17;
+            label5.Text = "服务端配置";
+            // 
+            // buttonSelectServerJsonPath
+            // 
+            buttonSelectServerJsonPath.Location = new Point(412, 129);
+            buttonSelectServerJsonPath.Name = "buttonSelectServerJsonPath";
+            buttonSelectServerJsonPath.Size = new Size(75, 23);
+            buttonSelectServerJsonPath.TabIndex = 18;
+            buttonSelectServerJsonPath.Text = "选择";
+            buttonSelectServerJsonPath.UseVisualStyleBackColor = true;
+            buttonSelectServerJsonPath.Click += buttonSelectServerJsonPath_Click;
+            // 
+            // Form1
+            // 
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            ClientSize = new Size(585, 161);
+            Controls.Add(buttonSelectServerJsonPath);
+            Controls.Add(label5);
+            Controls.Add(textBoxServerGenJsonPath);
+            Controls.Add(buttonSelectClientJsonPath);
+            Controls.Add(label4);
+            Controls.Add(textBoxClientGenJsonPath);
+            Controls.Add(buttonRun);
+            Controls.Add(buttonSelectServerPath);
+            Controls.Add(checkBoxGenServer);
+            Controls.Add(label3);
+            Controls.Add(textBoxServerGenPath);
+            Controls.Add(label2);
+            Controls.Add(checkBoxGenClient);
+            Controls.Add(buttonSelectClientPath);
+            Controls.Add(textBoxClientGenPath);
+            Controls.Add(label1);
+            Controls.Add(buttonSelectExcelPath);
+            Controls.Add(textBoxExcelPath);
+            Name = "Form1";
+            Text = "配置生成导出";
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private TextBox textBoxExcelPath;
+        private Button buttonSelectExcelPath;
+        private Label label1;
+        private TextBox textBoxClientGenPath;
+        private Button buttonSelectClientPath;
+        private CheckBox checkBoxGenClient;
+        private Label label2;
+        private TextBox textBoxServerGenPath;
+        private Label label3;
+        private CheckBox checkBoxGenServer;
+        private Button buttonSelectServerPath;
+        private Button buttonRun;
+        private TextBox textBoxClientGenJsonPath;
+        private Label label4;
+        private Button buttonSelectClientJsonPath;
+        private TextBox textBoxServerGenJsonPath;
+        private Label label5;
+        private Button buttonSelectServerJsonPath;
+    }
+}
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Form1.cs b/Tools/ConfigBuilder/NBConfigBuilder/Form1.cs
new file mode 100644
index 0000000..c41e3c9
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Form1.cs
@@ -0,0 +1,141 @@
+using System.Text.Json;
+
+namespace NBConfigBuilder
+{
+    public partial class Form1 : Form
+    {
+        // 配置文件路径
+        private readonly string configPath =
+            Path.Combine(Path.GetDirectoryName(Application.ExecutablePath) ?? string.Empty, "config.json");
+
+        public Form1()
+        {
+            InitializeComponent();
+            // 设置窗口大小不可变
+            this.FormBorderStyle = FormBorderStyle.FixedSingle;
+            this.MaximizeBox = false;
+
+            // 加载保存的配置
+            LoadConfig();
+        }
+
+        private void buttonRun_Click(object sender, EventArgs e)
+        {
+            // 保存当前配置
+            SaveConfig();
+            new ExcelExporter(ExportType.AllExcel).Run();
+        }
+
+        private void buttonSelectExcelPath_Click(object sender, EventArgs e)
+        {
+            using (FolderBrowserDialog folderDlg = new FolderBrowserDialog())
+            {
+                folderDlg.Description = "请选择配置表路径";
+                if (folderDlg.ShowDialog() == DialogResult.OK)
+                {
+                    textBoxExcelPath.Text = folderDlg.SelectedPath;
+                }
+            }
+        }
+
+        private void buttonSelectClientJsonPath_Click(object sender, EventArgs e)
+        {
+            using (FolderBrowserDialog folderDlg = new FolderBrowserDialog())
+            {
+                folderDlg.Description = @"选择客户端json保存目录";
+                if (folderDlg.ShowDialog() == DialogResult.OK)
+                {
+                    textBoxClientGenJsonPath.Text = folderDlg.SelectedPath;
+                }
+            }
+        }
+
+        private void buttonSelectServerJsonPath_Click(object sender, EventArgs e)
+        {
+            using (FolderBrowserDialog folderDlg = new FolderBrowserDialog())
+            {
+                folderDlg.Description = @"选择服务端json保存目录";
+                if (folderDlg.ShowDialog() == DialogResult.OK)
+                {
+                    textBoxServerGenJsonPath.Text = folderDlg.SelectedPath;
+                }
+            }
+        }
+
+        private void buttonSelectClientPath_Click(object sender, EventArgs e)
+        {
+            using (FolderBrowserDialog folderDlg = new FolderBrowserDialog())
+            {
+                folderDlg.Description = @"选择客户端代码保存目录";
+                if (folderDlg.ShowDialog() == DialogResult.OK)
+                {
+                    textBoxClientGenPath.Text = folderDlg.SelectedPath;
+                }
+            }
+        }
+
+        private void buttonSelectServerPath_Click(object sender, EventArgs e)
+        {
+            using (FolderBrowserDialog folderDlg = new FolderBrowserDialog())
+            {
+                folderDlg.Description = @"选择服务端代码保存目录";
+                if (folderDlg.ShowDialog() == DialogResult.OK)
+                {
+                    textBoxServerGenPath.Text = folderDlg.SelectedPath;
+                }
+            }
+        }
+
+        // 添加保存和加载配置的方法
+        private void SaveConfig()
+        {
+            var config = new AppConfig
+            {
+                ExcelPath = textBoxExcelPath.Text,
+                ClientPath = textBoxClientGenPath.Text,
+                ClientJsonPath = textBoxClientGenJsonPath.Text,
+                ServerPath = textBoxServerGenPath.Text,
+                ServerJsonPath = textBoxServerGenJsonPath.Text,
+                GenClient = checkBoxGenClient.Checked,
+                GenServer = checkBoxGenServer.Checked,
+            };
+            App.Config = config;
+            try
+            {
+                string json = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true });
+                File.WriteAllText(configPath, json);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show($"保存配置失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            }
+        }
+
+        private void LoadConfig()
+        {
+            if (!File.Exists(configPath)) return;
+
+            try
+            {
+                string json = File.ReadAllText(configPath);
+                var config = JsonSerializer.Deserialize<AppConfig>(json);
+
+                if (config != null)
+                {
+                    App.Config = config;
+                    textBoxExcelPath.Text = config.ExcelPath ?? "";
+                    textBoxClientGenPath.Text = config.ClientPath ?? "";
+                    textBoxServerGenPath.Text = config.ServerPath ?? "";
+                    checkBoxGenClient.Checked = config.GenClient;
+                    checkBoxGenServer.Checked = config.GenServer;
+                    textBoxClientGenJsonPath.Text = config.ClientJsonPath ?? "";
+                    textBoxServerGenJsonPath.Text = config.ServerJsonPath ?? "";
+                }
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show($"加载配置失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Form1.resx b/Tools/ConfigBuilder/NBConfigBuilder/Form1.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Form1.resx
@@ -0,0 +1,120 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Log.cs b/Tools/ConfigBuilder/NBConfigBuilder/Log.cs
new file mode 100644
index 0000000..6da4ad0
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Log.cs
@@ -0,0 +1,97 @@
+using NLog;
+using System;
+using System.Diagnostics;
+
+namespace NBConfigBuilder
+{
+    public static class Log
+    {
+        private static readonly Logger logger = LogManager.GetCurrentClassLogger();
+
+        static Log()
+        {
+        }
+
+        /// <summary>
+        /// 记录信息级别的日志消息。
+        /// </summary>
+        /// <param name="msg">日志消息。</param>
+        public static void Info(string msg)
+        {
+            logger.Info(msg);
+        }
+
+        /// <summary>
+        /// 记录错误级别的日志消息，并附带调用栈信息。
+        /// </summary>
+        /// <param name="msg">日志消息。</param>
+        public static void Error(string msg)
+        {
+            var st = new StackTrace(1, true);
+            logger.Error($"{msg}\n{st}");
+        }
+
+        /// <summary>
+        /// 记录异常的错误级别的日志消息，并附带调用栈信息。
+        /// </summary>
+        /// <param name="e">异常对象。</param>
+        public static void Error(Exception e)
+        {
+            if (e.Data.Contains("StackTrace"))
+            {
+                logger.Error($"{e.Data["StackTrace"]}\n{e}");
+                return;
+            }
+
+            var str = e.ToString();
+            logger.Error(str);
+        }
+
+        /// <summary>
+        /// 记录信息级别的格式化日志消息。
+        /// </summary>
+        /// <param name="message">日志消息模板。</param>
+        /// <param name="args">格式化参数。</param>
+        public static void Info(string message, params object[] args)
+        {
+            logger.Info(message, args);
+        }
+
+        /// <summary>
+        /// 记录调试级别的日志消息。
+        /// </summary>
+        /// <param name="msg">日志消息。</param>
+        public static void Debug(string msg)
+        {
+            logger.Debug(msg);
+        }
+
+        /// <summary>
+        /// 记录警告级别的日志消息。
+        /// </summary>
+        /// <param name="msg">日志消息。</param>
+        public static void Warn(string msg)
+        {
+            logger.Warn(msg);
+        }
+
+        /// <summary>
+        /// 记录严重错误级别的日志消息。
+        /// </summary>
+        /// <param name="msg">日志消息。</param>
+        public static void Fatal(string msg)
+        {
+            logger.Fatal(msg);
+        }
+
+        /// <summary>
+        /// 记录异常的错误级别的日志消息。
+        /// </summary>
+        /// <param name="e">异常对象。</param>
+        /// <param name="message">附加消息。</param>
+        public static void Error(Exception e, string message)
+        {
+            logger.Error(e, message);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/NBConfigBuilder.csproj b/Tools/ConfigBuilder/NBConfigBuilder/NBConfigBuilder.csproj
new file mode 100644
index 0000000..dea1755
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/NBConfigBuilder.csproj
@@ -0,0 +1,25 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>WinExe</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <Nullable>disable</Nullable>
+    <UseWindowsForms>true</UseWindowsForms>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="EPPlus" Version="8.2.0" />
+    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
+    <PackageReference Include="NLog" Version="6.0.4" />
+    <PackageReference Include="protobuf-net" Version="3.2.56" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <None Update="NLog.config">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/NBConfigBuilder.csproj.user b/Tools/ConfigBuilder/NBConfigBuilder/NBConfigBuilder.csproj.user
new file mode 100644
index 0000000..7814ea2
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/NBConfigBuilder.csproj.user
@@ -0,0 +1,8 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <ItemGroup>
+        <Compile Update="Form1.cs">
+            <SubType>Form</SubType>
+        </Compile>
+    </ItemGroup>
+</Project>
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/NLog.config b/Tools/ConfigBuilder/NBConfigBuilder/NLog.config
new file mode 100644
index 0000000..4bd1557
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/NLog.config
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+  <targets>
+    <!-- 文件目标 -->
+    <target xsi:type="File" 
+            name="fileTarget"
+            fileName="logs/${shortdate}.log"
+            layout="${longdate} ${uppercase:${level}} ${message} ${exception:format=ToString}" />
+    
+    <!-- 控制台目标 -->
+    <target xsi:type="Console"
+            name="consoleTarget"
+            layout="${longdate} ${uppercase:${level}} ${message} ${exception:format=ToString}" />
+  </targets>
+
+  <rules>
+    <!-- 记录所有级别高于 Debug 的日志到文件 -->
+    <logger name="*" minlevel="Debug" writeTo="fileTarget" />
+    
+    <!-- 记录所有级别高于 Info 的日志到控制台 -->
+    <logger name="*" minlevel="Info" writeTo="consoleTarget" />
+  </rules>
+</nlog>
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Program.cs b/Tools/ConfigBuilder/NBConfigBuilder/Program.cs
new file mode 100644
index 0000000..a3718e5
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Program.cs
@@ -0,0 +1,25 @@
+using NLog;
+
+namespace NBConfigBuilder
+{
+    internal static class Program
+    {
+        /// <summary>
+        ///  The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            // 配置NLog
+            var logger = LogManager.GetCurrentClassLogger();
+            logger.Info("Application started");
+            
+            // To customize application configuration such as set high DPI settings or default font,
+            // see https://aka.ms/applicationconfiguration.
+            ApplicationConfiguration.Initialize();
+            Application.Run(new Form1());
+            
+            logger.Info("Application closing");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Utils/FileHelper.cs b/Tools/ConfigBuilder/NBConfigBuilder/Utils/FileHelper.cs
new file mode 100644
index 0000000..db846ad
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Utils/FileHelper.cs
@@ -0,0 +1,182 @@
+using System.Text;
+
+namespace NBConfigBuilder;
+
+/// <summary>
+/// 文件操作助手类，提供了各种文件操作方法。
+/// </summary>
+public static partial class FileHelper
+{
+    /// <summary>
+    /// 获取相对路径的完整路径。
+    /// </summary>
+    /// <param name="relativePath">相对路径。</param>
+    /// <returns>完整路径。</returns>
+    public static string GetFullPath(string relativePath)
+    {
+        return Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), relativePath));
+    }
+
+    /// <summary>
+    /// 获取相对路径的完整路径。
+    /// </summary>
+    /// <param name="relativePath">相对于指定的目录的相对路径。</param>
+    /// <param name="srcDir">指定的目录</param>
+    /// <returns>完整路径。</returns>
+    public static string GetFullPath(string relativePath, string srcDir)
+    {
+        return Path.GetFullPath(Path.Combine(srcDir, relativePath));
+    }
+
+    /// <summary>
+    /// 获取相对路径的的文本信息。
+    /// </summary>
+    /// <param name="relativePath"></param>
+    /// <returns></returns>
+    public static async Task<string> GetTextByRelativePath(string relativePath)
+    {
+        var fullPath = GetFullPath(relativePath);
+        return await File.ReadAllTextAsync(fullPath, Encoding.UTF8);
+    }
+
+    /// <summary>
+    /// 获取绝对路径的的文本信息。
+    /// </summary>
+    /// <param name="fullPath"></param>
+    /// <returns></returns>
+    public static async Task<string> GetText(string fullPath)
+    {
+        return await File.ReadAllTextAsync(fullPath, Encoding.UTF8);
+    }
+
+    /// <summary>
+    /// 根据文件夹路径创建文件夹，如果文件夹不存在会自动创建文件夹。
+    /// </summary>
+    /// <param name="directoryPath"></param>
+    public static void CreateDirectory(string directoryPath)
+    {
+        if (directoryPath.LastIndexOf('/') != directoryPath.Length - 1)
+        {
+            directoryPath += "/";
+        }
+
+        var directoriesByFilePath = GetDirectoriesByFilePath(directoryPath);
+
+        foreach (var dir in directoriesByFilePath)
+        {
+            if (Directory.Exists(dir))
+            {
+                continue;
+            }
+
+            Directory.CreateDirectory(dir);
+        }
+    }
+
+    /// <summary>
+    /// 将文件复制到目标路径，如果目标目录不存在会自动创建目录。
+    /// </summary>
+    /// <param name="sourceFile">源文件路径。</param>
+    /// <param name="destinationFile">目标文件路径。</param>
+    /// <param name="overwrite">是否覆盖已存在的目标文件。</param>
+    public static void Copy(string sourceFile, string destinationFile, bool overwrite)
+    {
+        CreateDirectory(destinationFile);
+        File.Copy(sourceFile, destinationFile, overwrite);
+    }
+
+    /// <summary>
+    /// 获取文件路径内的所有文件夹路径。
+    /// </summary>
+    /// <param name="filePath">文件路径。</param>
+    /// <returns>文件夹路径列表。</returns>
+    public static IEnumerable<string> GetDirectoriesByFilePath(string filePath)
+    {
+        var dir = "";
+        var fileDirectories = filePath.Split('/');
+
+        for (var i = 0; i < fileDirectories.Length - 1; i++)
+        {
+            dir = $"{dir}{fileDirectories[i]}/";
+            yield return dir;
+        }
+
+        if (fileDirectories.Length == 1)
+        {
+            yield return filePath;
+        }
+    }
+
+    /// <summary>
+    /// 将文件夹内的所有内容复制到目标位置。
+    /// </summary>
+    /// <param name="sourceDirectory">源文件夹路径。</param>
+    /// <param name="destinationDirectory">目标文件夹路径。</param>
+    /// <param name="overwrite">是否覆盖已存在的文件。</param>
+    public static void CopyDirectory(string sourceDirectory, string destinationDirectory, bool overwrite)
+    {
+        // 创建目标文件夹
+
+        if (!Directory.Exists(destinationDirectory))
+        {
+            Directory.CreateDirectory(destinationDirectory);
+        }
+
+        // 获取当前文件夹中的所有文件
+
+        var files = Directory.GetFiles(sourceDirectory);
+
+        // 拷贝文件到目标文件夹
+
+        foreach (var file in files)
+        {
+            var fileName = Path.GetFileName(file);
+            var destinationPath = Path.Combine(destinationDirectory, fileName);
+            File.Copy(file, destinationPath, overwrite);
+        }
+
+        // 获取源文件夹中的所有子文件夹
+
+        var directories = Directory.GetDirectories(sourceDirectory);
+
+        // 递归方式拷贝文件夹
+
+        foreach (var directory in directories)
+        {
+            var directoryName = Path.GetFileName(directory);
+            var destinationPath = Path.Combine(destinationDirectory, directoryName);
+            CopyDirectory(directory, destinationPath, overwrite);
+        }
+    }
+
+    /// <summary>
+    /// 获取目录下的所有文件
+    /// </summary>
+    /// <param name="folderPath">文件夹路径。</param>
+    /// <param name="searchPattern">需要查找的文件通配符</param>
+    /// <param name="searchOption">查找的类型</param>
+    /// <returns></returns>
+    public static string[] GetDirectoryFile(string folderPath, string searchPattern, SearchOption searchOption)
+    {
+        return Directory.GetFiles(folderPath, searchPattern, searchOption);
+    }
+
+    /// <summary>
+    /// 清空文件夹内的所有文件。
+    /// </summary>
+    /// <param name="folderPath">文件夹路径。</param>
+    public static void ClearDirectoryFile(string folderPath)
+    {
+        if (!Directory.Exists(folderPath))
+        {
+            return;
+        }
+
+        var files = Directory.GetFiles(folderPath);
+
+        foreach (var file in files)
+        {
+            File.Delete(file);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Utils/HashCodeHelper.cs b/Tools/ConfigBuilder/NBConfigBuilder/Utils/HashCodeHelper.cs
new file mode 100644
index 0000000..92094c7
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Utils/HashCodeHelper.cs
@@ -0,0 +1,228 @@
+using System.Security.Cryptography;
+using System.Text;
+
+namespace NBConfigBuilder;
+
+/// <summary>
+/// HashCode算法帮助类
+/// </summary>
+public static partial class HashCodeHelper
+{
+    private static readonly SHA256 Sha256Hash = SHA256.Create();
+
+    /// <summary>
+    /// 计算两个字符串的HashCode
+    /// </summary>
+    /// <param name="a"></param>
+    /// <param name="b"></param>
+    /// <returns></returns>
+    public static int GetHashCode(string a, string b)
+    {
+        var hash = 17;
+        hash = hash * 31 + a.GetHashCode();
+        hash = hash * 31 + b.GetHashCode();
+        return hash;
+    }
+#if FANTASY_NET || !FANTASY_WEBGL
+    /// <summary>
+    /// 使用bkdr算法生成一个long的值
+    /// </summary>
+    /// <param name="str"></param>
+    /// <returns></returns>
+    public static unsafe long GetBKDRHashCode(string str)
+    {
+        ulong hash = 0;
+        // 如果要修改这个种子、建议选择一个质数来做种子
+        const uint seed = 13131; // 31 131 1313 13131 131313 etc..
+        fixed (char* p = str)
+        {
+            for (var i = 0; i < str.Length; i++)
+            {
+                var c = p[i];
+                var high = (byte)(c >> 8);
+                var low = (byte)(c & byte.MaxValue);
+                hash = hash * seed + high;
+                hash = hash * seed + low;
+            }
+        }
+
+        return (long)hash;
+    }
+
+    /// <summary>
+    /// 使用MurmurHash3算法生成一个uint的值
+    /// </summary>
+    /// <param name="str"></param>
+    /// <returns></returns>
+    public static unsafe uint MurmurHash3(string str)
+    {
+        const uint seed = 0xc58f1a7b;
+        uint hash = seed;
+        uint c1 = 0xcc9e2d51;
+        uint c2 = 0x1b873593;
+
+        fixed (char* p = str)
+        {
+            var current = p;
+
+            for (var i = 0; i < str.Length; i++)
+            {
+                var k1 = (uint)(*current);
+                k1 *= c1;
+                k1 = (k1 << 15) | (k1 >> (32 - 15));
+                k1 *= c2;
+
+                hash ^= k1;
+                hash = (hash << 13) | (hash >> (32 - 13));
+                hash = hash * 5 + 0xe6546b64;
+
+                current++;
+            }
+        }
+
+        hash ^= (uint)str.Length;
+        hash ^= hash >> 16;
+        hash *= 0x85ebca6b;
+        hash ^= hash >> 13;
+        hash *= 0xc2b2ae35;
+        hash ^= hash >> 16;
+        return hash;
+    }
+
+    /// <summary>
+    /// 使用MurmurHash3算法生成一个long的值
+    /// </summary>
+    /// <param name="str"></param>
+    /// <returns></returns>
+    public static unsafe long ComputeHash64(string str)
+    {
+        const ulong seed = 0xc58f1a7bc58f1a7bUL; // 64-bit seed
+        var hash = seed;
+        var c1 = 0x87c37b91114253d5UL;
+        var c2 = 0x4cf5ad432745937fUL;
+
+        fixed (char* p = str)
+        {
+            var current = p;
+
+            for (var i = 0; i < str.Length; i++)
+            {
+                var k1 = (ulong)(*current);
+                k1 *= c1;
+                k1 = (k1 << 31) | (k1 >> (64 - 31));
+                k1 *= c2;
+
+                hash ^= k1;
+                hash = (hash << 27) | (hash >> (64 - 27));
+                hash = hash * 5 + 0x52dce729;
+
+                current++;
+            }
+        }
+
+        hash ^= (ulong)str.Length;
+        hash ^= hash >> 33;
+        hash *= 0xff51afd7ed558ccdUL;
+        hash ^= hash >> 33;
+        hash *= 0xc4ceb9fe1a85ec53UL;
+        hash ^= hash >> 33;
+        return (long)hash;
+    }
+#endif
+#if FANTASY_WEBGL
+        /// <summary>
+        /// 使用bkdr算法生成一个long的值
+        /// </summary>
+        /// <param name="str"></param>
+        /// <returns></returns>
+        public static long GetBKDRHashCode(string str)
+        {
+            long hash = 0;
+            // 如果要修改这个种子、建议选择一个质数来做种子
+            const uint seed = 13131; // 31 131 1313 13131 131313 etc..
+            foreach (var c in str)
+            {
+                var high = (byte)(c >> 8);
+                var low = (byte)(c & byte.MaxValue);
+                hash = hash * seed + high;
+                hash = hash * seed + low;
+            }
+            return hash;
+        }
+        /// <summary>
+        /// 使用MurmurHash3算法生成一个uint的值
+        /// </summary>
+        /// <param name="str"></param>
+        /// <returns></returns>
+        public static uint MurmurHash3(string str)
+        {
+            const uint seed = 0xc58f1a7b;
+            uint hash = seed;
+            uint c1 = 0xcc9e2d51;
+            uint c2 = 0x1b873593;
+            
+            foreach (var t in str)
+            {
+                var k1 = (uint)(t);
+                k1 *= c1;
+                k1 = (k1 << 15) | (k1 >> (32 - 15));
+                k1 *= c2;
+
+                hash ^= k1;
+                hash = (hash << 13) | (hash >> (32 - 13));
+                hash = hash * 5 + 0xe6546b64;
+            }
+
+            hash ^= (uint)str.Length;
+            hash ^= hash >> 16;
+            hash *= 0x85ebca6b;
+            hash ^= hash >> 13;
+            hash *= 0xc2b2ae35;
+            hash ^= hash >> 16;
+            return hash;
+        }
+        
+        /// <summary>
+        /// 使用MurmurHash3算法生成一个long的值
+        /// </summary>
+        /// <param name="str"></param>
+        /// <returns></returns>
+        public static long ComputeHash64(string str)
+        {
+            const ulong seed = 0xc58f1a7bc58f1a7bUL; // 64-bit seed
+            var hash = seed;
+            var c1 = 0x87c37b91114253d5UL;
+            var c2 = 0x4cf5ad432745937fUL;
+            
+            foreach (var t in str)
+            {
+                var k1 = (ulong)(t);
+                k1 *= c1;
+                k1 = (k1 << 31) | (k1 >> (64 - 31));
+                k1 *= c2;
+
+                hash ^= k1;
+                hash = (hash << 27) | (hash >> (64 - 27));
+                hash = hash * 5 + 0x52dce729;
+            }
+
+            hash ^= (ulong)str.Length;
+            hash ^= hash >> 33;
+            hash *= 0xff51afd7ed558ccdUL;
+            hash ^= hash >> 33;
+            hash *= 0xc4ceb9fe1a85ec53UL;
+            hash ^= hash >> 33;
+            return (long)hash;
+        }
+#endif
+    /// <summary>
+    /// 根据字符串计算一个Hash值
+    /// </summary>
+    /// <param name="rawData"></param>
+    /// <returns></returns>
+    public static int ComputeSha256HashAsInt(string rawData)
+    {
+        var bytes = Sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
+        return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
+    }
+}
\ No newline at end of file
diff --git a/Tools/ConfigBuilder/NBConfigBuilder/Utils/TimeHelper.cs b/Tools/ConfigBuilder/NBConfigBuilder/Utils/TimeHelper.cs
new file mode 100644
index 0000000..8630260
--- /dev/null
+++ b/Tools/ConfigBuilder/NBConfigBuilder/Utils/TimeHelper.cs
@@ -0,0 +1,65 @@
+namespace NBConfigBuilder;
+
+/// <summary>
+/// 提供与时间相关的帮助方法。
+/// </summary>
+public static partial class TimeHelper
+{
+    /// <summary>
+    /// 一小时的毫秒值。
+    /// </summary>
+    public const long Hour = 3600000;
+
+    /// <summary>
+    /// 一分钟的毫秒值。
+    /// </summary>
+    public const long Minute = 60000;
+
+    /// <summary>
+    /// 一天的毫秒值。
+    /// </summary>
+    public const long OneDay = 86400000;
+
+    // 1970年1月1日的Ticks
+    private const long Epoch = 621355968000000000L;
+    /// <summary>
+    /// 获取当前时间的毫秒数，从1970年1月1日开始计算。
+    /// </summary>
+    public static long Now => (DateTime.UtcNow.Ticks - Epoch) / 10000;
+    
+    /// <summary>
+    /// 根据时间获取时间戳
+    /// </summary>
+    public static long Transition(DateTime dateTime)
+    {
+        return (dateTime.ToUniversalTime().Ticks - Epoch) / 10000;
+    }
+
+    /// <summary>
+    /// 根据时间获取 时间戳
+    /// </summary>
+    public static long TransitionToSeconds(DateTime dateTime)
+    {
+        return (dateTime.ToUniversalTime().Ticks - Epoch) / 10000000;
+    }
+
+    /// <summary>
+    /// 将毫秒数转换为日期时间。
+    /// </summary>
+    /// <param name="timeStamp">要转换的毫秒数。</param>
+    /// <returns>转换后的日期时间。</returns>
+    public static DateTime Transition(this long timeStamp)
+    {
+        return new DateTime(Epoch + timeStamp * 10000, DateTimeKind.Utc).ToUniversalTime();
+    }
+
+    /// <summary>
+    /// 将毫秒数转换为本地时间的日期时间。
+    /// </summary>
+    /// <param name="timeStamp">要转换的毫秒数。</param>
+    /// <returns>转换后的本地时间的日期时间。</returns>
+    public static DateTime TransitionLocal(this long timeStamp)
+    {
+        return new DateTime(Epoch + timeStamp * 10000, DateTimeKind.Utc).ToLocalTime();
+    }
+}
\ No newline at end of file
diff --git a/Tools/SourceCode/Fantasy.Tools.ConfigTable/Exporter/ExcelExporter.cs b/Tools/SourceCode/Fantasy.Tools.ConfigTable/Exporter/ExcelExporter.cs
index 00aa813..f11f6b0 100644
--- a/Tools/SourceCode/Fantasy.Tools.ConfigTable/Exporter/ExcelExporter.cs
+++ b/Tools/SourceCode/Fantasy.Tools.ConfigTable/Exporter/ExcelExporter.cs
@@ -664,6 +664,7 @@ public sealed class ExcelExporter
 
         Task.WaitAll(exportToBinaryTasks.ToArray());
     }
+    
     private void GenerateBinary(string fileInfoFullName, ExcelWorksheet excelWorksheet, DynamicConfigDataType dynamicInfo, List<int> cols, string id, int row, bool isLast, bool isServer)
     {
         if (cols == null || IsNullOrEmpty(id) || cols.Count <= 0 || dynamicInfo?.ConfigType == null)
@@ -718,6 +719,7 @@ public sealed class ExcelExporter
             dynamicInfo.Json.AppendLine($"{json},");
         }
     }
+    
     /// <summary>
     /// 从 Excel 文件加载工作表并返回 ExcelWorksheet 对象。
     /// </summary>
