资讯动态

ThinkPHP与Laravel混搭架构的Vue敬老院管理系统开发实战

发布时间:2026/10/10 5:48:10 来源:尧图企业网站定制
接手一个标题为“Thinkphp和Laravel基于VUE敬老院管理系统养老院”的项目时很多人第一反应是一个系统里怎么同时出现两个PHP框架这其实一点不稀奇很多实际业务系统就是历史代码加新模块迭代堆出来的也可能是有两个子团队各管一摊最后统一挂在一个域名下。敬老院管理系统这种典型的管理软件核心就是把老人档案、护理计划、费用统计、家属沟通这些数据打通同时还要兼顾权限、安全和并发。我以开发者的角度把这类项目从技术选型到环境搭建、从核心功能落地到高频排错完整梳理一遍重点放在VUE前端怎么和PHP后端配合以及那些文档里不会写的坑。无论你是刚接触PHPVUE组合的新人还是需要快速接手类似外包项目的开发者这篇内容都能帮你少走弯路。1. 项目整体设计与技术选型思路1.1 双PHP框架并存的原因与处理策略出现“ThinkPHP和Laravel”并存通常有几种背景。第一种是早期系统用ThinkPHP快速上线后来团队为了更好的设计模式、更强的安全机制引入Laravel来开发新模块第二种是系统由两个子系统组成比如对外接口平台用Laravel内部管理后台还是老ThinkPHP两者各自运行第三种是历史遗留的多个项目合并成一个总系统文件目录挨在一起但代码完全独立。我接手后不会急着把某个框架推翻而是先画一张“模块归属图”。比如老人档案、权限管理这类基础数据模块放在Laravel里因为需要更严谨的模型关联和事务逻辑而财务导出、旧报表统计这类可能放在ThinkPHP里跑得久逻辑稳定没必要折腾。两个框架操作同一个MySQL库时最怕的是字段规范不统一所以我会在项目根目录写一份数据库字段说明规定主键一律用id、外键用xxx_id、时间字段统一为create_time和update_time、所有表都用InnoDB引擎、字符集用utf8mb4这样两边操作起来才不会互相踩到。如果两个框架之间需要通信我建议先让前端统一通过一个API网关比如Nginx反向代理把请求分发到不同后端服务。前端感知不到细节它只请求/api/elder和/api/nurse网关把这两个路径分别指向Laravel服务和ThinkPHP服务。这样做的好处是以后把老模块拆出去重写前端代码完全不用变。1.2 为什么前端独选VUE敬老院管理系统这种后台项目页面交互密度非常高一个页面要同时容纳表格、搜索表单、弹窗、树形菜单、统计卡片。用jQuery去操作DOM项目开发到一半就会变成一团乱麻。Vue吸引我的是它足够“渐入”你可以先在一个老页面里引入Vue做局部动态渲染也可以直接把它做成单页应用。它的响应式数据绑定能把表格的增删改查状态管理得明明白白组件化机制让“老人卡片”“状态标签”“分页条”这些业务元素可以复用配合Element Plus或Naive UI后台管理系统需要的组件基本都齐了。对比过React和Angular以后我还是倾向于在中小型管理项目里用Vue。React的生态更灵活但需要自己决策的东西太多Angular太重量级学习曲线陡。Vue的中文文档完善模板语法直观前端新同事上手快。特别是Vue 3的Composition API配合组合式函数能把搜索、分页、弹窗这些重复逻辑抽出来写出来的代码比Options API更清爽。做项目不是炫技团队能快速出活才是最实在的。1.3 敬老院核心业务模块全景图一个能落地给敬老院用的系统至少要包含这些模块老人档案管理基本信息、床位房间、入住退住状态护理管理有计划排班、日常护理记录、用药提醒健康管理有体检数据、生命体征异常提醒费用管理有床位费、护理费、餐饮费等月度账单和缴费记录家属服务有留言、探视预约、老人状态推送系统管理有角色权限、员工账号、操作日志。模块之间是联动的。一条护理记录的异常体温可能要触发家属消息提醒一次退住操作要对当月费用做一次结算。所以在设计数据库时我把老人表作为核心表其他表都通过eld_id关联。在代码层面每个模块不再单独写一套“查询、新增、编辑、删除”而是用Vue封装一个通用页面框架传入不同的接口和字段配置就能生成对应的管理列表。这也是大家常说的“低代码平台”思路我们虽然没有用现成的低代码框架但通过组件化和配置化实现同样效果。2. 环境准备与项目初始化实操2.1 ThinkPHP项目运行环境配置细节后端环境首当其冲是PHP版本。ThinkPHP 5.2及以前兼容PHP 5.4到7.1ThinkPHP 6和8则要求PHP 7.1以上或8.0以上。本地调试我习惯用PHPStudy或宝塔面板创建一个站点指向项目的public目录。TP5时代入口文件在根目录index.phpTP6开始统一移到public/index.php很多人直接把站点根目录指到项目根目录结果访问的时候框架的路由全失效报一堆404或者No input file specified。这个细节一定要先确认。数据库导入也别太随意。拿到SQL文件后先看字符集是什么我建议在SQL文件头部加入SET NAMES utf8mb4然后再命令行导入mysql -u root -p 数据库名 xxx.sql。用phpMyAdmin导入大文件经常超时还是命令稳。导入后去项目的.env文件里修改数据库配置注意检查时区设置调试时把APP_DEBUG设为true方便看错误页但上线前必须改成false否则会暴露路径和数据结构。伪静态规则也是新手重灾区。Apache会在public目录下带.htaccess基本不用管Nginx下需要配置location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s$1 last; } }没有这条规则ThinkPHP的PATHINFO风格URL会打不开只有首页能访问。2.2 Vue安装及环境配置完整步骤Vue环境配置踩过的坑我可以说上三天三夜。先装Node.js一定要选LTS版本不要追新。很多依赖包在奇数版本上编译失败装个21、23之类的版本会哭。装完Node后在命令行检查node -v和npm -v然后顺手把npm源切到国内镜像npm config set registry https://registry.npmmirror.com创建项目的方式有两种。Vite是新生代主力npm create vitelatest project-name -- --template vue或者Vue CLI老项目维护也得会npm install -g vue/cli vue create project-name我现在的策略是新项目用Vite老项目继续用CLI。不管哪种方式项目生成后先别急着写代码先把依赖装完并启动一次。安装依赖时如果报错优先看是不是网络问题其次是看Node版本和锁文件。收别人的项目时我习惯先删掉node_modules和package-lock.json再重新执行npm install因为对方电脑的环境可能和我的不一样强制用对方的lock文件反而容易死锁。2.3 IDEA与Vite开发Vue项目的效率技巧很多前端同学习惯用Visual Studio Code但我发现用IDEA开发Vue项目的人也不少。IDEA对前端Vue的支持越来越好装一个Vue.js插件就能自动识别.vue文件提供模板语法高亮、组件跳转、标签自动补全。如果项目是Vite启动的可以在IDEA的Run Configuration里配置npm script直接点按钮启动比终端敲命令方便还能看控制台日志。IDEA里容易出问题的是Node解释器路径。如果本机装了多个Node版本IDEA可能会配错导致npm命令找不到要么在Settings里手动指定Node的路径要么直接在系统里用nvm切换到默认版本。还有一个提升效率的习惯给IDEA配一个“npm run dev”的快捷键然后打开浏览器的调试模式。Vite的热更新速度很快保存代码后页面一两秒内就刷新开发体验很舒服。2.4 前后端分离架构与代理配置开发环境里前端Vite跑在5173端口后端PHP跑在8000端口如果不配置代理前端请求后端的接口会触发跨域。解决跨域有两种思路后端开CORS或者前端的开发服务器做代理。我推荐代理因为生产环境里前后端大概率同域开发时模拟同域就不会出现“开发好好的一部署就跨域”的问题。Vite配置代理很简单在vite.config.js里加export default defineConfig({ plugins: [vue()], server: { proxy: { /api: { target: http://www.xxx.com:8000, changeOrigin: true, // 如果需要带cookie还得加 // cookieDomainRewrite: } } } });这样前端所有以/api开头的请求都会被转发到后端域名。后端不管是ThinkPHP还是Laravel只需要正常接收请求不用额外设置跨域头。3. 核心功能实现与代码要点3.1 老人档案模块从数据到接口再到页面老人档案是所有业务的地基。我的数据表结构大致是字段名类型说明idbigint主键namevarchar老人姓名gendertinyint1男2女birthdaydate出生日期id_cardvarchar身份证号唯一phonevarchar本人电话family_namevarchar家属姓名family_phonevarchar家属电话room_novarchar房间号bed_novarchar床位号entry_datedate入住日期statustinyint1在住 2退住 3预入住remarktext备注后端用Laravel的Model写列表接口重要的是支持搜索和分页public function index(Request $request) { $query Elder::query(); if ($request-filled(keyword)) { $query-where(function ($q) use ($request) { $q-where(name, like, % . $request-keyword . %) -orWhere(phone, like, % . $request-keyword . %) -orWhere(id_card, like, % . $request-keyword . %); }); } if ($request-filled(status)) { $query-where(status, $request-status); } return $this-success($query-paginate($request-get(page_size, 10))); }前端Vue页面用Element Plus的el-table展示数据el-pagination做分页。我会把“获取列表”的逻辑抽成一个useElderList组合式函数让列表页组件更干净import { ref, onMounted } from vue; import { getElderList } from /api/elder; export function useElderList() { const list ref([]); const loading ref(false); const page ref(1); const pageSize ref(10); const total ref(0); async function loadData() { loading.value true; try { const res await getElderList({ page: page.value, page_size: pageSize.value }); list.value res.data.data; total.value res.data.total; } finally { loading.value false; } } onMounted(loadData); return { list, loading, page, pageSize, total, loadData }; }新增和编辑用同一个弹窗组件传入elderId编辑时从父组件把当前行的数据拷贝一份传给子组件避免直接修改列表的引用数据。提交校验放在前端做一遍后端再验一遍身份证号唯一性两端都不能省。3.2 护理计划与记录的动态状态流转护理计划是敬老院区别于普通管理系统的重点。一张表是护理计划另一张表是护理记录。计划表里我维护的字段有计划编号、老人ID、护理等级自理/半自理/全护理、责任护士、开始日期、结束日期、护理措施描述、状态。状态值我定为1草稿、2生效、3暂停、4完成、5取消。状态流转必须用状态机来约束不能一个随便UPDATE就完事。比如草稿可以直接取消但生效中的计划不能直接改成草稿只能暂停或者完成。完成计划前需要校验是否存在未填写的当天记录。我通常把这块逻辑抽到服务类public function transition(ElderPlan $plan, string $action) { // action: submit, suspend, resume, complete, cancel // 校验当前状态是否允许该action // 执行对应状态变更 }前端页面对应就是一个状态标签和一组操作按钮。我用Vue的插槽渲染按钮区域根据当前状态显示“提交”“暂停”“继续”“完成”点击后调用后端接口。这里要特别说一个问题很多前端只会傻傻渲染后端返回的状态码不根据状态码去判断下一步允许什么操作。我建议后端接口返回每个状态的下一组允许操作前端按这个渲染按钮这样前端和后端逻辑一致不会出现前端点了个“完成”后端抛异常。3.3 费用账单与家属互动中的权限边界费用账单这块我采用的设计是每个老人的每月账单存一条记录账单明细用JSON字段。这样看起来不符合第一范式但在实际业务里极度高效。比如某个月新增了“空调费”项目不需要改表结构直接往JSON里塞一个键值对。生成账单的流程是点击“一键生成本月账单”后端先把本月已生成过的老人筛选掉再为其他在住老人生成账单。老人数量多时可以用异步任务但通常敬老院几百人以内同步也能接受。账单生成后前端按月份筛选、汇总统计点击“催缴”可以短信通知家属。家属互动模块就要严格划分权限了。家属端通过手机号加验证码或者小程序登录只能看到自己绑定老人的信息。在Laravel里我用多表关联老人表关联家属表家属表关联用户表。接口里通过当前登录用户的id去反查老人ID再查老人相关数据。前端路由守卫要配置好家属端路由和员工端路由完全分开。还有个容易忽略的点后端接口接收老人ID时必须校验该老人是否属于当前登录家属否则别人穷举接口地址就能看所有老人了这是数据安全事故。3.4 Vue路由、插槽与低代码化的组件复用Vue路由在这个项目里用得非常多。比如员工端菜单是根据角色动态渲染的登录后后端返回这个角色能访问的路由名称列表前端用router.addRoute动态添加这就是动态路由。路由守卫里做登录态校验和按钮级权限校验router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (!token to.path ! /login) { next(/login); } else { next(); } });插槽的应用场景我前面提到过。通用弹窗组件底部按钮用插槽扩展表格操作列用作用域插槽。这里给一个简单例子封装一个CommonTable组件template el-table :datadata slot/slot el-table-column label操作 template #default{ row } slot nameactions :rowrow/slot /template /el-table-column /el-table /template业务页面这样使用CommonTable :datalist el-table-column propname label姓名 / template #actions{ row } el-button clickedit(row)编辑/el-button /template /CommonTable所谓低代码化就是把这种通用组件铺开再用一个JSON配置驱动页面要显示哪些列、哪些按钮、搜索字段是什么全部用配置描述。后端的字段和接口也按约定命名那么一个新的管理页面只要配一个JSON就能出来。我见过一些团队用vue-form-render这类库做低代码但我们自己封装虽然前期成本高一点后期扩展性更好。3.5 视频监控与m3u8播放功能的集成方案敬老院系统里经常有视频监控、家人远程探视的功能。现在的监控摄像头一般输出HLS流也就是m3u8后缀的播放地址。前端要播放m3u8不需要额外装VLC这类播放器直接用浏览器就能搞。我用的方案是hls.js配合video标签不需要插件import Hls from hls.js; const video document.getElementById(video); const hls new Hls(); hls.loadSource(https://example.com/live/stream.m3u8); hls.attachMedia(video);如果浏览器原生支持HLS比如Safari那就直接设置video.src为m3u8地址。我把播放器封装成了Vue组件通过props传入streamUrl并兼容自动播放、音量控制、静音、全屏这些交互。这个功能在敬老院的家属探视场景里特别实用家属在手机上就能看到老人活动区域的实时画面当然要做好摄像头区域的隐私控制不能全区域无死角开放。4. 常见问题与调试技巧实录4.1 Vue环境与依赖问题速查我在这个项目上遇到最多的环境问题可以整理成一张速查表报错信息原因解决方案failed to load tsconfig vue/tsconfig/tsconfig.web.jsonvue/tsconfig依赖未装齐删除node_modules和锁文件重装依赖Cannot find module node-sassNode版本与node-sass不匹配改用dart-sasssass包或切换Node版本Port 5173 is already in use端口被占用修改vite server.port或杀掉占用进程vite:vite is not recognized全局没装vite或没执行npm install先安装依赖或使用npx vitenpm ERR! code ERESOLVE依赖树冲突使用npm install --legacy-peer-deps还有一个很多人忽视的细节你下载的项目里如果有.nvmrc文件说明项目指定了Node版本。Windows下可以用nvm-windows管理版本Mac用nvm或fnm。进入项目目录先把版本切到.nvmrc指定的版本再npm install很多莫名奇妙的报错都消失了。4.2 ThinkPHP和Laravel联调中的坑两个框架联调最核心的就是统一返回格式。我遇到过前端拿到一个成功json是{code:0,msg:ok,data:{...}}另一个是{status:200,message:success,result:{...}}前端拦截器要写两套特别痛苦。我的做法是在Laravel里写一个全局中间件把控制器返回的数据包统一在ThinkPHP里也写一个response函数两个最终都返回同样的结构。跨域是另一个坑。如果前端不配置代理后端就必须处理CORS。Laravel的写法是在中间件里加Headerheader(Access-Control-Allow-Origin: *); header(Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS); header(Access-Control-Allow-Headers: Content-Type, Authorization);注意OPTIONS预检请求要直接返回200不然后端会报“Method Not Allowed”。ThinkPHP我一般也是写一个全局过滤器或者直接在入口文件统一处理。开发时我强烈推荐用代理方式后端可以不做任何CORS处理省心。4.3 Vue项目源码怎么传递给他人和生产部署很多刚学Vue的人不知道源码怎么发给别人。完整的源码包应该包含src目录、public目录、index.html、package.json、package-lock.json、vite.config.js还有.env开头的一些配置文件。不要发node_modules别人拿到后只依赖package.json重新安装即可。发之前最好再跑一遍npm run build确认没有编译错误因为编译错误经常是某个文件大小写不对、路径引用错误这些只有在构建时才会暴露。生产部署时前端npm run build会生成dist目录把dist下的文件扔到Nginx的html目录就行。如果使用history路由模式Nginx必须有try_files回退location / { try_files $uri $uri/ /index.html; }如果Vue项目和PHP项目在同一个服务器我建议把前端dist放在一个独立目录然后Nginx里把/api开头的请求proxy_pass到PHP应用把普通请求指向静态文件。这样前后端始终同源Cookie和登录态不会出问题。4.4 样式冲突与动态路由的实战排查Vue的样式默认是全局的多个组件里偶然定义了同名的class样式就会互相污染。解决方法是给组件的style标签加scopedstyle scoped .search-bar { padding: 16px; } /style加上scoped后Vue会给组件的DOM元素添加一个data-v-xxx属性CSS选择器也会带上这个属性达到隔离效果。但这里有个坑如果你用了动态路由懒加载和组件缓存keep-alive有时候样式不生效就得检查是不是scoped导致干掉了某些全局样式或者组件没有正确命名。还有一个经典问题Google浏览器里安装了Vue插件打开页面却不显示Vue标签。这通常是网站运行在非开发模式或者页面里根本没有挂载Vue应用。还有一种情况是Vue 3项目用了ViteDevtools版本太旧需要更新到兼容Vue 3的Devtools版本。遇到这种问题时先确认页面是否在localhost环境是否真的用Vue渲染了内容再挨个排除。5. 项目复盘与个人经验沉淀5.1 从0到1的验收清单这类项目交付前我会习惯性过一遍验收清单。业务层面老人档案增删改查是否流畅搜索、分页是否正常护理计划能否按状态流转记录能否追溯修改日志费用账单能否按期生成和统计家属端权限隔离是否生效。技术层面所有接口是否统一返回格式敏感接口是否都有token鉴权和权限校验前端环境依赖是否有一键安装脚本部署文档是否写清了PHP版本和Nginx配置。这个清单看着简单但能有效防止上线时“数据库忘了配”“伪静态没开”“接口跨域”这类低级事故。5.2 扩展为小程序端的技术储备敬老院管理系统很自然的下一步是做家属端小程序。如果后端接口设计得好小程序端可以直接复用现有API只需要额外处理小程序的登录态。小程序没有浏览器的Cookie概念我一般会用手机号验证码换取一个token保存在本地请求时通过Authorization请求头传过去后端用一个统一的中间件解析token。前端Vue项目的axios拦截器和小程序的request封装可以共用一套逻辑只是把storage换成wx.setStorageSync。这样原来的业务模块诸如老人信息、护理记录、费用账单都能源源不断为小程序端提供数据一次后端开发多端复用。最后再分享一个我在实际项目里的经验这种多框架、多模块的系统代码写在哪个文件里不重要接口约定和数据结构才是关键。项目刚开始时我和前端伙伴在项目根目录建了一个api.md文档每次加接口都先更新文档再写代码。两个后端框架遵循同一套文档前端也按文档联调后期几乎没有因为接口参数对不齐返工。如果你手边也有这种“混搭”技术栈的项目别急着抱怨结构乱先把模块边界画清楚把接口统一好后面开发速度会越来越快。

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

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

免费获取报价 →
↑