| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- <?php
- namespace App\Module\Cleanup\Models;
- use App\Module\Cleanup\Enums\BACKUP_TYPE;
- use App\Module\Cleanup\Enums\COMPRESSION_TYPE;
- use App\Module\Cleanup\Enums\BACKUP_STATUS;
- use UCore\ModelCore;
- use Illuminate\Database\Eloquent\Relations\BelongsTo;
- use Illuminate\Database\Eloquent\Relations\HasMany;
- /**
- * 备份记录模型
- *
- * 存储计划的备份方案和备份内容
- */
- class CleanupBackup extends ModelCore
- {
- /**
- * 数据表名
- */
- protected $table = 'cleanup_backups';
- // field start
- /**
- * 可批量赋值的字段
- */
- protected $fillable = [
- 'plan_id',
- 'task_id',
- 'backup_name',
- 'backup_type',
- 'compression_type',
- 'backup_path',
- 'backup_size',
- 'original_size',
- 'tables_count',
- 'records_count',
- 'backup_status',
- 'backup_hash',
- 'backup_config',
- 'started_at',
- 'completed_at',
- 'expires_at',
- 'error_message',
- 'created_by',
- ];
- // field end
- /**
- * 字段类型转换
- */
- protected $casts = [
- 'plan_id' => 'integer',
- 'task_id' => 'integer',
- 'backup_type' => 'integer',
- 'compression_type' => 'integer',
- 'backup_size' => 'integer',
- 'original_size' => 'integer',
- 'tables_count' => 'integer',
- 'records_count' => 'integer',
- 'backup_status' => 'integer',
- 'backup_config' => 'array',
- 'created_by' => 'integer',
- 'started_at' => 'datetime',
- 'completed_at' => 'datetime',
- 'expires_at' => 'datetime',
- 'created_at' => 'datetime',
- 'updated_at' => 'datetime',
- ];
- /**
- * 获取备份类型枚举
- */
- public function getBackupTypeEnumAttribute(): BACKUP_TYPE
- {
- return BACKUP_TYPE::from($this->backup_type);
- }
- /**
- * 获取压缩类型枚举
- */
- public function getCompressionTypeEnumAttribute(): COMPRESSION_TYPE
- {
- return COMPRESSION_TYPE::from($this->compression_type);
- }
- /**
- * 获取备份状态枚举
- */
- public function getBackupStatusEnumAttribute(): BACKUP_STATUS
- {
- return BACKUP_STATUS::from($this->backup_status);
- }
- /**
- * 获取备份类型描述
- */
- public function getBackupTypeNameAttribute(): string
- {
- return $this->getBackupTypeEnumAttribute()->getDescription();
- }
- /**
- * 获取压缩类型描述
- */
- public function getCompressionTypeNameAttribute(): string
- {
- return $this->getCompressionTypeEnumAttribute()->getDescription();
- }
- /**
- * 获取备份状态描述
- */
- public function getBackupStatusNameAttribute(): string
- {
- return $this->getBackupStatusEnumAttribute()->getDescription();
- }
- /**
- * 获取备份状态颜色
- */
- public function getBackupStatusColorAttribute(): string
- {
- return $this->getBackupStatusEnumAttribute()->getColor();
- }
- /**
- * 获取备份状态图标
- */
- public function getBackupStatusIconAttribute(): string
- {
- return $this->getBackupStatusEnumAttribute()->getIcon();
- }
- /**
- * 获取格式化的备份大小
- */
- public function getBackupSizeFormattedAttribute(): string
- {
- return $this->formatBytes($this->backup_size);
- }
- /**
- * 获取格式化的原始大小
- */
- public function getOriginalSizeFormattedAttribute(): string
- {
- return $this->formatBytes($this->original_size);
- }
- /**
- * 获取压缩率
- */
- public function getCompressionRatioAttribute(): float
- {
- if ($this->original_size == 0) {
- return 0;
- }
- return (1 - $this->backup_size / $this->original_size) * 100;
- }
- /**
- * 获取格式化的压缩率
- */
- public function getCompressionRatioFormattedAttribute(): string
- {
- return number_format($this->compression_ratio, 2) . '%';
- }
- /**
- * 获取备份持续时间
- */
- public function getDurationAttribute(): ?float
- {
- if (!$this->started_at || !$this->completed_at) {
- return null;
- }
- return $this->started_at->diffInSeconds($this->completed_at);
- }
- /**
- * 获取格式化的备份持续时间
- */
- public function getDurationFormattedAttribute(): ?string
- {
- $duration = $this->duration;
- return $duration ? $this->formatDuration($duration) : null;
- }
- /**
- * 判断备份是否已过期
- */
- public function getIsExpiredAttribute(): bool
- {
- return $this->expires_at && $this->expires_at->isPast();
- }
- /**
- * 获取过期状态文本
- */
- public function getExpiryStatusAttribute(): string
- {
- if (!$this->expires_at) {
- return '永不过期';
- }
-
- if ($this->is_expired) {
- return '已过期';
- }
-
- return '剩余 ' . $this->expires_at->diffForHumans();
- }
- /**
- * 获取过期状态颜色
- */
- public function getExpiryColorAttribute(): string
- {
- if (!$this->expires_at) {
- return 'info';
- }
-
- if ($this->is_expired) {
- return 'danger';
- }
-
- $daysLeft = now()->diffInDays($this->expires_at);
- if ($daysLeft <= 3) {
- return 'warning';
- }
-
- return 'success';
- }
- /**
- * 获取文件扩展名
- */
- public function getFileExtensionAttribute(): string
- {
- $backupExt = $this->getBackupTypeEnumAttribute()->getFileExtension();
- $compressExt = $this->getCompressionTypeEnumAttribute()->getFileExtension();
-
- return $backupExt . $compressExt;
- }
- /**
- * 获取完整文件名
- */
- public function getFullFilenameAttribute(): string
- {
- return $this->backup_name . '.' . $this->file_extension;
- }
- /**
- * 判断文件是否存在
- */
- public function getFileExistsAttribute(): bool
- {
- return file_exists($this->backup_path);
- }
- /**
- * 关联清理计划
- */
- public function plan(): BelongsTo
- {
- return $this->belongsTo(CleanupPlan::class, 'plan_id');
- }
- /**
- * 关联清理任务
- */
- public function task(): BelongsTo
- {
- return $this->belongsTo(CleanupTask::class, 'task_id');
- }
- /**
- * 关联备份文件
- */
- public function files(): HasMany
- {
- return $this->hasMany(CleanupBackupFile::class, 'backup_id');
- }
- /**
- * 关联SQL备份记录
- */
- public function sqlBackups(): HasMany
- {
- return $this->hasMany(CleanupSqlBackup::class, 'backup_id');
- }
- /**
- * 作用域:按计划筛选
- */
- public function scopeByPlan($query, int $planId)
- {
- return $query->where('plan_id', $planId);
- }
- /**
- * 作用域:按任务筛选
- */
- public function scopeByTask($query, int $taskId)
- {
- return $query->where('task_id', $taskId);
- }
- /**
- * 作用域:按备份状态筛选
- */
- public function scopeByStatus($query, int $status)
- {
- return $query->where('backup_status', $status);
- }
- /**
- * 作用域:已完成的备份
- */
- public function scopeCompleted($query)
- {
- return $query->where('backup_status', BACKUP_STATUS::COMPLETED->value);
- }
- /**
- * 作用域:已过期的备份
- */
- public function scopeExpired($query)
- {
- return $query->where('expires_at', '<', now());
- }
- /**
- * 作用域:即将过期的备份
- */
- public function scopeExpiringSoon($query, int $days = 7)
- {
- return $query->whereBetween('expires_at', [now(), now()->addDays($days)]);
- }
- /**
- * 作用域:按备份名称搜索
- */
- public function scopeSearchName($query, string $search)
- {
- return $query->where('backup_name', 'like', "%{$search}%");
- }
- /**
- * 格式化字节大小
- */
- private function formatBytes(int $bytes): string
- {
- if ($bytes == 0) {
- return '0 B';
- }
- $units = ['B', 'KB', 'MB', 'GB', 'TB'];
- $i = floor(log($bytes, 1024));
- return round($bytes / pow(1024, $i), 2) . ' ' . $units[$i];
- }
- /**
- * 格式化持续时间
- */
- private function formatDuration(float $seconds): string
- {
- if ($seconds < 60) {
- return number_format($seconds, 2) . ' 秒';
- } elseif ($seconds < 3600) {
- return number_format($seconds / 60, 2) . ' 分钟';
- } else {
- return number_format($seconds / 3600, 2) . ' 小时';
- }
- }
- /**
- * 获取备份状态统计
- */
- public static function getStatusStats(): array
- {
- $stats = static::selectRaw('backup_status, COUNT(*) as count')
- ->groupBy('backup_status')
- ->get()
- ->keyBy('backup_status')
- ->toArray();
- $result = [];
- foreach (BACKUP_STATUS::cases() as $status) {
- $result[$status->value] = [
- 'name' => $status->getDescription(),
- 'count' => $stats[$status->value]['count'] ?? 0,
- 'color' => $status->getColor(),
- 'icon' => $status->getIcon(),
- ];
- }
- return $result;
- }
- /**
- * 获取存储统计
- */
- public static function getStorageStats(): array
- {
- $stats = static::selectRaw('
- COUNT(*) as total_backups,
- SUM(backup_size) as total_backup_size,
- SUM(original_size) as total_original_size,
- AVG(backup_size) as avg_backup_size
- ')->first();
- return [
- 'total_backups' => $stats->total_backups ?? 0,
- 'total_backup_size' => $stats->total_backup_size ?? 0,
- 'total_original_size' => $stats->total_original_size ?? 0,
- 'avg_backup_size' => $stats->avg_backup_size ?? 0,
- 'total_compression_ratio' => $stats->total_original_size > 0
- ? (1 - $stats->total_backup_size / $stats->total_original_size) * 100
- : 0,
- ];
- }
- }
|