Files
aurak/server/src/assessment/controllers/question-bank.controller.ts
T

180 lines
5.2 KiB
TypeScript

import {
Controller,
Get,
Post,
Put,
Delete,
Body,
Param,
Query,
UseGuards,
UsePipes,
ValidationPipe,
Req,
Logger,
} from '@nestjs/common';
import { QuestionBankService } from '../services/question-bank.service';
import {
CreateQuestionBankDto,
UpdateQuestionBankDto,
CreateQuestionBankItemDto,
UpdateQuestionBankItemDto,
ReviewDto,
} from '../services/question-bank.service';
import { CombinedAuthGuard } from '../../auth/combined-auth.guard';
import { KnowledgeGroupService } from '../../knowledge-group/knowledge-group.service';
@Controller('question-banks')
@UseGuards(CombinedAuthGuard)
@UsePipes(ValidationPipe)
export class QuestionBankController {
private readonly logger = new Logger(QuestionBankController.name);
constructor(
private readonly questionBankService: QuestionBankService,
private readonly groupService: KnowledgeGroupService,
) {}
@Post()
async create(@Body() createDto: CreateQuestionBankDto, @Req() req: any) {
try {
this.logger.log(`Creating question bank: ${createDto.name}, user: ${req.user?.id}, tenant: ${req.user?.tenantId}`);
return await this.questionBankService.create(createDto, req.user.id, req.user.tenantId);
} catch (err: any) {
this.logger.error(`[create] Failed: ${err.message}`, err.stack);
throw err;
}
}
@Get()
findAll(
@Req() req: any,
@Query('page') page?: string,
@Query('limit') limit?: string,
) {
const pageNum = page ? parseInt(page, 10) : undefined;
const limitNum = limit ? parseInt(limit, 10) : undefined;
return this.questionBankService.findAll(
req.user.id,
req.user.tenantId,
pageNum,
limitNum,
);
}
@Get('by-template/:templateId')
async findByTemplateId(@Param('templateId') templateId: string) {
return this.questionBankService.findByTemplateId(templateId);
}
@Get(':id')
async findOne(@Param('id') id: string) {
return this.questionBankService.findOne(id);
}
@Put(':id')
async update(@Param('id') id: string, @Body() updateDto: UpdateQuestionBankDto) {
return this.questionBankService.update(id, updateDto);
}
@Delete(':id')
async remove(@Param('id') id: string) {
return this.questionBankService.remove(id);
}
@Put(':id/submit')
async submitForReview(@Param('id') id: string, @Req() req: any) {
return this.questionBankService.submitForReview(id, req.user.id);
}
@Put(':id/review')
async review(@Param('id') id: string, @Body() reviewDto: ReviewDto, @Req() req: any) {
return this.questionBankService.review(id, reviewDto, req.user.id);
}
@Put(':id/publish')
async publish(@Param('id') id: string) {
return this.questionBankService.publish(id);
}
@Get(':bankId/items')
async getItems(@Param('bankId') bankId: string) {
const bank = await this.questionBankService.findOne(bankId);
return bank.items || [];
}
@Post(':bankId/items')
async addItem(
@Param('bankId') bankId: string,
@Body() createDto: CreateQuestionBankItemDto,
) {
return this.questionBankService.addItem(bankId, createDto);
}
@Put(':bankId/items/:id')
async updateItem(
@Param('bankId') bankId: string,
@Param('id') id: string,
@Body() updateDto: UpdateQuestionBankItemDto,
) {
return this.questionBankService.updateItem(bankId, id, updateDto);
}
@Delete(':bankId/items/:id')
async removeItem(
@Param('bankId') bankId: string,
@Param('id') id: string,
) {
return this.questionBankService.removeItem(bankId, id);
}
@Post(':bankId/generate')
async generate(
@Param('bankId') bankId: string,
@Body() body: { count: number; knowledgeBaseContent?: string },
@Req() req: any,
) {
let content = body.knowledgeBaseContent || '';
if (!content || content.trim().length < 10) {
try {
const bank = await this.questionBankService.findOne(bankId);
if (bank?.template?.knowledgeGroupId) {
const files = await this.groupService.getGroupFiles(
bank.template.knowledgeGroupId,
req.user.id,
req.user.tenantId,
);
content = files
.filter((f: any) => f.content && f.content.trim().length > 0)
.map((f: any) => `--- ${f.title || f.originalName || 'Document'} ---\n${f.content}`)
.join('\n\n');
this.logger.log(`[generate] Auto-loaded ${files.length} files, content length: ${content.length}`);
}
} catch (err: any) {
this.logger.warn(`[generate] Auto-load failed: ${err.message}`);
}
}
this.logger.log(`[generate] Generating ${body.count} questions for bank ${bankId}, content length: ${content.length}`);
return this.questionBankService.generateQuestions(
bankId,
body.count,
content,
req.user.tenantId,
);
}
@Post(':bankId/items/batch-review')
async batchReviewItems(
@Param('bankId') bankId: string,
@Body() body: { itemIds: string[]; approved: boolean; comment?: string },
) {
this.logger.log(`[batchReview] Reviewing ${body.itemIds.length} items, approved: ${body.approved}`);
return this.questionBankService.batchReviewItems(
bankId,
body.itemIds,
body.approved,
body.comment,
);
}
}