fix(admin): 用户详情页 USDT 改为绿积分 + 添加调试日志

前端修改:
- 钱包汇总: USDT 可用/冻结 → 绿积分 可用/冻结
- 认种汇总: 总金额 (USDT) → 总金额 (绿积分)
- 资产类型标签: USDT → 绿积分

后端修改:
- UserDetailController: 添加认种/钱包查询日志
- UserDetailQueryRepositoryImpl: 添加数据库查询日志
- 日志包含 accountSequence、查询结果、数据条数等信息

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-07 20:53:30 -08:00
parent f15bdeaef8
commit 5f6ecf9670
3 changed files with 36 additions and 5 deletions

View File

@ -7,6 +7,7 @@ import {
HttpStatus,
NotFoundException,
Inject,
Logger,
} from '@nestjs/common';
import { ReferralTreeQueryDto, LedgerQueryDto, WalletLedgerQueryDto } from '../dto/request/user-detail-query.dto';
import {
@ -32,6 +33,8 @@ import {
*/
@Controller('admin/users')
export class UserDetailController {
private readonly logger = new Logger(UserDetailController.name);
constructor(
@Inject(USER_QUERY_REPOSITORY)
private readonly userQueryRepository: IUserQueryRepository,
@ -188,7 +191,10 @@ export class UserDetailController {
@Param('accountSequence') accountSequence: string,
@Query() query: LedgerQueryDto,
): Promise<PlantingLedgerResponseDto> {
this.logger.log(`[getPlantingLedger] 查询认种分类账, accountSequence=${accountSequence}`);
const user = await this.userQueryRepository.findByAccountSequence(accountSequence);
this.logger.log(`[getPlantingLedger] 用户查询结果: ${user ? `userId=${user.userId}` : 'null'}`);
if (!user) {
throw new NotFoundException(`用户 ${accountSequence} 不存在`);
}
@ -204,6 +210,9 @@ export class UserDetailController {
),
]);
this.logger.log(`[getPlantingLedger] 认种汇总: ${JSON.stringify(summary)}`);
this.logger.log(`[getPlantingLedger] 认种流水条数: ${ledger.items.length}, total=${ledger.total}`);
return {
summary: {
totalOrders: summary?.totalOrders || 0,
@ -244,7 +253,10 @@ export class UserDetailController {
@Param('accountSequence') accountSequence: string,
@Query() query: WalletLedgerQueryDto,
): Promise<WalletLedgerResponseDto> {
this.logger.log(`[getWalletLedger] 查询钱包分类账, accountSequence=${accountSequence}`);
const user = await this.userQueryRepository.findByAccountSequence(accountSequence);
this.logger.log(`[getWalletLedger] 用户查询结果: ${user ? `userId=${user.userId}` : 'null'}`);
if (!user) {
throw new NotFoundException(`用户 ${accountSequence} 不存在`);
}
@ -264,6 +276,9 @@ export class UserDetailController {
),
]);
this.logger.log(`[getWalletLedger] 钱包汇总: ${JSON.stringify(summary)}`);
this.logger.log(`[getWalletLedger] 钱包流水条数: ${ledger.items.length}, total=${ledger.total}`);
return {
summary: {
usdtAvailable: this.formatDecimal(summary?.usdtAvailable),

View File

@ -1,4 +1,4 @@
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { Decimal } from '@prisma/client/runtime/library';
import { PrismaService } from '../prisma/prisma.service';
import {
@ -19,6 +19,8 @@ import {
@Injectable()
export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository {
private readonly logger = new Logger(UserDetailQueryRepositoryImpl.name);
constructor(private readonly prisma: PrismaService) {}
// ============================================================================
@ -160,12 +162,16 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
// ============================================================================
async getPlantingSummary(accountSequence: string): Promise<PlantingSummary | null> {
this.logger.log(`[getPlantingSummary] 查询认种汇总, accountSequence=${accountSequence}`);
// 先获取用户的 userId 用于查询持仓
const user = await this.prisma.userQueryView.findUnique({
where: { accountSequence },
select: { userId: true },
});
this.logger.log(`[getPlantingSummary] 用户查询结果: ${user ? `userId=${user.userId}` : 'null'}`);
if (!user) return null;
// 获取持仓信息
@ -173,6 +179,8 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
where: { userId: user.userId },
});
this.logger.log(`[getPlantingSummary] 持仓查询结果: ${position ? `effectiveTreeCount=${position.effectiveTreeCount}` : 'null'}`);
// 获取订单统计 - 使用 accountSequence
const [orderStats, firstOrder, lastOrder] = await Promise.all([
this.prisma.plantingOrderQueryView.aggregate({
@ -195,6 +203,8 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
}),
]);
this.logger.log(`[getPlantingSummary] 订单统计: count=${orderStats._count}, treeCount=${orderStats._sum.treeCount}, totalAmount=${orderStats._sum.totalAmount}`);
return {
totalOrders: orderStats._count,
totalTreeCount: orderStats._sum.treeCount || 0,
@ -257,10 +267,14 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
// ============================================================================
async getWalletSummary(accountSequence: string): Promise<WalletSummary | null> {
this.logger.log(`[getWalletSummary] 查询钱包, accountSequence=${accountSequence}`);
const wallet = await this.prisma.walletAccountQueryView.findUnique({
where: { accountSequence },
});
this.logger.log(`[getWalletSummary] 查询结果: ${wallet ? `id=${wallet.id}, userId=${wallet.userId}, usdtAvailable=${wallet.usdtAvailable}` : 'null'}`);
if (!wallet) return null;
return {
@ -292,6 +306,8 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
pageSize: number,
filters?: WalletLedgerFilters,
): Promise<WalletLedgerResult> {
this.logger.log(`[getWalletLedger] 查询钱包流水, accountSequence=${accountSequence}, page=${page}`);
const where: any = { accountSequence };
if (filters?.assetType) {

View File

@ -62,7 +62,7 @@ const entryTypeLabels: Record<string, string> = {
};
const assetTypeLabels: Record<string, string> = {
USDT: 'USDT',
USDT: '绿积分',
DST: 'DST',
BNB: 'BNB',
OG: 'OG',
@ -440,7 +440,7 @@ export default function UserDetailPage() {
</span>
</div>
<div className={styles.plantingTab__summaryItem}>
<span className={styles.plantingTab__summaryLabel}> (USDT)</span>
<span className={styles.plantingTab__summaryLabel}> (绿)</span>
<span className={styles.plantingTab__summaryValue}>
{formatAmount(plantingData.summary.totalAmount)}
</span>
@ -543,13 +543,13 @@ export default function UserDetailPage() {
<h3></h3>
<div className={styles.walletTab__summaryGrid}>
<div className={styles.walletTab__summaryItem}>
<span className={styles.walletTab__summaryLabel}>USDT </span>
<span className={styles.walletTab__summaryLabel}>绿 </span>
<span className={styles.walletTab__summaryValue}>
{formatAmount(walletData.summary.usdtAvailable)}
</span>
</div>
<div className={styles.walletTab__summaryItem}>
<span className={styles.walletTab__summaryLabel}>USDT </span>
<span className={styles.walletTab__summaryLabel}>绿 </span>
<span className={styles.walletTab__summaryValue}>
{formatAmount(walletData.summary.usdtFrozen)}
</span>