feat(mining-admin): 添加用户详情页缺失的 API 端点
- 添加 referral-tree API(返回空推荐关系数据) - 添加 planting-ledger API(返回空认种数据) - 添加 wallet-ledger API(返回空钱包流水数据) - 修复前端 referral-tree 组件空数据处理 注:这些 API 目前返回占位数据,完整数据需要通过 CDC 从各服务同步 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
fc3efe6a27
commit
1a7c73e531
|
|
@ -102,4 +102,43 @@ export class UsersController {
|
|||
status,
|
||||
});
|
||||
}
|
||||
|
||||
@Get(':accountSequence/referral-tree')
|
||||
@ApiOperation({ summary: '获取用户引荐关系树' })
|
||||
@ApiParam({ name: 'accountSequence', type: String })
|
||||
@ApiQuery({ name: 'direction', required: false, type: String, description: 'up, down, both' })
|
||||
@ApiQuery({ name: 'depth', required: false, type: Number })
|
||||
async getReferralTree(
|
||||
@Param('accountSequence') accountSequence: string,
|
||||
@Query('direction') direction?: string,
|
||||
@Query('depth') depth?: number,
|
||||
) {
|
||||
return this.usersService.getReferralTree(accountSequence, direction || 'both', depth || 1);
|
||||
}
|
||||
|
||||
@Get(':accountSequence/planting-ledger')
|
||||
@ApiOperation({ summary: '获取用户认种分类账' })
|
||||
@ApiParam({ name: 'accountSequence', type: String })
|
||||
@ApiQuery({ name: 'page', required: false, type: Number })
|
||||
@ApiQuery({ name: 'pageSize', required: false, type: Number })
|
||||
async getPlantingLedger(
|
||||
@Param('accountSequence') accountSequence: string,
|
||||
@Query('page') page?: number,
|
||||
@Query('pageSize') pageSize?: number,
|
||||
) {
|
||||
return this.usersService.getPlantingLedger(accountSequence, page ?? 1, pageSize ?? 20);
|
||||
}
|
||||
|
||||
@Get(':accountSequence/wallet-ledger')
|
||||
@ApiOperation({ summary: '获取用户钱包流水' })
|
||||
@ApiParam({ name: 'accountSequence', type: String })
|
||||
@ApiQuery({ name: 'page', required: false, type: Number })
|
||||
@ApiQuery({ name: 'pageSize', required: false, type: Number })
|
||||
async getWalletLedger(
|
||||
@Param('accountSequence') accountSequence: string,
|
||||
@Query('page') page?: number,
|
||||
@Query('pageSize') pageSize?: number,
|
||||
) {
|
||||
return this.usersService.getWalletLedger(accountSequence, page ?? 1, pageSize ?? 20);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,6 +252,99 @@ export class UsersService {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户引荐关系树
|
||||
* TODO: 从 identity-service 同步推荐关系数据
|
||||
*/
|
||||
async getReferralTree(accountSequence: string, direction: string, depth: number) {
|
||||
const user = await this.prisma.syncedUser.findUnique({
|
||||
where: { accountSequence },
|
||||
include: { contributionAccount: 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 同步',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户认种分类账
|
||||
* TODO: 从 adoption-service 同步认种数据
|
||||
*/
|
||||
async getPlantingLedger(accountSequence: string, page: number, pageSize: number) {
|
||||
const user = await this.prisma.syncedUser.findUnique({
|
||||
where: { accountSequence },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new NotFoundException(`用户 ${accountSequence} 不存在`);
|
||||
}
|
||||
|
||||
// 返回空数据,数据需要从 adoption-service 同步
|
||||
return {
|
||||
summary: {
|
||||
totalOrders: 0,
|
||||
totalTreeCount: 0,
|
||||
totalAmount: '0',
|
||||
effectiveTreeCount: 0,
|
||||
firstPlantingAt: null,
|
||||
lastPlantingAt: null,
|
||||
},
|
||||
items: [],
|
||||
total: 0,
|
||||
page,
|
||||
pageSize,
|
||||
totalPages: 0,
|
||||
note: '认种数据需要从 adoption-service 同步',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户钱包流水
|
||||
* TODO: 从 mining-service 同步钱包流水数据
|
||||
*/
|
||||
async getWalletLedger(accountSequence: string, page: number, pageSize: number) {
|
||||
const user = await this.prisma.syncedUser.findUnique({
|
||||
where: { accountSequence },
|
||||
include: { miningAccount: true },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new NotFoundException(`用户 ${accountSequence} 不存在`);
|
||||
}
|
||||
|
||||
const mining = user.miningAccount;
|
||||
|
||||
return {
|
||||
summary: {
|
||||
availableBalance: mining?.availableBalance?.toString() || '0',
|
||||
frozenBalance: mining?.frozenBalance?.toString() || '0',
|
||||
totalMined: mining?.totalMined?.toString() || '0',
|
||||
},
|
||||
items: [],
|
||||
total: 0,
|
||||
page,
|
||||
pageSize,
|
||||
totalPages: 0,
|
||||
note: '钱包流水数据需要从 mining-service 同步',
|
||||
};
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// 辅助方法
|
||||
// ===========================================================================
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export function ReferralTree({ accountSequence }: ReferralTreeProps) {
|
|||
|
||||
// 当 referralTree 数据加载完成后,自动展开当前用户的直推下级
|
||||
useEffect(() => {
|
||||
if (referralTree && referralTree.directReferrals.length > 0) {
|
||||
if (referralTree?.currentUser && referralTree.directReferrals?.length > 0) {
|
||||
setExpandedNodes((prev) => ({
|
||||
...prev,
|
||||
[referralTree.currentUser.accountSequence]: referralTree.directReferrals,
|
||||
|
|
@ -112,16 +112,16 @@ export function ReferralTree({ accountSequence }: ReferralTreeProps) {
|
|||
{/* 向上的引荐人链 */}
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-medium text-muted-foreground">引荐人链 (向上)</p>
|
||||
{referralTree.ancestors.length > 0 ? (
|
||||
{(referralTree.ancestors?.length ?? 0) > 0 ? (
|
||||
<div className="space-y-2">
|
||||
{referralTree.ancestors.map((ancestor, index) => (
|
||||
{(referralTree.ancestors || []).map((ancestor, index) => (
|
||||
<div key={ancestor.accountSequence}>
|
||||
<ReferralNodeCard
|
||||
node={ancestor}
|
||||
onClick={() => handleTreeNodeClick(ancestor)}
|
||||
variant="ancestor"
|
||||
/>
|
||||
{index < referralTree.ancestors.length - 1 && (
|
||||
{index < (referralTree.ancestors?.length ?? 0) - 1 && (
|
||||
<div className="flex justify-center py-1">
|
||||
<ChevronDown className="h-4 w-4 text-muted-foreground" />
|
||||
</div>
|
||||
|
|
@ -154,13 +154,13 @@ export function ReferralTree({ accountSequence }: ReferralTreeProps) {
|
|||
</div>
|
||||
|
||||
{/* 直推下级列表 */}
|
||||
{referralTree.directReferrals.length > 0 && (
|
||||
{(referralTree.directReferrals?.length ?? 0) > 0 && (
|
||||
<div className="space-y-2 ml-6 border-l-2 border-muted pl-4">
|
||||
<p className="text-sm font-medium text-muted-foreground">
|
||||
直推下级 ({referralTree.directReferrals.length})
|
||||
直推下级 ({referralTree.directReferrals?.length ?? 0})
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
{referralTree.directReferrals.map((child) => (
|
||||
{(referralTree.directReferrals || []).map((child) => (
|
||||
<ReferralNodeCard
|
||||
key={child.accountSequence}
|
||||
node={child}
|
||||
|
|
|
|||
Loading…
Reference in New Issue