ARTICLE DETAIL

资讯详情

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

SaaS门诊系统源码实战:SpringBoot+Vue.js多租户架构设计与落地

SaaS门诊系统源码实战:SpringBoot+Vue.js多租户架构设计与落地 1. 从单体HIS到SaaS门诊系统这波重构到底解决了什么我早年在做诊所信息化的时候最头疼的就是“每家诊所一套系统”这种搞法。今天这家要加个中药库明天那家要改个计费规则每次都是改一处代码、发一个新版、运维直接崩溃。到后来我彻底想明白一件事医疗软件要走下去必须从“项目定制”转向“产品化 多租户”。而我最近在深耕的一套SaaS门诊系统源码技术栈选的就是后端SpringBoot、前端Vue.js——这套组合做出来的东西不光是能给门诊用更是一套可以反复交付的“医疗数字化解决方案”。很多朋友一听到“医疗系统”就心里发怵觉得又是HIS又是LIS又是PACS复杂度直接拉满。确实医院级的信息系统是很重但门诊这个场景其实非常适合用SaaS模式切入。原因很直观门诊的业务流程相对标准——挂号、分诊、医生接诊、开方、收费、发药、复诊环环相扣但又不像三甲医院那样存在极其复杂的会诊、手术、病区流转。把这一套核心流程做扎实做成多租户可配置的产品一家诊所从部署到上线可以压缩到一周以内而且后续的升级维护都在云端完成不用再背着电脑去现场改Bug。这篇文章不打算写那种“本项目基于XX技术实现了XX功能”的套话我就直接以这套系统的源码设计为线索把SaaS门诊系统的架构思路、SpringBootVue.js落地时的关键决策、多租户怎么设计、以及我从实际项目中踩过的坑都翻出来讲一遍。如果你正准备在医疗信息化领域选型或者你已经拿到一套类似的源码想二次开发这篇文章应该能帮你省掉不少试错时间。2. 为什么偏偏是SpringBoot Vue.js选型逻辑拆给你看2.1 后端SpringBoot不是因为它火而是因为它“省心”医疗系统的后端有个很明显的特点并发量不会特别大但事务一致性要求极高。门诊高峰期也就几百号人同时在挂号、开单、缴费这点压力对现代后端框架来说都是小场面。真正难的是业务规则复杂、数据关系紧密、权限模型细腻。比如一位患者挂了号之后医生工作站要能立刻看到他的候诊状态还要能拉出历史病历收费窗口要能根据医生开的处方自动计算医保统筹和个人自付部分——这些操作横跨多个表、多个服务对事务和可靠性的要求是“一条都不能错”。SpringBoot在这个场景里几乎是量身定做的。它把Spring生态里那些繁琐的XML配置全部干掉用自动配置把数据源、事务管理、Web层全部串起来。我接手这套源码时的第一感受就是工程结构非常干净controller、service、mapper、entity分层清晰甚至不用看文档凭类名就能定位到某段业务逻辑。再加上spring-boot-starter-validation参数校验、spring-boot-starter-security做登录鉴权这些基础能力全部是开箱即用的我可以在核心业务上多花精力而不是和一堆配置搏斗。还有个点是SpringBoot的内嵌Tomcat。传统WAR包部署要装独立的Tomcat、调JVM参数、配数据源麻烦得很。内嵌容器直接java -jar一条命令就能起服务在门诊这种IT力量薄弱的场景里特别实用——很多小诊所连个专职运维都没有你把一个可执行Jar包扔上去配好数据库就行省心。2.2 前端Vue.js让医生和护士愿意用系统的关键说句可能得罪人的话很多医疗系统的失败不是功能不够而是界面太丑、操作太绕。门诊医生一天要看几十上百个号如果开个处方要点七八次鼠标他宁可手写。所以前端框架的选型直接决定了系统最后是被天天用还是被丢在角落里吃灰。Vue.js在这一块的优势是渐进式、组件化、上手平滑。它的响应式数据绑定让我在写医护工作台时非常舒服当医生选中一个患者右侧的“历史病历”“过敏史”“近期检验结果”面板自动刷新这些联动如果用原生jQuery去写能写到你怀疑人生但Vue里这就是几个响应式变量和计算属性的事。再加上vue-router做页面路由vuex或pinia做全局状态管理整个门诊工作台——从候诊大屏到医生接诊页再到收费划价页——可以拆成几十个独立组件每个组件只管自己的事。我做这套系统的前端时还特别注意了一个细节操作反馈速度。医生点击“保存处方”之后如果超过一秒没反应就会焦虑。Vue的异步更新机制配合SpringBoot的接口响应在局域网环境下基本能做到毫秒级反馈。配合Element UI这类组件库表格、表单、日期选择器这些医疗界面里的高频控件都能快速搭建。2.3 组合起来看API驱动的前后端分离是SaaS化的地基选SpringBootVue.js不只是为了开发效率更是因为这对组合天然就是前后端分离 纯API交互的样板。前端项目跑在Nginx上通过HTTP请求访问后端RESTful接口。这一层分离对SaaS模式至关重要——我可以在不改前端代码的情况下随时调整后端服务反过来我可以给不同的租户不同诊所提供不同的前端主题但后端服务还是同一套。拿这套源码里最典型的交互场景举例医生在Vue前端开完处方点击保存后前端通过axios发送一个包含患者ID、医生ID、药品明细、用量用法的JSON对象到/api/prescription/save接口。后端SpringBoot用RequestBody接收事务性地写入处方主表、处方明细表、收费记录表然后返回一个完整的收费单对象。前端拿到之后直接跳转到收费页面。整个过程就是一个清清楚楚的“请求-响应”闭环完全符合当前SaaS产品的技术审美。3. 回到业务本身SaaS门诊系统的核心模块是怎么设计和落地的3.1 门诊业务的完整闭环挂号、分诊、接诊、收费、药房一套能真正给门诊用的系统业务流程必须闭环。我常说如果一张流程图跑不通“患者进门到拿药出门”那这个系统就是样子货。这套源码里的核心模块我是按下面的流程拆的挂号收银台是患者进入门诊的第一站。这里要支持两种模式一是现场挂号患者给钱或刷医保卡登记基本信息二是预约挂号患者在微信公众号或小程序上提前约好号源到院后直接签到。源码里把这两条路径都打通了挂号成功后会自动进入分诊队列在候诊大屏上滚动显示。医生工作站是整个系统中使用频率最高、也最考验交互设计的模块。医生在这里看到自己的待诊列表一个个叫号然后快速录入主诉、现病史、诊断开出处方或检验检查单。这套源码的处方设计支持西药、中成药、中药饮片三种类型因为我在实际走访中发现很多门诊其实是中西医结合的。中药饮片要能自动算帖数、剂量西药要有库存联动——这些细节不做到位医生很快就会弃用。收费结算窗口接住医生开出的单据进行划价。这里最核心的是医保和自费的组合支付逻辑虽然各地医保政策千差万别但基础框架是相近的医保能报销的部分走医保账户不能报销的走自费。源码里用一个可配置的“收费规则引擎”处理这部分不同租户可以通过后台配置不同的报销比例和计费项目不用改代码。药房发药模块按收费状态自动生成待发药清单药师核对后执行发药操作库存自动扣减。当库存低于阈值时系统会自动生成采购建议单避免门诊出现“处方开了药房却没药”的尴尬。3.2 患者档案与健康数据的沉淀价值很多门诊老板一开始对这个不敏感但真正用起来之后会发现患者档案才是系统最值钱的部分。这次看病的病历、诊断、用药下次再来时直接调取医生几秒钟就能掌握患者的历史情况。这套源码里的患者管理模块支持完整的档案生命周期基础信息、家庭成员关系、过敏史、既往病史、历次就诊记录、历次处方明细、检验报告——全部结构化存储。这里我建议你在二次开发时要特别关注数据清洗和去重。现场挂号时很多患者手写字迹潦草身份证号填错的情况时有发生。源码里有一个患者检索的“模糊精确”双模式匹配身份证号码作为唯一索引姓名的同音字通过拼音索引来辅助匹配。不要小看这个功能我有一次在客户现场就遇到过一个患者半个月内用三个不同手机号挂了三次号如果没有患者合并功能他的病历就永远都是碎片化的。3.3 数据统计与运营报表给院长看的“驾驶舱”门诊系统的使用者不只有医生护士还有门诊的经营者。他们最关心的是今天收了多少钱哪个医生贡献最大哪些药品消耗最快本月的复诊率是多少这套源码内置了一套统计报表模块从挂号量、收费金额、科室分布、医生工作量、药品消耗等维度进行汇总并以图表形式展示。不过我必须坦白说一句源码自带的统计报表通常是“通版”的真要满足某个门诊的个性化需求二次开发是躲不掉的。比如有家中医诊所的老板跟我说他想看的是“每个节气前后特定方剂的使用趋势”这就要在处方明细表上做更细粒度的聚合。用SpringBoot配合MyBatis-Plus的Wrapper查询构造器这种定制查询写起来不算难前端用Vue的echarts组件渲染趋势图半天就能交付一个新报表。4. SaaS化的灵魂多租户架构和可配置能力到底怎么设计4.1 多租户数据隔离字段隔离还是独立库SaaS系统和普通单机版系统的本质区别在于一套代码同时服务多个诊所租户而彼此的数据绝对隔离。我见过很多“假SaaS”——只是简单地把几个客户部署在同一个服务器上数据混一起全靠代码里where client_id ?来过滤。这种做法在数据量小的时候看不出问题但只要某个租户的数据量暴涨或者查询条件写漏了一个租户ID就会发生严重的数据越权事故。在医疗场景里患者数据泄露是原则性问题。这套源码的做法是共享数据库、共享表结构、租户ID字段行级隔离。每一张业务表都有一个tenant_id字段当请求进来时后端先通过Token识别出当前是哪个租户然后把这个租户ID自动拼接到所有SQL查询条件里。SpringBoot里我是通过一个拦截器 MyBatis拦截器的组合实现的请求进入Controller之前先解析租户信息存入ThreadLocalMyBatis执行SQL时自动追加租户条件。这样业务代码里完全不用手动写租户过滤改起来也不容易出错。但我要提醒你行级隔离不是唯一的方案那种把每一个租户独立成一个数据库的“库隔离”方案在数据安全上更让人放心适合对数据隔离有强合规要求的大型医疗集团。它的缺点是运维成本高每次升级都要对几十个库执行脚本。早期做SaaS建议先采用字段隔离模式等客户量上去了再考虑升级粒度。4.2 租户可配置性从诊所名称到收费项目的动态定制SaaS产品能不能卖出去很大程度上取决于可配置性。我接触过的门诊规模从“夫妻店”到“五十人诊所”都有他们的需求差异非常大有的需要“医生排班”有的需要“线上复诊”有的需要“体质辨识”如果每个需求都要动代码那和做外包项目有什么区别所以在源码设计中我把一批高频变化的需求做成了“配置项”。诊所管理员登录后台可以自己改诊所名称、Logo、科室列表、医生排班规则、收费项目及价格、打印小票的格式、甚至挂号单上显示的文字。这些配置统一存放在一张tenant_config表里前端Vue在登录后拉取当前租户的配置渲染出不同的界面和流程。这个设计让同一套源码交付到十家门诊能呈现出十种不同的使用形态但核心代码纹丝不动。4.3 基于SpringBoot实现一个极简的多租户拦截器这一段我直接给你看一段实操代码。下面的TenantInterceptor是请求入口处的租户解析逻辑非常简单但非常关键。Component public class TenantInterceptor implements HandlerInterceptor { private static final ThreadLocalString TENANT_CONTEXT new ThreadLocal(); Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 1. 从请求头中获取租户标识 String tenantId request.getHeader(X-Tenant-ID); if (StringUtils.hasText(tenantId)) { TENANT_CONTEXT.set(tenantId); } else { // 2. 如果请求头没有尝试从Token中解析 String token request.getHeader(Authorization); if (token ! null token.startsWith(Bearer )) { // JWT解析逻辑省略这里假设从claims中拿到tenantId tenantId JwtUtils.parseTenant(token); TENANT_CONTEXT.set(tenantId); } } return true; } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 3. 请求处理完成后必须清理ThreadLocal否则线程池复用会串租户 TENANT_CONTEXT.remove(); } public static String getCurrentTenantId() { return TENANT_CONTEXT.get(); } }然后在MyBatis层面配置一个拦截器在执行SQL之前自动把租户条件拼进去。这一步我用的是MyBatis-Plus的TenantLineInnerInterceptor它可以直接指定需要忽略租户条件的表比如租户配置表本身非常方便。Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() { Override public Expression getTenantId() { return new StringValue(TenantInterceptor.getCurrentTenantId()); } Override public String getTenantIdColumn() { return tenant_id; } Override public boolean ignoreTable(String tableName) { // 租户配置表不需要追加租户条件 return tenant_config.equalsIgnoreCase(tableName); } })); return interceptor; }这段代码是你做SaaS二次开发时最容易踩坑的地方。最大的坑就是忘记清理ThreadLocal。在SpringBoot默认的Tomcat线程池中线程是会复用的上一个请求没清理的租户ID会“传染”到下一个请求轻则数据串了重则患者信息泄露。我最初犯过这个错排查了一整天才定位到问题。请务必确保afterCompletion里执行remove()。5. 前端Vue.js在门诊系统里的实战经验那些与“业务感”相关的事5.1 医护工作台的组件化拆解前端的组件化不只是一个技术概念它直接关系到后续功能迭代的速度。这套门诊系统我按角色拆成了几个大页面收银台、医生工作台、药房工作台、管理后台每个大页面又拆成更细的组件。比如医生工作台里有PatientQueue候诊队列、MedicalRecordForm病历录入、PrescriptionPanel处方开立、PastRecordsDrawer历史病历抽屉。这里有个经验不要过度抽象。医疗业务中有大量领域术语组件命名要贴近业务而不是贴近技术。我曾经见过有人把患者列表组件命名为ListContainer.vue三个月后自己都忘了这是干什么的。用PatientQueue.vue这种命名哪怕你半年不看代码扫一眼文件名就能重新上手。另一个经验是路由守卫和权限控制必须前置。门诊系统里有医生、护士、药师、管理员、收银员等好几个角色不同角色的菜单和按钮权限都不一样。在Vue里我统一在router.beforeEach中做登录态校验和角色路由过滤并且用自定义指令v-permission来控制单个按钮的显隐。后端接口同样要做鉴权前端控制UI只是体验问题后端鉴权才是安全问题——这两件事缺一不可。5.2 处方开立页一个反直觉但很好用的交互设计处方开立是整个系统交互最密集的页面。一开始我把药品搜索框、常用药列表、购物车式药品明细区、用法用量选择器全部放在同一个平铺页面里结果医生反馈说“太花眼睛累”。后来我做了个调整用药法用量用简明的Tab分段选择器常用药单独一个小侧栏历史处方一键复制。医生给一个复诊患者开药时最多只需要三步选中患者点击“复制上次处方”修改用量保存。这个改动给了我一个很重要的启发门诊系统的前端设计师不能只追求美观要追求“肌肉记忆”。医生每天重复操作几百次界面布局的位置应该保持高度稳定。所以我在做这套Vue前端时把维护一套稳定的布局规范看得比做花哨动效重要得多。Element UI的默认样式虽然谈不上惊艳但它组件间的一致性非常好这对高强度高频操作的工具型系统是非常加分的。5.3 Vue项目打包后如何优雅地放进SpringBoot这是一个我被问过非常多遍的问题开发时前后端分离但很多小门诊没有独立服务器希望能把前端打包后的静态文件直接放到SpringBoot的src/main/resources/static目录里让后端统一对外提供服务。我在这套源码里就是这么做的。前端项目根目录下配置vue.config.js设置publicPath: ./然后执行npm run build。构建产物dist目录下的所有文件直接复制到SpringBoot的resources/static目录。这样启动SpringBoot后访问http://ip:8080就能直接打开登录页后端API则统一挂在/api前缀下。在SpringBoot的application.yml里加一段配置避免前端路由和接口冲突spring: mvc: static-path-pattern: /** web: resources: static-locations: classpath:/static/需要注意Vue Router的History模式需要后端做回退支持。比如用户手动刷新/prescription/12这个路径时后台如果没有对应Controller就会返回404。在SpringBoot里我加了一个WebMvcConfigurer把非/api开头的所有路径都转发到index.htmlOverride public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController(/{path:[^\\.]*}).setViewName(forward:/index.html); }这个配置做完刷新问题就解决了。如果你用的是Hash模式则不受此影响但URL里会带个#号那个看起来不太专业能走History模式就尽量走History。6. 源码落地实操从拿到代码到本地跑起来6.1 环境准备清单与版本踩坑说明无论你在什么渠道获得这套SaaS门诊系统源码第一步做的都一样先把基础环境夯实在一个已知可用的版本组合上。我在做这套系统时用的环境如下JDK 8实际上Spring Boot 2.7.x在JDK 8下运行最稳如果用JDK 17部分老版本依赖会有兼容性问题Maven 3.6MySQL 5.7 或 MySQL 8.0推荐8.0但注意com.mysql.cj.jdbc.Driver参数和时区设置Node.js 14Vue前端构建需要我用的Vue CLI 5.xRedis如果你拿到的是带验证码或带Session共享的版本就需要Redis我最想提醒的是版本陷阱。SpringBoot在3.0之后做了一次大升级底层是Jakarta命名空间很多老源码基于javax命名空间写的直接升级SpringBoot 3.x会大量报错。如果你拿到的源码是基于SpringBoot 2.x的老老实实用JDK 8 Maven 3.6这套组合不要一上来就追求“越新越好”。6.2 数据库初始化和核心配置步骤拿到源码后我建议你按下面这个顺序操作建库在MySQL中创建一个数据库比如saas_clinic_db字符集选utf8mb4排序规则选utf8mb4_general_ci。千万不要用utf8否则遇到生僻字或特殊符号会报错。导入SQL脚本源码的sql目录下通常有init.sql、data.sql、demo_data.sql之类的文件把初始化脚本按顺序导入。注意看脚本里是否含有INSERT INTO ... tenant_config ...这类演示数据这种数据对于一个演示环境来说非常好用。修改后端配置打开application.yml或application-dev.yml改数据源连接。重点检查时区配置MySQL连接串里必须加serverTimezoneAsia/Shanghai否则时间字段会差8小时。spring: datasource: url: jdbc:mysql://localhost:3306/saas_clinic_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.Driver启动后端在项目根目录执行mvn spring-boot:run或用IDE直接启动Application类。看到Started Application in xx seconds日志后后端服务就起来了。构建前端进入web或frontend目录看源码结构有的叫ui先npm install安装依赖然后npm run serve以开发模式启动。浏览器访问localhost:8080Vue默认端口看vue.config.js配置如果后端跑在8080端口而前端要代理记得在vue.config.js里配置devServer.proxy把/api转发到后端。6.3 首次使用时的租户初始化这一步程序员最容易忽略这是我觉得最需要单拎出来讲的一步。SaaS系统第一次打开时你需要有一个“超级管理员”去创建第一个租户第一家诊所然后才能谈得上登录。源码中一般会内置一个sys_admin账号并在启动时自动创建平台管理员。你需要用它去后台创建第一个诊所录入诊所名称、执业许可证号、默认科室、默认收费项目等然后系统会为这个租户生成一个tenant_id。这个租户ID一定要妥善记录。前端登录页上一般会让用户选择“所属诊所”或输入“诊所编码”本质就是在告诉后端“我要以哪个租户身份登录”。这里常有开发者在测试时直接在后端Mock了一个tenant_id1结果换一台机器联调就忘了配置导致前端始终无法获取数据。如果你在本地联调时发现接口返回401或数据为空先检查请求头里有没有正确传递租户标识。7. 上线实战中的高频问题排查与性能优化7.1 门诊高峰期“卡顿”的真相与对策SaaS门诊系统在客户现场跑起来之后最大的性能考验就是上午9点到11点的就诊高峰。很多人一遇到卡顿就怀疑是服务器配置不够其实绝大部分情况不是这样。我用这套源码排查过的慢接口里最常见的原因是N1查询问题列表页查出100位患者后循环查询每位患者的最近一条就诊记录产生了101条SQL耗时飙升到好几秒。解决办法也不复杂用MyBatis的关联查询或批量查询代替循环查库。比如医生工作台待诊列表一次性查出所有候诊患者再用IN语句一次查出他们的最近就诊时间和主诉信息最后在Java内存中做匹配。改完之后接口响应时间基本能控制在200毫秒以内。另一个容易被忽视的点是前端表格的分页。不要一次性把某个月的全部挂号记录List出来前端再怎么懒加载都救不了数据量大的接口。后端用MyBatis-Plus的Page分页前端用el-pagination配合每页20条体验会非常流畅。7.2 数据准确性金额不一致的“元凶”排查思路收费金额不一致是门诊系统最敏感的问题。一套客户现场的系统如果统计报表和实际收费差了五毛钱老板就会对系统失去信任。这类问题一般有三个来源一是浮点数精度。金额计算不能用double或float必须用BigDecimal并且统一保留两位小数。二是并发更新。比如两个窗口同时对同一张处方单做退费操作就可能出现重复退费。解决方案是给关键单据状态加乐观锁version字段更新时校验版本号。三是数据库事务边界问题。我在代码评审时经常发现有人把insert和update分散在不同方法里没有放在同一个Transactional中。一旦中途抛异常数据就会处于半完成状态对账自然对不上。7.3 常用问题速查表症状可能原因处理办法前端能打开但登录后接口全部401请求头缺少Token或租户标识检查Axios拦截器是否自动添加Authorization和X-Tenant-ID启动报Table doesnt exist数据库脚本未完整导入重新按顺序导入SQL脚本注意字符集中文乱码数据源连接没有指定characterEncodingutf8在JDBC URL中追加characterEncodingutf8时间字段相差8小时时区配置错误JDBC URL追加serverTimezoneAsia/Shanghai接口响应慢N1查询或缺少索引启用MyBatis SQL日志分析慢语句对tenant_id patient_id建立联合索引部署到服务器后前端白屏静态资源路径不对确认publicPath: ./已设置图片使用相对路径部署后刷新子路由404Vue Router History模式未做回退按上文配置转发到index.html7.4 一套可以“抄作业”的ID生成与雪花算法实践最后补一个很实际的点医疗系统里挂号单号、处方单号、收费流水号这些编号会频繁出现在打印小票和跨系统对接的场景中格式必须统一而且不能重复。很多新手会直接在Java里用UUID.randomUUID().toString().substring(0, 16)当单号但UUID是字符串且无序放到数据库索引上性能不好打印出来也不好看。我在这套源码里用的是雪花算法支持下的自定义单号生成器。有人会担心雪花算法在分布式部署下时钟回拨会产生重复ID我的处理比较简单在单号里拼接一段业务前缀和日期。比如收费流水号格式为SF yyyyMMdd 6位自增序列每天重置一次再配合数据库唯一索引兜底。这样既保证了可读性也避免了并发冲突而且运营人员在Excel里按单号排序时非常方便。如果你拿到的源码里没有这个逻辑自己写一个IdGenerator组件也不难——只要保证“时间戳 自增序列 随机缓冲位”的结构就能满足门诊场景下的绝大多数需求。8. 基于这套源码还能往哪些方向扩展8.1 从门诊到诊所连锁向标准化集团管理演进单店SaaS门诊系统是一块敲门砖。一旦客户从一家诊所变成三家、五家连锁你对系统的掌控能力就直接决定了这个客户能跟你走多远。我在这套源码基础上做的第一个扩展就是连锁版本在租户之上再加一个group_id集团ID总部可查看旗下所有门店的营收、复诊率、药品库存周转等汇总数据各门店之间则保持数据隔离和独立运营。这个扩展从代码上讲改动并不大——业务表加个group_id字段报表层增加按门店聚合的路由——但商业价值完全不同客单价和客户粘性都会明显提升。8.2 线上线下一体化预约、问诊、电子处方流转门诊未来的核心竞争力不只是“到店看病”而是线上线下一体化。我在扩展时最常见的需求是患者通过公众号预约挂号、在线查看报告、在线缴费医生在接诊后可以生成电子处方慢病复诊患者甚至可以通过视频问诊完成开药药品直接快递到家。这些需求的落地路径非常清晰公众号或小程序端通过OAuth2对接SpringBoot后端走同一套API只是多了一层H5或小程序前端Vue.js后台管理端则天然适合做运营人员的工作台。在这个方向里接口设计一定要坚持RESTful风格和无状态Token鉴权这样后续接App、接小程序、接第三方平台都会非常从容。8.3 与医保接口、检验检查设备对接的规范化建议做医疗系统绕不开的一个话题是外部接口对接。但医保接口各地标准不同LIS和PACS设备的通信协议更是五花八门。我的建议是不要在源码的主流程里硬编码对接逻辑而是把外部接口抽象成一个ExternalService层用策略模式去适配不同的厂商协议再把对接配置写到tenant_config表里按租户激活。这样做的好处是你在A省上线时写的医保适配代码不会污染到B省客户的业务流某个诊所的某台检验设备没能对接成功也只会影响那一个租户的功能不会拖垮整个系统。我做这套SaaS门诊系统时最想留给你的一句话如果只让我选一条经验来总结那就是医疗系统的核心不是“能做出来”而是“能一直稳定地跑下去”。在门诊现场系统宕机十分钟就会造成患者积压、医生抱怨、前台手忙脚乱。SpringBoot和Vue.js这套组合当然不是唯一的选项但它是我实操下来稳定性、团队招聘难度、生态成熟度这三个维度上平衡得最好的一套。我见过太多项目死于过度设计——一开始就上微服务、上了K8s、搞了多机房容灾结果连一个门诊的日常业务都跑不顺。从单体SpringBoot开始从一套干干净净的Vue.js前端开始把业务流程吃透把多租户隔离做扎实等业务体量真正需要时再横向扩展这才是做SaaS医疗产品最务实的路径。希望这篇实操笔记能帮你少走一点我走过的弯路。
返回列表