diff --git a/backend/services/reward-service/src/application/services/reward-application.service.ts b/backend/services/reward-service/src/application/services/reward-application.service.ts index 1b61be41..411335b0 100644 --- a/backend/services/reward-service/src/application/services/reward-application.service.ts +++ b/backend/services/reward-service/src/application/services/reward-application.service.ts @@ -78,7 +78,8 @@ export class RewardApplicationService { } // 4. 写入 Outbox 发送到 wallet-service 同步汇总数据 - await this.publishSummaryUpdatesToOutbox(updatedSummaries); + // [已屏蔽] 前端直接从 reward-service 查询,不再同步到 wallet-service + // await this.publishSummaryUpdatesToOutbox(updatedSummaries); // 5. 发布领域事件 for (const reward of rewards) { @@ -123,9 +124,10 @@ export class RewardApplicationService { await this.rewardSummaryRepository.save(summary); // 写入 Outbox 同步到 wallet-service - if (claimedCount > 0) { - await this.publishSummaryUpdatesToOutbox([summary]); - } + // [已屏蔽] 前端直接从 reward-service 查询,不再同步到 wallet-service + // if (claimedCount > 0) { + // await this.publishSummaryUpdatesToOutbox([summary]); + // } this.logger.log(`Claimed ${claimedCount} rewards for user ${userId}, total ${totalUsdtClaimed} USDT`); @@ -198,7 +200,8 @@ export class RewardApplicationService { await this.rewardSummaryRepository.save(summary); // 写入 Outbox 同步到 wallet-service - await this.publishSummaryUpdatesToOutbox([summary]); + // [已屏蔽] 前端直接从 reward-service 查询,不再同步到 wallet-service + // await this.publishSummaryUpdatesToOutbox([summary]); } this.logger.log(`Settled ${totalUsdt} USDT for accountSequence ${params.accountSequence}`); @@ -269,9 +272,10 @@ export class RewardApplicationService { } // 写入 Outbox 同步到 wallet-service - if (updatedSummaries.length > 0) { - await this.publishSummaryUpdatesToOutbox(updatedSummaries); - } + // [已屏蔽] 前端直接从 reward-service 查询,不再同步到 wallet-service + // if (updatedSummaries.length > 0) { + // await this.publishSummaryUpdatesToOutbox(updatedSummaries); + // } this.logger.log(`Expired ${expiredRewards.length} rewards, total ${totalUsdtExpired} USDT`); diff --git a/backend/services/wallet-service/src/infrastructure/kafka/kafka.module.ts b/backend/services/wallet-service/src/infrastructure/kafka/kafka.module.ts index 86df97a9..723c0f8f 100644 --- a/backend/services/wallet-service/src/infrastructure/kafka/kafka.module.ts +++ b/backend/services/wallet-service/src/infrastructure/kafka/kafka.module.ts @@ -3,8 +3,9 @@ import { ConfigModule, ConfigService } from '@nestjs/config'; import { ClientsModule, Transport } from '@nestjs/microservices'; import { EventPublisherService } from './event-publisher.service'; import { DepositEventConsumerService } from './deposit-event-consumer.service'; -import { RewardEventConsumerController } from './reward-event-consumer.controller'; -import { EventAckPublisher } from './event-ack.publisher'; +// [已屏蔽] 前端直接从 reward-service 查询,不再订阅 reward-service 消息 +// import { RewardEventConsumerController } from './reward-event-consumer.controller'; +// import { EventAckPublisher } from './event-ack.publisher'; import { PrismaService } from '../persistence/prisma/prisma.service'; @Global() @@ -30,8 +31,10 @@ import { PrismaService } from '../persistence/prisma/prisma.service'; }, ]), ], - controllers: [RewardEventConsumerController], - providers: [PrismaService, EventPublisherService, DepositEventConsumerService, EventAckPublisher], - exports: [EventPublisherService, DepositEventConsumerService, EventAckPublisher, ClientsModule], + // [已屏蔽] 前端直接从 reward-service 查询,不再订阅 reward-service 消息 + // controllers: [RewardEventConsumerController], + controllers: [], + providers: [PrismaService, EventPublisherService, DepositEventConsumerService], + exports: [EventPublisherService, DepositEventConsumerService, ClientsModule], }) export class KafkaModule {} diff --git a/frontend/mobile-app/lib/core/di/injection_container.dart b/frontend/mobile-app/lib/core/di/injection_container.dart index 9b996f1b..111961e0 100644 --- a/frontend/mobile-app/lib/core/di/injection_container.dart +++ b/frontend/mobile-app/lib/core/di/injection_container.dart @@ -8,6 +8,7 @@ import '../services/authorization_service.dart'; import '../services/deposit_service.dart'; import '../services/wallet_service.dart'; import '../services/planting_service.dart'; +import '../services/reward_service.dart'; // Storage Providers final secureStorageProvider = Provider((ref) { @@ -65,6 +66,12 @@ final plantingServiceProvider = Provider((ref) { return PlantingService(apiClient: apiClient); }); +// Reward Service Provider (直接调用 reward-service) +final rewardServiceProvider = Provider((ref) { + final apiClient = ref.watch(apiClientProvider); + return RewardService(apiClient: apiClient); +}); + // Override provider with initialized instance ProviderContainer createProviderContainer(LocalStorage localStorage) { return ProviderContainer( diff --git a/frontend/mobile-app/lib/core/services/reward_service.dart b/frontend/mobile-app/lib/core/services/reward_service.dart new file mode 100644 index 00000000..83d34f8d --- /dev/null +++ b/frontend/mobile-app/lib/core/services/reward_service.dart @@ -0,0 +1,110 @@ +import 'package:flutter/foundation.dart'; +import '../network/api_client.dart'; + +/// 奖励汇总信息 (从 reward-service 获取) +class RewardSummary { + final double pendingUsdt; + final double pendingHashpower; + final DateTime? pendingExpireAt; + final int pendingRemainingTimeMs; + final double settleableUsdt; + final double settleableHashpower; + final double settledTotalUsdt; + final double settledTotalHashpower; + final double expiredTotalUsdt; + final double expiredTotalHashpower; + + RewardSummary({ + required this.pendingUsdt, + required this.pendingHashpower, + this.pendingExpireAt, + required this.pendingRemainingTimeMs, + required this.settleableUsdt, + required this.settleableHashpower, + required this.settledTotalUsdt, + required this.settledTotalHashpower, + required this.expiredTotalUsdt, + required this.expiredTotalHashpower, + }); + + factory RewardSummary.fromJson(Map json) { + return RewardSummary( + pendingUsdt: (json['pendingUsdt'] ?? 0).toDouble(), + pendingHashpower: (json['pendingHashpower'] ?? 0).toDouble(), + pendingExpireAt: json['pendingExpireAt'] != null + ? DateTime.tryParse(json['pendingExpireAt']) + : null, + pendingRemainingTimeMs: (json['pendingRemainingTimeMs'] ?? 0).toInt(), + settleableUsdt: (json['settleableUsdt'] ?? 0).toDouble(), + settleableHashpower: (json['settleableHashpower'] ?? 0).toDouble(), + settledTotalUsdt: (json['settledTotalUsdt'] ?? 0).toDouble(), + settledTotalHashpower: (json['settledTotalHashpower'] ?? 0).toDouble(), + expiredTotalUsdt: (json['expiredTotalUsdt'] ?? 0).toDouble(), + expiredTotalHashpower: (json['expiredTotalHashpower'] ?? 0).toDouble(), + ); + } + + /// 计算剩余秒数 + int get pendingRemainingSeconds => (pendingRemainingTimeMs / 1000).round(); +} + +/// 奖励服务 +/// +/// 直接调用 reward-service 的 API 获取奖励数据 +/// 不再通过 wallet-service 中转 +class RewardService { + final ApiClient _apiClient; + + RewardService({required ApiClient apiClient}) : _apiClient = apiClient; + + /// 获取我的奖励汇总 + /// + /// 调用 GET /rewards/summary (reward-service) + Future getMyRewardSummary() async { + try { + debugPrint('[RewardService] ========== 获取奖励汇总 =========='); + debugPrint('[RewardService] 请求: GET /rewards/summary'); + + final response = await _apiClient.get('/rewards/summary'); + + debugPrint('[RewardService] 响应状态码: ${response.statusCode}'); + debugPrint('[RewardService] 响应数据类型: ${response.data.runtimeType}'); + + if (response.statusCode == 200) { + final responseData = response.data as Map; + debugPrint('[RewardService] 原始响应数据: $responseData'); + + // API 返回格式: { success: true, data: {...}, timestamp: "..." } + // 需要解包内层的 data 字段 + final data = responseData['data'] as Map? ?? responseData; + debugPrint('[RewardService] 解包后数据: $data'); + + final summary = RewardSummary.fromJson(data); + debugPrint('[RewardService] -------- 解析结果 --------'); + debugPrint('[RewardService] pendingUsdt: ${summary.pendingUsdt}'); + debugPrint('[RewardService] pendingHashpower: ${summary.pendingHashpower}'); + debugPrint('[RewardService] pendingExpireAt: ${summary.pendingExpireAt}'); + debugPrint('[RewardService] pendingRemainingTimeMs: ${summary.pendingRemainingTimeMs}'); + debugPrint('[RewardService] pendingRemainingSeconds: ${summary.pendingRemainingSeconds}'); + debugPrint('[RewardService] settleableUsdt: ${summary.settleableUsdt}'); + debugPrint('[RewardService] settleableHashpower: ${summary.settleableHashpower}'); + debugPrint('[RewardService] settledTotalUsdt: ${summary.settledTotalUsdt}'); + debugPrint('[RewardService] settledTotalHashpower: ${summary.settledTotalHashpower}'); + debugPrint('[RewardService] expiredTotalUsdt: ${summary.expiredTotalUsdt}'); + debugPrint('[RewardService] expiredTotalHashpower: ${summary.expiredTotalHashpower}'); + debugPrint('[RewardService] ================================'); + + return summary; + } + + debugPrint('[RewardService] 请求失败,状态码: ${response.statusCode}'); + debugPrint('[RewardService] 响应内容: ${response.data}'); + throw Exception('获取奖励汇总失败: ${response.statusCode}'); + } catch (e, stackTrace) { + debugPrint('[RewardService] !!!!!!!!!! 获取奖励汇总异常 !!!!!!!!!!'); + debugPrint('[RewardService] 错误: $e'); + debugPrint('[RewardService] 堆栈: $stackTrace'); + rethrow; + } + } +} diff --git a/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart b/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart index be692b65..09a1e521 100644 --- a/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart +++ b/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart @@ -58,7 +58,7 @@ class _ProfilePageState extends ConsumerState { int _communityMonthlyTarget = 10; // 月度考核目标 int _communityMonthIndex = 0; // 当前考核月份 - // 收益数据(从 wallet-service 获取) + // 收益数据(从 reward-service 直接获取) double _pendingUsdt = 0.0; double _pendingPower = 0.0; double _settleableUsdt = 0.0; @@ -344,41 +344,41 @@ class _ProfilePageState extends ConsumerState { } } - /// 加载钱包和收益数据 (from wallet-service) + /// 加载收益数据 (直接从 reward-service 获取) Future _loadWalletData() async { try { - debugPrint('[ProfilePage] ========== 加载钱包数据 =========='); + debugPrint('[ProfilePage] ========== 加载收益数据 =========='); debugPrint('[ProfilePage] mounted: $mounted'); setState(() { _isLoadingWallet = true; _walletError = null; }); - debugPrint('[ProfilePage] 获取 walletServiceProvider...'); - final walletService = ref.read(walletServiceProvider); - debugPrint('[ProfilePage] 调用 getMyWallet()...'); - final wallet = await walletService.getMyWallet(); + debugPrint('[ProfilePage] 获取 rewardServiceProvider...'); + final rewardService = ref.read(rewardServiceProvider); + debugPrint('[ProfilePage] 调用 getMyRewardSummary()...'); + final summary = await rewardService.getMyRewardSummary(); - debugPrint('[ProfilePage] -------- 钱包数据加载成功 --------'); - debugPrint('[ProfilePage] 待领取 USDT: ${wallet.rewards.pendingUsdt}'); - debugPrint('[ProfilePage] 待领取 算力: ${wallet.rewards.pendingHashpower}'); - debugPrint('[ProfilePage] 可结算 USDT: ${wallet.rewards.settleableUsdt}'); - debugPrint('[ProfilePage] 已结算 USDT: ${wallet.rewards.settledTotalUsdt}'); - debugPrint('[ProfilePage] 已过期 USDT: ${wallet.rewards.expiredTotalUsdt}'); - debugPrint('[ProfilePage] 已过期 算力: ${wallet.rewards.expiredTotalHashpower}'); - debugPrint('[ProfilePage] 过期时间: ${wallet.rewards.pendingExpireAt}'); - debugPrint('[ProfilePage] 剩余秒数: ${wallet.rewards.pendingRemainingSeconds}'); + debugPrint('[ProfilePage] -------- 收益数据加载成功 --------'); + debugPrint('[ProfilePage] 待领取 USDT: ${summary.pendingUsdt}'); + debugPrint('[ProfilePage] 待领取 算力: ${summary.pendingHashpower}'); + debugPrint('[ProfilePage] 可结算 USDT: ${summary.settleableUsdt}'); + debugPrint('[ProfilePage] 已结算 USDT: ${summary.settledTotalUsdt}'); + debugPrint('[ProfilePage] 已过期 USDT: ${summary.expiredTotalUsdt}'); + debugPrint('[ProfilePage] 已过期 算力: ${summary.expiredTotalHashpower}'); + debugPrint('[ProfilePage] 过期时间: ${summary.pendingExpireAt}'); + debugPrint('[ProfilePage] 剩余秒数: ${summary.pendingRemainingSeconds}'); if (mounted) { debugPrint('[ProfilePage] 更新 UI 状态...'); setState(() { - _pendingUsdt = wallet.rewards.pendingUsdt; - _pendingPower = wallet.rewards.pendingHashpower; - _settleableUsdt = wallet.rewards.settleableUsdt; - _settledUsdt = wallet.rewards.settledTotalUsdt; - _expiredUsdt = wallet.rewards.expiredTotalUsdt; - _expiredPower = wallet.rewards.expiredTotalHashpower; - _remainingSeconds = wallet.rewards.pendingRemainingSeconds; + _pendingUsdt = summary.pendingUsdt; + _pendingPower = summary.pendingHashpower; + _settleableUsdt = summary.settleableUsdt; + _settledUsdt = summary.settledTotalUsdt; + _expiredUsdt = summary.expiredTotalUsdt; + _expiredPower = summary.expiredTotalHashpower; + _remainingSeconds = summary.pendingRemainingSeconds; _isLoadingWallet = false; }); @@ -398,7 +398,7 @@ class _ProfilePageState extends ConsumerState { } debugPrint('[ProfilePage] ================================'); } catch (e, stackTrace) { - debugPrint('[ProfilePage] !!!!!!!!!! 加载钱包数据失败 !!!!!!!!!!'); + debugPrint('[ProfilePage] !!!!!!!!!! 加载收益数据失败 !!!!!!!!!!'); debugPrint('[ProfilePage] 错误类型: ${e.runtimeType}'); debugPrint('[ProfilePage] 错误信息: $e'); debugPrint('[ProfilePage] 堆栈跟踪:');