feat: 创建数据模型

- SystemSetting: 系统设置模型,支持配置管理
- Terminal: 终端模型,支持终端管理
- TerminalKnowledgeBase: 终端知识库关联模型
- TerminalPrompt: 终端提示词模型
- TerminalSyncLog: 终端同步日志模型
- SopTemplate: SOP模板模型
- SopStep: SOP步骤模型
- SopInteractiveTask: SOP交互任务模型
- SopTemplateVersion: SOP模板版本模型

所有模型集成 LogsActivity trait 用于操作日志记录
This commit is contained in:
2026-03-09 10:07:31 +08:00
parent cedd910728
commit 9d0055138c
9 changed files with 575 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class SopInteractiveTask extends Model
{
/**
* 可批量赋值的属性
*
* @var array<string>
*/
protected $fillable = [
'sop_step_id',
'task_type',
'task_config',
'validation_rules',
'timeout_seconds',
'is_required',
];
/**
* 属性类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'task_config' => 'array',
'validation_rules' => 'array',
'is_required' => 'boolean',
];
}
/**
* 获取任务所属的步骤
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function step()
{
return $this->belongsTo(SopStep::class, 'sop_step_id');
}
}

54
app/Models/SopStep.php Normal file
View File

@@ -0,0 +1,54 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class SopStep extends Model
{
/**
* 可批量赋值的属性
*
* @var array<string>
*/
protected $fillable = [
'sop_template_id',
'step_number',
'title',
'content',
'sort_order',
'is_required',
];
/**
* 属性类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'is_required' => 'boolean',
];
}
/**
* 获取步骤所属的模板
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function template()
{
return $this->belongsTo(SopTemplate::class, 'sop_template_id');
}
/**
* 获取步骤的交互任务列表
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function interactiveTasks()
{
return $this->hasMany(SopInteractiveTask::class);
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;
class SopTemplate extends Model
{
use HasFactory, SoftDeletes, LogsActivity;
/**
* 可批量赋值的属性
*
* @var array<string>
*/
protected $fillable = [
'name',
'description',
'category',
'tags',
'version',
'status',
'applicable_departments',
'applicable_positions',
'published_at',
'created_by',
];
/**
* 属性类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'tags' => 'array',
'applicable_departments' => 'array',
'applicable_positions' => 'array',
'published_at' => 'datetime',
];
}
/**
* 获取模板的步骤列表
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function steps()
{
return $this->hasMany(SopStep::class)->orderBy('sort_order');
}
/**
* 获取模板的版本历史
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function versions()
{
return $this->hasMany(SopTemplateVersion::class);
}
/**
* 获取模板的创建者
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function creator()
{
return $this->belongsTo(User::class, 'created_by');
}
/**
* 配置活动日志选项
*
* @return \Spatie\Activitylog\LogOptions
*/
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->logOnly(['name', 'description', 'category', 'status', 'version'])
->logOnlyDirty()
->setDescriptionForEvent(fn(string $eventName) => "SOP模板已{$eventName}");
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class SopTemplateVersion extends Model
{
/**
* 表示模型是否应该被打上时间戳
* 注意: 只有created_at字段,没有updated_at
*
* @var bool
*/
public $timestamps = false;
/**
* 可批量赋值的属性
*
* @var array<string>
*/
protected $fillable = [
'sop_template_id',
'version',
'change_log',
'content_snapshot',
'created_by',
];
/**
* 属性类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'content_snapshot' => 'array',
'created_at' => 'datetime',
];
}
/**
* 获取版本所属的模板
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function template()
{
return $this->belongsTo(SopTemplate::class, 'sop_template_id');
}
/**
* 获取版本的创建者
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function creator()
{
return $this->belongsTo(User::class, 'created_by');
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;
class SystemSetting extends Model
{
use HasFactory, LogsActivity;
/**
* 可批量赋值的属性
*
* @var array<string>
*/
protected $fillable = [
'key',
'value',
'group',
'description',
'is_public',
];
/**
* 属性类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'value' => 'array',
'is_public' => 'boolean',
];
}
/**
* 获取配置值
*
* @param string $key 配置键
* @param mixed $default 默认值
* @return mixed
*/
public static function get(string $key, $default = null)
{
$setting = static::where('key', $key)->first();
return $setting ? $setting->value : $default;
}
/**
* 设置配置值
*
* @param string $key 配置键
* @param mixed $value 配置值
* @param string $group 配置分组
* @return \App\Models\SystemSetting
*/
public static function set(string $key, $value, string $group = 'general')
{
return static::updateOrCreate(
['key' => $key],
['value' => $value, 'group' => $group]
);
}
/**
* 配置活动日志选项
*
* @return \Spatie\Activitylog\LogOptions
*/
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->logOnly(['key', 'value', 'group', 'description'])
->logOnlyDirty()
->setDescriptionForEvent(fn(string $eventName) => "系统设置已{$eventName}");
}
}

90
app/Models/Terminal.php Normal file
View File

@@ -0,0 +1,90 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;
class Terminal extends Model
{
use HasFactory, SoftDeletes, LogsActivity;
/**
* 可批量赋值的属性
*
* @var array<string>
*/
protected $fillable = [
'name',
'code',
'ip_address',
'station_id',
'diagram_url',
'display_config',
'is_online',
'last_online_at',
];
/**
* 属性类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'display_config' => 'array',
'is_online' => 'boolean',
'last_online_at' => 'datetime',
];
}
/**
* 获取终端关联的知识库
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function knowledgeBases()
{
return $this->belongsToMany(KnowledgeBase::class, 'terminal_knowledge_bases')
->withPivot('priority')
->withTimestamps()
->orderBy('priority');
}
/**
* 获取终端的提示词配置
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function prompt()
{
return $this->hasOne(TerminalPrompt::class);
}
/**
* 获取终端的同步日志
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function syncLogs()
{
return $this->hasMany(TerminalSyncLog::class);
}
/**
* 配置活动日志选项
*
* @return \Spatie\Activitylog\LogOptions
*/
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->logOnly(['name', 'code', 'station_id', 'diagram_url', 'display_config'])
->logOnlyDirty()
->setDescriptionForEvent(fn(string $eventName) => "终端已{$eventName}");
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class TerminalKnowledgeBase extends Model
{
/**
* 可批量赋值的属性
*
* @var array<string>
*/
protected $fillable = [
'terminal_id',
'knowledge_base_id',
'priority',
];
/**
* 属性类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'priority' => 'integer',
];
}
/**
* 获取关联的终端
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function terminal(): BelongsTo
{
return $this->belongsTo(Terminal::class);
}
/**
* 获取关联的知识库
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function knowledgeBase(): BelongsTo
{
return $this->belongsTo(KnowledgeBase::class);
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;
class TerminalPrompt extends Model
{
use LogsActivity;
/**
* 可批量赋值的属性
*
* @var array<string>
*/
protected $fillable = [
'terminal_id',
'prompt_template',
'variables',
];
/**
* 属性类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'variables' => 'array',
];
}
/**
* 获取提示词所属的终端
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function terminal()
{
return $this->belongsTo(Terminal::class);
}
/**
* 配置活动日志选项
*
* @return \Spatie\Activitylog\LogOptions
*/
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->logOnly(['terminal_id', 'prompt_template', 'variables'])
->logOnlyDirty()
->setDescriptionForEvent(fn(string $eventName) => "终端提示词已{$eventName}");
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TerminalSyncLog extends Model
{
/**
* 可批量赋值的属性
*
* @var array<string>
*/
protected $fillable = [
'terminal_id',
'status',
'config_snapshot',
'synced_at',
'error_message',
];
/**
* 属性类型转换
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'config_snapshot' => 'array',
'synced_at' => 'datetime',
];
}
/**
* 获取同步日志所属的终端
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function terminal()
{
return $this->belongsTo(Terminal::class);
}
}