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 { $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() ]); } } }