ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

SpringBoot+Vue孕婴护理平台开发实战:从业务闭环到部署避坑

SpringBoot+Vue孕婴护理平台开发实战:从业务闭环到部署避坑 我去年帮朋友做了一个基于SpringBoot和Vue的孕婴护理平台从需求梳理到上线跑通前后花了三周。做完之后最深的感受是这类项目真正难的从来不是技术而是把护理这两个字落到具体的业务逻辑里。今天就把我实际动手过程中的设计思路、核心代码、踩坑记录全写下来给正在做毕设或者想接这类项目的同学做个参考。这个平台本质上解决的是这样一个问题孕产妇和新生儿父母需要一套工具帮她们管理产检记录、跟踪孕周变化、按时获得提醒、按阶段获取护理知识而不是像大多数管理系统那样堆一堆用不上的功能。下面我会按照需求定位、技术选型、后端设计、前端实现、部署验收这条线完整拆解一遍。1. 孕婴护理平台先想明白要做什么再动工写代码1.1 这类项目最常见的误区把护理平台做成了后台管理系统我看到过太多同类项目标题叫智能孕婴护理平台点进去一看全是后台管理功能用户列表、角色管理、菜单管理、权限配置……整得跟一个通用的管理后台脚手架一样。孕婴护理领域最核心的东西——孕期档案、产检记录、孕周计算、护理知识推荐、提醒任务——反而做得非常敷衍。为什么会出现这种情况核心原因是很多开发者拿到题目后第一反应是我有现成的管理系统模板于是直接套上去再往里面塞几个孕婴相关的表就算完事。这样的项目答辩时很容易被问住你的智能化体现在哪答不上来。我建议拿到这类题目后先做一件事把护理这个词拆开。护理不是管理它包含的是持续关注、按时提醒、阶段适配、知识支持。对应到系统功能上至少要有孕妇档案管理、产检数据记录与趋势分析、按孕周自动计算的提醒任务、按孕周和标签匹配的知识内容推荐。想清楚了这些后面的表结构设计和接口设计才会有方向。1.2 从需求里拆解出来的核心业务闭环我把核心业务闭环梳理成了一条主线孕妇注册登录后先填写个人档案包括末次月经日期LMP、预产期、孕前体重、身高、过敏史等。系统拿到末次月经日期后自动计算当前孕周。接着孕妇每次产检后录入体重、腹围、胎心率等数据系统把这些数据按时间排列生成趋势曲线并和医学参考范围做对比。同时系统根据当前孕周和档案里的标签在知识库里匹配对应的护理文章推送给用户另外有一个定时任务每天扫描一遍档案提前生成产检提醒、营养补充提醒等任务。管理员这边的职责比较简单维护知识文章审核用户产生的记录如果有社区功能的话查看系统运行情况。我把这个闭环拆成的核心模块如下用户模块注册、登录、JWT鉴权、角色区分档案模块孕妇基本信息、孕周计算、档案编辑产检模块产检记录增删改查、趋势图表数据聚合提醒模块基于孕周规则的任务生成、提醒列表、标记完成知识模块文章分类、标签体系、按孕周匹配推荐如果按这个列表去设计接口每个模块的边界非常清楚写代码时不会东一榔头西一棒子。这算是我给所有做类似系统的人的第一个建议先画业务闭环图再写代码。这个图不用很正式你自己能看懂就行但它能帮你省掉后面改表的很多时间。2. 技术选型为什么是SpringBoot Vue这套组合2.1 后端为什么选SpringBoot这个问题我几乎每次都会被问到尤其是有同学纠结要不要用SSHSpring Struts Hibernate或者直接用Servlet写。我的答案很简单SpringBoot就是目前Java做中小型业务系统最务实的选择没有之一。SpringBoot的核心价值在于约定大于配置。对于孕婴护理平台这种业务逻辑以CRUD为主、附带一些定时任务和推荐算法的中型项目SpringBoot把大量繁琐的配置都自动处理掉了你只需要关注业务代码本身。它和MyBatis-Plus配合起来单表CRUD几乎不用写SQL开发速度会快很多。我的建议版本组合是这样的这个组合我实测非常稳组件版本说明JDK8最稳妥SpringBoot 2.x全家桶都支持SpringBoot2.7.x稳定版教程多坑少MyBatis-Plus3.5.x单表CRUD神器分页插件好用MySQL8.0字符集用utf8mb4JJWT0.9.xJWT工具包代码简单Lombok1.18.x减少实体类样板代码这里要特别提醒一句SpringBoot 3.x虽然已经出了很久但它要求JDK17而且javax包名改成了jakarta网上很多老教程直接抄会编译不过去。如果你不是对SpringBoot 3特别熟悉做这类项目直接用2.7.x JDK8最省心。我见过太多同学卡在javax.servlet不存在这种问题上其实就是版本不匹配导致的。pom.xml核心依赖大致长这样dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt/artifactId version0.9.1/version /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency2.2 前端为什么选Vue前端我选了Vue 3 Vite Element Plus Pinia Vue Router Axios这套组合。Vue在国内的社区活跃度很高中文资料多遇到问题很容易搜到答案。Element Plus的组件覆盖了表单、表格、弹窗、日历、上传等常见场景做管理后台和业务页面效率极高不需要自己从头写UI组件。我建议的package.json关键依赖{ dependencies: { vue: ^3.3.0, vue-router: ^4.2.0, pinia: ^2.1.0, element-plus: ^2.4.0, axios: ^1.4.0, echarts: ^5.4.0, dayjs: ^1.11.0 }, devDependencies: { vite: ^4.3.0, vitejs/plugin-vue: ^4.2.0 } }这里有一个很多人忽略的问题Node版本。Vite 4要求Node 14.18但Node 20以上的某些版本和Vite 4又有兼容性问题。我实测下来Node 16或18最稳。如果你用nvm管理Node版本建议切到16.x或者18.x再跑npm install能省掉一堆莫名其妙的报错。2.3 数据库与中间件够用就行别过度设计很多人在技术选型时会纠结要不要上Redis要不要用ElasticSearch要不要搞消息队列我的看法很直接如果是做项目、做毕设一个MySQL就够用了。Redis在你的业务没有明显热点缓存需求之前加了只会增加复杂度。孕婴护理平台的知识推荐本质上就是按标签和孕周SQL查询数据量几千篇撑死了一个带索引的MySQL查询毫秒级返回根本不需要ElasticSearch。那什么时候需要加Redis我想到两个场景一是登录验证码存缓存二是首页热门文章缓存。这两个场景用Redis确实更优雅但如果你不想引入额外依赖验证码也可以用数据库表实现。我的建议是把核心功能跑通后再考虑加中间件而不是一开始就上一堆组件最后连数据都没填几条。3. 后端核心设计从数据表到接口实现3.1 数据库表设计抓住五个关键表就够了我设计的表结构核心就是五张表用户表、孕妇档案表、产检记录表、提醒任务表、知识文章表。另外加一张文章标签表或者文章里直接存标签ID列表看你要不要做筛选。我把每张表的关键字段列出来这些字段都是实际项目里会用到的最小集可以直接照着建表表名关键字段说明userid, username, password, role, nickname, avatar, create_timerole区分ADMIN/USERpregnant_profileid, user_id, lmp_date, due_date, pre_pregnancy_weight, height, allergy_history, current_week, week_updated_datecurrent_week是冗余字段加快查询checkup_recordid, user_id, checkup_date, weight, abdominal_circumference, fetal_heart_rate, blood_pressure, note每次产检一条记录remind_taskid, user_id, task_date, task_type, task_title, task_content, status, create_timetask_type区分产检/营养/运动knowledge_articleid, title, content, cover, week_start, week_end, tags, view_count, statusweek_start/week_end是适配的孕周范围这里有个设计细节值得展开说current_week为什么要冗余存储因为孕周是根据末次月经日期动态算出来的如果每次都实时算那在列表页、首页、推荐模块都要写一遍计算逻辑而且数据库没法直接按孕周筛选。我选择在更新档案时顺便算出当前孕周存到字段里每天定时任务再统一更新一次。这样查询时直接按current_week过滤不需要在SQL里写复杂的日期函数。另一个需要注意的点是体重、腹围这些数值字段要设计好精度。体重我用DECIMAL(5,1)腹围DECIMAL(5,1)胎心率用INT就行。不要用DOUBLE浮点计算在数据库里容易出精度问题。3.2 项目分包结构与启动配置后端项目结构我习惯这样分src/main/java/com/example/pregnancy/ ├── controller/ # 接口层 ├── service/ # 业务逻辑层 ├── mapper/ # MyBatis-Plus mapper接口 ├── entity/ # 数据库实体类 ├── dto/ # 请求/响应对象 ├── config/ # 配置类跨域、拦截器、自动填充 ├── common/ # 工具类、统一返回结果、异常处理 └── PregnancyApplication.java这种包结构是我做过很多项目后固定下来的习惯。核心原则是controller只做参数接收和结果返回业务逻辑全部放servicemapper只跟数据库打交道。不要图省事把业务逻辑全写在controller里后面改需求或者排查问题时你会非常痛苦。application.yml里最值得注意的有三个地方数据库连接的时区、MyBatis-Plus的日志输出、Jackson的日期格式。spring: datasource: url: jdbc:mysql://localhost:3306/pregnancy?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/Shanghai username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0 spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: Asia/Shanghai关于字符集多说一句数据库连接串里的characterEncodingutf8mb4和建库时的DEFAULT CHARSETutf8mb4必须一致否则存emoji或者生僻字会出现乱码。孕婴护理平台这种场景用户填写的备注里经常有特殊字符用utf8mb4准没错。3.3 核心接口的设计逻辑我实际实现的接口里下面这几个是最核心的把它们的逻辑捋清楚了整个后端就完成了一大半。登录接口PostMapping(/api/auth/login) public Result login(RequestBody LoginDTO dto) { User user userService.lambdaQuery() .eq(User::getUsername, dto.getUsername()) .one(); if (user null || !BCrypt.checkpw(dto.getPassword(), user.getPassword())) { return Result.error(用户名或密码错误); } String token JwtUtil.generateToken(user.getId(), user.getRole()); return Result.success(new LoginVO(token, user.getNickname(), user.getRole())); }密码存库前用BCrypt加密登录时用BCrypt.checkpw校验。这是安全底线不要用MD5MD5在现在来说已经非常容易被彩虹表撞库了。创建档案并计算孕周孕周计算是这个项目的标尺所有智能推荐和提醒都依赖它。计算规则是从末次月经第一天算起到今天为止的总天数除以7向下取整。预产期是末次月经月份减3、日期加7年份相应调整。public int calculateWeek(LocalDate lmpDate) { long days ChronoUnit.DAYS.between(lmpDate, LocalDate.now()); int week (int) (days / 7); return Math.max(week, 0); } public LocalDate calculateDueDate(LocalDate lmpDate) { return lmpDate.minusMonths(3).plusDays(7); }这里有个边界情况要处理如果用户填的末次月经日期是未来时间或者怀孕超过42周还没更新都要做校验。我在前端加了一层日期范围限制后端接口里也做了二次判断。不要指望前端帮你拦截所有非法数据后端必须有校验。产检趋势接口这个接口供前端画ECharts折线图用。返回的数据结构是每个日期的体重和腹围值GetMapping(/api/checkup/trend) public Result getTrend(RequestParam Long userId) { ListCheckupRecord records checkupRecordService.lambdaQuery() .eq(CheckupRecord::getUserId, userId) .orderByAsc(CheckupRecord::getCheckupDate) .list(); ListString dates records.stream().map(r - r.getCheckupDate().toString()).collect(...); ListBigDecimal weights records.stream().map(CheckupRecord::getWeight).collect(...); return Result.success(new TrendVO(dates, weights)); }前端拿到这个结构直接让ECharts绑定两个数组就能画出趋势图不需要前端做二次加工减少出错可能。3.4 定时提醒与智能推荐的实现逻辑提醒模块的设计思路是不搞复杂的规则引擎就用一个每天凌晨跑的定时任务扫描所有孕妇档案根据当前孕周判断需要生成哪些提醒任务。我用的Spring自带的Scheduled没有引Quartz因为这种按天扫表的场景定时效果完全够用Component public class RemindTaskScheduler { Scheduled(cron 0 30 2 * * ?) public void generateDailyTasks() { ListPregnantProfile profiles pregnantProfileService.list(); for (PregnantProfile profile : profiles) { int week profile.getCurrentWeek(); // 按孕周规则生成提醒 if (week 11 week 13) { createTask(profile.getUserId(), NT产检提醒, 当前孕周 week 建议预约NT检查, getToday()); } if (week 16 week 19) { createTask(profile.getUserId(), 唐筛产检提醒, 当前孕周 week 建议进行唐氏筛查, getToday()); } if (week 24) { createTask(profile.getUserId(), 补钙提醒, 孕晚期注意补钙每天600mg, getToday()); } // 更多规则自行添加 } } }生成任务时要注意幂等同一个用户同一天同一类型不能生成重复任务。我在remind_task表加了一个唯一索引(user_id, task_date, task_type)插入时捕获DuplicateKeyException这样定时任务重复执行也不会产生脏数据。知识推荐的实现更简单给每篇文章打一个孕周适用范围比如week_start20, week_end24用户请求推荐时按当前孕周查GetMapping(/api/knowledge/recommend) public Result recommend(RequestParam Long userId, RequestParam int week) { ListKnowledgeArticle articles knowledgeArticleService.lambdaQuery() .le(KnowledgeArticle::getWeekStart, week) .ge(KnowledgeArticle::getWeekEnd, week) .eq(KnowledgeArticle::getStatus, 1) .orderByDesc(KnowledgeArticle::getViewCount) .last(limit 10) .list(); return Result.success(articles); }这种设计朴素但实用。你可以在前端把week参数换成当前用户的孕周用户每次打开知识页看到的就是当前阶段最需要的护理内容。如果后面想做得更智能可以加标签匹配和用户行为反馈的分但那是锦上添花先把按孕周适配这条主干跑通再说。4. 前端Vue架构与核心页面实现4.1 目录结构与路由权限设计前端项目结构我这样组织src/ ├── api/ # 所有接口请求封装 ├── components/ # 公共组件 ├── views/ # 页面组件 │ ├── dashboard/ # 首页仪表盘 │ ├── profile/ # 档案管理 │ ├── checkup/ # 产检记录 │ ├── remind/ # 提醒日历 │ ├── knowledge/ # 知识库 │ └── login/ # 登录页 ├── router/ # 路由配置 ├── store/ # Pinia状态 ├── utils/ # 工具函数 └── App.vue路由这块我用了两种方式结合静态路由放公共页面登录页、首页需要权限的页面在路由守卫里做判断。简单说就是用户没登录时访问任何业务页面都重定向到登录页登录后如果是普通用户能看到自己的档案、产检、提醒、知识页面管理员多一个知识管理和用户管理的入口。router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path /login) { next() } else if (!token) { next(/login) } else { next() } })如果你还要做角色权限细分可以在meta里标记这个路由需要的角色然后在守卫里用角色判断一下。对这类项目来说这个量级的权限控制完全够了不需要引入复杂的动态路由方案。4.2 API请求封装与状态管理axios封装是我每次写前端项目都要做的事。核心目的是统一处理token、统一处理错误码、让接口调用代码尽量简洁。// src/utils/request.js import axios from axios import { ElMessage } from element-plus import router from /router const request axios.create({ baseURL: /api, timeout: 10000 }) request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer token } return config }) request.interceptors.response.use( response { const res response.data if (res.code ! 200) { ElMessage.error(res.msg || 请求失败) return Promise.reject(new Error(res.msg)) } return res }, error { if (error.response error.response.status 401) { localStorage.removeItem(token) router.push(/login) } ElMessage.error(error.message || 网络异常) return Promise.reject(error) } ) export default requestPinia的store我主要存用户信息和token。注意token要同步放到localStorage里因为Pinia是内存态刷新页面就丢了。4.3 核心页面的实现重点首页仪表盘进入后展示当前孕周大数字、预产期倒计时、今天的提醒任务数量、最近一次产检的信息摘要。这些内容基本都是后端接口直接返回聚合数据前端只需要排布展示。孕周数字用今天日期和LMP实时算我为了性能考虑也直接使用后端返回的currentWeek。体重趋势页这是整个平台视觉上最像智能的页面。用ECharts折线图展示每次产检的体重记录再加一条参考范围的上限和下限。参考范围怎么定可以用BMI对应的孕期增重范围或者简单地画一个上下浮动区间。这个页面不需要很复杂但图表做出来效果好演示时观感非常好。提醒日历页按月展示提醒任务这个用Element Plus的日历组件改造即可标有提醒任务的日期打上圆点标记点开看当天任务列表。做这个页面的价值是让用户对接下来的产检安排一目了然。知识库页左侧是孕周筛选条件右侧是文章列表。用户也可以直接搜索标题或标签。文章详情页用v-html渲染富文本内容。这里要注意一点后端返回的文章内容如果是富文本HTML前端必须注意XSS风险。我的做法是保存文章时不接受HTML只接受纯文本换行格式化或者用第三方库对HTML做清洗。4.4 前后端联调中的几个坑第一个坑是跨域。Vite开发服务器默认跑在5173端口后端跑在8080端口直接请求必然跨域。我用了两个方案双保险前端在Vite配置文件里设置proxy代理把/api开头的请求转发到后端后端同时配置CorsConfig允许跨域。// vite.config.js export default { server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }第二个坑是日期格式。前端传给后端的日期字段如果用了new Date()会带时分秒和LocalDate格式不匹配。我统一用dayjs格式化后再传后端Jackson也配置了yyyy-MM-dd的格式。前后端日期格式必须提前商量好这是联调时最容易拉锯的问题。第三个坑是文件上传大小。知识库需要传封面图SpringBoot默认单文件1MB限制如果上传大图会直接报错。我在application.yml里做了调整spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MB5. 直接决定项目成败的细节安全、一致性与性能5.1 登录鉴权与密码安全JWT的方案我在上面已经提过这里展开讲讲完整的链路。用户登录成功后后端生成一个有效期24小时的JWT返回给前端。前端存到localStorage在每个请求头里带上Authorization: Bearer token。后端通过拦截器统一解析token把用户信息放到ThreadLocal里方便后续接口取当前用户ID和角色。拦截器里要做两件事白名单放行比如登录接口、注册接口、文章列表接口不需要token其余接口校验token有效性。校验失败统一返回401前端响应拦截器看到401就清token跳登录页。Component public class JwtInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String auth request.getHeader(Authorization); if (auth ! null auth.startsWith(Bearer )) { String token auth.substring(7); try { Long userId JwtUtil.parseToken(token); UserContext.set(userId); return true; } catch (Exception e) { // token无效 } } response.setStatus(401); return false; } }关于密码我前端注册时也建议不要明文传输。简单做法是前端用SHA-256哈希再传到后端后端再用BCrypt加密存储。注意SHA-256在前端传输并不能防中间人攻击但至少能防止日志里出现明文密码。这个安全度对这类项目已经够用了。5.2 数据一致性并发场景怎么防重复这类项目虽然并发量不高但有两个场景容易出数据问题我实际开发时都遇到了。场景一是用户快速双击提交产检记录导致同一记录插入两条。解决办法前端按钮提交后置灰后端在数据层面加约束。我在checkup_record表加了(user_id, checkup_date)唯一索引如果同一天重复插入数据库直接报错后端捕获异常返回友好提示。场景二是定时任务生成提醒时如果服务器做了集群部署或者任务意外重跑会产生重复提醒。这个我前面提到过用唯一索引捕获DuplicateKeyException解决。这里的关键哲学是永远不要依赖代码层面的先查再插来判断是否存在两个请求之间有时间窗插入时让数据库来兜底最保险。事务管理方面涉及多表更新时要用Transactional。比如创建档案时要同时更新user表和pregnant_profile表一个失败另一个必须回滚。注意Transactional默认只回滚RuntimeException如果方法里抛了受检异常是不会回滚的需要指定rollbackFor Exception.class。Transactional(rollbackFor Exception.class) public void createProfile(ProfileDTO dto) { // 更新用户信息 // 插入档案信息 }5.3 性能优化什么时候需要加缓存这种体量的项目性能问题往往出在SQL上而不是系统层面。我建议优先做三件事成本低收益高。第一给所有表的逻辑外键字段加索引——user_id、task_date、week_start、week_end这些经常出现在WHERE条件里的字段都要有索引。第二列表接口一定要分页MyBatis-Plus的Page对象用法很简单不要一次性返回全表数据让前端自己翻。第三知识文章列表只查必要字段列表页不返回content大字段详情接口再单独返回全文这样列表接口会明显变快。做完这三步知识列表在万级数据量下都能毫秒级返回。这时候Redis加不加都不影响体验。如果一定要加我建议先做查询频率最高的首页聚合数据和热门知识列表的缓存设置5分钟过期时间续期策略用被动刷新即可。不要试图一开始就设计完美的缓存架构先跑通再说。6. 从开发到部署我踩过的坑与验收清单6.1 环境版本不匹配的连环坑开发过程中我踩过最耗时间的坑几乎全是版本问题。这里列一个我实测稳的版本组合清单组件推荐版本避坑说明JDK8不要用JDK17跑SpringBoot 2.x项目会出一堆奇怪的反射错误Maven3.63.8以上需要注意中央仓库的HTTPS配置Node.js16.x/18.xNode 20配合Vite 4有时会报digital envelope routines错误npm8.x跟随Node版本自动带的就行MySQL8.05.7兼容性也没问题但8.0对utf8mb4支持更好如果你用的是SpringBoot 3.x需要把javax包名改成jakarta拦截器、JWT库的选择都要换。如果不是特别原因我不推荐在毕设阶段用3.x教程和资料都少很多排错成本高。还有个很隐蔽的坑Maven项目里Lombok版本要和JDK匹配。JDK8环境用1.18.30是没问题的但如果你用高版本Lombok配合JDK8编译时会报java.lang.ExceptionInInitializerError之类的错误。解决办法是锁定Lombok为1.18.x版本。6.2 数据库字段设计时就要留出余地我做了太多项目后养成了一个习惯任何业务表都会有三个通用字段宁可不用也不要后期加。status状态字段默认0后续有逻辑上线下线需求直接能用deleted逻辑删除标记MyBatis-Plus有全局逻辑删除配置改写不删避免外键关联问题create_time / update_time时间字段配合MyBatis-Plus自动填充不需要代码里手动set时间Component public class MyMetaObjectHandler implements MetaObjectHandler { Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now()); this.strictInsertFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } }这套配置在实体类字段上用TableField(fill FieldFill.INSERT)标注一下代码里就不用在每个service里手动赋值了。省代码是其次关键是不会漏。6.3 部署与演示环境搭建最后说说部署。演示项目最省事的方案是后端打jar包前端打包后放到后端的静态资源目录里一个进程跑完整个系统。好处是演示时不担心端口跨域问题拷贝目录就能迁移。后端打包跳过测试mvn clean package -DskipTests然后后台运行jar包nohup java -jar pregnancy-platform-1.0.0.jar app.log 21 前端构建完的dist目录直接拷贝到src/main/resources/static目录下重新打包后端SpringBoot会自动托管静态文件。这是最省事的方案。如果你希望前端独立部署那就用Nginx托管dist目录配置一个代理转发/api到后端服务。两种方式我都在项目里用过如果是给别人演示、答辩强烈推荐第一种如果后续准备长期线上运营建议用Nginx。演示数据的初始化也很重要。我在数据库里预置了一个测试账号档案里的末次月经日期设置为30周前这样登录进去不用手动填数据首页就有完整的孕周信息、产检记录、提醒任务和推荐知识可以展示。这个测试账号一定不要忘了在答辩前准备好不然现场从注册开始演示体验会差很多。这次做完这个平台后我最大的一条心得是做业务系统先把业务语言翻译成技术语言再动手写代码。孕婴护理平台这种项目技术难度不算高但业务逻辑的完整性和细节打磨决定它的上限。如果你也是第一次做这类项目不如先花一天时间把角色流程图和数据关系图画清楚后面写代码会顺很多。等你把主体功能跑通自然会发现哪些地方需要补充智能化再迭代也不迟。
返回列表