fix(mining-admin-service): 实现getReferralTree返回真实推荐关系数据

- 从synced_referrals和synced_adoptions获取数据
- 实现getAncestors获取向上引荐人链
- 实现getDirectReferrals获取直推下级
- 实现getUserAdoptionStats获取认种统计

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-12 03:48:59 -08:00
parent 2025c6ce36
commit 9e9a7364b9
1 changed files with 198 additions and 16 deletions

View File

@ -450,32 +450,214 @@ export class UsersService {
/**
*
* TODO: identity-service
*/
async getReferralTree(accountSequence: string, direction: string, depth: number) {
async getReferralTree(
accountSequence: string,
direction: string,
depth: number,
) {
const user = await this.prisma.syncedUser.findUnique({
where: { accountSequence },
include: { contributionAccount: true },
include: {
contributionAccount: true,
referral: true,
},
});
if (!user) {
throw new NotFoundException(`用户 ${accountSequence} 不存在`);
}
// 返回基础结构,数据需要从 identity-service 同步
return {
currentUser: {
accountSequence: user.accountSequence,
nickname: user.realName || null,
avatar: null,
personalAdoptions: 0,
teamAdoptions: 0,
directReferralCount: user.contributionAccount?.directReferralCount || 0,
},
ancestors: [],
directReferrals: [],
note: '推荐关系数据需要从 identity-service 同步',
// 获取当前用户的认种统计
const currentUserAdoptions = await this.getUserAdoptionStats(accountSequence);
// 构建当前用户节点
const currentUser = {
accountSequence: user.accountSequence,
nickname: user.nickname || user.realName || null,
avatar: null,
personalAdoptions: currentUserAdoptions.personal,
teamAdoptions: currentUserAdoptions.team,
directReferralCount: 0,
};
// 获取直推下级数量
const directReferralCount = await this.prisma.syncedReferral.count({
where: { referrerAccountSequence: accountSequence },
});
currentUser.directReferralCount = directReferralCount;
// 获取向上的引荐人链 (ancestors)
let ancestors: any[] = [];
if (direction === 'up' || direction === 'both') {
ancestors = await this.getAncestors(accountSequence, depth);
}
// 获取直推下级 (directReferrals)
let directReferrals: any[] = [];
if (direction === 'down' || direction === 'both') {
directReferrals = await this.getDirectReferrals(accountSequence);
}
return {
currentUser,
ancestors,
directReferrals,
};
}
/**
*
*/
private async getUserAdoptionStats(
accountSequence: string,
): Promise<{ personal: number; team: number }> {
// 个人认种
const personalStats = await this.prisma.syncedAdoption.aggregate({
where: { accountSequence },
_sum: { treeCount: true },
});
// 获取用户的 originalUserId
const referral = await this.prisma.syncedReferral.findUnique({
where: { accountSequence },
select: { originalUserId: true },
});
let teamCount = 0;
if (referral?.originalUserId) {
// 团队认种 = 所有下级的认种总和
const teamMembers = await this.prisma.syncedReferral.findMany({
where: {
ancestorPath: { contains: referral.originalUserId.toString() },
},
select: { accountSequence: true },
});
if (teamMembers.length > 0) {
const teamStats = await this.prisma.syncedAdoption.aggregate({
where: {
accountSequence: { in: teamMembers.map((m) => m.accountSequence) },
},
_sum: { treeCount: true },
});
teamCount = teamStats._sum.treeCount || 0;
}
}
return {
personal: personalStats._sum.treeCount || 0,
team: teamCount,
};
}
/**
*
*/
private async getAncestors(
accountSequence: string,
maxDepth: number = 10,
): Promise<any[]> {
const ancestors: any[] = [];
// 获取当前用户的推荐关系
const referral = await this.prisma.syncedReferral.findUnique({
where: { accountSequence },
select: { referrerAccountSequence: true, ancestorPath: true },
});
if (!referral?.referrerAccountSequence) {
return ancestors;
}
// 通过 ancestorPath 解析祖先链
// ancestorPath 格式类似: "123,456,789" 其中 123 是直接上级的 originalUserId
if (referral.ancestorPath) {
const ancestorUserIds = referral.ancestorPath
.split(',')
.filter((id) => id.trim())
.slice(0, maxDepth);
// 获取所有祖先的 referral 记录以获取 accountSequence
const ancestorReferrals = await this.prisma.syncedReferral.findMany({
where: {
originalUserId: { in: ancestorUserIds.map((id) => BigInt(id)) },
},
select: { accountSequence: true, originalUserId: true },
});
const userIdToSeq = new Map(
ancestorReferrals.map((r) => [r.originalUserId.toString(), r.accountSequence]),
);
// 按顺序获取每个祖先的详细信息
for (const userId of ancestorUserIds) {
const seq = userIdToSeq.get(userId);
if (!seq) continue;
const user = await this.prisma.syncedUser.findUnique({
where: { accountSequence: seq },
select: { accountSequence: true, nickname: true, realName: true },
});
if (user) {
const adoptionStats = await this.getUserAdoptionStats(seq);
const directCount = await this.prisma.syncedReferral.count({
where: { referrerAccountSequence: seq },
});
ancestors.push({
accountSequence: user.accountSequence,
nickname: user.nickname || user.realName || null,
avatar: null,
personalAdoptions: adoptionStats.personal,
teamAdoptions: adoptionStats.team,
directReferralCount: directCount,
});
}
}
}
// 反转使得最近的祖先在最后(靠近当前用户)
return ancestors.reverse();
}
/**
*
*/
private async getDirectReferrals(accountSequence: string): Promise<any[]> {
// 获取所有直推下级
const directReferrals = await this.prisma.syncedReferral.findMany({
where: { referrerAccountSequence: accountSequence },
select: { accountSequence: true },
});
const results: any[] = [];
for (const ref of directReferrals) {
const user = await this.prisma.syncedUser.findUnique({
where: { accountSequence: ref.accountSequence },
select: { accountSequence: true, nickname: true, realName: true },
});
if (user) {
const adoptionStats = await this.getUserAdoptionStats(ref.accountSequence);
const directCount = await this.prisma.syncedReferral.count({
where: { referrerAccountSequence: ref.accountSequence },
});
results.push({
accountSequence: user.accountSequence,
nickname: user.nickname || user.realName || null,
avatar: null,
personalAdoptions: adoptionStats.personal,
teamAdoptions: adoptionStats.team,
directReferralCount: directCount,
});
}
}
return results;
}
/**