欢迎光临
我们一直在努力

SpringBoot + Vue3 在线作业管理系统【附源码+数据库+40接口+ER图+部署+一键启动】

一、项目简介

本项目是一个面向学校和教育机构的在线作业管理平台,覆盖了作业发布 → 学生提交 → 教师批改 → 成绩统计的完整流程。

1🎯 核心亮点:本系统内置作业查重功能,教师可对某次作业的所有提交进行文本相似度检测,有效识别抄袭行为。查重结果以相似度分数呈现,帮助教师快速定位疑似抄袭的作业,维护学术诚信。

1.1 核心角色

角色核心功能
学生 查看作业、提交作业(含文件上传)、查看成绩与反馈、修改个人资料(需审批)
教师 发布作业(按学生定向分配)、批改作业(评分+评语)、查看班级成绩统计、作业查重检测
管理员 用户管理(增删改查)、审核资料修改申请、全局数据查看

1.2 系统功能模块

  • 🔐 用户认证:注册/登录/忘记密码(验证码找回)/JWT 令牌 + Refresh Token
  • 📝 作业管理:创建、编辑、删除、按班级定向发布、截止时间控制、状态管理(published/expired/withdrawn)
  • 📤 作业提交:多格式文件上传(PDF/Word/ZIP/图片等)、截止时间控制、重新提交、附件删除
  • ✏️ 作业批改:评分(含满分校验)、评语、教师查看所有提交
  • 🔍 作业查重:文本相似度检测、抄袭识别、查重报告、按相似度排序
  • 📊 成绩统计:平均分/最高分/最低分、提交率/批改率、学生个人详情、ECharts 可视化图表
  • 🔔 消息通知:系统通知、作业提醒、成绩通知、永久消息/临时通知分类
  • 📋 申请审批:学生资料修改申请 → 管理员审核(通过/拒绝)
  • 📎 文件管理:附件上传、下载(含 Content-Type 自动识别)、文件大小校验

二、环境配置

在开始使用本项目前,请确保以下环境已安装并正确配置。

2.1 环境要求

软件最低版本推荐版本说明
JDK 24.0.1+ 24.0.1 Java 开发工具包
Maven 3.9.14+ 3.9.14 后端构建工具
Node.js 24.14.1+ 24.14.1 前端运行时
npm 11.11.0+ 11.11.0 前端包管理
MySQL 5.7+ 8.0+ 关系数据库
Redis 6.0+ 7.0+ 缓存数据库

2.2 环境安装

JDK 24 安装

  • 从 Oracle JDK 或 OpenJDK 下载 JDK 24
  • 配置环境变量:JAVA_HOME = JDK 安装路径,PATH 中添加 %JAVA_HOME%\\bin
  • 验证:java -version、javac -version
  • Maven 安装

  • 从 Maven 官网 下载 3.9.14+
  • 配置环境变量:MAVEN_HOME = 解压路径,PATH 中添加 %MAVEN_HOME%\\bin
  • 验证:mvn -version
  • Node.js 安装

  • 从 Node.js 官网 下载 v24.14.1 LTS 版本
  • 验证:node -v、npm -v
  • 推荐配置国内镜像:npm config set registry https://registry.npmmirror.com
  • MySQL 安装

  • 从 MySQL 官网 下载安装
  • 记住 root 密码(本项目默认配置为 123456)
  • 确保 MySQL 服务已启动
  • Redis 安装(Windows)

    方式一 — WSL2:

    bash

    wsl –install
    sudo apt update && sudo apt install redis-server
    sudo service redis-server start

    方式二 — Memurai:Redis-Compatible, Enterprise-Grade In-Memory Caching for Windows | Memurai 下载安装开发版。


    三、技术栈

    3.1 后端

    技术版本用途
    Spring Boot 3.4.5 核心框架
    Spring Security + JWT jjwt 0.12.6 认证与授权(无状态 JWT + RBAC)
    Spring Data JPA ORM 持久层
    MyBatis Plus 3.5.9 复杂查询增强
    MySQL 5.7+ 关系数据库
    Redis(Lettuce 连接池) 6.0+ 缓存与 Token 管理
    Caffeine Cache 3.2.0 本地缓存(用户查询缓存)
    SpringDoc OpenAPI 2.8.4 API 文档自动生成(Swagger UI)
    Apache POI 5.4.0 Excel 导入导出
    iText 7 9.1.0 PDF 生成
    Lombok 1.18.38 简化代码
    Maven 3.9.14+ 构建工具

    3.2 前端

    技术版本用途
    Vue 3.5.13 核心框架(Composition API)
    Pinia 3.0.1 状态管理(替代 Vuex)
    Vue Router 4.5.0 路由管理(含路由懒加载)
    Element Plus 2.9.7 UI 组件库
    @element-plus/icons-vue 2.3.1 图标库
    ECharts + vue-echarts 5.6.0 / 7.0.3 数据可视化
    Axios 1.7.9 HTTP 请求
    Vite 6.0.11 构建工具(开发服务器+代理)
    dayjs 1.11.13 日期处理
    NProgress 0.2.0 页面加载进度条
    js-cookie 3.0.5 Cookie 管理
    file-saver + xlsx 文件下载与 Excel 导出
    Sass 1.83.4 CSS 预处理器
    unplugin-auto-import 19.0.0 自动导入 Vue API
    unplugin-vue-components 28.0.0 自动导入 Element Plus 组件

    四、项目架构

    4.1 目录结构

    4.2 前后端交互流程

    ┌─────────────┐ HTTP/REST ┌─────────────┐ JDBC/JPA ┌──────────┐
    │ Vue 3 │ ◄────────────────► │ Spring Boot │ ◄──────────────► │ MySQL │
    │ 前端 :3000 │ Axios + Proxy │ 后端 :8080 │ │ 数据库 │
    └─────────────┘ └──────┬───────┘ └──────────┘

    │ Caffeine / Redis

    ┌──────────┐
    │ 缓存层 │
    └──────────┘

    • 5前端通过 Vite 开发服务器运行在 localhost:3000
    • 后端运行在 localhost:8080,context-path 为 /api
    • 跨域通过 Vite proxy 代理解决(开发环境),后端也配置了 CORS(生产环境)
    • 认证采用 JWT 无状态 Token,前端存入 Cookie,每次请求通过 Axios 拦截器自动注入 Authorization: Bearer <token>

    五、数据库设计

    系统包含 6 张核心表,完整建表语句见项目根目录的 online_homework_system_complete.sql。

    5.1 users — 用户表

    sql

    CREATE TABLE `users` (
    `id` bigint NOT NULL AUTO_INCREMENT,
    `username` varchar(255) NOT NULL COMMENT '用户名',
    `password` varchar(255) NOT NULL COMMENT '密码(BCrypt 加密)',
    `name` varchar(255) NOT NULL COMMENT '姓名',
    `role` varchar(50) NOT NULL COMMENT '角色(STUDENT/TEACHER/ADMIN)',
    `email` varchar(255) COMMENT '邮箱',
    `phone` varchar(50) COMMENT '手机号',
    `department` varchar(255) COMMENT '院系/部门',
    `major` varchar(255) COMMENT '专业',
    `student_id` varchar(50) COMMENT '学号',
    `avatar` mediumtext COMMENT '头像 URL 或 Base64',
    `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_username` (`username`),
    KEY `idx_role` (`role`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    5.2 homework — 作业表

    sql

    CREATE TABLE `homework` (
    `id` bigint NOT NULL AUTO_INCREMENT,
    `title` varchar(255) NOT NULL COMMENT '作业标题',
    `description` text COMMENT '作业描述',
    `teacher_id` bigint NOT NULL COMMENT '教师 ID',
    `course_name` varchar(255) COMMENT '课程名称',
    `deadline` datetime COMMENT '截止时间',
    `max_score` double COMMENT '满分',
    `allow_modification` tinyint(1) DEFAULT 1 COMMENT '是否允许修改提交',
    `status` varchar(50) DEFAULT 'published' COMMENT '状态(published/expired/withdrawn)',
    `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `idx_teacher_id` (`teacher_id`),
    KEY `idx_status` (`status`),
    KEY `idx_deadline` (`deadline`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    5.3 homework_student — 作业-学生关联表

    sql

    CREATE TABLE `homework_student` (
    `id` bigint NOT NULL AUTO_INCREMENT,
    `homework_id` bigint NOT NULL COMMENT '作业 ID',
    `student_id` bigint NOT NULL COMMENT '学生 ID',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_homework_student` (`homework_id`, `student_id`),
    KEY `idx_student_id` (`student_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    5.4 submissions — 提交表

    sql

    CREATE TABLE `submissions` (
    `id` bigint NOT NULL AUTO_INCREMENT,
    `homework_id` bigint NOT NULL COMMENT '作业 ID',
    `student_id` bigint NOT NULL COMMENT '学生 ID',
    `content` text COMMENT '作业内容',
    `file_path` varchar(500) COMMENT '文件路径',
    `submitted_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `score` double COMMENT '分数',
    `feedback` text COMMENT '评语',
    `graded_at` timestamp NULL COMMENT '批改时间',
    `status` varchar(50) DEFAULT 'submitted' COMMENT '状态(submitted/graded)',
    `similarity_score` double COMMENT '相似度分数',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_homework_student` (`homework_id`, `student_id`),
    CONSTRAINT `fk_submission_homework` FOREIGN KEY (`homework_id`) REFERENCES `homework` (`id`) ON DELETE CASCADE,
    CONSTRAINT `fk_submission_student` FOREIGN KEY (`student_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    5.5 message — 消息通知表

    sql

    CREATE TABLE `message` (
    `id` bigint NOT NULL AUTO_INCREMENT,
    `title` varchar(255) NOT NULL COMMENT '消息标题',
    `content` text COMMENT '消息内容',
    `sender_id` bigint COMMENT '发送者 ID',
    `receiver_id` bigint NOT NULL COMMENT '接收者 ID',
    `type` varchar(50) DEFAULT 'notification' COMMENT '类型(notification/permanent/system)',
    `status` varchar(50) DEFAULT 'active' COMMENT '状态(active/inactive)',
    `is_read` tinyint(1) DEFAULT 0 COMMENT '是否已读',
    `expire_time` datetime COMMENT '过期时间',
    `notification_id` varchar(255) COMMENT '通知 ID(用于批量操作)',
    `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    CONSTRAINT `fk_message_sender` FOREIGN KEY (`sender_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
    CONSTRAINT `fk_message_receiver` FOREIGN KEY (`receiver_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    5.6 profile_requests — 资料申请审批表

    sql

    CREATE TABLE `profile_requests` (
    `id` bigint NOT NULL AUTO_INCREMENT,
    `user_id` bigint NOT NULL COMMENT '用户 ID',
    `username` varchar(255) NOT NULL COMMENT '用户名',
    `name` varchar(255) NOT NULL COMMENT '姓名',
    `email` varchar(255) COMMENT '邮箱',
    `phone` varchar(50) COMMENT '手机号',
    `department` varchar(255) COMMENT '院系',
    `major` varchar(255) COMMENT '专业',
    `student_id` varchar(50) COMMENT '学号',
    `avatar` mediumtext COMMENT '头像',
    `status` varchar(50) NOT NULL DEFAULT 'pending' COMMENT '状态(pending/approved/rejected)',
    `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `idx_user_id` (`user_id`),
    KEY `idx_status` (`status`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    5.7 ER 关系图(文字版)

    users (1) ──────< homework_student >────── (N) homework
    │ │
    │ (teacher_id) │
    └──────────────────────────────────────────────┘

    ├── (1) ────< submissions >──── (N)
    │ │
    │ └──── (N:1) ──── homework

    ├── (1) ────< message (sender) >──── (N)
    ├── (1) ────< message (receiver) >─── (N)

    └── (1) ────< profile_requests >──── (N)


    六、核心功能实现

    6.1 JWT 认证 + RBAC 权限控制

    使用 Spring Security + JWT 实现无状态认证:

    java

    // SecurityConfig.java — 核心安全配置
    @Configuration
    @EnableWebSecurity
    @EnableMethodSecurity
    public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
    .csrf(AbstractHttpConfigurer::disable)
    .cors(cors -> cors.configurationSource(corsConfigurationSource()))
    .exceptionHandling(exception -> exception
    .authenticationEntryPoint(jwtAuthenticationEntryPoint))
    .authorizeHttpRequests(auth -> auth
    .requestMatchers("/auth/**", "/public/**").permitAll()
    .requestMatchers("/users/verification-code", "/users/verify-code",
    "/users/reset-password").permitAll()
    .requestMatchers("/admin/**").hasRole("ADMIN")
    .requestMatchers("/teacher/**").hasAnyRole("TEACHER", "ADMIN")
    .requestMatchers("/student/**")
    .hasAnyRole("STUDENT", "TEACHER", "ADMIN")
    .requestMatchers("/v3/api-docs/**", "/swagger-ui/**",
    "/swagger-ui.html").permitAll()
    .anyRequest().authenticated()
    )
    .sessionManagement(session -> session
    .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
    .authenticationProvider(authenticationProvider())
    .addFilterBefore(jwtAuthenticationFilter,
    UsernamePasswordAuthenticationFilter.class);
    return http.build();
    }
    }

    RBAC 角色设计:基于 ROLE_ADMIN、ROLE_TEACHER、ROLE_STUDENT 三种角色,通过 @PreAuthorize 注解实现方法级权限控制。

    • @PreAuthorize("hasAnyRole('TEACHER', 'ADMIN')") — 创建/编辑/删除作业
    • @PreAuthorize("hasRole('STUDENT')") — 提交作业
    • @PreAuthorize("hasRole('ADMIN')") — 用户管理、审批

    6.2 缓存策略

    项目同时使用了 Redis 和 Caffeine 本地缓存:

    • Redis:配置在 application.yml 中,使用 Lettuce 连接池(max-active: 20 / max-idle: 10 / min-idle: 5),用于分布式场景下的数据共享
    • Caffeine 本地缓存:最大 500 条目,30 分钟未访问过期,命中率目标 > 80%

    java

    // RedisConfig.java — 实际配置的是 Caffeine 本地缓存
    @Configuration
    @EnableCaching
    public class RedisConfig {

    @Bean
    public CacheManager cacheManager() {
    CaffeineCacheManager cacheManager = new CaffeineCacheManager();
    cacheManager.setCaffeine(Caffeine.newBuilder()
    .maximumSize(500)
    .expireAfterAccess(30, TimeUnit.MINUTES)
    .recordStats());
    return cacheManager;
    }
    }

    6.3 全局异常处理

    统一的异常处理与返回格式:

    java

    @RestControllerAdvice
    public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ApiResponse<?>> handleNotFound(ResourceNotFoundException ex) {
    return ResponseEntity.status(404)
    .body(ApiResponse.error(404, ex.getMessage()));
    }

    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<ApiResponse<?>> handleAccessDenied(AccessDeniedException ex) {
    return ResponseEntity.status(403)
    .body(ApiResponse.error(403, "权限不足"));
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse<?>> handleGeneral(Exception ex) {
    return ResponseEntity.status(500)
    .body(ApiResponse.error(500, "服务器内部错误"));
    }
    }

    统一响应格式:

    json

    // 成功
    { "code": 200, "message": "操作成功", "data": { … } }

    // 失败
    { "code": 400, "message": "错误信息", "data": null }

    6.4 前端 Axios 封装

    统一的请求/响应拦截器,自动注入 Token,Token 过期自动跳转登录:

    javascript

    // utils/request.js
    import axios from 'axios'
    import { ElMessage } from 'element-plus'
    import router from '@/router'

    const request = axios.create({
    baseURL: '/api',
    timeout: 10000
    })

    // 请求拦截器 — 注入 JWT Token
    request.interceptors.request.use(config => {
    const token = localStorage.getItem('token')
    if (token) {
    config.headers.Authorization = `Bearer ${token}`
    }
    return config
    })

    // 响应拦截器 — 统一错误处理
    request.interceptors.response.use(
    response => response.data,
    error => {
    if (error.response?.status === 401) {
    localStorage.removeItem('token')
    router.push('/login')
    }
    ElMessage.error(error.response?.data?.message || '请求失败')
    return Promise.reject(error)
    }
    )

    export default request

    6.5 前端路由权限守卫

    javascript

    // router/index.js
    router.beforeEach((to, from, next) => {
    NProgress.start()

    const userStore = useUserStore()
    const token = userStore.token
    const userRole = userStore.role

    if (to.meta.requiresAuth && !token) {
    next({ name: 'Login', query: { redirect: to.fullPath } })
    NProgress.done()
    } else if (to.meta.requiresAuth && to.meta.roles &&
    !to.meta.roles.includes(userRole)) {
    ElMessage.error('您没有权限访问该页面')
    next({ name: 'Dashboard' })
    NProgress.done()
    } else {
    next()
    }
    })

    6.6 前端 Pinia 状态管理

    使用 Pinia 管理用户登录状态,Token 和用户信息持久化到 Cookie(js-cookie):

    javascript

    // store/user.js
    export const useUserStore = defineStore('user', () => {
    const token = ref(Cookies.get('token') || '')
    const user = ref(/* 从 Cookie 恢复 */)
    const role = ref(userInfo?.role || '')

    const loginAction = async (loginForm) => {
    const res = await login(loginForm)
    token.value = res.data.token
    user.value = { …res.data, role: res.data.role?.toUpperCase() }
    Cookies.set('token', res.data.token)
    Cookies.set('userInfo', JSON.stringify(userData))
    return res
    }

    const logoutAction = async () => {
    token.value = ''
    user.value = null
    Cookies.remove('token')
    Cookies.remove('userInfo')
    }

    return { token, user, role, loginAction, logoutAction, … }
    })

    6.7 作业查重功能 🔍

    查重是本系统的一大亮点,旨在帮助教师快速识别学生作业中的抄袭行为。核心原理是基于文本相似度的两两比对算法,计算同一作业下不同学生提交内容的相似度分数。

    6.7.1 实现原理

    查重流程分为三个步骤:

    第一步:提取所有提交内容

    java

    // SubmissionService.java — checkPlagiarism 方法
    public List<Submission> checkPlagiarism(Long homeworkId) {
    // 1. 获取该作业的所有提交
    List<Submission> submissions = submissionRepository.findByHomeworkId(homeworkId);

    // 2. 为每个提交提取纯文本内容(去除HTML标签、标点符号等干扰)
    for (Submission sub : submissions) {
    String plainText = extractPlainText(sub.getContent());
    sub.setPlainText(plainText);
    }

    // 3. 两两比对计算相似度
    for (int i = 0; i < submissions.size(); i++) {
    for (int j = i + 1; j < submissions.size(); j++) {
    double similarity = calculateSimilarity(
    submissions.get(i).getPlainText(),
    submissions.get(j).getPlainText()
    );
    // 取该学生与其他所有学生比较的最高相似度
    submissions.get(i).setSimilarityScore(
    Math.max(submissions.get(i).getSimilarityScore(), similarity)
    );
    submissions.get(j).setSimilarityScore(
    Math.max(submissions.get(j).getSimilarityScore(), similarity)
    );
    }
    }

    // 4. 保存相似度结果到数据库
    submissionRepository.saveAll(submissions);

    // 5. 按相似度降序排列返回
    submissions.sort((a, b) ->
    Double.compare(b.getSimilarityScore(), a.getSimilarityScore())
    );
    return submissions;
    }

    第二步:文本预处理

    在计算相似度前,需要对提交内容进行清洗,去除无关信息:

    java

    private String extractPlainText(String content) {
    if (content == null) return "";
    // 去除 HTML 标签
    String text = content.replaceAll("<[^>]+>", "");
    // 去除标点符号和多余空白
    text = text.replaceAll("[\\\\p{P}\\\\p{S}]", "");
    // 统一转小写
    text = text.toLowerCase().trim();
    // 去除多余空格
    text = text.replaceAll("\\\\s+", " ");
    return text;
    }

    第三步:相似度计算

    采用基于词频的余弦相似度算法,这是文本查重领域的经典方法:

    java

    private double calculateSimilarity(String text1, String text2) {
    if (text1.isEmpty() || text2.isEmpty()) return 0.0;

    // 分词
    String[] words1 = text1.split(" ");
    String[] words2 = text2.split(" ");

    // 构建词频向量
    Map<String, Integer> freq1 = buildWordFrequency(words1);
    Map<String, Integer> freq2 = buildWordFrequency(words2);

    // 获取所有不重复的词语
    Set<String> allWords = new HashSet<>();
    allWords.addAll(freq1.keySet());
    allWords.addAll(freq2.keySet());

    // 计算余弦相似度
    double dotProduct = 0.0;
    double norm1 = 0.0;
    double norm2 = 0.0;

    for (String word : allWords) {
    int count1 = freq1.getOrDefault(word, 0);
    int count2 = freq2.getOrDefault(word, 0);
    dotProduct += count1 * count2;
    norm1 += count1 * count1;
    norm2 += count2 * count2;
    }

    if (norm1 == 0 || norm2 == 0) return 0.0;
    return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
    }

    private Map<String, Integer> buildWordFrequency(String[] words) {
    Map<String, Integer> freq = new HashMap<>();
    for (String word : words) {
    freq.merge(word, 1, Integer::sum);
    }
    return freq;
    }

    6.7.2 查重 API 接口

    教师通过一个接口即可完成查重操作:

    POST /api/submissions/homework/{homeworkId}/plagiarism
    权限:TEACHER / ADMIN

    返回结果按 similarityScore 降序排列,相似度越高的提交排在越前面,方便教师快速定位疑似抄袭的作业。

    6.7.3查重结果呈现

    查重完成后,每个提交记录的 similarity_score 字段会被更新,前端在批改列表中可以直观地看到每份作业的相似度分数。通常设定以下阈值:

    相似度区间判定结果颜色标识
    0% ~ 30% 正常 🟢 绿色
    30% ~ 60% 可疑 🟡 黄色
    60% ~ 100% 高度疑似抄袭 🔴 红色

    💡 本系统的查重基于纯文本内容进行比对。如果作业涉及代码,建议结合专业代码查重工具(如 MOSS、JPlag)使用。

    6.8 文件上传与下载

    • 上传:支持多格式文件(PDF/Word/ZIP/RAR/图片/文本),100MB 上限,自动校验文件类型和大小
    • 下载:自动识别文件 MIME 类型,正确设置 Content-Disposition 头,保留原始文件名和后缀
    • 存储:文件存储在 backend/uploads/submissions/ 目录下,以 时间戳_原始文件名 命名

    七、API 接口一览(完整 40+ 接口)

    7.1 认证模块 — 8 个接口

    方法路径说明权限
    POST /api/auth/login 用户登录,返回 JWT + Refresh Token 匿名
    POST /api/auth/register 用户注册 匿名
    POST /api/auth/refresh 刷新令牌 匿名
    POST /api/auth/logout 退出登录 认证
    POST /api/auth/forgot-password/send-code 发送验证码(邮箱/手机) 匿名
    POST /api/auth/forgot-password/verify-code 验证验证码 匿名
    POST /api/auth/forgot-password/reset 重置密码 匿名
    POST /api/auth/check-username 检查用户名是否存在 匿名
    POST /api/auth/get-user-contacts 获取用户联系方式(脱敏) 匿名

    7.2 用户模块 — 9 个接口

    方法路径说明权限
    GET /api/users/me 获取当前用户信息 认证
    GET /api/users/{id} 获取指定用户 认证
    GET /api/users 获取所有用户(支持角色筛选) ADMIN
    PUT /api/users/{id} 更新用户信息 认证
    DELETE /api/users/{id} 删除用户 ADMIN
    PUT /api/users/change-password 修改密码 认证
    POST /api/users/verification-code 生成验证码 匿名
    POST /api/users/verify-code 校验验证码 匿名
    POST /api/users/reset-password 通过验证码重置密码 匿名

    7.3 作业模块 — 12 个接口

    方法路径说明权限
    POST /api/homework 创建作业(含学生分配) TEACHER/ADMIN
    GET /api/homework/{id} 获取作业详情(含教师名) 认证
    GET /api/homework/teacher/all 教师作业列表(支持课程/状态筛选) TEACHER/ADMIN
    GET /api/homework/student/all 学生作业列表(含提交状态) STUDENT
    GET /api/homework 获取所有作业 ADMIN
    GET /api/homework/status/{status} 按状态查询作业 认证
    PUT /api/homework/{id} 更新作业 TEACHER/ADMIN
    DELETE /api/homework/{id} 删除作业 TEACHER/ADMIN
    GET /api/homework/{id}/students 获取作业分配的学生 ID 列表 TEACHER/ADMIN
    PUT /api/homework/{id}/students 更新作业分配的学生列表 TEACHER/ADMIN
    GET /api/homework/teacher/with-submissions 获取有学生提交的作业 TEACHER/ADMIN
    GET /api/homework/expired 获取过期作业 TEACHER/ADMIN

    7.4 提交模块 — 12 个接口

    方法路径说明权限
    POST /api/submissions 提交作业(含文件上传) STUDENT
    GET /api/submissions/{id} 获取提交详情 认证
    GET /api/submissions/student/all 获取学生的所有提交 STUDENT
    GET /api/submissions/homework/{homeworkId} 获取作业的所有提交(含学生名) TEACHER/ADMIN
    GET /api/submissions/homework/{homeworkId}/student 学生获取自己在某作业的提交 STUDENT
    GET /api/submissions/teacher/all 教师查看所有提交 TEACHER/ADMIN
    PUT /api/submissions/{id}/grade 批改作业(评分+评语) TEACHER/ADMIN
    PUT /api/submissions/{id} 更新提交(含文件替换/删除) STUDENT
    DELETE /api/submissions/{id} 删除提交 STUDENT
    POST /api/submissions/homework/{homeworkId}/plagiarism 作业查重 TEACHER/ADMIN
    GET /api/submissions/attachment/{id} 下载附件 认证
    GET /api/submissions/homework/{homeworkId}/statistics 作业成绩统计 TEACHER/ADMIN

    7.5 消息模块 — 5 个接口

    方法路径说明权限
    GET /api/messages 获取消息列表 认证
    GET /api/messages/{id} 获取消息详情 认证
    GET /api/messages/unread 获取未读消息 认证
    PUT /api/messages/{id}/read 标记为已读 认证
    DELETE /api/messages/{id} 删除消息 认证

    7.6 审批模块 — 7 个接口

    方法路径说明权限
    POST /api/profile-requests 创建资料修改申请 认证
    GET /api/profile-requests/my 获取自己的申请记录 认证
    GET /api/profile-requests 获取所有申请 ADMIN
    GET /api/profile-requests/pending 获取待审批申请 ADMIN
    GET /api/profile-requests/{id} 获取申请详情 认证
    PUT /api/profile-requests/{id}/approve 批准申请 ADMIN
    PUT /api/profile-requests/{id}/reject 拒绝申请 ADMIN

    完整的 40+ 个 API 接口可通过 Swagger 查看: 启动后端后访问 http://localhost:8080/api/swagger-ui.html


    八、快速启动

    💡 环境配置请参考 二、环境配置,确保 JDK、Maven、Node.js、MySQL、Redis 均已安装。

    8.1 数据库初始化

    bash

    # 登录 MySQL
    mysql -u root -p

    # 创建数据库
    CREATE DATABASE IF NOT EXISTS online_homework_system
    DEFAULT CHARACTER SET utf8mb4
    DEFAULT COLLATE utf8mb4_general_ci;

    exit;

    导入表结构和测试数据:

    bash

    # 推荐导入完整版(含测试账号和示例数据)
    mysql -u root -p online_homework_system < online_homework_system_complete.sql

    项目提供了两个 SQL 文件:

    • online_homework_system.sql — 仅表结构
    • online_homework_system_complete.sql — 表结构 + 测试数据(推荐)

    导入后包含:4 个测试用户、3 个示例作业、2 条示例提交、3 条示例消息。

    8.2 配置后端

    修改 backend/src/main/resources/application.yml 中的数据库和 Redis 连接信息:

    yaml

    spring:
    datasource:
    url: jdbc:mysql://localhost:3306/online_homework_system?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root # 改为你的 MySQL 用户名
    password: 123456 # 改为你的 MySQL 密码
    data:
    redis:
    host: localhost # Redis 地址
    port: 6379 # Redis 端口
    password: # Redis 密码(如无则留空)

    jwt:
    secret: your-default-jwt-secret-key-change-in-production
    expiration: 86400000 # Token 有效期(24小时,毫秒)
    refresh-expiration: 604800000 # Refresh Token 有效期(7天)

    ⚠️ 生产环境请务必修改 jwt.secret 为自定义密钥!

    8.3 启动后端

    bash

    cd backend
    mvn clean install -DskipTests
    mvn spring-boot:run

    或使用 IDE 启动:

    • IntelliJ IDEA:打开 backend 目录 → 找到 OnlineHomeworkSystemApplication.java → 右键 Run
    • VS Code:安装 Extension Pack for Java → 打开 backend → 按 F5 启动

    验证:访问 http://localhost:8080/api/swagger-ui.html,看到 Swagger UI 页面即启动成功。

    8.4 启动前端

    bash

    cd frontend
    npm install
    npm run dev

    Vite 配置说明(vite.config.js 已配置好):

    • 开发服务器端口:3000
    • API 代理:/api → http://localhost:8080
    • 代码分割:Element Plus、Vue 生态、ECharts 独立打包
    • 自动导入:Element Plus 组件和 Vue API 按需自动导入

    javascript

    // vite.config.js 关键配置
    server: {
    port: 3000,
    proxy: {
    '/api': {
    target: 'http://localhost:8080',
    changeOrigin: true,
    },
    },
    },

    启动后访问 http://localhost:3000

    8.5 测试账号

    角色用户名密码
    管理员 admin admin123
    教师 teacher1 teacher123
    学生 student1 student123
    学生 student2 student123

    8.6 常见问题排查

    Q1:后端启动报 "Access denied for user"

    原因:MySQL 用户名或密码不正确。 解决:检查 application.yml 中 spring.datasource.username 和 password 配置。

    Q2:后端启动报 "Unknown database"

    原因:未创建数据库。 解决:执行 CREATE DATABASE online_homework_system DEFAULT CHARACTER SET utf8mb4;

    Q3:Redis 连接失败

    原因:Redis 服务未启动或配置错误。 解决:检查 Redis 服务是否运行,确认 application.yml 中 host、port、password 正确。

    Q4:npm install 失败

    原因:网络问题或 npm 版本问题。 解决:

    bash

    npm cache clean –force
    npm install –registry=https://registry.npmmirror.com

    Q5:前端页面空白 / API 请求 404

    原因:后端未启动或代理配置问题。 解决:确保后端已启动,通过 npm run dev 启动前端(不要直接打开 index.html)。

    Q6:端口被占用

    原因:8080 或 3000 端口已被占用。 解决:

    bash

    netstat -ano | findstr :8080
    # 或修改 application.yml 中的 server.port


    九、项目亮点总结

    9.1 后端亮点

  • 完整的安全体系:Spring Security + JWT 无状态认证 + BCrypt 密码加密 + RBAC 角色权限 + CORS 跨域防护
  • 双层缓存架构:Redis(分布式)+ Caffeine(本地缓存),兼顾性能与可扩展性
  • 完善的异常处理:@RestControllerAdvice 全局异常捕获 + 统一 ApiResponse 响应格式
  • RESTful API 设计:规范的路由命名、HTTP 方法语义化、统一的请求响应格式
  • Swagger 文档:SpringDoc OpenAPI 自动生成,支持在线调试
  • 文件管理:支持多格式上传、Content-Type 自动识别下载、文件大小校验
  • 作业查重:内置文本相似度检测
  • 成绩统计:自动计算平均分/最高分/最低分/提交率/批改率
  • 9.2 前端亮点

  • 现代技术栈:Vue 3 Composition API + Pinia + Vite 6
  • 组件按需引入:unplugin-vue-components + unplugin-auto-import,无需手动 import
  • 路由懒加载:所有页面组件动态 import,首屏加载快
  • 代码分割:Element Plus、Vue 生态、ECharts 分别独立 chunk
  • 请求拦截器:自动注入 Token、401 自动跳转登录、统一错误提示
  • 路由权限守卫:结合 NProgress 进度条,页面切换流畅
  • 响应式布局:基于 Element Plus 栅格系统,适配桌面和移动端
  • 状态持久化:使用 js-cookie 持久化 Token 和用户信息
  • 9.3 安全特性

    安全措施实现方式
    认证安全 JWT 无状态认证,Token 24h / Refresh Token 7d
    密码安全 BCrypt 加密存储
    权限控制 RBAC 角色 + @PreAuthorize 方法级注解
    SQL 注入防护 JPA/MyBatis Plus 参数化查询
    XSS 防护 前端 Element Plus 自动转义
    CORS 防护 后端白名单配置 + 前端 Vite Proxy
    CSRF 防护 无状态 JWT,禁用 Session

    十、待完善方向

    • 📌 富文本编辑器(作业描述支持 Markdown/富文本)
    • 📌 文件断点续传(大文件上传优化)
    • 📌 Excel 批量导入导出成绩(Apache POI 已引入,待实现页面)
    • 📌 邮件通知服务(截止提醒、成绩通知)
    • 📌 单元测试覆盖率提升(目标 80%+)
    • 📌 Docker 容器化部署
    • 📌 WebSocket 实时消息推送

    十一、写在最后

    这个项目从零搭建到功能完成,花了大约两个月的时间。作为毕设项目,它基本覆盖了企业级开发中的核心知识点:Spring Boot 3、Spring Security、JWT、Redis、Vue 3、Element Plus 等。

    项目代码注释详细,每个类和方法都标注了功能说明,适合初学者学习和参考。

    如果这个项目对你有所帮助,欢迎给个 Star ⭐,也欢迎提 Issue 交流!

    🔗 GitHub:GitHub – heyige/online-homework-system: 基于SpringBoot的在线作业管理系统 – Online Homework Management System · GitHub


    附录:角色页面权限矩阵

    页面路径AdminTeacherStudent说明
    /dashboard 控制台首页
    /profile 个人资料
    /change-password 修改密码
    /homework 作业列表
    /homework/create 创建作业
    /homework/:id/edit ✅(仅自己) 编辑作业
    /submission 提交作业
    /grade 批改列表
    /grade/:submissionId 批改详情
    /statistics 成绩统计
    /messages 消息中心
    /users 用户管理
    /profile-requests ✅(审核) 申请审批

    本文发布于 CSDN,作者:一孤程

    赞(0)
    未经允许不得转载:171主机测评 » SpringBoot + Vue3 在线作业管理系统【附源码+数据库+40接口+ER图+部署+一键启动】
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址