SpringBoot+Vue养老院管理系统:前后端分离项目实战与部署
养老院管理系统说白了就是把院里的老人档案、床位、护理、费用这些事从纸质台账搬到系统里。我最近把这个项目完整撸了一遍从数据库设计到前后端联调再到打包部署踩了不少坑也总结出不少经验。这里不吹不黑把这套SpringBootVueMyBatisMySQL的前后端分离方案完整拆一遍源码和部署步骤都有需要的可以直接照着做毕业设计、课程项目或者中小型养老机构内部管理系统都能直接用上。先说清楚这套东西解决什么问题。养老院的日常管理其实很琐碎老人入住登记要填一堆表床位分配要翻纸质记录护工排班靠微信群吼费用结算月底算半天家属问老人近况还得打电话问护士。这些事儿用Excel硬撑也可以但一旦老人超过几十个数据一多就容易乱查个历史记录得要命。我做的这个系统用SpringBoot提供后端接口Vue负责页面展示MyBatis操作MySQL数据库通过JWT做登录认证角色权限分管理员、护士、护工、家属四类把老人管理、床位管理、护理记录、费用统计、家属端查看这些核心业务全部串起来。整套东西学完你不仅能掌握前后端分离项目的完整开发流程还能直接部署上线。1. 项目整体设计与思路拆解1.1 为什么选前后端分离而不是传统的JSP单体应用做管理系统很多人的第一反应是SpringBootThymeleaf或者直接JSP页面和逻辑混在一起一个人吭哧吭哧也能写完。但我选前后端分离不是因为流行是因为这套系统有三个现实需求刚好只有前后端分离能干净地解决。第一开发效率。前端和后端可以并行开发我定义好接口文档前端同学不用等后端写完才能动工直接拿Mock数据就能把页面搭出来。第二部署灵活性。前端打包成静态文件扔到Nginx里后端打成jar包独立运行哪天要换服务器或者加个负载均衡互不影响。第三扩展性。养老院以后很可能要加小程序端、App端到时候后端接口直接复用不用重新写一遍业务逻辑。如果你做的项目只是内部用几天就扔那另说但如果你想做一个能长期迭代、能写进简历的系统前后端分离是更值得投入的方案。这套架构还有个隐性好处前后端通过JSON交互数据格式统一调试起来很清晰。联调的时候用浏览器F12看Network面板请求和响应一目了然哪里出错一眼就能定位比我以前调的JSP页面模板引擎报错信息靠谱太多。1.2 技术选型的权衡SpringBoot、Vue、MyBatis、MySQL各司其职这套技术栈不是随便拼的每个组件都有自己的边界选型时我反复对比过这里把理由说透。SpringBoot负责后端接口层。选它最核心的原因是约定优于配置不用像SSH时代那样写一堆XML配置文件一个Application类加几个注解就能启动项目。而且SpringBoot生态里自带Starter机制项目整合MyBatis、MySQL驱动都是引入一个依赖就行这相当于把最繁琐的装配活儿全包了。我用的是SpringBoot 2.7.x版本搭配JDK 8为什么不用最新的SpringBoot 3.x因为3.x从javax迁移到jakarta很多老依赖不兼容MyBatis的starter要选适配版本对于学习项目没必要一上来就给自己挖坑。这个版本搭配等会儿部署章节我会细说现在的重点是先记住SpringBoot 2.7JDK 8是当前最稳的组合。Vue负责前端界面。我选的Vue 3组合Element Plus组件库Vue 3的组合式API写起来比Vue 2的选项式更加灵活逻辑复用也更方便。比如老人档案页面里表单校验、数据列表、分页组件是同一批逻辑用组合式API封装后每个模块都干净利落。如果你只会Vue 2也别慌核心的路由、状态管理、组件通信思想是通用的迁移成本并不高。MyBatis负责数据访问。选它不选JPA核心原因是我对SQL有控制欲。养老院系统的查询条件非常灵活比如统计某个护理等级的的老人数量、查询某个月的入住记录、关联查老人的床位和护工信息这种复杂查询用JPA写起来要绕半天用MyBatis直接写SQL分分钟搞定。而且动态SQL里用if标签拼条件比JPA的Specification代码好读得多。MySQL选5.7.44这个版本很多人问为什么不用MySQL 8.0或者最新的9.x。原因很简单5.7是经过海量生产环境验证的稳定版本占用内存低安装配置简单学习成本和服务器成本都低。8.0虽然性能更好但引入了caching_sha2_password认证插件容易出现连接认证问题对新手不够友好。做这种规模的管理系统5.7完全够用。1.3 数据库设计思路七张核心表把业务理清楚数据库设计是整个项目的地基表设计不好后面写代码就是灾难。我前后重构了两版最终定下来七张核心表这里把设计思路讲透。先看最核心的老人表elder主键id、姓名name、性别gender、年龄age、身份证号idCard、联系电话phone、紧急联系人contact、入住时间admitTime、护理等级careLevel1到4级数字越小越需要照护、状态status入住/退住/请假、备注remark。这里有个关键设计床位不直接存在elder表里的bedId字段上而是单独建一张床位表bedelder表通过床位分配表或直接在elder表存bedId我采用的是elder表存bedId的方式因为老人和床位是一一对应的把bedId作为外键挂在elder表上查询时一次联表就能拿到床位号避免再多查一次关联表。员工表staff包括姓名、工号、岗位护士/护工/管理员、手机号。老人和护工之间的关系是多对多一个护工要看护多个老人一个老人也可能由不同的护工轮流照顾所以我建了护理记录表care_record来关联记录字段包括老人id、护工id、护理内容、护理时间、备注。这张表不仅承担关联作用本身就是护理过程的流水账后面做工作量统计、健康趋势分析都靠它。费用表fee包括老人id、费用类型床位费/护理费/餐饮费、金额、月份、缴费状态。每月底系统生成费用记录家属在手机端看到的是汇总数据后台导出Excel交给财务。入住记录表和退住记录表我合并到了elder表的status字段用一个变更记录表change_log记录状态流转历史这样查询老人入住退住的完整时间线非常方便。用户表user和角色表role是多对多关系通过user_role中间表关联。用户表存账号、密码BCrypt加密后的密文、姓名、关联的员工id或家属id。这里有个设计习惯登录账号和业务人员实体分开比如护工李阿姨在staff表里是一条记录在user表里另有一条她的登录账号两边通过staffId字段关联。这样做的原因是登录凭证和业务数据生命周期不同员工离职了只是禁用账号不影响历史护理记录里的关联信息。2. 核心功能模块与技术要点解析2.1 登录认证和权限控制JWT 拦截器的组合拳这个模块是系统的门禁也是面试官最喜欢问的点。我先说整体思路后端使用JWTJSON Web Token生成Token前端每次请求带着Token后端通过拦截器验证合法性从而实现无状态认证。无状态的意思是服务器不需要保存用户的登录状态Token本身就携带了用户信息和过期时间很适合前后端分离这种跨域部署场景。JWT的结构是三段式Header加密算法和Token类型、Payload用户id、用户名、过期时间等、Signature前两段加密钥签名。后端生成Token的代码套路很固定定义一个JwtUtil工具类里面封装生成和解析两个方法生成时把用户id和角色塞进Payload设置过期时间比如2小时然后用HMAC-SHA256算法签名。前端拿到Token存到localStorage里每次请求在axios拦截器里加上Authorization请求头。权限控制我采用的是最简洁的RBAC模型用户-角色-权限但具体实现没搞得太复杂而是用拦截器角色判断搞定。定义一个AuthInterceptor拦截器在preHandle方法里从请求头取Token解析用户id和角色然后把用户信息塞进ThreadLocal供后续使用。再针对不同接口加RequireRole注解注解里声明允许访问的角色列表拦截器校验不通过就返回403。这种方案比整合Spring Security全家桶轻量得多代码逻辑也更容易理解。如果是企业级高安全要求项目Spring Security更适合但做管理系统学习项目这个方案的效果和可维护性已经非常好了。前端这边Vue路由用beforeEach守卫如果没有Token就强制跳转登录页并记录原本要访问的路径登录成功后跳回去。axios响应拦截器统一处理401状态码一旦Token过期就清除本地登录信息跳转登录页。这里有个容易踩的坑Token过期后用户正在填写表单直接跳转会丢数据更好的做法是弹提示登录已过期请重新登录再跳转。2.2 老人档案和床位管理CRUD之外的设计细节老人档案是系统的核心业务模块表面上就是增删改查但实际上有四个细节需要注意。第一个是照片上传。老人在入住登记时通常要传一张证件照后端接口用MultipartFile接收文件存储到服务器的uploads目录数据库里只保存相对路径。上传时要做文件类型校验jpg、png限制大小2MB以内文件名用UUID重命名防止中文文件名乱码和重复。第二个是分页查询。用PageHelper这个分页插件前端传pageNum和pageSize两个参数后端查询前一行PageHelper.startPage(pageNum, pageSize)紧接着的查询自动带上LIMIT再通过PageInfo封装返回total和list。这个插件用起来确实方便但注意startPage必须紧跟Mapper查询语句中间不能有其他数据库操作否则分页会失效这是新手容易忽略的坑。第三个是床位分配状态管理。床位表bed有状态字段status可分配、已占用、维修中。分配床位时要开启事务更新床位状态为已占用更新老人表的bedId两步操作要在一个Transactional里防止出现老人占了床位但床位状态没更新的情况。退住时同样要开事务反向操作。这种需要多步写操作的场景事务是最基本的保障。第四个是搜索过滤。列表页支持按姓名、身份证号、护理等级、入住时间区间搜索。这里MyBatis动态SQL的where标签就派上用场了通过if标签判断每个查询条件是否为空拼出灵活的查询语句。我写的时候还加了关键字搜索数组的循环拼接一次查询可以传多个条件后台动态生成SQL不用的条件自动过滤。2.3 护理记录和健康数据用流水账支撑业务养老院的护理工作非常依赖日常记录几点测血压、几点吃药、今天精神状况如何、有没有特殊情况。这个模块的核心价值不是CRUD而是让数据能回溯、能统计、能告警。设计上我单独建了一张表health_record字段包括老人id、体温、血压收缩压/舒张压、心率、血糖、护工id、记录时间、备注。护工每天定时录入几个核心指标作为独立字段存储这样后期做趋势分析的时候可以直接取出数值型数据进行计算。比如管理员查看某位老人的血压趋势就是查询这个人最近30天health_record的收缩压和舒张压在前端用ECharts折线图展示。这个功能很受管理者欢迎因为纸质记录根本做不了趋势可视化。还有一个细节是异常值提醒。判断逻辑不复杂比如收缩压超过160或者低于90就在页面显示醒目的红色标识。我在后端对录入的数据做了一层规则校验超过阈值就直接拒绝保存必须填写异常原因备注这样数据质量才有保障。现在很多智能硬件可以自动采集健康数据但手工录入在大多数养老院还是主力系统层面做好规则拦截就能避免很多低级错误。2.4 费用管理和统计报表多表联查和Excel导出的实战费用模块是管理系统里最容易被低估的部分实际写得时候发现逻辑比想象中复杂。养老院的费用分为三类床位费按床位等级定价护理费按护理等级定价餐饮费按天计算。每月初系统自动为所有在住老人生成上个月的账单算法很简单从elder表查出在住老人根据他关联的床位等级和护理等级计算费用再根据入住天数计算餐饮费注意新入住的老人从入住当天开始计算退住的老人算到退住那天为止。账单生成后页面要展示应收合计还要支持财务人员按月份查看账单明细以及导出Excel。导出功能后端用EasyExcel工具包把费用记录映射到实体类的Excel注解一行代码就能生成.xlsx文件。前端页面按钮触发下载从响应头拿到文件名用blob方式接收。这里有个小坑EasyExcel导出时金额字段如果直接用浮点数会出现精度问题正确做法是用BigDecimal存储金额字段数据库层面用decimal(10,2)类型从源头避免浮点误差。统计报表模块我用ECharts做柱状图和饼图展示每月收费总额 、不同护理等级的老人分布、床位利用率。后端SQL统计用GROUP BY加聚合函数比如查询某个季度每个月的费用总额就是按月份分组SUM金额。ECharts的配置项比较多但核心就三样图表类型type、数据series、坐标轴xAxis/yAxis。做管理后台的报表大多数场景都是这几种图表类型反复用封装一个公共的图表组件接收数据和配置项就能复用很多地方。2.5 家属端视频查看m3u8流媒体播放的落地很多养老院管理系统会提供视频探视功能让家属远程看看老人。这块有个比较特殊的技术点视频流通常是用m3u8格式HLS流媒体协议传输的不是传统的mp4文件。m3u8文件本身是一段文本里面记录了一堆.ts视频分片文件的地址。前端要播放m3u8,不能直接用HTML5的video标签因为原生video不支持这个格式需要借助hls.js这个库。我用的方案是后端提供视频地址接口返回m3u8的URL前端引入hls.js。在Vue组件中动态检测如果浏览器支持Media Source Extensions大多数现代浏览器都支持就通过Hls.js加载m3u8地址把视频流挂载到video元素上。这里需要注意跨域访问很多视频服务器对Referer有校验开发环境下容易遇到403解决方法是后端接口做一层代理前端请求后端后端转发视频流顺便绕过跨域限制实测下来这个方案最稳定。另外视频组件在页面上要加加载loading状态因为流媒体需要缓冲几秒才能播放不做loading用户会以为页面卡死了。3. 实操过程与核心环节实现3.1 开发环境准备版本搭配和老生常谈的坑工欲善其事必先利其器。这套项目的环境搭配我整理了一份清单照着装不会出错。JDK用8具体是8u202或更新IDEA推荐2022.3以上版本MySQL用5.7.44Node.js用16.20.2Vue CLI或Vite都需要Node支持16版本兼容性最好前端构建工具按Vite 4来配。Maven用3.6.3以上配置阿里云镜像源不然拉依赖能等到怀疑人生。MySQL的安装是我见过踩坑最多的地方。Windows 10上装MySQL 5.7.44最稳的是下载ZIP包解压安装不要用图形安装器因为图形安装器经常卡在最后一步配置。解压后先配置my.ini文件设置basedir和datadir路径然后以管理员身份运行cmd执行mysqld --initialize-insecure初始化数据目录再执行mysqld --install注册为Windows服务net start mysql启动服务。初始root用户无密码执行mysql -u root进入后用ALTER USER rootlocalhost IDENTIFIED BY 你的密码设置密码。这里有个容易忽略的步骤my.ini里要加skip-grant-tables吗不用正常初始化就行加了反而容易忘记取消导致安全问题。Node和Vue环境这块先执行node -v确认Node版本然后npm config设置registry为国内镜像源不然下载依赖太慢。用Vite创建Vue 3项目执行npm create vitelatest frontend -- --template vue然后安装Element Plus、Axios、Vue Router、Pinia、ECharts、Hls.js这些依赖。Vite项目的配置比Webpack简单很多开发服务器默认跑在5173端口后端接口跑在8080需要配置代理转发。3.2 后端项目搭建从零写出可运行的SpringBoot接口后端项目用Spring Initializr来建Group填com.exampleArtifact填nursing依赖选Spring Web、MyBatis、MySQL DriverSpringBoot版本固定到2.7.18。生成后补上其他依赖Lombok减少getter/setter样板代码、JWT的两依赖、PageHelper分页、EasyExcel。配置application.yml时注意数据源和MyBatis的两块配置我用的是Druid连接池最大活跃连接数20初始化5这个参数根据实际并发量定管理系统这个量级绰绰有余。MyBatis配置要特别注意Mapper扫描路径和XML映射文件的classpath。在启动类上加MapperScan(com.example.nursing.mapper)application.yml里设置mybatis.mapper-locationsclasspath:mapper/*.xml。开发阶段把SQL日志打印打开设置mybatis.configuration.log-implorg.apache.ibatis.logging.stdout.StdOutImpl这样控制台会直接输出SQL语句和参数值排查问题非常方便。这个配置上线前最好关掉因为SQL日志内容多会影响性能也容易泄露表结构。写一个通用返回结果类Result封装code、message、data三个字段提供静态方法success和error。所有Controller的返回值都用这个包装类前端才能统一拦截和处理。这个看似简单的封装对前后端协作帮助非常大接口返回格式不一致是联调最大的痛点约定一个规范方案就省心很多。老人管理的Controller、Service、Mapper三层我以分页查询老人列表这个接口为例说明调用链路。前端请求GET /api/elder/page?pageNum1pageSize10Controller接收参数调用Service层Service层先PageHelper.startPage再调Mapper的selectPage最后new PageInfo返回。Mapper.xml里写动态SQLwhere标签拼name关键字和careLevel条件排序按创建时间倒序。这套链路是后端开发的标准姿势所有模块都copy这个模式。3.3 前端项目搭建路由、接口封装和组件复用的关键代码Vue 3前端项目我先把目录结构整理好views目录放页面组件router目录放路由配置api目录放每个模块的接口请求方法utils目录放请求封装和工具函数components目录放公共组件。路由用createWebHistory模式这样地址栏不带#URL更干净但要注意部署时Nginx要配置try_files否则刷新页面会404。axios请求封装集中在一个文件里baseURL设为/api开发环境通过Vite代理转发到后端。请求拦截器从localStorage取Token加到Authorization头响应拦截器对code不等于200的情况统一弹错误提示对401做登录过期处理。这个封装文件是整个前端的骨架所有接口请求都走这一套逻辑其他地方不用再重复写错误处理。Vue Router的动态路由和按钮权限这块我做了一个实用方案。登录成功后后端根据角色返回菜单权限列表前端动态注册路由。以护工角色为例它只能访问护理记录和老人信息页面看不到费用统计和系统设置菜单。这种权限控制用Vue Router的addRoute方法实现后端返回的路由配置前端循环注册未授权页面直接加404路由兜底。这种动态路由方案比写死路由再靠守卫判断高级得多也更符合真实项目规范。组件的复用方面我封装了一个搜索表单组件和一个分页组件。以分页组件为例它接收total和pageNum、pageSize通过事件向父组件传更新参数。老人列表、护理记录列表、费用列表三个页面都复用这个组件每个页面少写大概三十行模板代码。Vue 3的插槽在这里用得很多尤其是表格操作列每行都不一样用Element Plus的el-table-column插槽是非常自然的写法。3.4 前后端联调的跨域处理和接口调试技巧前后端联调阶段最大的拦路虎是跨域问题。开发环境浏览器直接访问前端5173端口Ajax请求后端8080端口端口不同产生跨域。方案一后端配置全局CorsFilter允许特定来源访问设置请求头和方法。方案二Vite配置server.proxy代理把/api开头的请求转发到localhost:8080。我推荐方案二因为代理方式是开发环境的标准做法浏览器里看到的请求是同一个源不用在后端开跨域而且部署到生产环境时Nginx配置反代理整个请求路径都不用改无缝切换。接口调试我用Apifox导入后端接口的OpenAPI文档就能生成调试环境mock数据、环境切换、断言测试都有。联调过程中最常遇到的问题就是字段名对不上后端返回的字段是snake_case下划线命名前端JS习惯用camelCase驼峰命名。这个问题可以在后端通过JsonProperty注解做转换或者在MyBatis配置里开启mapUnderscoreToCamelCase自动映射。我后端全局配了map-underscore-to-camel-case: true这样数据库的下划线字段自动映射到实体的驼峰属性前端拿到JSON就是驼峰格式沟通成本少很多。4. 部署实战从打包到上线以及我踩过的那些坑4.1 前端打包和后端jar包一行命令搞定生产构建部署部分我分成开发环境部署和生产环境部署两步讲。开发环境把后端jar包跑在8080端口前端npm run dev跑在5173端口通过Vite代理联调这个前面已经说过了。生产环境则是完全不同的思路前端要构建成静态资源让Nginx托管后端打包成可执行的jar包SpringBoot内嵌Tomcat直接跑在一个端口Nginx做反向代理把/api请求转发给后端。后端打包在项目根目录执行mvn clean package -DskipTests然后到target目录下执行java -jar nursing-system-0.0.1-SNAPSHOT.jar。要是服务器上想后台运行用nohup命令nohup java -jar nursing-system.jar app.log 21 把输出日志重定向到文件。前端打包进dist目录在frontend目录下执行npm run build构建完成后把dist目录里的文件复制到Nginx的html目录下。Nginx的配置文件要注意root路径指向dist目录并且location /里配置try_files $uri $uri/ /index.html这一步是SPA路由的关键没有它刷新页面就404了。生产环境的数据库连接密码不能明文写在application.yml里我用的是环境变量方式配置文件里写${DB_PASSWORD}启动前在系统环境变量里设置实际值。这个习惯非常重要源码如果上传到Git仓库明文密码就泄露了用环境变量是底线。还有很多部署细节比如上传文件的目录要放在jar包外部并且确认有写入权限数据库连接串加个useSSLfalse参数避免MySQL连接警告用spring.profiles.active配置多环境切换开发、测试、生产环境用不同的配置文件。4.2 常见问题排查实录版本、缓存、依赖、流媒体的坑这个环节是实战中踩坑的精华每一个问题都是真实遇到过的。SpringBoot版本太高导致的javax/naming问题这是最典型的问题。开头说了SpringBoot 3.x改成了jakarta命名空间如果你的服务从SpringBoot 2.7升到3.x代码里import javax.servlet全都要改成import jakarta.servletMyBatis的starter也要换版本。很多老项目的第三方依赖根本不支持jakarta升级后各种ClassNotFoundException。我的建议是除非有硬性要求否则SpringBoot 2.7稳稳跑到生命周期结束。如果真要升级先用Spring Boot Migrator工具扫描代码它会告诉你哪里需要改。MyBatis缓存导致的数据不一致MyBatis默认开启一级缓存同一个SqlSession里重复执行同一条SQL会直接返回缓存结果。在管理系统里如果两个用户同时修改一条老人的信息页面刷新后可能看到的是旧数据因为查询走了一级缓存。解决办法是增删改操作后强制刷新缓存或者干脆配置localCacheScopeSTATEMENT让每次查询都走数据库。二级缓存默认是关闭的管理类系统建议保持关闭状态改数据频繁的地方开缓存反而容易出问题。Vue项目构建失败tsconfig报错和依赖版本不兼容用Vite创建Vue 3项目后运行时偶尔会报Failed to load tsconfig vue/tsconfig/tsconfig.web.json原因是没有安装vue/tsconfig这个依赖。用npm安装后问题就消失。另一个常见的构建失败是Element Plus版本和Vue版本不匹配Element Plus要求Vue 3.2以上如果用了Vue 3.0会报兼容性的警告建议项目直接锁死Vue 3.3和Element Plus 2.4。访问Docker容器内的MySQL连接不上这是部署时的高频坑。Docker容器里跑了MySQL宿主机上的SpringBoot连不上先检查端口映射有没有生效用docker ps看PORTS列再确认MySQL容器里有没有开放远程访问权限。MySQL默认只允许localhost连接需要执行GRANT ALL PRIVILEGES ON *.* TO root%。还有一个容易忽略的点服务器防火墙有没有开放3306端口云服务器要在安全组里配置规则这个不配置本地Ping通但就是连不上数据库。Vue播放m3u8视频卡顿或加载不出来这个在上面家属端视频模块也提了。除了引用Hls.js以外还要注意生产环境视频地址一定是相对路径或者通过后端代理如果直接把内网视频地址写在页面里家属在外部网络肯定打不开。还有一个坑是Hls.js要配置enableWorker: true和lowLatencyMode: true否则播放延迟大、容易卡顿实测配置后体验提升明显。4.3 部署性能调优从能用变好用项目部署上去之后还远远没到结束。很多系统能用和好用之间差着一大截我做了三个优化动作这里分享一下。第一个是MySQL慢查询优化在my.ini里开启slow_query_log慢查询阈值设为1秒跑一段时间后看日志把频繁出现的慢SQL拿出来分析执行计划。我在elder表的name字段和care_log的record_time字段上加了普通索引费用表的老人id加索引查询速度立竿见影。管理系统的数据量级虽然不大但索引设计好总没错。第二个是SpringBoot运行参数调优。JVM默认堆内存可能不够用启动命令加-Xms512m -Xmx512m根据服务器内存调整避免服务运行一段时间后频繁GC。如果使用Druid连接池initialSize、minIdle、maxActive这些参数要合理设置我上面提到的5/5/20在几十个并发请求下绰绰有余。前端静态资源也做了优化Element Plus按需引入后构建产物小了很多首屏加载速度快了不少。第三个是日志和监控。生产环境配置logback把日志输出到文件并做按天滚动保留七天。我加了个简单的基于Actuator的健康检查通过curl /actuator/health看服务存活状态。后来还写了个小的Shell脚本定时检查日志有没有报错关键字异常的自动发钉钉消息提醒。这些虽然都是小动作但一个系统能不能长期稳定跑下去靠的正是这些细节。5. 附加经验的分享如何把系统做得更好用、更耐看部署上线不是终点我做完这套系统之后回头复盘又做了不少功能优化这里挑几个实用度最高的分享出来。权限管理迭代了一版把页面级别控制细化到按钮级别。什么意思比如护士角色能看到老人管理页面但没权执行删除老人这个按钮后端接口用RequireRole注解标记删除接口只有管理员能调前端根据当前用户权限控制按钮的v-if显示隐藏。这个细化对系统安全等级提升很大也直接撑起了简历上细粒度权限控制这个描述。老人照片上传之后前端页面有个头像裁剪功能选完图片可以直接裁剪成正方形再上传避免老人照片因为比例不统一而变形。这个功能用的vue-cropper组件几十行代码就能集成效果非常直观。费用模块也扩展了一下支持不同月份批量生成账单后还加了未缴费老人的逾期提醒系统里有一份未缴费记录的列表可以导出Excel发给财务去催缴人事部门的压力小了不少。还有一个我最推荐的扩展接入了微信推送。家属端不再只能登录Web查看消息老人入住状态变化、护工提交了新的护理记录、费用账单生成都会通过模板消息自动推送到家属微信。这个功能对系统的整体评价提升作用非常直接因为家属感受到的不是一个冷冰冰的网页而是系统的主动服务。接入过程用到微信模板消息接口后端用HttpClient调用前端完全不用动工作量不大但效果是质变级的。功能之外代码质量这块我也做了不少清洗工作。后端统一异常处理升级了一版RestControllerAdvice捕获所有异常自定义业务异常类BusinessException业务代码里需要判断失败的地方直接throw维护效率高很多。前端把重复的请求逻辑封装到自定义hook里useElderApi、useFeeApi这种use函数页面逻辑变得非常清爽。代码规范的收益一时半会儿看不出来但项目越来越大之后每次改动都舒服很多。最后说一个做这类全栈项目的心理建设。很多同学拿到这类项目源码第一反应是我能看懂吗然后放着吃灰。我的建议是不要只当读者要当改代码的人。拿到这套系统后从改一个小功能入手比如给老人列表加一个按年龄排序的按钮从后端写SQL、改接口、到前端加按钮、调接口完整跑通一次你对整个系统的理解马上就不一样了。再往后可以加一个独立的小模块比如每周食谱管理通知公告管理的代码可以直接对标着写写完就相当于你自己从零设计了一个功能模块。这种抓手方法跟一味地看教程读源码比起来效果是天壤之别。这套源码放在那里是作为一个能跑、能改、能部署的活物而不是一份需要膜拜的文档。希望你能把它变成真正属于你自己的项目。

相关新闻

Gemini订阅太贵?我用SwiftUI写了个macOS菜单栏原生客户端

Gemini订阅太贵?我用SwiftUI写了个macOS菜单栏原生客户端

看到标题你们可能以为我开玩笑,但我真的很认真算过这笔账:过去半年我每个月都在给 Gemini 交订阅费,累计下来已经是一台入门级 iPad 的钱。为了让这笔钱不再打水漂,我动手写了一个 macOS 原生客户端,把日常高频用的对话…

2026/10/9 4:15:38 阅读更多 →
基于ThinkPHP+Laravel的高校食堂健康饮食推荐系统实现

基于ThinkPHP+Laravel的高校食堂健康饮食推荐系统实现

1. 项目背景与需求拆解1.1 高校食堂场景下的真实痛点做这个系统的念头,源于我在高校后勤信息化项目里看到的真实场景。每到饭点,食堂窗口前永远排着长队,学生们站在档口前犹豫不决,既不清楚今天哪个菜新鲜,也算不明白这…

2026/10/9 4:15:38 阅读更多 →
Gemini 3.8 Flash 生产级实测:代码、长文本、结构化输出与调参经验

Gemini 3.8 Flash 生产级实测:代码、长文本、结构化输出与调参经验

最近这两周,我把 Gemini 3.8 flash 正式接进了日常的自动化流程里,用真实业务任务连续跑了两百多次调用。这次不做 benchmark 跑分,也不看官方宣传页上的演示指标,就纯粹当成一个“员工”来试用:让它写代码、总结长文档…

2026/10/9 4:15:38 阅读更多 →

最新新闻

oneTBB concurrent_hash_map 非成员二元比较运算符(operator== / operator!=)详解

oneTBB concurrent_hash_map 非成员二元比较运算符(operator== / operator!=)详解

并发编程高性能计算 【免费下载链接】oneTBB oneAPI Threading Building Blocks (oneTBB) 项目地址: https://gitcode.com/gh_mirrors/on/oneTBB 点击查看 免费下载 导读 本文聚焦 oneAPI Threading Building Blocks(oneTBB)中 oneapi::tbb…

2026/10/9 4:49:04 阅读更多 →
Claude Code 命令速查手册:高频命令、快捷键与高效工作流

Claude Code 命令速查手册:高频命令、快捷键与高效工作流

1. 为什么需要一个命令速查手册刚接触 Claude Code 的人,十有八九会经历这么一个阶段:装好了,敲了个claude进去,然后对着那个闪烁的光标发呆——接下来该干嘛?官方文档当然有,但文档是线性的,从…

2026/10/9 4:49:04 阅读更多 →
ESP32 SoC与模组选型指南:从芯片架构到量产料号

ESP32 SoC与模组选型指南:从芯片架构到量产料号

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 4:49:04 阅读更多 →
Claude Code Mods扩展开发:工具挂载与终端界面渲染实战

Claude Code Mods扩展开发:工具挂载与终端界面渲染实战

1. 从终端里的AI助手说起:为什么需要给它加装工具和界面很多人第一次接触命令行里的AI编程助手时,感受往往是矛盾的。一方面,它能理解自然语言、能读写文件、能执行命令,确实比传统补全工具强出一大截;另一方面&#x…

2026/10/9 4:49:03 阅读更多 →
SSM框架2025年真实处境与Spring Boot渐进式迁移实战

SSM框架2025年真实处境与Spring Boot渐进式迁移实战

直接开写 说实话,每次在技术群里看到有人问“SSM框架还能打吗”,我就知道问这问题的十有八九是两种人:一种是刚接手了祖传项目、天天被XML配置折磨得想跑路的年轻开发,另一种是还在用SSM做老系统维护、看着外面的技术新闻越来越焦…

2026/10/9 4:49:03 阅读更多 →
LRE框架:重构AI智能体的时间感知与因果记忆机制

LRE框架:重构AI智能体的时间感知与因果记忆机制

1. 这不是“给AI加个备忘录”,而是重构智能体的时间感知能力很多人第一次看到“AI智能体记忆管理”这个词,下意识会想:不就是让大模型多存点上下文、加个向量数据库当外挂硬盘吗?我试过——在某个模拟项目X里,给一个任…

2026/10/9 4:48:03 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →