ShopController.ts 25 KB

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