# LotteryActivityService 抽奖活动服务类文档 ## 概述 `LotteryActivityService` 是抽奖活动管理的专门服务类,负责处理抽奖活动的状态管理、验证、查询、创建、更新、删除等操作。该类专注于活动层面的业务逻辑,与核心抽奖逻辑分离,提供清晰的活动管理接口。 ## 类结构 ```php namespace app\common\Service\lottery; class LotteryActivityService { // 活动状态检查方法 public static function isRunning(LotteryActivity $activity) public static function isEnded(LotteryActivity $activity) public static function isNotStarted(LotteryActivity $activity) public static function isSuspended(LotteryActivity $activity) public static function isCancelled(LotteryActivity $activity) public static function isInDrawTime(LotteryActivity $activity) // 活动查询方法 public static function getRunningActivities() public static function getNotStartedActivities() public static function getEndedActivities() public static function getDisplayableActivities() // 活动验证方法 public static function isValidStatus(LotteryActivity $activity) public static function isValidLotteryType(LotteryActivity $activity) // 活动信息方法 public static function getActivityStatusDescription(LotteryActivity $activity) public static function canUserParticipate(LotteryActivity $activity, $userId) public static function getActivityStatistics(LotteryActivity $activity) // 活动管理方法 public static function batchUpdateStatus() public static function createActivity($data) public static function updateActivity(LotteryActivity $activity, $data) public static function deleteActivity(LotteryActivity $activity) // 奖品查询方法 public static function getPrizes($activityId = null, $page = 1, $pageSize = 10, $type = null) public static function getActivityPrizeStats($activityId) public static function getRunningActivityPrizes($page, $pageSize, $type) public static function getActivityPrizes($activityId, $page, $pageSize, $type) } ``` ## 核心方法详解 ### 1. 活动状态检查方法 #### isRunning() - 检查活动是否正在进行 **功能**: 检查活动是否处于进行中状态。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `bool` 是否正在进行 **逻辑**: - 活动状态为 `STATUS_ONGOING` - 当前时间在活动开始和结束时间之间 **使用示例**: ```php $activity = LotteryActivity::find(1); if (LotteryActivityService::isRunning($activity)) { echo "活动正在进行中"; } ``` #### isEnded() - 检查活动是否已结束 **功能**: 检查活动是否已结束。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `bool` 是否已结束 **逻辑**: - 活动状态为 `STATUS_ENDED` 或当前时间超过结束时间 #### isNotStarted() - 检查活动是否未开始 **功能**: 检查活动是否还未开始。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `bool` 是否未开始 **逻辑**: - 活动状态为 `STATUS_NOT_STARTED` 且当前时间未到开始时间 #### isSuspended() - 检查活动是否已暂停 **功能**: 检查活动是否已暂停。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `bool` 是否已暂停 **逻辑**: - 活动状态为 `STATUS_SUSPENDED` #### isCancelled() - 检查活动是否已取消 **功能**: 检查活动是否已取消。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `bool` 是否已取消 **逻辑**: - 活动状态为 `STATUS_CANCELLED` #### isInDrawTime() - 检查是否在抽奖时间内 **功能**: 检查当前时间是否在活动的抽奖时间范围内。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `bool` 是否在抽奖时间内 **逻辑**: - 如果未启用抽奖时间限制,返回 `true` - 否则检查当前时间是否在 `draw_time_start` 和 `draw_time_end` 之间 **使用示例**: ```php $activity = LotteryActivity::find(1); if (LotteryActivityService::isInDrawTime($activity)) { echo "当前在抽奖时间内"; } else { echo "当前不在抽奖时间内"; } ``` ### 2. 活动查询方法 #### getRunningActivities() - 获取正在进行的活动 **功能**: 获取所有正在进行的抽奖活动。 **返回值**: `Collection` 活动集合 **查询条件**: - 状态为 `STATUS_ONGOING` - 当前时间在活动时间范围内 **使用示例**: ```php $runningActivities = LotteryActivityService::getRunningActivities(); foreach ($runningActivities as $activity) { echo "活动名称:" . $activity->name; } ``` #### getNotStartedActivities() - 获取未开始的活动 **功能**: 获取所有未开始的抽奖活动。 **返回值**: `Collection` 活动集合 **查询条件**: - 状态为 `STATUS_NOT_STARTED` - 开始时间大于当前时间 #### getEndedActivities() - 获取已结束的活动 **功能**: 获取所有已结束的抽奖活动。 **返回值**: `Collection` 活动集合 **查询条件**: - 状态为 `STATUS_ENDED` 或结束时间小于当前时间 #### getDisplayableActivities() - 获取可显示的活动 **功能**: 获取可显示的活动(排除逻辑状态)。 **返回值**: `Collection` 活动集合 **查询条件**: - 状态在可显示状态列表中(排除已关闭、已删除、已过期等逻辑状态) ### 3. 活动验证方法 #### isValidStatus() - 验证活动状态 **功能**: 验证活动状态是否有效。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `bool` 状态是否有效 **验证逻辑**: - 使用 `LotteryEnum::isValidActivityStatus()` 验证 #### isValidLotteryType() - 验证开奖方式 **功能**: 验证开奖方式是否有效。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `bool` 开奖方式是否有效 **验证逻辑**: - 使用 `LotteryEnum::isValidLotteryType()` 验证 ### 4. 活动信息方法 #### getActivityStatusDescription() - 获取活动状态描述 **功能**: 获取活动的详细状态描述。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `string` 状态描述 **状态描述**: - 已取消:`活动已取消` - 已暂停:`活动已暂停` - 已结束:`活动已结束` - 进行中:`活动进行中` - 未开始:`活动未开始` - 其他:`未知状态` **使用示例**: ```php $activity = LotteryActivity::find(1); $statusDesc = LotteryActivityService::getActivityStatusDescription($activity); echo "活动状态:" . $statusDesc; ``` #### canUserParticipate() - 检查用户是否可以参与活动 **功能**: 检查用户是否可以参与指定活动。 **参数**: - `$activity` (LotteryActivity): 活动对象 - `$userId` (int): 用户ID **返回值**: `bool` 是否可以参与 **检查内容**: 1. 活动状态检查(必须为进行中) 2. 抽奖时间检查(必须在抽奖时间内) 3. 用户群体限制检查(待实现) 4. 用户参与次数限制检查(待实现) **使用示例**: ```php $activity = LotteryActivity::find(1); $userId = 123; if (LotteryActivityService::canUserParticipate($activity, $userId)) { echo "用户可以参与活动"; } else { echo "用户不能参与活动"; } ``` #### getActivityStatistics() - 获取活动统计信息 **功能**: 获取活动的统计信息。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `array` 统计信息 **统计内容**: ```php [ 'total_participants' => 100, // 总参与人数 'total_winners' => 20, // 总中奖人数 'total_prizes' => 5, // 总奖品数量 'total_conditions' => 3 // 总参与条件数量 ] ``` **使用示例**: ```php $activity = LotteryActivity::find(1); $stats = LotteryActivityService::getActivityStatistics($activity); echo "参与人数:" . $stats['total_participants']; echo "中奖人数:" . $stats['total_winners']; ``` ### 5. 活动管理方法 #### batchUpdateStatus() - 批量更新活动状态 **功能**: 批量更新活动状态,处理过期和到期的活动。 **逻辑**: 1. 将已过期的进行中活动标记为已结束 2. 将到期的未开始活动标记为进行中 **使用示例**: ```php // 通常在定时任务中调用 LotteryActivityService::batchUpdateStatus(); ``` #### createActivity() - 创建新活动 **功能**: 创建新的抽奖活动。 **参数**: - `$data` (array): 活动数据 **返回值**: `LotteryActivity` 创建的活动对象 **验证内容**: - 活动状态有效性 - 开奖方式有效性 **异常**: `Exception` 验证失败时抛出异常 **使用示例**: ```php $activityData = [ 'name' => '新年抽奖活动', 'status' => LotteryEnum::STATUS_NOT_STARTED, 'lottery_type' => LotteryEnum::LOTTERY_TYPE_INSTANT, 'start_time' => time() + 3600, 'end_time' => time() + 86400, // ... 其他字段 ]; try { $activity = LotteryActivityService::createActivity($activityData); echo "活动创建成功,ID:" . $activity->id; } catch (Exception $e) { echo "活动创建失败:" . $e->getMessage(); } ``` #### updateActivity() - 更新活动 **功能**: 更新现有活动信息。 **参数**: - `$activity` (LotteryActivity): 活动对象 - `$data` (array): 更新数据 **返回值**: `bool` 更新是否成功 **验证内容**: - 活动状态有效性(如果更新状态) - 开奖方式有效性(如果更新开奖方式) **异常**: `Exception` 验证失败时抛出异常 **使用示例**: ```php $activity = LotteryActivity::find(1); $updateData = [ 'name' => '更新后的活动名称', 'status' => LotteryEnum::STATUS_ONGOING ]; try { $result = LotteryActivityService::updateActivity($activity, $updateData); if ($result) { echo "活动更新成功"; } } catch (Exception $e) { echo "活动更新失败:" . $e->getMessage(); } ``` #### deleteActivity() - 删除活动 **功能**: 删除抽奖活动。 **参数**: - `$activity` (LotteryActivity): 活动对象 **返回值**: `bool` 删除是否成功 **验证内容**: - 检查活动是否可以删除(进行中的活动不能删除) **异常**: `Exception` 验证失败时抛出异常 **使用示例**: ```php $activity = LotteryActivity::find(1); try { $result = LotteryActivityService::deleteActivity($activity); if ($result) { echo "活动删除成功"; } } catch (Exception $e) { echo "活动删除失败:" . $e->getMessage(); } ``` ### 6. 奖品查询方法 #### getPrizes() - 获取奖品列表 **功能**: 获取奖品列表,支持按活动ID查询或查询进行中活动的奖品。 **参数**: - `$activityId` (int|null): 活动ID,不传则查询进行中活动的奖品 - `$page` (int): 页码,默认1 - `$pageSize` (int): 每页数量,默认10 - `$type` (array|null): 奖品类型筛选数组 **返回值**: `\think\Paginator` 分页对象 **返回格式**: ```php [ 'list' => [ [ 'id' => 1, 'activity_id' => 1, 'name' => '一等奖', 'type' => 2, 'type_text' => '实物奖品', 'image' => '/uploads/prize1.jpg', 'description' => '奖品描述', 'probability' => 0.01, 'probability_percent' => 1.00, 'total_stock' => 10, 'remain_stock' => 8, 'stock_percent' => 80.00, 'win_prompt' => '恭喜中奖!', 'sort_order' => 1, 'unlock_people_num' => 100, 'is_unlocked' => true, 'activity_name' => '新年抽奖活动', 'activity_status' => 2, 'createtime' => 1640995200 ] ], 'total' => 1 ] ``` #### getActivityPrizeStats() - 获取活动奖品统计信息 **功能**: 获取指定活动的奖品统计信息。 **参数**: - `$activityId` (int): 活动ID **返回值**: `array` 统计信息 **返回格式**: ```php [ 'total_prizes' => 5, // 总奖品数量 'total_stock' => 100, // 总库存 'remain_stock' => 80, // 剩余库存 'used_stock' => 20, // 已使用库存 'prize_types' => [ // 按类型统计 2 => [ 'type' => 2, 'type_text' => '实物奖品', 'count' => 3, 'total_stock' => 3, 'remain_stock' => 2 ] ], 'unlocked_prizes' => 4, // 已解锁奖品数量 'locked_prizes' => 1 // 未解锁奖品数量 ] ``` #### getRunningActivityPrizes() - 获取进行中活动的奖品列表 **功能**: 获取所有进行中活动的奖品列表。 **参数**: - `$page` (int): 页码,默认1 - `$pageSize` (int): 每页数量,默认20 - `$type` (int|array|null): 奖品类型筛选,支持单个类型或类型数组 **返回值**: `\think\Paginator` 分页对象 #### getActivityPrizes() - 获取指定活动的奖品列表 **功能**: 获取指定活动的奖品列表。 **参数**: - `$activityId` (int): 活动ID - `$page` (int): 页码,默认1 - `$pageSize` (int): 每页数量,默认20 - `$type` (int|array|null): 奖品类型筛选,支持单个类型或类型数组 **返回值**: `\think\Paginator` 分页对象 ## 使用示例 ### 1. 活动状态管理 ```php // 获取所有活动状态 $activity = LotteryActivity::find(1); if (LotteryActivityService::isRunning($activity)) { echo "活动正在进行中"; } elseif (LotteryActivityService::isEnded($activity)) { echo "活动已结束"; } elseif (LotteryActivityService::isNotStarted($activity)) { echo "活动未开始"; } elseif (LotteryActivityService::isSuspended($activity)) { echo "活动已暂停"; } elseif (LotteryActivityService::isCancelled($activity)) { echo "活动已取消"; } // 获取状态描述 $statusDesc = LotteryActivityService::getActivityStatusDescription($activity); echo "活动状态:" . $statusDesc; ``` ### 2. 活动查询 ```php // 获取正在进行的活动 $runningActivities = LotteryActivityService::getRunningActivities(); echo "正在进行的活动数量:" . $runningActivities->count(); // 获取未开始的活动 $notStartedActivities = LotteryActivityService::getNotStartedActivities(); echo "未开始的活动数量:" . $notStartedActivities->count(); // 获取已结束的活动 $endedActivities = LotteryActivityService::getEndedActivities(); echo "已结束的活动数量:" . $endedActivities->count(); // 获取可显示的活动 $displayableActivities = LotteryActivityService::getDisplayableActivities(); echo "可显示的活动数量:" . $displayableActivities->count(); ``` ### 3. 用户参与检查 ```php $activity = LotteryActivity::find(1); $userId = 123; // 检查用户是否可以参与 if (LotteryActivityService::canUserParticipate($activity, $userId)) { echo "用户可以参与活动"; // 检查是否在抽奖时间内 if (LotteryActivityService::isInDrawTime($activity)) { echo "当前在抽奖时间内,可以抽奖"; } else { echo "当前不在抽奖时间内"; } } else { echo "用户不能参与活动"; } ``` ### 4. 活动统计 ```php $activity = LotteryActivity::find(1); $stats = LotteryActivityService::getActivityStatistics($activity); echo "活动统计信息:\n"; echo "总参与人数:" . $stats['total_participants'] . "\n"; echo "总中奖人数:" . $stats['total_winners'] . "\n"; echo "总奖品数量:" . $stats['total_prizes'] . "\n"; echo "总参与条件数量:" . $stats['total_conditions'] . "\n"; ``` ### 5. 活动管理 ```php // 创建活动 $activityData = [ 'name' => '测试抽奖活动', 'status' => LotteryEnum::STATUS_NOT_STARTED, 'lottery_type' => LotteryEnum::LOTTERY_TYPE_INSTANT, 'start_time' => time() + 3600, 'end_time' => time() + 86400, 'user_limit_type' => LotteryEnum::USER_LIMIT_ALL, 'person_limit_num' => 10, 'draw_time_enable' => 0 ]; try { $activity = LotteryActivityService::createActivity($activityData); echo "活动创建成功,ID:" . $activity->id; // 更新活动 $updateData = ['name' => '更新后的活动名称']; $result = LotteryActivityService::updateActivity($activity, $updateData); if ($result) { echo "活动更新成功"; } // 删除活动(如果允许) $result = LotteryActivityService::deleteActivity($activity); if ($result) { echo "活动删除成功"; } } catch (Exception $e) { echo "操作失败:" . $e->getMessage(); } ``` ### 6. 批量状态更新 ```php // 在定时任务中调用 LotteryActivityService::batchUpdateStatus(); echo "活动状态批量更新完成"; ``` ### 7. 奖品查询 ```php // 获取指定活动的奖品列表 $activityId = 1; $page = 1; $pageSize = 20; // 单个类型筛选 $type = 2; // 实物奖品类型 $paginate = LotteryActivityService::getActivityPrizes($activityId, $page, $pageSize, $type); // 多个类型筛选 $types = [2, 3, 4]; // 实物奖品、积分、余额 $paginate = LotteryActivityService::getActivityPrizes($activityId, $page, $pageSize, $types); echo "奖品数量:" . $paginate->total(); echo "当前页:" . $paginate->currentPage(); echo "总页数:" . $paginate->lastPage(); foreach ($paginate->items() as $prize) { echo "奖品名称:" . $prize->name; echo "中奖率:" . $prize->probability_percent . "%"; echo "库存百分比:" . $prize->stock_percent . "%"; } // 获取进行中活动的奖品列表 $paginate = LotteryActivityService::getRunningActivityPrizes($page, $pageSize, $types); echo "进行中活动奖品数量:" . $paginate->total(); // 获取活动奖品统计信息 $stats = LotteryActivityService::getActivityPrizeStats($activityId); echo "总奖品数量:" . $stats['total_prizes']; echo "总库存:" . $stats['total_stock']; echo "剩余库存:" . $stats['remain_stock']; echo "已使用库存:" . $stats['used_stock']; echo "已解锁奖品:" . $stats['unlocked_prizes']; echo "未解锁奖品:" . $stats['locked_prizes']; // 按奖品类型统计 foreach ($stats['prize_types'] as $typeInfo) { echo "奖品类型:" . $typeInfo['type_text']; echo "数量:" . $typeInfo['count']; echo "库存:" . $typeInfo['total_stock']; echo "剩余:" . $typeInfo['remain_stock']; } ``` ## 注意事项 ### 1. 状态管理 - 活动状态变更需要谨慎处理 - 进行中的活动不能删除 - 状态更新需要考虑时间因素 ### 2. 时间处理 - 所有时间比较都基于时间戳 - 抽奖时间限制需要考虑时区 - 批量更新状态时需要考虑性能 ### 3. 数据验证 - 创建和更新活动时必须验证数据有效性 - 使用枚举类确保状态和类型的一致性 - 异常处理要提供友好的错误信息 ### 4. 性能优化 - 查询方法可以使用缓存 - 批量操作时考虑数据库性能 - 统计查询可以使用索引优化 ### 5. 扩展性 - 预留用户群体限制检查接口 - 预留参与次数限制检查接口 - 支持自定义验证规则 ## 错误处理 ### 常见异常 1. `无效的活动状态` - 状态验证失败 2. `无效的开奖方式` - 开奖方式验证失败 3. `进行中的活动不能删除` - 删除验证失败 ### 异常处理建议 - 在控制器层捕获异常 - 记录详细的错误日志 - 提供用户友好的错误提示 ## 性能优化建议 ### 1. 缓存优化 - 缓存活动状态信息 - 缓存活动统计信息 - 使用Redis缓存热点数据 ### 2. 数据库优化 - 为状态和时间字段添加索引 - 优化查询条件 - 使用批量操作减少数据库访问 ### 3. 查询优化 - 减少不必要的字段查询 - 使用延迟加载 - 优化关联查询 ## 扩展建议 ### 1. 活动类型扩展 - 支持更多活动类型 - 支持活动模板 - 支持活动复制 ### 2. 状态管理扩展 - 支持状态流转日志 - 支持状态变更通知 - 支持状态回滚 ### 3. 统计功能扩展 - 支持实时统计 - 支持多维度统计 - 支持统计报表导出 ### 4. 权限控制扩展 - 支持活动权限管理 - 支持操作权限控制 - 支持数据权限控制 ## 相关依赖 - `app\common\model\lottery\LotteryActivity`: 活动模型 - `app\common\model\lottery\LotteryPrize`: 奖品模型 - `app\common\Enum\LotteryEnum`: 抽奖枚举类 - `think\Paginator`: ThinkPHP分页类 ## 版本信息 - 创建时间: 2024年 - 最后更新: 2024年 - 版本: 1.0