资讯动态

Node.js+Vue养老院服务系统:设计与实现全解析

发布时间:2026/9/30 4:52:14 来源:尧图企业网站定制
干过几个前后端分离的实战项目之后再看nodejs基于vue的养老院服务系统的设计与实现这种题目我第一反应是这不就是典型的毕设/课设级全栈项目吗很多人一拿到这种题就急着找代码、扒模板结果把系统做成了Excel表格录入页面——没有任何业务逻辑也没有权限边界答辩的时候一问就露馅。所以这篇我打算换个思路不贴一整段让你直接复制的完整代码。我更想把这套东西拆开讲清楚——为什么这个系统适合用Node.js Vue这套组合来做、模块到底怎么切、表结构怎么设计、前后端联调的时候哪些地方最容易卡壳、以及上线部署前你还需要补哪些课。我自己在带人做同类项目时发现大家踩的坑都高度一致环境装不明白、跨域调不通、权限一张纸、路由守卫没概念。这篇文章就是把这些坑一个个填平。1. 养老院服务系统的需求边界先搞清楚你要做的是管理系统还是业务平台1.1 第一件事不是写代码是把人和事分清楚养老院服务系统看起来是一个系统但实际上使用者至少分四类管理员院方负责全院数据总览、护工分配、费用审核、床位管理。护工接收排班任务、填写老人日常护理记录、上报异常情况。老人/家属查看老人档案、费用明细、健康记录有些系统还会做探访预约、请假申请。系统运维角色基本可以归入管理员但权限上要单独留接口。很多初次做这个题的人犯的第一个错误就是只建一张user表加一个role字段完事。但你在设计数据库的时候如果不在逻辑上把这几类人彻底分开后面做的每个页面都会越写越拧巴——护工给家属端留了删除按钮、家属端直接能看到整个养老院的床位图这类事故我见太多了。我的建议是在建表前先画一张简单的业务流转图不需要用专业工具纸笔都行把四个角色和核心实体老人、床位、排班、费用、护理记录、家属之间的关系落到纸面上一个老人对应一个床位但可能有多个家属账号一个护工可以负责多个老人但一个老人同一时间只归属于某个护工小组费用账单按月生成关联护理等级和床位费排班记录关联到护工和日期而不是关联到老人。这些关系都捋清楚了你再去写model和router心里才会有底。1.2 核心模块一共就那么几个档案、排班、费用、健康记录养老院业务看着复杂抽掉枝枝叶叶核心模块不会超过六块模块名称核心功能对应主要角色老人档案管理入住登记、家属绑定、护理等级评估、退住办理管理员、护工床位管理床位分配、空闲/占用状态维护、楼层/房间维度管理员护工排班排班表生成、换班申请、考勤统计管理员、护工健康/护理记录日常护理登记、体征数据录入、异常预警护工、家属费用管理月度账单生成、缴费记录、欠费提醒管理员、家属消息/公告院内通知、个人消息推送全部角色我为什么要强调模块而不是功能列表因为很多人在设计时把功能列得无比细致——多达三四十个菜单项但数据表就三张。真按这个方案做完前端页面会大量重复后端接口也会变成一个巨型控制器。如果按照上面六大模块去切每个模块单独一套controller/service/router/views代码的可维护性会好很多答辩的时候也更容易说清楚我的系统是怎么分层的。1.3 业务流程闭环从入住到退住你要走通一条线我自己判断一个养老院系统做得好不好不看功能多不多而是看能不能把入住-在住-退住这条主线走通老人入院管理员登记身份证信息、上传体检报告、建立档案管理员分配床位床位状态自动从空闲切为占用为老人指定护理等级自理/半自理/全护理费用模块根据档案生成首月账单护工开始按排班表记录每日护理情况家属通过家属端查看记录、在线缴费老人退住时系统生成结算单床位释放。你把这个闭环讲清楚了系统就不是一堆孤立页面的拼凑而是一个有业务语义的产品。这也是我反复和做毕设的朋友强调的一句话页面只是表现流程才是灵魂。2. 技术选型逻辑为什么我用Node.js Vue而不是Spring Boot2.1 这套组合在中小型系统里的真实优势现在很多课设和毕设依然首选Spring Boot但我得说句公道话如果你的目标是快速交付一个逻辑完整、可演示、可部署的前后端分离项目Node.js Vue的组合其实更顺手。第一前后端语言统一。后端用Node.js写接口前端用Vue写页面两边都是JavaScript/TypeScript数据类型、命名风格、JSON结构可以直接对齐你不需要在后端定义了一个long类型前端却按string处理这种问题上浪费时间。第二生态工具链成熟。Vue有Vite和Vue CLINode有Express或Koa数据库用MySQL配Sequelize或MongoDB配MongooseJWT做登录鉴权Nodemon做热更新——整个工具链你一天就能搭完。对比Spring Boot要处理Maven依赖、Tomcat配置、XML/注解一堆东西Node.js的启动速度确实是秒级的。第三更贴近前后端分离的真实协作模式。现在企业里前后端分离已经是标配前端团队和后端团队各维护一套代码。你在这个项目里用Node.js写RESTful API用Vue写SPA联调用Axios本身就是对真实工程协作方式的一次模拟。2.2 后端选型Express还是KoaExpress和Koa都是Node.js里非常成熟的Web框架。我的个人习惯是项目用Express因为它中间件生态最全、入门资料最多、出问题一搜就有解决方案。Koa的优势在于洋葱模型和async/await写起来更现代但它的核心库非常精简很多功能要自己组合中间件。对做课设/毕设的同学来说Express的req.params、res.json()、next()这三个API你十分钟就能掌握。不要在这种选择上纠结太多选成熟的那个把时间留给业务逻辑。2.3 前端选型Vue 3 Vite Element Plus现在做Vue项目我建议直接用Vue 3。Vue 3的组合式APIComposition API配合script setup写起来比Vue 2的选项式APIOptions API更简洁状态管理用Pinia路由用Vue Router 4UI组件库用Element Plus。这套组合几乎就是目前中型后台管理系统的主流标配。这里多说一句项目热词里有很多同学搜vue组合式和选项式混合开发说明大家容易在Vue 2和Vue 3之间摇摆。我的建议是做新项目就固定用Vue 3 组合式API不要混合。混合两套写法最常见的后果是同一个项目里某组件用export default { data(), methods }另一个组件用setup后续维护的人每次都要先分辨这是哪种写法才能改代码。2.4 数据库MySQL还是MongoDB如果只是做一个单机运行的课设MySQL就够了原因很简单养老院管理系统的数据以结构化数据为主——费用账单、床位状态、排班记录用表格存最自然你答辩的时候MySQL Sequelize这种组合不会给自己挖坑MySQL的图形化工具Navicat / Workbench能让你在出问题时快速看库里的数据对不对。MongoDB适合档案、健康记录这类文档结构较多的场景但如果你的数据量不大、关联关系又复杂强行上MongoDB反而会让联表查询变成一场灾难。我可以负责任地说一句以这类系统的复杂度MySQL是永远不会选错的方案。3. 环境搭建中最容易翻车的细节Node.js安装、npm配置、前端脚手架3.1 Node.js版本选择不是越新越好很多人在第一步就被Node.js困住了而且栽在版本选择上。我见过有人装了最新的Node 22结果某些原生模块编译不通过也有人装了很老的Node 12导致Vite要求Node 18直接启动失败。我的建议是装LTS版本比如Node 18或Node 20不要追最新版。判断标准很简单——打开 nodejs.org 看左侧标着LTS的那个版本号直接下载那个。LTS版本意味着社区验证充分、第三方依赖兼容性最好。装完之后在终端验证node -v npm -v如果两个命令都能输出版本号说明安装成功。注意Windows安装包默认会勾选Add to PATH选项这一步一定要保留勾选否则后续命令行里找不到node命令。3.2 全网高频报错npm.ps1无法加载PowerShell禁止运行脚本这个报错出现频率高到什么程度在Node.js相关热搜词里几乎长期占据前三npm : 无法加载文件 D:\Program Files\nodejs\npm.ps1 因为在此系统上禁止运行脚本。这个问题的本质不是npm坏了而是Windows PowerShell的执行策略Execution Policy默认阻止了.ps1脚本运行。你在cmd里执行npm -v可能没问题但一换到PowerShell就报这个错。解决方案是打开PowerShell以管理员身份执行Set-ExecutionPolicy RemoteSigned然后输入Y确认。RemoteSigned的含义是本地创建的脚本可以运行从网上下载的脚本必须有数字签名。这是一个相对安全的策略适用于开发场景。如果你不想改全局策略也可以只针对当前用户设置Set-ExecutionPolicy -Scope CurrentUser RemoteSigned设置完成后重新打开PowerShellnpm -v就正常了。这个坑我会建议每个做Node.js项目的朋友都先踩一遍再填平因为它几乎必然出现在每台新电脑上。3.3 镜像源和全局配置先配好这两样再动手安装完Node.js后建议立刻做两件小事配置npm镜像源。国内直连npm官方源经常超时换成淘宝镜像npmmirrornpm config set registry https://registry.npmmirror.com验证方式npm config get registry最好再建立单独目录来管理全局包npm config set prefix D:\nodejs_global npm config set cache D:\nodejs_cache这样做的好处是全局安装的包比如vue/cli、pm2、nodemon不会堆到C盘系统目录里后续装新模块时也不会出现权限报错。安装Vite并创建Vue项目。我个人推荐用Vite创建项目比Vue CLI更快npm create vitelatest elder-care-frontend -- --template vue cd elder-care-frontend npm install npm run dev如果你更习惯Vue CLInpm install -g vue/cli vue create elder-care-frontend两种方式都能用Vite是目前的趋势。项目创建完能正常打开页面后再做下面的后端部分不要两个一起开工——一面前端跑不起来一面后端报错排查起来会非常痛苦。3.4 后端项目初始化Express Sequelize后端项目基本结构我习惯这样建elder-care-server/ ├── app.js # 入口文件 ├── config/ │ └── db.js # 数据库配置 ├── models/ # 数据模型Sequelize Model ├── controllers/ # 控制器处理业务逻辑 ├── routes/ # 路由定义 ├── middleware/ # 中间件JWT校验、错误处理 ├── utils/ # 工具函数 └── package.json初始化非常简单mkdir elder-care-server cd elder-care-server npm init -y npm install express mysql2 sequelize cors jsonwebtoken bcryptjs npm install nodemon --save-devexpress核心Web框架mysql2MySQL驱动给Sequelize用sequelizeORM让你用JS对象操作表记录cors解决跨域请求问题前后端分离必装jsonwebtoken生成和校验JWTbcryptjs密码加密不要明文存密码nodemon文件变更自动重启服务开发神器。3.5 数据库创建编码问题一定要盯着看用Sequelize连数据库之前先手动建库CREATE DATABASE elder_care DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;注意一定要用utf8mb4而不是utf8。很多人的系统出现中文乱码、emoji存不进去查半天发现是库的字符集用的是老的utf8。在创建库时就选utf8mb4_unicode_ci后面所有表都默认继承这个编码可以少掉一大半中文字符集问题。4. 核心接口设计与前后端联动从登录到业务模块走一遍4.1 JWT登录鉴权前后端分离的标准姿势传统Session登录适合服务端渲染的架构前后端分离之后接口无状态化是基本要求。JWT的方案是登录成功之后后端签发一个token前端存到localStorage或Pinia中之后每个请求都在Authorization头带上token后端中间件校验通过才放行。后端登录接口示意// controllers/authController.js const jwt require(jsonwebtoken); const bcrypt require(bcryptjs); const { User } require(../models); exports.login async (req, res) { const { username, password } req.body; const user await User.findOne({ where: { username } }); if (!user) return res.status(401).json({ message: 用户不存在 }); const isValid bcrypt.compareSync(password, user.password); if (!isValid) return res.status(401).json({ message: 密码错误 }); const token jwt.sign( { id: user.id, role: user.role }, process.env.JWT_SECRET || elder-care-secret, { expiresIn: 2h } ); res.json({ token, user: { id: user.id, username: user.username, role: user.role } }); };前端Axios拦截器统一带token// utils/request.js import axios from axios; 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; }); export default request;4.2 路由守卫前端页面不能让登录用户乱闯只验证后端接口是不够的前端还要做路由级拦截。Vue Router 4里的守卫写法// router/index.js router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (to.meta.requiresAuth !token) { next(/login); } else if (to.meta.role to.meta.role ! localStorage.getItem(role)) { next(/403); } else { next(); } });这样访问受保护页面时如果没有token会直接跳登录页如果需要管理员角色但当前登录的是护工则跳到403页面。前后端双保险才是完整的权限方案只做前端不做后端接口被直接调用就暴露了只做后端不做前端页面体验就很差。4.3 RESTful接口设计以老人档案为例我习惯的接口风格是这样的RESTful语义 统一返回格式方法路径说明POST/api/elders新增老人档案GET/api/elders分页查询老人列表GET/api/elders/:id查询老人详情PUT/api/elders/:id更新老人档案DELETE/api/elders/:id删除老人档案建议逻辑删除统一返回格式也很有必要否则前端每次都要判断不同字段的存在性// utils/response.js exports.success (res, data, message ok) { res.json({ code: 0, data, message }); }; exports.error (res, message, code 1) { res.status(200).json({ code, message, data: null }); };把code放到响应体里网络状态码一直保持200前端只用判断code是否为0很省事。4.4 Vite代理解决跨域开发环境的No.1问题前后端分离开发时前端跑在localhost:5173后端跑在localhost:3000Axios直接请求http://localhost:3000必然触发跨域。虽然你后端装了cors中间件可以放行但更推荐的做法是在Vite里配代理让前端代码里用相对路径/api开头由Vite dev server转发到后端// vite.config.js export default defineConfig({ plugins: [vue()], server: { port: 5173, proxy: { /api: { target: http://localhost:3000, changeOrigin: true } } } });这样前端里请求/api/elders开发环境中实际上被转发到http://localhost:3000/api/elders。跨域问题消失且代码里不需要写死后端地址部署时也更灵活。4.5 联调排查路线前端报错先别急着改代码我在给朋友做联调指导时总结了一个接口排查五步走打开浏览器开发者工具F12看Network里请求有没有发出看请求URL是否正确、请求头里有没有token看响应体里的code是什么——业务错误还是网络错误后端看终端日志有没有走到对应的路由用Postman/Apifox单独测同一个接口确认是后端问题还是前端问题。很多同学一遇到前端页面数据没显示第一反应就是改前端代码结果查了半天是后端接口500了。记住数据链路是页面 - 接口 - 数据库排查也要按这个顺序来。5. 运行过程中的疑难杂症那些反复出现的报错和处理思路5.1 Node.js版本升级Windows上的版本切换热搜词里有windows如何升级nodejs版本说明很多人被版本问题困扰。Windows不像Linux有nvm那么顺滑最常见的两种方式是去 nodejs.org 下载最新LTS安装包直接覆盖安装node -v就会变成新版本用nvm-windows工具管理多版本nvm install 20、nvm use 20。我的建议是如果只是需要升到最新LTS直接覆盖安装最省心如果需要在多个项目之间切换不同Node版本确实有老项目要求Node 14那再上nvm-windows。5.2 Vue Devtools装不上确认版本匹配Vue项目里调试状态和数据vue-devtools几乎是必装的浏览器扩展。很多人在Chrome应用商店装完却发现图标是灰色的根本原因是版本不匹配——Vue 2项目要装Vue.js devtools 6.xVue 3项目要装Vue.js devtools 7.x以上版本。最稳妥的判断方法打开一个已启动的Vue 3项目页面如果Vue Devtools图标变亮并能打开组件树那说明匹配成功。如果图标灰色就换一个版本再试。5.3 端口冲突启动失败的头号嫌疑Vite默认5173Express默认3000。如果你之前启动过别的项目这两个端口可能被占用。报错信息里通常直接告诉你Port 3000 is already in use解决办法有两个# 找到占用进程并结束 netstat -ano | findstr :3000 taskkill /PID PID /F或者在启动命令中指定别的端口// package.json dev: nodemon app.js然后在app.js里const PORT process.env.PORT || 3000;5.4 前端页面上有数据但页面空白路由匹配、容器撑不开、循环key缺失三个最常出现的情况动态路由没配置对刷新/elders/:id页面时组件没匹配上URL对但页面空。El-Table/卡片容器高度为0父容器没有撑开内容渲染了但视觉上空白。列表循环缺:keyVue警告但不至于白屏不过性能和数据更新会出问题。这类问题用Vue Devtools看组件树非常有效组件树里有节点但页面不显示优先怀疑CSS布局。如果组件树压根没有这个节点优先怀疑路由和数据请求。5.5 M3U8视频播放如果系统里要嵌入监控/视频流热搜词里出现了vue播放m3u8播放器。如果养老院系统要做到房间摄像头画面实时查看或家属远程探视这类功能通常会涉及m3u8格式的视频流。Vue 3中推荐hls.js这个库核心用法是npm install hls.jsimport Hls from hls.js; const video document.getElementById(video); if (Hls.isSupported()) { const hls new Hls(); hls.loadSource(http://your-server/live/room1.m3u8); hls.attachMedia(video); }注意视频流地址务必通过后端接口返回不要把内网IP和端口硬编码在前端这也是安全性的一部分。5.6 Electron打包Vue如果之后想做成桌面端热搜词里还有electron打包vue项目。这个方向我不建议在毕设主流程里做但如果你学有余力确实可以把Vue项目用Electron包成Windows桌面应用npm install electron --save-devElectron主进程负责创建窗口渲染进程就是你的Vue应用。生产环境直接加载dist目录的文件开发环境则加载http://localhost:5173。两者之间用IPC通信记住一个原则DOM操作在渲染进程系统能力文件、窗口、数据库在主进程。这个扩展如果做得顺是可以写进答辩项目创新与扩展部分的。但前提是核心的养老院业务系统已经稳定跑通不要本末倒置。6. 上线之前这些细节决定系统是能跑还是经得起问6.1 密码加密、参数校验、错误处理三件套很多课设系统最大的问题不是功能缺失而是太脆弱。我验收别人的项目时第一件事就是打开注册接口看密码以什么形式落库——如果直接明文存MySQL我基本可以确定这个项目的安全意识是零。正确的做法是使用bcryptjs做哈希const bcrypt require(bcryptjs); const hashedPassword bcrypt.hashSync(password, 10);参数校验也必须做。Express 4的写法是在路由层用中间件校验或者直接在控制器里判断必填字段if (!req.body.name || !req.body.idCard) { return res.status(400).json({ code: 1, message: 缺少必要参数 }); }这些逻辑不能省也不难写。答辩时老师问你的系统安全性体现在哪里你能说出密码哈希加密 JWT过期 参数校验 权限控制就已经超过九成同题目的作品了。6.2 分页、模糊搜索、数据隔离管理系统必备三件套如果做一个列表页只写SELECT * FROM elders然后一次全量返回那数据量稍微上来一点系统就会卡。管理系统里分页是基本要求// controllers/elderController.js const { Op } require(sequelize); exports.list async (req, res) { const { page 1, pageSize 10, keyword } req.query; const offset (page - 1) * pageSize; const result await Elder.findAndCountAll({ where: { [Op.or]: [ { name: { [Op.like]: %${keyword}% } }, { idCard: { [Op.like]: %${keyword}% } } ] }, limit: Number(pageSize), offset: offset, order: [[createdAt, DESC]] }); res.json({ code: 0, data: { list: result.rows, total: result.count, page: Number(page), pageSize: Number(pageSize) } }); };前端配合Element Plus的el-pagination组件使用接口层和展示层就都能交差了。前端配合Element Plus的el-pagination组件使用。findAndCountAll是Sequelize自带的分页计数查询一条语句同时返回列表和总数比query两次要干净很多。数据隔离这一条容易被忽略——护工登录后只能看自己负责的老人而不能看全院的老人列表这就要在查询条件里额外加一层where条件if (req.user.role caregiver) { where.caregiverId req.user.id; }这种按登录角色动态拼接查询条件的做法才是多角色系统该有的样子。6.3 日志记录与软删除答辩时的高级话题你可以在项目里加入一个简单的操作日志表operation_logs记录用户的增删改操作。实现方法在需要记录的接口里调用logger工具或者在Express中间件层统一处理改动用POST/PUT/DELETE方法判断。这不会花太多时间但答辩时你可以说系统具备操作审计能力这个点是实打实的加分项。删除功能建议用软删除给表加一个deletedAt字段删除时只更新这个字段而非物理删除。Sequelize里只要在模型中配置paranoid: true就能自动实现。老人档案这种数据是不能说删就删的——万一误删影响的是真实业务。6.4 部署上线云服务器 PM2 Nginx 的经典组合如果你想在答辩时当场演示一个互联网可访问的系统而不是一直localhost那部署是绕不开的。经典方案是准备一台云服务器2核4G肯定够服务器安装Node.js、MySQL、Nginx后端项目用PM2守护进程pm2 start app.js --name elder-care-server前端项目执行npm run build生成dist目录Nginx配置将/api请求反向代理到http://localhost:3000其余路径指向dist目录的静态文件。Nginx关键配置片段server { listen 80; server_name your-domain.com; root /var/www/elder-care-frontend/dist; index index.html; location /api { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { try_files $uri $uri/ /index.html; } }这样前端的历史路由模式createWebHistory刷新时也不会404。PM2还可以帮你在服务器意外重启后自动拉起服务这一点在答辩演示时很实用——不会出现现场重启后系统起不来的尴尬场面。6.5 一个我建议你尽早做的演示数据脚本很多人做这类系统最后栽在数据库里空荡荡演示的时候页面大片空白。我的建议是写一个seed.js脚本预置好admin账号、若干个护工账号、几十个老人档案、一大片床位数据和费用记录并保证数据之间有真实的关联关系。这样做有两个好处一是演示时打开页面就是丰富的数据不用临时手工录入二是答辩评委会觉得这是一个经过实际测试的系统而不是一个空壳原型。我见过太多人在答辩现场因为添加按钮点了没反应列表里没有数据这种低级问题扣分一个预置数据脚本就能避免。6.6 时间规划完成这个项目的合理节奏最后给你一个实操层面的时间建议以每周能投入10~15小时为例第1周需求分析、模块拆分、建表、环境安装第2~3周后端接口开发先做登录和老人档案模块跑通后再扩展第4~5周前端页面开发登录页、布局框架、各模块页面第6周前后端联调、修登录态、调跨域、填权限第7周部署上线、预置数据、写答辩稿/文档。这个节奏不算紧张但对每个环节都要有产出。我最怕遇到的情况是学生花了两周去折腾用哪个UI框架是Vue 2还是Vue 3要不要上TypeScript——这些决策最多花半天就该定下来剩下的时间都应该给业务模块。做项目最怕的不是技术难而是方向来回摇摆。这套组合跑通的真实体感是第一周你觉得全是坑第二周理顺了以后后面每个模块开发基本是复制粘贴加改字段。Node.js生态的好处就在这——核心框架学完一次写业务逻辑就是在填数据。如果你正在做同类项目跟着上面这些模块一个个打通再按最后这节的部署方案丢到云服务器上你应该能体会到从代码到产品那条路走通的完整过程。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑