TaskRewardService.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <?php
  2. namespace App\Module\Task\Services;
  3. use App\Module\Task\Enums\REWARD_TYPE;
  4. use App\Module\Task\Models\TaskReward;
  5. use App\Module\Task\Models\TaskRewardLog;
  6. use App\Module\Task\Repositorys\TaskRewardLogRepository;
  7. use App\Module\Task\Repositorys\TaskRewardRepository;
  8. use Carbon\Carbon;
  9. use Illuminate\Support\Facades\DB;
  10. use Illuminate\Support\Facades\Log;
  11. /**
  12. * 任务奖励服务类
  13. *
  14. * 提供任务奖励相关的服务,包括奖励发放、奖励记录等功能。
  15. * 该类主要处理任务奖励的逻辑,与TaskService配合使用。
  16. */
  17. class TaskRewardService
  18. {
  19. /**
  20. * 任务奖励数据仓库
  21. *
  22. * @var TaskRewardRepository
  23. */
  24. protected $rewardRepository;
  25. /**
  26. * 任务奖励日志数据仓库
  27. *
  28. * @var TaskRewardLogRepository
  29. */
  30. protected $rewardLogRepository;
  31. /**
  32. * 构造函数
  33. *
  34. * @param TaskRewardRepository $rewardRepository
  35. * @param TaskRewardLogRepository $rewardLogRepository
  36. */
  37. public function __construct(
  38. TaskRewardRepository $rewardRepository,
  39. TaskRewardLogRepository $rewardLogRepository
  40. ) {
  41. $this->rewardRepository = $rewardRepository;
  42. $this->rewardLogRepository = $rewardLogRepository;
  43. }
  44. /**
  45. * 获取任务奖励列表
  46. *
  47. * @param int $taskId 任务ID
  48. * @return array 奖励列表
  49. */
  50. public function getTaskRewards(int $taskId): array
  51. {
  52. return $this->rewardRepository->getRewardsByTaskId($taskId);
  53. }
  54. /**
  55. * 发放任务奖励
  56. *
  57. * @param int $userId 用户ID
  58. * @param int $taskId 任务ID
  59. * @param int $userTaskId 用户任务ID
  60. * @return array 发放结果
  61. */
  62. public function distributeRewards(int $userId, int $taskId, int $userTaskId): array
  63. {
  64. try {
  65. // 开始事务
  66. DB::beginTransaction();
  67. // 获取任务奖励
  68. $rewards = $this->getTaskRewards($taskId);
  69. if (empty($rewards)) {
  70. throw new \Exception('任务没有奖励');
  71. }
  72. // 发放每个奖励
  73. $results = [];
  74. $allSuccess = true;
  75. foreach ($rewards as $reward) {
  76. $result = $this->distributeReward($userId, $reward);
  77. $results[] = $result;
  78. if (!$result['success']) {
  79. $allSuccess = false;
  80. }
  81. }
  82. // 记录奖励发放日志
  83. $this->recordRewardLog($userId, $taskId, $userTaskId, $rewards, $results);
  84. // 提交事务
  85. DB::commit();
  86. return [
  87. 'success' => $allSuccess,
  88. 'message' => $allSuccess ? '奖励发放成功' : '部分奖励发放失败',
  89. 'rewards' => $results,
  90. ];
  91. } catch (\Exception $e) {
  92. // 回滚事务
  93. DB::rollBack();
  94. Log::error('奖励发放失败', [
  95. 'user_id' => $userId,
  96. 'task_id' => $taskId,
  97. 'user_task_id' => $userTaskId,
  98. 'error' => $e->getMessage(),
  99. ]);
  100. return [
  101. 'success' => false,
  102. 'message' => '奖励发放失败: ' . $e->getMessage(),
  103. ];
  104. }
  105. }
  106. /**
  107. * 发放单个奖励
  108. *
  109. * @param int $userId 用户ID
  110. * @param array|TaskReward $reward 奖励信息
  111. * @return array 发放结果
  112. */
  113. protected function distributeReward(int $userId, $reward): array
  114. {
  115. try {
  116. // 将TaskReward对象转换为数组
  117. if ($reward instanceof TaskReward) {
  118. $reward = $reward->toArray();
  119. }
  120. // 根据奖励类型调用不同的发放方法
  121. $rewardType = REWARD_TYPE::tryFrom($reward['reward_type']) ?? null;
  122. if (!$rewardType) {
  123. throw new \Exception('未知的奖励类型: ' . $reward['reward_type']);
  124. }
  125. switch ($rewardType) {
  126. case REWARD_TYPE::ITEM:
  127. return $this->distributeItemReward($userId, $reward);
  128. case REWARD_TYPE::CURRENCY:
  129. return $this->distributeCurrencyReward($userId, $reward);
  130. case REWARD_TYPE::EXPERIENCE:
  131. return $this->distributeExperienceReward($userId, $reward);
  132. case REWARD_TYPE::FEATURE_UNLOCK:
  133. return $this->distributeFeatureUnlockReward($userId, $reward);
  134. case REWARD_TYPE::VIP_POINTS:
  135. return $this->distributeVipPointsReward($userId, $reward);
  136. case REWARD_TYPE::TITLE:
  137. return $this->distributeTitleReward($userId, $reward);
  138. case REWARD_TYPE::AVATAR_FRAME:
  139. return $this->distributeAvatarFrameReward($userId, $reward);
  140. case REWARD_TYPE::PET:
  141. return $this->distributePetReward($userId, $reward);
  142. case REWARD_TYPE::PET_ITEM:
  143. return $this->distributePetItemReward($userId, $reward);
  144. case REWARD_TYPE::FARM_DECORATION:
  145. return $this->distributeFarmDecorationReward($userId, $reward);
  146. default:
  147. throw new \Exception('未实现的奖励类型: ' . $rewardType->value);
  148. }
  149. } catch (\Exception $e) {
  150. Log::error('发放单个奖励失败', [
  151. 'user_id' => $userId,
  152. 'reward' => $reward,
  153. 'error' => $e->getMessage(),
  154. ]);
  155. return [
  156. 'success' => false,
  157. 'message' => '发放奖励失败: ' . $e->getMessage(),
  158. 'reward_type' => $reward['reward_type'] ?? 'unknown',
  159. 'reward_param1' => $reward['reward_param1'] ?? '',
  160. 'reward_param2' => $reward['reward_param2'] ?? '',
  161. 'quantity' => $reward['quantity'] ?? 0,
  162. ];
  163. }
  164. }
  165. /**
  166. * 发放物品奖励
  167. *
  168. * @param int $userId 用户ID
  169. * @param array $reward 奖励信息
  170. * @return array 发放结果
  171. */
  172. protected function distributeItemReward(int $userId, array $reward): array
  173. {
  174. // 这里应该调用物品模块的服务来发放物品
  175. // 例如:ItemService::addItem($userId, $reward['reward_param2'], $reward['quantity'], [...]);
  176. // 模拟发放结果
  177. $success = true;
  178. $message = '物品发放成功';
  179. return [
  180. 'success' => $success,
  181. 'message' => $message,
  182. 'reward_type' => $reward['reward_type'],
  183. 'reward_param1' => $reward['reward_param1'],
  184. 'reward_param2' => $reward['reward_param2'],
  185. 'quantity' => $reward['quantity'],
  186. ];
  187. }
  188. /**
  189. * 发放货币奖励
  190. *
  191. * @param int $userId 用户ID
  192. * @param array $reward 奖励信息
  193. * @return array 发放结果
  194. */
  195. protected function distributeCurrencyReward(int $userId, array $reward): array
  196. {
  197. // 这里应该调用货币模块的服务来发放货币
  198. // 例如:CurrencyService::addCurrency($userId, $reward['reward_param1'], $reward['reward_param2'], $reward['quantity'], [...]);
  199. // 模拟发放结果
  200. $success = true;
  201. $message = '货币发放成功';
  202. return [
  203. 'success' => $success,
  204. 'message' => $message,
  205. 'reward_type' => $reward['reward_type'],
  206. 'reward_param1' => $reward['reward_param1'],
  207. 'reward_param2' => $reward['reward_param2'],
  208. 'quantity' => $reward['quantity'],
  209. ];
  210. }
  211. /**
  212. * 发放经验奖励
  213. *
  214. * @param int $userId 用户ID
  215. * @param array $reward 奖励信息
  216. * @return array 发放结果
  217. */
  218. protected function distributeExperienceReward(int $userId, array $reward): array
  219. {
  220. // 这里应该调用经验模块的服务来发放经验
  221. // 例如:ExperienceService::addExperience($userId, $reward['reward_param1'], $reward['quantity'], [...]);
  222. // 模拟发放结果
  223. $success = true;
  224. $message = '经验发放成功';
  225. return [
  226. 'success' => $success,
  227. 'message' => $message,
  228. 'reward_type' => $reward['reward_type'],
  229. 'reward_param1' => $reward['reward_param1'],
  230. 'reward_param2' => $reward['reward_param2'],
  231. 'quantity' => $reward['quantity'],
  232. ];
  233. }
  234. /**
  235. * 发放功能解锁奖励
  236. *
  237. * @param int $userId 用户ID
  238. * @param array $reward 奖励信息
  239. * @return array 发放结果
  240. */
  241. protected function distributeFeatureUnlockReward(int $userId, array $reward): array
  242. {
  243. // 这里应该调用功能解锁模块的服务来解锁功能
  244. // 例如:FeatureService::unlockFeature($userId, $reward['reward_param1'], $reward['reward_param2'], [...]);
  245. // 模拟发放结果
  246. $success = true;
  247. $message = '功能解锁成功';
  248. return [
  249. 'success' => $success,
  250. 'message' => $message,
  251. 'reward_type' => $reward['reward_type'],
  252. 'reward_param1' => $reward['reward_param1'],
  253. 'reward_param2' => $reward['reward_param2'],
  254. 'quantity' => $reward['quantity'],
  255. ];
  256. }
  257. /**
  258. * 发放VIP点数奖励
  259. *
  260. * @param int $userId 用户ID
  261. * @param array $reward 奖励信息
  262. * @return array 发放结果
  263. */
  264. protected function distributeVipPointsReward(int $userId, array $reward): array
  265. {
  266. // 这里应该调用VIP模块的服务来发放VIP点数
  267. // 例如:VipService::addPoints($userId, $reward['quantity'], [...]);
  268. // 模拟发放结果
  269. $success = true;
  270. $message = 'VIP点数发放成功';
  271. return [
  272. 'success' => $success,
  273. 'message' => $message,
  274. 'reward_type' => $reward['reward_type'],
  275. 'reward_param1' => $reward['reward_param1'],
  276. 'reward_param2' => $reward['reward_param2'],
  277. 'quantity' => $reward['quantity'],
  278. ];
  279. }
  280. /**
  281. * 发放称号奖励
  282. *
  283. * @param int $userId 用户ID
  284. * @param array $reward 奖励信息
  285. * @return array 发放结果
  286. */
  287. protected function distributeTitleReward(int $userId, array $reward): array
  288. {
  289. // 这里应该调用称号模块的服务来发放称号
  290. // 例如:TitleService::addTitle($userId, $reward['reward_param1'], $reward['reward_param2'], [...]);
  291. // 模拟发放结果
  292. $success = true;
  293. $message = '称号发放成功';
  294. return [
  295. 'success' => $success,
  296. 'message' => $message,
  297. 'reward_type' => $reward['reward_type'],
  298. 'reward_param1' => $reward['reward_param1'],
  299. 'reward_param2' => $reward['reward_param2'],
  300. 'quantity' => $reward['quantity'],
  301. ];
  302. }
  303. /**
  304. * 发放头像框奖励
  305. *
  306. * @param int $userId 用户ID
  307. * @param array $reward 奖励信息
  308. * @return array 发放结果
  309. */
  310. protected function distributeAvatarFrameReward(int $userId, array $reward): array
  311. {
  312. // 这里应该调用头像框模块的服务来发放头像框
  313. // 例如:AvatarFrameService::addFrame($userId, $reward['reward_param1'], $reward['reward_param2'], [...]);
  314. // 模拟发放结果
  315. $success = true;
  316. $message = '头像框发放成功';
  317. return [
  318. 'success' => $success,
  319. 'message' => $message,
  320. 'reward_type' => $reward['reward_type'],
  321. 'reward_param1' => $reward['reward_param1'],
  322. 'reward_param2' => $reward['reward_param2'],
  323. 'quantity' => $reward['quantity'],
  324. ];
  325. }
  326. /**
  327. * 发放宠物奖励
  328. *
  329. * @param int $userId 用户ID
  330. * @param array $reward 奖励信息
  331. * @return array 发放结果
  332. */
  333. protected function distributePetReward(int $userId, array $reward): array
  334. {
  335. // 这里应该调用宠物模块的服务来发放宠物
  336. // 例如:PetService::addPet($userId, $reward['reward_param1'], $reward['reward_param2'], [...]);
  337. // 模拟发放结果
  338. $success = true;
  339. $message = '宠物发放成功';
  340. return [
  341. 'success' => $success,
  342. 'message' => $message,
  343. 'reward_type' => $reward['reward_type'],
  344. 'reward_param1' => $reward['reward_param1'],
  345. 'reward_param2' => $reward['reward_param2'],
  346. 'quantity' => $reward['quantity'],
  347. ];
  348. }
  349. /**
  350. * 发放宠物物品奖励
  351. *
  352. * @param int $userId 用户ID
  353. * @param array $reward 奖励信息
  354. * @return array 发放结果
  355. */
  356. protected function distributePetItemReward(int $userId, array $reward): array
  357. {
  358. // 这里应该调用宠物物品模块的服务来发放宠物物品
  359. // 例如:PetItemService::addItem($userId, $reward['reward_param1'], $reward['reward_param2'], $reward['quantity'], [...]);
  360. // 模拟发放结果
  361. $success = true;
  362. $message = '宠物物品发放成功';
  363. return [
  364. 'success' => $success,
  365. 'message' => $message,
  366. 'reward_type' => $reward['reward_type'],
  367. 'reward_param1' => $reward['reward_param1'],
  368. 'reward_param2' => $reward['reward_param2'],
  369. 'quantity' => $reward['quantity'],
  370. ];
  371. }
  372. /**
  373. * 发放农场装饰物奖励
  374. *
  375. * @param int $userId 用户ID
  376. * @param array $reward 奖励信息
  377. * @return array 发放结果
  378. */
  379. protected function distributeFarmDecorationReward(int $userId, array $reward): array
  380. {
  381. // 这里应该调用农场装饰物模块的服务来发放农场装饰物
  382. // 例如:FarmDecorationService::addDecoration($userId, $reward['reward_param1'], $reward['reward_param2'], $reward['quantity'], [...]);
  383. // 模拟发放结果
  384. $success = true;
  385. $message = '农场装饰物发放成功';
  386. return [
  387. 'success' => $success,
  388. 'message' => $message,
  389. 'reward_type' => $reward['reward_type'],
  390. 'reward_param1' => $reward['reward_param1'],
  391. 'reward_param2' => $reward['reward_param2'],
  392. 'quantity' => $reward['quantity'],
  393. ];
  394. }
  395. /**
  396. * 记录奖励发放日志
  397. *
  398. * @param int $userId 用户ID
  399. * @param int $taskId 任务ID
  400. * @param int $userTaskId 用户任务ID
  401. * @param array $rewards 奖励列表
  402. * @param array $results 发放结果
  403. * @return bool 是否成功
  404. */
  405. protected function recordRewardLog(int $userId, int $taskId, int $userTaskId, array $rewards, array $results): bool
  406. {
  407. try {
  408. // 创建奖励日志
  409. $this->rewardLogRepository->create([
  410. 'user_id' => $userId,
  411. 'task_id' => $taskId,
  412. 'user_task_id' => $userTaskId,
  413. 'rewards' => $rewards,
  414. 'rewarded_at' => Carbon::now(),
  415. 'ip_address' => request()->ip(),
  416. 'device_info' => request()->userAgent(),
  417. ]);
  418. return true;
  419. } catch (\Exception $e) {
  420. Log::error('记录奖励发放日志失败', [
  421. 'user_id' => $userId,
  422. 'task_id' => $taskId,
  423. 'user_task_id' => $userTaskId,
  424. 'error' => $e->getMessage(),
  425. ]);
  426. return false;
  427. }
  428. }
  429. /**
  430. * 获取用户的奖励发放历史
  431. *
  432. * @param int $userId 用户ID
  433. * @param int|null $taskId 任务ID(可选)
  434. * @param int $page 页码
  435. * @param int $pageSize 每页数量
  436. * @return array 奖励发放历史
  437. */
  438. public function getUserRewardHistory(int $userId, ?int $taskId = null, int $page = 1, int $pageSize = 10): array
  439. {
  440. try {
  441. // 构建查询
  442. $query = $this->rewardLogRepository->query()
  443. ->where('user_id', $userId);
  444. if ($taskId) {
  445. $query->where('task_id', $taskId);
  446. }
  447. // 分页查询
  448. $total = $query->count();
  449. $logs = $query->orderBy('id', 'desc')
  450. ->forPage($page, $pageSize)
  451. ->get();
  452. return [
  453. 'success' => true,
  454. 'total' => $total,
  455. 'page' => $page,
  456. 'page_size' => $pageSize,
  457. 'logs' => $logs,
  458. ];
  459. } catch (\Exception $e) {
  460. Log::error('获取用户奖励发放历史失败', [
  461. 'user_id' => $userId,
  462. 'task_id' => $taskId,
  463. 'error' => $e->getMessage(),
  464. ]);
  465. return [
  466. 'success' => false,
  467. 'message' => '获取用户奖励发放历史失败: ' . $e->getMessage(),
  468. ];
  469. }
  470. }
  471. }