feat: improve attendance scheduling and API validation

This commit is contained in:
2026-07-14 23:12:14 +08:00
parent c75a08affe
commit e45da7f998
33 changed files with 869 additions and 297 deletions

View File

@@ -13,6 +13,7 @@ import {
UseInterceptors,
UploadedFile,
Inject,
ParseIntPipe,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
@@ -21,7 +22,7 @@ import { ClassTeacher } from '../entities/class-teacher.entity';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Response } from 'express';
import { StudentsService } from './students.service';
import { CreateStudentDto, UpdateStudentDto } from './dto/student.dto';
import { CreateStudentDto, QueryStudentDto, UpdateStudentDto } from './dto/student.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { OperationLogsService } from '../operation-logs/operation-logs.service';
import { extractRequestInfo } from '../common/request-utils';
@@ -61,10 +62,7 @@ export class StudentsController {
@Get()
@RequirePermission('student:view')
async findAll(
@Query('name') name: string | undefined,
@Query('status') status: string | undefined,
@Query('includeArchived') includeArchived: string | undefined,
@Query('organizationId') organizationId: string | undefined,
@Query() query: QueryStudentDto,
@Request() req: AuthenticatedRequest,
) {
const classIds = await this.service.getAccessibleClassIds(
@@ -72,12 +70,7 @@ export class StudentsController {
this.canManageAllStudents(req),
);
return this.service.findAll(
{
name,
status,
includeArchived: includeArchived === 'true',
organizationId: organizationId ? +organizationId : undefined,
},
query,
classIds,
);
}
@@ -192,8 +185,8 @@ export class StudentsController {
@Get(':id')
@RequirePermission('student:view')
findOne(@Param('id') id: string) {
return this.service.findOne(+id);
findOne(@Param('id', ParseIntPipe) id: number) {
return this.service.findOne(id);
}
@Post()
@@ -217,15 +210,15 @@ export class StudentsController {
@Put(':id')
@RequirePermission('student:edit')
async update(@Param('id') id: string, @Body() dto: UpdateStudentDto, @Request() req: any) {
async update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateStudentDto, @Request() req: any) {
const { ipAddress, userAgent } = extractRequestInfo(req);
const result = await this.service.update(+id, dto);
const result = await this.service.update(id, dto);
await this.logService.log({
userId: req.user?.id,
username: req.user?.username,
module: '学生管理',
action: '编辑学生',
targetId: +id,
targetId: id,
targetType: 'student',
detail: JSON.stringify(dto),
ipAddress,
@@ -236,15 +229,15 @@ export class StudentsController {
@Delete(':id')
@RequirePermission('student:delete')
async remove(@Param('id') id: string, @Request() req: any) {
async remove(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
const { ipAddress, userAgent } = extractRequestInfo(req);
const result = await this.service.remove(+id);
const result = await this.service.remove(id);
await this.logService.log({
userId: req.user?.id,
username: req.user?.username,
module: '学生管理',
action: '删除学生',
targetId: +id,
targetId: id,
targetType: 'student',
ipAddress,
userAgent,
@@ -271,15 +264,15 @@ export class StudentsController {
@Put(':id/restore')
@RequirePermission('student:edit')
async restore(@Param('id') id: string, @Request() req: any) {
async restore(@Param('id', ParseIntPipe) id: number, @Request() req: any) {
const { ipAddress, userAgent } = extractRequestInfo(req);
const result = await this.service.restore(+id);
const result = await this.service.restore(id);
await this.logService.log({
userId: req.user?.id,
username: req.user?.username,
module: '学生管理',
action: '恢复学生',
targetId: +id,
targetId: id,
targetType: 'student',
ipAddress,
userAgent,
@@ -403,7 +396,7 @@ export class StudentsController {
@Get(':id/compare-classes')
@RequirePermission('student:view')
compareClasses(@Param('id') id: string) {
return this.service.compareClasses(+id);
compareClasses(@Param('id', ParseIntPipe) id: number) {
return this.service.compareClasses(id);
}
}