Browse Source

小球价格配置表

181404010226 2 months ago
parent
commit
02ef3ac499

+ 5 - 3
assets/Scenes/GameLevel.scene

@@ -35818,9 +35818,11 @@
       "__uuid__": "b0dff099-9502-41f9-8678-6126d42ddd68",
       "__expectedType__": "cc.JsonAsset"
     },
-    "ballPriceConfig": {
-      "__uuid__": "2c4beb85-fa85-41dc-a32a-b614ec345d96",
-      "__expectedType__": "cc.JsonAsset"
+    "addBallPriceNode": {
+      "__id__": 1064
+    },
+    "refreshBlockPriceNode": {
+      "__id__": 1112
     },
     "debugDrawSnapRange": true,
     "_id": "ealiXZigZIgrXLo2NL22Ns"

+ 5 - 11
assets/data/ball_price_config.json

@@ -1,20 +1,14 @@
 {
   "addBallPricing": {
-    "initialPrice": 80,
-    "priceIncrement": 10,
-    "maxPrice": 500,
-    "description": "加小球的价格配置"
+    "initialPrice": 65,
+    "priceIncrement": 15,
+    "maxPrice": 385,
+    "description": "加小球的价格配置"
   },
   "refreshBlockPricing": {
     "initialPrice": 5,
     "priceIncrement": 2,
-    "maxPrice": 50,
+    "maxPrice": 45,
     "description": "刷新方块的价格配置"
-  },
-  "priceHistory": {
-    "addBallCurrentPrice": 80,
-    "refreshBlockCurrentPrice": 5,
-    "addBallPurchaseCount": 0,
-    "refreshBlockPurchaseCount": 0
   }
 }

BIN
assets/data/excel/__pycache__/ball_price_config_manager.cpython-313.pyc


+ 12 - 0
assets/data/excel/__pycache__/ball_price_config_manager.cpython-313.pyc.meta

@@ -0,0 +1,12 @@
+{
+  "ver": "1.0.0",
+  "importer": "*",
+  "imported": true,
+  "uuid": "ad10146a-1248-46a2-96c1-f56df5330e5a",
+  "files": [
+    ".json",
+    ".pyc"
+  ],
+  "subMetas": {},
+  "userData": {}
+}

+ 285 - 0
assets/data/excel/ball_price_config_manager.py

@@ -0,0 +1,285 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+小球价格配置管理器
+从config_manager.py中提取的小球价格相关配置管理功能
+支持从Excel读取小球价格配置并与现有JSON配置合并
+"""
+
+import json
+import os
+from pathlib import Path
+from datetime import datetime
+
+try:
+    import pandas as pd
+    PANDAS_AVAILABLE = True
+except ImportError:
+    PANDAS_AVAILABLE = False
+    print("警告: pandas未安装,无法处理Excel文件")
+
+class BallPriceConfigManager:
+    """小球价格配置管理器"""
+    
+    def __init__(self, excel_file_path=None, json_file_path=None):
+        """初始化小球价格配置管理器
+        
+        Args:
+            excel_file_path: Excel配置文件路径
+            json_file_path: JSON配置文件路径
+        """
+        self.script_dir = Path(__file__).parent
+        
+        # 设置默认路径
+        if excel_file_path is None:
+            self.excel_file = self.script_dir / "小球价格配置" / "小球价格配置表.xlsx"
+        else:
+            self.excel_file = Path(excel_file_path)
+            
+        if json_file_path is None:
+            self.json_file = self.script_dir.parent / "ball_price_config.json"
+        else:
+            self.json_file = Path(json_file_path)
+            
+        print(f"Excel文件路径: {self.excel_file}")
+        print(f"JSON文件路径: {self.json_file}")
+    
+    def load_existing_json_config(self):
+        """加载现有的JSON配置文件"""
+        try:
+            if self.json_file.exists():
+                with open(self.json_file, 'r', encoding='utf-8') as f:
+                    config = json.load(f)
+                print(f"成功加载现有JSON配置")
+                return config
+            else:
+                print(f"JSON文件不存在,将创建新配置: {self.json_file}")
+                return {}
+        except Exception as e:
+            print(f"加载JSON配置失败: {e}")
+            return {}
+    
+    def read_excel_config(self):
+        """读取Excel配置文件"""
+        if not PANDAS_AVAILABLE:
+            print("错误: pandas未安装,无法读取Excel文件")
+            return None
+            
+        if not self.excel_file.exists():
+            print(f"Excel文件不存在: {self.excel_file}")
+            return None
+            
+        try:
+            # 读取Excel文件
+            excel_data = pd.read_excel(self.excel_file, sheet_name=None)
+            print(f"成功读取Excel文件,包含工作表: {list(excel_data.keys())}")
+            
+            # 查找小球价格配置工作表
+            config_sheet = None
+            sheet_names = ['小球价格配置', 'Ball Price Config', 'ball_price', '价格配置']
+            
+            for sheet_name in sheet_names:
+                if sheet_name in excel_data:
+                    config_sheet = excel_data[sheet_name]
+                    print(f"找到小球价格配置工作表: {sheet_name}")
+                    break
+            
+            if config_sheet is None:
+                # 如果没有找到特定工作表,使用第一个工作表
+                first_sheet_name = list(excel_data.keys())[0]
+                config_sheet = excel_data[first_sheet_name]
+                print(f"未找到指定工作表,使用第一个工作表: {first_sheet_name}")
+            
+            return self.parse_ball_price_config(config_sheet)
+            
+        except Exception as e:
+            print(f"读取Excel文件失败: {e}")
+            return None
+    
+    def parse_ball_price_config(self, df):
+        """解析小球价格配置数据"""
+        try:
+            print(f"开始解析配置数据,数据形状: {df.shape}")
+            print(f"列名: {list(df.columns)}")
+            
+            config = {}
+            
+            # 处理纵向格式的配置表(配置项在第一列,数值在第二列)
+            # 创建配置项到数值的映射
+            config_map = {}
+            
+            # 假设第一列是配置项,第二列是数值
+            first_col = df.columns[0] if len(df.columns) > 0 else None
+            second_col = df.columns[1] if len(df.columns) > 1 else None
+            
+            if first_col is None or second_col is None:
+                print("Excel文件格式不正确,需要至少两列数据")
+                return None
+            
+            print(f"配置项列: {first_col}, 数值列: {second_col}")
+            
+            # 遍历所有行,建立配置项到数值的映射
+            for index, row in df.iterrows():
+                config_item = row[first_col]
+                config_value = row[second_col]
+                
+                if pd.notna(config_item) and pd.notna(config_value):
+                    config_item_str = str(config_item).strip()
+                    # 尝试转换数值类型
+                    try:
+                        if isinstance(config_value, (int, float)):
+                            config_map[config_item_str] = config_value
+                        else:
+                            # 尝试转换为数字
+                            config_value_str = str(config_value).strip()
+                            if config_value_str.isdigit():
+                                config_map[config_item_str] = int(config_value_str)
+                            elif config_value_str.replace('.', '', 1).isdigit():
+                                config_map[config_item_str] = float(config_value_str)
+                            else:
+                                config_map[config_item_str] = config_value_str
+                    except:
+                        config_map[config_item_str] = config_value
+                    
+                    print(f"配置项: {config_item_str} = {config_map[config_item_str]}")
+            
+            print(f"配置映射: {config_map}")
+            
+            # 解析添加小球配置
+            add_ball_config = {}
+            if '增加小球初始价格' in config_map:
+                add_ball_config['initialPrice'] = int(config_map['增加小球初始价格'])
+            if '增加小球价格增量' in config_map:
+                add_ball_config['priceIncrement'] = int(config_map['增加小球价格增量'])
+            if '增加小球最大价格' in config_map:
+                add_ball_config['maxPrice'] = int(config_map['增加小球最大价格'])
+            
+            # 添加当前价格和购买次数(如果存在)
+            if '增加小球当前价格' in config_map:
+                add_ball_config['currentPrice'] = int(config_map['增加小球当前价格'])
+            if '增加小球购买次数' in config_map:
+                add_ball_config['purchaseCount'] = int(config_map['增加小球购买次数'])
+            
+            # 添加描述
+            add_ball_config['description'] = "添加小球的价格配置"
+            
+            if add_ball_config:
+                config['addBallPricing'] = add_ball_config
+                print(f"解析添加小球配置: {add_ball_config}")
+            
+            # 解析刷新方块配置
+            refresh_block_config = {}
+            if '刷新方块初始价格' in config_map:
+                refresh_block_config['initialPrice'] = int(config_map['刷新方块初始价格'])
+            if '刷新方块价格增量' in config_map:
+                refresh_block_config['priceIncrement'] = int(config_map['刷新方块价格增量'])
+            if '刷新方块最大价格' in config_map:
+                refresh_block_config['maxPrice'] = int(config_map['刷新方块最大价格'])
+            
+            # 添加当前价格和购买次数(如果存在)
+            if '刷新方块当前价格' in config_map:
+                refresh_block_config['currentPrice'] = int(config_map['刷新方块当前价格'])
+            if '刷新方块购买次数' in config_map:
+                refresh_block_config['purchaseCount'] = int(config_map['刷新方块购买次数'])
+            
+            # 添加描述
+            refresh_block_config['description'] = "刷新方块的价格配置"
+            
+            if refresh_block_config:
+                config['refreshBlockPricing'] = refresh_block_config
+                print(f"解析刷新方块配置: {refresh_block_config}")
+            
+            # 解析其他配置项(如果需要)
+            other_config = {}
+            for key, value in config_map.items():
+                if key in ['restitution', 'safeDistance', 'edgeOffset', 'sensor', 'maxAttempts']:
+                    other_config[key] = value
+            
+            if other_config:
+                config['otherSettings'] = other_config
+                print(f"解析其他配置: {other_config}")
+            
+            print(f"最终解析结果: {config}")
+            return config if config else None
+            
+        except Exception as e:
+            import traceback
+            print(f"解析小球价格配置失败: {e}")
+            print(f"详细错误信息: {traceback.format_exc()}")
+            return None
+    
+    def merge_configs(self, existing_config, new_config):
+        """合并现有配置和新配置"""
+        if not new_config:
+            return existing_config
+        
+        merged_config = existing_config.copy()
+        
+        # 合并小球价格配置
+        for key, value in new_config.items():
+            merged_config[key] = value
+            print(f"更新配置: {key}")
+        
+        return merged_config
+    
+    def save_config(self, config):
+        """保存配置到JSON文件"""
+        try:
+            # 创建备份
+            if self.json_file.exists():
+                backup_path = self.json_file.with_suffix(f'.backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json')
+                with open(self.json_file, 'r', encoding='utf-8') as f:
+                    backup_data = f.read()
+                with open(backup_path, 'w', encoding='utf-8') as f:
+                    f.write(backup_data)
+                print(f"创建备份文件: {backup_path}")
+            
+            # 保存新配置
+            with open(self.json_file, 'w', encoding='utf-8') as f:
+                json.dump(config, f, ensure_ascii=False, indent=2)
+            
+            print(f"配置已保存到: {self.json_file}")
+            return True
+            
+        except Exception as e:
+            print(f"保存配置失败: {e}")
+            return False
+    
+    def import_config(self, excel_file_path=None, json_file_path=None):
+        """导入配置的主方法"""
+        if excel_file_path:
+            self.excel_file = Path(excel_file_path)
+        if json_file_path:
+            self.json_file = Path(json_file_path)
+        
+        print("开始导入小球价格配置...")
+        
+        # 1. 加载现有配置
+        existing_config = self.load_existing_json_config()
+        
+        # 2. 读取Excel配置
+        new_config = self.read_excel_config()
+        if new_config is None:
+            print("读取Excel配置失败,导入终止")
+            return False
+        
+        # 3. 合并配置
+        merged_config = self.merge_configs(existing_config, new_config)
+        
+        # 4. 保存配置
+        success = self.save_config(merged_config)
+        
+        if success:
+            print("小球价格配置导入成功!")
+        else:
+            print("小球价格配置导入失败!")
+        
+        return success
+
+def main():
+    """测试函数"""
+    manager = BallPriceConfigManager()
+    manager.import_config()
+
+if __name__ == "__main__":
+    main()

+ 12 - 0
assets/data/excel/ball_price_config_manager.py.meta

@@ -0,0 +1,12 @@
+{
+  "ver": "1.0.0",
+  "importer": "*",
+  "imported": true,
+  "uuid": "3e309fad-e399-40ae-b693-6a8a3ad65b08",
+  "files": [
+    ".json",
+    ".py"
+  ],
+  "subMetas": {},
+  "userData": {}
+}

+ 84 - 0
assets/data/excel/config_manager.py

@@ -83,6 +83,13 @@ except ImportError:
     SHOP_MANAGER_AVAILABLE = False
     print("警告: shop_config_manager.py 未找到,商店配置功能将不可用")
 
+try:
+    from ball_price_config_manager import BallPriceConfigManager
+    BALL_PRICE_MANAGER_AVAILABLE = True
+except ImportError:
+    BALL_PRICE_MANAGER_AVAILABLE = False
+    print("警告: ball_price_config_manager.py 未找到,小球价格配置功能将不可用")
+
 
     def parse_skill_types(self, df):
         """解析技能类型配置"""
@@ -242,6 +249,7 @@ class ConfigManagerGUI:
         self.skill_config_manager_class = SkillConfigManager if SKILL_CONFIG_MANAGER_AVAILABLE else None
         self.game_skill_config_manager_class = GameSkillConfigManager if GAME_SKILL_MANAGER_AVAILABLE else None
         self.shop_config_manager_class = ShopConfigManager if SHOP_MANAGER_AVAILABLE else None
+        self.ball_price_config_manager_class = BallPriceConfigManager if BALL_PRICE_MANAGER_AVAILABLE else None
         
         # 初始化新的配置管理器模块
         self.init_config_managers()
@@ -430,6 +438,17 @@ class ConfigManagerGUI:
             ttk.Label(shop_btn_frame, text="商店配置管理器不可用", 
                      foreground="red").pack(side=tk.LEFT)
         
+        # 小球价格配置专用按钮
+        ball_price_btn_frame = ttk.Frame(right_frame)
+        ball_price_btn_frame.grid(row=9, column=0, sticky=(tk.W, tk.E), pady=(10, 0))
+        
+        if BALL_PRICE_MANAGER_AVAILABLE:
+            ttk.Button(ball_price_btn_frame, text="导入小球价格配置", 
+                      command=self.import_ball_price_config).pack(side=tk.LEFT)
+        else:
+            ttk.Label(ball_price_btn_frame, text="小球价格配置管理器不可用", 
+                     foreground="red").pack(side=tk.LEFT)
+        
         # 底部状态栏
         self.status_var = tk.StringVar()
         self.status_var.set("就绪")
@@ -1326,6 +1345,71 @@ class ConfigManagerGUI:
             print(f"启动商店配置导入失败,详细错误信息:")
             print(error_details)
             messagebox.showerror("错误", f"启动商店配置导入失败: {str(e)}\n\n详细错误信息已输出到控制台,请查看。")
+    
+    def import_ball_price_config(self):
+        """导入小球价格配置"""
+        try:
+            if not BALL_PRICE_MANAGER_AVAILABLE:
+                messagebox.showerror("错误", "小球价格配置管理器不可用,请检查ball_price_config_manager.py文件是否存在")
+                return
+            
+            # 创建小球价格配置管理器
+            excel_dir = Path(self.excel_dir)
+            ball_price_excel_file = excel_dir / "小球价格配置" / "小球价格配置表.xlsx"
+            ball_price_json_file = excel_dir.parent / "ball_price_config.json"
+            
+            if not ball_price_excel_file.exists():
+                messagebox.showwarning("警告", f"未找到小球价格配置文件: {ball_price_excel_file}")
+                return
+            
+            # 使用BallPriceConfigManager导入配置
+            ball_price_manager = BallPriceConfigManager(
+                excel_file_path=str(ball_price_excel_file),
+                json_file_path=str(ball_price_json_file)
+            )
+            
+            # 在后台线程中执行导入
+            def import_thread():
+                try:
+                    success = ball_price_manager.import_config()
+                    
+                    # 在主线程中更新UI
+                    def update_ui():
+                        if success:
+                            messagebox.showinfo("成功", "小球价格配置导入成功!")
+                            self.status_var.set("小球价格配置导入成功")
+                            # 更新预览文本
+                            self.preview_text.delete(1.0, tk.END)
+                            self.preview_text.insert(tk.END, "小球价格配置导入成功\n\n配置已从Excel文件合并到JSON文件中")
+                        else:
+                            messagebox.showerror("错误", "小球价格配置导入失败,请查看控制台输出")
+                            self.status_var.set("小球价格配置导入失败")
+                    
+                    self.root.after(0, update_ui)
+                    
+                except Exception as e:
+                    def show_error():
+                        import traceback
+                        error_details = traceback.format_exc()
+                        print(f"导入小球价格配置失败,详细错误信息:")
+                        print(error_details)
+                        messagebox.showerror("错误", f"导入小球价格配置失败: {str(e)}\n\n详细错误信息已输出到控制台,请查看。")
+                        self.status_var.set("小球价格配置导入失败")
+                    
+                    self.root.after(0, show_error)
+            
+            # 启动导入线程
+            self.status_var.set("正在导入小球价格配置...")
+            thread = threading.Thread(target=import_thread)
+            thread.daemon = True
+            thread.start()
+            
+        except Exception as e:
+            import traceback
+            error_details = traceback.format_exc()
+            print(f"启动小球价格配置导入失败,详细错误信息:")
+            print(error_details)
+            messagebox.showerror("错误", f"启动小球价格配置导入失败: {str(e)}\n\n详细错误信息已输出到控制台,请查看。")
 
     def init_config_managers(self):
         """初始化新的配置管理器模块"""

+ 12 - 0
assets/data/excel/~$小球价格配置表.xlsx.meta

@@ -0,0 +1,12 @@
+{
+  "ver": "1.0.0",
+  "importer": "*",
+  "imported": true,
+  "uuid": "d0a4e5c1-8b91-4bcc-8c0c-1105f3b9fb90",
+  "files": [
+    ".json",
+    ".xlsx"
+  ],
+  "subMetas": {},
+  "userData": {}
+}

+ 9 - 0
assets/data/excel/小球价格配置.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "1.2.0",
+  "importer": "directory",
+  "imported": true,
+  "uuid": "3be329c6-561f-4a87-9b67-3a26fee4603a",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

BIN
assets/data/excel/小球价格配置/小球价格配置表.xlsx


+ 1 - 1
assets/data/excel/小球价格配置表.xlsx.meta → assets/data/excel/小球价格配置/小球价格配置表.xlsx.meta

@@ -2,7 +2,7 @@
   "ver": "1.0.0",
   "importer": "*",
   "imported": true,
-  "uuid": "d9060612-b132-4cf3-a8a5-9c9ef959afb6",
+  "uuid": "a295b864-b2ba-4edc-8a41-392091aaf766",
   "files": [
     ".json",
     ".xlsx"

BIN
assets/data/excel/小球价格配置表.xlsx


+ 114 - 28
assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts

@@ -8,6 +8,7 @@ import { WeaponInfo } from './WeaponInfo';
 import { SkillManager } from '../SkillSelection/SkillManager';
 import { Audio } from '../../AudioManager/AudioManager';
 import { AdManager } from '../../Ads/AdManager';
+import { BundleLoader } from '../../Core/BundleLoader';
 
 import EventBus, { GameEvents } from '../../Core/EventBus';
 const { ccclass, property } = _decorator;
@@ -82,12 +83,22 @@ export class GameBlockSelection extends Component {
     })
     public weaponsConfig: JsonAsset = null;
 
-    // 小球价格配置JsonAsset - 通过装饰器预加载
+    // 小球价格配置数据 - 通过BundleLoader动态加载
+    private ballPriceConfigData: any = null;
+
+    // 新增小球价格显示节点 - 对应addBallPricing
     @property({
-        type: JsonAsset,
-        tooltip: '拖拽ball_price_config.json文件到这里,实现价格配置预加载'
+        type: Node,
+        tooltip: '拖拽Canvas/GameLevelUI/BlockSelectionUI/diban/ann001/Ball/db01/Price节点到这里'
+    })
+    public addBallPriceNode: Node = null;
+
+    // 刷新方块价格显示节点 - 对应refreshBlockPricing
+    @property({
+        type: Node,
+        tooltip: '拖拽Canvas/GameLevelUI/BlockSelectionUI/diban/ann003/Ball/db01/Price节点到这里'
     })
-    public ballPriceConfig: JsonAsset = null;
+    public refreshBlockPriceNode: Node = null;
 
     // 常量定义
     private readonly ADD_COIN_AMOUNT = 80;
@@ -102,18 +113,29 @@ export class GameBlockSelection extends Component {
     
     // 价格获取方法
     private getAddBallCost(): number {
-        if (this.ballPriceConfig && this.ballPriceConfig.json && this.ballPriceConfig.json.priceHistory) {
-            return this.ballPriceConfig.json.priceHistory.addBallCurrentPrice || this.DEFAULT_ADD_BALL_BASE_PRICE;
+        // 优先从JSON配置中获取价格
+        if (this.ballPriceConfigData && this.ballPriceConfigData.addBallPricing) {
+            return this.ballPriceConfigData.addBallPricing.initialPrice || this.DEFAULT_ADD_BALL_BASE_PRICE;
         }
         
+        // 其次从装饰器绑定的节点获取价格
         try {
-            const priceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann001/Ball/db01/Price');
-            if (priceNode) {
-                const label = priceNode.getComponent(Label);
+            if (this.addBallPriceNode) {
+                const label = this.addBallPriceNode.getComponent(Label);
                 if (label) {
                     const price = parseInt(label.string);
                     return isNaN(price) ? this.DEFAULT_ADD_BALL_BASE_PRICE : price;
                 }
+            } else {
+                // 回退到find方法(兼容性)
+                const priceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann001/Ball/db01/Price');
+                if (priceNode) {
+                    const label = priceNode.getComponent(Label);
+                    if (label) {
+                        const price = parseInt(label.string);
+                        return isNaN(price) ? this.DEFAULT_ADD_BALL_BASE_PRICE : price;
+                    }
+                }
             }
         } catch (error) {
             console.warn('[GameBlockSelection] 获取新增小球价格失败:', error);
@@ -121,19 +143,32 @@ export class GameBlockSelection extends Component {
         return this.DEFAULT_ADD_BALL_BASE_PRICE; // 默认价格
     }
     
-    private getRefreshCost(): number {
-        if (this.ballPriceConfig && this.ballPriceConfig.json && this.ballPriceConfig.json.priceHistory) {
-            return this.ballPriceConfig.json.priceHistory.refreshBlockCurrentPrice || this.DEFAULT_REFRESH_BASE_PRICE;
+    public getRefreshCost(): number {
+        // 优先从JSON配置中获取价格
+        console.log('[GameBlockSelection] 刷新方块价格配置:', this.ballPriceConfigData?.refreshBlockPricing);
+        if (this.ballPriceConfigData && this.ballPriceConfigData.refreshBlockPricing) {
+            return this.ballPriceConfigData.refreshBlockPricing.initialPrice || this.DEFAULT_REFRESH_BASE_PRICE;
         }
         
+        // 其次从装饰器绑定的节点获取价格
         try {
-            const priceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann003/Ball/db01/Price');
-            if (priceNode) {
-                const label = priceNode.getComponent(Label);
+            if (this.refreshBlockPriceNode) {
+                console.log('[GameBlockSelection] 刷新方块价格节点:', this.refreshBlockPriceNode);
+                const label = this.refreshBlockPriceNode.getComponent(Label);
                 if (label) {
                     const price = parseInt(label.string);
                     return isNaN(price) ? this.DEFAULT_REFRESH_BASE_PRICE : price;
                 }
+            } else {
+                // 回退到find方法(兼容性)
+                const priceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann003/Ball/db01/Price');
+                if (priceNode) {
+                    const label = priceNode.getComponent(Label);
+                    if (label) {
+                        const price = parseInt(label.string);
+                        return isNaN(price) ? this.DEFAULT_REFRESH_BASE_PRICE : price;
+                    }
+                }
             }
         } catch (error) {
             console.warn('[GameBlockSelection] 获取刷新方块价格失败:', error);
@@ -186,7 +221,18 @@ export class GameBlockSelection extends Component {
         }
     }
     
-    private initializeComponent() {        
+    private async initializeComponent() {
+        // 异步加载小球价格配置
+        try {
+            const bundleLoader = BundleLoader.getInstance();
+            const ballPriceConfigAsset = await bundleLoader.loadDataJson('ball_price_config');
+            this.ballPriceConfigData = ballPriceConfigAsset.json;
+            console.log('[GameBlockSelection] 小球价格配置加载成功:', this.ballPriceConfigData);
+        } catch (error) {
+            console.warn('[GameBlockSelection] 小球价格配置加载失败:', error);
+            this.ballPriceConfigData = null;
+        }
+        
         // 获取管理器实例
         this.session = LevelSessionManager.inst;
         
@@ -603,6 +649,9 @@ export class GameBlockSelection extends Component {
         
         // 清理所有方块标签
         BlockTag.clearAllTags();
+        
+        // 重置价格历史数据(局内数据,每局重置)
+        this.resetPriceHistory();
     
         // 更新金币显示
         this.updateCoinDisplay();
@@ -1260,8 +1309,8 @@ export class GameBlockSelection extends Component {
     
     // 获取价格配置数据(如果装饰器配置不存在则返回默认值)
     private getPriceConfigData(): any {
-        if (this.ballPriceConfig && this.ballPriceConfig.json) {
-            return this.ballPriceConfig.json;
+        if (this.ballPriceConfigData && this.ballPriceConfigData.json) {
+            return this.ballPriceConfigData.json;
         }
         
         // 返回默认配置
@@ -1291,10 +1340,10 @@ export class GameBlockSelection extends Component {
         const config = configData.addBallPricing;
         const history = configData.priceHistory;
         
-        // 增加购买次数
+        // 增加购买次数(局内数据,每局会重置)
         history.addBallPurchaseCount++;
         
-        // 计算新价格
+        // 计算新价格(随购买次数增加,但有上限)
         const newPrice = Math.min(
             config.initialPrice + (history.addBallPurchaseCount * config.priceIncrement),
             config.maxPrice
@@ -1339,22 +1388,38 @@ export class GameBlockSelection extends Component {
     
     // 更新价格显示
     private updatePriceDisplay() {
-        // 更新新增小球价格显示
-        const addBallPriceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann001/Ball/db01/Price');
-        if (addBallPriceNode) {
-            const label = addBallPriceNode.getComponent(Label);
+        // 更新新增小球价格显示 - 使用装饰器绑定的节点
+        if (this.addBallPriceNode) {
+            const label = this.addBallPriceNode.getComponent(Label);
             if (label) {
                 label.string = this.getAddBallCost().toString();
             }
+        } else {
+            // 回退到find方法(兼容性)
+            const addBallPriceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann001/Ball/db01/Price');
+            if (addBallPriceNode) {
+                const label = addBallPriceNode.getComponent(Label);
+                if (label) {
+                    label.string = this.getAddBallCost().toString();
+                }
+            }
         }
         
-        // 更新刷新方块价格显示
-        const refreshPriceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann003/Ball/db01/Price');
-        if (refreshPriceNode) {
-            const label = refreshPriceNode.getComponent(Label);
+        // 更新刷新方块价格显示 - 使用装饰器绑定的节点
+        if (this.refreshBlockPriceNode) {
+            const label = this.refreshBlockPriceNode.getComponent(Label);
             if (label) {
                 label.string = this.getRefreshCost().toString();
             }
+        } else {
+            // 回退到find方法(兼容性)
+            const refreshPriceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann003/Ball/db01/Price');
+            if (refreshPriceNode) {
+                const label = refreshPriceNode.getComponent(Label);
+                if (label) {
+                    label.string = this.getRefreshCost().toString();
+                }
+            }
         }
     }
     
@@ -1365,4 +1430,25 @@ export class GameBlockSelection extends Component {
         // 在实际项目中,价格变化应该保存到本地存储或服务器
         console.log('[GameBlockSelection] 价格配置已更新:', JSON.stringify(configData, null, 2));
     }
+    
+    // 重置价格历史数据(每局开始时调用)
+    private resetPriceHistory() {
+        const configData = this.getPriceConfigData();
+        const config = configData.addBallPricing;
+        const refreshConfig = configData.refreshBlockPricing;
+        const history = configData.priceHistory;
+        
+        // 重置购买次数
+        history.addBallPurchaseCount = 0;
+        history.refreshBlockPurchaseCount = 0;
+        
+        // 重置价格为初始价格
+        history.addBallCurrentPrice = config.initialPrice;
+        history.refreshBlockCurrentPrice = refreshConfig.initialPrice;
+        
+        // 更新UI显示
+        this.updatePriceDisplay();
+        
+        console.log('[GameBlockSelection] 价格历史数据已重置到初始状态');
+    }
 }