'integer', 'period_type' => 'integer', 'period_value' => 'integer', 'is_active' => 'boolean', ]; /** * 限制类型常量 */ const LIMIT_TYPE_GLOBAL = 1; // 全局限制 const LIMIT_TYPE_USER = 2; // 用户限制 const LIMIT_TYPE_DAILY = 3; // 每日限制 const LIMIT_TYPE_WEEKLY = 4; // 每周限制 const LIMIT_TYPE_MONTHLY = 5; // 每月限制 /** * 获取关联的物品 * * @return BelongsTo */ public function item(): BelongsTo { return $this->belongsTo(Item::class, 'item_id'); } /** * 获取用户产出限制计数 * * @return HasMany */ public function userCounters(): HasMany { return $this->hasMany(ItemUserOutputCounter::class, 'limit_id'); } /** * 检查是否达到全局限制 * * @return bool */ public function isGlobalLimitReached(): bool { if ($this->limit_type != self::LIMIT_TYPE_GLOBAL) { return false; } $totalCount = ItemUserOutputCounter::where('limit_id', $this->id) ->sum('current_count'); return $totalCount >= $this->max_quantity; } /** * 检查用户是否达到限制 * * @param int $userId 用户ID * @return bool */ public function isUserLimitReached(int $userId): bool { if ($this->limit_type == self::LIMIT_TYPE_GLOBAL) { return $this->isGlobalLimitReached(); } $counter = ItemUserOutputCounter::where('limit_id', $this->id) ->where('user_id', $userId) ->first(); if (!$counter) { return false; } return $counter->current_count >= $this->max_quantity; } /** * 增加计数 * * @param int $userId 用户ID * @param int $count 增加的数量 * @return bool */ public function incrementCount(int $userId, int $count = 1): bool { $counter = ItemUserOutputCounter::firstOrCreate( [ 'limit_id' => $this->id, 'user_id' => $userId, ], [ 'current_count' => 0, 'last_reset_time' => now(), ] ); // 检查是否需要重置计数 if ($this->shouldResetCounter($counter)) { $counter->current_count = 0; $counter->last_reset_time = now(); } $counter->current_count += $count; return $counter->save(); } /** * 检查是否应该重置计数器 * * @param ItemUserOutputCounter $counter 计数器 * @return bool */ protected function shouldResetCounter(ItemUserOutputCounter $counter): bool { if (empty($counter->last_reset_time)) { return true; } switch ($this->limit_type) { case self::LIMIT_TYPE_DAILY: return $counter->last_reset_time->diffInDays(now()) >= 1; case self::LIMIT_TYPE_WEEKLY: return $counter->last_reset_time->diffInWeeks(now()) >= 1; case self::LIMIT_TYPE_MONTHLY: return $counter->last_reset_time->diffInMonths(now()) >= 1; default: return false; } } }