| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- <?php
- namespace App\Module\Task\Services;
- use App\Module\Task\Enums\RESET_TYPE;
- use App\Module\Task\Enums\TASK_STATUS;
- use App\Module\Task\Events\TaskCompletedEvent;
- use App\Module\Task\Models\Task;
- use App\Module\Task\Models\TaskUserTask;
- use App\Module\Task\Repositorys\TaskRepository;
- use App\Module\Task\Repositorys\TaskResetLogRepository;
- use App\Module\Task\Repositorys\TaskUserProgressRepository;
- use App\Module\Task\Repositorys\TaskUserTaskRepository;
- use Carbon\Carbon;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Log;
- /**
- * 任务进度服务类
- *
- * 提供任务进度相关的服务,包括进度更新、任务完成检查、任务重置等功能。
- * 该类主要处理任务进度的逻辑,与TaskConditionService配合使用。
- */
- class TaskProgressService
- {
- /**
- * 任务数据仓库
- *
- * @var TaskRepository
- */
- protected $taskRepository;
-
- /**
- * 用户任务数据仓库
- *
- * @var TaskUserTaskRepository
- */
- protected $userTaskRepository;
-
- /**
- * 用户任务进度数据仓库
- *
- * @var TaskUserProgressRepository
- */
- protected $userProgressRepository;
-
- /**
- * 任务重置日志数据仓库
- *
- * @var TaskResetLogRepository
- */
- protected $resetLogRepository;
-
- /**
- * 任务条件服务
- *
- * @var TaskConditionService
- */
- protected $conditionService;
-
- /**
- * 构造函数
- *
- * @param TaskRepository $taskRepository
- * @param TaskUserTaskRepository $userTaskRepository
- * @param TaskUserProgressRepository $userProgressRepository
- * @param TaskResetLogRepository $resetLogRepository
- * @param TaskConditionService $conditionService
- */
- public function __construct(
- TaskRepository $taskRepository,
- TaskUserTaskRepository $userTaskRepository,
- TaskUserProgressRepository $userProgressRepository,
- TaskResetLogRepository $resetLogRepository,
- TaskConditionService $conditionService
- ) {
- $this->taskRepository = $taskRepository;
- $this->userTaskRepository = $userTaskRepository;
- $this->userProgressRepository = $userProgressRepository;
- $this->resetLogRepository = $resetLogRepository;
- $this->conditionService = $conditionService;
- }
-
- /**
- * 更新任务进度
- *
- * @param int $userId 用户ID
- * @param int $taskId 任务ID
- * @param int $progress 进度值(0-100)
- * @return array 更新结果
- */
- public function updateTaskProgress(int $userId, int $taskId, int $progress): array
- {
- try {
- // 获取用户任务
- $userTask = $this->userTaskRepository->getUserTask($userId, $taskId);
- if (!$userTask) {
- throw new \Exception('未接取该任务');
- }
-
- // 检查任务状态
- if ($userTask->status !== TASK_STATUS::IN_PROGRESS->value) {
- throw new \Exception('只能更新进行中的任务进度');
- }
-
- // 验证进度值
- if ($progress < 0 || $progress > 100) {
- throw new \Exception('进度值必须在0-100之间');
- }
-
- // 检查任务是否需要重置
- $this->checkAndResetTask($userTask);
-
- // 更新任务进度
- $userTask->progress = $progress;
- $userTask->save();
-
- // 如果进度达到100%,检查是否可以完成任务
- if ($progress === 100) {
- return $this->checkTaskCompletion($userId, $taskId);
- }
-
- return [
- 'success' => true,
- 'message' => '任务进度更新成功',
- 'progress' => $progress,
- ];
- } catch (\Exception $e) {
- Log::error('任务进度更新失败', [
- 'user_id' => $userId,
- 'task_id' => $taskId,
- 'progress' => $progress,
- 'error' => $e->getMessage(),
- ]);
-
- return [
- 'success' => false,
- 'message' => '任务进度更新失败: ' . $e->getMessage(),
- ];
- }
- }
-
- /**
- * 检查任务完成状态
- *
- * @param int $userId 用户ID
- * @param int $taskId 任务ID
- * @return array 检查结果
- */
- public function checkTaskCompletion(int $userId, int $taskId): array
- {
- try {
- // 开始事务
- DB::beginTransaction();
-
- // 获取用户任务
- $userTask = $this->userTaskRepository->getUserTask($userId, $taskId);
- if (!$userTask) {
- throw new \Exception('未接取该任务');
- }
-
- // 检查任务状态
- if ($userTask->status !== TASK_STATUS::IN_PROGRESS->value) {
- throw new \Exception('只能完成进行中的任务');
- }
-
- // 检查任务进度
- if ($userTask->progress < 100) {
- throw new \Exception('任务进度未达到100%');
- }
-
- // 获取任务信息
- $task = $this->taskRepository->find($taskId);
-
- // 更新任务状态
- $userTask->status = TASK_STATUS::COMPLETED->value;
- $userTask->completed_at = Carbon::now();
- $userTask->save();
-
- // 触发任务完成事件
- event(new TaskCompletedEvent(
- $userId,
- $taskId,
- $task->name,
- $userTask->completed_at
- ));
-
- // 提交事务
- DB::commit();
-
- return [
- 'success' => true,
- 'message' => '任务完成成功',
- 'user_task' => $userTask,
- ];
- } catch (\Exception $e) {
- // 回滚事务
- DB::rollBack();
-
- Log::error('任务完成检查失败', [
- 'user_id' => $userId,
- 'task_id' => $taskId,
- 'error' => $e->getMessage(),
- ]);
-
- return [
- 'success' => false,
- 'message' => '任务完成检查失败: ' . $e->getMessage(),
- ];
- }
- }
-
- /**
- * 检查并重置任务
- *
- * @param TaskUserTask $userTask 用户任务
- * @return bool 是否重置
- */
- public function checkAndResetTask(TaskUserTask $userTask): bool
- {
- try {
- // 获取任务信息
- $task = $this->taskRepository->find($userTask->task_id);
- if (!$task) {
- return false;
- }
-
- // 如果任务不需要重置,直接返回
- if (!$task->reset_type || $task->reset_type === 'none') {
- return false;
- }
-
- // 如果任务状态不是已完成或已领取奖励,不需要重置
- if (!in_array($userTask->status, [TASK_STATUS::COMPLETED->value, TASK_STATUS::REWARDED->value])) {
- return false;
- }
-
- // 检查是否需要重置
- $needReset = $this->needReset($userTask, $task);
-
- if ($needReset) {
- // 重置任务
- return $this->resetTask($userTask, $task);
- }
-
- return false;
- } catch (\Exception $e) {
- Log::error('检查并重置任务失败', [
- 'user_task_id' => $userTask->id,
- 'user_id' => $userTask->user_id,
- 'task_id' => $userTask->task_id,
- 'error' => $e->getMessage(),
- ]);
-
- return false;
- }
- }
-
- /**
- * 检查任务是否需要重置
- *
- * @param TaskUserTask $userTask 用户任务
- * @param Task $task 任务
- * @return bool 是否需要重置
- */
- protected function needReset(TaskUserTask $userTask, Task $task): bool
- {
- // 获取当前时间
- $now = Carbon::now();
-
- // 如果下次重置时间未设置,则计算下次重置时间
- if (!$userTask->next_reset_time) {
- // 如果上次重置时间未设置,则使用任务完成时间或当前时间
- $lastResetTime = $userTask->last_reset_time ?? $userTask->completed_at ?? $now;
-
- // 计算下次重置时间
- $nextResetTime = $this->calculateNextResetTime($task->reset_type, $lastResetTime);
-
- // 更新下次重置时间
- $userTask->next_reset_time = $nextResetTime;
- $userTask->save();
-
- // 如果下次重置时间已过,则需要重置
- return $now->greaterThanOrEqualTo($nextResetTime);
- }
-
- // 如果当前时间已超过下次重置时间,则需要重置
- return $now->greaterThanOrEqualTo($userTask->next_reset_time);
- }
-
- /**
- * 计算下次重置时间
- *
- * @param string $resetType 重置类型
- * @param Carbon $lastResetTime 上次重置时间
- * @return Carbon 下次重置时间
- */
- protected function calculateNextResetTime(string $resetType, Carbon $lastResetTime): Carbon
- {
- $resetType = RESET_TYPE::tryFrom($resetType) ?? RESET_TYPE::NONE;
-
- // 获取重置间隔(秒)
- $interval = RESET_TYPE::getInterval($resetType);
-
- if ($interval === null) {
- // 如果没有重置间隔,则返回一个很远的未来时间
- return Carbon::now()->addYears(100);
- }
-
- // 计算下次重置时间
- return $lastResetTime->copy()->addSeconds($interval);
- }
-
- /**
- * 重置任务
- *
- * @param TaskUserTask $userTask 用户任务
- * @param Task $task 任务
- * @return bool 是否成功
- */
- protected function resetTask(TaskUserTask $userTask, Task $task): bool
- {
- try {
- // 开始事务
- DB::beginTransaction();
-
- // 记录重置前的状态
- $oldStatus = $userTask->status;
- $oldProgress = $userTask->progress;
-
- // 重置任务进度
- $this->conditionService->resetTaskProgress($userTask->user_id, $userTask->task_id);
-
- // 更新任务状态
- $userTask->status = TASK_STATUS::IN_PROGRESS->value;
- $userTask->progress = 0;
- $userTask->completed_at = null;
- $userTask->rewarded_at = null;
- $userTask->last_reset_time = Carbon::now();
-
- // 计算下次重置时间
- $userTask->next_reset_time = $this->calculateNextResetTime($task->reset_type, $userTask->last_reset_time);
-
- // 增加重置次数
- $userTask->reset_count = ($userTask->reset_count ?? 0) + 1;
-
- // 保存更新
- $userTask->save();
-
- // 记录重置日志
- $this->resetLogRepository->create([
- 'user_id' => $userTask->user_id,
- 'task_id' => $userTask->task_id,
- 'user_task_id' => $userTask->id,
- 'reset_type' => $task->reset_type,
- 'old_status' => $oldStatus,
- 'old_progress' => $oldProgress,
- 'reset_time' => $userTask->last_reset_time,
- 'next_reset_time' => $userTask->next_reset_time,
- 'reset_count' => $userTask->reset_count,
- ]);
-
- // 提交事务
- DB::commit();
-
- return true;
- } catch (\Exception $e) {
- // 回滚事务
- DB::rollBack();
-
- Log::error('重置任务失败', [
- 'user_task_id' => $userTask->id,
- 'user_id' => $userTask->user_id,
- 'task_id' => $userTask->task_id,
- 'error' => $e->getMessage(),
- ]);
-
- return false;
- }
- }
-
- /**
- * 批量检查并重置任务
- *
- * @param int $userId 用户ID
- * @param string|null $resetType 重置类型(可选)
- * @return array 重置结果
- */
- public function batchCheckAndResetTasks(int $userId, ?string $resetType = null): array
- {
- try {
- // 获取用户任务
- $query = $this->userTaskRepository->query()
- ->where('user_id', $userId)
- ->whereIn('status', [TASK_STATUS::COMPLETED->value, TASK_STATUS::REWARDED->value]);
-
- // 如果指定了重置类型,则筛选任务
- if ($resetType) {
- $query->whereHas('task', function ($q) use ($resetType) {
- $q->where('reset_type', $resetType);
- });
- }
-
- $userTasks = $query->get();
-
- // 重置任务
- $resetCount = 0;
- foreach ($userTasks as $userTask) {
- $task = $this->taskRepository->find($userTask->task_id);
- if (!$task) {
- continue;
- }
-
- if ($this->checkAndResetTask($userTask)) {
- $resetCount++;
- }
- }
-
- return [
- 'success' => true,
- 'message' => "已重置{$resetCount}个任务",
- 'reset_count' => $resetCount,
- 'total_count' => $userTasks->count(),
- ];
- } catch (\Exception $e) {
- Log::error('批量检查并重置任务失败', [
- 'user_id' => $userId,
- 'reset_type' => $resetType,
- 'error' => $e->getMessage(),
- ]);
-
- return [
- 'success' => false,
- 'message' => '批量检查并重置任务失败: ' . $e->getMessage(),
- ];
- }
- }
-
- /**
- * 获取用户任务进度
- *
- * @param int $userId 用户ID
- * @param int $taskId 任务ID
- * @return array 任务进度
- */
- public function getTaskProgress(int $userId, int $taskId): array
- {
- try {
- // 获取用户任务
- $userTask = $this->userTaskRepository->getUserTask($userId, $taskId);
- if (!$userTask) {
- throw new \Exception('未接取该任务');
- }
-
- // 获取任务条件进度
- $conditionProgress = $this->userProgressRepository->getUserTaskProgress($userId, $taskId);
-
- return [
- 'success' => true,
- 'task_id' => $taskId,
- 'user_id' => $userId,
- 'status' => $userTask->status,
- 'progress' => $userTask->progress,
- 'completed_at' => $userTask->completed_at,
- 'rewarded_at' => $userTask->rewarded_at,
- 'condition_progress' => $conditionProgress,
- ];
- } catch (\Exception $e) {
- Log::error('获取任务进度失败', [
- 'user_id' => $userId,
- 'task_id' => $taskId,
- 'error' => $e->getMessage(),
- ]);
-
- return [
- 'success' => false,
- 'message' => '获取任务进度失败: ' . $e->getMessage(),
- ];
- }
- }
- }
|