feat: Phase 1-3 全部完成 — 沙盒增强、学情分析、学习路径

This commit is contained in:
yuzhiran-dev
2026-05-18 09:48:51 +08:00
commit 11bb86854c
277 changed files with 37755 additions and 0 deletions
@@ -0,0 +1,52 @@
import {
Controller,
Post,
UseInterceptors,
UploadedFile,
BadRequestException,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname, join } from 'path';
import { randomUUID } from 'crypto';
import { ApiTags } from '@nestjs/swagger';
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'];
const MAX_SIZE = 5 * 1024 * 1024;
@ApiTags('文件上传')
@Controller('upload')
export class UploadController {
@Post()
@UseInterceptors(
FileInterceptor('file', {
storage: diskStorage({
destination: join(process.cwd(), 'uploads'),
filename: (_req, file, cb) => {
const ext = extname(file.originalname);
cb(null, `${randomUUID()}${ext}`);
},
}),
limits: { fileSize: MAX_SIZE },
fileFilter: (_req, file, cb) => {
if (ALLOWED_TYPES.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new BadRequestException('不支持的文件类型,仅支持 jpg/png/gif/webp/svg'), false);
}
},
}),
)
uploadFile(@UploadedFile() file: Express.Multer.File) {
if (!file) {
throw new BadRequestException('请选择文件');
}
return {
url: `/uploads/${file.filename}`,
filename: file.filename,
size: file.size,
mimetype: file.mimetype,
};
}
}
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { UploadController } from './upload.controller';
import { UploadService } from './upload.service';
@Module({
controllers: [UploadController],
providers: [UploadService],
})
export class UploadModule {}
@@ -0,0 +1,18 @@
import { Injectable } from '@nestjs/common';
import { extname } from 'path';
import * as fs from 'fs';
@Injectable()
export class UploadService {
private uploadDir = 'uploads';
ensureUploadDir() {
if (!fs.existsSync(this.uploadDir)) {
fs.mkdirSync(this.uploadDir, { recursive: true });
}
}
getUploadDir(): string {
return this.uploadDir;
}
}