PHP项目实战:新生儿疫苗接种管理系统设计与实现(ThinkPHP+MySQL)

ThinkPHP + MySQL + Ajax|多角色权限|预约、接种、档案与库存闭环

|------------------------------------------------------------------------------------------------------------------------------------------------------|
| 项目概览 本项目采用 PHP、ThinkPHP、MySQL 与 Ajax 构建,面向系统用户、接种员工和管理员三类角色,覆盖疫苗信息、预约审核、完成接种、儿童档案、供应商、疫苗入库、库存与财务信息等模块。本文不照搬论文,而是按照技术博客的阅读习惯,提炼项目结构、关键设计和可复用实现思路。 |

图 1 系统首页:公告、导航和业务入口集中展示

一、为什么要做这个系统?

新生儿疫苗接种管理涉及人员、疫苗、预约、接种记录、儿童档案和库存等多类信息。如果长期依赖纸质台账或分散的 Excel 文件,容易出现信息重复、查询困难、数据更新不及时、权限边界模糊以及记录难追溯等问题。

因此,本项目的核心目标不是简单地"做一套增删改查",而是把疫苗管理流程串成一条可追踪的业务链:疫苗建档 → 入库 → 库存 → 用户预约 → 审核与接种 → 儿童档案 → 财务统计。

|---------------------------------------------------------------------------------------------------|
| 本文定位 这是一个课程设计/毕业设计级的软件原型,重点展示后台管理系统的需求分析、数据库建模、角色权限和业务闭环。真实医疗场景还需要更严格的法规评审、隐私保护、审计追踪、容灾和接口标准。 |

二、角色与权限如何拆分?

|--------|------------------------------------------|
| 角色 | 主要权限 |
| 系统用户 | 注册登录、查看公告与疫苗信息、维护个人账户、提交预约等。 |
| 接种员工 | 查看疫苗库存和预约信息,维护完成接种记录与儿童档案。 |
| 管理员 | 维护用户、员工、供应商、疫苗、入库、库存、预约、接种记录、档案、财务和公共内容。 |

角色拆分的价值在于落实最小权限原则:普通用户不应接触后台库存和财务数据,接种员工只能处理与接种相关的业务,管理员负责基础数据和全局配置。权限设计越清晰,后续接口鉴权和菜单展示越容易维护。

三、系统功能架构

|--------|-----------------------------|
| 层级 | 职责 |
| 展示层 | 首页、注册登录、疫苗列表、个人账户、后台管理页面 |
| 业务层 | 用户认证、预约审核、接种登记、档案管理、入库与库存联动 |
| 数据层 | MySQL 业务表、访问令牌、用户组与权限数据 |
| 支撑能力 | Ajax 异步交互、参数校验、日志、异常处理、数据备份 |

核心业务流程

|--------|-----------|
| 步骤 | 业务动作 |
| 1 | 维护疫苗与供应商 |
| 2 | 录入疫苗入库 |
| 3 | 更新库存 |
| 4 | 用户提交预约 |
| 5 | 员工/管理员审核 |
| 6 | 登记完成接种 |
| 7 | 更新儿童档案与统计 |

其中最关键的是"预约---库存---接种记录"的一致性。如果预约成功却没有锁定库存,或者完成接种后没有扣减库存,就会出现业务数据互相矛盾。因此,这一部分应使用数据库事务处理。

四、技术选型

|----------|---------------------------------|
| 技术 | 用途 |
| PHP | 负责服务端业务逻辑,开发成本低,适合中小型 Web 管理系统。 |
| ThinkPHP | 提供路由、控制器、模型、验证器和数据库访问能力,减少重复代码。 |
| MySQL | 存储用户、疫苗、预约、接种、档案和库存等结构化数据。 |
| Ajax | 用于表单提交、列表刷新和状态更新,减少整页刷新。 |
| HTML/CSS | 构建前台页面与后台管理界面。 |

论文原稿中存在少量 Java/Spring 注解和 MyBatis 报错内容,与 PHP 技术栈不一致。技术博客发布时应删除这类模板残留,否则会降低文章可信度。

五、核心功能设计

1. 用户端

  • 注册与登录:校验必填项、账号唯一性和密码规则,登录成功后生成访问令牌。
  • 公告信息:查看管理员发布的通知与说明。
  • 疫苗信息:按名称、类型或厂家查询疫苗基础信息与注意事项。
  • 个人账户:维护昵称、头像、手机号、邮箱和密码。
  • 预约信息:选择疫苗并提交预约,查看审核状态。

图 2 用户注册页面:录入账号、联系方式和基础资料

图 3 用户登录页面

图 4 疫苗信息展示页面

2. 接种员工端

  • 查看疫苗仓库与可用库存。
  • 处理预约信息,确认预约内容和状态。
  • 登记完成接种信息,关联预约号、疫苗编号和接种对象。
  • 查看或维护儿童档案,形成可追溯记录。

3. 管理员端

  • 用户管理:维护管理员、系统用户和接种员工。
  • 疫苗管理:维护疫苗编号、名称、类型、厂家、价格、注意事项等信息。
  • 供应商与入库:记录供应商、入库号、数量、单价、金额和日期。
  • 预约与接种:审核预约,查看完成接种记录。
  • 儿童档案与财务:维护档案文件、收入、支出、利润和统计日期。
  • 公共管理:维护公告和轮播图。

图 5 后台疫苗信息管理:列表查询、编辑与删除

图 6 疫苗入库页面:录入批次、数量、单价和供应商

六、数据库设计:不求"表多",而求关系清楚

|--------------------------|-----------------------|
| 核心表 | 职责 |
| user / user_group / auth | 账户、用户组和权限控制 |
| system_user | 系统用户扩展资料 |
| inoculated_employees | 接种员工资料与审核状态 |
| vaccine_information | 疫苗编号、名称、类型、厂家、价格、注意事项 |
| supplier | 供应商、负责人及联系方式 |
| vaccine_warehousing | 入库号、数量、单价、金额、日期与供应商 |
| vaccine_warehouse | 当前库存、规格和新增时间 |
| appointment_information | 预约号、疫苗信息、预约人和审核状态 |
| complete_vaccination | 完成接种记录 |
| childrens_archives | 档案编号、用户、员工与档案文件 |
| financial_information | 收入、支出、利润和统计日期 |

数据库设计的 5 个关键点

  1. 主键与业务编号分离:主键用于关联,预约号、入库号、疫苗编号用于业务查询。

  2. 状态字段可枚举:预约状态、员工审核状态、账户状态应定义明确取值,避免自由文本。

  3. 金额使用 DECIMAL:不要使用浮点数保存价格、收入和支出。

  4. 建立唯一索引:username、appointment_no、warehousing_no 等字段应避免重复。

  5. 保留创建与更新时间:重要业务表至少包含 create_time、update_time,并记录操作人。

七、关键代码:从"能运行"改到"更安全"

论文原代码使用 MD5 保存密码。MD5 不适合密码存储,下面给出基于原业务逻辑整理的安全化示例。代码用于说明设计思路,具体命名应与项目实际模型和验证器保持一致。

1. 注册:唯一性校验 + password_hash

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| PHP public function register() { data = Request::only(\['username', 'password', 'nickname', 'phone', 'email'\]); validate(UserValidate::class)-\>scene('register')-\>check(data); if (User::where('username', data\['username'\])-\>find()) { return json(\['code' =\> 409, 'message' =\> '账号已存在'\]); } data'password' = password_hash(data\['password'\], PASSWORD_DEFAULT); data'create_time' = date('Y-m-d H:i:s'); User::create($data); return json('code' =\> 0, 'message' =\> '注册成功'); } |

2. 登录:password_verify + 随机令牌

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| PHP public function login() { data = Request::only(\['username', 'password'\]); user = User::where('username', data\['username'\])-\>find(); if (!user || !password_verify(data\['password'\], user->password)) { return json('code' =\> 401, 'message' =\> '账号或密码错误'); } token = bin2hex(random_bytes(32)); AccessToken::create(\[ 'user_id' =\> user->user_id, 'token' => hash('sha256', token), 'maxage' =\> 7200, 'create_time' =\> date('Y-m-d H:i:s') \]); return json(\['code' =\> 0, 'data' =\> \['token' =\> token]]); } |

3. 预约与库存联动:使用事务防止超卖

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| PHP Db::transaction(function () use (userId, vaccineId, appointmentNo) { stock = VaccineWarehouse::where('vaccine_information_id', vaccineId) -\>lock(true) -\>find(); if (!stock || stock-\>inventory_quantity \<= 0) { throw new RuntimeException('当前疫苗库存不足'); } AppointmentInformation::create(\[ 'appointment_no' =\> appointmentNo, 'appointment_user' => userId, 'vaccine_information_id' =\> vaccineId, 'examine_state' => '待审核' ]); stock-\>inventory_quantity -= 1; stock->save(); }); |

如果业务要求"审核通过后才扣库存",可以在提交预约时冻结库存、审核失败时释放库存。无论采用哪种策略,都要保证状态变化和库存变化在同一事务中完成。

八、测试:不仅测按钮,还要测业务边界

|--------|-------------------|-----------------|
| 模块 | 测试场景 | 预期结果 |
| 注册 | 账号为空、重复账号、两次密码不一致 | 提示明确且不写入脏数据 |
| 登录 | 账号不存在、密码错误、令牌过期 | 拒绝访问并返回统一错误结构 |
| 疫苗入库 | 数量为 0、单价为负、入库号重复 | 校验失败,不更新库存 |
| 预约 | 库存不足、重复预约、并发提交 | 不超卖、不生成重复记录 |
| 完成接种 | 预约未审核、记录重复提交 | 阻止非法状态跳转 |
| 权限 | 普通用户访问后台接口 | 返回 403,前端菜单也不可见 |

常见问题与处理

  • 数据库中文乱码:数据库、数据表、连接和页面统一使用 utf8mb4。
  • 前后端参数不一致:为接口定义固定字段名和响应结构,避免前端写一个名字、后端读另一个名字。
  • 重复提交:关键表建立唯一索引,接口增加幂等校验。
  • 库存出现负数:事务、行锁和条件更新必须同时考虑。

九、从毕业设计走向可用系统,还需要补什么?

  1. 隐私保护:儿童档案、手机号等敏感信息需要脱敏展示、加密存储和访问审计。

  2. 安全防护:启用 CSRF 防护、输入校验、文件上传白名单、登录限流和操作日志。

  3. 批次追溯:库存应增加批号、生产日期、有效期、存储条件和召回状态。

  4. 权限细化:从"按角色控制菜单"升级为"按接口、数据范围和操作类型授权"。

  5. 备份与容灾:配置自动备份、恢复演练、异常告警和关键任务重试。

  6. 规范对接:真实部署前应根据当地卫生主管部门和医疗机构要求重新设计业务流程。

十、总结

这个项目的价值不只在于实现了多个管理页面,更重要的是把疫苗信息、入库库存、用户预约、完成接种和儿童档案串成了一个相对完整的业务闭环。对于 PHP 初学者而言,它可以帮助理解 ThinkPHP 分层、MySQL 关系建模、角色权限、状态流转和事务一致性。

在整理成技术博客时,应减少论文式背景铺陈和重复的增删改查描述,把篇幅集中到"为什么这样设计、关键表如何关联、核心流程如何保证一致性、代码有哪些安全问题"上。这样的内容更容易被搜索到,也更有收藏和复用价值。

|------------------------------------------------------|
| 关键词 PHP|ThinkPHP|MySQL|Ajax|疫苗接种管理系统|后台管理系统|毕业设计 |

|------------------------------------------------------------------------|
| 版权与合规说明 发布前请确认论文、代码和系统截图的版权归属;截图不得包含真实个人敏感信息。本文仅讨论软件设计与实现,不提供医疗建议。 |