
简介毕业生实习管理系统是一套面向高校、企业和学生的全流程实习管理源码包覆盖学生申请、教师审核、企业发布岗位、管理员统计等核心业务适合Java Web方向学习者做毕业设计或课程项目参考。压缩包共909个文件主要包括java源文件、class编译文件、html页面、css样式、js脚本、png图片及sql数据库脚本等整体仅1.61MB结构以管理员、用户、商品等控制模块清晰分层便于本地部署和二次开发。目前已有79人学习下载。资源附带数据库脚本和配置文件可快速搭建运行环境内容预览中可看到角色管理、采购单、销售单、退货单、报溢单等企业级后台功能适合研究权限管理、业务流设计和SSH/SSM框架整合的开发者参考使用。1. 毕业生实习管理系统为什么要以 zip 形式交付很多人拿到“毕业生实习管理系统.zip”的第一反应是解压找 exe真正打开后却是一堆 .java、.vue、.sql 和 .yml。这不是普通安装包而是一个前后端分离的校企实习管理项目学生提交周报、导师审核、院系导出成绩全都跑在同一个 Spring Boot 服务上。我见过太多人在这一步卡住原因不是代码缺文件而是不清楚 zip 包在本地部署时要解决 Java 版本、MySQL 初始化、前端产物放哪三个问题。这篇文章沿着一线部署和二次开发的顺序把这个压缩包里的管理系统从数据模型讲到打包回 zip再把最容易翻车的报错一次性说透适合正在接手这类毕设源码或想自建实习管理流程的开发者。2. 系统边界与核心数据模型先理清实习管理要管什么2.1 角色与权限边界五类账号的可见范围毕业生实习管理系统不是简单的“学生填表、老师查看”。它至少要覆盖校内外两条审核链学生提交实习信息后企业导师要反馈出勤校内导师要审核周报并给成绩院系管理员要导出全年级的实习汇总。如果权限边界一开始没划清后面所有接口都可能出现越权查询。这五个角色在各 zip 包里的命名可能不同但权限逻辑基本一致角色核心操作数据可见范围学生填写实习单位、提交周报、查看成绩本人记录企业导师填写学生出勤、提交企业评价被分配的实习生校内导师审核周报、评分、退回修改名下学生院系管理员汇总查询、导出 Excel本学院数据系统管理员用户分配、清空缓存、修复数据全部数据权限判断建议放在 Spring Security 的注解层比如在 Controller 方法上写PreAuthorize(hasRole(TEACHER))而不是在每个接口里用 if 判断登录用户角色。后者写起来很快但一旦出现五六个角色漏判一个分支就会把学院数据暴露给普通学生。在真正的 zip 源码里角色往往不写在前端路由而是通过后端返回的roles数组动态生成菜单。这样做的好处是学生端即使手动修改浏览器地址也访问不到导师接口因为后端会在过滤器阶段拦截未授权请求。二次开发时新增一个“班主任”角色不要直接复制学生角色代码先想清楚它是要看全班还是只看自己所带班级再在查询条件里加一个部门编码字段。2.2 数据库表结构实习信息、周报、审核记录的落库方式数据模型是整个 zip 项目里最值得先看的部分。实习管理的主线是“一份实习对应多份周报每份周报有多个审核节点”因此至少要拆出三张表学生实习表、周报表、审核日志表。打开常见的1_schema.sql会看到类似下面的结构CREATE TABLE student_internship ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL COMMENT 学生账号ID, company_name VARCHAR(100) NOT NULL COMMENT 实习单位名称, position_name VARCHAR(50) COMMENT 岗位名称, start_date DATE COMMENT 实习开始日期, end_date DATE COMMENT 实习结束日期, status TINYINT DEFAULT 0 COMMENT 0:实习中 1:已结束, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_user (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE weekly_report ( id BIGINT AUTO_INCREMENT PRIMARY KEY, internship_id BIGINT NOT NULL COMMENT 关联 student_internship.id, week_no INT NOT NULL COMMENT 第几周, content TEXT NOT NULL COMMENT 周报正文, attachment_path VARCHAR(255) COMMENT 附件相对路径, audit_status TINYINT DEFAULT 0 COMMENT 0:待审核 1:通过 2:退回, audit_comment VARCHAR(200) COMMENT 导师退回意见, submit_time DATETIME, audit_time DATETIME, INDEX idx_internship (internship_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里有两个容易被忽略的细节。第一状态字段用TINYINT而不是字符串比如audit_status只有 0、1、2 三种取值前端格式化时在 switch-case 里映射成“待审核”“已通过”“已退回”即可。第二weekly_report必须建idx_internship索引因为“按实习查周报”是最频繁的查询路径没有索引时数据过万就会明显变慢。如果拿到的 SQL 里没有这两句索引我会在部署时手动补上。在使用这套表时还要注意附件路径不要存完整 URL只存文件名或相对路径比如upload/2025/04/report_1024.docx。这样 zip 包换服务器后不用改数据库只要把整个 upload 目录一起迁移就行。如果你拿到的表结构里只有user_id而没有internship_id说明这个版本的周报是直接挂在学生账号下的。这种设计能少写一条关联但会带来一个麻烦一个学生换了两家公司实习两段经历会混在一起统计实习次数时还要从时间上猜。我建议在升级时补上 student_internship 表让 weekly_report 统一通过 internship_id 关联。2.3 zip 包内的目录约定配置、脚本、前后端产物放哪二次开发之前先花五分钟确认 zip 包目录结构可以避免把sql/当成后端资源目录、把dist/当作无用文件的误判。常见的布局是毕业生实习管理系统/ ├── backend/ # Spring Boot 后端源码 │ ├── src/main/java │ ├── src/main/resources │ └── pom.xml ├── frontend/ # Vue 前端源码 │ ├── src │ ├── vite.config.js │ └── package.json ├── sql/ │ ├── 1_schema.sql │ └── 2_data.sql ├── dist/ # 已构建的前端静态文件 ├── release/ # 部署目录 │ ├── internship.jar │ └── static/ └── 部署说明.md如果 zip 里带release/static那么后端通常已经把前端页面挂在同一个端口上如果没有release/就要在打包阶段自己合并。这里有个极易翻车的点Spring Boot 默认优先读取classpath:/static/前端构建产物放进去后必须确认 jar 里没有残留旧版本的index.html否则打开页面看到的还是上一版。我一般会在构建前执行mvn clean把 target 目录整个清掉。3. 用 Spring Boot Vue 搭出毕业生实习管理系统的最小后端与前端3.1 后端关键依赖与 application.yml 参数拿到一个实习管理系统源码先看pom.xml就能判断它是不是同类项目里最常见的 Spring Boot MyBatis-Plus 组合。用 MyBatis-Plus 而不是 MyBatis 或 JPA原因很实际周报列表、学生列表这类分页查询JPA 要写 Specification原生 MyBatis 要写 XML而 MyBatis-Plus 直接调用selectPage就够了适合这个规模的项目。parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency /dependencies版本选2.7.18而不是 Spring Boot 3.x是因为很多拿来部署的机器装的是 JDK 8。Spring Boot 3 强制 JDK 17如果 zip 包里的pom.xml写的 spring-boot 3而部署文档又说 JDK 8那这个包很可能被改过版本需要直接对照 Maven 仓库补齐依赖而不是硬着头皮启动。application.yml是部署时最常改动的地方重点看四个参数配置项示例值作用server.port8080后端与前端代理的约定端口spring.datasource.urljdbc:mysql://localhost:3306/internship_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai必须带 utf8 和时区spring.datasource.usernameroot数据库账号spring.servlet.multipart.max-file-size20MB周报附件大小上限server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/internship_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 servlet: multipart: max-file-size: 20MB max-request-size: 50MB mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: autoserverTimezoneAsia/Shanghai不是可选项少了这个参数MySQL 8 在连接时会报时区错误。调试阶段把log-impl设为StdOutImpl能在控制台直接看到 MyBatis 生成的 SQL查数据不对时不用猜。正式部署时再把这行去掉避免日志文件快速增长。3.2 实习周报提交接口的最小 Controller 实现后端最核心的接口不是登录而是周报提交和列表查询。因为学生可能一周会修改多次而导师审核只看最新状态所以提交接口只做插入和覆盖不做复杂的状态机。下面是一个能直接跑的 Controller 示例RestController RequestMapping(/api/report) public class WeeklyReportController { Resource private WeeklyReportMapper weeklyReportMapper; PostMapping(/submit) public Result? submit(RequestBody WeeklyReport report) { if (report.getInternshipId() null || report.getContent() null) { return Result.error(实习ID和内容不能为空); } report.setAuditStatus(0); report.setSubmitTime(new Date()); weeklyReportMapper.insert(report); return Result.success(周报提交成功); } GetMapping(/list) public Result? list(RequestParam Long internshipId, RequestParam(defaultValue 1) int page, RequestParam(defaultValue 10) int size) { PageWeeklyReport p new Page(page, size); LambdaQueryWrapperWeeklyReport qw new LambdaQueryWrapper(); qw.eq(WeeklyReport::getInternshipId, internshipId) .orderByDesc(WeeklyReport::getWeekNo); return Result.success(weeklyReportMapper.selectPage(p, qw)); } }submit方法先做非空校验再强制把auditStatus重置为 0这样被退回修改后再次提交导师端才能看到“待审核”状态。list方法用LambdaQueryWrapper代替手写 SQLeq指定查询条件orderByDesc(WeeklyReport::getWeekNo)让最新周报排在最前。注意page和size都加了默认值前端漏传参数时后端不会直接 500。这里有一个常见的二次开发改动需求学生撤回周报。如果直接在submit里加删除逻辑会把导师已审核的通过记录一起删掉正确的做法是新增一个recall接口只把audit_status改成“退回”不物理删除数据。接口统一返回 Result 对象而不是原始 Map也是这个项目能长期维护的关键。Result 里固定放 code、msg、data 三个字段前端拦截器只认 code。有人喜欢让接口直接返回数据、出错时抛异常一旦前端和后端约定不一致控制台就会不断出现 200 状态码但业务报错的诡异现象。3.3 前端请求封装与跨域处理Vue 前端和后端联调时最大的问题不是接口写法而是跨域。很多从 zip 解压出来的前端代码会把baseURL写成完整的http://localhost:8080这在开发环境能跑但部署到线上就变成后端地址写死。正确做法是用相对路径/api交给开发服务器或 Nginx 转发。import axios from axios import { message } from ant-design-vue const service axios.create({ baseURL: /api, timeout: 10000 }) service.interceptors.response.use( res { if (res.data.code ! 200) { message.error(res.data.msg) return Promise.reject(res.data) } return res.data }, err { message.error(err.message) return Promise.reject(err) } ) export function submitReport(data) { return service.post(/report/submit, data) }把统一请求封装放到src/api/目录里页面组件只需要调用submitReport(reportData)不需要关心 token 怎么塞进 header。响应拦截器里判断code ! 200后直接弹错误提示省得每个页面写一遍 try-catch。开发环境的跨域要在 Vite 配置里解决而不是开浏览器插件。下面这段vite.config.js把/api前缀的请求代理到 8080 端口export default defineConfig({ server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } })这样前端页面里的请求地址始终是/api/report/list后端接口不需要在 Controller 里写CrossOrigin。如果后端也开了CrossOrigin两边就可能会因为允许的来源不同而出现“看起来没跨域实际还是失败”的问题建议只保留一处。3.4 本地运行的最小命令集把 zip 解压后按顺序执行四组命令就能在开发环境把整套系统跑起来。先确保 MySQL 已启动且建好数据库再启动后端最后启动前端。# 1. 创建数据库如果还没执行过 SQL mysql -uroot -p -e CREATE DATABASE internship_db DEFAULT CHARACTER SET utf8mb4; # 2. 后端 mvn spring-boot:run # 3. 前端依赖安装 cd frontend npm install # 4. 前端开发服务器 npm run devnpm install会比较耗时如果项目里有package-lock.json说明依赖版本锁定过不要随便删如果 zip 里带了node_modules目录直接删掉再安装因为压缩包里的可能是别人机器上生成的二进制文件跨平台后会出现各种奇怪报错。mvn spring-boot:run启动后看到Started Application日志再操作浏览器否则第一次请求会打到尚未准备好的服务上。4. 打包、压缩与部署让毕业生实习管理系统 zip 包在其他机器跑起来4.1 Maven 打包与前端构建产物合并开发完成后需要把前后端合并成一个可执行 jar再连同数据库脚本压成新的 zip。Spring Boot 的标准做法是先把前端构建产物放进后端src/main/resources/static由spring-boot-maven-plugin打成单个 jar。这样部署时只需一个 jar 和一个 sql 脚本最省心。先构建前端cd frontend npm run build构建完成后的dist/目录包含index.html、assets/等文件。接下来把dist里的内容复制到后端静态资源目录rm -rf ../backend/src/main/resources/static/* cp -r dist/* ../backend/src/main/resources/static/复制前必须清空旧的 static 目录只复制不清理时旧版本的 JS 文件会和新版共存浏览器按文件名哈希加载不会出错但 zip 包体积会虚胖。随后执行 Maven 打包cd ../backend mvn clean package -DskipTests-DskipTests跳过测试用例避免测试环境连不到数据库导致打包中断clean的作用是清除上一次构建的 target 目录这一步正好呼应前文说的“static 残留问题”。4.2 用 7-Zip 生成部署 zip 的正确参数在 Windows 上最常用的是 7-Zip。有人习惯右键“添加到压缩文件”但这个操作会把日志文件和 node_modules 一并打进去导致交付 zip 体积从 60MB 膨胀到 400MB。我一般用命令行指定排除规则7z a -tzip 毕业生实习管理系统.zip release/ sql/ 部署说明.md -mx5 -xr!logs -xr!node_modules -xr!.git参数说明a表示添加文件到压缩包-tzip指定压缩格式-mx5是 7-Zip 的压缩级别数字越大压得越慢、体积越小普通项目取 5 即可。-xr!logs和-xr!node_modules是递归排除规则可以连续写多个。.git目录也建议排除否则别人拿到压缩包后会看到你的提交历史而且仓库里的.git体积往往不小。注意压缩时路径不要包含盘符。在项目父目录下执行命令得到 zip 后打开第一层应该直接是release/、sql/这样的目录名。如果打开 zip 看到的是D:/project/release/说明执行命令时所在位置不对解压的人会在目录结构上浪费大量时间。压缩完还要验证包完整性避免出现“导入资源包失败 caused by: invalid zip archive: could not find eocd”这类报错。eocd 是 ZIP 文件中央目录的结束标记压缩包在传输中被截断时最容易丢失。执行7z t 毕业生实习管理系统.zip会测试压缩包是否能正常读取。如果资源站为了绕过上传大小限制把包拆成了 z01 分卷要先把全部分卷和主 zip 放在同一目录再解压缺一个分卷就会提示文件损坏。打包内容用途是否可排除release/internship.jar后端可执行包否sql/1_schema.sql建表脚本否sql/2_data.sql初始化管理员账号否部署说明.md环境要求与命令否logs/运行时日志排除.git版本历史排除node_modules前端依赖排除4.3 数据库初始化脚本的一次性执行服务器上第一次部署时数据库初始化最容易出错。拿到 zip 里的sql/1_schema.sql后不要用图形化工具直接“运行整个文件”而是先看脚本开头有没有CREATE DATABASE和USE语句。如果没有得手动建库再指定库名执行mysql -uroot -p -e CREATE DATABASE internship_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p internship_db sql/1_schema.sql mysql -uroot -p internship_db sql/2_data.sql两个脚本都要指定internship_db否则会出现“No database selected”错误。utf8mb4_general_ci是兼容性较好的排序规则能存 emoji也和 MySQL 5.7、8.0 都兼容。2_data.sql里如果有管理员账号的插入语句密码字段一般是 BCrypt 密文不要手动改成明文否则登录时 Spring Security 比对会失败。4.4 从 GitHub 下载的 zip 项目与 git 关联失败时的修复很多人拿到源码后习惯复制下载链接而不是git clone这样下载到的是 GitHub 打包好的 zip里面没有.git目录。想把它关联到自己的远程仓库时最典型的报错是“failed to push some refs”或“变基到远程仓库失败”。原因很简单本地仓库和远程仓库有完全不一样的历史。这时候不要直接 rebase先用--allow-unrelated-histories合并即可unzip 毕业生实习管理系统.zip cd 毕业生实习管理系统 git init git add . git commit -m init from zip git branch -M main git remote add origin gitgithub.com:user/repo.git git pull origin main --allow-unrelated-histories git push -u origin main这里最后两步对应的是“zip项目与git项目关联”和“变基到远程仓库失败”。--allow-unrelated-histories允许合并两个没有共同祖先的提交比如远程仓库里有 README本地仓库是纯源码。合并且冲突解决后再执行 push。注意要先把本地文件提交成一次干净的基线不要急着 push否则后面的回溯会很痛苦。从 GitHub 下载 zip 还有一个坏处提交历史被丢掉后期看到某段代码想用 git blame 找回作者和原因时会很困难。因此如果项目会长期维护先把初版记录下来比打一堆临时补丁更值得。5. 毕业生实习管理系统接到真实环境前的检查和故障排查5.1 启动日志中的关键报错定位部署后不要直接访问页面先看启动日志。下面几类报错几乎覆盖了大部分毕业生实习管理系统启动失败原因报错关键片段原因处理方式Access denied for user rootlocalhost数据库密码错误检查 application.yml 里的 datasource.passwordPort 8080 was already in use端口被占用lsof -i:8080 找进程并结束或改 server.portTable internship_db.weekly_report doesnt existSQL 没执行确认是用 internship_db 执行 1_schema.sqlFailed to bind properties under spring.datasourceyml 缩进错误用两个空格替换 Tab查找端口占用和滚动查看日志用这两条命令lsof -i:8080 tail -f logs/spring.log如果application.yml里配置了logging.file.nameSpring Boot 会把日志输出到文件没配置时只输出控制台用nohup java -jar internship.jar app.log 21 启动时别忘记加21否则报错会被丢弃。5.2 静态资源与前端白屏的处理有一类问题在启动日志里完全看不到就是后端正常启动但访问页面显示空白。这一般是前端构建产物放错了位置。Spring Boot 查找静态资源的顺序是classpath:/static/、classpath:/public/、classpath:/resources/。如果index.html被复制到了src/main/resources/templates/页面不会自动渲染直接白屏。检查 jar 里的静态文件也可以不用解压jar tf release/internship.jar | grep index.html输出结果里应看到BOOT-INF/classes/static/index.html如果看到templates/就要把 index.html 移到 static 目录。这个命令在排查“本地 dev 正常jar 部署后 404”时非常实用。5.3 给实习管理系统加滚动日志的小技巧最后留一个能立刻用上的技巧。给src/main/resources/logback-spring.xml加上按天滚动和自动删除就不会让日志把磁盘打满appender nameROLLING classch.qos.logback.core.rolling.RollingFileAppender filelogs/internship.log/file rollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy fileNamePatternlogs/internship.%d{yyyy-MM-dd}.log/fileNamePattern maxHistory7/maxHistory /rollingPolicy /appendermaxHistory7表示只保留最近 7 天日志配合启动时--spring.profiles.activeprod使用还能在配置里按环境切换日志级别。排查问题时用grep ERROR logs/internship.log | tail -50截取最近 50 条异常再按日志里的时间戳去logs/internship.2025-xx-xx.log看完整堆栈。本文还有配套的精品资源点击获取