1. 项目背景与核心需求
宠物医疗行业近年来呈现爆发式增长态势。根据行业数据显示,2023年全国宠物医院数量已突破3万家,年复合增长率达到18%。这种快速增长带来了管理上的挑战——传统纸质记录和单机版管理系统已经无法满足现代宠物医院的运营需求。
我在大三暑期实习时,曾亲眼目睹一家中型宠物医院因为系统崩溃导致当天所有预约信息丢失的混乱场景。医生们不得不手写记录,前台需要反复打电话确认预约,整个医院乱成一团。这次经历让我深刻认识到:一个稳定可靠的数字化管理系统,对宠物医院而言不是锦上添花,而是刚需。
基于SSM(Spring+SpringMVC+MyBatis)和Vue.js的技术组合,正好能够解决以下几个核心痛点:
- 数据孤岛问题:传统Excel记录导致病历、药品、财务数据分散存储
- 预约效率低下:电话预约占用人手且容易出错
- 库存管理混乱:药品和耗材过期、缺货情况频发
- 决策缺乏依据:无法快速生成经营报表
这个毕设项目的独特价值在于:它不是简单的CRUD系统演示,而是针对宠物医院真实业务场景的完整解决方案。从医生排班到疫苗提醒,从寄养管理到会员积分,每个功能模块都源自实际需求。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与架构设计
2.1 为什么选择SSM+Vue这个技术栈?
在技术选型阶段,我对比了三种常见方案:
| 方案 | 开发效率 | 学习成本 | 社区支持 | 适合场景 |
|---|---|---|---|---|
| PHP+Laravel | 高 | 低 | 一般 | 快速原型开发 |
| Node.js+Express | 中 | 中 | 较好 | 实时性要求高的应用 |
| SSM+Vue | 中高 | 中高 | 优秀 | 企业级管理系统 |
最终选择SSM+Vue主要基于以下考量:
- 技术成熟度:SSM框架经过多年企业级应用验证,Spring的IoC容器和AOP支持能有效管理复杂业务逻辑
- 前后端分离:Vue的响应式特性与SSM的RESTful API天然契合
- 扩展性需求:考虑到未来可能对接智能硬件(如宠物可穿戴设备),需要稳健的后台架构
- 团队协作:清晰的接口文档便于前后端并行开发
2.2 系统架构详解
系统采用经典的三层架构,但在细节上做了针对性优化:
code复制[前端层] Vue 2.6 + Element UI + Axios
↑↓ HTTP/HTTPS
[应用层] Spring MVC + RESTful API
↑↓ 接口调用
[持久层] MyBatis + MySQL 8.0
↑↓ 连接池
[基础设施] Redis缓存 + 阿里云OSS
几个关键设计决策:
- 双Token机制:采用Access Token + Refresh Token解决医患端频繁登录问题
- 智能分表策略:病历数据按宠物ID哈希分表,避免单表过大
- 混合缓存方案:
- Redis缓存高频访问的药品目录
- LocalStorage缓存用户个性化设置
- 文件存储优化:
- 小于1MB的检查报告直接存数据库(Base64)
- 大于1MB的影像资料上传OSS
特别注意:MyBatis的二级缓存默认是Session级别,对于药品库存这种关键数据,必须关闭缓存或实现自定义更新策略,否则会导致超卖问题。
3. 核心功能模块实现
3.1 预约挂号子系统的技术难点
预约模块看似简单,实则隐藏着诸多陷阱。以下是我们在开发中遇到的实际问题及解决方案:
问题1:并发预约冲突
当多个用户同时预约同一位医生时,可能出现超约情况。我们最终采用MySQL乐观锁+Redis分布式锁的双重保障:
java复制// 伪代码示例
public boolean makeAppointment(Long doctorId, LocalDateTime time) {
String lockKey = "lock:appoint:" + doctorId + ":" + time;
try {
// 获取分布式锁(设置3秒过期防止死锁)
Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 3, TimeUnit.SECONDS);
if (locked != null && locked) {
// 查询剩余可约数量
Integer remaining = appointmentMapper.selectRemainingSlots(doctorId, time);
if (remaining > 0) {
// 使用版本号控制并发更新
int updated = appointmentMapper.updateSlotsWithVersion(
doctorId, time, version);
if (updated > 0) {
return true;
}
}
}
return false;
} finally {
redisTemplate.delete(lockKey);
}
}
问题2:医生临时停诊处理
最初的设计是在停诊时删除相关时间段记录,但这样会丢失已预约记录。改进方案:
- 新增
schedule_status字段(0=可约,1=已约,2=停诊) - 停诊操作改为批量更新状态
- 前端用不同颜色区分状态
- 自动短信通知已预约用户
3.2 电子病历模块的创新设计
传统病历系统往往只是纸质记录的电子化,我们在此基础上增加了三个实用功能:
-
智能模板:
- 根据宠物品种自动推荐检查项目
- 常见病种一键生成病历框架
- 支持自定义模板保存
-
病程图谱:
mermaid复制graph LR
A[首次就诊] -->|主诉: 呕吐| B[血常规]
B --> C[诊断为肠胃炎]
C --> D[开药: 益生菌]
D -->|3天后复诊| E[症状缓解]
E --> F[调整用药剂量]
(注:实际实现使用ECharts绘制时间轴图表)
- 用药提醒:
- 自动计算下次驱虫时间
- 微信推送用药提醒
- 关联药品库存自动生成采购建议
4. 典型业务场景与代码实现
4.1 疫苗到期提醒的完整实现链路
这个功能看似简单,但要考虑多种边界情况:
-
数据采集阶段:
- 需要区分核心疫苗(如狂犬病疫苗)和非核心疫苗
- 记录疫苗批次和有效期
- 关联宠物年龄、体重等基本信息
-
提醒触发逻辑:
java复制// 每天凌晨1点执行的定时任务
@Scheduled(cron = "0 0 1 * * ?")
public void checkVaccineExpiration() {
// 查询未来7天内到期的疫苗记录
List<VaccineReminder> reminders = vaccineMapper.selectExpiringSoon();
reminders.forEach(reminder -> {
// 排除已提醒过的记录
if (!reminder.isNotified()) {
// 组装提醒内容
String content = buildReminderContent(reminder);
// 发送短信(异步处理)
smsService.sendAsync(reminder.getOwnerPhone(), content);
// 标记为已提醒
vaccineMapper.updateNotifiedStatus(reminder.getId(), true);
}
});
}
- 用户体验优化:
- 提供"稍后提醒"选项(1天后/3天后)
- 支持一键预约疫苗接种
- 显示附近宠物医院地图
4.2 库存管理的防呆设计
药品库存管理是医院运营的核心环节,我们实现了以下防护措施:
-
批次管理:
- 同一药品不同批次分开显示
- 近效期自动置顶显示
- 过期药品自动锁定
-
智能预警:
sql复制-- 库存预警视图
CREATE VIEW inventory_alert AS
SELECT
m.id,
m.name,
m.spec,
i.current_quantity,
m.min_stock,
DATEDIFF(m.expiry_date, CURDATE()) AS days_to_expire
FROM
medicine m
JOIN
inventory i ON m.id = i.medicine_id
WHERE
i.current_quantity < m.min_stock
OR DATEDIFF(m.expiry_date, CURDATE()) < 30;
- 出入库审计:
- 每次操作记录操作人、时间、前后数量
- 支持按药品/时间段/操作人多维查询
- 异常变动自动标记待审核
5. 论文写作要点与答辩技巧
5.1 技术章节的写作框架
毕业论文的技术章节切忌变成代码罗列,建议采用以下结构:
-
架构设计部分:
- 绘制清晰的架构图(建议使用PlantUML)
- 说明技术选型的对比过程
- 突出解决的特殊问题
-
核心算法部分:
- 医生排班的贪心算法实现
python复制def schedule_doctors(requests, shifts): sorted_requests = sorted(requests, key=lambda x: -x['priority']) result = [] for req in sorted_requests: available = [s for s in shifts if s['date'] == req['date']] if available: result.append((req['doctor'], available[0])) shifts.remove(available[0]) return result- 药品相似度计算的余弦相似度应用
-
性能优化部分:
- 预约查询的SQL优化(添加复合索引)
- 前端懒加载策略
- 缓存命中率统计
5.2 答辩常见问题与应对策略
根据往届答辩记录,评委最常问的三大类问题:
-
技术深度问题:
- "你们的系统如何处理高并发预约?"
- 回答要点:先说明压力测试结果(如JMeter测试数据),再解释锁机制和队列处理
-
业务逻辑问题:
- "宠物主人忘记带宠物就诊怎么处理?"
- 回答要点:演示系统中的"预约异常处理"流程,包括标记、备注和重新预约功能
-
创新点质疑:
- "这个系统和市面上已有产品有什么区别?"
- 回答策略:准备对比表格,重点突出针对中小型医院的成本优化方案
建议准备一个"应急演示包":包含主要功能的录屏、关键接口的Postman测试集合、数据库的备份文件。当现场演示出现意外时,可以快速切换至备用方案。
