api-server/src/modules/users/admin-users-mgmt.controller.ts
wangdl 0ea36a7073
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 50s
feat(API-ADMIN-010): add enrichWithNames to admin list controllers
- New shared helper: src/common/helpers/name-resolver.ts
- Applied to: reviews, users/members, files, knowledge-bases, imports
- Learning service refactored to use shared helper

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 13:04:55 +08:00

99 lines
3.8 KiB
TypeScript

import { Controller, Get, Post, Delete, Body, Param, Query, UseGuards } from '@nestjs/common';
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
import { PrismaService } from '../../infrastructure/database/prisma.service';
import { enrichWithNames } from '../../common/helpers/name-resolver';
import { AdminAuthGuard } from '../../common/guards/admin-auth.guard';
import { AdminRolesGuard } from '../../common/guards/admin-roles.guard';
import { AdminRoles } from '../../common/decorators/admin-roles.decorator';
import type { AdminRole } from '../../common/types/admin-role.enum';
@ApiTags('admin-users')
@Controller('admin-api/users')
@UseGuards(AdminAuthGuard, AdminRolesGuard)
@ApiBearerAuth()
export class AdminUsersMgmtController {
constructor(private readonly prisma: PrismaService) {}
// ── User List ──
@Get()
@AdminRoles('ADMIN' as AdminRole)
@ApiOperation({ summary: 'C 端用户列表' })
async listUsers(@Query('search') search?: string, @Query('page') page?: string, @Query('limit') limit?: string) {
const take = Math.min(Number(limit) || 20, 100);
const skip = (Math.max(Number(page) || 1, 1) - 1) * take;
const where: any = { deletedAt: null };
if (search) where.OR = [{ email: { contains: search } }, { nickname: { contains: search } }];
const [items, total] = await Promise.all([
this.prisma.user.findMany({ where, orderBy: { createdAt: 'desc' }, take, skip, select: { id: true, email: true, nickname: true, role: true, status: true, lastLoginAt: true, createdAt: true } }),
this.prisma.user.count({ where }),
]);
const enriched = await enrichWithNames(this.prisma, items); return { items: enriched, total };
}
// ── Membership ──
@Get('memberships')
@AdminRoles('ADMIN' as AdminRole)
@ApiOperation({ summary: '用户会员列表' })
async memberships(@Query('userId') userId?: string) {
return this.prisma.userMembership.findMany({
where: userId ? { userId } : undefined,
include: { plan: true },
orderBy: { createdAt: 'desc' },
take: 100,
});
}
@Post('memberships')
@AdminRoles('SUPER_ADMIN' as AdminRole)
@ApiOperation({ summary: '手动分配会员' })
async addMembership(@Body() d: { userId: string; planId: string; expiresAt?: string }) {
return this.prisma.userMembership.create({
data: { userId: d.userId, planId: d.planId, expiresAt: d.expiresAt ? new Date(d.expiresAt) : null },
});
}
// ── Deletion Requests ──
@Get('deletion-requests')
@AdminRoles('ADMIN' as AdminRole)
@ApiOperation({ summary: '注销申请列表' })
async deletionRequests(@Query('status') status?: string) {
return this.prisma.accountDeletionRequest.findMany({
where: status ? { status } : undefined,
orderBy: { createdAt: 'desc' },
take: 100,
});
}
@Post('deletion-requests/:id/approve')
@AdminRoles('SUPER_ADMIN' as AdminRole)
@ApiOperation({ summary: '批准注销(立即执行)' })
async approveDeletion(@Param('id') id: string) {
return this.prisma.accountDeletionRequest.update({
where: { id },
data: { status: 'completed', reviewedAt: new Date(), completedAt: new Date() },
});
}
@Post('deletion-requests/:id/reject')
@AdminRoles('SUPER_ADMIN' as AdminRole)
@ApiOperation({ summary: '驳回注销' })
async rejectDeletion(@Param('id') id: string) {
return this.prisma.accountDeletionRequest.update({
where: { id },
data: { status: 'cancelled', reviewedAt: new Date(), cancelledAt: new Date() },
});
}
// ── Devices ──
@Get(':userId/devices')
@AdminRoles('ADMIN' as AdminRole)
@ApiOperation({ summary: '查看用户设备' })
async userDevices(@Param('userId') userId: string) {
return this.prisma.userDevice.findMany({ where: { userId }, orderBy: { lastSeenAt: 'desc' } });
}
}