2023-11-17 14:44:01 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
2025-05-07 19:48:19 +08:00
|
|
|
use App\Utils\Helper;
|
2025-01-21 14:57:54 +08:00
|
|
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
2023-12-08 15:43:17 +08:00
|
|
|
use Laravel\Sanctum\HasApiTokens;
|
2025-05-07 19:48:19 +08:00
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
2023-11-17 14:44:01 +08:00
|
|
|
|
2025-05-07 19:48:19 +08:00
|
|
|
/**
|
|
|
|
|
* App\Models\User
|
|
|
|
|
*
|
|
|
|
|
* @property int $id 用户ID
|
|
|
|
|
* @property string $email 邮箱
|
|
|
|
|
* @property string $password 密码
|
|
|
|
|
* @property string|null $password_algo 加密方式
|
|
|
|
|
* @property string|null $password_salt 加密盐
|
|
|
|
|
* @property string $token 邀请码
|
|
|
|
|
* @property string $uuid
|
|
|
|
|
* @property int|null $invite_user_id 邀请人
|
|
|
|
|
* @property int|null $plan_id 订阅ID
|
|
|
|
|
* @property int|null $group_id 权限组ID
|
|
|
|
|
* @property int|null $transfer_enable 流量(KB)
|
|
|
|
|
* @property int|null $speed_limit 限速Mbps
|
|
|
|
|
* @property int|null $u 上行流量
|
|
|
|
|
* @property int|null $d 下行流量
|
|
|
|
|
* @property int|null $banned 是否封禁
|
|
|
|
|
* @property int|null $remind_expire 到期提醒
|
|
|
|
|
* @property int|null $remind_traffic 流量提醒
|
|
|
|
|
* @property int|null $expired_at 过期时间
|
|
|
|
|
* @property int|null $balance 余额
|
|
|
|
|
* @property int|null $commission_balance 佣金余额
|
|
|
|
|
* @property float $commission_rate 返佣比例
|
2025-07-14 00:33:04 +08:00
|
|
|
* @property int|null $commission_type 返佣类型
|
2025-05-07 19:48:19 +08:00
|
|
|
* @property int|null $device_limit 设备限制数量
|
|
|
|
|
* @property int|null $discount 折扣
|
|
|
|
|
* @property int|null $last_login_at 最后登录时间
|
|
|
|
|
* @property int|null $parent_id 父账户ID
|
|
|
|
|
* @property int|null $is_admin 是否管理员
|
2025-06-22 17:38:17 +08:00
|
|
|
* @property int|null $next_reset_at 下次流量重置时间
|
|
|
|
|
* @property int|null $last_reset_at 上次流量重置时间
|
2025-07-26 18:49:58 +08:00
|
|
|
* @property int|null $telegram_id Telegram ID
|
2025-06-22 01:18:38 +08:00
|
|
|
* @property int $reset_count 流量重置次数
|
2025-05-07 19:48:19 +08:00
|
|
|
* @property int $created_at
|
|
|
|
|
* @property int $updated_at
|
|
|
|
|
* @property bool $commission_auto_check 是否自动计算佣金
|
|
|
|
|
*
|
|
|
|
|
* @property-read User|null $invite_user 邀请人信息
|
|
|
|
|
* @property-read \App\Models\Plan|null $plan 用户订阅计划
|
|
|
|
|
* @property-read ServerGroup|null $group 权限组
|
|
|
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, InviteCode> $codes 邀请码列表
|
|
|
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, Order> $orders 订单列表
|
|
|
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, StatUser> $stat 统计信息
|
|
|
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, Ticket> $tickets 工单列表
|
2025-06-22 01:18:38 +08:00
|
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, TrafficResetLog> $trafficResetLogs 流量重置记录
|
2025-05-07 19:48:19 +08:00
|
|
|
* @property-read User|null $parent 父账户
|
|
|
|
|
* @property-read string $subscribe_url 订阅链接(动态生成)
|
|
|
|
|
*/
|
2025-01-21 14:57:54 +08:00
|
|
|
class User extends Authenticatable
|
2023-11-17 14:44:01 +08:00
|
|
|
{
|
2025-01-21 14:57:54 +08:00
|
|
|
use HasApiTokens;
|
2023-11-17 14:44:01 +08:00
|
|
|
protected $table = 'v2_user';
|
|
|
|
|
protected $dateFormat = 'U';
|
|
|
|
|
protected $guarded = ['id'];
|
|
|
|
|
protected $casts = [
|
|
|
|
|
'created_at' => 'timestamp',
|
2025-05-07 19:48:19 +08:00
|
|
|
'updated_at' => 'timestamp',
|
2025-06-22 17:38:17 +08:00
|
|
|
'banned' => 'boolean',
|
|
|
|
|
'is_admin' => 'boolean',
|
|
|
|
|
'is_staff' => 'boolean',
|
2025-05-07 19:48:19 +08:00
|
|
|
'remind_expire' => 'boolean',
|
|
|
|
|
'remind_traffic' => 'boolean',
|
|
|
|
|
'commission_auto_check' => 'boolean',
|
2025-06-22 01:18:38 +08:00
|
|
|
'commission_rate' => 'float',
|
|
|
|
|
'next_reset_at' => 'timestamp',
|
|
|
|
|
'last_reset_at' => 'timestamp',
|
2023-11-17 14:44:01 +08:00
|
|
|
];
|
2025-01-21 14:57:54 +08:00
|
|
|
protected $hidden = ['password'];
|
2023-12-07 04:01:32 +08:00
|
|
|
|
2025-05-07 19:48:19 +08:00
|
|
|
public const COMMISSION_TYPE_SYSTEM = 0;
|
|
|
|
|
public const COMMISSION_TYPE_PERIOD = 1;
|
|
|
|
|
public const COMMISSION_TYPE_ONETIME = 2;
|
|
|
|
|
|
2023-12-07 04:01:32 +08:00
|
|
|
// 获取邀请人信息
|
2025-05-07 19:48:19 +08:00
|
|
|
public function invite_user(): BelongsTo
|
2023-12-07 04:01:32 +08:00
|
|
|
{
|
|
|
|
|
return $this->belongsTo(self::class, 'invite_user_id', 'id');
|
|
|
|
|
}
|
2023-12-08 15:43:17 +08:00
|
|
|
|
2025-05-07 19:48:19 +08:00
|
|
|
/**
|
|
|
|
|
* 获取用户订阅计划
|
|
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
|
|
|
*/
|
|
|
|
|
public function plan(): BelongsTo
|
2023-12-08 15:43:17 +08:00
|
|
|
{
|
|
|
|
|
return $this->belongsTo(Plan::class, 'plan_id', 'id');
|
|
|
|
|
}
|
2023-12-10 17:53:31 +08:00
|
|
|
|
2025-05-07 19:48:19 +08:00
|
|
|
public function group(): BelongsTo
|
2025-01-21 14:57:54 +08:00
|
|
|
{
|
|
|
|
|
return $this->belongsTo(ServerGroup::class, 'group_id', 'id');
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-10 17:53:31 +08:00
|
|
|
// 获取用户邀请码列表
|
2025-05-07 19:48:19 +08:00
|
|
|
public function codes(): HasMany
|
2023-12-10 17:53:31 +08:00
|
|
|
{
|
|
|
|
|
return $this->hasMany(InviteCode::class, 'user_id', 'id');
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-07 19:48:19 +08:00
|
|
|
public function orders(): HasMany
|
2025-01-25 16:57:17 +08:00
|
|
|
{
|
|
|
|
|
return $this->hasMany(Order::class, 'user_id', 'id');
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-07 19:48:19 +08:00
|
|
|
public function stat(): HasMany
|
2025-01-25 16:57:17 +08:00
|
|
|
{
|
|
|
|
|
return $this->hasMany(StatUser::class, 'user_id', 'id');
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-10 17:53:31 +08:00
|
|
|
// 关联工单列表
|
2025-05-07 19:48:19 +08:00
|
|
|
public function tickets(): HasMany
|
2023-12-10 17:53:31 +08:00
|
|
|
{
|
|
|
|
|
return $this->hasMany(Ticket::class, 'user_id', 'id');
|
|
|
|
|
}
|
2025-01-21 14:57:54 +08:00
|
|
|
|
2025-05-07 19:48:19 +08:00
|
|
|
public function parent(): BelongsTo
|
2025-01-21 14:57:54 +08:00
|
|
|
{
|
|
|
|
|
return $this->belongsTo(self::class, 'parent_id', 'id');
|
|
|
|
|
}
|
2025-05-07 19:48:19 +08:00
|
|
|
|
2025-06-22 01:18:38 +08:00
|
|
|
/**
|
|
|
|
|
* 关联流量重置记录
|
|
|
|
|
*/
|
|
|
|
|
public function trafficResetLogs(): HasMany
|
|
|
|
|
{
|
|
|
|
|
return $this->hasMany(TrafficResetLog::class, 'user_id', 'id');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查用户是否处于活跃状态
|
|
|
|
|
*/
|
|
|
|
|
public function isActive(): bool
|
|
|
|
|
{
|
|
|
|
|
return !$this->banned &&
|
|
|
|
|
($this->expired_at === null || $this->expired_at > time()) &&
|
|
|
|
|
$this->plan_id !== null;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-15 09:49:11 +08:00
|
|
|
/**
|
|
|
|
|
* 检查用户是否可用节点流量且充足
|
|
|
|
|
*/
|
|
|
|
|
public function isAvailable(): bool
|
|
|
|
|
{
|
|
|
|
|
return $this->isActive() && $this->getRemainingTraffic() > 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-22 01:18:38 +08:00
|
|
|
/**
|
|
|
|
|
* 检查是否需要重置流量
|
|
|
|
|
*/
|
|
|
|
|
public function shouldResetTraffic(): bool
|
|
|
|
|
{
|
|
|
|
|
return $this->isActive() &&
|
|
|
|
|
$this->next_reset_at !== null &&
|
|
|
|
|
$this->next_reset_at <= time();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取总使用流量
|
|
|
|
|
*/
|
|
|
|
|
public function getTotalUsedTraffic(): int
|
|
|
|
|
{
|
|
|
|
|
return ($this->u ?? 0) + ($this->d ?? 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取剩余流量
|
|
|
|
|
*/
|
|
|
|
|
public function getRemainingTraffic(): int
|
|
|
|
|
{
|
|
|
|
|
$used = $this->getTotalUsedTraffic();
|
|
|
|
|
$total = $this->transfer_enable ?? 0;
|
|
|
|
|
return max(0, $total - $used);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取流量使用百分比
|
|
|
|
|
*/
|
|
|
|
|
public function getTrafficUsagePercentage(): float
|
|
|
|
|
{
|
|
|
|
|
$total = $this->transfer_enable ?? 0;
|
|
|
|
|
if ($total <= 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$used = $this->getTotalUsedTraffic();
|
|
|
|
|
return min(100, ($used / $total) * 100);
|
|
|
|
|
}
|
2023-11-17 14:44:01 +08:00
|
|
|
}
|