From d303cf076b2bd2b2f5c882ab3b0904ff59b4f6ac Mon Sep 17 00:00:00 2001 From: hailin Date: Wed, 7 Jan 2026 22:30:38 -0800 Subject: [PATCH] =?UTF-8?q?fix(admin-service):=20=E5=BC=95=E8=8D=90?= =?UTF-8?q?=E5=85=B3=E7=B3=BB=E6=A0=91=E5=AE=9E=E6=97=B6=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=9C=AC=E4=BA=BA=E8=AE=A4=E7=A7=8D=E5=92=8C=E7=9B=B4=E6=8E=A8?= =?UTF-8?q?=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - 引荐节点的"本人认种"和"引荐"显示为0 - user_query_view.personal_adoption_count 和 referral_query_view.direct_referral_count 没有被CDC更新 解决方案: - getAncestors: 实时统计每个祖先的认种订单数和直推数 - getDirectReferrals: 实时统计每个下级的认种订单数和直推数 - getReferralTree API: 实时获取当前用户的统计数据 - 新增 getDirectReferralCount 方法 实时统计方式: - 本人认种 = planting_order_query_view 中状态为 MINING_ENABLED 的订单数 - 直推数量 = referral_query_view 中 referrer_id 等于该用户的记录数 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../api/controllers/user-detail.controller.ts | 11 ++- .../user-detail-query.repository.ts | 5 ++ .../user-detail-query.repository.impl.ts | 88 +++++++++++++++---- 3 files changed, 84 insertions(+), 20 deletions(-) diff --git a/backend/services/admin-service/src/api/controllers/user-detail.controller.ts b/backend/services/admin-service/src/api/controllers/user-detail.controller.ts index 137da697..03e30ccc 100644 --- a/backend/services/admin-service/src/api/controllers/user-detail.controller.ts +++ b/backend/services/admin-service/src/api/controllers/user-detail.controller.ts @@ -131,16 +131,21 @@ export class UserDetailController { throw new NotFoundException(`用户 ${accountSequence} 不存在`); } - const referralInfo = await this.userDetailRepository.getReferralInfo(accountSequence); + // 获取引荐信息和实时统计 + const [referralInfo, personalAdoptionCount, directReferralCount] = await Promise.all([ + this.userDetailRepository.getReferralInfo(accountSequence), + this.userDetailRepository.getPersonalAdoptionCount(accountSequence), + this.userDetailRepository.getDirectReferralCount(accountSequence), + ]); const currentUser: ReferralNodeDto = { accountSequence: user.accountSequence, userId: user.userId.toString(), nickname: user.nickname, avatar: user.avatarUrl, - personalAdoptions: user.personalAdoptionCount, + personalAdoptions: personalAdoptionCount, depth: referralInfo?.depth || 0, - directReferralCount: referralInfo?.directReferralCount || 0, + directReferralCount: directReferralCount, isCurrentUser: true, }; diff --git a/backend/services/admin-service/src/domain/repositories/user-detail-query.repository.ts b/backend/services/admin-service/src/domain/repositories/user-detail-query.repository.ts index 21823e3d..a17a74d3 100644 --- a/backend/services/admin-service/src/domain/repositories/user-detail-query.repository.ts +++ b/backend/services/admin-service/src/domain/repositories/user-detail-query.repository.ts @@ -251,6 +251,11 @@ export interface IUserDetailQueryRepository { */ getPersonalAdoptionCount(accountSequence: string): Promise; + /** + * 获取用户直推数量 + */ + getDirectReferralCount(accountSequence: string): Promise; + /** * 获取用户团队统计(团队地址数、团队认种量) * 团队包括所有直推和间推用户 diff --git a/backend/services/admin-service/src/infrastructure/persistence/repositories/user-detail-query.repository.impl.ts b/backend/services/admin-service/src/infrastructure/persistence/repositories/user-detail-query.repository.impl.ts index 9d7b62ad..ab4f252e 100644 --- a/backend/services/admin-service/src/infrastructure/persistence/repositories/user-detail-query.repository.impl.ts +++ b/backend/services/admin-service/src/infrastructure/persistence/repositories/user-detail-query.repository.impl.ts @@ -60,7 +60,7 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository const ancestorIds = referral.ancestorPath.slice(0, depth); if (ancestorIds.length === 0) return []; - // 获取祖先用户信息 + // 获取祖先用户信息和引荐关系 const [users, referrals] = await Promise.all([ this.prisma.userQueryView.findMany({ where: { userId: { in: ancestorIds } }, @@ -69,19 +69,41 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository accountSequence: true, nickname: true, avatarUrl: true, - personalAdoptionCount: true, }, }), this.prisma.referralQueryView.findMany({ where: { userId: { in: ancestorIds } }, select: { userId: true, + accountSequence: true, depth: true, - directReferralCount: true, }, }), ]); + // 实时统计:获取每个祖先的认种数量和直推数量 + const accountSequences = users.map(u => u.accountSequence); + const [adoptionCounts, directReferralCounts] = await Promise.all([ + // 统计每个用户的认种订单数量(状态为 MINING_ENABLED) + this.prisma.plantingOrderQueryView.groupBy({ + by: ['accountSequence'], + where: { + accountSequence: { in: accountSequences }, + status: 'MINING_ENABLED', + }, + _count: { id: true }, + }), + // 统计每个用户的直推数量 + this.prisma.referralQueryView.groupBy({ + by: ['referrerId'], + where: { referrerId: { in: ancestorIds } }, + _count: { userId: true }, + }), + ]); + + const adoptionCountMap = new Map(adoptionCounts.map(a => [a.accountSequence, a._count.id])); + const directCountMap = new Map(directReferralCounts.map(d => [d.referrerId.toString(), d._count.userId])); + // 合并数据 const referralMap = new Map(referrals.map((r) => [r.userId.toString(), r])); const userMap = new Map(users.map((u) => [u.userId.toString(), u])); @@ -94,9 +116,9 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository accountSequence: user?.accountSequence || '', nickname: user?.nickname || null, avatarUrl: user?.avatarUrl || null, - personalAdoptionCount: user?.personalAdoptionCount || 0, + personalAdoptionCount: adoptionCountMap.get(user?.accountSequence || '') || 0, depth: ref?.depth || index, - directReferralCount: ref?.directReferralCount || 0, + directReferralCount: directCountMap.get(id.toString()) || 0, }; }); } @@ -115,24 +137,45 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository userId: true, accountSequence: true, depth: true, - directReferralCount: true, }, }); if (directReferrals.length === 0) return []; // 获取用户信息 + const userIds = directReferrals.map((r) => r.userId); const users = await this.prisma.userQueryView.findMany({ - where: { userId: { in: directReferrals.map((r) => r.userId) } }, + where: { userId: { in: userIds } }, select: { userId: true, accountSequence: true, nickname: true, avatarUrl: true, - personalAdoptionCount: true, }, }); + // 实时统计:获取每个用户的认种数量和直推数量 + const userAccountSequences = directReferrals.map(r => r.accountSequence); + const [adoptionCounts, directReferralCounts] = await Promise.all([ + // 统计每个用户的认种订单数量(状态为 MINING_ENABLED) + this.prisma.plantingOrderQueryView.groupBy({ + by: ['accountSequence'], + where: { + accountSequence: { in: userAccountSequences }, + status: 'MINING_ENABLED', + }, + _count: { id: true }, + }), + // 统计每个用户的直推数量 + this.prisma.referralQueryView.groupBy({ + by: ['referrerId'], + where: { referrerId: { in: userIds } }, + _count: { userId: true }, + }), + ]); + + const adoptionCountMap = new Map(adoptionCounts.map(a => [a.accountSequence, a._count.id])); + const directCountMap = new Map(directReferralCounts.map(d => [d.referrerId.toString(), d._count.userId])); const userMap = new Map(users.map((u) => [u.userId.toString(), u])); return directReferrals.map((ref) => { @@ -142,9 +185,9 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository accountSequence: ref.accountSequence, nickname: user?.nickname || null, avatarUrl: user?.avatarUrl || null, - personalAdoptionCount: user?.personalAdoptionCount || 0, + personalAdoptionCount: adoptionCountMap.get(ref.accountSequence) || 0, depth: ref.depth, - directReferralCount: ref.directReferralCount, + directReferralCount: directCountMap.get(ref.userId.toString()) || 0, }; }); } @@ -428,21 +471,32 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository } async getPersonalAdoptionCount(accountSequence: string): Promise { + // 统计用户的认种订单数量(状态为 MINING_ENABLED) + const count = await this.prisma.plantingOrderQueryView.count({ + where: { + accountSequence, + status: 'MINING_ENABLED', + }, + }); + + return count; + } + + async getDirectReferralCount(accountSequence: string): Promise { // 先获取用户的 userId - const user = await this.prisma.userQueryView.findUnique({ + const referral = await this.prisma.referralQueryView.findUnique({ where: { accountSequence }, select: { userId: true }, }); - if (!user) return 0; + if (!referral) return 0; - // 从 PlantingPositionQueryView 获取有效认种树数 - const position = await this.prisma.plantingPositionQueryView.findUnique({ - where: { userId: user.userId }, - select: { effectiveTreeCount: true }, + // 统计以该用户为 referrerId 的用户数量 + const count = await this.prisma.referralQueryView.count({ + where: { referrerId: referral.userId }, }); - return position?.effectiveTreeCount || 0; + return count; } async getTeamStats(accountSequence: string): Promise<{ teamAddressCount: number; teamAdoptionCount: number }> {