
在家庭生活中,“药品安全存储”与“便捷取用”的平衡、“过期预警”与“合理用药”的协同始终是家庭健康管理的痛点。传统家庭药品管理常面临“过期遗漏”“存放散乱”“用药混淆”等问题。所以我打算用飞算JavaAI针对家庭场景特性,构建了从药品收纳到健康提醒的轻量级管理系统,实现药品全生命周期可视化管理,过期预警准确率达100%,为家庭健康保驾护航。本文聚焦家庭药品管理系统的技术实现,解析如何通过技术简化家庭药品管理流程。

家庭药品管理系统需实现“药品录入、状态监测、智能提醒、用药指导”的核心功能。飞算JavaAI通过轻量化设计,打造适配家庭场景的便捷管理工具。

传统家庭药品常因“名称不清、分类混乱”导致误用风险。该模块通过“智能识别 + 分类存储 + 精准查询”,实现药品信息的规范化管理:
@Service
@Slf4j
public class MedicineInfoService {
@Autowired
private MedicineRepository medicineRepo; // 药品数据访问
@Autowired
private RedisTemplate<String, Object> redisTemplate; // 缓存优化
@Autowired
private ImageRecognitionService imageService; // 飞算AI图像识别
@Autowired
private MedicineDictionaryService dictService; // 药品字典服务
// 缓存Key设计(按家庭隔离,提升访问效率)
private static final String FAMILY_MEDICINE_KEY = "medicine:family:"; // 家庭药品列表(7天有效期)
private static final String MEDICINE_CATEGORY_KEY = "medicine:category:"; // 分类药品缓存
private static final String MEDICINE_DETAIL_KEY = "medicine:detail:"; // 药品详情缓存
/**
* 家庭药品库初始化:预热缓存,加速后续访问
*/
public void initFamilyMedicineLibrary(Long familyId) {
// 加载家庭已有药品
List<Medicine> medicines = medicineRepo.findByFamilyId(familyId);
if (medicines.isEmpty()) {
log.info("家庭[{}]药品库为空,初始化完成", familyId);
return;
}
// 缓存全量药品列表(减少数据库查询)
String cacheKey = FAMILY_MEDICINE_KEY + familyId;
redisTemplate.opsForValue().set(cacheKey, medicines, 7, TimeUnit.DAYS);
// 按分类缓存(如“感冒药”“慢性病药”),支持快速筛选
Map<String, List<Medicine>> categoryMap = medicines.stream()
.collect(Collectors.groupingBy(Medicine::getCategory));
categoryMap.forEach((category, meds) -> {
redisTemplate.opsForValue().set(
MEDICINE_CATEGORY_KEY + familyId + ":" + category,
meds, 7, TimeUnit.DAYS);
});
log.info("家庭[{}]药品库初始化完成,共{}种药品", familyId, medicines.size());
}
/**
* 药品快速录入:支持扫码/拍照识别,减少手动输入
*/
public MedicineResult addMedicine(MedicineAddRequest request) {
// 基础参数校验
if (request.getFamilyId() == null) {
return MedicineResult.fail("家庭ID不能为空");
}
Medicine medicine = new Medicine();
medicine.setMedicineId(generateMedicineId(request.getFamilyId())); // 唯一标识
medicine.setFamilyId(request.getFamilyId());
medicine.setAddTime(LocalDateTime.now());
medicine.setStatus(MedicineStatus.STORED); // 初始状态:存储中
// 智能识别优先:条码/图片自动填充信息
if (StringUtils.isNotBlank(request.getBarcode())) {
// 条码识别:对接药品数据库获取标准信息
MedicineInfo recognizedInfo = dictService.getMedicineByBarcode(request.getBarcode());
if (recognizedInfo != null) {
fillMedicineFromDict(medicine, recognizedInfo); // 自动填充名称、有效期等
}
} else if (request.getImageData() != null) {
// 拍照识别:OCR提取药品名称、生产日期等文本
MedicineOcrResult ocrResult = imageService.recognizeMedicineImage(request.getImageData());
if (ocrResult.isSuccess()) {
fillMedicineFromOcr(medicine, ocrResult); // 填充识别结果
}
}
// 用户输入补充:覆盖识别结果,支持个性化信息
if (StringUtils.isNotBlank(request.getName())) {
medicine.setName(request.getName()); // 优先用户输入的名称
}
if (request.getProductionDate() != null) {
medicine.setProductionDate(request.getProductionDate());
}
if (request.getExpiryDate() != null) {
medicine.setExpiryDate(request.getExpiryDate()); // 有效期为必填项
}
medicine.setStorageLocation(request.getStorageLocation()); // 存储位置(如“客厅药箱”“冰箱”)
medicine.setDosage(request.getDosage()); // 用法用量
medicine.setNote(request.getNote()); // 自定义备注(如“儿童减半”)
// 必要信息校验(防止关键信息缺失)
if (StringUtils.isBlank(medicine.getName())) {
return MedicineResult.fail("药品名称不能为空");
}
if (medicine.getExpiryDate() == null) {
return MedicineResult.fail("请填写药品有效期");
}
// 保存并更新缓存
medicineRepo.save(medicine);
updateMedicineCache(medicine); // 实时更新缓存,确保数据最新
log.info("家庭[{}]新增药品:{}", request.getFamilyId(), medicine.getName());
return MedicineResult.success(medicine);
}
/**
* 药品分类查询:支持多条件筛选,快速定位所需药品
*/
public MedicineQueryResult queryFamilyMedicines(MedicineQueryRequest request) {
Long familyId = request.getFamilyId();
String cacheKey = FAMILY_MEDICINE_KEY + familyId;
// 缓存优先查询
List<Medicine> medicines = (List<Medicine>) redisTemplate.opsForValue().get(cacheKey);
if (medicines == null) {
medicines = medicineRepo.findByFamilyId(familyId);
redisTemplate.opsForValue().set(cacheKey, medicines, 7, TimeUnit.DAYS);
}
// 多条件筛选(状态、分类、位置等)
List<Medicine> filtered = filterMedicines(medicines, request);
// 统计关键指标(过期/即将过期数量)
Map<String, Long> categoryStats = filtered.stream()
.collect(Collectors.groupingBy(Medicine::getCategory, Collectors.counting()));
MedicineQueryResult result = new MedicineQueryResult();
result.setFamilyId(familyId);
result.setTotalCount(filtered.size());
result.setCategoryStats(categoryStats);
result.setMedicines(filtered);
result.setExpiringCount((int) filtered.stream()
.filter(this::isExpiringSoon) // 30天内过期
.count());
result.setExpiredCount((int) filtered.stream()
.filter(this::isExpired) // 已过期
.count());
return result;
}
// 辅助方法:判断药品状态
private boolean isExpiringSoon(Medicine medicine) {
if (medicine.getExpiryDate() == null) return false;
LocalDate today = LocalDate.now();
return !medicine.getExpiryDate().isBefore(today) &&
medicine.getExpiryDate().isBefore(today.plusDays(30));
}
private boolean isExpired(Medicine medicine) {
return medicine.getExpiryDate() != null &&
medicine.getExpiryDate().isBefore(LocalDate.now());
}
}技术亮点:
家庭药品管理的核心风险在于“过期不知、漏用忘吃”。该模块通过定时监测与多场景提醒,实现药品状态的动态管理:
@Service
public class MedicineReminderService {
@Autowired
private MedicineRepository medicineRepo;
@Autowired
private ReminderRepository reminderRepo;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private NotificationService notificationService; // 通知服务(APP推送/短信)
@Autowired
private AsyncService asyncService; // 异步任务
// 缓存与消息设计
private static final String REMINDER_KEY = "medicine:reminder:"; // 提醒缓存(7天)
private static final String EXPIRY_ALERT_KEY = "medicine:expiry:"; // 过期预警缓存
private static final String REMINDER_EVENT_TOPIC = "medicine:reminder:event"; // 提醒事件主题
/**
* 每日药品状态巡检:自动发现过期/即将过期药品
*/
@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行,减少打扰
public void checkMedicineStatuses() {
log.info("开始每日药品状态检查");
// 获取所有有药品的活跃家庭
List<Long> activeFamilyIds = medicineRepo.findActiveFamilyIds();
if (activeFamilyIds.isEmpty()) {
log.info("无活跃家庭,药品检查结束");
return;
}
// 逐个家庭检查
activeFamilyIds.forEach(familyId -> {
try {
checkFamilyMedicineStatus(familyId);
} catch (Exception e) {
log.error("检查家庭[{}]药品状态失败", familyId, e);
}
});
log.info("每日药品状态检查完成");
}
/**
* 家庭药品状态检查:分类处理过期/低库存问题
*/
private void checkFamilyMedicineStatus(Long familyId) {
List<Medicine> medicines = medicineRepo.findByFamilyId(familyId);
if (medicines.isEmpty()) return;
// 1. 识别已过期药品(需立即处理)
List<Medicine> expiredMedicines = medicines.stream()
.filter(med -> med.getExpiryDate() != null &&
med.getExpiryDate().isBefore(LocalDate.now()) &&
med.getStatus() != MedicineStatus.DISCARDED) // 排除已丢弃药品
.collect(Collectors.toList());
// 2. 识别即将过期药品(30天内,需优先使用)
List<Medicine> expiringMedicines = medicines.stream()
.filter(med -> med.getExpiryDate() != null &&
!med.getExpiryDate().isBefore(LocalDate.now()) &&
med.getExpiryDate().isBefore(LocalDate.now().plusDays(30)) &&
med.getStatus() == MedicineStatus.STORED)
.collect(Collectors.toList());
// 3. 识别低库存药品(需补货)
List<Medicine> lowStockMedicines = medicines.stream()
.filter(med -> med.getRemainingCount() != null &&
med.getRemainingCount() <= med.getLowStockThreshold() && // 低于阈值(如剩余2次用量)
med.getStatus() == MedicineStatus.STORED)
.collect(Collectors.toList());
// 生成对应提醒
if (!expiredMedicines.isEmpty()) {
createExpiryReminders(familyId, expiredMedicines); // 过期提醒:“请丢弃XX药品”
}
if (!expiringMedicines.isEmpty()) {
createExpiringReminders(familyId, expiringMedicines); // 临期提醒:“XX药品即将过期,请优先使用”
}
if (!lowStockMedicines.isEmpty()) {
createReplenishReminders(familyId, lowStockMedicines); // 补货提醒:“XX药品不足,请购买”
}
}
/**
* 用药提醒创建:支持单次/重复提醒,适配慢性病规律用药场景
*/
public ReminderResult createDosageReminder(ReminderCreateRequest request) {
// 参数校验
if (request.getFamilyId() == null || request.getMedicineId() == null ||
request.getReminderTime() == null || request.getDosage() == null) {
return ReminderResult.fail("缺少必要参数(药品ID、提醒时间、用量)");
}
// 验证药品存在性
Medicine medicine = medicineRepo.findByFamilyIdAndMedicineId(
request.getFamilyId(), request.getMedicineId());
if (medicine == null) {
return ReminderResult.fail("药品不存在");
}
// 创建提醒记录
MedicineReminder reminder = new MedicineReminder();
reminder.setReminderId(generateReminderId(request.getFamilyId()));
reminder.setFamilyId(request.getFamilyId());
reminder.setMedicineId(request.getMedicineId());
reminder.setMedicineName(medicine.getName());
reminder.setReminderType(ReminderType.DOSAGE);
reminder.setReminderTime(request.getReminderTime()); // 具体时间(如“每天8:00”)
reminder.setDosage(request.getDosage()); // 用量(如“1片/次”)
reminder.setRepeatType(request.getRepeatType() != null ?
request.getRepeatType() : RepeatType.NONE); // 重复类型(每天/每周)
reminder.setStatus(ReminderStatus.ACTIVE);
reminder.setNote(request.getNote()); // 备注(如“饭后服用”)
// 保存并更新缓存
reminderRepo.save(reminder);
updateReminderCache(reminder);
log.info("家庭[{}]创建用药提醒:{},时间:{}",
request.getFamilyId(), medicine.getName(), request.getReminderTime());
return ReminderResult.success(reminder);
}
/**
* 到期提醒处理:精准推送,避免漏服
*/
public void processDueReminders() {
LocalDateTime now = LocalDateTime.now();
LocalDateTime endTime = now.plusMinutes(30); // 处理未来30分钟内的提醒
// 查询待处理提醒
List<MedicineReminder> dueReminders = reminderRepo.findDueReminders(
now, endTime, ReminderStatus.ACTIVE);
if (dueReminders.isEmpty()) return;
// 批量发送通知
dueReminders.forEach(reminder -> {
try {
// 多渠道通知(APP推送+短信备份)
notificationService.sendMedicineReminder(reminder);
// 更新状态:单次提醒标记完成,重复提醒更新下次时间
if (reminder.getRepeatType() == RepeatType.NONE) {
reminder.setStatus(ReminderStatus.COMPLETED);
} else {
updateNextReminderTime(reminder); // 按重复规则计算下次时间
}
reminderRepo.save(reminder);
updateReminderCache(reminder);
} catch (Exception e) {
log.error("处理提醒[{}]失败", reminder.getReminderId(), e);
}
});
}
}技术亮点:
家庭用药安全的核心痛点是“用法不清、禁忌不明”。该模块通过说明书查询、禁忌检查与用药记录,降低用药风险:
@Service
public class MedicineSafetyService {
@Autowired
private MedicineRepository medicineRepo;
@Autowired
private DosageRecordRepository recordRepo;
@Autowired
private MedicineDictionaryService dictService; // 对接权威药品数据库
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 缓存设计
private static final String MEDICINE_SAFETY_KEY = "medicine:safety:"; // 安全信息缓存(30天)
private static final String DOSAGE_RECORD_KEY = "medicine:dosage:"; // 用药记录缓存
/**
* 药品安全信息查询:说明书、禁忌一站式获取
*/
public MedicineSafetyResult getMedicineSafetyInfo(Long familyId, String medicineId) {
// 获取药品基础信息
Medicine medicine = medicineRepo.findByFamilyIdAndMedicineId(familyId, medicineId);
if (medicine == null) {
return MedicineSafetyResult.fail("药品不存在");
}
String cacheKey = MEDICINE_SAFETY_KEY + medicineId;
// 缓存查询安全信息(说明书、禁忌、存储要求等)
MedicineSafetyInfo cachedSafety = (MedicineSafetyInfo) redisTemplate.opsForValue().get(cacheKey);
if (cachedSafety != null) {
return MedicineSafetyResult.success(cachedSafety);
}
// 从权威药品字典获取信息
MedicineSafetyInfo safetyInfo = dictService.getMedicineSafetyInfo(
medicine.getName(), medicine.getProductionEnterprise());
// 补充家庭自定义信息(如存储要求、过敏备注)
if (safetyInfo == null) safetyInfo = new MedicineSafetyInfo();
safetyInfo.setMedicineId(medicineId);
safetyInfo.setMedicineName(medicine.getName());
safetyInfo.setStorageRequirements(medicine.getStorageRequirements()); // 如“避光冷藏”
safetyInfo.setCustomNote(medicine.getNote()); // 家庭过敏提示(如“儿童禁用”)
// 缓存安全信息
redisTemplate.opsForValue().set(cacheKey, safetyInfo, 30, TimeUnit.DAYS);
return MedicineSafetyResult.success(safetyInfo);
}
/**
* 用药记录:追踪历史,辅助健康管理
*/
public DosageRecordResult recordDosage(DosageRecordRequest request) {
// 参数校验
if (request.getFamilyId() == null || request.getMedicineId() == null ||
request.getDosageTime() == null) {
return DosageRecordResult.fail("缺少必要参数(用药时间、药品ID)");
}
// 验证药品存在性
Medicine medicine = medicineRepo.findByFamilyIdAndMedicineId(
request.getFamilyId(), request.getMedicineId());
if (medicine == null) {
return DosageRecordResult.fail("药品不存在");
}
// 创建用药记录
DosageRecord record = new DosageRecord();
record.setRecordId(generateRecordId(request.getFamilyId()));
record.setFamilyId(request.getFamilyId());
record.setMedicineId(request.getMedicineId());
record.setMedicineName(medicine.getName());
record.setDosageTime(request.getDosageTime()); // 实际用药时间
record.setDosageAmount(request.getDosageAmount()); // 实际用量
record.setRecipient(request.getRecipient()); // 用药人(如“爸爸”“孩子”)
record.setNote(request.getNote()); // 备注(如“无不适反应”)
// 保存记录并更新药品剩余数量
recordRepo.save(record);
if (medicine.getRemainingCount() != null && medicine.getRemainingCount() > 0) {
medicine.setRemainingCount(medicine.getRemainingCount() - 1); // 用量减1
medicineRepo.save(medicine);
updateMedicineCache(medicine);
}
// 缓存用药记录
String cacheKey = DOSAGE_RECORD_KEY + request.getFamilyId();
List<DosageRecord> records = (List<DosageRecord>) redisTemplate.opsForValue().get(cacheKey);
if (records == null) records = new ArrayList<>();
records.add(record);
redisTemplate.opsForValue().set(cacheKey, records, 30, TimeUnit.DAYS);
log.info("家庭[{}]记录用药:{},用量:{}",
request.getFamilyId(), medicine.getName(), request.getDosageAmount());
return DosageRecordResult.success(record);
}
/**
* 药品禁忌检查:避免危险联用
*/
public MedicineWarningResult checkMedicineWarning(Long familyId, List<String> medicineIds) {
MedicineWarningResult result = new MedicineWarningResult();
result.setFamilyId(familyId);
result.setCheckTime(LocalDateTime.now());
result.setWarnings(new ArrayList<>());
if (medicineIds == null || medicineIds.size() < 2) {
result.setSafe(true); // 单种药品无需检查联用禁忌
return result;
}
// 获取药品信息
List<Medicine> medicines = new ArrayList<>();
for (String id : medicineIds) {
Medicine med = medicineRepo.findByFamilyIdAndMedicineId(familyId, id);
if (med != null) medicines.add(med);
}
// 检查药品间相互作用(基于权威数据库)
List<MedicineWarning> warnings = dictService.checkMedicineInteractions(medicines);
result.setWarnings(warnings);
result.setSafe(warnings.isEmpty());
return result;
}
}技术亮点:
系统采用轻量化架构设计,适配家庭场景“低门槛、高隐私、易维护”的需求。
@Configuration
public class MedicineSystemConfig {
/**
* 缓存配置:轻量级Redis适配家庭场景
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// JSON序列化:支持复杂对象缓存(药品信息、提醒记录)
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
/**
* 定时任务配置:低资源占用设计
*/
@Bean
public ScheduledExecutorService medicineScheduler() {
// 单线程定时任务池,满足家庭场景需求(每日检查+提醒处理)
return Executors.newSingleThreadScheduledExecutor(runnable -> {
Thread thread = new Thread(runnable, "medicine-scheduler");
thread.setDaemon(true); // 守护线程,不影响设备休眠
return thread;
});
}
/**
* 药品图像识别配置:家庭场景优化
*/
@Bean
public ImageRecognitionService imageRecognitionService() {
OcrConfig config = new OcrConfig();
config.setEnableLocalModel(true); // 本地轻量模型,无网络可用
config.setMaxImageSize(5 * 1024 * 1024); // 限制图片大小,避免资源占用过高
config.setRecognizeTimeout(3000); // 3秒超时,提升用户体验
return new ImageRecognitionService(config);
}
}系统采用极致轻量化部署,兼顾易用性与隐私安全:
飞算 JavaAI 家庭药品管理系统通过轻量化技术设计,将专业医疗管理能力下沉到家庭场景。从“扫码即录入”的便捷体验,到“过期必提醒”的安全保障,再到“禁忌早知道”的风险防控,系统用技术解决了传统家庭药品管理的痛点。
这套系统的核心价值,在于将“专业、复杂”的药品管理流程转化为“简单、可靠”的家庭工具——让老人不再因看不清说明书而误用,让家长不再为儿童药品过期而担忧,让慢性病患者不再漏服药物。这种“润物细无声”的技术赋能,正在成为现代家庭健康管理的基础配置,用科技筑牢家庭健康的第一道防线。