Files
chatroom/app/Models/MysteryBox.php

126 lines
3.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:神秘箱子模型
*
* 管理聊天室内投放的神秘箱记录,提供领取状态管理及类型标签工具方法。
* 对应表mystery_boxes
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
class MysteryBox extends Model
{
protected $fillable = [
'box_type',
'passcode',
'reward_min',
'reward_max',
'status',
'expires_at',
'dropped_by',
];
/**
* 属性类型转换。
*/
protected function casts(): array
{
return [
'reward_min' => 'integer',
'reward_max' => 'integer',
'expires_at' => 'datetime',
];
}
// ─── 关联关系 ────────────────────────────────────────────────────
/**
* 领取记录(一个箱子只能被一人领取,但关联为 HasOne
*/
public function claim(): HasOne
{
return $this->hasOne(MysteryBoxClaim::class);
}
/**
* 所有领取记录(逻辑上只有一条,保留 HasMany 供统计使用)
*/
public function claims(): HasMany
{
return $this->hasMany(MysteryBoxClaim::class);
}
// ─── 查询作用域 ──────────────────────────────────────────────────
/**
* 当前可领取open 状态 + 未过期)的箱子。
*/
public static function currentOpenBox(): ?static
{
return static::query()
->where('status', 'open')
->where(fn ($q) => $q->whereNull('expires_at')->orWhere('expires_at', '>', now()))
->latest()
->first();
}
// ─── 工具方法 ────────────────────────────────────────────────────
/**
* 返回箱子类型的 emoji 前缀。
*/
public function typeEmoji(): string
{
return match ($this->box_type) {
'normal' => '📦',
'rare' => '💎',
'trap' => '☠️',
default => '📦',
};
}
/**
* 返回箱子类型中文名称。
*/
public function typeName(): string
{
return match ($this->box_type) {
'normal' => '普通箱',
'rare' => '稀有箱',
'trap' => '黑化箱',
default => '神秘箱',
};
}
/**
* 随机生成奖励金额trap 类型为负数)。
*/
public function rollReward(): int
{
$amount = random_int(
min(abs($this->reward_min), abs($this->reward_max)),
max(abs($this->reward_min), abs($this->reward_max)),
);
// trap 类型:倒扣金币(负数)
return $this->box_type === 'trap' ? -$amount : $amount;
}
/**
* 判断箱子是否已过期
*/
public function isExpired(): bool
{
return $this->expires_at !== null && $this->expires_at->isPast();
}
}