180 lines
5.2 KiB
TypeScript
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,
|
|
);
|
|
}
|
|
} |