1. 项目背景与核心价值
养宠人群的快速增长催生了宠物服务行业的数字化转型需求。去年我在帮朋友改造一家线下宠物店时,发现他们还在用纸质本子记录会员信息和寄养情况,经常出现预约冲突和账目混乱的问题。这个"云宠之家"管理系统正是为了解决这类痛点而设计的全栈解决方案。
系统采用SpringBoot+Vue的前后端分离架构,主要实现三大核心模块:
- 宠物档案的电子化管理和健康追踪
- 寄养服务的在线预约与智能排期
- 会员积分商城的运营体系
相比市面上的通用CRM系统,我们针对宠物行业特别优化了:
- 宠物特征字段(品种、疫苗记录、过敏史等)
- 可视化寄养舱位管理
- 集成宠物健康监测设备API
2. 技术架构设计
2.1 后端技术栈选型
选择SpringBoot 2.7作为基础框架主要考虑:
- 快速构建RESTful API
- 与Spring生态的无缝集成(特别是Spring Security)
- 内嵌Tomcat简化部署
数据库采用MySQL 8.0+,关键设计点:
sql复制CREATE TABLE pet_profile (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
pet_name VARCHAR(20) NOT NULL,
pet_type ENUM('DOG','CAT','OTHER') NOT NULL,
birth_date DATE,
chip_number VARCHAR(50) UNIQUE,
owner_id BIGINT NOT NULL,
CONSTRAINT fk_owner FOREIGN KEY (owner_id) REFERENCES member(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 前端技术方案
Vue 3组合式API带来两大优势:
- 更灵活的逻辑复用(如预约日历组件)
- 更好的TypeScript支持
典型组件示例:
vue复制<template>
<div class="cage-status">
<div v-for="cage in cages"
:class="['cage', { occupied: cage.status === 'OCCUPIED' }]"
@click="handleSelect(cage.id)">
{{ cage.number }}
</div>
</div>
</template>
3. 核心业务实现
3.1 智能寄养排期算法
冲突检测的核心逻辑:
java复制public boolean checkScheduleConflict(LocalDate startDate, LocalDate endDate, Long cageId) {
return reservationRepository.existsByCageIdAndStatusNotAndDateBetween(
cageId,
ReservationStatus.CANCELLED,
startDate,
endDate
);
}
3.2 健康记录提醒服务
使用Spring Scheduled实现定时提醒:
java复制@Scheduled(cron = "0 0 9 * * ?") // 每天上午9点执行
public void sendVaccinationReminders() {
List<PetVaccination> upcoming = vaccinationRepository
.findByNextDateBetween(LocalDate.now(), LocalDate.now().plusDays(7));
upcoming.forEach(vaccination -> {
String message = String.format("%s的%s疫苗即将到期",
vaccination.getPet().getName(),
vaccination.getVaccineType());
smsService.send(vaccination.getPet().getOwner().getPhone(), message);
});
}
4. 系统安全设计
4.1 基于RBAC的权限控制
权限表结构设计:
sql复制CREATE TABLE sys_role (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
role_name VARCHAR(50) NOT NULL UNIQUE,
role_desc VARCHAR(100)
);
CREATE TABLE sys_user_role (
user_id BIGINT NOT NULL,
role_id BIGINT NOT NULL,
PRIMARY KEY (user_id, role_id)
);
4.2 JWT令牌增强方案
自定义Claims包含:
java复制public class TokenClaims {
private Long userId;
private String username;
private List<String> roles;
// 添加宠物店ID字段用于多门店系统
private Long storeId;
}
5. 部署与性能优化
5.1 Docker化部署方案
docker-compose.yml关键配置:
yaml复制services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
5.2 缓存策略设计
使用Redis缓存热点数据:
java复制@Cacheable(value = "petProfile", key = "#petId")
public PetProfile getPetProfile(Long petId) {
return petProfileRepository.findById(petId)
.orElseThrow(() -> new ResourceNotFoundException("Pet not found"));
}
6. 踩坑实录与解决方案
6.1 日期时间处理陷阱
发现的问题:
- MySQL的DATETIME类型时区问题
- 前端传参的日期格式不统一
最终解决方案:
- 统一使用ISO8601格式传输
- 数据库存储UTC时间
- 前端按用户时区显示
6.2 并发预约冲突
典型场景:
多个用户同时预约同一笼位
采用方案:
java复制@Transactional
public Reservation createReservation(ReservationDTO dto) {
// 添加SELECT FOR UPDATE锁
Cage cage = cageRepository.findLockedById(dto.getCageId())
.orElseThrow(...);
if (checkScheduleConflict(dto.getStartDate(), dto.getEndDate(), cage.getId())) {
throw new BusinessException("该时段已被预约");
}
// 创建预约记录...
}
7. 扩展性设计
7.1 多门店支持方案
通过ThreadLocal存储当前门店上下文:
java复制public class StoreContextHolder {
private static final ThreadLocal<Long> context = new ThreadLocal<>();
public static void setStoreId(Long storeId) {
context.set(storeId);
}
public static Long getStoreId() {
return context.get();
}
}
7.2 开放API设计
使用Swagger UI构建文档:
java复制@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info().title("云宠之家API")
.version("1.0")
.contact(new Contact().name("API支持")));
}
关键提示:宠物行业系统要特别注意敏感字段加密,特别是宠物芯片号、主人身份证号等信息需要做脱敏处理
在实际部署中发现,宠物照片存储是个容易被忽视的性能瓶颈。我们最终采用阿里云OSS分片上传方案,将图片访问响应时间从原来的800ms降低到200ms以内。具体实现时要注意设置合理的过期时间和CDN缓存策略。