最近几年带过不少计算机专业的毕业设计发现一个很有意思的现象很多同学在选题和需求构思阶段花费的时间远远超过了实际编码的时间。他们往往卡在“我要做一个什么系统”这个问题上反复纠结迟迟无法动手。最后要么选一个网上泛滥的“图书管理系统”要么硬着头皮写一个自己都说不清楚需求的应用导致整个毕设过程痛苦且成果单薄。如果你也正为此发愁那么今天讨论的这个“校企实习管理系统”或许能给你提供一个全新的思路。它不是一个让你照抄的模板而是一个从真实业务场景出发帮你快速构建完整、合理、有深度的毕业设计项目的实战指南。它的核心价值在于你不用再凭空“构思”需求而是基于一个成熟、通用的业务模型去理解、拆解和实现它。这不仅能让你快速启动项目更能让你在过程中真正理解一个企业级应用是如何从需求到落地的。为什么实习管理系统是个好选题因为它介于“过于简单”和“过于复杂”之间。它不像“学生信息管理”那样基础也不像“电商平台”那样庞大。它具备清晰的业务角色学生、企业、学校管理员、完整的业务流程岗位发布、投递、审核、过程管理、评价和适中的技术复杂度非常适合用来展示你对SpringBoot、Vue、数据库设计、前后端交互等核心技术的综合运用能力。接下来我们将抛开空泛的概念直接进入实战。我会带你走过从环境搭建到功能实现的完整路径并重点分享那些新手最容易忽略却又决定项目成败的关键细节。1. 为什么“实习管理系统”是毕设的黄金选题在开始敲代码之前我们得先想明白为什么这个选题值得做。很多同学选课题时容易陷入两个极端要么追求“高大上”搞AI、区块链结果技术栈不熟做成了空中楼阁要么图省事做“增删改查”管理后台导致项目深度不足答辩时经不起推敲。实习管理系统巧妙地避开了这两个坑。首先它的业务逻辑是自洽且真实的。你不需要编造需求只需要把现实中学校、学生、企业三方在实习过程中的互动关系梳理清楚即可。这为你提供了一个坚实、可信的需求基础。其次它的技术栈覆盖全面且主流。后端可以用SpringBoot构建RESTful API前端用Vue实现动态交互数据库用MySQL存储关系型数据中间可能涉及文件上传、权限控制、状态流转等常见企业级功能。最后它的复杂度可控。你可以根据自身时间和能力决定是做单学校版本还是支持多学校、多院系的版本是只做流程管理还是加入数据分析报表。更重要的是这个项目能很好地回答答辩老师最关心的几个问题业务理解你能说清楚学生从找实习到完成实习的完整流程吗技术选型你为什么用SpringBoot而不是SSM为什么用Vue而不是jQuery系统设计你的数据库表是如何设计的如何保证数据的一致性难点与解决你在开发中遇到了什么具体问题是如何解决的一个选题如果能让你自然地展示这些能力那它就是一个好选题。实习管理系统正是这样的存在。2. 环境与工具准备避开第一个“坑”万事开头难而“开头”往往就卡在环境配置上。很多教程默认你万事俱备但现实中版本冲突、依赖下载失败、配置错误才是常态。我们的原则是用最稳定、最通用的版本组合先让项目跑起来。2.1 后端环境 (SpringBoot)JDK推荐 JDK 8 或 JDK 11。这是企业级应用最主流的两个LTS版本兼容性最好。确保JAVA_HOME环境变量配置正确。开发工具IntelliJ IDEA 社区版或旗舰版均可。它的Spring Initializr集成和智能提示能极大提升效率。项目初始化访问 start.spring.io 这是最官方的起点。生成项目时选择Project: Maven Project (更通用)Language: JavaSpring Boot: 选择 2.7.x 或 3.0.x 的稳定版本注意3.x需要JDK 17Dependencies: 这是我们项目的骨架务必选对Spring Web(构建Web应用)Spring Data JPA或MyBatis-Plus(数据库ORM二选一新手推荐JPA)MySQL Driver(数据库驱动)Lombok(简化实体类代码强烈推荐)数据库安装MySQL 5.7或8.0。创建一个空数据库例如internship_db。记住连接信息url, username, password。2.2 前端环境 (Vue)Node.js去官网下载LTS版本如18.x。安装后在命令行用node -v和npm -v验证。包管理工具npm 随Node安装但国内速度可能慢。建议安装yarn或配置 npm 淘宝镜像。Vue CLI这是官方脚手架。在命令行运行npm install -g vue/cli进行全局安装。完成后用vue --version验证。创建项目在合适目录下运行vue create internship-frontend。选择Manually select features然后勾选Babel(ES6转译)Router(路由必选)Vuex(状态管理对于多角色系统很有用)CSS Pre-processors(如Sass/Scss选装)其他如Linter/Formatter可根据喜好选择。开发工具Visual Studio Code 是前端开发的首选轻量且插件丰富。必装插件Vetur (Vue语法高亮)、ESLint、Prettier。注意不要在这个阶段追求最新版本。毕设的核心是稳定完成而不是技术探险。锁定上述版本组合能帮你避开至少80%的环境问题。3. 核心业务与数据库设计先想清楚再动手这是项目的“地基”。很多同学一上来就写Controller和页面结果写到一半发现表结构设计不合理又要推倒重来非常打击士气。正确的顺序是梳理业务 - 设计数据库 - 创建实体 - 编写基础CRUD。3.1 业务角色与流程梳理我们的系统主要涉及三类用户学生查看实习岗位、投递简历、查看进度、提交周报/总结、评价企业。企业注册/登录、发布岗位、审核简历、管理实习生、评价学生。学校管理员/导师审核企业资质、管理学生信息、审核实习申请、查看实习过程、处理异常。核心业务流程可以简化为企业发布岗位 - 管理员审核岗位 - 学生浏览并投递 - 企业审核简历 - 学生进入实习 - 双方过程记录与评价 - 实习结束归档。3.2 数据库表设计核心表举例基于以上流程我们可以设计出以下核心表。这里使用注释说明字段意义和关联关系。-- 用户表统一存储学生、企业、管理员通过user_type区分 CREATE TABLE sys_user ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键, username varchar(50) NOT NULL COMMENT 用户名/登录账号, password varchar(100) NOT NULL COMMENT 加密后的密码, nickname varchar(50) DEFAULT NULL COMMENT 昵称/真实姓名, avatar varchar(255) DEFAULT NULL COMMENT 头像, email varchar(100) DEFAULT NULL COMMENT 邮箱, phone varchar(20) DEFAULT NULL COMMENT 手机号, user_type tinyint NOT NULL COMMENT 用户类型1-学生2-企业3-管理员, status tinyint DEFAULT 1 COMMENT 状态0-禁用1-正常, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) COMMENT系统用户表; -- 学生扩展信息表 CREATE TABLE student_info ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL COMMENT 关联用户ID, student_number varchar(20) NOT NULL COMMENT 学号, college varchar(100) DEFAULT NULL COMMENT 学院, major varchar(100) DEFAULT NULL COMMENT 专业, grade varchar(20) DEFAULT NULL COMMENT 年级, resume_url varchar(255) DEFAULT NULL COMMENT 简历文件路径, PRIMARY KEY (id), UNIQUE KEY uk_user_id (user_id), UNIQUE KEY uk_student_number (student_number), CONSTRAINT fk_student_user FOREIGN KEY (user_id) REFERENCES sys_user (id) ON DELETE CASCADE ) COMMENT学生信息表; -- 企业扩展信息表 CREATE TABLE company_info ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL COMMENT 关联用户ID, company_name varchar(200) NOT NULL COMMENT 企业全称, credit_code varchar(50) DEFAULT NULL COMMENT 统一社会信用代码, industry varchar(100) DEFAULT NULL COMMENT 所属行业, scale varchar(50) DEFAULT NULL COMMENT 企业规模, address varchar(255) DEFAULT NULL COMMENT 地址, introduction text COMMENT 企业简介, business_license_url varchar(255) DEFAULT NULL COMMENT 营业执照, audit_status tinyint DEFAULT 0 COMMENT 审核状态0-待审核1-通过2-拒绝, PRIMARY KEY (id), UNIQUE KEY uk_user_id (user_id), CONSTRAINT fk_company_user FOREIGN KEY (user_id) REFERENCES sys_user (id) ON DELETE CASCADE ) COMMENT企业信息表; -- 实习岗位表 CREATE TABLE internship_post ( id bigint NOT NULL AUTO_INCREMENT, company_id bigint NOT NULL COMMENT 发布企业ID, title varchar(200) NOT NULL COMMENT 岗位标题, description text COMMENT 岗位描述, requirement text COMMENT 任职要求, location varchar(100) DEFAULT NULL COMMENT 工作地点, recruit_number int DEFAULT NULL COMMENT 招聘人数, apply_number int DEFAULT 0 COMMENT 已申请人数, start_date date DEFAULT NULL COMMENT 实习开始日期, end_date date DEFAULT NULL COMMENT 实习结束日期, status tinyint DEFAULT 1 COMMENT 状态0-关闭1-开放, publish_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 发布时间, audit_status tinyint DEFAULT 0 COMMENT 审核状态0-待审核1-通过2-拒绝, PRIMARY KEY (id), KEY idx_company_id (company_id), CONSTRAINT fk_post_company FOREIGN KEY (company_id) REFERENCES company_info (id) ) COMMENT实习岗位表; -- 实习申请记录表核心流程表 CREATE TABLE internship_application ( id bigint NOT NULL AUTO_INCREMENT, post_id bigint NOT NULL COMMENT 岗位ID, student_id bigint NOT NULL COMMENT 学生ID, resume_url varchar(255) DEFAULT NULL COMMENT 投递的简历, application_status tinyint DEFAULT 0 COMMENT 申请状态0-已投递1-已查看2-通过初筛3-面试邀请4-录用5-拒绝, feedback varchar(500) DEFAULT NULL COMMENT 企业反馈, apply_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 投递时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 状态更新时间, PRIMARY KEY (id), UNIQUE KEY uk_post_student (post_id,student_id), -- 防止重复投递 KEY idx_student_id (student_id), CONSTRAINT fk_application_post FOREIGN KEY (post_id) REFERENCES internship_post (id), CONSTRAINT fk_application_student FOREIGN KEY (student_id) REFERENCES student_info (id) ) COMMENT实习申请记录表;其他表如周报表、评价表等可根据需要扩展设计要点用户统一认证sys_user表是所有用户的登录入口通过user_type区分角色。这样做的好处是登录逻辑统一权限控制清晰。信息分离学生和企业的详细信息放在扩展表中与核心登录信息解耦结构更清晰。状态字段status,audit_status,application_status等状态字段是业务流程驱动的核心。设计时要穷举所有可能状态并在代码中用枚举类管理。外键与索引合理使用外键保证数据完整性在post_id,student_id等查询频繁的字段上建立索引提升性能。时间戳create_time,update_time是必备字段用于记录和追踪。4. 后端实现从实体到API的完整链路有了清晰的数据模型后端开发就变成了有迹可循的“填空题”。我们以“实习岗位”模块为例走通从实体到控制器Controller的完整链路。4.1 创建实体类 (Entity)使用Spring Data JPA实体类与数据库表一一对应。结合Lombok代码非常简洁。package com.internship.system.entity; import lombok.Data; import javax.persistence.*; import java.time.LocalDateTime; import java.util.Date; Data Entity Table(name internship_post) public class InternshipPost { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; Column(name company_id, nullable false) private Long companyId; Column(nullable false, length 200) private String title; Column(columnDefinition TEXT) private String description; Column(columnDefinition TEXT) private String requirement; private String location; private Integer recruitNumber; private Integer applyNumber 0; Temporal(TemporalType.DATE) private Date startDate; Temporal(TemporalType.DATE) private Date endDate; private Integer status 1; // 使用枚举更佳 private Integer auditStatus 0; Column(updatable false) private LocalDateTime publishTime LocalDateTime.now(); // 省略 getter/setter由Lombok的Data注解提供 }4.2 创建数据访问层 (Repository)JPA的Repository接口提供了强大的数据访问能力无需编写SQL。package com.internship.system.repository; import com.internship.system.entity.InternshipPost; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.util.List; public interface InternshipPostRepository extends JpaRepositoryInternshipPost, Long { // 根据企业ID分页查询 PageInternshipPost findByCompanyId(Long companyId, Pageable pageable); // 根据状态查询例如查询所有已审核通过的岗位 ListInternshipPost findByAuditStatus(Integer auditStatus); // 复杂查询示例根据标题关键词和地点查询已审核通过的岗位 Query(SELECT p FROM InternshipPost p WHERE p.auditStatus 1 AND (p.title LIKE %:keyword% OR p.description LIKE %:keyword%) AND p.location LIKE %:location%) PageInternshipPost searchPosts(Param(keyword) String keyword, Param(location) String location, Pageable pageable); }4.3 创建业务逻辑层 (Service)Service层处理核心业务逻辑是Controller和Repository之间的桥梁。package com.internship.system.service; import com.internship.system.entity.InternshipPost; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import java.util.Map; public interface InternshipPostService { // 保存或更新岗位 InternshipPost saveOrUpdate(InternshipPost post); // 根据ID获取岗位 InternshipPost getById(Long id); // 分页查询岗位带条件 PageInternshipPost getPostsByPage(MapString, Object conditions, Pageable pageable); // 更新岗位状态 void updateStatus(Long id, Integer status); // 删除岗位逻辑删除或物理删除 void deleteById(Long id); }package com.internship.system.service.impl; import com.internship.system.entity.InternshipPost; import com.internship.system.repository.InternshipPostRepository; import com.internship.system.service.InternshipPostService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.persistence.criteria.Predicate; import java.util.ArrayList; import java.util.List; import java.util.Map; Service RequiredArgsConstructor // Lombok注解自动注入final字段 public class InternshipPostServiceImpl implements InternshipPostService { private final InternshipPostRepository postRepository; Override public InternshipPost saveOrUpdate(InternshipPost post) { // 这里可以添加业务校验例如企业是否存在日期是否合理等 if (post.getId() null) { post.setApplyNumber(0); // 新建岗位申请人数为0 } return postRepository.save(post); } Override public PageInternshipPost getPostsByPage(MapString, Object conditions, Pageable pageable) { // 使用Specification动态构建查询条件这是JPA处理复杂查询的优雅方式 SpecificationInternshipPost spec (root, query, cb) - { ListPredicate predicates new ArrayList(); // 条件审核状态为通过 predicates.add(cb.equal(root.get(auditStatus), 1)); // 条件岗位状态为开放 predicates.add(cb.equal(root.get(status), 1)); // 动态添加其他条件 if (conditions.containsKey(keyword) StringUtils.hasText((String)conditions.get(keyword))) { String keyword (String) conditions.get(keyword); Predicate p1 cb.like(root.get(title), % keyword %); Predicate p2 cb.like(root.get(description), % keyword %); predicates.add(cb.or(p1, p2)); } if (conditions.containsKey(location) StringUtils.hasText((String)conditions.get(location))) { predicates.add(cb.like(root.get(location), % conditions.get(location) %)); } // 可以继续添加其他条件如企业行业、实习日期范围等 query.where(predicates.toArray(new Predicate[0])); query.orderBy(cb.desc(root.get(publishTime))); // 按发布时间倒序 return query.getRestriction(); }; return postRepository.findAll(spec, pageable); } // ... 其他方法实现 }4.4 创建Web控制层 (Controller)Controller接收前端请求调用Service并返回统一格式的响应。这里使用RestController和RequestMapping。package com.internship.system.controller; import com.internship.system.common.Result; import com.internship.system.entity.InternshipPost; import com.internship.system.service.InternshipPostService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; RestController RequestMapping(/api/post) RequiredArgsConstructor public class InternshipPostController { private final InternshipPostService postService; /** * 分页查询实习岗位列表 (学生端/前台) * param page 页码从0开始 * param size 每页大小 * param keyword 搜索关键词 * param location 工作地点 * return 分页结果 */ GetMapping(/list) public ResultPageInternshipPost getPostList( RequestParam(defaultValue 0) Integer page, RequestParam(defaultValue 10) Integer size, RequestParam(required false) String keyword, RequestParam(required false) String location) { Pageable pageable PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, publishTime)); MapString, Object conditions new HashMap(); if (keyword ! null) conditions.put(keyword, keyword); if (location ! null) conditions.put(location, location); PageInternshipPost postPage postService.getPostsByPage(conditions, pageable); return Result.success(postPage); } /** * 根据ID获取岗位详情 */ GetMapping(/{id}) public ResultInternshipPost getPostDetail(PathVariable Long id) { InternshipPost post postService.getById(id); if (post null) { return Result.error(岗位不存在); } return Result.success(post); } /** * 企业发布新岗位 */ PostMapping public ResultInternshipPost createPost(RequestBody InternshipPost post, RequestAttribute Long currentUserId) { // 从请求属性中获取当前登录的企业用户ID需要配合拦截器实现 post.setCompanyId(currentUserId); post.setAuditStatus(0); // 新发布岗位默认为待审核 InternshipPost savedPost postService.saveOrUpdate(post); return Result.success(savedPost); } // ... 其他接口更新、删除、状态变更等 }后端开发核心经验统一响应格式定义一个ResultT类封装code,message,data让前端处理结果更规范。全局异常处理使用ControllerAdvice和ExceptionHandler捕获并处理各类异常返回友好的错误信息而不是堆栈跟踪。参数校验在DTO或实体字段上使用NotBlank,Size等注解并在Controller方法上加Valid注解避免无效数据进入业务层。分页查询对于列表数据务必使用分页。Spring Data的Pageable和Page对象能极大简化开发。接口文档使用Swagger或Knife4j自动生成API文档方便前后端联调。5. 前端实现用Vue构建动态管理界面前端的目标是构建一个清晰、交互友好的管理界面。我们以“岗位列表页”和“岗位发布页”为例。5.1 安装必要依赖并配置请求库在Vue项目根目录下安装axios和element-ui一个流行的UI组件库。npm install axios element-ui --save在main.js中引入import Vue from vue import App from ./App.vue import router from ./router import store from ./store import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; import axios from axios Vue.config.productionTip false Vue.use(ElementUI); // 配置axios基准URL和请求拦截器用于添加token axios.defaults.baseURL http://localhost:8080/api; // 假设后端运行在8080端口 axios.interceptors.request.use(config { const token localStorage.getItem(token); if (token) { config.headers.Authorization Bearer ${token}; } return config; }); axios.interceptors.response.use( response response.data, error { // 统一处理错误例如token过期跳转到登录页 if (error.response error.response.status 401) { router.push(/login); } return Promise.reject(error); } ); Vue.prototype.$axios axios; new Vue({ router, store, render: h h(App) }).$mount(#app)5.2 岗位列表页组件 (PostList.vue)这个页面展示所有已审核通过的实习岗位支持搜索和分页。template div classpost-list-container el-card !-- 搜索区域 -- div classsearch-bar el-input v-modelsearchForm.keyword placeholder请输入岗位关键词 stylewidth: 300px; margin-right: 15px; keyup.enter.nativehandleSearch /el-input el-input v-modelsearchForm.location placeholder请输入工作地点 stylewidth: 200px; margin-right: 15px; keyup.enter.nativehandleSearch /el-input el-button typeprimary iconel-icon-search clickhandleSearch搜索/el-button el-button clickresetSearch重置/el-button /div !-- 岗位列表表格 -- el-table :datatableData stylewidth: 100%; margin-top: 20px; v-loadingloading el-table-column proptitle label岗位名称 width200/el-table-column el-table-column propcompanyName label企业名称 width180/el-table-column el-table-column proplocation label工作地点 width120/el-table-column el-table-column proprecruitNumber label招聘人数 width100/el-table-column el-table-column propapplyNumber label已申请 width80/el-table-column el-table-column propstartDate label开始日期 width120 template slot-scopescope {{ formatDate(scope.row.startDate) }} /template /el-table-column el-table-column propendDate label结束日期 width120 template slot-scopescope {{ formatDate(scope.row.endDate) }} /template /el-table-column el-table-column label操作 width150 template slot-scopescope el-button typetext sizesmall clickviewDetail(scope.row.id)查看详情/el-button el-button typetext sizesmall clickhandleApply(scope.row) :disabledscope.row.applied投递简历/el-button /template /el-table-column /el-table !-- 分页组件 -- el-pagination size-changehandleSizeChange current-changehandleCurrentChange :current-pagepagination.current :page-sizes[10, 20, 50] :page-sizepagination.size layouttotal, sizes, prev, pager, next, jumper :totalpagination.total stylemargin-top: 20px; text-align: center; /el-pagination /el-card /div /template script export default { name: PostList, data() { return { searchForm: { keyword: , location: }, tableData: [], // 表格数据 loading: false, pagination: { current: 1, size: 10, total: 0 } } }, mounted() { this.fetchPostList(); }, methods: { // 获取岗位列表 async fetchPostList() { this.loading true; try { const params { page: this.pagination.current - 1, // 后端页码从0开始 size: this.pagination.size, ...this.searchForm }; const res await this.$axios.get(/post/list, { params }); this.tableData res.data.content; // Spring Data Page 对象的内容 this.pagination.total res.data.totalElements; } catch (error) { this.$message.error(获取岗位列表失败); console.error(error); } finally { this.loading false; } }, // 搜索 handleSearch() { this.pagination.current 1; // 搜索时回到第一页 this.fetchPostList(); }, // 重置搜索 resetSearch() { this.searchForm { keyword: , location: }; this.handleSearch(); }, // 分页大小变化 handleSizeChange(val) { this.pagination.size val; this.pagination.current 1; this.fetchPostList(); }, // 当前页变化 handleCurrentChange(val) { this.pagination.current val; this.fetchPostList(); }, // 查看详情 viewDetail(id) { this.$router.push(/post/detail/${id}); }, // 投递简历 handleApply(row) { // 这里应该弹出一个对话框上传简历或选择已有简历 this.$confirm(确定要投递「${row.title}」岗位吗, 提示, { confirmButtonText: 确定, cancelButtonText: 取消, type: warning }).then(async () { try { await this.$axios.post(/application, { postId: row.id }); this.$message.success(投递成功); row.applied true; // 禁用按钮 this.fetchPostList(); // 刷新列表更新申请人数 } catch (error) { this.$message.error(投递失败 (error.message || 未知错误)); } }); }, // 日期格式化 formatDate(dateStr) { if (!dateStr) return -; return new Date(dateStr).toLocaleDateString(); } } } /script style scoped .search-bar { margin-bottom: 20px; } /style5.3 路由与状态管理配置在router/index.js中配置路由在store/index.js中可以使用Vuex管理用户登录状态等全局信息。这部分是Vue项目的标准配置此处不再赘述。前端开发核心经验组件化将页面拆分为可复用的组件如搜索栏、表格、分页、表单对话框等。状态管理对于跨组件共享的状态如用户信息使用Vuex进行集中管理。API封装将所有的后端请求封装成独立的service模块便于维护和复用。错误处理在axios拦截器中统一处理网络错误和业务错误给用户友好的提示。用户体验合理使用loading状态、按钮防抖、操作确认弹窗等提升交互体验。6. 前后端联调与部署让项目真正跑起来代码写完了但项目还停留在本地。联调和部署是检验项目能否正常工作的最后一步也是问题高发区。6.1 解决跨域问题前后端分离开发前端运行在localhost:8081后端在localhost:8080浏览器会因同源策略阻止请求。在后端SpringBoot项目中添加一个配置类即可解决。package com.internship.system.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) // 针对所有/api开头的接口 .allowedOrigins(http://localhost:8081) // 允许前端地址 .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }6.2 打包与部署后端打包在项目根目录下执行mvn clean packageMaven项目会在target目录生成一个.jar文件。使用java -jar your-project.jar即可运行。前端打包在Vue项目根目录下执行npm run build会在dist目录生成静态文件HTML, JS, CSS。部署方式简单方式将前端dist目录下的文件复制到SpringBoot项目的src/main/resources/static/目录下然后打包成一个jar。这样访问后端地址就能看到前端页面。适合毕设演示分离部署后端jar包运行在服务器上前端静态文件使用Nginx托管。需要配置Nginx将API请求代理到后端服务。更接近生产环境6.3 常见问题排查清单当项目跑不起来时按这个顺序检查后端启动失败检查端口是否被占用netstat -ano | findstr :8080。检查数据库连接配置application.yml或application.properties是否正确。查看启动日志是否有依赖冲突或Bean创建错误。前端请求报错404检查请求URL是否正确后端对应RequestMapping路径是否存在。405检查请求方法GET/POST与后端接口定义是否一致。500后端内部错误查看后端控制台日志通常是空指针、SQL异常或业务逻辑错误。跨域错误确认后端CORS配置已生效且前端请求地址无误。页面显示异常打开浏览器开发者工具F12查看Console和Network标签页这里会有详细的错误信息。检查Element-UI等组件库版本是否兼容。检查Vue、Vue Router、Vuex的版本是否匹配。7. 从“能运行”到“像样作品”毕设的加分项一个能运行的系统和一份优秀的毕设作品之间还差一些“匠心”。这些点能让你的项目在答辩时脱颖而出。权限控制实现基于角色的访问控制RBAC。学生不能审核岗位企业不能查看其他企业的申请者。可以使用Spring Security或Shiro框架这是展示你系统设计能力的好机会。文件上传实现简历、营业执照等文件的上传与下载功能。考虑文件类型限制、大小限制、存储路径本地或OSS和访问权限。数据可视化为管理员增加数据看板。使用ECharts等库展示实习岗位数量趋势、学生投递情况、企业分布等图表。消息通知当学生的申请状态变更如通过初筛、被拒绝时通过站内信或邮件集成Spring Mail通知用户。日志记录关键操作如登录、发布岗位、审核申请记录操作日志便于追踪和审计。接口文档使用Swagger生成并维护一份清晰的API文档这体现了你的工程素养。代码质量保持代码规范有清晰的注释对关键算法或复杂逻辑进行说明。可以进行简单的单元测试。记住毕业设计考察的不仅仅是你实现了什么功能更是你如何思考问题、如何设计系统、如何解决问题以及如何呈现成果。这个“校企实习管理系统”项目为你提供了一个坚实的舞台让你可以系统地展示这些能力。从今天开始不要再纠结于“构思需求”而是动手去“实现一个清晰的业务”。当你把上述每一步都走通、走扎实之后你会发现一份令人满意的毕设作品已然在你手中。