ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot+Vue毕业设计项目实战:民生政务交流平台从0到部署

SpringBoot+Vue毕业设计项目实战:民生政务交流平台从0到部署 我做这个毕业设计的时候纠结了很久到底选什么题。既要能体现这两年学的Java后端功底又不能在答辩的时候被问倒还得保证工作量看起来是那么回事儿。最后定下来的题目是“民生政务交流平台”技术栈选了SpringBoot Vue这套经典组合。这个项目说白了就是做一个网上办事和互动的窗口老百姓能在这里看到政务公告、办事指南对关心的民生问题在线提问相关工作人员负责审核、回复整个流程在系统里闭环跑通。这篇博文把我从立项选型、数据库设计、核心接口实现到前端页面对接、部署演示踩过的坑全部整理一遍。正在纠结毕业设计选题、或者已经选了类似题目的同学可以直接抄作业。1. 先搞清楚民生政务交流平台到底要做什么1.1 从业务场景倒推功能边界很多同学拿到题目第一反应就是“我要做一个管理系统”然后开始画用户管理、角色管理、菜单管理……最后做出来一个谁都不想用的壳子。我的建议正好相反先想清楚这个平台给谁用、解决什么问题再去倒推功能。民生政务交流平台核心是“政务信息发布”和“民意交流互动”两条线。第一条线针对的是公告、政策解读、办事指南这类信息通常由后台管理员或者官方账号维护用户主要是浏览查看。第二条线针对的是用户遇到问题比如社保缴纳问题、小区周边环境问题、办事流程不清楚可以发起在线咨询管理员对问题审核后分发给对应部门最后由工作人员回复用户收到通知整个沟通过程系统留痕。明确了这两条线功能模块就很清晰了。用户端需要的是注册登录账号密码就能进角色分普通用户和管理员浏览政务公告、政策解读、办事指南能按分类筛选、按关键词搜索提交咨询问题填标题、选分类、写具体内容查看我的咨询记录以及每条咨询的官方回复个人中心改密码、看消息通知管理端需要的是公告内容管理发布、编辑、下架用户提交问题的审核通过或者驳回驳回要写原因对已通过的问题进行回复用户管理列表查看、禁用异常账号数据概览首页展示公告数、问题数、回复数等信息1.2 流程设计与状态机设计这个项目答辩的时候很容易被问到一个问题用户提交的问题怎么流转这就涉及状态设计。我在问题表里设计了一个status字段取值分四档状态值含义说明0待审核用户提交后默认状态前台不可见1已审核通过管理员审核通过前台公开展示2已驳回管理员驳回用户能看到驳回原因3已关闭问题超期未处理自动关闭或管理员人工关闭回答是跟问题一对多的关系。一个问题通过审核之后官方回复就挂在问题下面。为了让演示效果更好我还在初始数据里准备了几个典型问答评审老师一打开首页就能看到有人提问、有人回复不用自己现注册一个号再发一条等半天这个细节后面单独说。1.3 演示数据和自动初始化毕业设计演示最怕的是空页面。打开系统一片空白老师第一印象就差了。我自己的做法是写一个CommandLineRunner在应用启动的时候自动导入初始数据10条公告、5条政策解读、6个用户、8个问题覆盖不同状态、每条问题下挂1到3条回复。这样应用一启动整个平台看起来就是活的。顺带说一个跟这个场景相关的技巧用SpringBoot MyBatis时如果想让表不存在就自动创建可以在application.yml里配置spring.sql.init的相关参数或者直接放一个schema.sql和data.sql让SpringBoot在启动时自动执行。我刚接触的时候也纠结过这个问题后来发现用MyBatis-Plus也可以配合写一个初始化表结构的代码但最省事的还是直接放SQL脚本配合CommandLineRunner去做数据初始化。这样不管换到哪台机器上部署演示只要MySQL里建好库、配好账号应用一启动表和初始数据就全有了。2. 技术选型为什么是SpringBoot Vue2.1 后端选SpringBoot的理由后端选择SpringBoot我认为是现阶段毕业设计最稳的选择没有之一。SpringBoot的核心价值是“约定大于配置”它帮我们预置了Web开发的大部分基础配置内置Tomcat打包直接打成可执行的jar包java -jar丢上去就能跑。相比传统SSH或者SSM那一套动辄几十个XML配置的玩法SpringBoot把开发者的注意力从“配置”上解放出来真正聚焦到业务代码上。我的具体版本组合是SpringBoot 2.7.x搭配JDK 8。这里多说一句很多同学习惯一上来就上最新版本其实没必要。SpringBoot 3.x要求JDK 17起步虽然新但网上大部分教程、博客、面试题解析还是基于2.x遇到问题排查资料更丰富。如果只是做毕业设计优先级是“稳”而不是“新”。至于SpringBoot的“自动配置”原理这属于java面试八股文的高频考点我建议答辩前认真读一遍源码思想至少能说清楚SpringBootApplication为什么能自动扫描、自动装配是怎么生效的这个后文可以展开聊。2.2 前端选Vue的理由前端选择Vue原因也很直接上手门槛低中文资料多熟练度和生态都比React更友好。Vue的核心设计就是响应式数据驱动模板语法简单配合Element Plus组件库后台管理页面几乎不用自己写CSS表格、表单、弹窗、分页全都开箱即用。你只需要关注数据和交互逻辑项目就能很快成型。Vue现在的版本我建议直接用Vue 3配合Vite构建起步快开发体验好。状态管理用Pinia路由用Vue Router 4请求用axios这些基本是Vue 3全家桶的标准配置。工具方面浏览器装一个Vue DevTools调试插件看组件状态、检查路由跳转都特别方便强烈建议装上。我记得第一次联调的时候接口数据返回了但页面不更新就是用DevTools一看Store里的值没变马上定位到是响应拦截器里代码写错了这个工具能省很多事。2.3 整体架构和数据流向这个项目是标准的前后端分离架构。浏览器端由Vue脚手架提供页面开发时用Vite的devServer跑在5173端口生产环境把构建好的静态文件交给Nginx托管。所有数据交互都通过axios发送HTTP请求到后端的SpringBoot服务开发时后端跑在8080生产环境用Nginx反向代理转发到8080。数据流向整体上是这样的用户操作页面触发Vue组件里的方法方法调用api目录下封装好的请求函数axios实例自动携带token请求到达SpringBoot的Controller校验参数后交给ServiceService里实现业务逻辑调用MyBatis-Plus的Mapper接口操作MySQL数据原路返回前端拿到JSON后更新响应式状态页面自动刷新后端只提供RESTful API不关心页面长什么样前端只负责展示和交互不直接碰数据库。这就是前后端分离最大的好处职责单一开发和联调可以并行而且答辩的时候你可以很清楚地讲“前端发什么请求、后端返回什么数据、状态是怎么流转的”这个逻辑闭环是加分项。我对比过传统JSP模式和前后端分离模式把关键差异整理成了下面这张表。对比项传统JSP模式前后端分离模式页面渲染服务端渲染Java代码直接写进页面前端JS渲染后端只返回JSON开发调试前后端耦合改样式也要重启服务后端接口可以用Postman单独测前端用devServer部署方式打成war包丢Tomcat后端jar包独立运行前端静态文件由Nginx托管团队协作一个人全包耦合度高前后端可以并行开发接口文档先行答辩价值相对传统贴合主流企业开发方式更有说服力3. 后端SpringBoot核心实现细节3.1 项目初始化与依赖选择项目本身可以直接用Spring Initializr生成也可以直接去官网start点两下把依赖选好下载下来导进IDEA。注意如果网络不行用阿里云的镜像地址创建会顺畅很多。我用的核心依赖spring-boot-starter-web提供Web能力内置Tomcatmybatis-plus-boot-starter数据库ORM简化单表CRUDmysql-connector-java连接MySQLlombok减少实体类的getter/setter编写jjwtio.jsonwebtoken生成和解析JWT Tokenhutool-all可选提供一些工具类比如验证码生成、日期处理validation参数校验spring-boot-starter-validationpom.xml里关于MyBatis-Plus的部分大概是这样的dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency这个版本跟SpringBoot 2.7.x兼容得很好我实际用下来没有碰到版本冲突。这里顺带提醒一句新手很容易在“SpringBoot版本太高”上翻车比如直接用SpringBoot 3.2然后去网上找一个2.x时代的MyBatis-Plus用法结果发现很多类被废弃或者移了包路径排查起来特别痛苦。所以我坚持建议毕业设计不追新稳定能用、资料好查才是第一位。3.2 目录结构与分层思想后端项目结构我按controller / service / mapper / entity四层来组织src/main/java/com/example/govplatform ├── controller # 接口入口只负责参数接收和数据返回 │ ├── AuthController │ ├── ArticleController │ ├── QuestionController │ └── AdminController ├── service # 业务逻辑层 │ ├── UserService │ ├── ArticleService │ ├── QuestionService │ └── impl ├── mapper # MyBatis-Plus的Mapper接口操作数据库 │ ├── UserMapper │ ├── ArticleMapper │ └── QuestionMapper ├── entity # 数据库实体类与表字段一一对应 │ ├── User │ ├── Article │ └── Question ├── common # 公共类 │ ├── Result # 统一返回体 │ ├── GlobalExceptionHandler │ └── JwtInterceptor └── config # 配置类 └── MybatisPlusConfig这个分层的价值在于每个类只干一件事。Controller里不写业务SQLService里不出现HttpServletRequest相关的东西Mapper只定义接口不写实现大家各司其职。答辩时老师问到这个分层依据你可以直接回答“高内聚、低耦合每一层只关注自己的职责既方便维护也方便做单元测试”。我在实际写代码的时候还发现一点Service接口和Impl实现分开写虽然多了一层但对毕业设计来讲是“规范感”的体现老师看目录结构就能看出你不是随便糊的。所以即使只有一个实现类我也建议按接口Impl的方式去组织。3.3 数据库设计数据库我用的MySQL 8.0数据库名直接叫gov_platform。核心表一共五张设计思路如下表名用途核心字段user用户表id, username, password, nickname, avatar, role, status, create_timearticle公告/文章表id, title, content, category, status, view_count, author_id, publish_timequestion咨询问题表id, user_id, category, title, content, status, reject_reason, view_count, create_timereply回复表id, question_id, replier_id, content, like_count, create_timenotification消息通知表id, user_id, content, is_read, create_time这里我说几个关键设计点。第一user表的role字段用字符串方式存值就是USER和ADMIN两个不做复杂权限表。对毕业设计来说一个角色字段足够支撑整个权限逻辑做RBAC权限模型反而会拖慢进度。第二question表一定得有reject_reason字段很多同学忘了设计驳回原因。如果没有这个字段管理员驳回问题时用户根本不知道为什么被拒业务闭环就断了。第三content字段用text类型。我用MyBatis-Plus的TableField注解配合typeHandler处理text字段避免查询大字段时性能问题虽然这个体量的项目性能都无所谓但功能要完整。第四所有表都有create_time用MyBatis-Plus的自动填充功能。在字段上加TableField(fill FieldFill.INSERT)再写一个MetaObjectHandler的配置类插入数据时自动填入当前时间。这样实体类不用手动set时间代码干净很多。3.4 JWT登录鉴权登录鉴权我选的是JWT方案没有用传统的Session。毕业设计选JWT的合理性在于前后端分离架构下前端和后端的域名都可能不同Session的Cookie机制天然跨域受限而JWT把身份信息直接放在Token里前端每次请求在Header里带上Authorization就行。JWT的整体流程是用户登录成功后后端利用密钥生成一个Token里面封装userId、username、role设置过期时间我设置的24小时前端拿到Token存到LocalStorage每次axios请求前带上后端写一个拦截器对所有需要认证的接口校验TokenToken有效才放行我封装了一个JwtUtil工具类核心方法有三个generateToken、parseToken、isTokenValid。生成Token的时候用jjwt库的API代码大概是这样的public String generateToken(User user) { return Jwts.builder() .setSubject(user.getUsername()) .claim(userId, user.getId()) .claim(role, user.getRole()) .setExpiration(new Date(System.currentTimeMillis() 24 * 60 * 60 * 1000)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); }拦截器的处理逻辑也不复杂核心就是在preHandle方法里从请求头取Token解析成功就把userId放回Request作用域里然后放行解析失败直接返回401状态码和提示信息。需要说明的是登录接口和注册接口要在拦截器里放行不然没登录的人连注册都进不来。我的放行路径配置是/api/auth/**其他所有接口都走认证。管理后台的接口我还会额外校验请求里带上来的用户角色必须是ADMIN防止普通用户调用管理接口。3.5 统一返回体与全局异常处理我见过不少同学的接口返回格式五花八门有的返回布尔值有的直接返回实体类有的查询失败就直接抛500页面。这样前端对接时非常痛苦。我的做法是定义一个统一的Result类public class ResultT { private Integer code; // 200成功400业务错误401未认证500系统错误 private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.code 200; result.message 操作成功; result.data data; return result; } public static T ResultT error(Integer code, String message) { ResultT result new Result(); result.code code; result.message message; return result; } }然后再用一个RestControllerAdvice全局异常处理器把Controller层抛出的异常统一转成Result格式返回。比如参数校验失败返回400业务规则不满足返回400并把提示消息带上未捕获的Exception返回500。这样就保证了前端拿到的永远是同一种JSON结构不管成功还是失败前端在响应拦截器里统一处理code就行不用每个接口单独写错误分支。全局异常处理还有一个好处答辩演示的时候就算真的出现了空指针或者SQL异常用户看到的是一段友好的业务提示而不是一坨堆栈信息专业感直接拉满。3.6 核心业务接口实现整个项目最核心的接口我认为是“问题提交-审核-回复”这条链路上的三个。下面把关键逻辑拆开讲一下。提交问题的Controller大致是这样PostMapping(/api/questions) public ResultString submit(RequestBody Question question, HttpServletRequest request) { Long userId (Long) request.getAttribute(userId); question.setUserId(userId); question.setStatus(0); // 待审核 questionService.save(question); return Result.success(提交成功请等待审核); }这里有个细节userId不是前端传的而是从JWT拦截器放到Request里的。我设计的原则是当前登录用户是谁必须由后端从Token里取前端传的userId不能信。否则用户随便改个参数就能冒充别人发问题。审核接口的逻辑是这样的PutMapping(/api/admin/questions/{id}/audit) public ResultString audit(PathVariable Long id, RequestParam Integer status, RequestParam(required false) String rejectReason) { Question question questionService.getById(id); if (question null) { return Result.error(400, 问题不存在); } if (status 1) { question.setStatus(1); } else if (status 2) { question.setStatus(2); question.setRejectReason(rejectReason); // 给用户发一条驳回通知 notificationService.send(question.getUserId(), 您的问题被驳回 rejectReason); } questionService.updateById(question); return Result.success(操作成功); }回复接口处理的是官方回复人员对一个通过审核的问题添加回复。回复成功之后要给提问者发一条站内通知告诉他“您的问题有新的回复了”。这个通知功能虽然简单但正好能呼应“交流”这个主题业务完整性一下子就有了。4. 前端Vue落地实操4.1 项目搭建与环境准备前端我用的是Vite Vue 3。环境方面需要注意几点Node.js版本最好用长期支持版npm安装依赖如果太慢就换淘宝镜像源。很多同学卡在“vue安装依赖”这一步其实大部分都是网络问题。创建项目我推荐使用官方推荐的命令npm create vuelatest执行之后会提示你选择是否使用TypeScript、是否使用Vue Router、是否使用Pinia等。如果不是特别熟悉TS我建议选No直接JavaScript。路由和Pinia选上后面省得自己装。进入项目目录之后装基础依赖然后继续安装Element Plus和axiosnpm install npm install element-plus npm install axiosElement Plus的引入方式官方推荐完整引入最省事import ElementPlus from element-plus import element-plus/dist/index.css app.use(ElementPlus)对毕业设计这个体量来说完整引入完全可以接受按需自动导入反而多一套配置工作。另外一个小技巧用SpringBoot官方或者第三方工具生成一个自定义的Banner启动后端项目的时候终端会输出一行很酷的ASCII艺术字。这个东西虽然没有实际功能但是答辩现场演示启动项目时能让人眼前一亮算是一个加分的小细节。4.2 目录组织与请求封装Vue项目的目录结构我保持了一贯的清晰风格src ├── api # 所有接口请求函数 │ ├── auth.js │ ├── article.js │ ├── question.js │ └── admin.js ├── router # 路由配置 ├── stores # Pinia状态管理 ├── views # 页面级组件 │ ├── Home.vue │ ├── Login.vue │ ├── QuestionDetail.vue │ ├── UserCenter.vue │ └── admin │ ├── AdminLayout.vue │ ├── ArticleManage.vue │ └── QuestionAudit.vue ├── components # 公共业务组件 │ ├── QuestionCard.vue │ ├── ArticleList.vue │ └── Pagination.vue └── utils └── request.js # axios实例封装request.js是我重点封装的一个文件。axios实例统一设置了baseURL开发环境是http://localhost:8080/api添加了请求拦截器每次请求自动从LocalStorage里取出Token并放到Authorization请求头上。响应拦截器统一处理后端返回的Result结构code为200就返回data其他情况用Element Plus的Message组件弹出错误提示并处理401跳转到登录页。核心代码长这样const request axios.create({ baseURL: /api, timeout: 10000 }) request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization token } return config }) request.interceptors.response.use( response { const res response.data if (res.code 200) { return res.data } if (res.code 401) { router.push(/login) } Message.error(res.message) return Promise.reject(new Error(res.message)) }, error { Message.error(网络请求失败) return Promise.reject(error) } )baseURL写成/api配合Vite代理前端请求就完全不用关心后端地址这个方案能从根本上解决开发时的跨域问题后面在常见问题里会细讲。4.3 页面实现与组件拆分页面方面几个核心页面我做一下说明。首页是整个平台的的门面上半部分是一个公告轮播区展示最新公告往下是分类导航再往下是问题列表。问题列表用了我抽出来的QuestionCard组件每一张卡片展示问题标题、分类标签、提问时间、浏览数、回复数。点击卡片跳转到问题详情页。问题详情页是展示交流闭环的地方布局分左右两栏左侧是问题内容和全部回复记录右侧是同分类的推荐问题。回复列表做了一个时间线样式官方回复和普通回复用不同颜色的标签区分。涉及路由参数传递时我用的是Vue Router 4的useRoute获取params跳转时用route.push({ path: /question/ id })。这里有个细节就是刷新页面之后数据能不能保持只要从路由参数里拿id再调接口刷新以后自然能恢复千万不要把详情数据只放在Pinia里然后刷新就丢了。登录注册页用了一个卡片居中布局表单校验用的是Element Plus自带的rules。注册成功之后自动跳到登录页登录成功之后把Token和用户ID存到LocalStorage然后根据角色决定跳转首页还是管理后台。管理后台用了单独的Layout框架左侧菜单、右侧内容区。公告管理页面就是典型的增删改查表格展示、弹窗表单新增、编辑时回填、状态切换。问题审核页面是管理端的核心用Tab来区分“待审核/已通过/已驳回”三个列表待审核列表每条后面有“通过”和“驳回”两个操作按钮驳回的时候弹窗让填写驳回原因。用户管理页面就是一个表格加一个“禁用/启用”按钮即可。4.4 路由守卫与权限控制前端路由防不做权限控制是不行的否则用户直接手输一个/admin地址就能进管理页面了。我这里用Vue Router的全局前置守卫来做权限控制。核心逻辑很直白router.beforeEach((to, from, next) { const token localStorage.getItem(token) const role localStorage.getItem(role) if (to.path /login || to.path /register) { next() return } if (!token) { next(/login) return } if (to.path.startsWith(/admin) role ! ADMIN) { Message.error(无权限访问) next(/) return } next() })这样一来未登录用户访问任何业务页面都会被弹回登录页普通用户访问管理后台会被拦截。需要注意的是前端路由守卫只是体验层面的保护真正的安全校验还是后端拦截器那一层做的两边都要有缺一不可。5. 开发过程中踩过的坑与排查实录5.1 前后端联调时的跨域问题前后端分离开发跨域基本人人都会遇到。前端的http://localhost:5173访问后端的http://localhost:8080浏览器出于同源策略直接拦截响应报错信息里最常见的就是“CORS policy”。我开发环境的解决方案是用Vite的代理配置在vite.config.js里把以/api开头的请求转发到后端8080端口server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这样前端请求/api/articles就被代理到http://localhost:8080/api/articles浏览器看到的请求是同源的就不会触发跨域。这个方案的好处是前端代码不用写完整域名后端也不需要额外处理CORS开发体验最好。生产环境我用Nginx做反向代理同样是把/api转发到后端服务这个在部署章节一起说。5.2 时间格式、Long精度、分页插件这三个问题听起来小但每一个都能让你卡上半天。时间格式的问题表现是后端返回的时间是“2025-03-01T12:00:00.00000:00”这种带T带时区的字符串前端直接显示非常难看。我的处理方式是后端在application.yml里配置统一的JSON序列化格式spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8这样所有接口返回的时间字段都是2025-03-01 20:00:00这种格式前端的dayjs都不用额外处理了。Long精度丢失的问题是Java后端经典大坑。数据库表主键如果用自增的Long类型当值的位数超过JavaScript的安全整数范围2的53次方减1时前端拿到的数字最后几位会变成0。解决方式也很简单在实体类的主键字段上加一个注解JsonSerialize(using ToStringSerializer.class) private Long id;让后端返回给前端的时候把Long转成字符串前端展示和路由传参都不会丢精度。MyBatis-Plus的分页插件必须手动配置才能用不然调用Page方法会发现查出来的数据跟预想不一样。配置方式是在MybatisPlusConfig里注册一个分页插件Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }配置好之后Service层就可以用page(new Page(current, size), queryWrapper)这种方式来做分页查询返回的对象里自带总条数、当前页数据前端配合分页组件直接用。5.3 部署上线与前端刷新404等到项目做完我建议完整地走一遍部署流程因为答辩现场很可能不是在你自己的开发环境上演示。整个部署分四步第一步后端打包。在项目根目录执行mvn clean package -DskipTests生成可执行的jar包。然后直接在服务器上运行nohup java -jar gov-platform.jar app.log 21 确认8080端口起来。第二步前端构建。在Vue项目目录执行npm run build生成dist目录里面是静态文件。第三步配置Nginx。Nginx的作用是托管前端静态文件并把/api请求反向代理到后端服务。配置文件里的关键部分server { listen 80; server_name localhost; root /usr/share/nginx/html/dist; index index.html; location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { try_files $uri $uri/ /index.html; } }这里有一个必踩的坑Vue Router使用history模式时如果用户直接访问http://服务器地址/adminNginx会去磁盘上找admin这个文件找不到就404。所以location /里必须配置try_files $uri $uri/ /index.html让所有非静态文件的请求都回退到index.html由前端路由接管。第四步改前端接口地址。如果前端构建时用的还是/api的相对路径那部署到Nginx后根本不用改代码但如果你之前在axios里写死了http://localhost:8080部署时必须改成服务器地址否则页面能打开但数据全是“网络请求失败”。5.4 演示前的自测清单做毕业设计这几年我见过太多演示现场翻车的情况。最尴尬的不是代码报错而是老师坐在旁边看着你你连登录都登不进去。每次演示前我建议至少把下面这些场景走一遍正常注册一个新账号会收到验证成功的提示用管理员账号登录能进管理后台普通用户提交一条新问题状态是待审核在管理后台审核通过这条问题前台首页能立刻看到在问题详情页发一条回复提问者账号的个人中心能看到消息提醒刷新页面登录态还在Token有效期没到直接访问/admin会被拦截跳回首页准备一个专用的演示账号建议用户名就用“admin/admin123”这种好记的避免现场输错密码。如果演示用的是自己电脑还要确认WiFi靠谱最好准备一个手机热点作为备用别问我是怎么知道的。结尾项目做完之后我最大的体会是毕业设计这个东西难度真的不在于“技术多高深”而在于“流程是否完整”。大家都会写增删改查但能从需求分析、数据库设计、接口定义、权限控制、前后端联调一直串到部署上线这一整条链路走下来才算真正把课本上的东西用起来了。我后续如果有时间还会在这个项目基础上加一个统计图表模块用ECharts把每天的问题提交量、回复率做成可视化大屏放进管理后台首页工作量立刻又能上一个档次。也希望这篇笔记能帮正打算做SpringBoot Vue项目或者已经在做的朋友少走几步弯路代码踩坑不可怕可怕的是没人告诉你坑在哪。
返回列表