| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- <?php
- namespace App\Module\GameItems\Services;
- use App\Module\GameItems\Dtos\ItemDto;
- use App\Module\GameItems\Dtos\ItemUserDto;
- use App\Module\GameItems\Logics\Item as ItemLogic;
- use App\Module\GameItems\Logics\ItemQuantity;
- use App\Module\GameItems\Models\Item;
- use App\Module\GameItems\Models\ItemUser;
- use Exception;
- use Illuminate\Support\Collection as SupportCollection;
- use UCore\Db\Helper;
- use UCore\Dto\Res;
- /**
- * 物品服务类
- *
- * 提供物品相关的服务,包括获取用户物品、添加物品到用户背包、消耗用户物品等功能。
- * 该类是物品模块对外提供服务的主要入口,封装了物品操作的复杂逻辑,
- * 通过调用ItemLogic类实现具体的业务逻辑处理。
- *
- * 所有方法均为静态方法,可直接通过类名调用。
- */
- class ItemService
- {
- /**
- * 获取用户物品列表
- *
- * @param int $userId 用户ID
- * @param array $filters 过滤条件
- * @param bool $includeExpired 是否包含已过期物品
- * @return SupportCollection|ItemUserDto[] 用户物品DTO集合
- */
- public static function getUserItems(int $userId, array $filters = [], bool $includeExpired = false): SupportCollection
- {
- $query = ItemUser::where('user_id', $userId)
- ->with(['item', 'instance']);
- // 应用过滤条件
- if (isset($filters['item_id'])) {
- $query->where('item_id', $filters['item_id']);
- }
- if (isset($filters['category_id'])) {
- $query->whereHas('item', function ($q) use ($filters) {
- $q->where('category_id', $filters['category_id']);
- });
- }
- if (isset($filters['type'])) {
- $query->whereHas('item', function ($q) use ($filters) {
- $q->where('type', $filters['type']);
- });
- }
- // 排除过期物品
- if (!$includeExpired) {
- $now = now();
- $query->where(function ($q) use ($now) {
- $q->whereNull('expire_at')
- ->orWhere('expire_at', '>', $now);
- })->whereHas('item', function ($q) use ($now) {
- $q->where(function ($subQ) use ($now) {
- $subQ->whereNull('global_expire_at')
- ->orWhere('global_expire_at', '>', $now);
- });
- });
- }
- // 获取模型集合
- $itemUsers = $query->get();
- // 转换为DTO集合
- return $itemUsers->map(function (ItemUser $itemUser) {
- return ItemUserDto::fromModel($itemUser);
- });
- }
- /**
- * 添加物品到用户背包
- *
- * @param int $userId 用户ID
- * @param int $itemId 物品ID
- * @param int $quantity 数量
- * @param array $options 选项
- * @return array 添加结果
- * @throws Exception
- */
- public static function addItem(int $userId, int $itemId, int $quantity, array $options = []): array
- {
- // 获取物品信息
- $item = Item::findOrFail($itemId);
- // 检查物品是否已过期(全局过期)
- if (ItemLogic::isExpired($item)) {
- throw new Exception("物品 {$itemId} 已全局过期");
- }
- // 处理单独属性物品
- if ($item->is_unique) {
- return ItemLogic::addUniqueItem($userId, $itemId, $options);
- }
- // 处理统一属性物品
- return ItemLogic::addNormalItem($userId, $itemId, $quantity, $options);
- }
- /**
- * 消耗用户物品
- *
- * @param int $userId 用户ID
- * @param int $itemId 物品ID
- * @param int|null $instanceId 物品实例ID(单独属性物品)
- * @param int $quantity 数量
- * @param array $options 选项
- * @return array 消耗结果
- * @throws Exception
- */
- public static function consumeItem(int $userId, int $itemId, ?int $instanceId, int $quantity, array $options = []): array
- {
- Helper::check_tr();
- // 获取物品信息(确保物品存在)
- Item::findOrFail($itemId);
- if ($instanceId) {
- // 消耗单独属性物品
- return ItemLogic::consumeUniqueItem($userId, $itemId, $instanceId, $options);
- } else {
- // 消耗统一属性物品
- return ItemLogic::consumeNormalItem($userId, $itemId, $quantity, $options);
- }
- }
- /**
- * 获取物品信息
- *
- * @param int $itemId 物品ID
- * @return ItemDto|null 物品信息DTO
- */
- public static function getItemInfo(int $itemId): ?ItemDto
- {
- $item = Item::find($itemId);
- if (!$item) {
- return null;
- }
- return ItemDto::fromModel($item);
- }
- /**
- * 获取物品数值属性
- *
- * @param int $itemId 物品ID
- * @param string $attributeName 属性名称
- * @param int $defaultValue 默认值
- * @return int 属性值
- */
- public static function getItemNumericAttribute(int $itemId, string $attributeName, int $defaultValue = 0): int
- {
- /**
- * @var Item $item
- */
- $item = Item::find($itemId);
- if (!$item) {
- return $defaultValue;
- }
- $numericAttributes = (array)$item->numeric_attributes;
- return $numericAttributes[$attributeName] ?? $defaultValue;
- }
- /**
- * 验证用户是否拥有足够数量的物品
- *
- * @param int $userId 用户ID
- * @param int $itemId 物品ID
- * @param int $quantity 需要的数量
- * @param int|null $instanceId 物品实例ID(可选,用于验证特定实例物品)
- * @param bool $includeAllTypes 是否包含所有类型的物品(普通物品和实例物品)
- * @param bool $includeExpired 是否包含已过期物品
- * @return Res 验证结果
- */
- public static function checkItemQuantity(int $userId, int $itemId, int $quantity, ?int $instanceId = null, bool $includeAllTypes = false, bool $includeExpired = false): Res
- {
- try {
- // 获取物品信息
- $item = Item::find($itemId);
- if (!$item) {
- return Res::error("物品不存在(ID: {$itemId})");
- }
- // 检查物品是否已过期(全局过期)
- if (ItemLogic::isExpired($item)) {
- return Res::error("物品已全局过期(ID: {$itemId})");
- }
- // 根据不同情况进行验证
- if ($instanceId !== null) {
- // 验证特定实例物品
- $hasInstance = ItemQuantity::hasInstanceItem($userId, $itemId, $instanceId, $includeExpired);
- if (!$hasInstance) {
- return Res::error("用户不拥有指定的实例物品(ID: {$instanceId})");
- }
- return Res::success("用户拥有指定的实例物品");
- } else if ($includeAllTypes) {
- // 验证所有类型物品(普通物品和实例物品)的总数量
- $totalQuantity = ItemQuantity::getUserTotalItemQuantity($userId, $itemId, $includeExpired);
- if ($totalQuantity < $quantity) {
- return Res::error("物品总数量不足,需要{$quantity}个,但只有{$totalQuantity}个", [
- 'required' => $quantity,
- 'available' => $totalQuantity
- ]);
- }
- return Res::success("物品总数量足够", [
- 'quantity' => $totalQuantity,
- 'required' => $quantity
- ]);
- } else {
- // 只验证普通物品数量
- $normalQuantity = ItemQuantity::getUserItemQuantity($userId, $itemId, $includeExpired);
- if ($normalQuantity < $quantity) {
- return Res::error("普通物品数量不足,需要{$quantity}个,但只有{$normalQuantity}个", [
- 'required' => $quantity,
- 'available' => $normalQuantity
- ]);
- }
- return Res::success("普通物品数量足够", [
- 'quantity' => $normalQuantity,
- 'required' => $quantity
- ]);
- }
- } catch (Exception $e) {
- return Res::error("验证物品数量时发生错误: " . $e->getMessage(), [
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString()
- ]);
- }
- }
- }
|