ShopController.ts 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. import { _decorator, Component, Node, Label, Button, JsonAsset, Sprite, Color, SpriteFrame, director } from 'cc';
  2. import { SaveDataManager } from '../../LevelSystem/SaveDataManager';
  3. import EventBus, { GameEvents } from '../../Core/EventBus';
  4. import { TopBarController } from '../TopBarController';
  5. import { MoneyAni } from '../../Animations/MoneyAni';
  6. import { AdManager } from '../../Ads/AdManager';
  7. import { JsonConfigLoader } from '../../Core/JsonConfigLoader';
  8. const { ccclass, property } = _decorator;
  9. interface ShopConfig {
  10. dailyRewards: {
  11. money: {
  12. rewards: number[];
  13. maxClaimsPerDay: number;
  14. };
  15. diamond: {
  16. rewards: number[];
  17. maxClaimsPerDay: number;
  18. };
  19. }
  20. }
  21. interface DailyRewardData {
  22. lastResetDate: string;
  23. moneyFreeCount: number;
  24. moneyAdCount: number;
  25. diamondsFreeCount: number;
  26. diamondsAdCount: number;
  27. // 每日免费机会是否已使用
  28. moneyFreeUsed: boolean;
  29. diamondFreeUsed: boolean;
  30. }
  31. @ccclass('ShopController')
  32. export class ShopController extends Component {
  33. @property(Node)
  34. moneyRewardNode: Node = null;
  35. @property(Node)
  36. diamondRewardNode: Node = null;
  37. @property(Button)
  38. moneyButton: Button = null;
  39. @property(Button)
  40. diamondButton: Button = null;
  41. @property(Label)
  42. moneyCountLabel: Label = null;
  43. @property(Label)
  44. diamondCountLabel: Label = null;
  45. @property(Label)
  46. moneyAmountLabel: Label = null;
  47. @property(Label)
  48. diamondAmountLabel: Label = null;
  49. // @property(JsonAsset) shopConfigAsset: JsonAsset = null; // 已改为动态加载
  50. @property(Node)
  51. billSpriteNode: Node = null; // Canvas/ShopUI/ScrollView/view/content/bill/Sprite/Sprite
  52. @property(Node)
  53. diamondSpriteNode: Node = null; // Canvas/ShopUI/ScrollView/view/content/diamond/Sprite/Sprite
  54. @property(Node)
  55. moneyIconNode: Node = null; // Canvas/ShopUI/ScrollView/view/content/bill/Sprite/次数/antb-02
  56. @property(Node)
  57. diamondIconNode: Node = null; // Canvas/ShopUI/ScrollView/view/content/diamond/Sprite/次数/antb-02
  58. private shopConfig: ShopConfig = null;
  59. private dailyRewardData: DailyRewardData = null;
  60. private saveDataManager: SaveDataManager = null;
  61. private readonly DAILY_REWARD_KEY = 'daily_reward_data';
  62. /**
  63. * 格式化数字显示,在数字之间添加空格
  64. * @param num 要格式化的数字
  65. * @returns 格式化后的字符串,如 "50" -> "5 0"
  66. */
  67. private formatNumberWithSpaces(num: number): string {
  68. return num.toString().split('').join(' ');
  69. }
  70. async onLoad() {
  71. this.saveDataManager = SaveDataManager.getInstance();
  72. // 用户已手动隐藏图标,代码只在非免费时显示图标
  73. this.loadDailyRewardData();
  74. await this.loadShopConfig();
  75. this.setupEventListeners();
  76. this.updateUI();
  77. }
  78. start() {
  79. // start方法保留为空,所有初始化逻辑已在onLoad中完成
  80. }
  81. private async loadShopConfig() {
  82. try {
  83. const shopData = await JsonConfigLoader.getInstance().loadConfig('shop');
  84. if (shopData) {
  85. this.shopConfig = shopData as ShopConfig;
  86. console.log('[ShopController] shop.json加载成功:', this.shopConfig);
  87. this.updateUI();
  88. } else {
  89. console.warn('[ShopController] shop.json加载失败,使用默认配置');
  90. this.useDefaultConfig();
  91. }
  92. } catch (error) {
  93. console.error('[ShopController] 加载shop.json时出错:', error);
  94. this.useDefaultConfig();
  95. }
  96. }
  97. /**
  98. * 使用默认商店配置
  99. */
  100. private useDefaultConfig() {
  101. this.shopConfig = {
  102. dailyRewards: {
  103. money: {
  104. rewards: [100, 200, 300, 400, 500],
  105. maxClaimsPerDay: 5
  106. },
  107. diamond: {
  108. rewards: [10, 20, 30, 40, 50],
  109. maxClaimsPerDay: 5
  110. }
  111. }
  112. };
  113. console.log('[ShopController] 使用默认商店配置:', this.shopConfig);
  114. this.updateUI();
  115. }
  116. private loadDailyRewardData() {
  117. const savedData = localStorage.getItem(this.DAILY_REWARD_KEY);
  118. const today = this.getCurrentDateString();
  119. if (savedData) {
  120. const data = JSON.parse(savedData) as DailyRewardData;
  121. // 兼容旧数据:如果存在旧的costFreeUsed字段,迁移到新字段
  122. if (data.hasOwnProperty('costFreeUsed')) {
  123. const oldCostFreeUsed = (data as any).costFreeUsed;
  124. data.moneyFreeUsed = oldCostFreeUsed || false;
  125. data.diamondFreeUsed = oldCostFreeUsed || false;
  126. delete (data as any).costFreeUsed;
  127. console.log('[ShopController] 迁移旧的costFreeUsed数据到新字段');
  128. }
  129. // 确保新字段存在,设置默认值
  130. if (data.moneyFreeUsed === undefined) {
  131. data.moneyFreeUsed = false; // 默认为false(未使用)
  132. console.log('[ShopController] 设置moneyFreeUsed默认值: false');
  133. }
  134. if (data.diamondFreeUsed === undefined) {
  135. data.diamondFreeUsed = false; // 默认为false(未使用)
  136. console.log('[ShopController] 设置diamondFreeUsed默认值: false');
  137. }
  138. // 检查是否需要重置(新的一天)
  139. if (data.lastResetDate !== today) {
  140. console.log('[ShopController] 检测到新的一天,重置每日奖励数据');
  141. this.resetDailyRewardData(today);
  142. } else {
  143. this.dailyRewardData = data;
  144. console.log('[ShopController] 加载已有的每日奖励数据');
  145. }
  146. } else {
  147. console.log('[ShopController] 首次运行,创建新的每日奖励数据');
  148. this.resetDailyRewardData(today);
  149. }
  150. console.log('[ShopController] 每日奖励数据:', this.dailyRewardData);
  151. }
  152. private resetDailyRewardData(date: string) {
  153. this.dailyRewardData = {
  154. lastResetDate: date,
  155. moneyFreeCount: 0,
  156. moneyAdCount: 0,
  157. diamondsFreeCount: 0,
  158. diamondsAdCount: 0,
  159. moneyFreeUsed: false,
  160. diamondFreeUsed: false
  161. };
  162. this.saveDailyRewardData();
  163. }
  164. private saveDailyRewardData() {
  165. localStorage.setItem(this.DAILY_REWARD_KEY, JSON.stringify(this.dailyRewardData));
  166. }
  167. private getCurrentDateString(): string {
  168. const now = new Date();
  169. const month = (now.getMonth() + 1).toString();
  170. const day = now.getDate().toString();
  171. const paddedMonth = month.length === 1 ? '0' + month : month;
  172. const paddedDay = day.length === 1 ? '0' + day : day;
  173. return `${now.getFullYear()}-${paddedMonth}-${paddedDay}`;
  174. }
  175. private setupEventListeners() {
  176. // 监听货币变化事件,更新UI
  177. EventBus.getInstance().on(GameEvents.CURRENCY_CHANGED, this.updateUI, this);
  178. }
  179. private updateUI() {
  180. if (!this.shopConfig || !this.dailyRewardData) {
  181. console.log('[ShopController] 配置或数据未准备好,跳过UI更新');
  182. return;
  183. }
  184. console.log('[ShopController] 开始更新UI,数据状态:', {
  185. moneyFreeUsed: this.dailyRewardData.moneyFreeUsed,
  186. diamondFreeUsed: this.dailyRewardData.diamondFreeUsed
  187. });
  188. // 更新钞票奖励UI
  189. this.updateMoneyRewardUI();
  190. // 更新钻石奖励UI
  191. this.updateDiamondRewardUI();
  192. }
  193. private updateMoneyRewardUI() {
  194. if (!this.shopConfig || !this.dailyRewardData) return;
  195. const config = this.shopConfig.dailyRewards.money;
  196. const freeCount = this.dailyRewardData.moneyFreeCount;
  197. const adCount = this.dailyRewardData.moneyAdCount;
  198. const totalCount = freeCount + adCount;
  199. const maxCount = config.maxClaimsPerDay;
  200. const freeUsed = this.dailyRewardData.moneyFreeUsed;
  201. // 计算当前次数索引(免费机会未使用时为0,否则为总次数)
  202. const currentIndex = freeUsed ? totalCount : 0;
  203. const currentReward = config.rewards[currentIndex] || config.rewards[config.rewards.length - 1];
  204. // 更新金额显示
  205. if (this.moneyAmountLabel) {
  206. this.moneyAmountLabel.string = this.formatNumberWithSpaces(currentReward);
  207. }
  208. // 更新按钮状态和显示
  209. if (this.moneyButton) {
  210. const canClaim = totalCount < maxCount;
  211. this.moneyButton.interactable = canClaim;
  212. // 更新按钮文本
  213. const buttonLabel = this.moneyButton.node.getChildByName('Label')?.getComponent(Label);
  214. if (buttonLabel) {
  215. if (!canClaim) {
  216. buttonLabel.string = "今日已达上限";
  217. } else if (!freeUsed) {
  218. buttonLabel.string = "免 费";
  219. } else {
  220. buttonLabel.string = "观看广告";
  221. }
  222. }
  223. // 更新次数显示和图标
  224. if (this.moneyCountLabel) {
  225. if (!freeUsed) {
  226. this.moneyCountLabel.string = "免 费";
  227. // 免费时保持图标隐藏(用户已手动隐藏)
  228. console.log('[ShopController] 钞票免费状态:保持图标隐藏,显示"免费"');
  229. } else {
  230. const remainingCount = maxCount - totalCount;
  231. this.moneyCountLabel.string = `${remainingCount}/${maxCount}`;
  232. // 非免费时显示图标
  233. if (this.moneyIconNode) {
  234. this.moneyIconNode.active = true;
  235. console.log(`[ShopController] 钞票广告状态:显示图标,剩余次数 ${remainingCount}/${maxCount}`);
  236. }
  237. }
  238. }
  239. }
  240. }
  241. private updateDiamondRewardUI() {
  242. if (!this.shopConfig || !this.dailyRewardData) return;
  243. const config = this.shopConfig.dailyRewards.diamond;
  244. const freeCount = this.dailyRewardData.diamondsFreeCount;
  245. const adCount = this.dailyRewardData.diamondsAdCount;
  246. const totalCount = freeCount + adCount;
  247. const maxCount = config.maxClaimsPerDay;
  248. const freeUsed = this.dailyRewardData.diamondFreeUsed;
  249. // 计算当前次数索引(免费机会未使用时为0,否则为总次数)
  250. const currentIndex = freeUsed ? totalCount : 0;
  251. const currentReward = config.rewards[currentIndex] || config.rewards[config.rewards.length - 1];
  252. // 更新金额显示
  253. if (this.diamondAmountLabel) {
  254. this.diamondAmountLabel.string = this.formatNumberWithSpaces(currentReward);
  255. }
  256. // 更新按钮状态和显示
  257. if (this.diamondButton) {
  258. const canClaim = totalCount < maxCount;
  259. this.diamondButton.interactable = canClaim;
  260. // 更新按钮文本
  261. const buttonLabel = this.diamondButton.node.getChildByName('Label')?.getComponent(Label);
  262. if (buttonLabel) {
  263. if (!canClaim) {
  264. buttonLabel.string = "今日已达上限";
  265. } else if (!freeUsed) {
  266. buttonLabel.string = "免 费";
  267. } else {
  268. buttonLabel.string = "观看广告";
  269. }
  270. }
  271. // 更新次数显示和图标
  272. if (this.diamondCountLabel) {
  273. if (!freeUsed) {
  274. this.diamondCountLabel.string = "免 费";
  275. // 免费时保持图标隐藏(用户已手动隐藏)
  276. console.log('[ShopController] 钻石免费状态:保持图标隐藏,显示"免费"');
  277. } else {
  278. const remainingCount = maxCount - totalCount;
  279. this.diamondCountLabel.string = `${remainingCount}/${maxCount}`;
  280. // 非免费时显示图标
  281. if (this.diamondIconNode) {
  282. this.diamondIconNode.active = true;
  283. console.log(`[ShopController] 钻石广告状态:显示图标,剩余次数 ${remainingCount}/${maxCount}`);
  284. }
  285. }
  286. }
  287. }
  288. }
  289. // 钞票奖励按钮点击事件
  290. public onMoneyRewardClick() {
  291. if (!this.shopConfig || !this.dailyRewardData) return;
  292. const config = this.shopConfig.dailyRewards.money;
  293. const freeCount = this.dailyRewardData.moneyFreeCount;
  294. const adCount = this.dailyRewardData.moneyAdCount;
  295. const totalCount = freeCount + adCount;
  296. const maxCount = config.maxClaimsPerDay;
  297. const freeUsed = this.dailyRewardData.moneyFreeUsed;
  298. if (totalCount >= maxCount) {
  299. console.log('[ShopController] 钞票奖励已达每日上限');
  300. return;
  301. }
  302. // 如果免费机会未使用,直接发放奖励
  303. if (!freeUsed) {
  304. console.log('[ShopController] 使用免费机会获取钞票奖励');
  305. this.dailyRewardData.moneyFreeUsed = true;
  306. // 免费奖励不计入freeCount,只标记为已使用
  307. this.saveDailyRewardData();
  308. this.updateUI();
  309. // 播放奖励动画并添加货币
  310. const amount = config.rewards[0] || config.rewards[config.rewards.length - 1];
  311. this.saveDataManager.addMoney(amount, 'daily_free_reward');
  312. this.playMoneyRewardAnimation(amount, () => {
  313. console.log(`[ShopController] 钞票免费奖励动画播放完成: ${amount}`);
  314. });
  315. } else {
  316. // 看广告增加次数
  317. this.showAdForMoneyReward();
  318. }
  319. }
  320. // 钻石奖励按钮点击事件
  321. public onDiamondRewardClick() {
  322. if (!this.shopConfig || !this.dailyRewardData) return;
  323. const config = this.shopConfig.dailyRewards.diamond;
  324. const freeCount = this.dailyRewardData.diamondsFreeCount;
  325. const adCount = this.dailyRewardData.diamondsAdCount;
  326. const totalCount = freeCount + adCount;
  327. const maxCount = config.maxClaimsPerDay;
  328. const freeUsed = this.dailyRewardData.diamondFreeUsed;
  329. if (totalCount >= maxCount) {
  330. console.log('[ShopController] 钻石奖励已达每日上限');
  331. return;
  332. }
  333. // 如果免费机会未使用,直接发放奖励
  334. if (!freeUsed) {
  335. console.log('[ShopController] 使用免费机会获取钻石奖励');
  336. this.dailyRewardData.diamondFreeUsed = true;
  337. // 免费奖励不计入freeCount,只标记为已使用
  338. this.saveDailyRewardData();
  339. this.updateUI();
  340. // 播放奖励动画并添加货币
  341. const amount = config.rewards[0] || config.rewards[config.rewards.length - 1];
  342. this.saveDataManager.addDiamonds(amount, 'daily_free_reward');
  343. this.playDiamondRewardAnimation(amount, () => {
  344. console.log(`[ShopController] 钻石免费奖励动画播放完成: ${amount}`);
  345. });
  346. } else {
  347. // 看广告增加次数
  348. this.showAdForDiamondReward();
  349. }
  350. }
  351. private claimMoneyReward(isFromAd: boolean) {
  352. const config = this.shopConfig.dailyRewards.money;
  353. // 更新领取次数(先更新数据)
  354. if (isFromAd) {
  355. this.dailyRewardData.moneyAdCount++;
  356. } else {
  357. this.dailyRewardData.moneyFreeCount++;
  358. }
  359. // 计算当前次数索引和对应奖励
  360. const totalCount = this.dailyRewardData.moneyFreeCount + this.dailyRewardData.moneyAdCount;
  361. const currentIndex = totalCount - 1; // 减1因为已经增加了次数
  362. const amount = config.rewards[currentIndex] || config.rewards[config.rewards.length - 1];
  363. this.saveDailyRewardData();
  364. this.updateUI();
  365. console.log(`[ShopController] 开始播放钞票奖励动画: ${amount}, 来源: ${isFromAd ? '广告' : '免费'}`);
  366. // 添加货币到账户并播放奖励动画
  367. this.saveDataManager.addMoney(amount, isFromAd ? 'daily_ad_reward' : 'daily_free_reward');
  368. this.playMoneyRewardAnimation(amount, () => {
  369. console.log(`[ShopController] 钞票奖励动画播放完成: ${amount}`);
  370. });
  371. }
  372. private claimDiamondReward(isFromAd: boolean) {
  373. const config = this.shopConfig.dailyRewards.diamond;
  374. // 更新领取次数(先更新数据)
  375. if (isFromAd) {
  376. this.dailyRewardData.diamondsAdCount++;
  377. } else {
  378. this.dailyRewardData.diamondsFreeCount++;
  379. }
  380. // 计算当前次数索引和对应奖励
  381. const totalCount = this.dailyRewardData.diamondsFreeCount + this.dailyRewardData.diamondsAdCount;
  382. const currentIndex = totalCount - 1; // 减1因为已经增加了次数
  383. const amount = config.rewards[currentIndex] || config.rewards[config.rewards.length - 1];
  384. this.saveDailyRewardData();
  385. this.updateUI();
  386. console.log(`[ShopController] 开始播放钻石奖励动画: ${amount}, 来源: ${isFromAd ? '广告' : '免费'}`);
  387. // 播放奖励动画,动画完成后会自动添加钻石
  388. this.playDiamondRewardAnimation(amount, () => {
  389. console.log(`[ShopController] 钻石奖励动画播放完成: ${amount}`);
  390. });
  391. }
  392. private showAdForMoneyReward() {
  393. console.log('[ShopController] 显示钞票奖励广告');
  394. // 显示激励视频广告
  395. AdManager.getInstance().showRewardedVideoAd(
  396. () => {
  397. // 广告观看完成,发放钞票奖励
  398. console.log('[ShopController] 广告观看完成,发放钞票奖励');
  399. this.claimMoneyReward(true);
  400. },
  401. (error) => {
  402. console.error('[ShopController] 钞票奖励广告显示失败:', error);
  403. // 广告失败时不给予奖励
  404. }
  405. );
  406. }
  407. private showAdForDiamondReward() {
  408. console.log('[ShopController] 显示钻石奖励广告');
  409. // 显示激励视频广告
  410. AdManager.getInstance().showRewardedVideoAd(
  411. () => {
  412. // 广告观看完成,发放钻石奖励
  413. console.log('[ShopController] 广告观看完成,发放钻石奖励');
  414. this.claimDiamondReward(true);
  415. },
  416. (error) => {
  417. console.error('[ShopController] 钻石奖励广告显示失败:', error);
  418. // 广告失败时不给予奖励
  419. }
  420. );
  421. }
  422. // showRewardEffect方法已被MoneyAni.playReward替代,不再需要
  423. // Cost按钮相关方法已移除,功能已整合到主按钮中
  424. // 从配置JSON更新钞票数值显示
  425. private updateMoneyAmountFromConfig() {
  426. if (this.moneyAmountLabel && this.shopConfig) {
  427. // 从配置中读取下一次的钞票数值
  428. const nextMoneyAmount = this.shopConfig.dailyRewards.money.rewards[0] || 100;
  429. this.moneyAmountLabel.string = this.formatNumberWithSpaces(nextMoneyAmount);
  430. console.log('[ShopController] 从配置更新钞票数值:', nextMoneyAmount);
  431. }
  432. }
  433. // 从配置JSON更新钻石数值显示
  434. private updateDiamondAmountFromConfig() {
  435. if (this.diamondAmountLabel && this.shopConfig) {
  436. // 从配置中读取下一次的钻石数值
  437. const nextDiamondAmount = this.shopConfig.dailyRewards.diamond.rewards[0] || 10;
  438. this.diamondAmountLabel.string = this.formatNumberWithSpaces(nextDiamondAmount);
  439. console.log('[ShopController] 从配置更新钻石数值:', nextDiamondAmount);
  440. }
  441. }
  442. /**
  443. * 播放钞票奖励动画
  444. */
  445. private playMoneyRewardAnimation(amount: number, onComplete?: () => void) {
  446. // 查找场景中的MoneyAni组件
  447. const scene = director.getScene();
  448. if (!scene) {
  449. console.error('[ShopController] 无法获取当前场景');
  450. if (onComplete) onComplete();
  451. return;
  452. }
  453. const findMoneyAni = (node: Node): MoneyAni | null => {
  454. const moneyAni = node.getComponent(MoneyAni);
  455. if (moneyAni) return moneyAni;
  456. for (const child of node.children) {
  457. const result = findMoneyAni(child);
  458. if (result) return result;
  459. }
  460. return null;
  461. };
  462. const moneyAni = findMoneyAni(scene);
  463. if (!moneyAni) {
  464. console.error('[ShopController] 场景中未找到MoneyAni组件');
  465. if (onComplete) onComplete();
  466. return;
  467. }
  468. // 临时设置钞票起始位置
  469. if (this.billSpriteNode) {
  470. moneyAni.coinStartNode = this.billSpriteNode;
  471. }
  472. // 播放钞票动画
  473. moneyAni.playRewardAnimation(amount, 0, onComplete);
  474. }
  475. /**
  476. * 播放钻石奖励动画
  477. */
  478. private playDiamondRewardAnimation(amount: number, onComplete?: () => void) {
  479. // 查找场景中的MoneyAni组件
  480. const scene = director.getScene();
  481. if (!scene) {
  482. console.error('[ShopController] 无法获取当前场景');
  483. if (onComplete) onComplete();
  484. return;
  485. }
  486. const findMoneyAni = (node: Node): MoneyAni | null => {
  487. const moneyAni = node.getComponent(MoneyAni);
  488. if (moneyAni) return moneyAni;
  489. for (const child of node.children) {
  490. const result = findMoneyAni(child);
  491. if (result) return result;
  492. }
  493. return null;
  494. };
  495. const moneyAni = findMoneyAni(scene);
  496. if (!moneyAni) {
  497. console.error('[ShopController] 场景中未找到MoneyAni组件');
  498. if (onComplete) onComplete();
  499. return;
  500. }
  501. // 临时设置钻石起始位置
  502. if (this.diamondSpriteNode) {
  503. moneyAni.diamondStartNode = this.diamondSpriteNode;
  504. }
  505. // 播放钻石动画
  506. moneyAni.playRewardAnimation(0, amount, onComplete);
  507. }
  508. onDestroy() {
  509. // 移除事件监听
  510. EventBus.getInstance().off(GameEvents.CURRENCY_CHANGED, this.updateUI, this);
  511. }
  512. // 调试方法:重置每日奖励数据
  513. public resetDailyRewards() {
  514. const today = this.getCurrentDateString();
  515. this.resetDailyRewardData(today);
  516. this.updateUI();
  517. console.log('[ShopController] 每日奖励数据已重置');
  518. }
  519. // 获取当前每日奖励状态(用于调试)
  520. public getDailyRewardStatus() {
  521. return {
  522. config: this.shopConfig,
  523. data: this.dailyRewardData,
  524. today: this.getCurrentDateString()
  525. };
  526. }
  527. }