初始化
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Article extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'category_id',
|
||||
'user_id',
|
||||
'title',
|
||||
'slug',
|
||||
'summary',
|
||||
'body',
|
||||
'cover',
|
||||
'author',
|
||||
'status',
|
||||
'template',
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'published_at',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'category_id' => 'integer',
|
||||
'published_at' => 'datetime',
|
||||
];
|
||||
|
||||
public const TEMPLATES = [
|
||||
'standard' => '标准文章',
|
||||
'tech' => '技术文档',
|
||||
'feature' => '专题报道',
|
||||
];
|
||||
|
||||
public function category(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Category::class, 'category_id');
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 可见性作用域(与 forum 一致):
|
||||
* - 审核员(articles.moderate):看全部
|
||||
* - 登录用户:看已审 + 自己投稿(无论状态)
|
||||
* - 游客:仅看已审
|
||||
*/
|
||||
public function scopeVisibleTo($query, ?User $user = null)
|
||||
{
|
||||
if ($user && $user->canPerm('articles.moderate')) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
if ($user) {
|
||||
return $query->where(function ($q) use ($user) {
|
||||
$q->where('status', 'approved')->orWhere('user_id', $user->id);
|
||||
});
|
||||
}
|
||||
|
||||
return $query->where('status', 'approved');
|
||||
}
|
||||
|
||||
public function scopePublished($query)
|
||||
{
|
||||
return $query->where('status', 'approved')
|
||||
->whereNotNull('published_at')
|
||||
->orderByDesc('published_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* 前台可见文章:已审核通过(approved) 且已设定发布时间。
|
||||
* 用户自己的待审(pending)/驳回(rejected) 由控制器单独查询,不进此作用域。
|
||||
*/
|
||||
public function scopeVisiblePublic($query)
|
||||
{
|
||||
return $query->where('status', 'approved')
|
||||
->whereNotNull('published_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* 前台 SEO 标题:优先用文章自定义,否则回退到标题。
|
||||
*/
|
||||
public function seoTitle(): string
|
||||
{
|
||||
return $this->seo_title ?: $this->title;
|
||||
}
|
||||
|
||||
public function seoDescription(): string
|
||||
{
|
||||
return $this->seo_description ?: ($this->summary ?: $this->title);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Category extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'slug',
|
||||
'type',
|
||||
'parent_id',
|
||||
'sort',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'parent_id' => 'integer',
|
||||
'sort' => 'integer',
|
||||
];
|
||||
|
||||
public function products(): HasMany
|
||||
{
|
||||
return $this->hasMany(Product::class, 'category_id');
|
||||
}
|
||||
|
||||
public function articles(): HasMany
|
||||
{
|
||||
return $this->hasMany(Article::class, 'category_id');
|
||||
}
|
||||
|
||||
public function scopeOfType($query, string $type)
|
||||
{
|
||||
return $query->where('type', $type)->orderBy('sort')->orderBy('name');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ContactMessage extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'phone',
|
||||
'company',
|
||||
'subject',
|
||||
'message',
|
||||
'ip',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
'ip',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class ForumBoard extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'slug',
|
||||
'description',
|
||||
'sort',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'sort' => 'integer',
|
||||
];
|
||||
|
||||
public function threads(): HasMany
|
||||
{
|
||||
return $this->hasMany(ForumThread::class, 'board_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class ForumReply extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'thread_id',
|
||||
'user_id',
|
||||
'body',
|
||||
'status',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'thread_id' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
];
|
||||
|
||||
public const STATUS_PENDING = 'pending';
|
||||
public const STATUS_APPROVED = 'approved';
|
||||
public const STATUS_REJECTED = 'rejected';
|
||||
|
||||
/**
|
||||
* 可见性作用域(同 ForumThread):
|
||||
* - 审核员:全部
|
||||
* - 登录用户:已审 + 自己发的
|
||||
* - 游客:仅已审
|
||||
*/
|
||||
public function scopeVisible($query, ?User $user = null)
|
||||
{
|
||||
if ($user && $user->canPerm('forum.moderate')) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
if ($user) {
|
||||
return $query->where(function ($q) use ($user) {
|
||||
$q->where('status', self::STATUS_APPROVED)
|
||||
->orWhere('user_id', $user->id);
|
||||
});
|
||||
}
|
||||
|
||||
return $query->where('status', self::STATUS_APPROVED);
|
||||
}
|
||||
|
||||
public function thread(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ForumThread::class, 'thread_id');
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class ForumThread extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'board_id',
|
||||
'user_id',
|
||||
'title',
|
||||
'body',
|
||||
'status',
|
||||
'is_pinned',
|
||||
'is_locked',
|
||||
'views',
|
||||
'last_reply_at',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'board_id' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'is_pinned' => 'boolean',
|
||||
'is_locked' => 'boolean',
|
||||
'views' => 'integer',
|
||||
'last_reply_at' => 'datetime',
|
||||
];
|
||||
|
||||
public const STATUS_PENDING = 'pending';
|
||||
public const STATUS_APPROVED = 'approved';
|
||||
public const STATUS_REJECTED = 'rejected';
|
||||
|
||||
/**
|
||||
* 可见性作用域:
|
||||
* - 审核员(forum.moderate):看全部(含待审/驳回)
|
||||
* - 登录用户:看已审 + 自己发的(无论状态)
|
||||
* - 游客:仅看已审
|
||||
*/
|
||||
public function scopeVisible($query, ?User $user = null)
|
||||
{
|
||||
if ($user && $user->canPerm('forum.moderate')) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
if ($user) {
|
||||
return $query->where(function ($q) use ($user) {
|
||||
$q->where('status', self::STATUS_APPROVED)
|
||||
->orWhere('user_id', $user->id);
|
||||
});
|
||||
}
|
||||
|
||||
return $query->where('status', self::STATUS_APPROVED);
|
||||
}
|
||||
|
||||
public function board(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ForumBoard::class, 'board_id');
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
public function replies(): HasMany
|
||||
{
|
||||
return $this->hasMany(ForumReply::class, 'thread_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class GlossaryTerm extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'term',
|
||||
'slug',
|
||||
'definition',
|
||||
'aliases',
|
||||
'category',
|
||||
];
|
||||
|
||||
public function scopeOrdered($query)
|
||||
{
|
||||
return $query->orderBy('term');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class HeroSlide extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'location',
|
||||
'title',
|
||||
'content',
|
||||
'cta_text',
|
||||
'cta_url',
|
||||
'cta2_text',
|
||||
'cta2_url',
|
||||
'is_active',
|
||||
'sort_order',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'is_active' => 'boolean',
|
||||
'sort_order' => 'integer',
|
||||
];
|
||||
|
||||
public function scopeLocation(Builder $query, string $location): Builder
|
||||
{
|
||||
return $query->where('location', $location);
|
||||
}
|
||||
|
||||
public function scopeActive(Builder $query): Builder
|
||||
{
|
||||
return $query->where('is_active', true);
|
||||
}
|
||||
|
||||
public function scopeOrdered(Builder $query): Builder
|
||||
{
|
||||
return $query->orderBy('sort_order')->orderBy('id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class NavigationMenu extends Model
|
||||
{
|
||||
protected $fillable = ['label', 'url', 'is_visible', 'sort_order'];
|
||||
|
||||
protected $casts = [
|
||||
'is_visible' => 'boolean',
|
||||
'sort_order' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* 前台可见菜单:按排序返回。
|
||||
*/
|
||||
public function scopeVisible(Builder $query): Builder
|
||||
{
|
||||
return $query->where('is_visible', true);
|
||||
}
|
||||
|
||||
public function scopeOrdered(Builder $query): Builder
|
||||
{
|
||||
return $query->orderBy('sort_order')->orderBy('id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class News extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'slug',
|
||||
'category',
|
||||
'summary',
|
||||
'body',
|
||||
'cover',
|
||||
'status',
|
||||
'published_at',
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'published_at' => 'datetime',
|
||||
];
|
||||
|
||||
public const CATEGORIES = [
|
||||
'industry' => '行业资讯',
|
||||
'company' => '公司动态',
|
||||
'event' => '展会活动',
|
||||
];
|
||||
|
||||
public function scopePublished($query)
|
||||
{
|
||||
return $query->where('status', 'published')
|
||||
->whereNotNull('published_at')
|
||||
->orderByDesc('published_at');
|
||||
}
|
||||
|
||||
public function categoryLabel(): string
|
||||
{
|
||||
return self::CATEGORIES[$this->category] ?? $this->category ?? '—';
|
||||
}
|
||||
|
||||
public function seoTitle(): string
|
||||
{
|
||||
return $this->seo_title ?: $this->title;
|
||||
}
|
||||
|
||||
public function seoDescription(): string
|
||||
{
|
||||
return $this->seo_description ?: ($this->summary ?: $this->title);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Product extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'category_id',
|
||||
'name',
|
||||
'slug',
|
||||
'model',
|
||||
'summary',
|
||||
'description',
|
||||
'specs',
|
||||
'cover',
|
||||
'status',
|
||||
'sort',
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'category_id' => 'integer',
|
||||
'sort' => 'integer',
|
||||
];
|
||||
|
||||
public function category(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Category::class, 'category_id');
|
||||
}
|
||||
|
||||
public function scopePublished($query)
|
||||
{
|
||||
return $query->where('status', 'published')->orderBy('sort')->orderBy('name');
|
||||
}
|
||||
|
||||
public function seoTitle(): string
|
||||
{
|
||||
return $this->seo_title ?: ($this->name . ' - 深圳市云创芯电子有限公司');
|
||||
}
|
||||
|
||||
public function seoDescription(): string
|
||||
{
|
||||
return $this->seo_description ?: ($this->summary ?: $this->name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Setting extends Model
|
||||
{
|
||||
protected $fillable = ['key', 'value', 'group'];
|
||||
|
||||
/**
|
||||
* 读取设置值,未设置时返回默认值。
|
||||
*/
|
||||
public static function get(string $key, ?string $default = null): ?string
|
||||
{
|
||||
$row = static::where('key', $key)->first();
|
||||
if (!$row) {
|
||||
return $default;
|
||||
}
|
||||
return $row->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入或更新设置值。
|
||||
*/
|
||||
public static function set(string $key, ?string $value, string $group = 'general'): void
|
||||
{
|
||||
static::updateOrCreate(
|
||||
['key' => $key],
|
||||
['value' => $value, 'group' => $group]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Solution extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'slug',
|
||||
'power_segment',
|
||||
'application',
|
||||
'chip_platform',
|
||||
'power',
|
||||
'summary',
|
||||
'advantages',
|
||||
'description',
|
||||
'cover',
|
||||
'status',
|
||||
'sort',
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
];
|
||||
|
||||
public const POWER_SEGMENTS = [
|
||||
'lt30' => '30W 以下',
|
||||
'30-65' => '30–65W',
|
||||
'65-100' => '65–100W',
|
||||
'gt100' => '100W 以上',
|
||||
];
|
||||
|
||||
public const APPLICATIONS = [
|
||||
'charger' => '充电器',
|
||||
'powerbank' => '移动电源',
|
||||
'car' => '车载充电',
|
||||
'dock' => '扩展坞 / 多口排插',
|
||||
];
|
||||
|
||||
public const CHIP_PLATFORMS = [
|
||||
'protocol' => '协议芯片',
|
||||
'soc' => '高集成 SoC',
|
||||
'rectifier' => '同步整流',
|
||||
];
|
||||
|
||||
public function scopePublished($query)
|
||||
{
|
||||
return $query->where('status', 'published')->orderBy('sort')->orderBy('name');
|
||||
}
|
||||
|
||||
public function powerSegmentLabel(): string
|
||||
{
|
||||
return self::POWER_SEGMENTS[$this->power_segment] ?? $this->power_segment ?? '—';
|
||||
}
|
||||
|
||||
public function applicationLabel(): string
|
||||
{
|
||||
return self::APPLICATIONS[$this->application] ?? $this->application ?? '—';
|
||||
}
|
||||
|
||||
public function chipPlatformLabel(): string
|
||||
{
|
||||
return self::CHIP_PLATFORMS[$this->chip_platform] ?? $this->chip_platform ?? '—';
|
||||
}
|
||||
|
||||
public function advantagesList(): array
|
||||
{
|
||||
if (! $this->advantages) {
|
||||
return [];
|
||||
}
|
||||
return collect(explode("\n", $this->advantages))
|
||||
->map(fn ($line) => trim($line))
|
||||
->filter()
|
||||
->all();
|
||||
}
|
||||
|
||||
public function seoTitle(): string
|
||||
{
|
||||
return $this->seo_title ?: ($this->name . ' - 深圳市云创芯电子有限公司');
|
||||
}
|
||||
|
||||
public function seoDescription(): string
|
||||
{
|
||||
return $this->seo_description ?: ($this->summary ?: $this->name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasFactory, Notifiable;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'password',
|
||||
'is_admin',
|
||||
'role',
|
||||
'permissions',
|
||||
'points',
|
||||
'real_name',
|
||||
'phone',
|
||||
'company',
|
||||
'industry',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'is_admin' => 'boolean',
|
||||
'role' => 'string',
|
||||
'permissions' => 'array',
|
||||
'points' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 等级阈值(积分下限),键名即等级 L1..L5
|
||||
*/
|
||||
public const LEVELS = [
|
||||
1 => 0,
|
||||
2 => 50,
|
||||
3 => 200,
|
||||
4 => 600,
|
||||
5 => 1500,
|
||||
];
|
||||
|
||||
public const LEVEL_NAMES = [
|
||||
1 => '新芯用户',
|
||||
2 => '活跃用户',
|
||||
3 => '资深用户',
|
||||
4 => '核心用户',
|
||||
5 => '云创芯达人',
|
||||
];
|
||||
|
||||
/**
|
||||
* 兼容旧逻辑:有后台角色即视为「管理员」(用于前台「后台」入口判断)。
|
||||
* 新逻辑请使用 role() / canPerm()。
|
||||
*/
|
||||
public function isAdmin(): bool
|
||||
{
|
||||
return $this->role !== 'user';
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色等级(1-5),用于层级判断。
|
||||
*/
|
||||
public function roleLevel(): int
|
||||
{
|
||||
return (int) config("permissions.roles.{$this->role}.level", 1);
|
||||
}
|
||||
|
||||
public function roleLabel(): string
|
||||
{
|
||||
return config("permissions.roles.{$this->role}.label", '注册用户');
|
||||
}
|
||||
|
||||
public function isSuperAdmin(): bool
|
||||
{
|
||||
return $this->role === 'super_admin';
|
||||
}
|
||||
|
||||
public function isStaff(): bool
|
||||
{
|
||||
return $this->role === 'staff';
|
||||
}
|
||||
|
||||
/**
|
||||
* 细粒度权限判定。
|
||||
* - 超级管理员:恒 true
|
||||
* - 内部员工:查 users.permissions(管理员勾选分配)
|
||||
* - 其他角色:查 config/permissions.php 中该角色的默认权限集
|
||||
*/
|
||||
public function canPerm(string $key): bool
|
||||
{
|
||||
if ($this->role === 'super_admin') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->role === 'staff') {
|
||||
$perms = is_array($this->permissions) ? $this->permissions : [];
|
||||
return in_array($key, $perms, true);
|
||||
}
|
||||
|
||||
$def = config("permissions.roles.{$this->role}.permissions", []);
|
||||
if (in_array('*', $def, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return in_array($key, $def, true);
|
||||
}
|
||||
|
||||
public function threads()
|
||||
{
|
||||
return $this->hasMany(ForumThread::class);
|
||||
}
|
||||
|
||||
public function replies()
|
||||
{
|
||||
return $this->hasMany(ForumReply::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加积分(用于注册、发帖、回帖等动作)。
|
||||
*/
|
||||
public function awardPoints(int $amount): void
|
||||
{
|
||||
$this->increment('points', max(0, $amount));
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前等级(1-5)。
|
||||
*/
|
||||
public function level(): int
|
||||
{
|
||||
$points = $this->points ?? 0;
|
||||
$level = 1;
|
||||
foreach (self::LEVELS as $lv => $threshold) {
|
||||
if ($points >= $threshold) {
|
||||
$level = $lv;
|
||||
}
|
||||
}
|
||||
return $level;
|
||||
}
|
||||
|
||||
public function levelName(): string
|
||||
{
|
||||
return self::LEVEL_NAMES[$this->level()] ?? '用户';
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前等级进度(用于前台进度条展示)。
|
||||
*/
|
||||
public function levelProgress(): array
|
||||
{
|
||||
$level = $this->level();
|
||||
$current = self::LEVELS[$level] ?? 0;
|
||||
$next = self::LEVELS[$level + 1] ?? null;
|
||||
|
||||
if ($next === null) {
|
||||
return ['level' => $level, 'current' => $this->points, 'next' => null, 'percent' => 100];
|
||||
}
|
||||
|
||||
$span = $next - $current;
|
||||
$done = $this->points - $current;
|
||||
$percent = $span > 0 ? (int) min(100, round($done / $span * 100)) : 100;
|
||||
|
||||
return ['level' => $level, 'current' => $this->points, 'next' => $next, 'percent' => $percent];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user