'datetime',
'updated_at' => 'datetime',
'image_count' => 'integer',
'total_questions' => 'integer',
'analysis_pdf_url' => 'string',
];
public function questions(): HasMany
{
return $this->hasMany(OCRQuestionResult::class, 'ocr_record_id', 'id');
}
public function ocrRawData()
{
return $this->hasOne(\App\Models\OCRRawData::class, 'ocr_record_id', 'id');
}
public function student()
{
return $this->belongsTo(Student::class, 'user_id', 'student_id');
}
public function getStatusBadgeAttribute(): string
{
return match ($this->status) {
'pending' => '待处理',
'processing' => '处理中',
'completed' => '已完成',
'failed' => '失败',
default => '未知',
};
}
// 兼容性方法:获取 student_id
public function getStudentIdAttribute(): ?string
{
return $this->user_id;
}
// 兼容性方法:设置 student_id
public function setStudentIdAttribute(?string $value): void
{
// 同时设置两个字段以保持数据一致性
$this->attributes['student_id'] = $value;
$this->attributes['user_id'] = $value;
}
public function getImagePathAttribute(): string
{
// 将 file_path 映射为 image_path 以保持兼容性
return $this->file_path ?? '';
}
public function getImageUrlAttribute(): string
{
// 使用 file_path(通过上面的访问器也可以通过 image_path 访问)
$path = $this->file_path;
if ($path && file_exists(public_path($path))) {
return asset($path);
}
return '';
}
/**
* 获取处理完成时间(确保返回 Carbon 对象)
*/
public function getProcessedAtAttribute($value): ?\Carbon\Carbon
{
if (empty($value)) {
return null;
}
// 如果已经是 Carbon 实例,直接返回
if ($value instanceof \Carbon\Carbon) {
return $value;
}
// 如果是字符串,解析为 Carbon 实例
if (is_string($value)) {
return \Carbon\Carbon::parse($value);
}
return null;
}
public function getProgressPercentageAttribute(): int
{
if ($this->total_questions === 0) {
return 0;
}
return intval(($this->processed_questions / $this->total_questions) * 100);
}
public function getPaperTypeLabelAttribute(): string
{
return match($this->paper_type) {
'unit_test' => '单元测试',
'midterm' => '期中考试',
'final' => '期末考试',
'homework' => '家庭作业',
'quiz' => '随堂测验',
'other' => '其他',
default => '未分类',
};
}
}