Files
KnowledgeBase/app/Filament/Resources/TerminalResource.php
2026-03-16 13:56:10 +08:00

346 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\TerminalResource\Pages;
use App\Models\Terminal;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
class TerminalResource extends Resource
{
protected static ?string $model = Terminal::class;
protected static ?string $navigationIcon = 'heroicon-o-computer-desktop';
protected static ?string $navigationLabel = '终端管理';
protected static ?string $modelLabel = '终端';
protected static ?string $pluralModelLabel = '终端';
protected static ?int $navigationSort = 2;
protected static ?string $navigationGroup = '业务管理';
/**
* 控制导航菜单是否显示
*/
public static function shouldRegisterNavigation(): bool
{
return auth()->user()?->can('terminal.view') ?? false;
}
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Section::make('基本信息')
->schema([
Forms\Components\TextInput::make('name')
->label('终端名称')
->required()
->maxLength(255)
->placeholder('例如: 生产线A-工位1')
->helperText('终端的显示名称'),
Forms\Components\TextInput::make('code')
->label('终端编码')
->required()
->unique(ignoreRecord: true)
->maxLength(100)
->placeholder('例如: TERM-0001')
->helperText('终端的唯一标识符')
->regex('/^[A-Z0-9\-]+$/')
->validationMessages([
'regex' => '终端编码只能包含大写字母、数字和连字符',
]),
Forms\Components\TextInput::make('ip_address')
->label('IP地址')
->ip()
->maxLength(45)
->placeholder('例如: 192.168.1.100')
->helperText('终端的IP地址'),
Forms\Components\TextInput::make('mac_address')
->label('MAC地址')
->maxLength(17)
->placeholder('AA:BB:CC:DD:EE:FF')
->helperText('终端的MAC地址用于自动识别终端')
->regex('/^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/')
->validationMessages([
'regex' => 'MAC地址格式不正确应为 AA:BB:CC:DD:EE:FF',
]),
Forms\Components\TextInput::make('station_id')
->label('线站ID')
->maxLength(50)
->placeholder('例如: BL02U1')
->helperText('关联的光束线/线站标识'),
])
->columns(2),
Forms\Components\Section::make('组态配置')
->schema([
Forms\Components\TextInput::make('diagram_url')
->label('组态界面地址')
->url()
->maxLength(500)
->placeholder('https://example.com/diagram.png')
->helperText('组态界面的访问地址'),
]),
Forms\Components\Section::make('网关配置')
->schema([
Forms\Components\TextInput::make('scada_data_url')
->label('数据查询URL')
->url()
->maxLength(500)
->placeholder('http://gateway:8080/api/data')
->helperText('网关的数据查询地址'),
Forms\Components\TextInput::make('scada_tags_url')
->label('点位定义URL')
->url()
->maxLength(500)
->placeholder('http://gateway:8080/api/tags')
->helperText('网关的点位定义查询地址'),
])
->columns(2),
Forms\Components\Section::make('知识库关联')
->schema([
Forms\Components\Repeater::make('knowledgeBaseAssociations')
->label('关联知识库')
->relationship('knowledgeBases')
->schema([
Forms\Components\Select::make('id')
->label('知识库')
->options(\App\Models\KnowledgeBase::where('status', 'active')->pluck('name', 'id'))
->required()
->searchable()
->distinct()
->disableOptionsWhenSelectedInSiblingRepeaterItems()
->helperText('选择要关联的知识库'),
Forms\Components\TextInput::make('priority')
->label('优先级')
->numeric()
->default(0)
->required()
->minValue(0)
->helperText('数字越小优先级越高0为最高优先级'),
])
->columns(2)
->reorderable()
->reorderableWithButtons()
->addActionLabel('添加知识库')
->reorderableWithDragAndDrop(false)
->itemLabel(
fn(array $state): ?string =>
\App\Models\KnowledgeBase::find($state['id'])?->name ?? '未选择'
)
->collapsed()
->collapsible()
->helperText('可以关联多个知识库,并设置优先级。拖动或使用按钮调整顺序。'),
])
->description('配置终端可以访问的知识库及其优先级'),
Forms\Components\Section::make('指引关联')
->schema([
Forms\Components\Repeater::make('guideAssociations')
->label('关联指引')
->relationship('guides')
->schema([
Forms\Components\Select::make('id')
->label('指引')
->options(\App\Models\Guide::where('status', 'published')->pluck('name', 'id'))
->required()
->searchable()
->distinct()
->disableOptionsWhenSelectedInSiblingRepeaterItems()
->helperText('选择要关联的指引'),
Forms\Components\TextInput::make('priority')
->label('优先级')
->numeric()
->default(0)
->required()
->minValue(0)
->helperText('数字越小优先级越高0为最高优先级'),
])
->columns(2)
->reorderable()
->reorderableWithButtons()
->addActionLabel('添加指引')
->reorderableWithDragAndDrop(false)
->itemLabel(
fn(array $state): ?string =>
\App\Models\Guide::find($state['id'])?->name ?? '未选择'
)
->collapsed()
->collapsible()
->helperText('可以关联多个指引,并设置优先级。拖动或使用按钮调整顺序。'),
])
->description('配置终端可以访问的操作指引及其优先级'),
Forms\Components\Section::make('AI提示词配置')
->schema([
Forms\Components\Grid::make(3)
->schema([
\AbdelhamidErrahmouni\FilamentMonacoEditor\MonacoEditor::make('prompt.prompt_template')
->label('提示词模板')
->language('markdown')
->fontSize('14px')
->helperText('编辑AI提示词模板支持使用变量如 {user}, {station}, {time} 等')
->placeholderText('请输入AI提示词模板...')
->disablePreview()
->columnSpan(2),
Forms\Components\Grid::make(1)
->schema([
Forms\Components\Placeholder::make('template_selector')
->label('模板库')
->content(fn() => view('filament.components.prompt-template-selector')),
Forms\Components\Placeholder::make('variable_helper')
->label('变量参考')
->content(fn() => view('filament.components.prompt-variable-helper')),
])
->columnSpan(1),
]),
])
->description('配置终端的AI提示词模板用于指导AI助手的行为')
->collapsible(),
Forms\Components\Section::make('状态信息')
->schema([
Forms\Components\Toggle::make('is_online')
->label('在线状态')
->helperText('终端是否在线')
->default(false)
->disabled()
->dehydrated(false),
Forms\Components\DateTimePicker::make('last_online_at')
->label('最后在线时间')
->disabled()
->dehydrated(false),
])
->columns(2)
->visibleOn('edit'),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name')
->label('终端名称')
->searchable()
->sortable()
->weight('bold'),
Tables\Columns\TextColumn::make('code')
->label('终端编码')
->searchable()
->sortable()
->copyable()
->tooltip('点击复制'),
Tables\Columns\TextColumn::make('mac_address')
->label('MAC地址')
->searchable()
->copyable()
->placeholder('未设置')
->toggleable(),
Tables\Columns\TextColumn::make('ip_address')
->label('IP地址')
->searchable()
->copyable()
->placeholder('未设置'),
Tables\Columns\TextColumn::make('station_id')
->label('线站ID')
->sortable()
->placeholder('未绑定'),
Tables\Columns\IconColumn::make('is_online')
->label('在线状态')
->boolean()
->trueIcon('heroicon-o-check-circle')
->falseIcon('heroicon-o-x-circle')
->trueColor('success')
->falseColor('danger')
->sortable(),
Tables\Columns\TextColumn::make('last_online_at')
->label('最后在线时间')
->dateTime('Y-m-d H:i:s')
->sortable()
->placeholder('从未在线')
->toggleable(),
Tables\Columns\TextColumn::make('created_at')
->label('创建时间')
->dateTime('Y-m-d H:i:s')
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->label('更新时间')
->dateTime('Y-m-d H:i:s')
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
Tables\Filters\TernaryFilter::make('is_online')
->label('在线状态')
->placeholder('全部')
->trueLabel('在线')
->falseLabel('离线'),
])
->actions([
Tables\Actions\ViewAction::make()
->label('查看'),
Tables\Actions\EditAction::make()
->label('编辑'),
Tables\Actions\DeleteAction::make()
->label('删除'),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make()
->label('批量删除'),
]),
])
->defaultSort('created_at', 'desc')
->groups([
Tables\Grouping\Group::make('station_id')
->label('按线站分组')
->collapsible(),
Tables\Grouping\Group::make('is_online')
->label('按在线状态分组')
->getTitleFromRecordUsing(fn(Terminal $record): string => $record->is_online ? '在线' : '离线')
->collapsible(),
]);
}
public static function getPages(): array
{
return [
'index' => Pages\ListTerminals::route('/'),
'create' => Pages\CreateTerminal::route('/create'),
'edit' => Pages\EditTerminal::route('/{record}/edit'),
'view' => Pages\ViewTerminal::route('/{record}'),
];
}
}