feat: add mark-staff/mark-student endpoints with studentStatus in user list

This commit is contained in:
2026-07-09 10:06:31 +08:00
parent 6e0ad8759f
commit 14eec2852a
2 changed files with 89 additions and 3 deletions

View File

@@ -127,8 +127,9 @@ export class RbacController {
@Get('users')
@RequirePermission('user:view')
getUsers() {
return this.rbacService.findAllUsers();
getUsers(@Query('isArchived') isArchived?: string) {
const archived = isArchived === 'true';
return this.rbacService.findAllUsers(archived);
}
@Post('users')
@@ -219,6 +220,50 @@ export class RbacController {
}
}
@Put('users/:id/archive')
@RequirePermission('user:edit')
async archiveUser(@Param('id') id: string) {
try {
return await this.rbacService.archiveUser(+id);
} catch (e: unknown) {
const err = e as { message?: string };
throw new BadRequestException(err?.message);
}
}
@Put('users/:id/restore')
@RequirePermission('user:edit')
async restoreUser(@Param('id') id: string) {
try {
return await this.rbacService.restoreUser(+id);
} catch (e: unknown) {
const err = e as { message?: string };
throw new BadRequestException(err?.message);
}
}
@Put('users/:id/mark-staff')
@RequirePermission('user:edit')
async markAsStaff(@Param('id') id: string) {
try {
return await this.rbacService.markAsStaff(+id);
} catch (e: unknown) {
const err = e as { message?: string };
throw new BadRequestException(err?.message);
}
}
@Put('users/:id/mark-student')
@RequirePermission('user:edit')
async markAsStudent(@Param('id') id: string) {
try {
return await this.rbacService.markAsStudent(+id);
} catch (e: unknown) {
const err = e as { message?: string };
throw new BadRequestException(err?.message);
}
}
// ---- 用户资料 ----
@Get('users/:id/profile')

View File

@@ -325,16 +325,25 @@ export class RbacService {
// ---- 用户管理 ----
async findAllUsers() {
async findAllUsers(isArchived = false) {
const users = await this.userRepo.find({
where: { isArchived },
relations: ['roles'],
order: { createdAt: 'DESC' },
});
const userIds = users.map((u) => u.id);
const students = await this.studentRepo.find({
where: { userId: In(userIds) },
select: ['userId', 'status'],
});
const statusMap = new Map(students.map((s) => [s.userId, s.status]));
return users.map((u) => ({
id: u.id,
username: u.username,
name: u.name,
isActive: u.isActive,
isArchived: u.isArchived,
studentStatus: statusMap.get(u.id) || null,
lastLoginAt: u.lastLoginAt,
createdAt: u.createdAt,
updatedAt: u.updatedAt,
@@ -386,10 +395,42 @@ export class RbacService {
return { message: '密码已重置' };
}
async archiveUser(id: number) {
const user = await this.userRepo.findOne({ where: { id } });
if (!user) throw new Error('用户不存在');
if (user.username === 'admin') throw new Error('不能归档默认管理员');
await this.userRepo.update(id, { isArchived: true });
return { message: '用户已归档' };
}
async restoreUser(id: number) {
const user = await this.userRepo.findOne({ where: { id } });
if (!user) throw new Error('用户不存在');
await this.userRepo.update(id, { isArchived: false });
return { message: '用户已恢复' };
}
async markAsStaff(userId: number) {
const student = await this.studentRepo.findOne({ where: { userId } });
if (!student) throw new Error('该用户没有学员记录');
await this.studentRepo.update(student.id, { status: 'staff' });
this.logger.log(`User ${userId} Student ${student.id} marked as staff`);
return { message: '已标记为教职工' };
}
async markAsStudent(userId: number) {
const student = await this.studentRepo.findOne({ where: { userId } });
if (!student) throw new Error('该用户没有学员记录');
await this.studentRepo.update(student.id, { status: 'active' });
this.logger.log(`User ${userId} Student ${student.id} restored to student`);
return { message: '已恢复为学员' };
}
async deleteUser(id: number) {
const user = await this.userRepo.findOne({ where: { id } });
if (!user) throw new Error('用户不存在');
if (user.username === 'admin') throw new Error('不能删除默认管理员');
if (!user.isArchived) throw new Error('请先归档再删除');
await this.userRepo.remove(user);
return { message: '用户已删除' };
}