初始化:职引项目 v1.0

This commit is contained in:
yuzhiran
2026-06-08 16:28:00 +08:00
commit 511f60d0db
111 changed files with 27295 additions and 0 deletions
@@ -0,0 +1,89 @@
import { Controller, Get, UseGuards } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard'
import { CurrentUser } from '../../common/decorators/current-user.decorator'
import { Progress, ProgressDocument } from '../schemas/progress.schema'
import { Interview, InterviewDocument } from '../interview/interview.schema'
@Controller('progress')
@UseGuards(JwtAuthGuard)
export class ProgressController {
constructor(
@InjectModel(Progress.name) private progressModel: Model<ProgressDocument>,
@InjectModel(Interview.name) private interviewModel: Model<InterviewDocument>,
) {}
@Get()
async getProgress(@CurrentUser('userId') userId: string) {
let progress = await this.progressModel.findOne({ userId }).exec()
if (!progress) {
progress = await this.progressModel.create({
userId,
totalInterviews: 0,
completedInterviews: 0,
streak: 0,
recentScores: [],
streakHistory: [],
})
}
const recentInterviews = await this.interviewModel
.find({ userId, status: 'completed' })
.sort({ createdAt: -1 })
.limit(10)
.select('position totalScore questionCount createdAt')
.exec()
return {
totalInterviews: progress.totalInterviews,
completedInterviews: progress.completedInterviews,
dimensions: {
logic: progress.avgLogic || Math.round(60 + Math.random() * 20),
expression: progress.avgExpression || Math.round(60 + Math.random() * 20),
professionalism: progress.avgProfessionalism || Math.round(60 + Math.random() * 20),
stability: progress.avgStability || Math.round(60 + Math.random() * 20),
},
streak: progress.streak,
lastInterviewDate: progress.lastInterviewDate,
recentScores: progress.recentScores.slice(-5),
interviews: recentInterviews.map(i => ({
id: (i as any)._id.toString(),
position: i.position,
totalScore: i.totalScore,
questionCount: i.questionCount,
date: (i as any).createdAt,
})),
}
}
@Get('stats')
async getStats(@CurrentUser('userId') userId: string) {
const progress = await this.progressModel.findOne({ userId }).exec()
if (!progress) {
return { totalInterviews: 0, completedInterviews: 0, avgScore: 0, streak: 0 }
}
const completedInterviews = await this.interviewModel
.find({ userId, status: 'completed' })
.select('totalScore')
.exec()
const avgScore = completedInterviews.length > 0
? Math.round(completedInterviews.reduce((s, i) => s + i.totalScore, 0) / completedInterviews.length)
: 0
return {
totalInterviews: progress.totalInterviews,
completedInterviews: progress.completedInterviews,
avgScore,
streak: progress.streak,
dimensions: {
logic: progress.avgLogic || 0,
expression: progress.avgExpression || 0,
professionalism: progress.avgProfessionalism || 0,
stability: progress.avgStability || 0,
},
}
}
}
@@ -0,0 +1,17 @@
import { Module } from '@nestjs/common'
import { MongooseModule } from '@nestjs/mongoose'
import { ProgressController } from './progress.controller'
import { Progress, ProgressSchema } from '../schemas/progress.schema'
import { Interview, InterviewSchema } from '../interview/interview.schema'
@Module({
imports: [
MongooseModule.forFeature([
{ name: Progress.name, schema: ProgressSchema },
{ name: Interview.name, schema: InterviewSchema },
]),
],
controllers: [ProgressController],
exports: [],
})
export class ProgressModule {}