where('item_id', $itemId); // 排除过期物品 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); }); }); } return $query->sum('quantity'); } catch (Exception $e) { throw new Exception("获取用户物品数量失败: " . $e->getMessage(), 0, $e); } } /** * 获取用户实例物品数量 * * @param int $userId 用户ID * @param int $itemId 物品ID * @param int|null $instanceId 实例ID,如果为null则获取所有实例 * @param bool $includeExpired 是否包含已过期物品 * @return int 物品数量 * @throws Exception 如果查询过程中发生错误 */ public static function getUserInstanceItemQuantity(int $userId, int $itemId, ?int $instanceId = null, bool $includeExpired = false): int { try { $query = ItemUser::where('user_id', $userId) ->where('item_id', $itemId) ->whereNotNull('instance_id'); // 如果指定了实例ID,则只查询该实例 if ($instanceId !== null) { $query->where('instance_id', $instanceId); } // 排除过期物品 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); }); }); } return $query->sum('quantity'); } catch (Exception $e) { throw new Exception("获取用户实例物品数量失败: " . $e->getMessage(), 0, $e); } } /** * 获取用户物品总数量(包括普通物品和实例物品) * * @param int $userId 用户ID * @param int $itemId 物品ID * @param bool $includeExpired 是否包含已过期物品 * @return int 物品总数量 * @throws Exception 如果查询过程中发生错误 */ public static function getUserTotalItemQuantity(int $userId, int $itemId, bool $includeExpired = false): int { $normalQuantity = self::getUserItemQuantity($userId, $itemId, $includeExpired); $instanceQuantity = self::getUserInstanceItemQuantity($userId, $itemId, null, $includeExpired); return $normalQuantity + $instanceQuantity; } /** * 检查用户是否拥有足够数量的普通物品 * * @param int $userId 用户ID * @param int $itemId 物品ID * @param int $quantity 需要的数量 * @param bool $includeExpired 是否包含已过期物品 * @return bool 是否拥有足够数量 * @throws Exception 如果查询过程中发生错误 */ public static function hasEnoughItems(int $userId, int $itemId, int $quantity, bool $includeExpired = false): bool { $userQuantity = self::getUserItemQuantity($userId, $itemId, $includeExpired); return $userQuantity >= $quantity; } /** * 检查用户是否拥有指定的实例物品 * * @param int $userId 用户ID * @param int $itemId 物品ID * @param int $instanceId 实例ID * @param bool $includeExpired 是否包含已过期物品 * @return bool 是否拥有该实例物品 * @throws Exception 如果查询过程中发生错误 */ public static function hasInstanceItem(int $userId, int $itemId, int $instanceId, bool $includeExpired = false): bool { $quantity = self::getUserInstanceItemQuantity($userId, $itemId, $instanceId, $includeExpired); return $quantity > 0; } /** * 检查用户是否拥有足够数量的物品(包括普通物品和实例物品) * * @param int $userId 用户ID * @param int $itemId 物品ID * @param int $quantity 需要的数量 * @param bool $includeExpired 是否包含已过期物品 * @return bool 是否拥有足够数量 * @throws Exception 如果查询过程中发生错误 */ public static function hasEnoughTotalItems(int $userId, int $itemId, int $quantity, bool $includeExpired = false): bool { $totalQuantity = self::getUserTotalItemQuantity($userId, $itemId, $includeExpired); return $totalQuantity >= $quantity; } }