You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.7 KiB

3 days ago
<?php
namespace App\Models;
2 days ago
use Illuminate\Database\Eloquent\Builder;
3 days ago
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Venue extends Model
{
use HasFactory;
protected $fillable = [
'name',
'venue_type',
2 days ago
'venue_types',
3 days ago
'unit_name',
'district',
'ticket_type',
2 days ago
'appointment_type',
2 days ago
'open_mode',
3 days ago
'open_time',
'reservation_notice',
1 day ago
'ticket_content',
'booking_method',
'visit_form',
'consultation_hours',
3 days ago
'address',
2 days ago
'contact_phone',
3 days ago
'lat',
'lng',
'cover_image',
'gallery_media',
'detail_html',
'live_people_count',
'sort',
'is_active',
2 days ago
'audit_status',
'audit_remark',
'last_approved_snapshot',
];
public const AUDIT_APPROVED = 'approved';
public const AUDIT_PENDING = 'pending';
public const AUDIT_REJECTED = 'rejected';
/** @var list<string> */
public const SNAPSHOT_KEYS = [
'name', 'venue_type', 'venue_types', 'unit_name', 'district', 'ticket_type',
1 day ago
'appointment_type', 'open_mode', 'open_time', 'reservation_notice',
'ticket_content', 'booking_method', 'visit_form', 'consultation_hours',
2 days ago
'address', 'contact_phone', 'lat', 'lng', 'cover_image', 'gallery_media',
'detail_html', 'live_people_count', 'sort', 'is_active',
3 days ago
];
protected $casts = [
'is_active' => 'boolean',
'gallery_media' => 'array',
2 days ago
'venue_types' => 'array',
3 days ago
'lat' => 'float',
'lng' => 'float',
'sort' => 'integer',
'live_people_count' => 'integer',
2 days ago
'last_approved_snapshot' => 'array',
3 days ago
];
2 days ago
/**
* H5 仅展示已启用且审核通过的场馆(待审核、已退回均不展示)。
*/
public function scopeVisibleOnH5(Builder $query): Builder
{
return $query
->where('is_active', true)
->where('audit_status', self::AUDIT_APPROVED);
}
/**
* @return array<string, mixed>|null
*/
public function toH5Payload(): ?array
{
if ($this->audit_status !== self::AUDIT_APPROVED || ! $this->is_active) {
return null;
}
return $this->toArray();
}
/**
* 场馆管理员修改「已通过」记录前,保存用于 H5 继续展示的旧数据。
*
* @return array<string, mixed>
*/
public function buildAuditSnapshot(): array
{
$out = [];
foreach (self::SNAPSHOT_KEYS as $k) {
$out[$k] = $this->getAttribute($k);
}
return $out;
}
2 days ago
protected static function booted(): void
{
static::saving(function (Venue $v) {
$types = $v->venue_types;
if (is_array($types) && count($types)) {
$clean = array_values(array_filter(array_map('strval', $types), fn ($s) => $s !== ''));
$v->venue_types = $clean;
$v->venue_type = $clean[0] ?? null;
} elseif (! empty($v->venue_type)) {
$v->venue_types = [$v->venue_type];
} else {
$v->venue_type = null;
$v->venue_types = null;
}
});
}
public function activities(): HasMany
{
return $this->hasMany(Activity::class);
}
3 days ago
public function admins(): BelongsToMany
{
return $this->belongsToMany(User::class, 'user_venue')->withTimestamps();
}
public function reservations(): HasMany
{
return $this->hasMany(Reservation::class);
}
}