ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Node.js+Vue养老院管理系统:膳食管理与护工评价实战

Node.js+Vue养老院管理系统:膳食管理与护工评价实战 1. 项目概述与整体设计1.1 项目背景与需求拆解养老院这个场景很多人第一反应是“不就是管吃管住嘛”但真正深入进去你会发现它的信息化管理远比想象中复杂。以老年人膳食管理为例不同老人有不同慢性病有人糖尿病不能吃含糖高的有人高血压要控盐有人牙口不好只能吃软食食谱安排得一人一策。而护工评价这块就更典型了——护工服务质量直接影响老人生活质量但评价数据散落在纸质表格里月底统计一次要翻好几本记录本既低效又容易遗漏。这个项目的核心目标就是把“膳食管理”和“护工评价”两个高频业务场景搬到线上做一个轻量但完整的管理系统。管理员能维护老人档案、制定每周食谱、登记每日用餐情况家属或管理人员能对护工进行多维度评分系统自动生成统计报表让管理者一眼看清“这个月护工整体表现如何”“哪类膳食满意度偏低”。技术选型上题目已经给定后端Node.js前端Vue。这个组合最适合这类中小型管理系统的原因是前后端都用JavaScript语言栈统一一个人就能全栈搞定Node.js的npm生态里现成的轮子多Express框架写RESTful API非常快Vue组件化开发做后台管理界面效率极高。整个项目能在一个月内从零到可用对毕设、对小型团队内部系统来说都是性价比很高的路线。这个系统适合谁参考一类是正在做毕设的计算机专业学生这套题目的完整度可以当全栈实训范本另一类是想给自家非IT行业单位做信息化的开发者比如医养机构的技术人员照着这个思路搭一套内管系统完全可行。1.2 技术选型为什么是Node.js Vue而不是其他方案很多人会问这种管理系统用Java Spring Boot Vue不是更主流吗为什么选Node.js坦白说Java在后端领域确实老成但Node.js在这个规模的项目上有它独特的优势。首先内存占用低一个养老院内部系统撑死几十个并发用户Node.js单线程事件循环处理这种IO密集型请求绰绰有余服务器成本可以压得很低。其次是开发效率——Express框架中创建一个CRUD接口只需要几行代码配合Nodemon自动重启改完代码立刻生效开发节奏非常快。再一个很实际的原因如果前端你已经选择了Vue那么前后端统一用JavaScript/TypeScript意味着数据模型定义、工具函数、甚至某些业务逻辑都能前后端复用沟通成本几乎为零。Vue这边选用Vue 3 Element Plus是比较稳妥的选择。Vue 3的组合式APIComposition API让代码组织更清晰一套组件逻辑可以按功能聚合而不是按选项分散。Element Plus则直接提供了Table、Form、Dialog、Pagination这些后台管理开发中90%要用到的组件写页面基本是在“拼积木”。另外提一个容易被忽略的点这套技术栈的人才供给。养老院这类单位后续要维护系统招一个懂Vue的工程师远比招一个会Java微服务的人容易用工成本也低一截。1.3 系统功能模块与角色权限架构这个系统的用户角色我最终拆成了四个系统管理员、膳食管理员、护工、评价人员可以是护士长或家属代表。四类角色对应不同的功能边界这是管理系统的地基一定要在设计阶段就理清。系统管理员管全局用户管理、角色分配、数据看板。膳食管理员负责菜谱维护、食材计划、每日用餐登记。护工角色最轻主要查看自己的排班、查看被评价的结果与改进建议。评价人员负责对护工评分、填写评价意见。权限这块我采用RBAC基于角色的访问控制模型数据库里建role表存角色信息user表通过role_id关联角色。前端根据角色控制菜单渲染后端在API层做二次校验——前端控制只能防君子真正的安全防线在后端。功能模块拆成六个老人档案管理、食谱与膳食管理、护工信息管理、排班管理、评价中心、系统管理。其中评价中心是核心中的核心后面我会单独展开讲。2. 数据库设计与Node.js后端实现2.1 数据表结构设计与关系梳理数据库我用MySQL 8.0设计工具用Navicat直接建库。表结构是重头戏我列几张核心表的字段做个说明照着抄基本不会出大问题。用户表sys_user字段类型说明idbigint PK自增主键usernamevarchar(50)登录名唯一索引passwordvarchar(100)BCrypt加密后的密码real_namevarchar(50)真实姓名role_idint关联角色表phonevarchar(20)联系方式statustinyint0禁用 1启用create_timedatetime创建时间老人信息表elderid、name、gender、age、bed_no床号、health_status健康状态、dietary_notes饮食禁忌如“糖尿病忌甜食”、guardian_phone家属电话、create_time。食谱表recipeid、meal_type早餐/午餐/晚餐/加餐、dish_name、ingredients食材清单、calories卡路里、nutrition_info营养成分JSON、适用人群标签糖尿病适用/高血压适用/普通、week_day周几1-7、status0停用 1启用。膳食记录表meal_recordid、elder_id、recipe_id、actual_meal_time、portion实际用餐量、remark备注如“今天没胃口只吃了一半”。护工表caregiverid、user_id关联登录账号、name、gender、id_card、hire_date、level星级、status。评价维度表evaluation_dimensionid、dimension_name如“服务态度”、max_score满分默认10分、sort_order。评价记录表evaluation_recordid、caregiver_id、elder_id被谁评价、evaluator_id评价人用户ID、score总分、attitude_score、skill_score、response_score、communication_score、content文字评价、evaluation_date。表关系上精髓在于评价记录表用一列存一个评分维度而不是拆成多张表——这个项目最多四五个评价维度拆表反而增加联表查询的复杂度。另外设计时别忘了加索引常用查询条件如elder_id、caregiver_id、evaluation_date都要建索引数据量过万后差别很大。2.2 基于Express的API层设计与工程结构后端工程结构我推荐分层清晰、不搞花活的写法server/ ├── app.js # 入口创建Express实例 ├── routes/ # 路由定义按模块分文件 │ ├── auth.js # 登录/注册 │ ├── elder.js # 老人档案 │ ├── recipe.js # 食谱管理 │ ├── mealRecord.js # 膳食记录 │ ├── caregiver.js # 护工管理 │ └── evaluation.js # 评价中心 ├── controllers/ # 控制器处理请求参数、调用service ├── services/ # 业务逻辑层写核心业务 ├── models/ # 数据模型封装SQL查询 ├── middleware/ # 中间件JWT鉴权、错误处理、日志 ├── config/ # 数据库连接配置 └── utils/ # 工具函数jwt生成、密码加密等API设计遵循RESTful规范用几个示例说明POST /api/auth/login—— 登录返回JWT tokenGET /api/elders?page1pageSize10—— 分页查询老人列表POST /api/recipes—— 新增食谱GET /api/evaluations/caregiver/:id?month2025-01—— 查询某护工某月的评价记录GET /api/evaluations/stats?typemonthtime2025-01—— 评价统计数据聚合接口JWT鉴权是这套系统的安全核心。用户登录后后端用jsonwebtoken库生成token载荷里包含userId和roleId设置过期时间12小时。前端把token存在localStorage每次请求在Axios拦截器里带上Authorization: Bearer token。后端写一个authMiddleware在需要鉴权的路由上挂载每次请求校验token合法性并解析出用户信息。密码存储这块千万不要用MD5或者SHA1直接用bcryptjs做哈希加盐处理单条密码哈希耗时约100ms对用户无感知但对撞库攻击来说成本高到不值得。2.3 膳食管理模块的核心逻辑实现膳食管理这个模块需求看起来是“维护菜谱”“记录用餐”但真正难的是“记什么”。对于每个老人我设计了dietary_notes字段来标记饮食禁忌这是一个非常关键的字段。健康老人记录“无禁忌”糖尿病老人记录“低糖、无糖主食优先”高血压老人记录“低盐”。在食谱表里每条菜谱存applicable_tags字段标注这道菜适合哪类人群。这样膳食管理员排菜谱时系统能自动提示“这道红烧肉不适合糖尿病老人”避免人为疏忽。每周食谱生成是一个很讨好用的功能。我在route层提供一个GET /api/recipes/weekly接口后端用SQL把当前周的七天食谱按meal_type分组查出来组装成前端要好渲染的结构{ monday: { breakfast: [小米粥, 煮鸡蛋, 馒头], lunch: [红烧鱼块, 清炒时蔬, 米饭], dinner: [紫菜蛋花汤, 蒸南瓜, 花卷] }, tuesday: { ... }, ... }每日用餐登记的另一个可设亮点是“用餐量反馈”。老年人生病、心情不好、饭菜不合口味都会体现在用餐量上。我让护工在老人每餐后勾选用餐量全部吃完/大部分/一半/基本没吃后台把出餐量和实际用餐量对比就能看出来伙食的满意度趋势。做得好的话这个数据能直接反哺护工评价里的“膳食满意度”维度。3. Vue前端工程与核心界面实现3.1 工程初始化、UI组件库与项目目录规划前端用Vite Vue 3创建工程。有件事提醒一下——Vite相比Vue CLI最大的优势是冷启动极快基于ES模块的按需编译不用像webpack那样启动前全量打包改代码浏览器即时刷新开发体验完全不一样。创建命令很简单npm create vitelatest elder-care-web -- --template vue cd elder-care-web npm install npm install vue-router4 pinia element-plus axios echarts注意这里装的这几个依赖基本是这个项目的前端根基vue-router负责路由pinia负责状态管理element-plus是UI库axios是HTTP客户端echarts是图表库用于评价统计可视化。Element Plus这里有一个实用配置方法——按需引入。全量引入会把所有组件打进包里即便没用到也占体积。按需引入需要装unplugin-vue-components和unplugin-auto-import插件在vite.config.js里配置后组件和API用到了才自动引入打包体积能小一半左右。目录结构按功能分模块而非按文件类型硬分src/ ├── api/ # 按模块封装的请求函数 │ ├── auth.js │ ├── elder.js │ ├── recipe.js │ └── evaluation.js ├── views/ # 页面级组件 │ ├── Login.vue │ ├── Dashboard.vue │ ├── elder/ │ ├── recipe/ │ ├── caregiver/ │ ├── evaluation/ │ └── system/ ├── components/ # 通用业务组件 │ ├── ElderSelect.vue │ ├── RecipeCard.vue │ └── ScoreInput.vue ├── router/index.js # 路由配置 ├── stores/ # Pinia状态管理 └── utils/request.js # Axios封装3.2 路由设计、登录态管理与动态路由生成路由是前端项目的命脉。由于系统有四种角色不同角色看到的菜单不同我采用动态路由方案——用户登录后前端拿着后端返回的角色信息动态注册该角色可访问的路由。实现思路分三步第一步路由表里只放所有角色都能访问的公共路由登录页、404页。第二步登录成功后后端返回用户信息和角色标识前端根据角色与路由的映射关系用router.addRoute()动态添加该角色对应的路由。第三步在路由的beforeEach全局前置守卫里做三件事检查token是否存在不存在就跳登录页检查当前访问的路由是否已注册未注册则尝试根据用户角色动态添加检查路由meta里的roles权限不匹配就跳403页面。router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (!token to.path ! /login) { next(/login) return } if (token to.path /login) { next(/dashboard) return } next() })这里必须提醒一个新手常踩的坑动态添加路由后务必调用router.replace(to.fullPath)重新导航一次否则页面会白屏——这是因为首次跳转时路由还没注册完需要重进一次触发重新匹配。当初我排查这个问题花了大半个晚上。3.3 护工评价模块的前端交互设计评价中心的前端是整个项目最需要打磨交互的页面。我给评价人员提供的录入界面分三个区选择被评护工、选择关联老人、评分与意见填写。评分区我用Element Plus的el-rate组件做星星评分五个维度各一行每行有维度名称和对应的星星组件以及实时分值显示。用户点击星星后前端即时汇总总分并展示在界面顶部比如“当前总分46/50”让评价人可以直观感受到打分情况。提交评价前做一个防重复提交的处理每个评价人每天对同一护工最多提交一次评价这是后端接口校验的规则前端也同步判断——当评价人选中某护工后前端调用GET /api/evaluations/check?caregiverIdxxxevaluatorIdxxxdatetoday如果已存在记录直接置灰提交按钮并提示“今日已评价该护工”。评价记录列表页用Table组件展示支持按月份、评价人、是否高分筛选。每条记录的评分用不同颜色标签区分——优秀45分以上绿色、合格35-44分蓝色、待改进35分以下红色。这样的视觉设计让管理者打开页面时一眼就能锁定问题护工。4. 关键功能实现与业务算法详解4.1 营养配比与特殊饮食禁忌的自动提醒这个功能我做得比较克制没有引入营养学专业计算引擎那会大大增加开发量而是采用“规则配置 — 标签匹配 — 预警提示”三级方案。在规则配置层食谱表里每条菜谱存了calories字段和applicable_tags字段。tags用JSON数组存储例如[糖尿病患者适用, 低盐]。老人档案里同样存dietary_notes例如“糖尿病、高血压”。在后端services层写一个validateRecipeForElder函数function validateRecipeForElder(recipe, elder) { const elderNotes elder.dietary_notes || const recipeTags recipe.applicable_tags || [] // 规则1老人有糖尿病食谱必须包含糖尿病适用 if (elderNotes.includes(糖尿病) !recipeTags.includes(糖尿病适用)) { return { valid: false, reason: 该食谱不适合糖尿病老人 } } // 规则2老人有高血压食谱必须包含低盐 if (elderNotes.includes(高血压) !recipeTags.includes(低盐)) { return { valid: false, reason: 该食谱不适合高血压老人 } } return { valid: true } }预警提示落在两个场景膳食管理员在排周食谱时系统对每一餐逐一校验所有老人的匹配情况把不合格的菜品在界面上用红色感叹号标出来护工在给老人登记用餐时如果菜品与老人禁忌不匹配同样弹窗提醒。这个功能做出来以后食堂阿姨和管理员都反馈“再也不会给糖尿病人端甜粥了”。4.2 评价维度设计分数怎么算才公平护工评价的评分算法是这套系统里最需要用心的地方。网上很多模板系统就是“打个总星数”但实际业务里这种评价毫无参考价值——说不上来差在哪也就不知道改什么。我的做法是把评价拆成五个维度每个维度10分服务态度、专业技能、响应速度、沟通能力、个人卫生。这五个维度覆盖了养老护理的核心素质要求。总分满分50分45分以上为“优秀”35分至44分为“合格”35分以下为“待改进”。但总分只是表面数据。月度汇总时我还做了一个单护工维度薄弱项分析// 取某护工当月所有评价记录 const records await getMonthlyRecords(caregiverId, month) // 按维度求平均分 const avgByDimension { attitude: avg(records.map(r r.attitude_score)), skill: avg(records.map(r r.skill_score)), response: avg(records.map(r r.response_score)), communication: avg(records.map(r r.communication_score)), hygiene: avg(records.map(r r.hygiene_score)) } // 找出最低维度标记为薄弱项 const weakPoint Object.entries(avgByDimension) .sort((a, b) a[1] - b[1])[0]这个薄弱项直接展示在护工个人月度报告里并自动生成一句“下月重点提升项”。管理者不用再自己翻记录找问题系统把改进方向都给出来了这是整个系统里最“好用”的一个功能。4.3 膳食满意度与护工评分的关联分析模块开发到后期我发现了一个很有价值的数据交叉点老人“用餐量反馈”和“护工评分”之间是否存在关联这个洞察来源于实际业务观察——有些护工负责的老人在膳食记录里频繁出现“只吃了一半”“基本没吃”的反馈而这位护工在“服务态度”“沟通能力”两个维度的评分也偏低。这是一致的因为护工决定了餐食是否合胃口、是否主动询问老人对菜品的意见也决定了老人就餐时的体验。我写了一个关联分析接口按月查询每位护工负责老人的平均剩饭率1 - 实际份数/出餐份数递归查找剩饭率超过30%且评价总分低于40分的护工名单。这个并不复杂但做出来的“风险护工预警列表”让管理层眼前一亮——之前这两个数据从来是分开看的现在被关联起来可以主动发现服务问题。5. 开发环境配置与联调阶段的坑5.1 Node.js安装与npm脚本执行报错这个项目的第一个拦路虎几乎都是环境问题。我遇到过很多次在一个项目里npm start时报错npm : 无法加载文件 npm.ps1因为在此系统上禁止运行脚本。这是Windows PowerShell的执行策略限制导致的尤其是许多人在Administrator权限下装。解决办法是打开PowerShell执行Set-ExecutionPolicy -ExecutionPolicy RemoteSigned输A确认即可。这个命令把本机执行策略从Restricted改为RemoteSigned——意思是本地脚本可以运行从网络下载的脚本需要有可信签名。装Node.js的时候我建议直接去官网下载LTS版本的安装包不要用某些工具一键安装那种容易装出一堆环境变量和权限问题。Node.js装完后验证一下node -v npm -v如果npm下载依赖非常慢把默认源切换到国内镜像站一劳永逸npm config set registry https://registry.npmmirror.com npm config get registry5.2 Vue项目安装依赖与构建时的常见问题Vue项目里依赖装到一半卡住是很多新手会非常崩溃的问题。比较常见的是node_modules残留导致的冲突解决办法是先删掉重来rm -rf node_modules package-lock.json npm installElement Plus的按需自动导入插件偶尔会报auto-imports.d.ts找不到的错解决方法是确保vite.config.js里配置的插件顺序正确并且把生成的d.ts文件排除在eslint检查之外。另外构建时容易遇到的坑是内存不足。Vue项目打包时JavaScript堆溢出报错JavaScript heap out of memory直接用命令加大堆内存build: node --max-old-space-size4096 node_modules/vite/bin/vite.js build5.3 前后端跨域与联调的正确姿势开发过程中前端跑在localhost:5173Vite默认端口后端跑在localhost:3000浏览器直接请求后端接口必然跨域。两个解决方案都值得掌握因为上线时通常还会遇到一次。开发阶段用Vite自带的代理在vite.config.js里配置server: { proxy: { /api: { target: http://localhost:3000, changeOrigin: true } } }前端代码里axios的baseURL直接写/api匹配到/api开头的请求全部转发到后端3000端口。上线阶段用Nginx做反向代理这同时也是后端服务的兜底方案location /api/ { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }CORS在开发阶段有个更省事的兜底方案——后端加cors中间件一句话允许所有跨域请求。但上线必须关掉改成Nginx代理或者白名单方式这是安全保障层面的事。6. 测试重点与部署落地经验6.1 功能测试的三个重点板块这类管理系统测试不能只看页面通不通要重点测三块逻辑权限边界、数据关联完整性、统计准确性。权限边界测试我专门写了一个测试清单用管理员账号能否修改普通用户密码评价人员能否删除评价记录护工登录后是否能看到他人评分这类越权测试是管理系统最隐蔽的坑前端菜单里没暴露入口不代表后端接口不存在后端的鉴权中间件必须每一层都覆盖到。数据关联完整性测试删除一位老人之后他名下的膳食记录怎么处理我建议业务逻辑上不物理删除而是用逻辑删除is_deleted字段历史评价记录也要保留。这个设计在测试时能省掉很多返工否则真删了数据、统计报表出现负数简直欲哭无泪。统计准确性测试就是要回到数据库里手工算一遍对比页面结果。比如我统计“1月所有评价记录的平均总分”就写SQL查询再与前端图表对照确保聚合逻辑没有偏移。6.2 部署方案选择一台服务器搞定前后端这类中小型系统不需要复杂的容器编排我最终采用的方案是一台2核4G的云服务器系统为Ubuntu 22.04前端用Nginx托管静态文件后端用pm2守护Node进程。后端部署步骤汇总# 1. 把server目录上传到服务器或者用git拉取 git clone 仓库地址 cd server # 2. 安装生产依赖跳过开发依赖显著提速 npm install --production # 3. 用pm2启动并设置开机自启 npm install -g pm2 pm2 start app.js --name elder-care-api pm2 save pm2 startup前端部署步骤# 本地执行构建产出dist目录 npm run build # 把dist/目录上传到服务器 /var/www/elder-care/ scp -r dist/* useryour-server:/var/www/elder-care/ # Nginx配置文件里把根目录指向dist并配置代理数据库这块别忘了定时备份。我写了一个简单的cron任务每天凌晨3点用mysqldump全量备份保留最近7天备份文件0 3 * * * mysqldump -u root -p*** elder_care_db /backup/elder_$(date \%Y\%m\%d).sql find /backup -name *.sql -mtime 7 -delete6.3 运维心得与体检式调优系统上线运行一段时间后一定要做一次“体检式”复盘。我当时发现的问题很典型某个查询接口响应越来越慢。排查路径是先用后端日志看耗时再Explain分析SQL最终定位到evaluation_record表的查询没有走索引手动补了caregiver_id和evaluation_date的联合索引后响应时间从900ms降到50ms。另外评价中心的图表在首页Dashboard上初始化时接口并发请求较多我做了两个优化一是把统计接口拆成按需加载Dashboard页才请求二是对月度汇总数据加了Redis缓存缓存时间为10分钟。这个改动让首页加载速度肉眼可见地提升。最后的实操心得这个系统从零开始写到能交付使用我前前后后大概用了三周多的时间。最想提醒后来者的一件事是管理系统的核心竞争力从来不在技术多炫而在你把业务细节吃得多透。你花两天时间研究“护工评价维度怎么设计才科学”比花两天时间把组件库换成更新潮的框架价值高得多。另外一个切身的体会是和真实的养老院管理人员沟通需求非常必要。我在项目开始之前专门去家附近的一家养老机构做了半天的访谈问他们现在最痛的三个问题排食谱靠手写、护工评价靠月底翻记录本、老人用餐情况靠口头转达。这三个问题直接变成了系统的三个核心功能模块。做出来的东西没有浪费一行代码。最后分享一个可以继续扩展的方向这个系统的老人档案、膳食记录、评价数据沉淀下来之后可以做一套面向家属的小程序让家属远程看到父母今天吃了什么、护工评价如何。技术上只需要把现有API对小程序端开放再加一层家属角色权限整个系统的价值就能再上一个台阶。这是一个比“堆技术栈”更有意义的迭代方向。
返回列表