☰
基于SpringBoot+Vue3的健美操评分系统设计与实战
2026/10/1 11:58:56 网站建设 项目流程

做毕设的时候,很多人第一反应就是"图书管理系统""学生信息管理系统",一搜一大把,答辩撞车率极高。健美操评分系统这个名字听起来小众,但恰恰是这种自带明确业务规则的项目,反而更容易在答辩时讲出亮点。这套基于 SpringBoot + Vue 3 + MySQL 的健美操评分系统管理平台,覆盖了赛事管理、评委打分、实时成绩展示、排名统计这些核心场景,技术栈主流、前后端分离、业务逻辑清晰,非常适合拿来做毕业设计、课程设计,或者作为 Java 和前端入门学习的完整参考项目。

这篇文章我会把整个项目从需求拆解、数据库设计、后端接口实现、前端页面开发到联调部署讲一遍,重点是把我实际开发中踩过的坑和"为什么这样做"的逻辑讲透。不管你是准备照着做一遍,还是想从里面抽几个模块学习,都应该能有所收获。

1. 项目概述与核心业务梳理

1.1 健美操评分场景到底在解决什么问题

健美操比赛和普通的考试评分完全是两回事。考试是学生交卷老师改分,一个人改一份卷子就完事;健美操比赛是多个评委同时给一支队伍打分,而且分数维度不止一个。以常见的竞技健美操评分规则为例,评委需要分别给出艺术分、完成分、难度分,最后还要通过一套规则去掉极端值、计算最终得分。

这里面有几件麻烦事:

  • 多评委并行打分:一场比赛少则五六个评委,多则十几个,手工收集评分表效率极低。
  • 多个评分维度:每个维度的权重、计算方式不一样,纯手工算容易出错。
  • 计分规则繁琐:需要去掉最高分和最低分再取平均,还要处理同分排名等边界情况。
  • 成绩实时性要求高:比赛现场通常有大屏实时显示各队得分,纸质流程基本做不到。
  • 数据追溯困难:比赛结束后如果有队伍对成绩提出异议,得能查到是哪些评委、哪些维度出了问题。

以前很多比赛是用 Excel 收集评分表,再人工算分,我见过某个基层赛事因为算分出错,排名公布半小时后又改回来的尴尬场面。这套系统的核心价值就是把"评分-计算-排名-公示"全流程线上化,每一笔评分都有记录,每一项成绩都能追溯来源。对毕设而言,这种"有真实场景、有明确痛点"的项目,天然就比千篇一律的管理系统更适合展开讲。

1.2 为什么是 SpringBoot + Vue 这个组合

老实说,做这类项目你可以有不止一种选择,但我最终选了 SpringBoot + Vue + MySQL,理由是实际考量过的:

  • SpringBoot 生态成熟、资料量巨大:遇到任何报错基本都能搜到解决方案。它的自动配置让项目起步极快,不用像 SSM 那样写一大堆 XML 配置。这对课设和毕设的时间安排非常重要。
  • Vue 响应式和组件化:评委打分是高频率交互场景,Vue 的双向绑定让分数录入、即时校验写起来非常顺手。组件化开发也能把队列表格、打分表单、排名面板拆开维护。
  • MySQL 免费且通用:学校机房、个人电脑都能装,网上教程一抓一把,部署成本几乎为零。
  • 前后端分离是当前主流开发模式:用这套组合做完,你既练了后端接口设计,也练了前端联调,答辩时能聊的东西面儿很宽。

有人会问,为什么不用 JSP + Servlet?我的看法是:JSP 方案技术太旧,现在企业里基本见不到了,做毕设对就业的参考价值有限。还有人问为什么不用 SpringCloud 微服务,这属于典型的过度设计,一个评分系统单体架构完全够用,微服务的分布式事务、服务注册发现这些问题在答辩时反而容易把自己绕进去。

1.3 系统角色与核心业务流程

这个系统我设计了三类角色,正好对应比赛现场的三类人:

  • 管理员:负责创建赛事、配置组别、录入参赛队伍、创建评委账号、查看所有评分记录和最终排名。
  • 评委:登录后选择赛事和组别,给参赛队伍打分,可查看自己已提交的评分。
  • 观众/大屏:不需要登录,通过公开接口查看实时成绩和排名,用于现场大屏展示。

核心业务流程大概是:管理员创建赛事并设置组别 → 录入参赛队伍并分配到对应组别 → 创建评委账号并关联到赛事 → 比赛开始后评委逐队打分 → 系统实时计算成绩并推送大屏 → 比赛结束后台生成最终排名和报表。这套流程从"赛前准备"到"赛中评分"再到"赛后统计"全覆盖,每一环都能对应到具体的表结构和接口,做需求分析的时候非常好讲。

2. 数据库建模与评分规则设计

2.1 核心表结构设计

表设计是这个系统的灵魂,我前后改了三版才定下来。核心表一共五张:

用户表(sys_user)

字段类型说明
idbigint主键
usernamevarchar(50)登录账号
passwordvarchar(100)BCrypt加密后的密码
rolevarchar(20)ADMIN / JUDGE / VIEWER
real_namevarchar(50)真实姓名

这里有两个细节值得注意。第一,密码必须加密存储,我用的是 BCrypt,不能明文存库,这是很多课设项目答辩时被老师批评的重灾区。第二,评委和赛事之间的关系我放在独立的赛事评委关系表里,而不是在用户表加一个 competition_id 字段,因为同一个评委可能参与多场赛事。

赛事表(competition)

字段包括 id、赛事名称、举办地点、开始日期、结束日期、状态(0未开始/1进行中/2已结束)。状态字段很重要,它决定了评委能不能打分、大屏能不能看到成绩,前端也能根据状态切换页面展示。

组别表(category)

健美操比赛通常是分组进行的,比如小学组、初中组、高中组、大学组、社会组,不同组别评分规则可能不同。组别表挂在赛事表下面,字段有 id、赛事id、组别名称、排序号。为什么要独立建表而不是直接在赛事表里存一个组别名字段?因为一个赛事有多个组别,如果把组别存到赛事表里,改起来会非常痛苦。

参赛队伍表(team)

字段包括 id、赛事id、组别id、队伍名称、教练姓名、联系电话、出场顺序。出场顺序单独建一个 sort_order 字段,方便比赛前手动调整出场顺序,不用改队伍基本信息。

评分表(score)

这是整个系统最关键的表:

字段类型说明
idbigint主键
competition_idbigint赛事id
category_idbigint组别id
team_idbigint队伍id
judge_idbigint评委id
art_scoredecimal(4,1)艺术分
execution_scoredecimal(4,1)完成分
difficulty_scoredecimal(4,1)难度分
total_scoredecimal(4,1)三个维度总分
create_timedatetime提交时间
update_timedatetime修改时间

这里我特别想强调一个设计思路:每个评委的一次打分在 score 表里存一条独立记录,而不是只存最终平均分。为什么?因为去掉最高分最低分的规则要求系统保存所有评委的原始评分,最终成绩需要实时计算。而且赛事结束后如果有队伍对成绩有异议,管理员能清楚看到"这个队去掉的是哪两个评委的分数"。这个追溯能力,恰恰是 Excel 手工操作最容易出问题的地方。

2.2 计分规则的核心算法

健美操评分系统里最核心的算法是"去掉最高分和最低分取平均",这是国际体操和健美操赛事的通用做法,目的是避免个别评委的极端打分影响整体结果。

假设一场比赛有 5 个评委,每个评委打出一个总分,计算最终得分的逻辑是:

  1. 收集所有评委的总分。
  2. 按从小到大排序。
  3. 去掉一个最高分、一个最低分。
  4. 对剩下的分数求平均,保留两位小数。

对应的 Java 代码如下:

public BigDecimal calculateFinalScore(List<BigDecimal> scores) { if (scores == null || scores.size() < 3) { throw new IllegalArgumentException("有效成绩不足,无法计算最终得分"); } List<BigDecimal> sorted = scores.stream() .sorted() .collect(Collectors.toList()); // 去掉一个最低分和一个最高分 sorted.remove(0); sorted.remove(sorted.size() - 1); // 剩余分数求平均,保留两位小数 return sorted.stream() .reduce(BigDecimal.ZERO, BigDecimal::add) .divide(BigDecimal.valueOf(sorted.size()), 2, RoundingMode.HALF_UP); }

这个代码里有一个所有初学者都必须记住的坑:一定要用 BigDecimal,不能用 double 或 float。因为浮点数在计算机里是用二进制表示的,0.1 + 0.2 的结果不是 0.3,而是 0.30000000000000004。在比赛成绩这种精确到小数点后两位的评分场景里,用 double 做累加和除法,最后很可能出现 9.990000000000002 这样的情况。真要在答辩现场被老师指出这个问题,那基本就是从"优秀"滑到"合格"的关键失误。

另外在三个维度分别打分时,我采用了"各维度独立去掉最高最低再平均,最后汇总"的方式,比"先加总分再去掉最高最低"更符合实际赛制的评分习惯。具体用哪种规则,可以在管理员后台做成可配置项,这样也让系统显得更完整。

2.3 同分排名怎么处理

还有一个容易被忽略的点:同分排名。两个队伍最终得分完全相同怎么办?我的实现是设计了一个排名字段 rank,按以下规则计算:

  1. 先按最终得分降序排列。
  2. 若最终得分相同,按完成分(execution_score)降序排列。
  3. 若完成分仍相同,按队伍出场顺序升序排列。

这个规则在管理后台的赛事配置里可以调整,比如改成"按队伍编号排序"或"并列排名"。为什么把规则做成可配置?因为现实中不同赛事的仲裁规则不一样,写死的话遇到特殊情况就得改代码。这个设计细节在答辩时讲到"我对不同赛事规则的兼容性做了考虑"会非常加分。

3. 后端核心模块实现

3.1 项目结构与目录规划

后端我用的是 Maven 标准结构,单模块就够用了。包结构如下:

src/main/java/com/example/aerobics ├── controller // REST接口层,只做参数接收和结果封装 ├── service // 业务逻辑层,加分、算分、排名的核心逻辑在这里 ├── mapper // MyBatis-Plus的Mapper接口 ├── entity // 数据库实体类 ├── dto // 前端传来的参数对象 ├── vo // 返回给前端的视图对象 ├── config // 配置类(CORS、MyBatis-Plus分页、WebSocket等) ├── interceptor // JWT登录拦截器 ├── exception // 全局异常处理 └── common // 统一返回结果 Result、常量定义等

分层的好处不用多说,但我建议你在做的时候想一个问题:如果让你新增一个"导出成绩 PDF"的功能,你要动哪些地方的代码?答案应该是:controller 加一个接口方法,service 加一个方法,前端加一个下载按钮。如果这个改动需要你翻遍所有层才能定位,说明分层有问题。

统一返回结果我用了一个泛型类Result<T>,包含 code、message、data 三个字段。所有接口都返回这个结构,前端拦截器就能统一处理错误码,比如 401 跳登录、500 弹提示框,不用每个接口单独处理。

3.2 JWT 认证与权限控制

用户登录后,后端签发一个 JWT,前端后续请求都在请求头里带上这个 token,后端通过拦截器校验。为什么不用传统的 Session?核心原因是前后端分离之后,前端和后端可能部署在不同的端口甚至不同的服务器上,Session 的跨域和共享问题处理起来很麻烦。JWT 是无状态的,后端不用保存登录状态,扩展性也好。

JWT 的配置我建议这样:

jwt: secret: your-256-bit-random-secret-key expiration: 7200000 # 2小时,单位毫秒

密钥长度至少要 256 位,而且不能直接写在代码里写死"123456",应该放到配置文件里,正式环境用环境变量注入。过期时间我设置的是 2 小时,因为比赛期间评委可能长时间停留在打分页面,时间太短会频繁被踢下线,但也不能太长,否则安全性没有保障。

拦截器的实现逻辑:

public class JwtInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录接口和公开查询接口 if (request.getRequestURI().contains("/api/auth/login")) { return true; } String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); } // 校验token,解析失败则返回401 try { Claims claims = JwtUtil.parseToken(token); request.setAttribute("userId", claims.get("userId")); request.setAttribute("role", claims.get("role")); return true; } catch (Exception e) { response.setStatus(401); return false; } } }

这里要注意:拦截器要排除登录接口、大屏公开查询接口、以及日常开发要用的接口文档路径。否则你在测试登录接口时会一直被 401 拦截,排查半天才发现是拦截器把自己的登录接口也拦了,这个坑我踩过。

权限控制我用的是最朴素的方式:在拦截器里解析出角色,接口层通过自定义注解或者手动判断当前用户角色来决定是否放行。管理员接口打一个 @RequireAdmin 注解,评委接口必须校验当前登录用户确实关联到该赛事,否则返回 403。这个"业务级权限校验"比单纯角色判断更难写,但也更能体现思考深度。

3.3 打分接口与成绩计算实现

打分是整个系统使用频率最高的操作,接口设计要简单直接:

@PostMapping("/api/score/submit") public Result<?> submitScore(@RequestBody ScoreSubmitDTO dto) { // dto 包含 competitionId、categoryId、teamId、judgeId、 // artScore、executionScore、difficultyScore、totalScore return scoreService.submitScore(dto); }

打分接口的核心逻辑有几步:

  1. 校验当前赛事状态是否为"进行中",不是则拒绝打分。
  2. 校验该评委是否被分配到这个赛事。
  3. 校验分数范围(0-10 分,合法分数到 0.1 精度)。
  4. 判断该评委是否已给该队伍打过分数,若已打过则走更新逻辑。
  5. 保存或更新评分记录。

有一个容易踩坑的细节:评委提交后发现打错了,怎么办?我采用的方案是"可修改但有痕迹"。评委在比赛结束前可以修改自己的打分,score 表里 update_time 会更新,同时我在审计日志表里记录修改前后的分数。比赛结束后赛事状态变为"已结束",打分接口直接拒绝提交。这样既保证了灵活性,也为成绩争议提供了追溯依据。

3.4 成绩发布与实时推送

比赛现场的成绩展示要求实时性。最传统的方案是前端轮询,每 3 秒请求一次成绩接口。这个方案实现简单,毕设完全够用。但如果你想让系统更有含金量,建议引入 WebSocket 或者 SSE,后端在成绩变化时主动推送新数据到前端大屏。

我当时用的是 SpringBoot 自带的 WebSocket,逻辑不复杂:评委提交分数后,后端计算该队伍的最新有效评分和排名,然后通过 WebSocket 推送到 /topic/score 频道,大屏页面订阅这个频道,收到消息后自动刷新。相比轮询,这个方案实时性更高、对服务器压力更小,而且在答辩现场演示"评委提交后大屏秒级更新"的效果非常直观。

4. 前端页面开发与交互

4.1 前端项目结构与路由设计

前端我用的是 Vue 3 + Vite + Element Plus。如果你用 Vue 2,那就配 Element UI,两者选一个就行,不要混用。项目结构如下:

src/ ├── api/ // axios请求封装 │ ├── request.js // axios实例,拦截器统一处理token和错误 │ ├── auth.js // 登录相关接口 │ └── score.js // 打分、成绩、排名接口 ├── router/ // 路由配置 ├── store/ // Pinia状态管理 ├── views/ │ ├── login/ // 登录页 │ ├── admin/ // 管理员:赛事管理、组别管理、队伍管理、评委管理 │ ├── judge/ // 评委:赛事选择、打分页 │ ├── scoreboard/ // 大屏:实时成绩展示 │ └── report/ // 报表:ECharts统计图表 └── components/ // 公共组件:赛事选择器、队伍表格、分数输入组件等

路由设计的核心是权限。不同角色登录后看到的菜单和页面应该不一样,我用的是动态路由方案:用户登录后根据角色从后端拉取可访问路由列表,通过router.addRoute动态注册。如果没有做动态路由,至少也要在路由守卫里做静态的角色判断:

router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') const role = localStorage.getItem('role') if (to.path === '/login') { next() } else if (!token) { next('/login') } else if (to.meta.role && to.meta.role.indexOf(role) === -1) { next('/403') } else { next() } })

4.2 核心页面拆解:打分页、成绩大屏

打分页是这个系统交互要求最高的页面。评委的操作场景是:比赛现场很吵、节奏很快,评委要快速找到当前出场的队伍,快速输入分数并提交。所以打分页的设计有几个原则:

  • 队伍信息要醒目:当前打分队伍的名称、组别、出场顺序要放在页面最显眼的位置。
  • 输入框要大:分数输入用大号数字输入框,支持键盘快速操作。
  • 提交防误触:提交按钮要做二次确认弹窗,防止点错。

分数输入组件我用的是 Element Plus 的el-input-number,设置:min="0" :max="10" :step="0.1",确保评委不会输入超出范围的分数。同时在前端做一次校验:三个维度分数都合法才能提交,避免无效请求打到后端。

成绩大屏页是展示系统逼格的核心页面。我用深色背景、大号字体显示队伍排名和得分,顶部轮播显示各组别当前前三名。技术上如果用了 WebSocket,大屏就是实时刷新的;如果用轮询,建议用setInterval每 3 秒拉一次成绩。轮询要注意页面销毁时清除定时器,否则切走后定时器还在后台跑,白白消耗资源。

4.3 Axios 封装与接口联调

前端所有请求都走一个 axios 实例,统一配置 baseURL 和拦截器。开发环境我用 Vite 的代理解决跨域问题:

// vite.config.js export default { server: { proxy: { '/api': { target: 'http://localhost:8080', // 后端地址 changeOrigin: true } } } }

这个配置的意思是:前端请求/api/xxx时,Vite 开发服务器会把这个请求转发到http://localhost:8080/api/xxx。这样前端代码里不需要写完整的后端地址,也避免了浏览器直接跨域请求后端的问题。

请求拦截器统一加 token:

http.interceptors.request.use(config => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config })

响应拦截器统一处理业务码和 HTTP 错误码,比如 401 清空本地 token 并跳转登录页,500 弹出错误提示。这样做的好处是:所有页面的错误处理逻辑统一,不用在每处调接口的地方重复写 try/catch。

5. 环境搭建与部署要点

5.1 开发环境准备

做这个项目之前,先把环境准备好,版本问题可以少一半:

  • JDK:SpringBoot 2.7.x 用 JDK 8 或 JDK 11,SpringBoot 3.x 需要 JDK 17。做毕设建议用 SpringBoot 2.7.x + JDK 8,网上资料最多,遇到报错最容易搜到答案。SpringBoot 3.x 把 javax 包名换成了 jakarta,很多老代码直接复制过来会报编译错误,新手容易被折腾崩溃。
  • Maven:3.6 以上即可。
  • MySQL:5.7 或 8.0 都可以。8.0 的驱动类名是com.mysql.cj.jdbc.Driver,连接 URL 要加时区参数,比如jdbc:mysql://localhost:3306/aerobics?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8。不加时区参数会报The server time zone value '�й���׼ʱ��' is unrecognized这类错误,看着像乱码,实际是时区问题。
  • Node.js:16 以上,npm 或 pnpm 都行。前端依赖安装慢的话,可以配置 npmmirror 镜像源,十分钟能省。

5.2 项目快速跑起来的完整步骤

  1. 新建数据库,比如aerobics,执行项目里的sql/init.sql,创建表结构并插入管理员账号和测试数据。
  2. 打开后端项目,修改application.yml里的数据库地址、账号、密码,改成自己的。
  3. 在 IDEA 里运行AerobicsApplication.java的主方法,或者在项目根目录执行mvn spring-boot:run,看到 Tomcat started 说明后端启动成功,默认端口 8080。
  4. 打开前端项目,执行npm install安装依赖,然后npm run dev启动开发服务器,默认端口 5173(Vite)。
  5. 浏览器访问http://localhost:5173,用管理员账号登录(比如 admin / 123456),创建一场赛事、录入队伍,再创建评委账号,切到评委账号打分,大屏页查看实时成绩。

整个流程走通后,你基本就把这个系统的全貌掌握了。

5.3 初始化数据怎么做比较省事

每次手动往数据库里插测试数据很烦,我建议用 SpringBoot 的CommandLineRunner或者直接在init.sql里写死初始数据。比如给管理员账号、三个测试评委账号、两支测试队伍,这样项目启动后就能直接登录体验,不用手动敲 SQL。

但要注意:初始化数据的逻辑要写清楚哪些是"演示数据",正式部署上线时要删掉或改为不自动插入,否则真实赛事的数据和演示数据混在一起,后期清理很麻烦。

6. 常见问题与排查经验

6.1 前后端联调阶段的高频问题

我把自己在开发过程中真实遇到过的、以及帮学弟学妹排查过的问题整理成了表格,对着找基本能对症下药:

现象可能原因解决办法
前端请求一直 404Vite 代理没配,或后端接口路径和前端不一致检查 vite.config.js 的 proxy 和接口路径
登录接口 500MySQL 连接失败、驱动类名错误、时区配置缺失检查 application.yml 的 URL、驱动、serverTimezone
返回中文乱码数据库连接没加 characterEncodingURL 加useUnicode=true&characterEncoding=utf8
请求能通但返回 401token 过期、拦截器没放行登录接口检查 JWT 过期时间和拦截器排除路径
前端页面跨域报错没用 Vite proxy,直接请求了后端地址用代理,或后端配 CorsFilter
改了后端代码前端无变化前端代理缓存了旧配置重启 Vite dev server 或强制刷新
启动端口被占用8080 被其他进程占用改 server.port,或杀掉占用进程
npm install 慢到怀疑人生默认源在国外配置 npmmirror 镜像

6.2 评委并发打分时最容易忽略的问题

比赛场景里多个评委是同时在打分,这就带来了并发问题。比如两个评委同时给同一支队伍提交分数,如果后端不做控制,可能出现数据覆盖。

我的方案是:submitScore 方法加事务,并且同一评委对同一队伍的打分执行 upsert(存在即更新,不存在即插入)。数据库层面给(team_id, judge_id)加了唯一索引,从根上避免重复插入。

还有一个小坑:成绩计算需要读取所有评委的评分,如果在一个评委提交分数的同时另一个评委也在提交,计算时可能读到不完整的数据。所以最终成绩的计算我放在了查询时实时计算,而不是在每次打分后写入一个固定的"最终成绩字段"。这样虽然多了一点计算开销,但避免了并发更新的数据一致性问题。对毕设规模的数据量来说,这点性能损耗完全不是问题。

6.3 大屏数据刷新的性能问题

如果用的是轮询方案,要注意一个细节:成绩大屏页面可能有多个组件同时拉数据,比如排名组件、得分组件、队伍列表组件,如果每个组件各自 setInterval 拉接口,请求数量会翻倍。我的做法是:父组件统一拉取数据,通过 props 分发给子组件,或者用 Pinia 存一份全局成绩状态,这样大屏刷新只需一个定时器。

另外轮询间隔不建议小于 2 秒,太频繁会给数据库带来不必要的压力。如果用的是 WebSocket 推送,则不存在这个问题,这是推荐做 WebSocket 的另一个理由。

7. 个人实操心得与扩展方向

做完这个项目,我最大的体会是:一个评分系统的难点从不在于"登录"和"增删改查",而在于业务规则的严谨性和数据的一致性。去掉最高最低分的算法写起来只有十几行,但为了想清楚"同分怎么办""打错了怎么改""并发提交怎么防覆盖"这几个问题,我翻了不少赛事规则文档,也改了好几版设计。

对准备拿这个项目做毕设或课设的同学,有几点建议:

  • 数据库表设计一定要花足够时间想清楚。表设计错了,后面所有代码都是推翻重来。我第一版把评委和赛事的关系放在用户表里,后来发现一个评委可以参加多场比赛,只能改表结构,连带改了一堆代码。
  • 答辩时不要只讲"我用了 SpringBoot 和 Vue",要讲清楚"我的系统解决了什么真实问题、评分规则是怎么设计的、并发和数据一致性是怎么处理的"。这些才是体现专业度的地方。
  • 项目的扩展方向很多,我列几个你可以继续做的点:接入 MinIO 做比赛视频上传和回放,给争议判罚提供视频证据;用 WebSocket 替代轮询做实时推送;增加 Excel 导出功能,比赛结束一键生成成绩单;用 Docker 打包部署到服务器,让评委通过浏览器远程打分。

如果只是学习用,我建议你也不要只照着抄代码,而是自己从头把建表 SQL 写一遍,把打分接口自己实现一遍,遇到不会的再看参考代码。这个项目的技术栈和学习路径都很常规,照着敲一遍能巩固 SpringBoot 的接口开发、MyBatis-Plus 的数据库操作、Vue 的组件通信、axios 的请求封装这些核心技能,比只看不做要扎实得多。把它彻底吃透,后面再接触更复杂的项目,很多思路都是通用的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询