getShopItems($filters); // 批量获取用户购买数量,避免N+1查询 $userBoughtCounts = []; if ($userId !== null && $shopItems->isNotEmpty()) { $shopItemIds = $shopItems->pluck('id')->toArray(); $userBoughtCounts = \App\Module\Shop\Models\ShopPurchaseLog::where('user_id', $userId) ->whereIn('shop_item_id', $shopItemIds) ->groupBy('shop_item_id') ->selectRaw('shop_item_id, SUM(quantity) as total_quantity') ->pluck('total_quantity', 'shop_item_id') ->toArray(); } // 将模型集合转换为DTO数组 return $shopItems->map(function ($shopItem) use ($userId, $userBoughtCounts) { return ShopItemDto::fromModelOptimized($shopItem, $userId, $userBoughtCounts); })->values()->all(); } /** * 获取商店分类列表 * * @param bool $onlyActive 是否只获取激活的分类 * @return array ShopCategoryDto数组 */ public static function getShopCategories(bool $onlyActive = true): array { $shopLogic = new ShopLogic(); $categories = $shopLogic->getShopCategories($onlyActive); // 将模型集合转换为DTO数组 return $categories->map(function ($category) { return ShopCategoryDto::fromModel($category); })->values()->all(); } /** * 获取商店分类树 * * @param bool $onlyActive 是否只获取激活的分类 * @return array 分类树 */ public static function getShopCategoryTree(bool $onlyActive = true): array { $shopLogic = new ShopLogic(); return $shopLogic->getShopCategoryTree($onlyActive); } /** * 购买商品 * 注意:由于商品结构变更,此方法需要根据消耗组和奖励组重新实现 * * @param int $userId 用户ID * @param int $shopItemId 商品ID * @param int $quantity 购买数量 * @param array $options 选项 * @return array|bool 购买结果或失败标志 */ public static function buyShopItem(int $userId, int $shopItemId, int $quantity = 1, array $options = []) { try { // 获取商品信息 $shopItem = ShopItem::with(['consumeGroup', 'rewardGroup'])->findOrFail($shopItemId); // 检查购买限制 $shopLogic = new ShopLogic(); list($canBuy, $errorMessage) = $shopLogic->checkBuyLimit($userId, $shopItem, $quantity); if (!$canBuy) { throw new LogicException($errorMessage); } // 开始事务 DB::beginTransaction(); // TODO: 实现消耗组逻辑 - 扣除用户资源 if ($shopItem->consumeGroup) { // 这里需要实现消耗组的扣除逻辑 // $consumeResult = ConsumeService::consume($userId, $shopItem->consume_group_id, $quantity); // if (!$consumeResult) { // throw new LogicException("资源不足"); // } } // TODO: 实现奖励组逻辑 - 给予用户奖励 $rewardResults = []; if ($shopItem->rewardGroup) { // 这里需要实现奖励组的发放逻辑 // $rewardResults = RewardService::giveReward($userId, $shopItem->reward_group_id, $quantity); } // 记录购买记录 $purchaseLog = $shopLogic->recordPurchase($userId, $shopItem, $quantity, 0); // 总价暂时为0 // 触发商品购买事件 event(new ShopItemPurchased($userId, $shopItem, $quantity, 0, $purchaseLog->id)); // 提交事务 DB::commit(); // 返回结果 return [ 'success' => true, 'shop_item' => [ 'id' => $shopItem->id, 'name' => $shopItem->name, 'consume_group' => $shopItem->consumeGroup ? $shopItem->consumeGroup->name : null, 'reward_group' => $shopItem->rewardGroup ? $shopItem->rewardGroup->name : null ], 'rewards' => $rewardResults, 'purchase_log_id' => $purchaseLog->id ]; } catch (Exception $e) { // 回滚事务 if (DB::transactionLevel() > 0) { DB::rollBack(); } Log::error('购买商品失败', [ 'user_id' => $userId, 'shop_item_id' => $shopItemId, 'quantity' => $quantity, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return false; } } /** * 获取用户购买记录 * * @param int $userId 用户ID * @param array $filters 过滤条件 * @return Collection 购买记录 */ public static function getUserPurchaseHistory(int $userId, array $filters = []): Collection { $shopLogic = new ShopLogic(); return $shopLogic->getUserPurchaseHistory($userId, $filters); } /** * 获取商品详情 * * @param int $shopItemId 商品ID * @param int|null $userId 用户ID(可选,用于获取用户购买数量) * @return ShopItemDto|null 商品详情DTO */ public static function getShopItemDetail(int $shopItemId, ?int $userId = null): ?ShopItemDto { $shopItem = ShopItem::with(['category', 'consumeGroup', 'rewardGroup', 'promotions'])->find($shopItemId); if (!$shopItem) { return null; } return ShopItemDto::fromModel($shopItem, $userId); } /** * 获取促销活动列表 * * @param array $filters 过滤条件 * @return Collection 促销活动列表 */ public static function getPromotions(array $filters = []): Collection { $shopLogic = new ShopLogic(); return $shopLogic->getPromotions($filters); } /** * 获取促销活动详情 * * @param int $promotionId 促销活动ID * @return ShopPromotion|null 促销活动详情 */ public static function getPromotionDetail(int $promotionId): ?ShopPromotion { $shopLogic = new ShopLogic(); return $shopLogic->getPromotionDetail($promotionId); } /** * 添加商品到促销活动 * * @param int $promotionId 促销活动ID * @param int $shopItemId 商品ID * @param int|null $customDiscountValue 自定义折扣值 * @return ShopPromotionItem 促销商品关联 */ public static function addItemToPromotion(int $promotionId, int $shopItemId, ?int $customDiscountValue = null): ShopPromotionItem { $shopLogic = new ShopLogic(); return $shopLogic->addItemToPromotion($promotionId, $shopItemId, $customDiscountValue); } /** * 从促销活动中移除商品 * * @param int $promotionId 促销活动ID * @param int $shopItemId 商品ID * @return bool 是否成功 */ public static function removeItemFromPromotion(int $promotionId, int $shopItemId): bool { $shopLogic = new ShopLogic(); return $shopLogic->removeItemFromPromotion($promotionId, $shopItemId); } /** * 获取商品的价格信息 * 注意:由于商品不再有固定价格,此方法需要根据消耗组重新实现 * * @param int $shopItemId 商品ID * @return array 价格信息 */ public static function getItemPriceInfo(int $shopItemId): array { $shopItem = ShopItem::with(['consumeGroup', 'rewardGroup'])->findOrFail($shopItemId); $promotion = $shopItem->getActivePromotion(); return [ 'consume_group' => $shopItem->consumeGroup ? [ 'id' => $shopItem->consumeGroup->id, 'name' => $shopItem->consumeGroup->name, 'description' => $shopItem->consumeGroup->description ] : null, 'reward_group' => $shopItem->rewardGroup ? [ 'id' => $shopItem->rewardGroup->id, 'name' => $shopItem->rewardGroup->name, 'description' => $shopItem->rewardGroup->description ] : null, 'promotion' => $promotion ? [ 'id' => $promotion->id, 'name' => $promotion->name, 'discount_type' => $promotion->discount_type, 'discount_value' => $promotion->discount_value, 'end_time' => $promotion->end_time ? $promotion->end_time->toDateTimeString() : null ] : null ]; } }