1. 项目概述与背景
宠物主题咖啡厅近年来在国内各大城市迅速兴起,成为年轻人休闲社交的新宠。这类场所不仅提供咖啡饮品,更重要的是让顾客能够与各类萌宠互动,享受"撸猫撸狗"的治愈时光。然而,随着客流量的增加,传统手工记录的管理方式暴露出诸多问题:
- 预约混乱:顾客到店后经常需要长时间等待,宠物互动时段安排不合理
- 库存管理困难:咖啡原料、宠物零食等库存情况无法实时掌握
- 会员体系割裂:消费记录、积分、优惠等信息分散在不同系统中
- 数据统计滞后:无法快速获取经营数据分析,影响决策效率
这套基于SpringBoot的宠物咖啡店管理系统正是为解决这些痛点而设计。系统将门店的核心业务流程数字化,实现了"前台下单+后台管理"的一体化运营模式。顾客可以通过手机端完成预约、点单、支付等操作,而管理员则能在后台实时监控各项经营数据。
2. 系统架构设计
2.1 技术选型与考量
系统采用当前主流的Java技术栈进行开发,主要基于以下考虑:
后端技术:
- SpringBoot 2.7.x:简化配置,快速搭建项目框架
- MyBatis-Plus 3.5.x:增强ORM功能,减少基础CRUD代码量
- Redis 6.x:缓存热点数据,提升系统响应速度
前端技术:
- Vue.js 3.x:组件化开发,良好的用户体验
- Element Plus:丰富的UI组件库,加速前端开发
- Axios:处理HTTP请求,与后端交互
数据库:
- MySQL 8.0:关系型数据库,存储业务数据
- 选择理由:开源免费、性能稳定、社区支持完善
开发工具:
- IntelliJ IDEA:智能Java开发IDE
- Navicat:数据库管理工具
- Git:版本控制
提示:技术选型时特别考虑了毕业设计的实际情况,所有组件均为开源免费,避免版权问题。
2.2 系统架构图
系统采用经典的三层架构设计:
code复制表示层(Web前端)
↓
业务逻辑层(SpringBoot)
↓
数据访问层(MyBatis+MySQL)
这种分层架构的优势在于:
- 职责分离,各层专注自身功能
- 易于维护和扩展
- 适合团队协作开发
2.3 数据库设计要点
数据库设计遵循第三范式,主要包含以下核心表:
-
用户表(user):存储会员信息
- 字段:用户ID、账号、密码、姓名、性别、手机、头像、余额、会员等级等
-
宠物表(pet):记录店内宠物信息
- 字段:宠物ID、名称、种类、性别、年龄、性情、状态、图片等
-
商品表(product):管理咖啡、食品等商品
- 字段:商品ID、名称、分类、价格、库存、图片等
-
门票表(ticket):宠物互动套餐
- 字段:套餐ID、名称、时长、价格、说明等
-
订单表(order):记录交易信息
- 字段:订单ID、用户ID、总金额、状态、创建时间等
实体关系设计时特别注意了:
- 建立适当的索引提升查询效率
- 设置外键约束保证数据完整性
- 合理的数据类型选择节省存储空间
3. 核心功能实现
3.1 用户模块
3.1.1 注册登录流程
用户注册采用手机号+验证码的方式,流程如下:
- 前端输入手机号,请求发送验证码
- 后端调用短信接口发送6位随机码
- 用户输入验证码后提交注册
- 系统校验验证码有效性
- 创建用户账号,初始化为普通会员
关键代码实现:
java复制// 发送验证码
public Result sendCode(String phone) {
// 生成6位随机码
String code = RandomUtil.randomNumbers(6);
// 存入Redis,设置5分钟过期
redisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code, 5, TimeUnit.MINUTES);
// 调用短信服务发送(模拟)
log.info("发送短信验证码:{},手机号:{}", code, phone);
return Result.ok();
}
// 注册登录
public Result login(LoginFormDTO loginForm) {
String phone = loginForm.getPhone();
// 校验验证码
String cacheCode = redisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);
if (cacheCode == null || !cacheCode.equals(loginForm.getCode())) {
return Result.fail("验证码错误");
}
// 查询用户是否存在
User user = query().eq("phone", phone).one();
if (user == null) {
// 新用户自动注册
user = createUserWithPhone(phone);
}
// 生成token返回
String token = UUID.randomUUID().toString(true);
UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
// 用户信息存入Redis
redisTemplate.opsForValue().set(LOGIN_USER_KEY + token, userDTO, 30, TimeUnit.MINUTES);
return Result.ok(token);
}
3.1.2 会员体系设计
系统设计了多级会员体系,不同等级享受不同折扣:
- 普通会员:无折扣
- 白银会员:9折,累计消费满500元升级
- 黄金会员:8折,累计消费满2000元升级
- 钻石会员:7折,累计消费满5000元升级
会员升级采用定时任务每日检查:
java复制@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
public void checkMemberLevel() {
// 查询所有需要升级的用户
List<User> users = userMapper.selectList(new QueryWrapper<User>()
.select("id, total_amount")
.orderByAsc("id"));
users.forEach(user -> {
BigDecimal amount = user.getTotalAmount();
Integer newLevel = 0; // 普通
if (amount.compareTo(new BigDecimal("5000")) >= 0) {
newLevel = 3; // 钻石
} else if (amount.compareTo(new BigDecimal("2000")) >= 0) {
newLevel = 2; // 黄金
} else if (amount.compareTo(new BigDecimal("500")) >= 0) {
newLevel = 1; // 白银
}
// 更新等级
if (!newLevel.equals(user.getLevel())) {
userMapper.updateLevel(user.getId(), newLevel);
}
});
}
3.2 宠物管理模块
3.2.1 宠物信息管理
管理员可以添加、编辑店内宠物信息,主要字段包括:
- 基础信息:名称、种类、性别、年龄
- 特征描述:性情、爱好、健康状况
- 业务信息:互动价格、当前状态(可预约/休息中)
- 多媒体:展示图片、视频
后端接口设计:
java复制@RestController
@RequestMapping("/pet")
public class PetController {
@Autowired
private PetService petService;
// 分页查询宠物列表
@GetMapping("/list")
public Result queryPetList(
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "page", defaultValue = "1") Integer page,
@RequestParam(value = "size", defaultValue = "10") Integer size) {
return petService.queryPetList(name, page, size);
}
// 添加新宠物
@PostMapping
public Result addPet(@RequestBody Pet pet) {
return petService.addPet(pet);
}
// 更新宠物信息
@PutMapping
public Result updatePet(@RequestBody Pet pet) {
return petService.updatePet(pet);
}
// 删除宠物
@DeleteMapping("/{id}")
public Result deletePet(@PathVariable Long id) {
return petService.deletePet(id);
}
}
3.2.2 宠物状态管理
系统实时跟踪每只宠物的状态,包括:
- 可互动:宠物处于可预约状态
- 互动中:正在与顾客互动
- 休息中:需要休息,暂不接客
- 医疗中:生病或体检,不可互动
状态变更通过WebSocket实时推送到前端:
java复制@GetMapping("/status/{petId}")
public Result getPetStatus(@PathVariable Long petId) {
String status = redisTemplate.opsForValue().get(PET_STATUS_KEY + petId);
if (status == null) {
status = "可互动"; // 默认状态
redisTemplate.opsForValue().set(PET_STATUS_KEY + petId, status);
}
return Result.ok(status);
}
@PutMapping("/status")
public Result updatePetStatus(@RequestBody PetStatusDTO dto) {
redisTemplate.opsForValue().set(PET_STATUS_KEY + dto.getPetId(), dto.getStatus());
// 通知所有客户端状态变更
simpMessagingTemplate.convertAndSend("/topic/petStatus", dto);
return Result.ok();
}
3.3 商品与订单模块
3.3.1 商品库存管理
系统实现了完整的进销存管理:
- 商品入库:记录采购信息,增加库存
- 库存预警:设置最低库存阈值,自动提醒补货
- 销售出库:订单生成时自动扣减库存
库存变更采用乐观锁防止超卖:
java复制public Result deductStock(Long productId, Integer num) {
// 使用乐观锁更新库存
int updated = productMapper.deductStock(productId, num);
if (updated == 0) {
// 库存不足
return Result.fail("库存不足");
}
// 检查是否需要预警
Product product = productMapper.selectById(productId);
if (product.getStock() <= product.getWarningStock()) {
// 发送预警通知
warningService.sendStockWarning(product);
}
return Result.ok();
}
3.3.2 订单流程设计
订单状态机设计:
code复制待支付 → 已支付 → 已完成
↓
已取消
↓
已退款
订单超时自动取消实现:
java复制@Transactional
public void cancelOrder(Long orderId) {
// 查询订单
Order order = orderMapper.selectById(orderId);
if (order == null || !"待支付".equals(order.getStatus())) {
return;
}
// 更新状态
order.setStatus("已取消");
order.setCancelTime(LocalDateTime.now());
orderMapper.updateById(order);
// 释放库存
order.getItems().forEach(item -> {
productMapper.addStock(item.getProductId(), item.getNum());
});
// 记录日志
logService.addLog(order.getUserId(), "订单自动取消", "订单ID:" + orderId);
}
3.4 门票预约模块
3.4.1 时段预约设计
系统将营业时间划分为多个时段(如每30分钟一个时段),每个时段可预约人数有限制。预约流程:
- 用户选择日期和时段
- 系统显示可预约宠物列表
- 用户选择宠物和套餐
- 生成预约订单
时段管理关键代码:
java复制public List<TimeSlot> getAvailableSlots(LocalDate date) {
// 获取当天的所有时段
List<TimeSlot> allSlots = timeSlotMapper.selectByDate(date);
// 查询已预约数量
Map<Long, Integer> reservedMap = reservationMapper.countBySlots(date);
// 计算剩余可预约数
return allSlots.stream()
.peek(slot -> {
int reserved = reservedMap.getOrDefault(slot.getId(), 0);
slot.setRemain(slot.getMaxPeople() - reserved);
})
.filter(slot -> slot.getRemain() > 0)
.collect(Collectors.toList());
}
3.4.2 动态定价策略
系统支持多种定价策略:
- 固定价格:基础定价
- 时段溢价:高峰时段加价
- 会员折扣:不同等级享受不同折扣
- 套餐优惠:组合购买更划算
价格计算服务:
java复制public BigDecimal calculatePrice(Long ticketId, Long userId, LocalDateTime time) {
// 获取基础价格
Ticket ticket = ticketMapper.selectById(ticketId);
BigDecimal price = ticket.getPrice();
// 时段溢价
int hour = time.getHour();
if (hour >= 10 && hour <= 12 || hour >= 18 && hour <= 20) {
price = price.multiply(new BigDecimal("1.2")); // 高峰时段+20%
}
// 会员折扣
User user = userMapper.selectById(userId);
switch (user.getLevel()) {
case 1: price = price.multiply(new BigDecimal("0.9")); break; // 白银9折
case 2: price = price.multiply(new BigDecimal("0.8")); break; // 黄金8折
case 3: price = price.multiply(new BigDecimal("0.7")); break; // 钻石7折
}
return price.setScale(2, RoundingMode.HALF_UP);
}
4. 系统特色与优化
4.1 实时数据看板
为店主设计的经营数据可视化看板,包含:
- 今日关键指标:营业额、客流量、热门商品
- 趋势图表:近30天销售趋势
- 宠物状态监控:当前可互动宠物数量
- 库存预警:需要补货的商品列表
使用ECharts实现动态图表:
javascript复制// 销售趋势图
function renderSalesChart(data) {
const chart = echarts.init(document.getElementById('sales-chart'));
const option = {
tooltip: { trigger: 'axis' },
legend: { data: ['营业额', '订单量'] },
xAxis: { type: 'category', data: data.dates },
yAxis: [{ type: 'value', name: '金额' }, { type: 'value', name: '订单数' }],
series: [
{ name: '营业额', type: 'line', data: data.amounts },
{ name: '订单量', type: 'bar', yAxisIndex: 1, data: data.counts }
]
};
chart.setOption(option);
}
4.2 智能推荐系统
基于用户行为数据分析,实现:
- 热门推荐:销量最高的宠物互动和商品
- 个性化推荐:根据用户历史偏好推荐
- 组合推荐:经常一起购买的商品组合
推荐算法核心逻辑:
java复制public List<RecommendItem> recommendForUser(Long userId) {
List<RecommendItem> items = new ArrayList<>();
// 1. 热门推荐
List<Product> hotProducts = productMapper.selectHotProducts(5);
items.addAll(hotProducts.stream()
.map(p -> new RecommendItem(p.getId(), "product", "热门商品"))
.collect(Collectors.toList()));
// 2. 基于用户历史的推荐
if (userId != null) {
List<Long> viewedPets = behaviorMapper.selectViewedPets(userId);
if (!viewedPets.isEmpty()) {
List<Pet> similarPets = petMapper.selectSimilarPets(viewedPets, 3);
items.addAll(similarPets.stream()
.map(p -> new RecommendItem(p.getId(), "pet", "猜你喜欢"))
.collect(Collectors.toList()));
}
}
// 3. 组合推荐
items.add(new RecommendItem(101L, "combo", "撸猫+咖啡套餐"));
return items.stream().distinct().limit(6).collect(Collectors.toList());
}
4.3 性能优化措施
-
缓存策略:
- Redis缓存热点数据:宠物信息、商品信息、用户信息
- 本地缓存配置信息:系统参数、价格策略
- 多级缓存策略减少数据库压力
-
数据库优化:
- 合理设计索引
- 读写分离
- 大表分库分表
-
接口优化:
- 批量接口减少网络请求
- 数据压缩传输
- 异步处理非核心流程
示例缓存配置:
java复制@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)) // 默认1小时过期
.disableCachingNullValues()
.serializeKeysWith(SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
// 特殊缓存配置
Map<String, RedisCacheConfiguration> cacheConfigs = new HashMap<>();
cacheConfigs.put("pet", config.entryTtl(Duration.ofMinutes(30))); // 宠物信息30分钟
cacheConfigs.put("product", config.entryTtl(Duration.ofHours(2))); // 商品信息2小时
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.withInitialCacheConfigurations(cacheConfigs)
.build();
}
}
5. 部署与运维
5.1 系统部署方案
推荐部署环境:
- 服务器:2核4G以上配置
- 操作系统:Linux CentOS 7+
- 中间件:Nginx + Tomcat
- 数据库:MySQL 8.0主从架构
部署步骤:
- 环境准备:安装JDK、MySQL、Redis、Nginx
- 数据库初始化:执行SQL脚本创建表结构
- 后端部署:
bash复制# 打包 mvn clean package -DskipTests # 上传jar包到服务器 scp target/pet-cafe.jar user@server:/app/ # 启动 nohup java -jar pet-cafe.jar --spring.profiles.active=prod > log.out 2>&1 & - 前端部署:
bash复制# 构建生产环境代码 npm run build # 上传到Nginx目录 scp -r dist/* user@server:/usr/share/nginx/html/ - Nginx配置:
nginx复制server { listen 80; server_name yourdomain.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://localhost:8080; proxy_set_header Host $host; } }
5.2 系统监控与维护
建议的监控指标:
- 系统健康检查:
- API响应时间
- 错误率
- JVM内存使用
- 业务指标监控:
- 订单创建量
- 库存预警数量
- 在线用户数
使用Spring Boot Actuator暴露监控端点:
properties复制# application-prod.properties
management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.metrics.export.prometheus.enabled=true
日志收集方案:
- ELK Stack(Elasticsearch + Logstash + Kibana)
- 按天滚动日志文件
- 关键业务操作记录详细日志
6. 常见问题与解决方案
6.1 开发环境问题
问题1:MySQL连接失败
- 现象:启动时报数据库连接异常
- 排查:
- 检查application.yml中的数据库配置
- 确认MySQL服务是否启动
- 检查网络连接和防火墙设置
- 解决:
yaml复制spring: datasource: url: jdbc:mysql://localhost:3306/pet_cafe?useSSL=false&serverTimezone=Asia/Shanghai username: root password: yourpassword
问题2:Redis超时
- 现象:偶尔出现Redis操作超时
- 排查:
- 检查Redis服务器负载
- 检查网络延迟
- 查看Redis配置中的timeout设置
- 解决:
java复制@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); template.setEnableTransactionSupport(true); // 增加连接超时设置 LettuceClientConfiguration config = LettuceClientConfiguration.builder() .commandTimeout(Duration.ofSeconds(3)) .build(); return template; } }
6.2 业务逻辑问题
问题3:库存超卖
- 现象:高并发下出现库存扣减为负数
- 原因:多个线程同时读取库存,都认为足够后同时扣减
- 解决方案:
- 使用数据库乐观锁
- Redis分布式锁
- 消息队列串行化处理
乐观锁实现示例:
sql复制UPDATE product SET stock = stock - #{num}
WHERE id = #{id} AND stock >= #{num}
问题4:重复预约
- 现象:同一用户同一时段重复预约
- 解决方案:
- 数据库唯一索引
- 分布式锁防止并发提交
- 前端按钮防重复点击
唯一索引方案:
sql复制ALTER TABLE reservation
ADD UNIQUE INDEX idx_user_time (user_id, slot_id, reservation_date);
6.3 性能优化问题
问题5:首页加载慢
- 现象:首页接口响应时间超过2秒
- 优化方案:
- 使用Redis缓存首页数据
- 静态资源CDN加速
- 接口数据分页加载
- 图片懒加载
缓存实现:
java复制@Cacheable(value = "home", key = "'data'")
public HomeVO getHomeData() {
HomeVO vo = new HomeVO();
vo.setPets(petMapper.selectRecommendPets());
vo.setProducts(productMapper.selectHotProducts());
vo.setNotices(noticeMapper.selectLatestNotices());
return vo;
}
问题6:大数据量查询慢
- 现象:历史订单查询越来越慢
- 解决方案:
- 添加合适索引
- 分库分表
- 使用Elasticsearch加速查询
- 限制查询时间范围
分表策略示例:
java复制// 按月分表
public String getOrderTableName(LocalDate date) {
return "order_" + date.getYear() + "_" + date.getMonthValue();
}
// 动态表名查询
public List<Order> queryOrders(Long userId, LocalDate start, LocalDate end) {
List<Order> result = new ArrayList<>();
while (!start.isAfter(end)) {
String table = getOrderTableName(start);
result.addAll(orderMapper.selectByUserAndDate(table, userId, start));
start = start.plusMonths(1);
}
return result;
}
7. 项目总结与扩展方向
7.1 项目成果总结
通过本系统的开发,实现了以下目标:
- 业务流程数字化:将宠物咖啡店的各项业务从线下搬到线上
- 运营效率提升:减少了人工操作错误,提高了服务响应速度
- 顾客体验优化:便捷的预约和支付流程,减少等待时间
- 数据驱动决策:通过经营数据分析,帮助店主优化运营策略
系统特色亮点:
- 一体化的宠物+咖啡店管理模式
- 精细化的会员等级体系
- 智能化的库存预警机制
- 可视化的经营数据看板
7.2 未来扩展方向
- 小程序/APP开发:提供更便捷的移动端体验
- 智能硬件对接:
- 宠物健康监测设备
- 智能门禁系统
- 自助点单终端
- AI技术应用:
- 宠物行为分析
- 智能客服
- 人脸识别会员系统
- 连锁店支持:多门店管理,数据互通
- 社交功能扩展:用户社区,宠物照片分享
技术演进路线:
mermaid复制graph LR
A[单店系统] --> B[多店连锁版]
B --> C[SaaS云平台]
C --> D[行业解决方案]
7.3 开发经验分享
在项目开发过程中积累的一些宝贵经验:
- 需求分析要透彻:前期与店主深入沟通,真正理解业务痛点
- 技术选型要务实:选择成熟稳定的技术,避免过度追求新技术
- 代码规范很重要:统一的编码风格和注释,方便团队协作
- 测试环节不能省:完善的单元测试和集成测试,保证质量
- 文档记录要详细:系统设计文档、API文档、部署手册等
特别提醒:在开发类似系统时,要特别注意数据安全和用户隐私保护,遵循相关法律法规,对敏感信息进行加密存储和传输。