2026-06-18 11:22:03 +08:00
|
|
|
import { Controller, Get, Put, Post, Delete, Param, Body, Req, Query } from '@nestjs/common';
|
2026-06-11 20:39:29 +08:00
|
|
|
import { UserAiService } from './user-ai.service';
|
2026-06-18 11:22:03 +08:00
|
|
|
import { SaveLearningProfileDto, UpdateAiSettingsDto, CreateCredentialDto, UpdateCredentialDto, CreateAnalysisJobDto } from './user-ai.dto';
|
2026-06-11 20:39:29 +08:00
|
|
|
|
|
|
|
|
@Controller('ai')
|
|
|
|
|
export class UserAiController {
|
|
|
|
|
constructor(private readonly service: UserAiService) {}
|
|
|
|
|
|
|
|
|
|
// ── Profile ──
|
|
|
|
|
|
|
|
|
|
@Get('profile')
|
|
|
|
|
async getProfile(@Req() req: any) {
|
2026-06-18 11:57:38 +08:00
|
|
|
return (await this.service.getProfile(req.user.id)) ?? {};
|
2026-06-11 20:39:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Put('profile')
|
|
|
|
|
async saveProfile(@Req() req: any, @Body() dto: SaveLearningProfileDto) {
|
|
|
|
|
return this.service.saveProfile(req.user.id, dto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Settings ──
|
|
|
|
|
|
|
|
|
|
@Get('settings')
|
|
|
|
|
async getSettings(@Req() req: any) {
|
|
|
|
|
return this.service.getSettings(req.user.id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Put('settings')
|
|
|
|
|
async updateSettings(@Req() req: any, @Body() dto: UpdateAiSettingsDto) {
|
|
|
|
|
return this.service.updateSettings(req.user.id, dto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Model Credentials ──
|
|
|
|
|
|
|
|
|
|
@Get('model-credentials')
|
|
|
|
|
async listCredentials(@Req() req: any) {
|
|
|
|
|
return this.service.listCredentials(req.user.id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Post('model-credentials')
|
|
|
|
|
async createCredential(@Req() req: any, @Body() dto: CreateCredentialDto) {
|
|
|
|
|
return this.service.createCredential(req.user.id, dto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Put('model-credentials/:id')
|
|
|
|
|
async updateCredential(@Req() req: any, @Param('id') id: string, @Body() dto: UpdateCredentialDto) {
|
|
|
|
|
return this.service.updateCredential(req.user.id, id, dto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Delete('model-credentials/:id')
|
|
|
|
|
async deleteCredential(@Req() req: any, @Param('id') id: string) {
|
|
|
|
|
await this.service.deleteCredential(req.user.id, id);
|
|
|
|
|
return { ok: true };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Post('model-credentials/:id/test')
|
|
|
|
|
async testCredential(@Req() req: any, @Param('id') id: string) {
|
|
|
|
|
return this.service.testCredential(req.user.id, id);
|
|
|
|
|
}
|
2026-06-18 11:22:03 +08:00
|
|
|
|
|
|
|
|
// ── Analysis Jobs ──
|
|
|
|
|
|
|
|
|
|
@Post('jobs')
|
|
|
|
|
async createAnalysisJob(@Req() req: any, @Body() dto: CreateAnalysisJobDto) {
|
|
|
|
|
return this.service.createAnalysisJob(req.user.id, dto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Post('jobs/:jobId/cancel')
|
|
|
|
|
async cancelJob(@Req() req: any, @Param('jobId') jobId: string) {
|
|
|
|
|
return this.service.cancelJob(req.user.id, jobId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('jobs/:jobId')
|
|
|
|
|
async getJob(@Req() req: any, @Param('jobId') jobId: string) {
|
|
|
|
|
return this.service.getJob(req.user.id, jobId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('jobs')
|
|
|
|
|
async listJobs(@Req() req: any, @Query('status') status?: string, @Query('take') take?: string) {
|
|
|
|
|
return this.service.listJobs(req.user.id, status, take ? parseInt(take) : undefined);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Quiz Publish ──
|
|
|
|
|
|
|
|
|
|
@Post('quizzes/:quizId/publish')
|
|
|
|
|
async publishQuiz(@Req() req: any, @Param('quizId') quizId: string) {
|
|
|
|
|
return this.service.publishQuiz(req.user.id, quizId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Post('flashcards/:cardId/publish')
|
|
|
|
|
async publishFlashcard(@Req() req: any, @Param('cardId') cardId: string) {
|
|
|
|
|
return this.service.publishFlashcard(req.user.id, cardId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Analysis Results ──
|
|
|
|
|
|
|
|
|
|
@Get('analyses/:id')
|
|
|
|
|
async getAnalysis(@Req() req: any, @Param('id') id: string) {
|
|
|
|
|
return this.service.getAnalysis(req.user.id, id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('analyses')
|
|
|
|
|
async listAnalyses(
|
|
|
|
|
@Req() req: any,
|
|
|
|
|
@Query('targetType') targetType?: string,
|
|
|
|
|
@Query('targetId') targetId?: string,
|
|
|
|
|
@Query('take') take?: string,
|
|
|
|
|
) {
|
|
|
|
|
return this.service.listAnalyses(req.user.id, targetType, targetId, take ? parseInt(take) : undefined);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('recommendations')
|
|
|
|
|
async listRecommendations(
|
|
|
|
|
@Req() req: any,
|
|
|
|
|
@Query('targetType') targetType?: string,
|
|
|
|
|
@Query('targetId') targetId?: string,
|
|
|
|
|
@Query('status') status?: string,
|
|
|
|
|
@Query('take') take?: string,
|
|
|
|
|
) {
|
|
|
|
|
return this.service.listRecommendations(req.user.id, targetType, targetId, status, take ? parseInt(take) : undefined);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('weak-points')
|
|
|
|
|
async listWeakPoints(
|
|
|
|
|
@Req() req: any,
|
|
|
|
|
@Query('targetType') targetType?: string,
|
|
|
|
|
@Query('targetId') targetId?: string,
|
|
|
|
|
@Query('status') status?: string,
|
|
|
|
|
@Query('take') take?: string,
|
|
|
|
|
) {
|
|
|
|
|
return this.service.listWeakPoints(req.user.id, targetType, targetId, status, take ? parseInt(take) : undefined);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('quizzes/:quizId')
|
|
|
|
|
async getQuiz(@Req() req: any, @Param('quizId') quizId: string) {
|
|
|
|
|
return this.service.getQuiz(req.user.id, quizId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('quizzes/:quizId/questions')
|
|
|
|
|
async getQuizQuestions(@Req() req: any, @Param('quizId') quizId: string) {
|
|
|
|
|
return this.service.getQuizQuestions(req.user.id, quizId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('quizzes')
|
|
|
|
|
async listQuizzes(
|
|
|
|
|
@Req() req: any,
|
|
|
|
|
@Query('knowledgeBaseId') knowledgeBaseId?: string,
|
|
|
|
|
@Query('status') status?: string,
|
|
|
|
|
@Query('take') take?: string,
|
|
|
|
|
) {
|
|
|
|
|
return this.service.listQuizzes(req.user.id, knowledgeBaseId, status, take ? parseInt(take) : undefined);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Post('reanalyze')
|
|
|
|
|
async triggerReanalysis(
|
|
|
|
|
@Req() req: any,
|
|
|
|
|
@Body('targetType') targetType: string,
|
|
|
|
|
@Body('targetId') targetId: string,
|
|
|
|
|
) {
|
|
|
|
|
return this.service.triggerReanalysis(req.user.id, targetType, targetId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('notifications')
|
|
|
|
|
async listNotifications(@Req() req: any, @Query('take') take?: string) {
|
|
|
|
|
return this.service.listNotifications(req.user.id, take ? parseInt(take) : undefined);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Post('artifacts/:type/:id/feedback')
|
|
|
|
|
async submitArtifactFeedback(
|
|
|
|
|
@Req() req: any,
|
|
|
|
|
@Param('type') artifactType: string,
|
|
|
|
|
@Param('id') artifactId: string,
|
|
|
|
|
@Body() dto: { feedbackType: string; reason?: string },
|
|
|
|
|
) {
|
|
|
|
|
return this.service.submitArtifactFeedback(req.user.id, artifactType, artifactId, dto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Post('feedback')
|
|
|
|
|
async submitFeedback(@Req() req: any, @Body() dto: { category: string; content: string; email?: string; deviceInfo?: any }) {
|
|
|
|
|
return this.service.submitFeedback(req.user.id, dto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('flashcards/:cardId')
|
|
|
|
|
async getFlashcard(@Req() req: any, @Param('cardId') cardId: string) {
|
|
|
|
|
return this.service.getFlashcard(req.user.id, cardId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get('flashcards')
|
|
|
|
|
async listFlashcards(
|
|
|
|
|
@Req() req: any,
|
|
|
|
|
@Query('knowledgePointId') knowledgePointId?: string,
|
|
|
|
|
@Query('status') status?: string,
|
|
|
|
|
@Query('take') take?: string,
|
|
|
|
|
) {
|
|
|
|
|
return this.service.listFlashcards(req.user.id, knowledgePointId, status, take ? parseInt(take) : undefined);
|
|
|
|
|
}
|
2026-06-11 20:39:29 +08:00
|
|
|
}
|