尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

基于SpringBoot+Vue的幼儿园管理系统:从权限设计到部署实战

发布时间:2026/9/26 18:55:18

资讯中心
01
ARTICLE

基于SpringBoot+Vue的幼儿园管理系统:从权限设计到部署实战

基于SpringBoot+Vue的幼儿园管理系统:从权限设计到部署实战
说实话像“基于springboot vue幼儿园管理系统”这种项目网上搜源码一抓一大把但真正能落地跑通、逻辑完整、拿来就能交作业或者用在园所里的其实不多。市面上大量开源版本存在同一个问题代码堆得很满业务却简单到只能算个“幼儿信息表格”要么就是前端页面漂亮后端接口一塌糊涂部署时各种报错。这几个月我前后帮几个朋友处理过这套系统的二次开发和部署也自己从头梳理过一个可复现的完整版本涵盖了源码结构、数据库脚本和配套说明文档。今天准备把整个项目的核心设计、关键模块实现、数据库表结构、部署踩坑全流程整理成一篇实操笔记给正在做课程设计、毕业设计或者想给幼儿园做信息化改造的朋友一个可以直接参考的“作业答案”。这套系统适合谁一句话说清楚适合需要快速交付一个前后端分离、具备完整业务闭环幼儿档案、班级管理、晨检考勤、缴费通知、教职工管理的人。下面我直接按从设计到部署的顺序来拆。1. 业务拆解一套管理系统的核心设计思路1.1 角色权限系统的“地基”做管理系统第一步不是写登录而是把“谁会用什么功能”想清楚。幼儿园系统的核心角色通常有五类超级管理员一般是园长或系统维护者、行政/教务、教师、保健医、财务。家长这个角色严格来说不算后台用户更多偏前端/小程序端查看。不同角色能看到的菜单和数据范围完全不同所以权限模型必须一开始就搭好。我整理后的权限模型用最经典的 RBAC基于角色的访问控制方案用户表、角色表、菜单/权限表、用户角色关联表、角色菜单关联表五张表。前端根据当前登录用户的角色动态生成路由菜单后端接口用注解做接口粒度的权限校验。这样做的好处是新来一个老师只要给她的账号绑定“教师”角色她就自然拥有排课、点名、录晨检的权限而不会看到财务的缴费统计也不用改任何代码。这里有一个很关键的取舍很多简单系统会把“权限”做死在代码里比如判断if(admin.equals(username))这种写法确实省事但一换人员就抓瞎。课程设计或者小园所里RBAC表确实能在“可交作业”和“真实可用”之间平衡得最好。1.2 功能模块规划从“记台账”到“管业务”幼儿园管理系统的核心不是管理“幼儿”这一个对象而是围绕幼儿产生的整个业务链条。我按优先级把功能分成三批第一批是刚需模块基础版就能跑幼儿档案入园登记、家长信息、身体状况、所在班级、照片上传班级管理年级、班级的新增编辑、班级人数统计教职工管理教师信息、任课班级、联系方式考勤管理幼儿每日入园/离园记录支持手动补录公告通知园方发布消息家长端可见第二批是提效模块进阶版晨检记录体温、手口、精神状态检查异常自动预警缴费管理费用项配置、账单生成、缴费状态跟踪体检疫苗记录常规体检数据、疫苗接种时间提醒食谱管理每周食谱发布家长端能看第三批属于加分项校车定位、实时监控对接、请假审批流、异常统计报表等。说实话把这些都做出来工作量不亚于一个小型 SaaS 项目。我给大多数朋友的建议都是优先保证第一批功能闭环做好看做完整个增删改查流程再根据精力决定是否加第二批。实际交付的作业/园所项目中晨检和缴费往往是老师最关心的这两个模块建议优先做。1.3 前后端职责划分既然是 springboot vue 的前后端分离架构就要明确各自的职责后端只提供数据接口负责权限校验、业务逻辑处理、数据库交互不关心页面长什么样。前端负责路由跳转、页面渲染、表单校验、调用接口渲染数据。换句话说后端是“厨房”把菜做好装盘前端是“服务员”负责把菜端到顾客面前。顾客园长/老师/家长不会直接进厨房抢菜浏览器也永远不会直接连数据库——所有数据都通过 JSON 在前后端之间来回传。有个容易犯的错误把大量业务逻辑写在前端比如在前端计算幼儿年龄、判断缴费状态。看起来响应挺快但换一个浏览器或者绕过页面直接调接口整个逻辑就崩了。正确做法是前端只做展示和交互真正的计算、判断、状态流转必须放后端。2. 技术选型解析为什么是 Spring Boot Vue 这套组合2.1 后端Spring Boot 的生态优势Spring Boot 在这个项目里几乎是“标准答案”因为它的自动配置机制能把大量繁琐的 Spring 配置直接省掉。比如你要连 MySQL只要在 pom 里加一个spring-boot-starter-data-jpa或者mybatis-plus-boot-starter再在application.yml里写上数据源地址就能直接跑起来。我实测下来配合 MyBatis-Plus 做单表 CRUD效率极高。MyBatis-Plus 的BaseMapper自带selectById、insert、updateById、selectPage这些方法你几乎不用写 SQL单表操作直接调用就行。多表查询再写自定义 XML 或注解 SQL这样代码量能砍掉至少三分之一。这里额外说一个容易被忽视的点统一返回体。前后端分离项目里接口返回格式如果不统一前端解析会非常痛苦。我习惯的处理方式是封装一个ResultT类包含code、msg、data三个字段成功返回code: 200业务异常返回code: 500并在msg里写明原因。所有 Controller 的方法都返回Result配合全局异常处理器RestControllerAdvice前端只需判断code是否为 200 就能决定下一步操作。这个小设计能让联调少吵九九八十一次架。2.2 前端Vue 2 还是 Vue 3Element UI 还是 Element Plus这是很多做毕设的同学最纠结的问题。我的建议是如果你用的是现成模板比如基于 Vue 2 Element UI 的后台管理模板不要因为“想尝新”非要升到 Vue 3。原因很简单这套项目的核心目标是业务闭环和稳定运行不是技术尝鲜。网上现成的 Vue 2 Element UI 管理后台资源极其丰富踩坑求助好找到人Element UI 组件稳定文档齐全。如果你是纯手工从零搭前端那建议直接上 Vue 3 Vite Element Plus。原因也很简单工程构建更快Composition API 写逻辑更清爽Element Plus 还在持续维护。最关键的是Vue 3 是当前主流写出来在简历上更好看。实际项目里我强烈推荐用 Vue 2 Element UI 的管理后台模板快速起手因为在 Vue 2 下坑少。如果项目要求必须 Vue 3那就注意this.$set这类写法没了响应式用reactive/ref替代v-model绑定方式没变路由用法基本一致。无论哪种版本核心其实是前端的路由权限控制和状态管理这部分我会在第三节详细讲。2.3 开发环境与初始工程结构我在完整部署这套系统时开发环境是JDK 1.8Spring Boot 2.x 用 8 完全够用不用硬上 17Maven 3.6建议配阿里云镜像不然第一次拉依赖会等到怀疑人生MySQL 5.7 或 8.0含数据库脚本文件导入后直接改账号密码Node.js 14Vue2 环境建议 Node 14Vue3Vite 建议 Node 16IDEA后端 VS Code前端组合也可以全程 IDEA后端项目结构我通常这样规划controller接口层、service业务逻辑、mapper数据库操作、entity实体类、config配置类、common通用返回体、异常处理。前端则是views页面组件、router路由、store状态管理、api接口封装。这套结构也是在接手别人源码时最希望对方能遵守的目录规范——结构清晰的项目二次开发起来舒服太多。3. 核心功能实现的实操细节从登录到业务闭环3.1 登录认证与权限校验JWT 怎么用才不出错登录功能几乎所有系统都有但实现细节决定它好不好用。我这里采用 JWTJSON Web Token方案用户登录成功后后端用密钥生成一个 token 返回给前端前端把 token 存在localStorage或Vuex每次请求时放在请求头Authorization字段里后端通过拦截器统一校验token 有效则放行无效则返回 401前端收到 401 自动跳转登录页。这里有几个非常值得注意的实操细节第一密码绝不允许明文存储。必须用BCryptPasswordEncoder做哈希加密。BCrypt 加密的特性是即使两个用户密码明文相同加密后的密文也不同它自带盐值而且计算成本可控远比 MD5 加盐更安全。在 Spring Boot 里用new BCryptPasswordEncoder().encode(password)生成密文校验时用.matches(rawPassword, encodedPassword)即可。第二token 过期时间要合理设置。我一般设为 24 小时太短老师用着用着就掉线太长有安全隐患。如果需要“记住我”功能可以额外给一个 refresh token这个作为扩展点基础版不用做。第三拦截器要做两件事鉴权token 合法吗和鉴权后的用户身份获取。我通常在验证 token 后把用户 id 塞进request.getAttribute(userId)后续查询数据时拿这个值做数据范围过滤。3.2 幼儿档案不仅仅是“增删改查”幼儿档案模块看起来是标准的 CRUD但其实有几个点很容易做砸照片上传。我之前接过一个源码上传用的是前端 base64 转字符串直接存数据库longtext字段。这样做确实省事但数据库瞬间膨胀查询也变慢。正确做法是后端接收MultipartFile将文件保存到本地磁盘指定目录或者云存储数据库只保存文件的访问 URL 路径。本地做法在配置文件里设置一个上传路径比如file.uploadPath D:/upload/返回给前端的则是http://localhost:8080/upload/xxx.jpg这种可访问地址需要再配一个静态资源映射。幼儿年龄的自动计算。很多源码会把年龄写死成一个字段结果孩子过完生日年龄还是旧的非常尴尬。正确设计是数据库只存出生日期birth_date展示层根据当前日期实时计算年龄后端返回一个计算好的age字段也可以但存储层不该有冗余的年龄字段。证件号码唯一性校验。幼儿身份证号或护照号有的孩子没有中国户口在同一个园所内应该唯一新增和编辑时都要校验否则一人多档案没法做考勤和缴费统计。我用的是查询时排除当前 id 的方式简单可靠。家长信息。很多版本把家长名字和电话直接写在幼儿表的两个字段里一孩一档没问题但“双胞胎在同一所园”就麻烦了——两个孩子要录两遍家长手机号。业务上可扩展为家长独立表此时得多做一步幼儿表和家长表多对一。基础版可以先不做但你心里要知道这是后续接口升级的潜在点。3.3 晨检与考勤让数据产生管理价值晨检是幼儿园每天早晨进门必做的流程保健医要给每个孩子量体温、看手、看口腔、看精神状态。电子化以后这些记录会成为园所管理者判断班级健康趋势的重要数据。我的实现思路是晨检记录表health_check字段包含幼儿 id、班级 id、晨检日期、体温、口腔检查正常/异常、手部检查正常/异常、精神状态正常/萎靡、备注。保健医在晨检页面按班级筛选幼儿逐条录入保存时自动带上当前日期。如果出现体温超过 37.3℃ 或其他异常项系统会自动标记该日为异常并展示在管理端的“今日异常统计”卡片上。这里有个小经验晨检页面不要让保健医先挑日期再录默认取当前日期并锁定因为晨检本质是“当日实时”操作减少一个选择步骤能让每天的录入速度快很多。如果确实漏录了再提供“补录”入口限制只能补最近 3 天。考勤逻辑类似每天早上家长送孩子到园时老师在考勤页面点“入园”下午点“离园”判断方法是当前所在班级是否与幼儿档案一致。实际数据落表为attendance表字段包括幼儿 id、班次、日期、入园时间、离园时间。日报表直接按DATE_FORMAT(attendance_date, %Y-%m-%d)分组统计非常稳。3.4 缴费管理把“催费”从电话里解放出来缴费模块的核心表是bill账单号、幼儿 id或家长手机号、费用项目、金额、账单月份、缴费状态未缴/已缴、缴费时间、备注。费用项配置表可以预置保教费、餐费、校车费、材料费等每月由管理员点击“生成当月账单”系统自动为所有在园幼儿按费用项生成账单。家长端看到账单明细线下转账后财务在后台标记“已缴”或者未来接支付接口自动回调。这里要注意金额字段的数据库类型。千万不能用varchar存金额也不要用float/double浮点数在计算时会出现 0.10.2 不等于 0.3 的经典问题。正确做法是用DECIMAL(10,2)类型Java 实体对应BigDecimal这样在做金额汇总时精度才有保证。这是很多网上教爬代码的博主根本不提的细节但实际运行长短就看这类东西。3.5 家长端消息触达是这个系统的灵魂说句实在话园所老师最烦的就是一个个打电话通知事情。所以公告通知模块虽然是“基础功能”却是家长端打开率最高的功能。我在前端做了一个“班务通知”页面管理员/老师发布通知时选择接收范围全体、某个年级、某个班级保存到notice表字段包括标题、内容、发布人、接收范围、发布时间、是否置顶。家长端登录后接口只返回当前家长所有孩子的班级相关的通知实现方式就是一个多表关联查询noticejoin 班级表再关联幼儿表尾部带“signal”标记即可。这里留的扩展点是小程序或微信公众号模板消息代码里预留一个push_status字段和异步推送接口等接微信模板消息时只需要调一次接口即可不需要改表结构。4. 数据库设计表结构与建表 SQL 实战4.1 核心数据表清单数据库是整个系统的“账本”表结构设计不好后面所有代码都别扭。我这里给出核心表的清单和用途全部是实际交付验证过的结构表名用途关键字段sys_user系统用户管理员、老师、保健医、财务username, password, real_name, phone, role_id, statussys_role角色role_name, role_code, remarksys_menu菜单/权限menu_name, parent_id, path, component, permssys_user_role用户角色关联user_id, role_idsys_role_menu角色菜单关联role_id, menu_idkindergarten_class班级class_name, grade_name, head_teacher_id, student_count, remarkstudent幼儿档案student_no, name, gender, birth_date, id_card, class_id, father_name, father_phone, mother_name, mother_phone, address, enroll_date, photo, statusstaff教职工staff_no, name, gender, phone, position, entry_date, statusattendance考勤student_id, class_id, attendance_date, in_time, out_time, status, remarkhealth_check晨检记录student_id, class_id, check_date, temperature, mouth, hand, spirit, result, remarkbill缴费账单bill_no, student_id, fee_item, amount, bill_month, status, pay_time, remarknotice公告通知title, content, publisher_id, target_type, target_class_id, create_time, is_top这里有意识地保持表的垂直拆分一张表负责一件事不把晨检塞进考勤表不把缴费塞进幼儿表。这样的好处一是历史记录可以无限积累而不影响主表查询二是统计报表直接查询对应表即可不用join一长串。4.2 幼儿表和晨检表的建表 SQL 参考很多人拿到源码后第一步就是导入 sql 文件但根本不看表结构遇到问题就抓瞎。我把两个最核心的表 SQL 贴出来方便你理解字段含义CREATE TABLE student ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键, student_no varchar(32) NOT NULL COMMENT 学号/档案编号, name varchar(64) NOT NULL COMMENT 幼儿姓名, gender tinyint(1) DEFAULT 1 COMMENT 性别 1男 2女, birth_date date DEFAULT NULL COMMENT 出生日期, id_card varchar(32) DEFAULT NULL COMMENT 证件号码, class_id bigint(20) DEFAULT NULL COMMENT 班级ID, father_name varchar(64) DEFAULT NULL COMMENT 父亲姓名, father_phone varchar(20) DEFAULT NULL COMMENT 父亲电话, mother_name varchar(64) DEFAULT NULL COMMENT 母亲姓名, mother_phone varchar(20) DEFAULT NULL COMMENT 母亲电话, address varchar(255) DEFAULT NULL COMMENT 家庭住址, enroll_date date DEFAULT NULL COMMENT 入园日期, photo varchar(255) DEFAULT NULL COMMENT 头像URL, status tinyint(1) DEFAULT 1 COMMENT 状态 1在园 0离园, remark varchar(255) DEFAULT NULL COMMENT 备注, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), KEY idx_class_id (class_id), KEY idx_id_card (id_card) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4 COMMENT幼儿信息表;CREATE TABLE health_check ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键, student_id bigint(20) NOT NULL COMMENT 幼儿ID, class_id bigint(20) DEFAULT NULL COMMENT 班级ID, check_date date NOT NULL COMMENT 晨检日期, temperature decimal(4,2) DEFAULT NULL COMMENT 体温, mouth tinyint(1) DEFAULT 1 COMMENT 口腔 1正常 2异常, hand tinyint(1) DEFAULT 1 COMMENT 手部 1正常 2异常, spirit tinyint(1) DEFAULT 1 COMMENT 精神状态 1正常 2异常, result tinyint(1) DEFAULT 1 COMMENT 晨检结果 1正常 2异常, remark varchar(255) DEFAULT NULL COMMENT 备注, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), KEY idx_student_date (student_id, check_date), KEY idx_class_date (class_id, check_date) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4 COMMENT晨检记录表;建表有三个通用原则一是所有表必须有主键最好bigint auto_increment二是时间字段统一datetime记录创建时间用默认值CURRENT_TIMESTAMP更新时间用ON UPDATE CURRENT_TIMESTAMP这样你不用在代码里手动维护一劳永逸三是字符集统一utf8mb4因为它能存 emoji 表情万一家长备注里写了特殊符号也不会报错。4.3 数据库设计里的几个“坑”我处理过的源码里遇到最多的表设计问题如下软删除 vs 物理删除。幼儿离园后如果直接 DELETE 掉之前所有的考勤、晨检、缴费记录都会失去关联统计报表直接乱套。正确做法是增加status字段0 代表离园/禁用1 代表在园/启用。查询时默认过滤status 1但底层数据都还在。需要恢复时直接改状态即可。这个设计看着不起眼却是系统能持续跑下去的关键之一。时间冗余字段。有些表把year、month单独作为字段存比如考勤表存year 2024month 06。这确实让统计查询非常爽但容易出现数据不一致老师补录 6 月 30 日的数据代码忘了更新month统计就错位了。我建议基础版不要单独存年月字段直接用attendance_date这个 date 类型字段查询时用DATE_FORMAT函数处理。如果数据量大了再考虑加冗余字段并配合定时任务保证一致。逻辑外键 vs 物理外键。很多课程设计要求用外键约束但实际生产我建议不建物理外键只建普通索引。原因很简单物理外键在删除父表数据时会校验子表容易报错且性能变差而逻辑外键只需要在字段上建普通索引关联关系靠代码保证。面试时能说清楚这个取舍反而是加分项。5. 环境搭建、项目启动与部署实操5.1 拿到源码后第一步做什么很多朋友拿到源码第一步就急着启动结果一上来就是白屏、报错心态直接崩掉。正确顺序应该是先看 README如果有或者项目根的介绍文档搞清楚版本要求。导入数据库用 Navicat 或命令行执行源码里的 sql 文件确认表数量和核心表结构。改配置文件application.yml里的数据库账号密码、端口号、文件上传路径改成自己环境的值。启动后端用 IDEA 打开后端代码等 Maven 下载完依赖运行主类。看到 “Started ... in X seconds” 说明后端 OK。启动前端npm install这一步在node_modules没有时才需要然后npm run serve或npm run dev浏览器访问前端地址。这个顺序最大的好处是先把基础环境验证通过再深入业务代码和二次开发。如果一上来就改代码错了都不知道是配置问题还是代码问题。5.2 后端配置文件的几个必改项在application.yml里我最关心的配置项是这几个server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/kindergarten?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghai username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: map-underscore-to-camel-case: true global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0 file: uploadPath: D:/upload/ jwt: secret: your-secret-key-change-me expire: 86400有几个细节解释一下serverTimezoneAsia/Shanghai一定要加不然 MySQL 驱动连接时区和本地不一致时间查询会差 8 小时。map-underscore-to-camel-case开启后数据库字段id_card能自动映射到实体的idCard省掉大量TableField注解。上传路径和后端静态资源映射要对应不然前端能看到接口返回的路径但浏览器 404。5.3 前端路由和请求封装前端项目的核心文件是router/index.js和api/request.js。路由要做两个事情基础路由登录页和带布局的页面路由。权限控制在路由守卫beforeEach里做判断本地有没有 token没有就让登录有 token 但没有用户信息就调用接口拉取用户信息和动态菜单。请求封装推荐用 axios 实例统一 baseURL 指向后端。我给一个简化版封装很多项目里就是靠这个拦截器解决 90% 的接口问题import axios from axios import { Message } from element-ui import router from ../router const service axios.create({ baseURL: process.env.VUE_APP_BASE_URL || http://localhost:8080, timeout: 10000 }) service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] token } return config }) service.interceptors.response.use( response { const res response.data if (res.code 200) { return res } else if (res.code 401) { localStorage.removeItem(token) router.push(/login) return Promise.reject(res) } else { Message.error(res.msg || 请求失败) return Promise.reject(res) } }, error { Message.error(网络异常请稍后重试) return Promise.reject(error) } ) export default service这里易坑的是很多源码的后端返回字段不是data而是result或者成功码不是 200 而是 0。拿到源码第一件事就是看接口实际返回的 JSON 长什么样然后对着改前端封装。中间换字段名的代价比想象中大得多。5.4 生产部署的两种常见方案生产环境不推荐用前端npm run serve那套开发模式正确姿势是前端构建成静态文件由 Nginx 托管后端打成 jar 包后台运行。方案一简单直接前端执行npm run build生成dist目录。把dist里所有文件传到服务器/usr/share/nginx/html/。后端执行mvn clean package -DskipTests得到 jar用nohup java -jar xxx.jar log.txt 21 启动。Nginx 配置监听 80 端口location /指向前端目录location /api/做反向代理转发到http://127.0.0.1:8080/。方案二Docker 部署 写一个Dockerfile构建后端镜像再用nginx.conf和docker-compose.yml把前端、后端、MySQL 三个服务编排起来。这个方案优点是一键启动、环境隔离缺点是初次配置踩坑多。如果是交作业方案一足够如果是真实项目交付方案二更有说服力。部署时最容易出现的问题就是静态文件路由刷新 404。因为 Vue 是单页应用路由走 history 模式刷新一个深层路径时 Nginx 找不到对应文件。解决方案是location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; }这行配置的含金量很高能解决 90% 的刷新白屏问题。如果你用的是 hash 路由则没有这个问题但 URL 里会有#不太好看。6. 常见问题排查与踩坑实录6.1 数据库连接失败这种问题在换电脑、换环境后出现频率最高。先别急着怀疑代码按顺序排查MySQL 服务有没有启动Windows 上用命令net start mysql或看服务面板Mac 上用brew services list。账号密码对不对用 Navicat 或命令行mysql -u root -p试连一下很多源码默认密码是123456你自己机器可能不是。application.yml里 url 的库名是否存在有朋友建了库叫kindergarten_db配置里写kindergarten提示数据库不存在。依赖的驱动版本和 MySQL 版本匹配吗MySQL 8 用com.mysql.cj.jdbc.DriverMySQL 5.7 可以用com.mysql.jdbc.Driver但前者也兼容注意useSSLfalse参数否则会有警告但不影响连接。6.2 前端页面能打开但接口全部 404 或跨域报错这类问题的根源往往是前后端接口地址没对齐。你在浏览器 F12 打开网络面板看请求的 URL 是http://localhost:8080/api/xxx还是http://localhost:3000/api/xxx跟你后端实际访问地址对不对得上。跨域问题如果前后端不在同一端口必然会出现。后端解决跨域的经典配置是写一个CorsConfig类实现WebMvcConfigurer的addCorsMappings字段 setallowedOrigins(*)。但如果同时用了 Spring Security跨域配置要把.cors()一起加上不然拦截器先返回 401跨域配置根本没有执行机会请求就被干掉了。6.3 上传文件失败或访问图片 404先看后台上传时控制台报什么错。常见的是上传目录不存在服务器没有自动创建该路径手动创建一下即可。然后是前端的图片地址问题后端返回的是相对路径/upload/xxx.jpg你在页面标签里写了img srchttp:localhost:8080/upload/xxx.jpg浏览器直接请求后端端口这时需要后端做静态资源映射。在 Spring Boot 里加一个配置类Configuration public class WebConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String uploadPath file: System.getProperty(user.dir) /upload/; registry.addResourceHandler(/upload/**).addResourceLocations(uploadPath); } }如果搞不懂绝对路径和相对路径的区别就记住数据库中存的是相对路径 URL转成可访问地址这件事是后端干的。6.4 时间字段差 8 小时或显示成英文这几乎是接手十套源码里八套会遇到的问题。表现是接口返回的时间比实际晚了 8 小时或者前端显示Oct 20, 2024这种英文格式。处理方式有两步第一步MySQL 连接 URL 加serverTimezoneAsia/Shanghai。 第二步后端实体类的时间字段加JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8)注解强制 JSON 序列化时用中国时区。如果还不对再检查前端有没有做 UTC 转换。很多前端框架或 axios 封装会自动把时间按 UTC 解析这属于叠加 bug前端拿到字符串后不要偷偷转格式原样展示最稳妥。6.5 常见问题速查表把实际操作中最常遇到的五个问题整理成表方便对着排查现象常见原因解决方向启动报BindException: Port already in use端口被占用换端口或用netstat -ano查占用进程杀掉Maven 依赖下载很慢或失败未配国内镜像在settings.xml配阿里云镜像仓库前端npm install报错Node 版本太高/太低锁定 Node 14 或 16删除node_modules重装登录接口返回 500数据库脚本没导完整用 Navicat 对比表数量检查sys_user表是否有初始账号接口返回中文乱码字符集不一致MySQL 建库用utf8mb4连接 URL 加characterEncodingutf-86.6 一个独家避坑技巧先看数据库再看代码很多朋友拿到源码习惯从 Controller 开始读代码结果绕了半天找不到逻辑。我的习惯正好相反先看数据库里的表和数据再反推代码。比如管理员账号想重置密码不用翻代码直接看sys_user表的数据找到admin行把password字段改成某个已知明文密码的 BCrypt 密文。再比如想看某个功能存哪张表直接在数据库执行模糊查询找到包含业务关键词的表再去代码里搜表的 Mapper。数据库是系统的“断面图”把表结构看懂了业务的来龙去脉基本就清楚了一半。这套系统的二次开发空间也很大前端登录页的 Logo、系统名称、主题色修改配置文件里的参数就能改成任何园所的定制版后端加一个“家长端微信小程序”的话接口基本可以复用报表模块加上 ECharts 就能输出各班出勤率、晨检异常趋势图。我个人在实际操作中最深的体会是这种管理系统源码的价值不在于“跑通”而在于你能把“幼儿园的线下流程”和“线上的数据表”一一对应起来——当你能说出“晨检异常数据落到 health_check 表通过 result 字段过滤再同步到 notice 推送家长端”这句话时这套系统的核心就已经是你的能力了。最后再分享一个小技巧改完前端想快速看效果别频繁npm run build开发模式下开热更新改一行代码浏览器自动刷新后端改了 Java 代码可以用 IDEA 的 Spring Boot DevTools 自动重启。我见过很多朋友每次改一个文件都要重启整个项目白白浪费大量时间。把开发效率提上来这套系统的完成度还能再上一个台阶。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。