417 lines
9.3 KiB
PHP
Raw Permalink 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
namespace App\Models\Students;
use App\Models\BaseModel;
use App\Models\Students\StudentClass;
use App\Models\Schools\School;
use App\Models\Schools\SchoolClass;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
/**
* 学生模型
* @package App\Models\Students
* @property int $id 主键ID
* @property string $username 用户名
* @property string|null $real_name 真实姓名
* @property string $password 密码
* @property string $salt 随机串
* @property int $role 所属角色(2学生 3家长)
* @property int $grade_id 年级ID
* @property int $parent_id 家长ID
* @property string|null $email 电子邮件
* @property string|null $phone_number 手机号
* @property string $title 头衔
* @property string $avatar 头像URL
* @property \Carbon\Carbon|null $reg_time 注册时间
* @property string|null $reg_ip 注册IP
* @property int $status 用户状态(0禁用1正常2欠费3未激活)
* @property int $vip_level 常规VIP等级
* @property int $sex 性别(1男2女0不填)
* @property string|null $qq QQ号
* @property string|null $examing_number 考号
*/
class Student extends Authenticatable
{
use HasApiTokens, Notifiable;
/**
* 数据表名
* @var string
*/
protected $table = 'student';
/**
* 主键
* @var string
*/
protected $primaryKey = 'id';
/**
* 关闭自动时间戳
* @var bool
*/
public $timestamps = false;
/**
* 可批量赋值的字段
* @var array
*/
protected $fillable = [
'username',
'real_name',
'password',
'salt',
'role',
'grade_id',
'parent_id',
'email',
'phone_number',
'title',
'avatar',
'reg_time',
'reg_ip',
'status',
'vip_level',
'sex',
'qq',
'examing_number'
];
/**
* 隐藏的字段
* @var array
*/
protected $hidden = [
'password',
'salt',
];
/**
* 字段类型转换
* @var array
*/
protected $casts = [
'reg_time' => 'datetime',
'role' => 'integer',
'grade_id' => 'integer',
'parent_id' => 'integer',
'status' => 'integer',
'vip_level' => 'integer',
'sex' => 'integer',
];
/**
* 角色常量
*/
const ROLE_STUDENT = 2; // 学生
const ROLE_PARENT = 3; // 家长
/**
* 状态常量
*/
const STATUS_DISABLED = 0; // 禁用
const STATUS_NORMAL = 1; // 正常
const STATUS_ARREARS = 2; // 欠费
const STATUS_INACTIVE = 3; // 未激活
/**
* 性别常量
*/
const SEX_UNKNOWN = 0; // 不填
const SEX_MALE = 1; // 男
const SEX_FEMALE = 2; // 女
/**
* 角色映射
* @var array
*/
public static $roleMap = [
self::ROLE_STUDENT => '学生',
self::ROLE_PARENT => '家长',
];
/**
* 状态映射
* @var array
*/
public static $statusMap = [
self::STATUS_DISABLED => '禁用',
self::STATUS_NORMAL => '正常',
self::STATUS_ARREARS => '欠费',
self::STATUS_INACTIVE => '未激活',
];
/**
* 性别映射
* @var array
*/
public static $sexMap = [
self::SEX_UNKNOWN => '不填',
self::SEX_MALE => '男',
self::SEX_FEMALE => '女',
];
/**
* 获取学生班级关联
* @return HasMany
*/
public function studentClasses(): HasMany
{
return $this->hasMany(StudentClass::class, 'student_id', 'id');
}
/**
* 获取学生所属班级(多对多)
* @return BelongsToMany
*/
public function classes(): BelongsToMany
{
return $this->belongsToMany(SchoolClass::class, 'student_class', 'student_id', 'class_id')
->withPivot(['join_time', 'leave_time', 'status', 'remark'])
->withTimestamps();
}
/**
* 获取家长关联(如果是学生)
* @return BelongsTo
*/
public function parent(): BelongsTo
{
return $this->belongsTo(Student::class, 'parent_id', 'id');
}
/**
* 获取子女关联(如果是家长)
* @return HasMany
*/
public function children(): HasMany
{
return $this->hasMany(Student::class, 'parent_id', 'id');
}
/**
* 只查询学生
* @param $query
* @return mixed
*/
public function scopeStudents($query)
{
return $query->where('role', self::ROLE_STUDENT);
}
/**
* 只查询家长
* @param $query
* @return mixed
*/
public function scopeParents($query)
{
return $query->where('role', self::ROLE_PARENT);
}
/**
* 只查询正常状态
* @param $query
* @return mixed
*/
public function scopeNormal($query)
{
return $query->where('status', self::STATUS_NORMAL);
}
/**
* 按年级过滤
* @param $query
* @param int $gradeId
* @return mixed
*/
public function scopeByGrade($query, int $gradeId)
{
return $query->where('grade_id', $gradeId);
}
/**
* 按性别过滤
* @param $query
* @param int $sex
* @return mixed
*/
public function scopeBySex($query, int $sex)
{
return $query->where('sex', $sex);
}
/**
* 获取角色名称
* @return string
*/
public function getRoleNameAttribute(): string
{
return self::$roleMap[$this->role] ?? '未知';
}
/**
* 获取状态名称
* @return string
*/
public function getStatusNameAttribute(): string
{
return self::$statusMap[$this->status] ?? '未知';
}
/**
* 获取性别名称
* @return string
*/
public function getSexNameAttribute(): string
{
return self::$sexMap[$this->sex] ?? '未知';
}
/**
* 获取头像URL如果为空则返回默认头像
* @return string
*/
public function getAvatarUrlAttribute(): string
{
return $this->avatar ?: '/images/default-avatar.png';
}
/**
* 检查是否为学生
* @return bool
*/
public function isStudent(): bool
{
return $this->role === self::ROLE_STUDENT;
}
/**
* 检查是否为家长
* @return bool
*/
public function isParent(): bool
{
return $this->role === self::ROLE_PARENT;
}
/**
* 检查是否为正常状态
* @return bool
*/
public function isNormal(): bool
{
return $this->status === self::STATUS_NORMAL;
}
/**
* 检查是否为男性
* @return bool
*/
public function isMale(): bool
{
return $this->sex === self::SEX_MALE;
}
/**
* 检查是否为女性
* @return bool
*/
public function isFemale(): bool
{
return $this->sex === self::SEX_FEMALE;
}
/**
* 获取当前所在班级
* @return SchoolClass|null
*/
public function getCurrentClass(): ?SchoolClass
{
$studentClass = $this->studentClasses()
->where('status', StudentClass::STATUS_NORMAL)
->whereNull('leave_time')
->first();
return $studentClass ? $studentClass->schoolClass : null;
}
/**
* 获取所有历史班级
* @return \Illuminate\Database\Eloquent\Collection
*/
public function getHistoryClasses()
{
return $this->classes()
->orderBy('student_class.join_time', 'desc')
->get();
}
/**
* 密码加密
* @param string $password
* @param string $salt
* @return string
*/
public static function encryptPassword(string $password, string $salt): string
{
return md5($password . $salt);
}
/**
* 验证密码
* @param string $password
* @return bool
*/
public function verifyPassword(string $password): bool
{
return $this->password === self::encryptPassword($password, $this->salt);
}
/**
* 生成随机盐值
* @return string
*/
public static function generateSalt(): string
{
return substr(md5(time() . mt_rand()), 0, 6);
}
/**
* 获取完整信息(包含班级、家长等)
* @return array
*/
public function getFullInfo(): array
{
$info = $this->toArray();
// 添加角色名称
$info['role_name'] = $this->role_name;
$info['status_name'] = $this->status_name;
$info['sex_name'] = $this->sex_name;
$info['avatar_url'] = $this->avatar_url;
// 添加当前班级信息
$currentClass = $this->getCurrentClass();
$info['current_class'] = $currentClass ? $currentClass->toArray() : null;
// 添加家长信息(如果是学生)
if ($this->isStudent() && $this->parent_id) {
$info['parent'] = $this->parent ? $this->parent->toArray() : null;
}
// 添加子女信息(如果是家长)
if ($this->isParent()) {
$info['children'] = $this->children->toArray();
}
return $info;
}
}