feat(reward): 可结算列表改为从 reward-service 读取
将前端可结算奖励列表的数据源从 wallet-service 改为 reward-service: - 后端:在 reward-service 添加 GET /rewards/settleable 接口 - 前端:修改 getSettleableRewards() 调用 /rewards/settleable - 前端:更新 SettleableRewardItem 字段映射 (rightType, claimedAt, sourceOrderNo, memo) 解决权益收益(社区权益、市区域权益)无法在可结算列表显示的问题。 遵循单一数据源原则,reward-service 是奖励的权威数据源。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
834a1fc0b0
commit
36074948d7
|
|
@ -58,4 +58,12 @@ export class RewardController {
|
|||
const accountSequence = req.user.accountSequence;
|
||||
return this.rewardService.getPendingRewards(accountSequence);
|
||||
}
|
||||
|
||||
@Get('settleable')
|
||||
@ApiOperation({ summary: '获取可结算奖励列表' })
|
||||
@ApiResponse({ status: 200, description: '成功' })
|
||||
async getSettleable(@Request() req) {
|
||||
const accountSequence = req.user.accountSequence;
|
||||
return this.rewardService.getSettleableRewards(accountSequence);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -444,6 +444,24 @@ export class RewardApplicationService {
|
|||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可结算奖励列表
|
||||
*/
|
||||
async getSettleableRewards(accountSequence: string) {
|
||||
const rewards = await this.rewardLedgerEntryRepository.findSettleableByAccountSequence(accountSequence);
|
||||
|
||||
return rewards.map(r => ({
|
||||
id: r.id?.toString(),
|
||||
rightType: r.rewardSource.rightType,
|
||||
usdtAmount: r.usdtAmount.amount,
|
||||
hashpowerAmount: r.hashpowerAmount.value,
|
||||
createdAt: r.createdAt,
|
||||
claimedAt: r.claimedAt,
|
||||
sourceOrderNo: r.sourceOrderNo,
|
||||
memo: r.memo,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布汇总更新到 Outbox(同步到 wallet-service)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -63,40 +63,43 @@ class PendingRewardItem {
|
|||
String get rightTypeName => getAllocationTypeName(rightType);
|
||||
}
|
||||
|
||||
/// 可结算奖励条目 (从 GET /wallet/settleable-rewards 获取)
|
||||
/// 可结算奖励条目 (从 GET /rewards/settleable 获取)
|
||||
class SettleableRewardItem {
|
||||
final String id;
|
||||
final String allocationType;
|
||||
final String rightType;
|
||||
final double usdtAmount;
|
||||
final double hashpowerAmount;
|
||||
final DateTime createdAt;
|
||||
final DateTime settledAt;
|
||||
final String sourceOrderId;
|
||||
final DateTime? claimedAt;
|
||||
final String sourceOrderNo;
|
||||
final String memo;
|
||||
|
||||
SettleableRewardItem({
|
||||
required this.id,
|
||||
required this.allocationType,
|
||||
required this.rightType,
|
||||
required this.usdtAmount,
|
||||
required this.hashpowerAmount,
|
||||
required this.createdAt,
|
||||
required this.settledAt,
|
||||
required this.sourceOrderId,
|
||||
this.claimedAt,
|
||||
required this.sourceOrderNo,
|
||||
required this.memo,
|
||||
});
|
||||
|
||||
factory SettleableRewardItem.fromJson(Map<String, dynamic> json) {
|
||||
return SettleableRewardItem(
|
||||
id: json['id']?.toString() ?? '',
|
||||
allocationType: json['allocationType'] ?? '',
|
||||
rightType: json['rightType'] ?? '',
|
||||
usdtAmount: (json['usdtAmount'] ?? 0).toDouble(),
|
||||
hashpowerAmount: (json['hashpowerAmount'] ?? 0).toDouble(),
|
||||
createdAt: DateTime.tryParse(json['createdAt'] ?? '') ?? DateTime.now(),
|
||||
settledAt: DateTime.tryParse(json['settledAt'] ?? '') ?? DateTime.now(),
|
||||
sourceOrderId: json['sourceOrderId'] ?? '',
|
||||
claimedAt: json['claimedAt'] != null ? DateTime.tryParse(json['claimedAt']) : null,
|
||||
sourceOrderNo: json['sourceOrderNo'] ?? '',
|
||||
memo: json['memo'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取权益类型的中文名称
|
||||
String get allocationTypeName => getAllocationTypeName(allocationType);
|
||||
String get rightTypeName => getAllocationTypeName(rightType);
|
||||
}
|
||||
|
||||
/// 已过期奖励条目 (从 GET /wallet/expired-rewards 获取)
|
||||
|
|
@ -297,14 +300,14 @@ class RewardService {
|
|||
|
||||
/// 获取可结算奖励列表
|
||||
///
|
||||
/// 调用 GET /wallet/settleable-rewards (wallet-service)
|
||||
/// 返回所有已领取待结算的奖励条目
|
||||
/// 调用 GET /rewards/settleable (reward-service)
|
||||
/// 返回所有可结算的奖励条目(包括权益收益和分享收益)
|
||||
Future<List<SettleableRewardItem>> getSettleableRewards() async {
|
||||
try {
|
||||
debugPrint('[RewardService] ========== 获取可结算奖励列表 ==========');
|
||||
debugPrint('[RewardService] 请求: GET /wallet/settleable-rewards');
|
||||
debugPrint('[RewardService] 请求: GET /rewards/settleable');
|
||||
|
||||
final response = await _apiClient.get('/wallet/settleable-rewards');
|
||||
final response = await _apiClient.get('/rewards/settleable');
|
||||
|
||||
debugPrint('[RewardService] 响应状态码: ${response.statusCode}');
|
||||
debugPrint('[RewardService] 响应数据类型: ${response.data.runtimeType}');
|
||||
|
|
@ -330,7 +333,7 @@ class RewardService {
|
|||
.toList();
|
||||
|
||||
for (var item in items) {
|
||||
debugPrint('[RewardService] - ${item.allocationTypeName}: ${item.usdtAmount} USDT, ${item.hashpowerAmount} 算力');
|
||||
debugPrint('[RewardService] - ${item.rightTypeName}: ${item.usdtAmount} USDT, ${item.hashpowerAmount} 贡献值');
|
||||
}
|
||||
debugPrint('[RewardService] ================================');
|
||||
|
||||
|
|
|
|||
|
|
@ -2210,8 +2210,9 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
|||
|
||||
/// 构建单条可结算奖励项
|
||||
Widget _buildSettleableRewardItem(SettleableRewardItem item) {
|
||||
// 格式化结算时间
|
||||
final settledDate = '${item.settledAt.month}/${item.settledAt.day} ${item.settledAt.hour.toString().padLeft(2, '0')}:${item.settledAt.minute.toString().padLeft(2, '0')}';
|
||||
// 格式化时间(优先使用 claimedAt,否则使用 createdAt)
|
||||
final displayDate = item.claimedAt ?? item.createdAt;
|
||||
final settledDate = '${displayDate.month}/${displayDate.day} ${displayDate.hour.toString().padLeft(2, '0')}:${displayDate.minute.toString().padLeft(2, '0')}';
|
||||
|
||||
// 构建金额显示文本
|
||||
final List<String> amountParts = [];
|
||||
|
|
@ -2242,7 +2243,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
item.allocationTypeName,
|
||||
item.rightTypeName,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: 'Inter',
|
||||
|
|
@ -2289,8 +2290,9 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
|||
|
||||
/// 构建堆叠卡片样式的可结算奖励项
|
||||
Widget _buildStackedSettleableRewardCard(SettleableRewardItem item, bool isSelected) {
|
||||
// 格式化结算时间
|
||||
final settledDate = '${item.settledAt.month}/${item.settledAt.day} ${item.settledAt.hour.toString().padLeft(2, '0')}:${item.settledAt.minute.toString().padLeft(2, '0')}';
|
||||
// 格式化时间(优先使用 claimedAt,否则使用 createdAt)
|
||||
final displayDate = item.claimedAt ?? item.createdAt;
|
||||
final settledDate = '${displayDate.month}/${displayDate.day} ${displayDate.hour.toString().padLeft(2, '0')}:${displayDate.minute.toString().padLeft(2, '0')}';
|
||||
|
||||
// 构建金额显示文本
|
||||
final List<String> amountParts = [];
|
||||
|
|
@ -2323,7 +2325,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
item.allocationTypeName,
|
||||
item.rightTypeName,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: 'Inter',
|
||||
|
|
@ -2373,7 +2375,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
item.allocationTypeName,
|
||||
item.rightTypeName,
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: 'Inter',
|
||||
|
|
@ -2552,7 +2554,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
item.allocationTypeName,
|
||||
item.rightTypeName,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: 'Inter',
|
||||
|
|
@ -2633,7 +2635,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
item.allocationTypeName,
|
||||
item.rightTypeName,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontFamily: 'Inter',
|
||||
|
|
@ -2683,7 +2685,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
item.allocationTypeName,
|
||||
item.rightTypeName,
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontFamily: 'Inter',
|
||||
|
|
|
|||
Loading…
Reference in New Issue