
这些年做全栈项目我经手过不少类似“社区医院信息管理系统”的东西有拿来练手的、毕业设计用的也有真实准备上线给基层医疗机构用的。说实话这类项目看着是典型的CRUD但一旦把预约挂号、医生接诊、病历处方、药品库存、收费退费这些环节串起来复杂度立刻就不一样了。今天要拆解的这个项目标题很直白“企业级社区医院信息平台管理系统源码SpringBootVueMyBatis架构MySQL数据库【完整版】”我不打算给你罗列源码目录而是从需求、数据表、核心模块、部署排坑四个维度把这个系统讲透让你拿到类似项目或者自己要写一套时能真正落地。这套系统面向的核心场景就是社区医院/基层卫生服务中心的信息化管理涉及的患者端、医生端、药房端、管理端都能在这个系统里找到对应流程。技术栈是SpringBoot Vue MyBatis MySQL属于目前Java全栈开发里非常稳妥、也非常适合中小型团队维护的组合。适合谁来参考准备做医院管理类毕设的学生、想积累完整全栈项目的初级开发者以及小团队接基层医疗信息化外包的技术负责人都可以把它当成一个相对完整的研究样本。1. 项目整体设计与需求拆解1.1 社区医院的信息化痛点很多人以为社区医院的业务比三甲医院简单其实恰恰相反。社区医院的特点是科室少、人员少、但业务覆盖宽日常门诊、慢病随访、疫苗接种、体检、家庭医生签约都有可能掺进来。信息系统的最大难题不是某个功能多难写而是“流程要闭环”。举个例子只做一个“挂号页面”很容易但挂完号之后医生能不能在系统里看到候诊队列看完病开的处方能不能自动扣减药房库存患者缴费之后药房能不能收到发药通知这些环节只要断了一处系统就很难真正用起来最后还是会退回手工登记。所以这个系统设计的第一原则是“以患者就诊主流程为主线以库存和财务为约束”。一切功能都是围绕“预约挂号 - 医生接诊 - 开方开检 - 缴费 - 取药/检查 - 报告查询”这条链路来构建的。1.2 角色梳理与核心业务流程系统里至少要能区分出四类核心角色患者/访客注册、登录、预约挂号、查报告、看缴费记录。医生查看当日患者列表、书写病历、开处方、开检验检查、查看历史病历。药房库管/药师药品入库、库存管理、发药退药、近效期预警。系统管理员科室管理、排班管理、员工账号、收费项目管理、数据统计。这四类角色对应到权限设计上不能靠前端按钮隐藏去做安全控制后端每个接口都必须校验角色。实际开发中我会用JWT携带用户ID和角色标识再通过拦截器或注解去控制接口访问范围。主流程上图的话是这样患者选科室看排班 - 选择医生和时间段 - 生成挂号记录同步扣号源 - 就诊日医生叫号 - 医生录入主诉、诊断 - 开处方或检验检查单 - 患者缴费 - 药房/医技科室接到任务 - 发药/执行检查 - 结果回传 - 患者查询。这个流程里最容易被忽略的是“状态机”。比如挂号记录的状态待支付、已支付、已就诊、已取消缴费记录的状态待支付、已支付、已退费。每条状态流转都要在代码里明确约束不然上线之后数据会很乱。1.3 功能模块清单从实际交付的角度看一个完整的社区医院信息平台至少包含以下模块系统管理用户、角色、菜单、科室、数据字典。排班管理医生出诊计划、号源数量、停诊/替代。预约挂号号源查询、预约、取消、当日挂号。门诊医生站接诊列表、电子病历、处方开立、检查检验申请。药库管理药品档案、入库、出库、库存盘点、预警。收费管理收退款、缴费单、发票号登记。查询统计收入日报、科室工作量、药品消耗排行、患者来源分析。在这些模块里最值得花精力的是“医生站”和“药库管理”因为它们直接关系到医护人员日常工作效率也是项目里事务逻辑最密集的地方。2. 技术选型与架构设计2.1 为什么是这个技术组合SpringBoot Vue MyBatis MySQL的组合不是最炫的但它很适合这类业务系统。SpringBoot的自动配置和Starter机制能大幅减少配置代码开发效率高而且Java生态在医疗这类传统行业里认可度很高后续接医保接口、电子健康档案、区域卫生信息平台时Java的兼容性优势还是比较明显的。Vue在前端生态里的学习曲线平缓组件化开发很适合医院这类多表单、多列表的管理系统。配合Element UI或Element Plus表格、弹窗、表单校验这些组件基本开箱即用开发速度很快。MyBatis是这类系统的另一个好选择。医院管理的SQL往往比较复杂比如多表关联查询医生排班、统计报表里的分组汇总MyBatis允许开发者直接写SQL可控性很强。遇到复杂查询时JPA那种自动生成的SQL反而会让人抓狂。MySQL作为关系型数据库满足事务ACID要求支撑医疗数据的强一致性部署和运维成本也低社区医院级别的并发量完全够用。2.2 前后端分离架构项目采用的是前后端分离架构分为server后端和ui前端两个部分。后端无状态接口前端通过HTTP调用鉴权用JWT。一个比较清晰的后端目录结构是这样src/main/java ├── com.hospital │ ├── controller # 接口层 │ ├── service # 业务层写核心逻辑 │ ├── mapper # MyBatis Mapper接口 │ ├── entity # 数据库实体 │ ├── dto # 前端交互对象避免暴露实体 │ ├── vo # 视图对象如统计报表 │ ├── config # 配置类如CORS、拦截器 │ ├── security # JWT相关工具和过滤器 │ ├── common # 统一返回结果、全局异常处理 │ └── utils # 工具类前端目录按Vue项目的标准来views下面按角色分目录admin、doctor、pharmacist、patient每个页面组件独立路由懒加载。2.3 MyBatis的合理使用方式项目如果用的是原生MyBatis不带MyBatis-Plus我建议从第一天就约定好规范否则后期维护成本会很高。第一Mapper接口与XML的路径要一一对应。比如com.hospital.mapper.DoctorScheduleMapper对应resources/mapper/DoctorScheduleMapper.xml命名不能随意改。第二所有复杂的动态SQL都写在XML里用sql片段抽取公共字段用where和foreach处理动态条件避免在Java代码里拼SQL字符串。第三通用字段如创建时间、更新时间、逻辑删除标记在每个实体类里都保留同时提供一个基础ResultMap方便统一映射。以排班查询为例医生排班要关联科室表、医生表、号源表如果只查一张表就返回vo那代码里要循环查N次数据库性能很差。正确的做法是在XML里一次多表查询直接映射到视图对象比如select idselectScheduleList resultTypecom.hospital.vo.DoctorScheduleVO SELECT ds.id AS scheduleId, d.dept_name AS deptName, u.real_name AS doctorName, u.title AS doctorTitle, ds.work_date AS workDate, ds.time_slot AS timeSlot, ds.total_num AS totalNum, ds.remain_num AS remainNum, ds.fee AS regFee FROM hos_doctor_schedule ds INNER JOIN hos_dept d ON ds.dept_id d.id INNER JOIN sys_user u ON ds.doctor_id u.id WHERE ds.work_date BETWEEN #{startDate} AND #{endDate} ORDER BY ds.work_date, ds.time_slot /select2.4 关于Redis和微服务的取舍这个项目没有把Redis写进技术栈里我认为这是合理的。社区医院系统的用户量有限并发挂号峰值远没到必须用Redis秒杀的程度。数据库行锁和唯一索引足以保证业务正确性。但如果你想让项目更有竞争力可以在“验证码”“今日热门科室缓存”“Token黑名单”这些点上引入Redis作为扩展点展示。微服务也一样这个阶段强行拆订单服务、用户服务只会增加运维负担单体应用配合良好的模块划分不仅开发效率更高部署也省心。3. 数据库设计与核心表结构3.1 设计原则业务闭环优先数据库设计是整个系统里最影响成败的环节。我见过很多项目代码架构很漂亮但表结构设计得一塌糊涂导致写业务的时候反复调整。医疗信息系统的表设计有几个原则要牢记主键统一用自增ID或雪花ID不要用业务字段做主键。金额字段一律用DECIMAL(10,2)禁止使用FLOAT或DOUBLE。所有涉及时间状态的表要有status字段并建立索引。逻辑删除用deleted字段不物理删除医疗记录便于追溯。关键业务表都带create_time、update_time、create_by、update_by。3.2 核心数据表概览整个系统的表大致可以分成四组基础资料组sys_user用户、sys_role角色、sys_user_role用户角色关联、hos_dept科室、hos_drug_info药品档案、hos_settle_item收费项目。业务流转组hos_patient患者档案、hos_doctor_schedule排班、hos_appointment预约挂号、hos_medical_record病历、hos_prescription处方、hos_prescription_item处方明细、hos_check_order检验检查申请。药库财务组hos_drug_stock库存、hos_drug_stock_flow出入库流水、hos_payment_record缴费记录、hos_refund_record(退费记录)。统计分析组主要依赖上述业务表做汇总一般无需额外建表但可以建hos_settle_day_summary日结表把每天的挂号收入、药品收入汇总进去方便月底对账。3.3 关键字段设计示例以预约挂号表为例这是全系统最容易出错的表之一CREATE TABLE hos_appointment ( id BIGINT NOT NULL AUTO_INCREMENT, appointment_no VARCHAR(32) NOT NULL COMMENT 就诊号/流水号, patient_id BIGINT NOT NULL, schedule_id BIGINT NOT NULL COMMENT 排班ID, dept_id BIGINT NOT NULL, doctor_id BIGINT NOT NULL, appointment_date DATE NOT NULL, time_slot TINYINT NOT NULL COMMENT 时间段 1-上午 2-下午, fee DECIMAL(10,2) NOT NULL DEFAULT 0.00, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待支付 1已支付 2已就诊 3已取消, source_type TINYINT DEFAULT 1 COMMENT 号源类型 1-预约 2-现场挂, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_appointment_no (appointment_no), UNIQUE KEY uk_patient_schedule (patient_id, schedule_id, appointment_date, time_slot), KEY idx_doctor_date (doctor_id, appointment_date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里最关键的约束是uk_patient_schedule它的作用是防止同一个患者在同一个时间段重复挂号。这个唯一索引比在Java代码里先查再插要可靠得多涉及并发时有无索引差距很大。排班表里则需要包含total_num和remain_num两个字段挂号成功时remain_num remain_num - 1。这个扣减操作不能做成“先查询剩余再判断大于0再更新”而应该用一条带条件的UPDATE来实现原子扣减UPDATE hos_doctor_schedule SET remain_num remain_num - 1 WHERE id #{scheduleId} AND remain_num 0上面这条SQL返回的影响行数如果为1说明号源扣减成功如果为0说明已经没有余号业务层直接抛出“号源已满”的异常。这是互联网秒杀系统里“乐观锁扣库存”的常用手法在这个规模的项目里正好适用。3.4 索引与冗余字段的取舍很多新手在表设计时习惯加很多外键我不建议加物理外键因为医院系统的数据是持续增长的物理外键会在高并发写入时带来额外锁开销。业务完整性由代码层和索引约束共同保证外键关系通过表的关联字段维护即可。但索引不能少。业务上高频查询的字段必须建索引排班表的(doctor_id, work_date)、挂号表的(patient_id, status)、缴费记录的(payment_no)、药品库存的(drug_id)。统计报表涉及的create_time字段也建议加索引否则数据量上来之后日报会越查越慢。4. 关键功能模块实现4.1 JWT登录鉴权与权限拦截登录模块使用JWT作为无状态凭证。用户用用户名和密码登录成功后后端生成一个Token里面放入userId、realName和roleCode客户端存到localStorage里之后每次请求在请求头带上Authorization。Token生成可以用Java的jjwt库核心代码大致是public String createToken(Long userId, String username, String roleCode) { Date now new Date(); Date expire new Date(now.getTime() 7200 * 1000); // 2小时过期 return Jwts.builder() .setSubject(username) .claim(userId, userId) .claim(roleCode, roleCode) .setIssuedAt(now) .setExpiration(expire) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); }密码存储一律用BCryptPasswordEncoder不要用MD5或SHA明文加密因为这两者已经被彩虹表打穿了。社区医院系统虽然不像互联网大厂那样天天被攻击但医疗数据属于敏感数据密码处理和权限控制不能糊弄。后端权限拦截用HandlerInterceptor实现注册时指定拦截路径。放行登录接口和静态资源其他接口校验Token有效性再根据接口上的RequireRole注解校验角色。我见过的很多前端项目把按钮权限控制写在路由里这只能提升用户体验不能作为安全措施。真正的权限校验必须在后端接口层完成因为接口是可以被绕过前端直接调用的。4.2 排班查询与预约挂号流程排班查询接口的输入是科室ID、日期范围输出是医生排班列表包含医生姓名、职称、出诊时间、剩余号源和挂号费。前端页面可以选择科室、日期然后以卡片或表格形式展示排班。选好时段后点击“预约”如果用户之前没建档要先填写身份证、姓名、手机号生成患者档案。挂号的后端逻辑采用“事务内先扣库存再插入挂号记录”的顺序。也就是说在同一个Transactional方法里先执行前面那条条件UPDATE扣减排班表的remain_num如果影响行数为0则抛出业务异常事务回滚如果成功再插入hos_appointment记录。这里有个容易踩坑的点如果把插入挂号记录放在扣库存之前一旦库存扣减失败就产生了一条状态为待支付的孤儿挂号单需要定时任务反复清理。先扣库存后插入配合事务回滚数据始终是一致的。挂号费用支付这里可以做模拟支付用一笔缴费记录状态表示是否支付。真实的医院系统会对接支付渠道但为了源码便于学习和本地运行做成“余额支付/模拟支付”是务实的做法。4.3 医生接诊与电子处方医生登录后进入门诊医生站看到当天自己名下的患者列表。这个列表来自hos_appointment表中状态为“已支付”且日期为当天的记录。接诊时医生创建或更新病历。电子病历的核心字段包括主诉、现病史、既往史、查体、初步诊断、处理意见。这些是医疗文书记录的一部分任何字段都不允许在没留痕的情况下修改因此hos_medical_record表里record_no、record_status这些字段要在一开始就设计好。开处方的业务逻辑比病历稍复杂一张处方有多个药品明细每个药品都要校验当前库存是否充足不足则不能开立。前端逐行加入药品后端在保存处方时批量查询药品库存生成处方主表记录和明细记录同时扣减对应药品的库存。扣减库存同样不能用“先查库存再减”的方式而是逐条执行条件UPDATE例如UPDATE hos_drug_stock SET stock_num stock_num - #{useNum} WHERE drug_id #{drugId} AND stock_num #{useNum}如果某条更新影响行数为0说明库存不足抛异常让整个处方事务回滚所有药品都不扣减。这就避免了患者缴费后药房凑不齐药的情况。4.4 药品库存与出入库流水药品管理相对独立但逻辑上要细致。入库时填写供货商、批号、生产日期、有效期、采购价和零售价入库成功后同时生成一条入库流水库存数量增加。出库时对应药房发药或药品报损生成出库流水库存减少。库存台账里有几个字段要特别注意warning_num预警阈值、shelf_status上下架状态、expire_date有效期。近效期预警功能的SQL很简单查询有效期在30天内且库存大于0的药品即可。上线后这个功能很受药房人员欢迎因为手工登记很容易忘记哪些药快过期了。发药流程要和缴费记录联动。患者缴费成功后药房看到待发药列表点击发药时确认库存扣减同时将缴费记录状态更新为“已发药”。退药则要走逆向流程先检查处方是否已发药、是否存在退费记录再回补库存。4.5 统计报表与数据汇总统计报表如果全部实时从业务表里COUNT和SUM数据量上去后会拖慢业务库。折中方案是每天凌晨通过定时任务把前一天的数据汇总到hos_settle_day_summary表报表查询只查汇总表。当日数据仍然实时统计实时统计和日结表通过“日期”维度合并展示。日报指标包括预约挂号量、现场挂号量、门诊收入、药品收入、检查检验收入、退费金额。科室维度的统计通过GROUP BY dept_id实现医生维度统计通过GROUP BY doctor_id实现。这个模块虽然技术难度不高但在业务上很为项目加分。因为医院管理者最关心的往往不是哪个界面操作顺畅而是“今天收入多少、哪个科室患者多、哪些药品消耗快”这些数据是系统上线后被高频使用的功能。5. 部署上线与运维避坑5.1 数据库初始化与种子数据项目自带的SQL脚本一般分三类建表脚本、基础数据脚本、演示数据脚本。拿到源码后建议按顺序执行。基础数据里至少要包含系统管理员账号、科室数据内科、外科、儿科、妇产科、中医科、全科等、常用数据字典时间段、挂号状态、缴费类型、药品分类和几种常用药品。这里踩过不少坑MySQL初始化脚本如果直接复制粘贴到命令行执行容易因为编码格式不对导致中文乱码。正确的做法是在执行前用source命令导入或者在客户端里设置连接字符集为utf8mb4后再导入。5.2 application.yml配置细节后端配置是运行能不能顺畅的关键尤其是数据源配置。以MySQL 8.0为例常见的正确配置是spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/hospital_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue username: root password: 123456几个参数的用途说明一下characterEncodingutf8保证中文正常读写。serverTimezoneAsia/Shanghai解决MySQL 8.0时区报错的问题。allowPublicKeyRetrievaltrue解决新版MySQL驱动在非SSL连接时报警告的问题。useSSLfalse是因为本地开发通常不需要SSL加密内网数据库开SSL反而增加性能开销。如果你还在用MySQL 5.7驱动类名要写com.mysql.jdbc.Driver但MySQL 8.0以上的驱动必须用com.mysql.cj.jdbc.Driver。项目报错“ClassNotFoundException”或者“Public Key Retrieval is not allowed”时第一反应先检查这一行。5.3 前端打包与Nginx配置前端开发模式通过Vite或Webpack代理后端地址生产环境则把源码构建成静态文件放在Nginx里托管。Nginx的核心配置就三块监听端口、前端静态资源目录、API反向代理。示例配置片段如下server { listen 80; server_name localhost; root /opt/hospital/dist; index index.html; location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { try_files $uri $uri/ /index.html; } }这里最关键的是最后一行try_files $uri $uri/ /index.html它的作用是前端路由的history模式刷新页面时不返回404。很多新手把前端打包扔到Nginx后发现刷新子页面就白屏问题基本就出在这条配置缺失。生产环境我一般建议把后端服务做成systemd服务开机自启日志输出到固定文件方便排错。也可以用Docker但社区医院这种规模的项目一台2核4G的云服务器部署单体应用完全够用不一定要上容器。5.4 时区、日期和跨域问题前后端分离项目联调时最消耗时间的问题往往不是业务逻辑而是数据格式。第一个是日期格式。后端返回的LocalDateTime默认序列化格式是yyyy-MM-ddTHH:mm:ss前端如果不做处理表格里会出现字母T用户体验很差。解决办法是在配置类里统一设置ObjectMapper的日期格式。第二个是跨域。开发时前端跑在5173或3000端口后端跑在8080端口浏览器会因为同源策略拦截请求。解决方式不是在前端代理里全部配置一遍而是在后端加一个全局CORS配置允许开发环境的来源。Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }生产环境有Nginx反向代理后前后端域名通常一致或通过前缀区分反而不会有跨域问题所以这个配置主要在本地开发阶段发挥作用。6. 常见问题与排查技巧实录6.1 登录鉴权常见的坑**问题1前端登录后刷新页面用户信息丢失。**这个通常是因为只存了Token没有存角色信息或者路由守卫里没有根据Token拉取用户信息。解决办法是在本地持久化Token并在路由守卫里判断Token存在时拉取一次用户信息接口。**问题2改完密码后老Token还能用。**JWT是无状态的Token签发后服务器无法主动让它失效除非维护一个黑名单。社区医院场景不要求那么严格但从安全角度可以在用户表存一个token_version字段每次改密码加一JWT里带上这个版本号校验时比对版本号即可。**问题3权限注解不生效。**如果是自定义的RequireRole注解配拦截器实现要注意注解是否被Spring扫描到以及方法参数解析是否被拦截器正确执行。最简单的方式是在拦截器里通过HandlerMethod.getMethodAnnotation(RequireRole.class)获取而不是自己反射解析。6.2 挂号与库存并发问题**问题现象**两个用户同时点击最后一个号源数据库里可能出现超卖。**原因**代码逻辑是“先查询剩余号数大于0再插入挂号记录”两条请求同时查询到剩余1就都能通过校验。**解决办法**用我前面写的条件UPDATE扣减库存影响行数为0就报错。这个办法在MySQL的InnoDB引擎下是安全的因为UPDATE执行时会自动对满足条件的行加锁。药品库存扣减同理。处方如果包含多个药品必须把所有扣减放在同一个事务内任何一个药品库存不足整体回滚。6.3 金额计算精度问题**问题现象**统计报表里金额合计出现0.30000000000000004或者9.9999999999这类数字。**原因**浮点数用二进制无法精确表示十进制小数医院收费金额一旦出现这种情况对账就会很痛苦。**解决办法**数据库用DECIMAL(10,2)Java实体类用BigDecimal不要用double。计算合计时在SQL里直接SUM(amount)数据库返回的本身就是BigDecimal避免在Java里遍历累加时又转成double。前端展示金额时也要小心JavaScript的parseFloat依然是浮点运算适合展示不适合做金额累加。金额相关的计算尽量让后端完成前端只负责展示。6.4 MyBatis常见报错速查我整理了一个简单的速查表都是实际开发中频率较高的报错报错信息常见原因解决办法Invalid bound statement (not found)Mapper接口方法未在XML中定义或XML路径不对检查Mapper XML的namespace和方法ID确保与接口一致Parameter xxx not found多参数方法未使用Param注解接口方法参数前加Param(xxx)Cause: java.sql.SQLSyntaxErrorExceptionXML中SQL写错或使用了数据库保留字关键字段加反引号比如status、orderResultMap映射出来的对象属性全是null数据库列名和下划线字段映射未开启开启mapUnderscoreToCamelCasetrue或写完整的resultMap批量插入效率太低for循环单条插入使用foreach标签拼接批量INSERT这里特别说一下mapUnderscoreToCamelCase。MyBatis在配置里开启这个选项后数据库的create_time可以自动映射到实体的createTime省去大量resultMap。但不建议所有映射都依赖它因为一旦字段别名变了很容易出现局部null问题。7. 项目扩展方向与个人实操体会这类社区医院信息平台做完核心流程之后后续还可以围绕几个方向继续扩展这里分享一点我自己的看法。首先是健康档案模块。社区医院的定位是居民健康守门人长期随访和慢病管理才是它的核心价值。可以在现有患者档案基础上增加血压、血糖、体质指数等测量记录生成趋势图。这个扩展对代码而言就是在患者维度新增几张测量记录表再写几个查询接口但在基层医疗的业务价值上非常高真正解决了医院对慢病患者的日常跟踪需求。其次是体检管理。社区医院普遍承担居民体检任务流程里包含体检套餐选择、分科室检查、总检报告生成。这个模块涉及的状态比门诊更多很能锻炼开发者的流程建模能力。第三是公共卫生数据上报。很多基层医院需要定期整理数据上报系统做得好可以直接从业务表里取数生成上报报表减少人工统计工作量。最后说一点我做这类项目的个人体会。拿到类似“社区医院信息管理系统”的项目不要急于先写页面先把业务主流程画出来然后直接设计数据库表表设计决定了这个项目的天花板。如果能把挂号、处方、库存这个三角闭环讲清楚表结构设计得经得起推敲代码哪怕朴素一点这个项目也是扎实的。反过来表设计得混乱后面所有模块写起来都会很累改来改去等于返工。还有一个小技巧建议开发时一定要写一个“模拟数据初始化脚本”把排班、挂号、病历、处方、库存都预置好。每次改动完代码重置一次数据库就能快速进入联调状态。没有演示数据的系统开发效率会低很多因为测试一个医生接诊流程至少要手动创建好几条关联数据很浪费时间。这个脚本值得保留下来后面做演示、写文档、带新人都会用到。