User.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. namespace App\Models;
  3. // use Illuminate\Contracts\Auth\MustVerifyEmail;
  4. use Filament\Models\Contracts\FilamentUser;
  5. use Filament\Models\Contracts\HasName;
  6. use Filament\Panel;
  7. use Illuminate\Database\Eloquent\Factories\HasFactory;
  8. use Illuminate\Foundation\Auth\User as Authenticatable;
  9. use Illuminate\Notifications\Notifiable;
  10. class User extends Authenticatable implements FilamentUser, HasName
  11. {
  12. /** @use HasFactory<\Database\Factories\UserFactory> */
  13. use HasFactory, Notifiable;
  14. /**
  15. * The table associated with the model.
  16. *
  17. * @var string
  18. */
  19. protected $table = 'users';
  20. /**
  21. * The primary key associated with the table.
  22. *
  23. * @var string
  24. */
  25. protected $primaryKey = 'id';
  26. /**
  27. * Indicates if the model's ID is auto-incrementing.
  28. *
  29. * @var bool
  30. */
  31. public $incrementing = true;
  32. /**
  33. * The data type of the primary key ID.
  34. *
  35. * @var string
  36. */
  37. protected $keyType = 'int';
  38. /**
  39. * The attributes that are mass assignable.
  40. *
  41. * @var list<string>
  42. */
  43. protected $fillable = [
  44. 'id',
  45. 'user_id',
  46. 'username', // 手机号作为登录名(必填)
  47. 'email', // 邮箱(可选)
  48. 'phone', // 手机号(备用)
  49. 'password',
  50. 'password_hash',
  51. 'full_name',
  52. 'role',
  53. 'department',
  54. 'is_active',
  55. 'remember_token',
  56. 'last_login',
  57. 'login_count',
  58. 'deleted_at',
  59. ];
  60. /**
  61. * The attributes that should be hidden for serialization.
  62. *
  63. * @var list<string>
  64. */
  65. protected $hidden = [
  66. 'password_hash',
  67. 'remember_token',
  68. ];
  69. /**
  70. * Get the attributes that should be cast.
  71. *
  72. * @return array<string, string>
  73. */
  74. protected function casts(): array
  75. {
  76. return [
  77. 'email_verified_at' => 'datetime',
  78. 'is_active' => 'boolean',
  79. ];
  80. }
  81. public function canAccessPanel(?Panel $panel): bool
  82. {
  83. // 只有激活的用户才能访问面板
  84. return $this->is_active === true;
  85. }
  86. /**
  87. * Get the password for authentication.
  88. */
  89. public function getAuthPassword(): string
  90. {
  91. return (string) $this->password_hash;
  92. }
  93. /**
  94. * Get the username for authentication.
  95. */
  96. public function getAuthIdentifierName(): string
  97. {
  98. return 'username';
  99. }
  100. /**
  101. * Retrieve the unique identifier for the user.
  102. */
  103. public function getAuthIdentifier(): mixed
  104. {
  105. return $this->username;
  106. }
  107. /**
  108. * Get the password attribute (for compatibility).
  109. */
  110. public function getPasswordAttribute(): string
  111. {
  112. return $this->password_hash;
  113. }
  114. /**
  115. * Set the password attribute (for compatibility).
  116. */
  117. public function setPasswordAttribute(string $value): void
  118. {
  119. $this->attributes['password_hash'] = $value;
  120. }
  121. /**
  122. * Get the name to display for the user in Filament.
  123. * This fixes the TypeError where getUserName() expected string but got null.
  124. */
  125. public function getFilamentName(): string
  126. {
  127. return $this->full_name ?: $this->username ?: $this->email ?: 'Unknown User';
  128. }
  129. /**
  130. * Retrieve a user by their credentials.
  131. * Override this to use username instead of email for authentication.
  132. */
  133. public function retrieveByCredentials(array $credentials)
  134. {
  135. if (empty($credentials)) {
  136. return null;
  137. }
  138. // Check if the credentials array has 'username' key
  139. if (isset($credentials['username'])) {
  140. return static::where('username', $credentials['username'])->first();
  141. }
  142. // Fallback to default behavior for other credentials
  143. foreach ($credentials as $key => $value) {
  144. if (in_array($key, ['password', 'remember_token'])) {
  145. continue;
  146. }
  147. if (method_exists(static::class, $key)) {
  148. if ($this->{$key}() instanceof \Illuminate\Database\Eloquent\Relations\BelongsTo) {
  149. if ($this->{$key}()->getRelated()->where($key, $value)->exists()) {
  150. return $this;
  151. }
  152. } else {
  153. if (static::where($key, $value)->exists()) {
  154. return static::where($key, $value)->first();
  155. }
  156. }
  157. }
  158. }
  159. return null;
  160. }
  161. /**
  162. * 获取用户的老师信息(如果当前用户是老师)
  163. */
  164. public function teacher(): \Illuminate\Database\Eloquent\Relations\HasOne
  165. {
  166. return $this->hasOne(Teacher::class, 'user_id', 'user_id');
  167. }
  168. /**
  169. * 检查当前用户是否是老师
  170. */
  171. public function isTeacher(): bool
  172. {
  173. return $this->teacher()->exists();
  174. }
  175. /**
  176. * 获取当前登录用户的teacher_id(如果没有则返回null)
  177. */
  178. public static function getCurrentTeacherId(): ?int
  179. {
  180. $user = auth()->user();
  181. if (!$user) {
  182. return null;
  183. }
  184. $teacher = $user->teacher;
  185. return $teacher?->teacher_id;
  186. }
  187. }