news 2026/9/28 9:25:04

SpringBoot+Vue+MyBatis医院后台管理系统:核心设计与部署实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot+Vue+MyBatis医院后台管理系统:核心设计与部署实践

这套“企业级医院后台管理系统”的话题,我在技术群里见过太多次了。SpringBoot + Vue + MyBatis + MySQL这套组合,几乎是国内中小型企业内部系统、课程设计、毕业设计里最经典的配置,医院后台管理系统就是其中一个非常有代表性的形态。你搜源码的时候会发现版本特别多,有带前端的、有不带前端的、有Spring Cloud微服务的,但真正在公司环境里跑得稳、能讲清楚设计思路的,反而是这种单体应用加清晰分层的版本。

这篇文章不打算贴一大段代码然后让你自己看,而是从我和这类系统打了几年交道的角度,把你拿到这套源码之后最需要搞懂的几件事拆开讲:整个系统在解决什么业务问题、SpringBoot后端和Vue前端是怎么协作的、MyBatis在真实业务里的缓存和分页有哪些坑、以及最后怎么把它从源码变成一台能访问的服务器。不管你是把源码当成课设参考,还是准备在公司内网部署一套医疗管理系统,这篇文章都值得你花十分钟看完,比你自己闷头翻代码有效得多。

1. 一套医院后台系统到底在做什么

1.1 模块拆解与业务复杂度分析

医院后台管理系统听名字好像就是“挂号、开药、结账”三个功能,但真正画出功能清单会发现,它其实是一个典型的RBAC权限模型加多模块业务系统的组合体。以我接触过的同类项目来说,最基础的功能模块通常包括:系统管理(用户、角色、菜单权限)、基础数据(科室、医生、诊室、药品字典)、门急诊业务(挂号、分诊、医生接诊、收费结算)、住院管理(床位、医嘱、费用)、药房管理(库存、发药、退药)、统计报表(日营收、就诊量、药品消耗)。

这些模块之间不是孤立的。挂号会关联科室和医生排班,收费会关联挂号记录和药品明细,药房库存又会受收费发药影响。一个看起来简单的“病人缴费”操作,后端往往要同时更新收费主表、收费明细表、药品库存表、挂号状态表,涉及至少四张表的数据一致性。这也是为什么这类系统特别适合用来练习事务管理和多表关联查询——业务复杂程度刚好,不会像电商系统那样庞大到劝退,又比简单的CRUD多出不少真实场景的约束。

从架构形态上看,医院后台管理系统用的是典型的B/S架构,浏览器通过HTTP请求访问后端接口,后端用SpringBoot提供RESTful API,数据落在MySQL里。前端Vue负责页面渲染和交互,通过axios和后端通信。这个模式的好处是前后端完全分离,Vue打包成静态文件扔进Nginx,SpringBoot打包成jar独立运行,部署和理解成本都很低,对团队协作也很友好。

1.2 为什么是SpringBoot + Vue + MyBatis这套组合

先说SpringBoot。医院这类系统有一个特点:业务规则多、迭代频繁、维护周期长。SpringBoot在这方面的价值是“少配置、快启动、生态全”,内置Tomcat让部署变得极其简单,配合Spring家族的AOP可以做日志切面、权限拦截、全局异常处理。相比老一代SSH或者纯Servlet开发,开发效率提升得不是一星半点。

Vue这边,选它不是因为比React强,而是因为国内前端生态里Vue的学习曲线更平缓,Element UI这类组件库对后台管理系统几乎是量身定做的。“表单加表格”这种后台管理页面最常规的形态,用Element UI的el-form和el-table拼接,半天时间就能完成一个基础模块的页面开发。Vue的双向绑定和组件化思路也很直观,有Java基础的人看几天Vue代码就能上手改页面。

MyBatis在国内企业里的普及度非常高,原因在于它把SQL的控制权完全交还给开发者。医院业务的查询逻辑很复杂,比如“查询某医生在某时间段的挂号记录并带出患者信息和收费状态”,这种SQL用MyBatis的resultMap和动态SQL写出来,逻辑一目了然,后期调优DBA也能直接看懂SQL。相比Hibernate的全自动ORM映射,MyBatis的半自动模式在复杂查询场景下反而更可控。

MySQL更不用多说,开源免费、稳定可靠,医院内部系统的数据量级对MySQL来说毫无压力。真正用好这套组合的关键,不在于会选型,而在于知道每个环节里的细节和坑在哪里。

2. 后端核心实现:数据库与MyBatis的实操细节

2.1 数据库设计与常用表结构

拿到源码后第一件事不要急着启动,先打开SQL脚本看表结构。一套好的医院后台系统,数据库设计通常能反映出业务的全貌。以挂号收费这条主链路为例,最少需要这几张核心表:

用户表(sys_user)、角色表(sys_role)、菜单权限表(sys_menu)负责登录和权限;科室表(dept)、医生表(doctor)、排班表(schedule)负责挂号资源管理;患者表(patient)、挂号记录表(register)、收费记录表(charge)、收费明细表(charge_item)负责门诊核心业务;药品表(drug)、库存表(drug_stock)、出入库记录表(stock_log)负责药房管理。

设计这套表的时候有几个常见的取舍。患者表要不要和挂号表分开?要分。同一个患者可能多次挂号,如果字段全塞在挂号表里,数据冗余会很严重。药品库存这种高频更新字段,要不要存冗余库存数量?要存,但是要以库存流水表为准,也就是说每次出入库都记流水,当前库存是流水累计出来的结果,直接改库存字段很容易对不上账。

字段设计上还有一个细节值得注意:金额字段用decimal而不是float或者double。这是医疗系统里最容易踩的坑,涉及钱的计算如果用了浮点类型,可能出现0.1加0.2不等于0.3的问题。我见过不少源码把费用字段设计成double,这是绝对不可取的,正确做法是decimal(10,2)起步,复杂场景甚至用decimal(12,4)加前端展示转换。

2.2 MyBatis映射、动态SQL与多表关联的常见写法

看MyBatis部分的时候,重点看三个东西:resultMap、动态SQL、多表查询的写法。

resultMap是MyBatis的核心,它解决的是数据库字段和Java对象属性之间的映射关系。医院系统里下划线命名的字段特别多,比如register_no、patient_name,而Java里习惯驼峰命名,比如registerNo。在配置文件里开启mapUnderscoreToCamelCase,让下划线自动转驼峰,可以省去大量手动映射的代码。但遇到关联查询查出多张表字段时,column属性还是需要显式指定,否则容易出现字段覆盖问题。

动态SQL是MyBatis最实用的能力。比如查询挂号记录时,管理员可能按患者姓名过滤,也可能按时间范围过滤,也可能按科室过滤。用原生JDBC写这种查询,要拼接SQL字符串,还要小心引号和特殊字符。MyBatis的<where>标签配合<if>标签可以优雅解决:

<select id="pageList" resultType="com.hospital.entity.Register"> SELECT r.*, p.patient_name, d.dept_name FROM register r LEFT JOIN patient p ON r.patient_id = p.id LEFT JOIN dept d ON r.dept_id = d.id <where> <if test="patientName != null and patientName != ''"> AND p.patient_name LIKE CONCAT('%', #{patientName}, '%') </if> <if test="deptId != null"> AND r.dept_id = #{deptId} </if> <if test="startDate != null"> AND r.create_time &gt;= #{startDate} </if> </where> ORDER BY r.create_time DESC </select>

这里注意两个细节:一是<where>标签会自动去掉多余的AND前缀,所以写条件时带上AND也没问题;二是时间比较时不要用>=直接写在XML里,>符号会被XML解析器认为是标签结束,必须用&gt;转义,这是新手最容易踩的坑。

多表关联查询的写法上,医院系统里常见的是两层结构嵌套。比如查询收费明细需要带出药品名称,用LEFT JOIN即可。但碰到“医生信息带出科室信息再带出门诊排班”这种三层嵌套,直接用resultMap的association嵌套映射更合适,比多层JOIN的性能好,代码也更清晰。

2.3 缓存与分页插件:容易出问题的两个点

MyBatis的缓存机制看起来简单,实际用起来有不少坑。一级缓存是SqlSession级别的,默认开启,同一个SqlSession中执行两次完全相同的SQL会走缓存。Spring整合MyBatis后,每次请求都会新建SqlSession,所以一级缓存的作用范围基本被限制在一个事务内,问题不大。真正的问题是二级缓存,它是mapper级别的,默认关闭。有人觉得开启二级缓存能提升性能,但在医院这种读写频繁、数据实时性要求高的业务里,开启二级缓存很容易出现“上一个请求改了数据,下一个请求却读到旧值”的脏读问题。我的建议是:这个系统默认不开二级缓存,维持现状就好,真有性能瓶颈时优先优化SQL和加索引,别一开始就动缓存。

分页插件是MyBatis生态里使用率最高的组件,PageHelper几乎成了标配。用法很简单:

PageHelper.startPage(pageNum, pageSize); List<User> list = userMapper.selectUserList(); PageInfo<User> pageInfo = new PageInfo<>(list);

但这东西有个非常经典的坑:PageHelper.startPage()调用后,必须紧跟第一个select查询,中间不能有任何其他SQL操作,否则分页参数会被下一个查询消费,导致莫名其妙的数据错乱。另一个坑是pageNum从1开始,不是0。前端Vue里el-pagination默认也是从1开始,两边对齐问题不大。真遇到“前端传1查不出第一页”的情况,多半是后端有人写了pageNum = pageNum - 1,找出来删掉就好。

3. 前端Vue部分的工程化实践

3.1 工程初始化和目录结构

Vue项目这块,拿到源码后先看package.json,搞清楚用的是Vue 2还是Vue 3、用的是Element UI还是Element Plus、构建工具是webpack还是Vite。医院后台系统开源的代码目前大量还是Vue 2 + Element UI + Vue CLI的组合,这并不代表落后,这类系统要的是稳定,Vue 2的生态非常成熟,踩坑资料也多。

目录结构上,一套合理的Vue项目通常长这样:src下面分views(页面组件)、router(路由配置)、api(接口请求)、components(公共组件)、utils(工具函数)、store(Vuex状态管理,如果用了的话)。其中最核心的是views和api的对应关系。后端一个模块对应前端一个页面,这个对应关系理清了,你改代码的时候才能快速定位。

有些源码会把所有接口请求直接写在页面组件里,每个页面重复写axios调用。这种写法不是不行,后期维护会很痛苦。更规范的做法是单独建一个api目录,每个后端Controller对应一个JS文件,把接口统一封装成方法,页面里只关心调用和回显。

3.2 axios封装与登录态管理

axios封装是前端工程质量的分水岭。好的封装会做三件事:统一请求头、统一错误处理、统一携带token。以这个医院系统为例:用户登录成功后,后端返回一个JWT令牌,前端存储在本地,然后axios请求拦截器里自动加上Authorization请求头。

service.interceptors.request.use(config => { const token = localStorage.getItem('token'); if (token) { config.headers['Authorization'] = token; } return config; });

响应拦截器要处理的是后端返回的统一响应体。这套系统的后端接口一般会封装Result对象,有code、msg、data三个字段。当code不为200时,前端拦截器直接弹出错误提示,不需要每个页面试着catch一遍。还有一个细节是处理登录过期:当拦截器捕获到401状态码时,清除本地token并跳转到登录页,这是很多源码容易漏掉的地方。

登录态管理这一块,token存localStorage还是sessionStorage各有说法。localStorage刷新后还在,适合“记住我”的场景,但存在XSS风险。sessionStorage关闭标签页就没了,更安全一点。医院内部的系统安全要求通常高一些,建议用sessionStorage,并且后端接口要校验token的有效期。

3.3 动态菜单和路由权限控制

权限控制是后台管理系统里不好绕过去的点。医院系统的角色分为超级管理员、医生、护士、收费员等多种,不同角色看到的菜单和能访问的页面不一样。前端实现权限控制有几种方案,最常见的做法是:登录后从后端获取当前用户的菜单列表和权限标识,前端根据这些数据动态生成侧边栏菜单。

路由权限这块,可以用vue-router的addRoutes方法动态注册路由,也可以只做页面级按钮的v-if控制。实际项目里我更推荐一个折中方案:路由表写全部页面,但配合导航守卫做角色校验,用户访问没有权限的路由时直接重定向到首页。这种方式配置简单,不容易出错,安全性以后端接口校验兜底。因为前端菜单隐藏只是用户体验层面的事,真正的权限拦截必须在后端接口上做,否则有人绕过前端直接请求接口就能越权操作,这是医院系统绝对不能犯的错误。

后端权限这块,我在这类项目里一般用拦截器配合注解实现。自定义一个@RequirePermission注解,标注在Controller方法上,拦截器里读取当前用户的角色和权限集合做校验,不通过就抛出401异常。这种方案比Spring Security简单,也够用。

4. 业务模块实现:挂号、收费、药房这些典型场景怎么落地

4.1 挂号与医生排班模块的实现套路

挂号是医院系统的入口业务,它牵扯到患者建档、医生排班、号源锁定三个环节。患者第一次来要先建档,填写姓名、身份证、手机号等信息,生成一个患者ID。再来就诊时输入手机号或身份证号就能调出档案。这个逻辑在后端对应的是一个“查不到就新增”的操作,用SELECT判断后再INSERT很容易出现并发重复建卡的问题,更稳妥的做法是在患者表身份证号字段上建唯一索引,用INSERT ... ON DUPLICATE KEY UPDATE来保证数据唯一。

医生排班的实现通常是排班表加时间段规则。医生表关联排班表,排班表里存上午、下午两个时段,每个时段限定号源总数。挂号时先查询该时段剩余号源,判断是否大于0,然后执行扣减。这个“查剩余号源再扣减”的操作如果并发量上来,需要加锁或者用乐观锁控制,否则两个患者同时挂最后一个号源可能导致超卖。不少简单源码没有处理这个问题,考试交作业没问题,真要上线做改造,这是必须补的一环。

挂号成功后,系统要生成挂号记录并关联门诊收费状态。状态一般分“未收费”“已收费”“已退号”几种。退号操作要检查是否已经发生收费和药品发放,如果医生已经开了药,是不允许直接退号的,需要走退费流程。这些状态流转的校验代码,是业务逻辑里最需要细心看的部分。

4.2 收费结算模块的事务处理

收费结算是整个系统里数据一致性要求最高的模块。一笔门诊收费涉及的操作包括:更新挂号记录状态为已收费、插入收费主表记录、插入收费明细记录、扣减药品库存、生成药品出库流水。任何一个步骤失败,整个操作都要回滚,否则会出现“钱扣了但药房库存没扣”的严重业务Bug。

SpringBoot里用@Transactional注解解决这个问题,但要注意几个使用细节。注解默认在RuntimeException时回滚,如果代码里捕获了异常然后自己做处理,事务不会回滚。正确做法是只捕获异常、做好日志、然后继续向上抛出,让Spring帮忙回滚。另外不要在一个事务里调用另一个类中被@Transactional标注的方法,Spring的事务是基于代理实现的,自调用会绕过代理,导致事务失效。这个是非常经典的“事务不生效”的场景。

收费金额的计算这里也要强调,一定要用BigDecimal。药品单价乘以数量的结果,如果用double计算,肉眼看着没问题,但有时候会出现小数点后的误差。对账的时候差几分钱,查到你头秃也找不到原因。BigDecimal的写法:

BigDecimal totalAmount = price.multiply(new BigDecimal(quantity)) .setScale(2, RoundingMode.HALF_UP);

4.3 药房库存和统计报表

药房模块的核心是库存流转闭环。入库增加库存,出库扣减库存,每一步操作都要写流水表。库存不能自由修改,只能通过出入库操作来调整。盘点时发现库存不对,排查的依据就是流水表。这套系统里的药品表、库存表、流水表是三个关联紧密的表,理解的时候要当成一个整体来看。

统计报表这块,要用到MySQL的日期函数和分组查询。日报表就是按天统计收费金额和挂号数,SQL大概长这样:

SELECT DATE_FORMAT(create_time, '%Y-%m-%d') AS day, COUNT(*) AS register_count, SUM(total_amount) AS total_amount FROM charge WHERE create_time >= #{startDate} AND create_time <= #{endDate} GROUP BY DATE_FORMAT(create_time, '%Y-%m-%d')

这类SQL本身不复杂,但报表查询通常会跨多张表联合统计,不加索引的话数据量大时会非常慢。常见的优化手段是保证where条件里的时间字段建了索引,group by字段也建了索引。前端报表页面用ECharts折线图展示每日营收趋势,这一块在源码里通常是Dashboard页面,不算太复杂,理清SQL结果怎么映射到图表数据的思路就够了。

5. 部署上线:从源码到能访问的完整流程

5.1 环境准备:MySQL、JDK、Node这些基础依赖

在IDE里跑通这个系统不难,难的是把源码部署到一台干净的服务器上。先说环境,这系统跑起来需要三样东西:MySQL、JDK、Node(构建前端用的)。

MySQL安装可以参考网上任何一个安装教程,但要注意版本。这套源码的SQL脚本如果是基于MySQL 5.7写的,放在MySQL 8.0上执行大概率会有兼容问题,最常见的报错是排序规则不兼容或者datetime默认值语法变了。所以我一般建议直接用MySQL 8.0,少数SQL脚本需要手工改一下。安装完MySQL后用Navicat新建数据库,字符集选utf8mb4,排序规则选utf8mb4_general_ci,然后导入SQL脚本。

导入SQL脚本有一个经常出问题的点:如果SQL脚本文件是GBK编码,在utf8mb4的库上导入会出现中文乱码。用Navicat导入时,要注意文件编码和数据库编码保持一致。如果不确定,用记事本打开SQL文件另存为UTF-8编码再导入,基本不会错。

JDK方面,SpringBoot 2.x系列要求JDK 8以上,我用的是JDK 8,稳定省心。如果你拿到的源码是基于SpringBoot 3.x写的,那就要JDK 17了,两者差距很大,先确认版本再装环境。

5.2 前后端打包与服务器部署

后端打包在项目根目录执行:

mvn clean package -DskipTests

打包完成后target目录下会生成一个jar包。这一步如果报错,大概率是依赖下载失败或者测试用例没跳过。还有一种情况是MySQL连接配置的问题,打包本身不会校验数据库连接,但运行时启动就会报错,所以application.yml里的数据库地址、用户名、密码要在打包前就确认好。

SpringBoot有两种部署方式:直接用java -jar跑,或者部署到Tomcat的webapps目录。用内置Tomcat的方式更简单,一条命令就能启动。但要注意服务器防火墙要放行项目端口,SpringBoot默认是8080,如果外网访问不了,先检查防火墙和安全组规则。

前端的构建很简单:

npm install npm run build

构建完成后dist目录就是纯静态文件。部署方式通常是把dist目录上传到Nginx的html目录里,然后配置Nginx把请求转发到后端接口。这里有个很关键的地方:前端和后端不在同一个端口,跨域问题是怎么处理的。比较省事的方式是在Nginx里配置反向代理,让前端页面请求/api开头的接口时,统一转发到后端的8080端口:

location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }

这样配置的好处是前端代码里只需要写相对路径,不用写死IP和端口,后续换服务器或者改端口不用重打前端包,只需要改Nginx配置就行。

6. 实际开发中踩过的坑与排查思路

6.1 分页插件失效的几个常见场景

PageHelper失效是个容易把人搞懵的问题。表现是查询结果没有被分页,一条SQL把全表数据都查出来了。常见的坑有三个:第一个是startPage之后没有紧跟查询,中间隔了别的逻辑;第二个是在分页查询的SQL里有自定义拦截器或者嵌套子查询,PageHelper的count查询生成出错;第三个是多个数据源场景下PageHelper配置没有指定方言或者没有拦截到正确的Executor,导致分页不生效。排查思路很简单:先看MyBatis打印出来的SQL,如果SQL最后没有LIMIT关键词,说明分页根本没拼接上去,顺着这个方向去查startPage和查询之间的代码就行。

6.2 MySQL 8的时区与编码问题

MySQL 8连接时区报错是出现频率最高的问题。错误信息通常是“The server time zone value is unrecognized”或者连接直接超时。解决办法是在JDBC连接串里加时区参数:

url: jdbc:mysql://localhost:3306/hospital?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

注意useUnicode和characterEncoding这两个参数一起用,不然中文会出现乱码。另外&符号在YAML文件里不需要转义,在properties文件里也不要写成&amp;,这是很多人会搞混的地方。

编码问题还有一个隐蔽场景:数据库表字段是utf8mb4,但JDBC连接串没指定characterEncoding=utf8,插入中文数据时会显示问号或者乱码,表现是“能连接、能查询、但中文全变问号”。遇到这个问题先检查连接串,再加验证数据库和表两级的编码设置。

6.3 跨域配置与前端上线后的404场景

前端开发环境访问不到后端接口,最常见的问题是跨域。开发阶段,Vue的devServer可以配置代理解决;生产阶段,用前面说的Nginx反向代理解决。还有一种偷懒方式是后端写一个CorsConfig配置类,放开所有跨域限制。本地联调这么搞可以,但上线前一定要做限制,只允许固定域名访问,否则等于把系统接口裸奔在公网上,完全不具备企业级系统应有的安全底线。

上线后遇到刷新页面404,是另一个高频问题。原因是前端采用了history模式的路由,URL路径在服务端不存在,刷新时服务器返回404。解决方式是在Nginx里配置try_files:

location / { try_files $uri $uri/ /index.html; }

这个配置的意思是,如果请求的路径找不到对应文件,就回退到index.html,让前端路由接管。这个坑很多人第一次部署都会遇到,记住了以后基本不会再翻车。

从拿到源码到把系统跑起来,我个人的经验是,不要急于去看业务代码,先跑通链路,再顺着一条最能代表系统全貌的业务流去读代码。我一般从挂号开始,看到收费结算结束,这条链路读懂了,整个系统的骨架也就掌握了。这套SpringBoot + Vue + MyBatis + MySQL的组合,未来几年里依旧会是国内后端开发的主流形态之一。最后分享一个小习惯:我会在阅读这类源码时,用思维导图按模块记录表和接口的对应关系,等整个系统跑通了再回头看,这张图就是你对这套系统最宝贵的认知沉淀,对自己写过的项目复盘同样适用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 9:24:57

UE5打包报VC++缺失?注册表格式错误才是真因

1. 这不是运行库没装&#xff0c;是注册表在“说谎”你打包 UE5 项目生成 exe 后双击报错&#xff1a;“此应用程序无法启动&#xff0c;因为计算机中缺少 Microsoft Visual C 2015–2022 Redistributable (x64)。请安装该软件包。”——而你明明刚从微软官网下载、以管理员身份…

作者头像 李华
网站建设 2026/9/28 9:24:55

奈奎斯特频率与采样定理:破解混叠幽灵谱线的工程密码

做音频采集的时候&#xff0c;我遇到过一件让我印象很深的事&#xff1a;一套8kHz采样率的老式语音采集系统&#xff0c;频谱里突然出现了一根干净的6kHz谱线。理论上8kHz采样只记录4kHz以下的内容&#xff0c;这根谱线从哪来的&#xff1f;排查到最后才发现&#xff0c;是附近…

作者头像 李华
网站建设 2026/9/28 9:24:29

Cusor:在Cursor中编译运行Qt项目的配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 9:24:25

Terraform模板安全审计流水线:将合规检查前置到代码阶段

1. 为什么我建议把审计逻辑前置到模板阶段上个月我帮团队搭了一套Terraform模板的安全合规性自动化审计流水线&#xff0c;目标是让所有基础设施代码在合并之前先过一轮机器审计。以前我们的安全合规检查主要靠云控制台人工点选&#xff0c;模板改了没人记得同步基线&#xff1…

作者头像 李华
网站建设 2026/9/28 9:22:36

Node.js+Vue构建云上水果商城:全栈开发与部署实践

最近在做一个基于Node.js和Vue的云上新鲜水果超市商城系统&#xff0c;内部代号g0a71。这个项目不是一个什么重量级电商平台&#xff0c;而是面向中小型生鲜商家的一条线上化方案。从用户端的水果浏览、购物车&#xff0c;到管理端的订单处理、商品上下架&#xff0c;再到云服务…

作者头像 李华
网站建设 2026/9/28 9:22:17

Node.js+Vue实战:从零搭建幼儿园管理系统全攻略

做幼儿园管理系统这个项目&#xff08;内部代号 elx46&#xff09;&#xff0c;前后断断续续花了三周时间。技术栈选的就是 Node.js 加 Vue&#xff0c;后端用 Node.js 提供接口&#xff0c;前端用 Vue 写管理后台&#xff0c;给一家小型私立幼儿园搭了一套真正能跑起来的日常管…

作者头像 李华