import { Controller, Get, Query } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiQuery, } from '@nestjs/swagger'; import { DashboardService } from '../../application/services/dashboard.service'; @ApiTags('Dashboard') @ApiBearerAuth() @Controller('dashboard') export class DashboardController { constructor(private readonly dashboardService: DashboardService) {} @Get() @ApiOperation({ summary: '获取仪表盘统计数据' }) async getStats() { const raw = await this.dashboardService.getDashboardStats(); // 计算24小时价格变化 let priceChange24h = 0; if (raw.latestPrice) { const open = parseFloat(raw.latestPrice.open) || 1; const close = parseFloat(raw.latestPrice.close) || 1; priceChange24h = (close - open) / open; } // 详细算力分解数据 const dc = raw.detailedContribution || {}; // 转换为前端期望的格式 return { // 基础统计 totalUsers: raw.users?.total || 0, adoptedUsers: raw.users?.adopted || 0, totalTrees: raw.contribution?.totalTrees || 0, networkEffectiveContribution: raw.contribution?.effectiveContribution || '0', networkTotalContribution: raw.contribution?.totalContribution || '0', networkLevelPending: dc.levelContribution?.pending || '0', networkBonusPending: dc.bonusContribution?.pending || '0', totalDistributed: raw.mining?.totalMined || '0', totalBurned: raw.mining?.latestDailyStat?.totalBurned || '0', circulationPool: raw.trading?.circulationPool?.totalShares || '0', currentPrice: raw.latestPrice?.close || '1', priceChange24h, totalOrders: raw.trading?.totalAccounts || 0, totalTrades: raw.trading?.totalAccounts || 0, // ========== 详细算力分解 ========== detailedContribution: { totalTrees: dc.totalTrees || 0, // 全网算力(理论值)= 总树数 * 22617 networkTotalTheory: dc.networkTotalTheory || '0', // 个人算力(70%) personalTheory: dc.personalTheory || '0', personalActual: raw.contribution?.personalContribution || '0', // 运营账户(12%) operationTheory: dc.operationTheory || '0', operationActual: dc.operationActual || '0', // 省公司(1%) provinceTheory: dc.provinceTheory || '0', provinceActual: dc.provinceActual || '0', // 市公司(2%) cityTheory: dc.cityTheory || '0', cityActual: dc.cityActual || '0', // 层级算力(7.5%) level: { theory: dc.levelTheory || '0', unlocked: dc.levelContribution?.unlocked || '0', pending: dc.levelContribution?.pending || '0', // 分档详情 tier1: dc.levelContribution?.byTier?.tier1 || { unlocked: '0', pending: '0' }, tier2: dc.levelContribution?.byTier?.tier2 || { unlocked: '0', pending: '0' }, tier3: dc.levelContribution?.byTier?.tier3 || { unlocked: '0', pending: '0' }, }, // 团队奖励算力(7.5%) bonus: { theory: dc.bonusTheory || '0', unlocked: dc.bonusContribution?.unlocked || '0', pending: dc.bonusContribution?.pending || '0', // 分档详情 tier1: dc.bonusContribution?.byTier?.tier1 || { unlocked: '0', pending: '0' }, tier2: dc.bonusContribution?.byTier?.tier2 || { unlocked: '0', pending: '0' }, tier3: dc.bonusContribution?.byTier?.tier3 || { unlocked: '0', pending: '0' }, }, }, }; } @Get('stats') @ApiOperation({ summary: '获取仪表盘统计数据(别名)' }) async getStatsAlias() { return this.getStats(); } @Get('realtime') @ApiOperation({ summary: '获取实时数据' }) async getRealtimeStats() { const raw = await this.dashboardService.getRealtimeStats(); // 转换为前端期望的格式 return { currentMinuteDistribution: raw.minuteDistribution || '0', currentMinuteBurn: '0', // 暂无实时销毁数据 activeOrders: 0, // 暂无实时订单数据 pendingTrades: 0, // 暂无待处理交易数据 lastPriceUpdateAt: raw.timestamp, }; } @Get('reports') @ApiOperation({ summary: '获取每日报表' }) @ApiQuery({ name: 'page', required: false, type: Number }) @ApiQuery({ name: 'pageSize', required: false, type: Number }) async getReports( @Query('page') page?: number, @Query('pageSize') pageSize?: number, ) { return this.dashboardService.getReports(page ?? 1, pageSize ?? 30); } }