feat(admin): show user subscription plan and token quota in user pages

Expose active subscription summary on user list and detail so operators can see plan type, total/used/remaining tokens without opening billing subscriptions.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-09-07 16:22:08 +08:00
parent c1aa1ba459
commit e07686f29d
6 changed files with 193 additions and 10 deletions
+24 -1
View File
@@ -290,13 +290,36 @@ export function createAdminApp(services) {
role: typeof req.query.role === 'string' ? req.query.role.trim() : '',
status: typeof req.query.status === 'string' ? req.query.status.trim() : '',
});
if (subscriptionService?.getActiveSubscription && Array.isArray(result.users) && result.users.length) {
result.users = await Promise.all(
result.users.map(async (user) => {
if (user.role !== 'user') return user;
const sub = await subscriptionService.getActiveSubscription(user.id);
if (!sub) return { ...user, subscription: null };
return {
...user,
subscription: {
planType: sub.planType,
status: sub.status,
periodTokensLimit: sub.periodTokensLimit,
periodTokensUsed: sub.periodTokensUsed,
expiresAt: sub.expiresAt,
},
};
}),
);
}
res.json(result);
});
adminApi.get('/users/:userId', requireAdmin, async (req, res) => {
const user = await userAuth.getUserPublic(req.params.userId);
if (!user) return res.status(404).json({ message: '用户不存在' });
res.json({ user });
let subscription = null;
if (subscriptionService?.getActiveSubscription && user.role === 'user') {
subscription = await subscriptionService.getActiveSubscription(req.params.userId);
}
res.json({ user, subscription });
});
adminApi.get('/summary', requireAdmin, async (_req, res) => {