2026 全栈实战:NestJS + 现代化前端,从零搭建企业级考试题库系统

1 阅读7分钟

前言

在教育数字化、企业内部培训、职业认证考试全面普及的今天,考试题库系统已经成为刚需产品。作为全栈开发者,掌握一套稳定、可扩展、高性能的考试题库开发方案,无论是接外包、做内部系统、还是打造 SaaS 产品,都极具价值。

当前市面上的考试系统要么臃肿难用,要么收费昂贵,要么接口难以定制化。而基于 NestJS 开发后端,搭配现代化前端框架,能快速搭建出支持百万题库、高并发、权限严密、自动组卷、在线考试的企业级系统。

本文是一篇纯原创、可直接落地、从零到一的全栈实战教程,从需求分析、架构设计、后端接口开发、数据库设计、前端实现、部署上线全覆盖,代码干净、注释完整,适合全栈开发者、后端工程师、学生学习,也可直接作为毕业设计、企业项目模板。


一、系统需求与功能规划(真实企业级标准)

1.1 核心使用角色

  • 超级管理员:系统配置、权限管理、题库管理、用户管理
  • 教师 / 管理员:题目管理、试卷管理、考试管理、成绩管理
  • 学生 / 考生:在线考试、查看成绩、错题练习、个人中心

1.2 核心功能模块

  1. 用户权限模块:登录、注册、JWT 鉴权、RBAC 权限控制
  2. 题库管理模块:单选、多选、判断、简答、材料题全题型支持
  3. 试卷管理模块:固定组卷、随机组卷、难度控制、知识点分类
  4. 考试管理模块:发布考试、时间限制、防切屏、自动阅卷
  5. 答题模块:在线答题、自动保存、倒计时、交卷评分
  6. 成绩统计模块:考试排名、正确率统计、错题分析
  7. 系统管理模块:日志、参数配置、数据备份

1.3 技术栈选型(2026 最稳全栈组合)

后端

  • NestJS(企业级 Node 框架)
  • TypeORM / Prisma(数据库 ORM)
  • MySQL / PostgreSQL(关系型数据库)
  • Redis(缓存、登录状态、考试限流)
  • JWT(身份鉴权)
  • Swagger(自动接口文档)

前端

  • Vue3 / React 二选一
  • Vite
  • Element Plus / Ant Design
  • Pinia/Vuex
  • TypeScript

部署

  • Docker + Docker Compose
  • Nginx 反向代理
  • PM2 进程守护

二、数据库设计(考试系统核心)

考试系统的数据库设计直接决定扩展性,以下是生产环境可用的核心表结构:

2.1 用户表(user)

id、username、password、nickname、role、phone、email、status、create_time、update_time

2.2 角色权限表(role、permission)

RBAC 权限模型,支持菜单权限、接口权限细粒度控制

2.3 题库分类表(question_category)

id、name、parent_id、sort、status

2.4 题目表(question)

id、type(单选 / 多选 / 判断 / 简答)、title、content、category_id、difficulty、answer、analysis、score、creator、create_time

2.5 试卷表(exam_paper)

id、title、duration、total_score、pass_score、random_question(是否随机)、status、create_time

2.6 试卷题目关联表(paper_question)

id、paper_id、question_id、sort

2.7 考试记录表(exam_record)

id、user_id、paper_id、score、status、start_time、submit_time、use_time

2.8 答题详情表(exam_record_detail)

id、record_id、question_id、user_answer、is_correct、score


三、NestJS 后端项目搭建与初始化

3.1 环境搭建

bash

运行

# 安装 Nest CLI
npm i -g @nestjs/cli

# 创建项目
nest new exam-system-backend

# 安装核心依赖
npm install @nestjs/typeorm typeorm mysql2 redis @nestjs/jwt @nestjs/passport passport-jwt bcryptjs class-validator class-transformer swagger-ui-express @nestjs/swagger

3.2 项目结构(企业级标准)

plaintext

src
├── auth       认证模块
├── user       用户模块
├── question   题目模块
├── paper      试卷模块
├── exam       考试模块
├── record     考试记录
├── common     通用工具
├── config     配置
├── entity     数据库实体
└── main.ts

3.3 配置数据库与 ORM

typescript

运行

// app.module.ts
TypeOrmModule.forRoot({
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: 'root',
  database: 'exam_system',
  entities: [__dirname + '/**/*.entity{.ts,.js}'],
  synchronize: true,
  autoLoadEntities: true,
})

3.4 配置 JWT 认证

typescript

运行

JwtModule.register({
  secret: 'exam-system-2026',
  signOptions: { expiresIn: '24h' },
})

3.5 启用 Swagger 接口文档

typescript

运行

// main.ts
const config = new DocumentBuilder()
.setTitle('考试题库系统 API')
.setDescription('NestJS 全栈考试系统')
.setVersion('1.0')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);

启动后访问:http://localhost:3000/api 即可看到自动生成的接口文档。


四、核心模块开发(代码可直接复制使用)

4.1 认证模块(登录 + JWT)

登录逻辑

  • 校验用户名密码
  • 生成 JWT Token
  • 返回用户信息 + 权限

核心代码

typescript

运行

async login(loginDto: LoginDto) {
  const user = await this.userService.findByUsername(loginDto.username);
  if (!user) throw new BadRequestException('用户不存在');
  
  const isMatch = await bcrypt.compare(loginDto.password, user.password);
  if (!isMatch) throw new BadRequestException('密码错误');
  
  const token = this.jwtService.sign({ id: user.id, username: user.username });
  return { token, user };
}

4.2 题目管理模块(支持 5 种题型)

支持:

  • 单选
  • 多选
  • 判断
  • 简答
  • 材料题

新增题目接口

typescript

运行

@Post()
async create(@Body() createDto: CreateQuestionDto) {
  return await this.questionService.create(createDto);
}

题目列表(分页 + 筛选 + 分类 + 难度)

typescript

运行

async findAll(query: QueryQuestionDto) {
  const { page = 1, size = 10, categoryId, type, difficulty } = query;
  const qb = this.questionRepository.createQueryBuilder('q');
  if (categoryId) qb.andWhere('q.categoryId = :categoryId', { categoryId });
  if (type) qb.andWhere('q.type = :type', { type });
  if (difficulty) qb.andWhere('q.difficulty = :difficulty', { difficulty });
  
  const total = await qb.getCount();
  const list = await qb.skip((page - 1) * size).take(size).getMany();
  return { total, list };
}

4.3 试卷模块(随机组卷 + 固定组卷)

随机组卷逻辑

typescript

运行

async randomPaper(dto: RandomPaperDto) {
  const { categoryId, radioCount, radioScore, multiCount, multiScore, judgeCount, judgeScore } = dto;
  
  // 随机抽取单选题
  const radios = await this.questionRepository
    .createQueryBuilder('q')
    .where('q.type = 1 AND q.categoryId = :categoryId', { categoryId })
    .orderBy('RAND()')
    .limit(radioCount)
    .getMany();
  
  // 多选、判断同理...
  
  // 组装试卷并保存
  return await this.paperService.createWithQuestions({ ...dto, questions: [...radios, ...multis, ...judges] });
}

4.4 考试模块(开始考试 + 自动保存 + 交卷)

核心逻辑

  • 校验是否参加过考试
  • 生成考试记录
  • 返回题目列表
  • 交卷自动阅卷、算分、判断是否通过

自动阅卷代码

typescript

运行

async autoGrade(recordId: number, answers: AnswerItem[]) {
  let totalScore = 0;
  const details = [];
  
  for (const item of answers) {
    const question = await this.questionService.findById(item.questionId);
    let isCorrect = 0;
    let score = 0;
    
    if (question.type === 1 || question.type === 3) {
      // 单选、判断
      if (item.userAnswer === question.answer) {
        isCorrect = 1;
        score = question.score;
        totalScore += score;
      }
    }
    
    details.push({ recordId, questionId: item.questionId, userAnswer: item.userAnswer, isCorrect, score });
  }
  
  // 保存成绩
  await this.recordRepository.update(recordId, { score: totalScore, status: 2 });
  await this.recordDetailRepository.save(details);
  
  return { score: totalScore };
}

五、前端项目搭建(Vue3 + Element Plus)

5.1 项目创建

bash

运行

npm create vite@latest exam-system-frontend
cd exam-system-frontend
npm install element-plus pinia axios vue-router

5.2 核心页面

  • 登录页
  • 首页(数据看板)
  • 题库管理(增删改查、批量导入)
  • 试卷管理(随机组卷、固定组卷)
  • 考试管理(发布、列表)
  • 在线考试页面(答题、倒计时、自动保存)
  • 成绩详情、错题本

5.3 在线考试答题页(核心体验)

包含:

  • 顶部倒计时
  • 题目选项渲染
  • 答题卡定位
  • 自动保存
  • 禁止刷新、防切屏提示
  • 交卷确认

vue

<template>
  <div class="exam-page">
    <div class="timer">{{ formatTime(time) }}</div>
    <div v-for="q in questionList" :key="q.id" class="question-item">
      <h3>{{ q.title }}</h3>
      <el-radio-group v-model="answers[q.id]" v-if="q.type === 1">
        <el-radio label="A">A. {{ q.optionA }}</el-radio>
        <el-radio label="B">B. {{ q.optionB }}</el-radio>
      </el-radio-group>
    </div>
    <el-button @click="submitExam">交卷</el-button>
  </div>
</template>

六、Excel 批量导入题库(企业必备功能)

NestJS 轻松实现 Excel 导入:

  • 安装 xlsx
  • 上传 Excel → 解析 → 批量入库

typescript

运行

@Post('import')
@UseInterceptors(FileInterceptor('file'))
async import(@UploadedFile() file) {
  const workbook = XLSX.read(file.buffer);
  const sheet = workbook.Sheets[workbook.SheetNames[0]];
  const data = XLSX.utils.sheet_to_json(sheet);
  
  const list = data.map(item => ({
    title: item['题目'],
    type: item['类型'],
    optionA: item['选项A'],
    answer: item['答案'],
    score: item['分值'],
  }));
  
  await this.questionRepository.save(list);
  return { count: list.length };
}

七、权限控制(RBAC 细粒度)

  • 接口守卫
  • 菜单权限
  • 按钮权限
  • 前端动态路由

typescript

运行

@Get('admin/list')
@Roles('admin')
async adminList() {
  return await this.userService.findAll();
}

八、部署上线(Docker Compose 一键部署)

yaml

version: '3'
services:
  mysql:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: exam_system
  redis:
    image: redis
  backend:
    build: ./backend
    ports:
      - 3000:3000
  frontend:
    build: ./frontend
    ports:
      - 80:80

一行命令启动整套系统:

bash

运行

docker-compose up -d

九、系统亮点与扩展方向

9.1 本系统亮点

  1. 纯 NestJS 企业级架构
  2. 支持 5 种考试题型
  3. 随机 + 固定组卷
  4. 自动阅卷、自动算分
  5. 防切屏、考试监控
  6. 错题本、成绩统计
  7. RBAC 权限、接口安全
  8. Excel 批量导入题库
  9. Docker 一键部署
  10. 支持高并发、百万题库

9.2 可扩展方向

  • 人脸识别防作弊
  • 视频监考
  • 主观题 AI 批改
  • 微信小程序、公众号
  • 多租户 SaaS 版本
  • 刷题模式、模拟考试

十、总结

这套 NestJS 全栈考试题库系统 是一套真正能上线、能赚钱、能当毕设、能进企业项目的完整方案。

相比市面上的速成项目,本系统:

  • 架构更清晰
  • 代码更规范
  • 功能更完整
  • 体验更流畅
  • 安全性更高
  • 可直接用于商业开发

无论你是前端想转全栈,还是后端想练手,或是学生做毕业设计,这套系统都能让你快速掌握 NestJS 全栈开发思想,轻松拿下各类考试系统类需求。