- AiVoiceRecording 모델 (상태 상수, 접근자) - AiVoiceRecordingService (GCS 업로드, STT, Gemini 분석 파이프라인) - AiVoiceRecordingController (CRUD, 녹음 처리, 상태 폴링) - React 블레이드 뷰 (녹음 UI, 파일 업로드, 목록, 상세 모달) - 라우트 추가 (system/ai-voice-recording) - 메뉴 시더에 AI 음성녹음 항목 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
95 lines
2.3 KiB
PHP
95 lines
2.3 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Traits\BelongsToTenant;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
class AiVoiceRecording extends Model
|
|
{
|
|
use BelongsToTenant, SoftDeletes;
|
|
|
|
protected $table = 'ai_voice_recordings';
|
|
|
|
protected $fillable = [
|
|
'tenant_id',
|
|
'user_id',
|
|
'title',
|
|
'interview_template_id',
|
|
'audio_file_path',
|
|
'audio_gcs_uri',
|
|
'transcript_text',
|
|
'analysis_text',
|
|
'status',
|
|
'duration_seconds',
|
|
'file_expiry_date',
|
|
];
|
|
|
|
protected $casts = [
|
|
'duration_seconds' => 'integer',
|
|
'file_expiry_date' => 'datetime',
|
|
'created_at' => 'datetime',
|
|
'updated_at' => 'datetime',
|
|
'deleted_at' => 'datetime',
|
|
];
|
|
|
|
public const STATUS_PENDING = 'PENDING';
|
|
|
|
public const STATUS_PROCESSING = 'PROCESSING';
|
|
|
|
public const STATUS_COMPLETED = 'COMPLETED';
|
|
|
|
public const STATUS_FAILED = 'FAILED';
|
|
|
|
public function user(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class);
|
|
}
|
|
|
|
public function getFormattedDurationAttribute(): string
|
|
{
|
|
if (! $this->duration_seconds) {
|
|
return '00:00';
|
|
}
|
|
|
|
$minutes = floor($this->duration_seconds / 60);
|
|
$seconds = $this->duration_seconds % 60;
|
|
|
|
return sprintf('%02d:%02d', $minutes, $seconds);
|
|
}
|
|
|
|
public function getStatusLabelAttribute(): string
|
|
{
|
|
return match ($this->status) {
|
|
self::STATUS_PENDING => '대기중',
|
|
self::STATUS_PROCESSING => '처리중',
|
|
self::STATUS_COMPLETED => '완료',
|
|
self::STATUS_FAILED => '실패',
|
|
default => $this->status,
|
|
};
|
|
}
|
|
|
|
public function getStatusColorAttribute(): string
|
|
{
|
|
return match ($this->status) {
|
|
self::STATUS_PENDING => 'badge-warning',
|
|
self::STATUS_PROCESSING => 'badge-info',
|
|
self::STATUS_COMPLETED => 'badge-success',
|
|
self::STATUS_FAILED => 'badge-error',
|
|
default => 'badge-ghost',
|
|
};
|
|
}
|
|
|
|
public function isCompleted(): bool
|
|
{
|
|
return $this->status === self::STATUS_COMPLETED;
|
|
}
|
|
|
|
public function isProcessing(): bool
|
|
{
|
|
return $this->status === self::STATUS_PROCESSING;
|
|
}
|
|
}
|