资讯详情

SpringBoot+Vue宠物医疗管理系统:从业务建模到部署全解析

📅 2026/9/25 21:58:44 | 华诺云谱 👁 阅读
SpringBoot+Vue宠物医疗管理系统:从业务建模到部署全解析
1. 宠物医疗管理系统到底在管什么业务需求先于技术选型我得先泼一盆冷水很多人拿到基于SpringBootVue的宠物医疗管理系统这类课题第一反应是先把技术栈摆出来SpringBoot、Vue、MyBatis-Plus、MySQL一套全安排上然后照着网上CRUD模板猛写最后交出来一个披着宠物外衣的图书管理系统。这在答辩现场是极其致命的——老师随便问一句你的诊疗流程里挂号和开药的数据是怎么关联的就露馅了。这个问题我见过太多次因为宠物医疗管理系统它的难点压根不在技术而在业务模型的特殊性。你很难找到第二个领域既有严格的库存管理逻辑药品、耗材、又有精细的状态流转预约、就诊、住院、还需要对时间敏感的记录管理疫苗周期、驱虫计划。换句话说这个系统中每种数据都不是躺在数据库里的死字段而是彼此咬合的齿轮。我先说这个就是想让你先把思路倒过来先想清楚宠物医院是怎么运转的再想怎么写代码。1.1 它和人类医院的管理系统差在哪宠物医疗管理系统的核心对象是宠物主人的双主体结构。人类的医疗系统只需要围绕患者个人做记录但宠物不是独立自然人它的行为能力归它的主人管所以系统里必须同时维护两条线宠物的生物档案品种、年龄、是否绝育、既往病史和主人的联系信息电话、地址、会员等级。这两条线还会交叉医院一般按主人会员做储值折扣但看病时记录的是某宠物的病历。边界划不清楚后面做充值、开处方、统计收入时会乱成一团。更麻烦的是动物不会说话。人类患者能自己描述哪里不舒服宠物只能靠主人转述和医生检查。所以宠物病历里大量出现的是主诉主人描述 检查发现 初步诊断三段式的结构化描述。系统设计病历表的时候这三个字段是必须分开的而不是塞进一个长长的文本备注里。这个小细节恰恰是区分真懂业务和照模板写的分水岭。另一个巨大的差异是疫苗和驱虫的周期性管理。宠物疫苗不是打一次就完了幼犬第一年要打三针联苗加一针狂犬之后每年续种一次驱虫也分体内体外不同体重有不同用药方案。一个不专业的系统只会在宠物档案表里留一个疫苗记录文本框而专业的系统会把每次接种拆成独立的记录行带着疫苗批号、接种剂量、下次应种时间。这直接决定你后端要怎么写定时提醒接口前端要不要单独做一个疫苗日历页面。1.2 三类使用者与一条核心就诊链路这个系统最典型的使用者有三类管理员、医生、前台。我在答辩里经常让学弟学妹当场画这三类人的权限边界很多人画着画着就乱了。管理员管门店、管员工账号、管药品库存的上下限、看经营报表。他通常不下诊断也不操作会员收银但能看所有数据。医生/助理核心是接诊、写病历、开处方、安排住院和手术。医生只能看自己经手的病历或经过授权查看会诊病例不能直接改药品库存价格。前台负责挂号、收费、会员充值、预约登记。她是操作最频繁的角色但没有任何医疗权限不能看完整病历内容。这三类角色对应的权限设计后端做JWT拦截时就要在接口层面把接口分成三类admin/、doctor/、reception/**。前端侧边栏也要跟着角色动态生成菜单。不要做那种所有角色共用一套菜单、进去看运气的简陋系统。核心业务链路则是这样一条线用户在小程序或电话预约 → 前台确认预约并建档若新客 → 医生按队列接诊 → 问诊体检后写病历 → 开处方或医嘱 → 前台按处方划价收费 → 药房发药若需要则办理住院 → 定期跟进复查/疫苗提醒。这条链路上每一步都和前一步的数据强关联没有挂号记录接诊界面就拉不出宠物档案没有处方单收费就没有项目依据没有收费完成的标识取药确认就是空中楼阁。所以表结构设计必须保证主键ID能顺着链路一路传下去。我见过不少系统把挂号、病历、处方做成三张孤岛表互相之间只有一个petId藕断丝连这种设计一旦走到某医生某月开了多少钱的药统计就会彻底崩盘。1.3 容易被忽略的隐藏需求除了主干链路宠物医院还有几个不显眼但老板很在意的需求第一是会员储值。宠物看病费用高医院普遍推充值满赠、充值折扣来锁定客流。这个需求意味着你至少要有充值记录表、余额字段、以及余额扣减的原子性保证。扣费必须和收费操作绑定在同一事务里否则就可能出现前端显示扣款成功、后台余额还够再刷一次的尴尬场面。第二是多宠物关联。一个主人可能带两只猫来看病一只是复诊一只是新发皮肤病。系统里必须通过owner_id把多份pet档案关联到同一个主人账号下而主人账号本身又是会员储值的载体。这个一对多主人到宠物的关系需要从表设计的第一天就固化下来。第三是药品的批次和效期。宠物医院的药品效期管理往往比人用药更严格因为宠物药开封后保质期更短。如果库存表里没有lot_no批号和expire_date效期实际药房管理人员会非常抗拒使用你的系统宁可用Excel记录。这个字段看似不起眼但在答辩时老师问到药品快过期了系统怎么处理这就是一个实打实的加分项。2. 技术栈为什么锁定SpringBootVue一套务实的前后端分离方案业务模型心里有数之后再来聊技术选型就顺畅多了。这个课题选择SpringBootVue我不认为纯属跟风而是这套组合在校园项目、中小型实际落地场景中确实是性价比最优的解。下面我从后端、前端、为什么不换别的三个角度拆解。2.1 SpringBoot的后端优势把配置地狱变成自动装配很多教材还停留在SSH或SSM的阶段但SpringBoot最核心的价值就是干掉了大量XML配置把Spring生态从每次新建项目要配一周环境变成一个spring-boot-starter-web就能跑起来。对于宠物医疗系统这种业务偏重、技术复杂度适中的项目你需要的不是更底层的控制力而是快速把CRUD和业务逻辑铺开的能力。SpringBoot的starter机制比如mybatis-plus-boot-starter、spring-boot-starter-validation把常用组件的依赖和自动配置都打包好了你只需要关注业务代码。同时SpringBoot也天然具备后续扩展的能力。宠物医疗系统并不只停留在毕业设计层面很多学长把它做成商业项目卖给了本地宠物诊所。一旦要接支付、接短信通知、接电子发票SpringBoot庞大的生态都能覆盖到——Retrofit、Hutool、JustAuth这些都是现成的工具库不用重新造轮子。有个容易被忽视的点是SpringBoot的单元测试和打包部署体验。内置Tomcat使得spring-boot:run一键启动package打出来的jar可以直接 java -jar 运行这对后端部署到服务器非常友好。相比传统SSM项目要单独装Tomcat、改server.xml运维成本低一个量级。做宠物医疗系统免不了要演示给客户或老师看能一条命令从零跑到一个可用系统这种省心感是实打实的。2.2 Vue前端的价值交互复杂页面真的需要组件化宠物医疗系统的前台页面复杂程度远超一个后台管理系统的平均水准。医生的接诊工作台需要同时展示宠物信息、病史时间线、检查项列表、常用处方模板并且支持在一个页面内连续操作。如果用JQuery模板引擎来做DOM操作和状态同步会让你写到怀疑人生。而Vue的响应式数据绑定、组件化开发能让这种多区块联动的页面变得可维护。举一个具体场景在挂号收费页前台选择宠物后需要联动展示该宠物的会员折扣、剩余余额、历史欠费如果有。这个页面有三个联动变量当前宠物、当前项目挂号/检查/药品、应收金额。用Vue写起来就是data里维护三个状态computed里实时算金额下拉框变化时自动触发。这套逻辑在JQuery里要手动监听每个select的change事件再手动去更新多个DOM节点容易写乱后期加需求也容易崩。Vue的组件化对于复用场景帮助也很大。系统里的宠物档案卡片会在挂号页、接诊页、住院页重复出现封装成一个PetCard组件后用props传宠物对象就能复用。处方明细编辑表格在医生开药页和前台划价页长得几乎一样做成同一个组件再加一个disabled属性就能区分。这种复用带来的开发效率提升可能在第一次开发时感觉不明显但后续维护和加功能时会深有体会。2.3 Vue2还是Vue3怎么选说实话这个问题我每次都会被问到。我的建议是如果是从零开始做新项目直接选Vue3 Vite Pinia。理由很实际Vue3的Composition API对复杂逻辑的聚合能力远超Vue2的Options API。接诊工作台这种需要同时维护宠物信息、病历表单、处方列表、费用预结算四个独立模块的页面用Composition API可以把每个模块的响应式变量和操作函数集中到一个区域代码可读性和维护性都更好。而Vue2的Options API会把同一模块的data、methods、computed拆得七零八落改一个模块要上下翻好几屏。另一个原因是生态现状。2025年已经很成熟Element PlusVue3版组件库、Vite构建工具、Pinia状态管理这套组合已经非常稳定网上教程也多到泛滥。反观Vue2因为官方维护进入尾声新项目再入坑不值。唯一要留意的坑是Node.js版本——Vite要求Node 18如果你电脑还停在14/16要么升级要么用nvm切换。这里要提醒一个很多人踩过的坑不要一上来就跑到官网复制一堆最新语法而是先确认你下载的Element Plus版本和你抄的教程版本对齐。比如Element Plus 2.x和1.x在部分组件props上是有差异的网上很多Vue3后台管理系统教程其实是拿Vue3Element Plus 1.x写的直接照搬到2.x项目里可能组件不渲染。稳妥做法是用脚手架先跑通一个最小可运行页面再往里填业务。3. 数据库建模把整个系统的骨架立稳这个阶段是整个项目里最不能快进的部分。我见过太多人一上来就猛写代码写到一半发现挂号和病历没关联、处方不知道挂在哪张表下然后推翻重来。数据库设计要遵循逆推法从最终交付的功能往回推表结构。你想要统计报表就逆推出订单表要有状态字段和金额快照你想要疫苗提醒就逆推出疫苗记录表要存带next_date的计划字段。3.1 核心表结构一览下面这个表清单是一套经过验证的核心结构覆盖了从预约到住院的完整链路表名核心字段作用边界userid, username, password, real_name, role, status系统登录用户role区分管理员/医生/前台ownerid, name, phone, address, member_level, balance, card_no宠物主人会员档案与储值账户petid, owner_id, name, species, breed, gender, birthday, sterilized, avatar宠物档案外键关联主人appointmentid, pet_id, owner_id, doctor_id, appoint_time, status预约与挂号记录medical_recordid, pet_id, doctor_id, appointment_id, chief_complaint, examination, diagnosis, conclusion病历主表记录单次就诊prescriptionid, record_id, total_amount, status处方单主表prescription_itemid, prescription_id, drug_id, quantity, amount, usage处方明细关联药品与用法drugid, name, category, spec, stock, warn_stock, price, batch_no, expire_date药品库存与效期vaccination_recordid, pet_id, drug_id, doctor_id, vaccinate_date, next_date, vaccine_no疫苗/驱虫接种记录hospitalizationid, pet_id, record_id, start_date, end_date, cage_no, status住院床位与状态流转recharge_recordid, owner_id, amount, method, operator, create_time会员储值流水payment_recordid, owner_id, biz_type, biz_no, amount, status, create_time收费流水biz_type区分挂号/药品/住院每张表的核心都在于和业务流程一一对应。比如prescription_item表必须有usage字段用药方式是宠物医疗的刚需一天两次、一次半片、连吃五天这种信息只写在备注里是不够的后面统计药品消耗和做费用明细时只有结构化字段才能参与计算。3.2 几个关键设计的细想软删除与逻辑状态宠物档案删除在真实业务里非常敏感可能涉及历史病历追溯所以不建议用物理DELETE。设计时给表加一个status或deleted标志位1表示逻辑删除查询时统一过滤。同样道理药品表被处方引用后就不能物理删掉只能下架。这个设计逻辑要在数据模型旁边用注释写清楚不然自己过两个月来看都容易懵。金额与快照收费流水表里的amount必须是当时算出来的实收金额而不是通过会员等级实时算。因为会员折扣规则会改药品价格会调一旦历史单据在月底统计时发现金额变了那财务就乱套了。因此处方明细里的amount字段要在开单那一刻把单价快照下来以后药品价格调整不影响历史单据。预约状态的流转appointment表的status字段我建议做成一个完整的枚举比如待确认→已确认→已就诊→已取消。这个流转在之后前端页面做今日接诊队列的时候特别好用前台确认后医生接诊界面就能按就诊时间排序拉出一列待诊宠物看完后一键把状态改成已就诊。用状态机而不是零散的是否就诊布尔值是这类系统的关键设计。资金账户的余额扣减owner表里的balance字段要和recharge_record、payment_record放在同一个事务逻辑里考虑。会员储值、消费扣费、退款每笔金额变动都要生成流水账户余额不过是流水汇总出来的结果而不是一个可以随意update的独立字段。这条原则如果守住就不会出现余额对不上账的经典事故。4. 后端工程落地从Controller到Mapper的全链路实操数据库设计一旦定稿后端的开发节奏就可以非常线性。下面是实际落地时我认为最合适的实现路线也把一些容易踩的坑一并写出来。4.1 项目骨架搭建用IDEA的Spring Initializr创建项目时Dependencies建议先选这几个Spring Web、MySQL Driver、Lombok、Validation。后面再手动引入MyBatis-Plus习惯用Hutool的话也可以加上工具类能省不少代码。这里有一个值得说的点不建议在创建项目时盲目勾选Spring Security。宠物医疗系统做JWT权限校验自己实现一个Filter往往更直观尤其对于入门阶段的开发者。Spring Security的学习曲线陡峭光是一个SecurityFilterChain配置就能劝退很多人而且它的默认登录页、CSRF防护逻辑如果不熟悉反而会干扰你的接口联调。用Sa-Token或者自己写一个简单的Token拦截器完全够用而且答辩时你能讲清楚每一步原理。当然如果你已经熟练使用Spring Security用也行二选一。但我的经验是十天半个月的开发周期里不熟的东西最好别碰。生成完骨架后我习惯先做一个技术验证闭环把数据库连接调通写一个最简单的findAll验证MyBatis-Plus能查到数再配一个全局异常处理器再去写业务。为什么这么做因为如果到联调阶段才发现数据库连不上、时间字段时区不对排查会更费劲。4.2 登录、JWT与权限三件套鉴权模块是整个后端最容易出问题的地方但同时也是最好讲清楚的地方。我的实现思路是这样的登录接口接收用户名和密码用BCrypt加密比对Spring Security的crypto模块可以单独引入只借用它的加密工具不用整套安全框架验证通过后用用户的id和role生成JWT密钥放在application.yml里过期时间建议设置为12小时。响应体里返回token和一个简单的userInfo对象含username和role。前端每个请求会在Header里带上Authorization: Bearer token后端写一个OncePerRequestFilter从Header里取token用JJWT库解析验证通过后把userId和role塞进ThreadLocal里供后续Controller使用。这种方式比直接把用户信息放在session里更适合前后端分离的场景因为服务器不保存会话状态横向扩展的时候不需要考虑session同步问题。在这里要特别提醒权限校验的两层逻辑第一层是登录态拦截没有token直接401第二层是角色拦截比如医生改药品库存接口就是非法操作。实现上可以在自定义注解里写RequireRole(doctor)在拦截器里把当前用户的role和注解要求比对比对失败返回403。这个设计能在Controller层用一行注解搞定权限管控而且答辩时讲起来逻辑清晰。4.3 统一响应体与全局异常代码瘦身的最有效手段我在翻学生代码时最常看到的问题是每个Controller方法都用HashMap返回结果前端拿到的东西五花八门。这个在小项目里虽然是能用但一旦页面多了前端要兼容各种code200但data是字符串的怪异返回联调效率会非常低。统一响应体的思路很简单定义一个泛型类R Data public class RT { private Integer code; // 200成功其他为失败 private String message; // 提示信息 private T data; // 数据体 public static T RT ok(T data) { ... } public static T RT fail(String message) { ... } }配合RestControllerAdvice全局异常处理器把业务异常、参数校验异常、兜底Exception分别处理统一包装成R对象返回。这样前端axios响应拦截器只需要处理一种结构就算后端抛了NPE前端拿到的也是系统异常请稍后重试而不是一堆堆栈。这个习惯要在写第一个接口时就养成不要后来再统一改否则改一处漏一处很痛苦。4.4 MyBatis-Plus实践与分页MyBatis-Plus几乎是这类项目的默认选择它的优势内置通用的selectById、save、updateById比纯MyBatis手写SQL省力很多。但需要注意几点第一逻辑删除要配置TableLogic注解加在deleted字段上然后在application.yml里配置logic-delete-value和logic-not-delete-value。这样你写的DeleteById实际上执行的是UPDATE语句查询时MP会自动追加过滤条件非常省心。第二自动填充。创建时间和更新时间这种字段可以通过实现MetaObjectHandler统一填充不用在每个insert时手动set。这个做法很常规但能减少很多低级漏填。第三分页插件一定要先注册否则Page对象拿到的records是null。配置方式在MyBatis-Plus 3.x下是这样的Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; }有了这个插件分页查询只需要在service层page(new Page(current, size), wrapper)就能自动生成带LIMIT的SQL同时还能拿到total总数。宠物列表管理页、药品库存页、收费流水页全是这一套写起来非常快。5. Vue前端请求封装、路由守卫与核心页面落地前端部分我建议走框架先行路线用Vite创建一个Vue3项目装好Vue Router、Pinia、Element Plus和Axios先把登录页跑通再扩展业务页面。这样等于先建立了前端可运行的安全网再往上面填功能不会因为环境问题磨半天。5.1 前端目录结构一个经典的划分方式是这样src/ ├─ api/ // 按模块划分的接口请求定义 │ ├─ auth.js // 登录相关 │ ├─ pet.js // 宠物档案 │ ├─ medical.js // 病历处方 │ └─ system.js // 用户药品 ├─ components/ // 公共组件PetCard、StatusTag等 ├─ layout/ // 后台布局侧边栏、顶栏、面包屑 ├─ router/ // 路由配置 ├─ store/ // Pinia状态管理 ├─ views/ // 页面组件 │ ├─ login │ ├─ dashboard │ ├─ pet │ ├─ medical │ ├─ pharmacy │ └─ system └─ utils/ └─ request.js // axios实例封装这个结构的核心思路是api层和页面层分离页面里不直接写axios请求而是调用api模块里的函数。好处是接口地址改动时只需要动一个文件而且每个页面的代码量减半人看着清爽很多。5.2 axios封装把token和错误处理集中起来axios封装是所有前端联调体验的基石。我在request.js里通常做三件事baseURL指向/api并在Vite devServer里做代理解决跨域、请求拦截器里从localStorage里取token加到Header响应拦截器里对HTTP 200但业务code非200的情况统一弹提示并针对401做跳转登录页的处理。一个简化的拦截器写法service.interceptors.request.use(config { const token localStorage.getItem(token); if (token) config.headers.Authorization Bearer ${token}; return config; }); service.interceptors.response.use( response { const res response.data; if (res.code 200) { return res.data; // 直接解包给页面 } if (res.code 401) { router.push(/login); // 登录过期 } return Promise.reject(new Error(res.message)); }, error { Message.error(error.message || 网络异常); return Promise.reject(error); } );注意这里我在成功分支里直接返回了res.data而不是整个res这意味着页面里调用api时能直接拿到数据体少写一层点。这种约定要在整个团队/项目里统一不然一半页面写res.data一半页面写res迟早出bug。5.3 动态路由与侧边栏按角色生成菜单根据第1章里说到的三类角色前端的路由不能写死。具体做法登录成功后后端返回当前用户的权限标识列表或角色字段前端在Pinia里存一份。路由守卫里做判断如果当前访问的路由meta里配置了roles: [admin, doctor]而当前用户角色不在其中就重定向到403页面。这样Router的meta信息就成了权限配置的唯一地方侧边栏菜单通过遍历路由表里的meta.title和meta.icon自动生成。这样设计的好处是系统的菜单不用在前端模板里硬编码新增一个页面时只要在路由表里加一行菜单就自动出现角色权限也跟着生效。在答辩演示时切换不同角色账号登录能明显看到菜单项不同效果比口头讲解权限设计直观得多。5.4 核心页面逐一拆解登录页表单校验用了Element Plus的Form Rules登录成功存token到localStorage跳转到dashboard。这个页面做得漂亮点对印象分很有帮助毕竟老师第一眼看的就是登录页。接诊工作台医生视角这是整个系统前端最重的页面。左侧是今日待诊队列中间是宠物信息卡片和病历表单右侧是处方明细表格。数据流是进入页面时请求/doctor/todayAppointments拿到待诊列表点击某个宠物后拉取宠物详情和既往病史。病历表单里主诉、检查、诊断三个字段分别单独绑定处方区内可以动态增删药品行实时汇总金额。这里我会用Composition API把当前待诊宠物、病历表单、处方列表分别抽成几个独立的逻辑块代码结构更清晰。药品库存页一个典型的列表页但带了检索和库存预警。表格里列出药品名称、规格、当前库存、预警阈值库存低于阈值的行高亮红色顶部加一个低库存药品筛选开关。药品入库弹窗里需要选择批号、填入有效期保存时做新增和原批次影响处理——这个逻辑后端Validate一下即可。挂号收费页前台视角操作路径是选择主人→选择该主人名下的宠物→选择挂号类型→收费。宠物下拉框的数据来自选定主人这在前端是一个watch(ownerId)联动请求的动作。收费完成后页面显示本次挂号流水详情并可打印小票浏览器CtrlP即可不用额外集成打印机。疫苗记录页列表展示每只宠物已经接种过哪些疫苗、下次接种日期。这个页面的关键操作是批量提醒筛选出未来7天内需要接种的宠物列表生成提醒并支持一键标记已通知。前端就是一次接口调用后端写一个简单的日期范围查询。6. 从本地联调到上线部署这些年踩过的坑合集很多新手项目最后挂在跑不起来上——不是代码写不出来而是本地能跑换个环境就崩。我把这个过程中高频遇到的坑集中列一下都是曾经真实发生过、且耗费过大量时间的问题。6.1 本地联调阶段的跨域问题Vue开发服务器默认跑在5173后端跑在8080。如果前端直接发请求浏览器会因为跨域拦截。这里有两种解决方式第一种是后端配置CrossOrigin或全局CorsFilter适合快速解决第二种是前端Vite devServer配置代理更接近生产环境的行为。我更推荐第二种。在vite.config.js里设置server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, rewrite: path path.replace(/^\/api/, ) } } }这样前端请求/api/login时会自动转发到http://localhost:8080/login浏览器看到的始终是同源的请求规避了跨域同时后端不需要写任何CORS配置生产部署时再用Nginx做同样的反代。用这套方案最舒服的地方是开发环境和生产环境的请求路径保持一致前端不用做任何环境切换适配。6.2 打包与部署的完整流程前端构建npm run build会在dist目录下生成纯静态文件。后端构建mvn clean package -DskipTests生成一个可执行jar。生产环境最简单的部署方式是在服务器上装MySQL和JDK然后java -jar pet-clinic.jar --spring.profiles.activeprodnginx配置中把/api代理到后端8080其他请求全部指向dist目录。这个方案适合项目演示也适合宠物医院这种小体量的真实环境。如果你想要更好的部署体验可以在此基础上加一层Docker。一个docker-compose文件里编排mysql、redis如果用的话、app-server、nginx四个容器就能一键拉起整个系统。我第一次用Docker部署时花了整整一天原因是Jar包在容器里时区不对、MySQL连接超时、静态资源挂载失败全是一行配置的事。所以如果时间不充裕可以先不用Docker直接裸机跑通nginxjar即可。上线这件事稳定简单优先于花哨。6.3 高发环境坑清单MySQL 8的时区问题连接字符串里一定要加serverTimezoneAsia/Shanghai否则时间字段偏8小时疫苗提醒功能全部错乱。Node版本太高或太低Vite要求Node 18但npm install时又可能因为node-sass报错——解决方式是统一使用sassDartSass替代node-sass或者干脆用Vite默认的less支持。JWT密钥不要写死用配置项注入否则打包后没法换过期时间设短一点12小时配合前端401自动跳转登录长时间挂机被踢要比token过期但不感知体验好一些。文件上传大小限制宠物头像一般不超过2MB但如果要做高清影像上传X光片SpringBoot默认的1MB大小限制会导致前端一直报413。记得在application.yml里调整spring.servlet.multipart.max-file-size为10MB。跨域在部署后依然存在如果生产环境你用域名直接访问前端裸IP加端口访问后端浏览器还是会拦。所以nginx必须把/api也反代到后端让浏览器始终面对同一个域名。我在实际部署中最大的体会是上线前一定要模拟一次全新环境部署。找一台干净的服务器从零开始克隆代码、装依赖、起服务把整个过程完整走一遍。你会发现很多在自己电脑上没问题的项目到了干净环境会因为端口占用、环境变量缺失、版本差异立刻暴露问题。这个过程虽然痛苦但它是保证答辩现场、甲方现场演示不翻车的最可靠方法。写在最后这个系统做到后期我从业务里总结出的一个心得是宠物医疗管理系统真正的核心价值不在技术炫技而在数据链路是否闭环——从挂号那一刻起宠物主人的电话、宠物的疫苗史、医生的诊断、处方的用药、收费的金额、库存的出库全部被一条线有序串起来。技术选型SpringBootVue只是这一串链条的载体。如果在做完基础版本之后想再往上走我建议优先做这三件事一是给系统加一个基于Echarts的经营看板让老板一眼看到今日收入、接诊量、库存预警二是把疫苗提醒改成主动推送接入公众号模板消息或短信通知让系统从被动查询变成主动服务三是做一份多端口的联调文档把前端、后端、数据库的启动方式和默认账号密码写清楚方便任何人在新机器上一键跑起来。最后一个建议对毕业设计来说尤其重要因为评阅老师拿到项目后第一件事肯定是尝试自己启动它一个导不起来的项目再好的功能也白搭。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑