feat: 为批量归档补充批量恢复

This commit is contained in:
2026-07-25 09:34:03 +08:00
parent 1da763109b
commit 0ef86e65ce
19 changed files with 1365 additions and 317 deletions

View File

@@ -14,6 +14,8 @@ import {
UploadedFile,
Inject,
ParseIntPipe,
UsePipes,
ValidationPipe,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
@@ -35,6 +37,7 @@ import {
parseStudentImportWorkbook,
STUDENT_EXPORT_COLUMNS,
} from './student-import';
import { BatchIdsDto } from '../common/batch-ids.dto';
interface AuthenticatedRequest {
user: AuthenticatedUser;
@@ -196,6 +199,24 @@ export class StudentsController {
return result;
}
@Put('batch-restore')
@RequirePermission('student:edit')
@UsePipes(new ValidationPipe({ transform: true, whitelist: true, forbidNonWhitelisted: true }))
async batchRestore(@Body() dto: BatchIdsDto, @Request() req: any) {
const { ipAddress, userAgent } = extractRequestInfo(req);
const result = await this.service.batchRestore(dto.ids);
await this.logService.log({
userId: req.user?.id,
username: req.user?.username,
module: '学生管理',
action: '批量恢复学生',
detail: `IDs: ${dto.ids.join(',')}`,
ipAddress,
userAgent,
});
return result;
}
@Put(':id')
@RequirePermission('student:edit')
async update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateStudentDto, @Request() req: any) {

View File

@@ -219,6 +219,30 @@ export class StudentsService {
return { message: '已恢复' };
}
async batchRestore(ids: number[]) {
const uniqueIds = [...new Set(ids || [])];
if (uniqueIds.length === 0) throw new BadRequestException('请选择要恢复的学生');
if (uniqueIds.some((id) => !Number.isInteger(id) || id <= 0)) {
throw new BadRequestException('学生 ID 无效');
}
const students = await this.repo.find({ where: { id: In(uniqueIds) } });
if (students.length !== uniqueIds.length) throw new NotFoundException('部分学生不存在');
const targetIds = students.filter((student) => student.status === 'archived').map((student) => student.id);
const skipped = students.length - targetIds.length;
let restored = 0;
if (targetIds.length > 0) {
const result = await this.repo
.createQueryBuilder()
.update()
.set({ status: 'active' })
.where('id IN (:...ids)', { ids: targetIds })
.execute();
restored = result.affected || 0;
}
return { message: `已批量恢复 ${restored} 名学生`, restored, skipped };
}
async batchImport(importData: StudentWorkbookImport | StudentImportRow[]) {
const data = this.normalizeImportData(importData);
let imported = 0;