From 2025c6ce36a61f27e2a9b027d7d9830615933bf2 Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 12 Jan 2026 03:42:54 -0800 Subject: [PATCH] =?UTF-8?q?fix(mining-admin):=20=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=88=97=E8=A1=A8API=E6=B7=BB=E5=8A=A0=E8=AE=A4=E7=A7=8D?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E5=92=8C=E6=8E=A8=E8=8D=90=E4=BA=BA=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端getUsers添加批量查询认种统计和推荐人信息 - 后端formatUserListItem返回adoption和referral字段 - 前端transformUserOverview映射新字段 Co-Authored-By: Claude Opus 4.5 --- .../src/application/services/users.service.ts | 141 +++++++++++++++++- .../src/features/users/api/users.api.ts | 8 +- 2 files changed, 144 insertions(+), 5 deletions(-) diff --git a/backend/services/mining-admin-service/src/application/services/users.service.ts b/backend/services/mining-admin-service/src/application/services/users.service.ts index f3ca22a3..11484902 100644 --- a/backend/services/mining-admin-service/src/application/services/users.service.ts +++ b/backend/services/mining-admin-service/src/application/services/users.service.ts @@ -36,6 +36,7 @@ export class UsersService { { phone: { contains: search } }, { accountSequence: { contains: search } }, { realName: { contains: search } }, + { nickname: { contains: search } }, ]; } @@ -63,13 +64,31 @@ export class UsersService { contributionAccount: true, miningAccount: true, tradingAccount: true, + referral: true, }, }), this.prisma.syncedUser.count({ where }), ]); + // 批量获取认种统计 + const accountSequences = users.map((u) => u.accountSequence); + const adoptionStats = await this.getAdoptionStatsForUsers(accountSequences); + + // 批量获取推荐人信息 + const referrerAccountSequences = users + .map((u) => u.referral?.referrerAccountSequence) + .filter((s): s is string => !!s); + const referrers = await this.getReferrersInfo(referrerAccountSequences); + return { - data: users.map((user) => this.formatUserListItem(user)), + data: users.map((user) => + this.formatUserListItem(user, { + adoptionStats: adoptionStats.get(user.accountSequence), + referrerInfo: user.referral?.referrerAccountSequence + ? referrers.get(user.referral.referrerAccountSequence) + : null, + }), + ), pagination: { page, pageSize, @@ -79,6 +98,102 @@ export class UsersService { }; } + /** + * 批量获取用户认种统计 + */ + private async getAdoptionStatsForUsers( + accountSequences: string[], + ): Promise> { + const result = new Map< + string, + { personalCount: number; teamCount: number } + >(); + + if (accountSequences.length === 0) return result; + + // 获取每个用户的个人认种数量 + const personalAdoptions = await this.prisma.syncedAdoption.groupBy({ + by: ['accountSequence'], + where: { accountSequence: { in: accountSequences } }, + _sum: { treeCount: true }, + }); + + for (const stat of personalAdoptions) { + result.set(stat.accountSequence, { + personalCount: stat._sum.treeCount || 0, + teamCount: 0, + }); + } + + // 确保所有用户都有记录 + for (const seq of accountSequences) { + if (!result.has(seq)) { + result.set(seq, { personalCount: 0, teamCount: 0 }); + } + } + + // 获取团队认种数量(通过 referral 的 originalUserId 和 ancestorPath) + const referrals = await this.prisma.syncedReferral.findMany({ + where: { accountSequence: { in: accountSequences } }, + select: { accountSequence: true, originalUserId: true }, + }); + + for (const ref of referrals) { + if (!ref.originalUserId) continue; + + // 找所有下级 + const teamMembers = await this.prisma.syncedReferral.findMany({ + where: { + ancestorPath: { contains: ref.originalUserId.toString() }, + }, + select: { accountSequence: true }, + }); + + if (teamMembers.length > 0) { + const teamAdoptionStats = await this.prisma.syncedAdoption.aggregate({ + where: { + accountSequence: { in: teamMembers.map((m) => m.accountSequence) }, + }, + _sum: { treeCount: true }, + }); + const stats = result.get(ref.accountSequence); + if (stats) { + stats.teamCount = teamAdoptionStats._sum.treeCount || 0; + } + } + } + + return result; + } + + /** + * 批量获取推荐人信息 + */ + private async getReferrersInfo( + accountSequences: string[], + ): Promise> { + const result = new Map< + string, + { nickname: string | null; phone: string } + >(); + + if (accountSequences.length === 0) return result; + + const referrers = await this.prisma.syncedUser.findMany({ + where: { accountSequence: { in: accountSequences } }, + select: { accountSequence: true, nickname: true, phone: true }, + }); + + for (const ref of referrers) { + result.set(ref.accountSequence, { + nickname: ref.nickname, + phone: ref.phone, + }); + } + + return result; + } + /** * 获取用户详情 */ @@ -430,7 +545,13 @@ export class UsersService { // 辅助方法 // =========================================================================== - private formatUserListItem(user: any) { + private formatUserListItem( + user: any, + extra?: { + adoptionStats?: { personalCount: number; teamCount: number }; + referrerInfo?: { nickname: string | null; phone: string } | null; + }, + ) { return { accountSequence: user.accountSequence, phone: this.maskPhone(user.phone), @@ -440,6 +561,22 @@ export class UsersService { realName: user.realName, isLegacyUser: user.isLegacyUser, createdAt: user.createdAt, + // 认种统计 + adoption: { + personalAdoptionCount: extra?.adoptionStats?.personalCount || 0, + teamAdoptions: extra?.adoptionStats?.teamCount || 0, + }, + // 推荐人信息 + referral: user.referral + ? { + referrerAccountSequence: user.referral.referrerAccountSequence, + referrerNickname: + extra?.referrerInfo?.nickname || + (extra?.referrerInfo?.phone + ? this.maskPhone(extra.referrerInfo.phone) + : null), + } + : null, contribution: user.contributionAccount ? { totalContribution: diff --git a/frontend/mining-admin-web/src/features/users/api/users.api.ts b/frontend/mining-admin-web/src/features/users/api/users.api.ts index 151766a6..9af37bf6 100644 --- a/frontend/mining-admin-web/src/features/users/api/users.api.ts +++ b/frontend/mining-admin-web/src/features/users/api/users.api.ts @@ -25,9 +25,11 @@ function transformUserOverview(backendUser: any): UserOverview { miningBalance: backendUser.mining?.availableBalance || '0', tradingBalance: backendUser.trading?.shareBalance || '0', frozenBalance: '0', - personalAdoptions: 0, - teamAdoptions: 0, - referrerId: null, + // 认种数据 - 从后端 adoption 字段获取 + personalAdoptions: backendUser.adoption?.personalAdoptionCount || 0, + teamAdoptions: backendUser.adoption?.teamAdoptions || 0, + // 推荐人 + referrerId: backendUser.referral?.referrerAccountSequence || null, status: backendUser.status?.toLowerCase() as 'active' | 'frozen' | 'deactivated', isOnline: false, createdAt: backendUser.createdAt,