Files
chatroom/app/Models/User.php

247 lines
6.4 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
/**
* 文件功能:主用户模型
*
* 对应原 ASP 文件user 表
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'username',
'password',
'email',
'sex',
'sign',
'user_level',
'inviter_id',
'room_id',
'first_ip',
'previous_ip',
'last_ip',
'usersf',
'vip_level_id',
'hy_time',
'question',
'answer',
'has_received_new_gift',
'in_time', // 进房时间(用于勤务日志 login_at 基准)
'out_time', // 离房时间
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
'temppass',
'ppass',
'userpassword',
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'log_time' => 'datetime',
'in_time' => 'datetime',
'out_time' => 'datetime',
'hy_time' => 'datetime',
'xr_time' => 'datetime',
'yx_time' => 'datetime',
'sj' => 'datetime',
'q3_time' => 'datetime',
'has_received_new_gift' => 'boolean',
];
}
/**
* 头像文件名访问器
*
* 原 ASP 系统的头像文件名存储在 usersf 字段中(如 "75.gif"
* 同时也支持用户自定义上传的头像,保存在 Laravel Storage 的 public 磁盘下。
* 此 accessor 将 headface 属性映射到 usersf 字段,如果包含 storage/ 则当作独立路径,自动转换旧版后缀小写。
*/
protected function headface(): Attribute
{
return Attribute::make(
get: function () {
$val = $this->usersf ?: '1.gif';
if (str_starts_with($val, 'storage/')) {
return $val;
}
// 仅对非 storage 下的旧头像做小写处理,兼容旧库数据
return strtolower($val);
},
set: function ($value) {
if (str_starts_with($value, 'storage/')) {
return tap($value, fn () => $this->attributes['usersf'] = $value);
}
return tap(strtolower($value), fn () => $this->attributes['usersf'] = strtolower($value));
}
);
}
/**
* 获取带前缀的完整头像 URL
* 避免前端多处硬编码 '/images/headface/'
*/
protected function headfaceUrl(): Attribute
{
return Attribute::make(
get: function () {
$hf = $this->headface;
if (str_starts_with((string) $hf, 'storage/')) {
return '/'.$hf;
}
return '/images/headface/'.$hf;
}
);
}
/**
* 如果当前头像是自定义上传的图片,则从本地存储中删除此文件
*/
public function deleteCustomAvatar(): void
{
$hf = (string) $this->usersf;
if (str_starts_with($hf, 'storage/')) {
$path = substr($hf, 8); // 去除 'storage/' 前缀
\Illuminate\Support\Facades\Storage::disk('public')->delete($path);
}
}
/**
* 关联:用户所属的 VIP 会员等级
*/
public function vipLevel(): BelongsTo
{
return $this->belongsTo(VipLevel::class, 'vip_level_id');
}
/**
* 判断用户是否为有效 VIP有等级且未过期
*/
public function isVip(): bool
{
if (! $this->vip_level_id) {
return false;
}
// hy_time 为 null 表示永久会员
if (! $this->hy_time) {
return true;
}
return $this->hy_time->isFuture();
}
/**
* 获取 VIP 会员名称(无效则返回空字符串)
*/
public function vipName(): string
{
if (! $this->isVip()) {
return '';
}
return $this->vipLevel?->name ?? '';
}
/**
* 获取 VIP 会员图标(无效则返回空字符串)
*/
public function vipIcon(): string
{
if (! $this->isVip()) {
return '';
}
return $this->vipLevel?->icon ?? '';
}
// ── 职务相关关联 ──────────────────────────────────────────────────────
/**
* 全部猎务履历(包括历史记录)
*/
public function positions(): HasMany
{
return $this->hasMany(UserPosition::class)->with(['position.department'])->orderByDesc('appointed_at');
}
/**
* 当前在职职务记录HasOne最多一条
*/
public function activePosition(): HasOne
{
return $this->hasOne(UserPosition::class)->where('is_active', true)->with(['position.department']);
}
/**
* 该用户在职期间的权限操作日志
*/
public function authorityLogs(): HasMany
{
return $this->hasMany(PositionAuthorityLog::class)->orderByDesc('created_at');
}
/**
* 判断用户是否有当前在职职务
*/
public function hasActivePosition(): bool
{
return $this->activePosition()->exists();
}
/**
* 关联:邀请当前用户的人
*/
public function inviter(): BelongsTo
{
return $this->belongsTo(self::class, 'inviter_id');
}
/**
* 关联:当前用户邀请的所有人
*/
public function invitees(): HasMany
{
return $this->hasMany(self::class, 'inviter_id');
}
}