19 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
构建和开发命令
构建应用程序
# 清理构建(默认跳过测试)
mvn clean package
# 清理构建并执行测试
mvn clean package -DskipTests=false
# 运行应用程序
mvn spring-boot:run
测试命令
# 运行特定测试类
mvn test -Dtest=FaceCleanerTest
# 运行特定测试方法
mvn test -Dtest=FaceCleanerTest#testSpecificMethod
# 运行特定包的测试
mvn test -Dtest="com.ycwl.basic.storage.adapters.*Test"
# 运行pricing模块测试
mvn test -Dtest="com.ycwl.basic.pricing.*Test"
# 运行所有测试
mvn test -DskipTests=false
# 运行测试并生成详细报告
mvn test -DskipTests=false -Dsurefire.printSummary=true
开发环境配置
应用程序使用 Spring 配置文件:
- 默认激活配置文件:
dev
- 生产环境配置文件:
prod
(启用定时任务) - 配置文件:
application-dev.yml
、application-prod.yml
架构概览
这是一个 Spring Boot 3.3.5 应用程序(Java 21),采用多租户架构,通过不同的 API 端点为不同的客户端类型提供服务。
控制器架构
- 移动端 APIs (
/api/mobile/
):面向移动应用的客户端端点 - PC 端 APIs (
/api/
):Web 仪表板/管理面板端点 - 任务 APIs (
/task/
):后台工作和渲染任务端点 - 外部 APIs:专用集成(打印机、代理、viid、vpt、wvp)
核心业务模块
工厂模式实现
三个主要工厂类管理第三方集成:
-
StorageFactory (
com.ycwl.basic.storage.StorageFactory
)- 管理:本地存储、AWS S3、阿里云 OSS 存储适配器
- 配置节:
storage.configs[]
-
PayFactory (
com.ycwl.basic.pay.PayFactory
)- 管理:微信支付、聪明支付适配器
- 配置节:
pay.configs[]
-
FaceBodyFactory (
com.ycwl.basic.facebody.FaceBodyFactory
)- 管理:阿里云、百度人脸识别适配器
- 配置节:
facebody.configs[]
适配器模式
每个工厂使用标准化接口:
IStorageAdapter
:文件操作(上传/下载/删除/ACL)IPayAdapter
:支付生命周期(创建/回调/退款)IFaceBodyAdapter
:人脸识别操作
定时任务系统
com.ycwl.basic.task
包中的后台任务(仅生产环境):
VideoTaskGenerator
:人脸识别和视频处理FaceCleaner
:人脸和存储清理任务DynamicTaskGenerator
:带延迟队列的动态任务创建ScenicStatsTask
:统计数据聚合
数据库和持久化
- MyBatis Plus:具有自动 CRUD 操作的 ORM
- MapperScan:扫描
com.ycwl.basic.mapper
及子包 - 数据库:MySQL 配合 HikariCP 连接池
- Redis:会话管理和缓存
主要库和依赖
- Spring Boot 3.3.5 启用 Java 21 虚拟线程
- MyBatis Plus 3.5.5 用于数据库操作
- JWT (jjwt 0.9.0) 用于身份验证
- 微信支付 SDK 用于支付处理
- 阿里云 OSS 和 AWS S3 用于文件存储
- 阿里云和百度 SDK 用于人脸识别
- OpenTelemetry 用于可观测性(开发环境中禁用)
业务逻辑组织
- Service 层:
service
包中的业务逻辑实现 - Biz 层:
biz
包中的高级业务编排 - Repository 模式:
repository
包中的数据访问抽象 - 自定义异常:特定领域的异常处理
配置管理
每个模块使用 Spring Boot 自动配置启动器:
- 支持多供应商的命名配置
- 通过配置进行默认供应商选择
- 针对不同环境的特定配置文件
常见开发模式
添加新的存储/支付/人脸识别供应商
- 实现相应接口(
IStorageAdapter
、IPayAdapter
、IFaceBodyAdapter
) - 在相应的类型枚举中添加枚举值
- 更新工厂的 switch 表达式
- 如需要,添加配置类
- 在 application.yml 中更新新供应商配置
身份验证上下文
在整个应用程序中使用 BaseContextHandler.getUserId()
获取当前已认证用户 ID。
API 响应模式
所有 API 都返回 ApiResponse<T>
包装器,通过 CustomExceptionHandle
进行一致的错误处理。
添加新的定时任务
- 在
com.ycwl.basic.task
包中创建类 - 添加
@Component
和@Profile("prod")
注解 - 使用
@Scheduled
进行基于 cron 的执行 - 遵循现有的错误处理和日志记录模式
多端API架构
应用程序通过路径前缀区分不同的客户端:
- 移动端:
/api/mobile/*
- 针对移动应用优化的接口 - PC管理端:
/api/*
- Web管理面板接口 - 任务处理:
/task/*
- 后台任务和渲染服务接口 - 外部集成: 专用集成接口(打印机、代理、viid、vpt、wvp等)
每个端点都有对应的Controller包结构,确保API的职责分离和维护性。
价格查询系统 (Pricing Module)
核心架构
价格查询系统是一个独立的业务模块,位于 com.ycwl.basic.pricing
包中,提供商品定价、优惠券管理、券码管理和统一优惠检测功能。
关键组件
- PriceCalculationController (
/api/pricing/calculate
):统一价格计算API,支持自动优惠组合 - CouponManagementController (
/api/pricing/admin/coupons/
):优惠券配置和统计管理 - VoucherManagementController (
/api/pricing/voucher/
):券码批次和券码管理 - VoucherUsageController (
/api/pricing/voucher/usage/
):券码使用记录和统计 - PricingConfigController (
/api/pricing/config/
):商品价格配置管理 - OnePricePurchaseController (
/api/pricing/admin/one-price/
):一口价配置管理
商品类型支持
ProductType枚举定义了支持的商品类型:
- VLOG_VIDEO: Vlog视频
- RECORDING_SET: 录像集
- PHOTO_SET: 照相集
- PHOTO_PRINT: 照片打印
- MACHINE_PRINT: 一体机打印
价格计算流程(统一优惠检测)
- 接收PriceCalculationRequest(包含商品列表、用户ID、券码等)
- 查找商品基础配置和分层定价
- 处理套餐商品(BundleProductItem)
- 统一优惠检测:通过IDiscountDetectionService自动检测所有可用优惠
- 券码优惠(VoucherDiscountProvider,优先级100)
- 优惠券优惠(CouponDiscountProvider,优先级80)
- 一口价优惠(OnePricePurchaseDiscountProvider,优先级60)
- 智能优惠组合:按优先级和叠加规则应用最优优惠组合
- 返回PriceCalculationResult(包含原价、最终价格、使用的优惠详情、可用优惠列表)
优惠券系统
- CouponType: PERCENTAGE(百分比)、FIXED_AMOUNT(固定金额)
- CouponStatus: CLAIMED(已领取)、USED(已使用)、EXPIRED(已过期)
- 支持商品类型限制 (
applicableProducts
JSON字段) - 最小消费金额和最大折扣限制
- 时间有效期控制
分页查询功能
所有管理接口都支持分页查询:
- 优惠券系统:使用PageHelper实现
- 优惠券配置分页:支持按状态、名称筛选
- 领取记录分页:支持按用户、优惠券、状态、时间范围筛选
- 券码系统:使用MyBatis-Plus Page实现
- 券码批次分页:支持按景区、批次名称、状态筛选
- 券码列表分页:支持按批次、状态、用户筛选
- 使用记录分页:支持按券码、用户、时间范围筛选
统计功能
- 优惠券统计:基础统计(领取数、使用数、可用数)、详细统计(使用率、平均使用天数)
- 券码统计:支持可重复使用的统计(使用率、重复使用率、平均使用次数)
- 时间范围统计:指定时间段的整体数据分析
券码管理系统 (Voucher System)
核心特性
券码系统支持可重复使用的优惠券管理,与传统优惠券系统并行工作。
关键优势
- 可重复使用:支持单个券码多次使用,通过
maxUseCount
配置最大使用次数 - 用户使用限制:支持单个用户对券码的使用次数限制(
maxUsePerUser
) - 使用间隔控制:支持设置使用时间间隔(
useIntervalHours
) - 时间范围控制:支持设置券码的有效期开始和结束时间
券码优惠类型
public enum VoucherDiscountType {
FREE_ALL(0, "全场免费"), // 优先级最高,且不可叠加
REDUCE_PRICE(1, "商品降价"), // 每个商品减免固定金额
DISCOUNT(2, "商品打折"); // 每个商品按百分比打折
}
数据库表结构
- price_voucher_batch_config:券码批次配置表,支持按景区、推客创建券码批次
- price_voucher_code:券码表,每个券码全局唯一,支持同一用户在同一景区只能领取一次
- price_voucher_usage_record:券码使用记录表,记录每次使用的完整信息
- voucher_print_record:券码打印记录表,用于移动端打印功能
统一优惠检测系统 (Unified Discount Detection)
设计模式
采用策略模式的可扩展优惠检测系统,统一管理并自动组合多种优惠类型。
核心接口
// 优惠提供者接口
public interface IDiscountProvider {
String getProviderType(); // 提供者类型
int getPriority(); // 优先级(数字越大越高)
List<DiscountInfo> detectAvailableDiscounts(); // 检测可用优惠
DiscountResult applyDiscount(); // 应用优惠
}
// 优惠检测服务接口
public interface IDiscountDetectionService {
DiscountCombinationResult calculateOptimalCombination(); // 计算最优组合
DiscountCombinationResult previewOptimalCombination(); // 预览优惠组合
}
优惠提供者实现(按优先级排序)
-
VoucherDiscountProvider (优先级: 100)
- 处理券码优惠逻辑
- 支持用户主动输入券码或自动选择最优券码
- 全场免费券码不可与其他优惠叠加
-
CouponDiscountProvider (优先级: 80)
- 处理优惠券优惠逻辑
- 自动选择最优优惠券
- 可与券码叠加使用(除全场免费券码外)
-
OnePricePurchaseDiscountProvider (优先级: 60)
- 处理一口价优惠逻辑(景区级统一价格)
- 仅当一口价小于当前金额时产生优惠
- 叠加性由配置
canUseCoupon/canUseVoucher
控制
优惠应用策略
原价 → 券码 → 优惠券 → 一口价 → 最终价格
特殊情况:
- 全场免费券码:直接最终价=0,停止后续优惠
- 一口价:可叠加性由配置 canUseCoupon / canUseVoucher 控制
开发模式
添加新商品类型
- 在ProductType枚举中添加新类型
- 在PriceProductConfig表中配置default配置
- 根据需要添加分层定价(PriceTierConfig)
- 更新前端产品类型映射
添加新优惠券类型
- 在CouponType枚举中添加类型
- 在CouponServiceImpl中实现计算逻辑
- 更新applicableProducts验证规则
添加新优惠提供者(策略扩展)
@Component
public class FlashSaleDiscountProvider implements IDiscountProvider {
@Override
public String getProviderType() { return "FLASH_SALE"; }
@Override
public int getPriority() { return 90; } // 介于券码和优惠券之间
@Override
public List<DiscountInfo> detectAvailableDiscounts(DiscountDetectionContext context) {
// 实现限时抢购优惠检测逻辑
return discountInfoList;
}
@Override
public DiscountResult applyDiscount(DiscountDetectionContext context, DiscountInfo discount) {
// 实现优惠应用逻辑
return discountResult;
}
}
创建可重复使用券码批次
VoucherBatchCreateReqV2 request = new VoucherBatchCreateReqV2();
request.setBatchName("限时活动券码");
request.setMaxUseCount(3); // 每个券码最多使用三次
request.setMaxUsePerUser(2); // 每个用户最多使用两次
request.setUseIntervalHours(12); // 使用间隔12小时
request.setValidStartTime(startTime); // 有效期开始时间
request.setValidEndTime(endTime); // 有效期结束时间
自定义TypeHandler使用
项目使用自定义TypeHandler处理复杂JSON字段:
BundleProductListTypeHandler
:处理套餐商品列表JSON序列化
测试策略
针对pricing模块的全面测试策略:
单元测试类型
- 服务层测试:每个服务类都有对应测试类
PriceBundleServiceTest
- 套餐价格计算测试ReusableVoucherServiceTest
- 可重复使用券码测试VoucherTimeRangeTest
- 券码时间范围功能测试VoucherPrintServiceCodeGenerationTest
- 券码生成测试
- 实体映射测试:验证数据库映射和JSON序列化
PriceBundleConfigStructureTest
- 实体结构测试PriceBundleConfigJsonTest
- JSON序列化测试CouponSwitchFieldsMappingTest
- 字段映射测试
- 类型处理器测试:验证自定义TypeHandler
BundleProductListTypeHandlerTest
- 套餐商品列表序列化测试
- 配置验证测试:验证系统配置完整性
DefaultConfigValidationTest
- 验证所有ProductType的default配置CodeGenerationStandaloneTest
- 独立代码生成测试
测试执行命令
# 运行单个测试类
mvn test -Dtest=VoucherTimeRangeTest
mvn test -Dtest=ReusableVoucherServiceTest
mvn test -Dtest=BundleProductListTypeHandlerTest
# 运行整个pricing模块测试
mvn test -Dtest="com.ycwl.basic.pricing.*Test"
# 运行特定分类的测试
mvn test -Dtest="com.ycwl.basic.pricing.service.*Test" # 服务层测试
mvn test -Dtest="com.ycwl.basic.pricing.handler.*Test" # TypeHandler测试
mvn test -Dtest="com.ycwl.basic.pricing.entity.*Test" # 实体测试
mvn test -Dtest="com.ycwl.basic.pricing.mapper.*Test" # Mapper测试
# 运行带详细报告的测试
mvn test -Dtest="com.ycwl.basic.pricing.*Test" -Dsurefire.printSummary=true
重点测试场景
- 价格计算核心流程:验证统一优惠检测和组合逻辑
- 可重复使用券码:验证多次使用、时间间隔、用户限制逻辑
- 时间范围控制:验证券码有效期开始和结束时间
- 优惠叠加规则:验证券码、优惠券、一口价的叠加逻辑
- JSON序列化:验证复杂对象在数据库中的存储和读取
- 分页功能:验证PageHelper和MyBatis-Plus分页集成
- 异常处理:验证业务异常和全局异常处理器
关键架构模式
Repository 层模式
项目使用Repository层抽象数据访问逻辑:
- Repository接口定义数据访问契约
- Mapper接口处理MyBatis Plus的数据库映射
- Service层通过Repository访问数据,避免直接依赖Mapper
异常处理架构
- 全局异常处理:
CustomExceptionHandle
提供统一的异常处理和响应格式 - 业务异常: 自定义异常类继承RuntimeException,携带业务错误码
- 集成异常:
IntegrationException
专门处理外部服务调用异常
配置驱动的扩展性
通过配置文件驱动的多供应商支持:
- 存储:本地、AWS S3、阿里云 OSS
- 支付:微信支付、聪明支付
- 人脸识别:阿里云、百度 每个供应商通过统一接口访问,配置切换无需代码修改。
业务层架构
- Service层: 核心业务逻辑实现
- Biz层: 高级业务流程编排,组合多个Service
- Controller层: HTTP请求处理和响应转换
- Repository层: 数据访问抽象
认证和会话管理
- JWT: 使用jjwt库进行身份验证
- Redis: 存储会话信息和缓存
- BaseContextHandler: 提供当前用户上下文访问
微服务集成架构 (Integration Package)
核心架构
位于 com.ycwl.basic.integration
包,使用 Spring Cloud OpenFeign 和 Nacos 实现外部微服务集成。
通用基础设施
- IntegrationProperties: 所有集成的集中配置管理
- FeignErrorDecoder: 自定义错误解码器,统一错误处理
- IntegrationException: 标准化集成异常
- CommonResponse/PageResponse: 外部服务响应包装器
已实现的服务集成
- Scenic Integration (
integration.scenic
): ZT-Scenic 微服务集成 - Device Integration (
integration.device
): ZT-Device 微服务集成
集成模式
每个外部服务按以下结构组织:
service/
├── client/ # Feign 客户端
├── config/ # 服务特定配置
├── dto/ # 数据传输对象
├── service/ # 业务逻辑层
└── example/ # 使用示例
配置管理
integration:
scenic:
enabled: true
serviceName: zt-scenic
connectTimeout: 5000
readTimeout: 10000
device:
enabled: true
serviceName: zt-device
connectTimeout: 5000
readTimeout: 10000
使用模式
所有集成服务使用统一的 handleResponse
模式进行错误处理,确保一致的异常包装和日志记录。
测试集成服务
# 运行特定集成测试
mvn test -Dtest=ScenicIntegrationServiceTest
mvn test -Dtest=DeviceIntegrationServiceTest
# 运行所有集成测试
mvn test -Dtest="com.ycwl.basic.integration.*Test"
调试集成问题
启用 Feign 客户端日志:
logging:
level:
com.ycwl.basic.integration: DEBUG
开发环境和调试
端口配置
- 开发环境端口: 8030
- 应用名称: zt
日志配置
开发环境默认启用详细的集成服务日志,便于调试外部服务调用问题。
CI/CD 配置
项目使用 Jenkins 进行持续集成:
- JDK 版本: OpenJDK 21
- 构建命令:
mvn clean package -DskipTests=true
- 构建产物: 自动归档和发布 JAR 文件
重要开发约定
测试文件组织
测试按功能模块组织,包括:
- 适配器测试:
*AdapterTest.java
测试第三方集成 - 实体测试: 验证数据库映射和JSON序列化
- Mapper测试: 验证数据访问层逻辑
- Handler测试: 测试自定义TypeHandler
模块化架构
每个业务模块(如 pricing
、integration
、order
)都有完整的分层结构:
module/
├── controller/ # REST API控制器
├── service/ # 业务逻辑层
├── repository/ # 数据访问抽象
├── mapper/ # MyBatis数据映射
├── entity/ # JPA/MyBatis实体
├── dto/ # 数据传输对象
├── enums/ # 枚举定义
└── exception/ # 模块特定异常
外部服务集成
集成服务统一使用以下模式:
- Feign客户端: 声明式HTTP客户端调用
- 错误处理: 统一的
handleResponse
模式 - 配置管理: 通过
IntegrationProperties
集中配置 - 超时配置: 连接超时5秒,读取超时10秒
Windows 开发环境注意事项
路径处理
- 项目在Windows系统上运行,注意路径分隔符使用反斜杠
\
- 配置文件中的资源路径已适配Windows环境
- 日志文件和临时文件路径会自动适配系统环境
开发工具兼容性
- 确保使用Java 21兼容的IDE
- Maven命令在Windows Command Prompt和PowerShell中均可使用
- 建议使用UTF-8编码避免中文字符问题
端口占用检查
开发时如遇端口冲突,使用以下命令检查:
netstat -ano | findstr :8030
taskkill /f /pid <PID>