forked from wangziqi/gongxue-base
146 lines
4.3 KiB
TypeScript
146 lines
4.3 KiB
TypeScript
import {
|
|
Body,
|
|
Controller,
|
|
Get,
|
|
Param,
|
|
ParseIntPipe,
|
|
Post,
|
|
Put,
|
|
Query,
|
|
Request,
|
|
UseGuards,
|
|
UsePipes,
|
|
ValidationPipe,
|
|
} from '@nestjs/common';
|
|
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
|
import { RequirePermission } from '../auth/decorators/permission.decorator';
|
|
import { extractRequestInfo } from '../common/request-utils';
|
|
import { OperationLogsService } from '../operation-logs/operation-logs.service';
|
|
import type { AuthenticatedUser } from '../authorization';
|
|
import { CreateExamDto, QueryExamDto, UpdateExamScoreValueDto } from './dto/exam.dto';
|
|
import { ExamsService } from './exams.service';
|
|
|
|
interface AuthenticatedRequest {
|
|
user: AuthenticatedUser;
|
|
ip?: string;
|
|
headers?: Record<string, string | string[] | undefined>;
|
|
}
|
|
|
|
@UseGuards(JwtAuthGuard)
|
|
@UsePipes(new ValidationPipe({ transform: true, whitelist: true, forbidNonWhitelisted: true }))
|
|
@Controller('exams')
|
|
export class ExamsController {
|
|
constructor(
|
|
private readonly service: ExamsService,
|
|
private readonly logService: OperationLogsService,
|
|
) {}
|
|
|
|
private canManageAll(req: AuthenticatedRequest) {
|
|
return req.user.isSuperAdmin || req.user.permissions.includes('exam:edit');
|
|
}
|
|
|
|
@Get()
|
|
@RequirePermission('exam:view')
|
|
async findAll(@Query() query: QueryExamDto, @Request() req: AuthenticatedRequest) {
|
|
const classIds = await this.service.getAccessibleClassIds(req.user.id, this.canManageAll(req));
|
|
return this.service.findAll(query, classIds);
|
|
}
|
|
|
|
@Get(':id')
|
|
@RequirePermission('exam:view')
|
|
findOne(@Param('id', ParseIntPipe) id: number, @Request() req: AuthenticatedRequest) {
|
|
return this.service.findOne(id, req.user.id, this.canManageAll(req));
|
|
}
|
|
|
|
@Post()
|
|
@RequirePermission('exam:view')
|
|
async create(@Body() dto: CreateExamDto, @Request() req: AuthenticatedRequest) {
|
|
const result = await this.service.create(dto, req.user.id, this.canManageAll(req));
|
|
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
await this.logService.log({
|
|
userId: req.user.id,
|
|
username: req.user.username,
|
|
module: '考试管理',
|
|
action: '创建考试',
|
|
targetId: result.id,
|
|
targetType: 'exam',
|
|
detail: `${dto.examName} - ${dto.subject}`,
|
|
ipAddress,
|
|
userAgent,
|
|
});
|
|
return result;
|
|
}
|
|
|
|
@Put(':id/archive')
|
|
@RequirePermission('exam:view')
|
|
async archive(
|
|
@Param('id', ParseIntPipe) id: number,
|
|
@Request() req: AuthenticatedRequest,
|
|
) {
|
|
const result = await this.service.archive(id, req.user.id, this.canManageAll(req));
|
|
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
await this.logService.log({
|
|
userId: req.user.id,
|
|
username: req.user.username,
|
|
module: '考试管理',
|
|
action: '归档考试',
|
|
targetId: id,
|
|
targetType: 'exam',
|
|
ipAddress,
|
|
userAgent,
|
|
});
|
|
return result;
|
|
}
|
|
|
|
@Put(':id/restore')
|
|
@RequirePermission('exam:view')
|
|
async restore(
|
|
@Param('id', ParseIntPipe) id: number,
|
|
@Request() req: AuthenticatedRequest,
|
|
) {
|
|
const result = await this.service.restore(id, req.user.id, this.canManageAll(req));
|
|
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
await this.logService.log({
|
|
userId: req.user.id,
|
|
username: req.user.username,
|
|
module: '考试管理',
|
|
action: '恢复考试',
|
|
targetId: id,
|
|
targetType: 'exam',
|
|
ipAddress,
|
|
userAgent,
|
|
});
|
|
return result;
|
|
}
|
|
|
|
@Put(':examId/scores/:scoreId')
|
|
@RequirePermission('exam:view')
|
|
async updateScore(
|
|
@Param('examId', ParseIntPipe) examId: number,
|
|
@Param('scoreId', ParseIntPipe) scoreId: number,
|
|
@Body() dto: UpdateExamScoreValueDto,
|
|
@Request() req: AuthenticatedRequest,
|
|
) {
|
|
const result = await this.service.updateScore(
|
|
examId,
|
|
scoreId,
|
|
dto.score,
|
|
req.user.id,
|
|
this.canManageAll(req),
|
|
);
|
|
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
await this.logService.log({
|
|
userId: req.user.id,
|
|
username: req.user.username,
|
|
module: '考试管理',
|
|
action: dto.score === null || dto.score === undefined ? '清空成绩' : '录入成绩',
|
|
targetId: scoreId,
|
|
targetType: 'exam_score',
|
|
detail: dto.score === null || dto.score === undefined ? '成绩已清空' : `成绩:${dto.score}`,
|
|
ipAddress,
|
|
userAgent,
|
|
});
|
|
return result;
|
|
}
|
|
}
|