form->fill([ 'inject' => $this->normalizeBlocks(Setting::get('inject.blocks', [])), 'theme_vars' => app(ThemeManager::class)->variables(), ]); } public function form(Schema $schema): Schema { $groups = [ '页面级' => ['head', 'header', 'content_top', 'content_bottom', 'footer', 'body_end'], '侧边栏级' => ['sidebar_top', 'sidebar_bottom'], '文章级' => ['post_content_top', 'post_content_bottom'], ]; $tabs = []; foreach ($groups as $groupLabel => $points) { $sections = []; foreach ($points as $point) { $sections[] = \Filament\Schemas\Components\Section::make(ThemeInjector::POINTS[$point]) ->description($point) ->schema([ Repeater::make("inject.{$point}") ->label('注入块(多条按拖拽顺序渲染)') ->schema([ TextInput::make('title')->label('名称')->placeholder('如:百度统计')->columnSpan(2), Textarea::make('html')->label('内容(HTML)')->rows(3)->columnSpanFull(), Toggle::make('enabled')->label('启用')->default(true), ]) ->columns(3) ->defaultItems(0) ->collapsible() ->reorderable() ->reorderableWithButtons() ->addActionLabel('添加一条'), ]); } $tabs[] = Tab::make($groupLabel)->schema($sections); } $tabs[] = Tab::make('主题变量(stylevar)') ->schema([ KeyValue::make('theme_vars') ->label('当前主题变量:视图用 {{ theme(\'var\', \'key\') }} 引用') ->keyLabel('变量名') ->valueLabel('内容(HTML)') ->reorderable() ->columnSpanFull(), ]); return $schema ->components([ Tabs::make('inject-tabs') ->tabs($tabs), ]) ->statePath('data'); } public function save(): void { $data = $this->form->getState(); $blocks = []; foreach ($data['inject'] ?? [] as $point => $items) { $order = 0; foreach ($items ?? [] as $item) { if (trim((string) ($item['html'] ?? '')) === '') { continue; } $blocks[] = [ 'point' => $point, 'title' => $item['title'] ?? '', 'html' => $item['html'], 'sort' => $order++, 'enabled' => (bool) ($item['enabled'] ?? true), ]; } } Setting::set('inject.blocks', $blocks); Setting::set('theme_vars_'.app(ThemeManager::class)->active(), $data['theme_vars'] ?? []); Notification::make()->title('注入内容已保存')->success()->send(); } protected function getFormActions(): array { return [ Action::make('save')->label('保存')->submit('save'), ]; } private function normalizeBlocks(mixed $blocks): array { if (! is_array($blocks)) { $blocks = json_decode((string) $blocks, true) ?: []; } $normalized = []; foreach ($blocks as $b) { $point = $b['point'] ?? null; if (! $point) { continue; } $normalized[$point][] = [ 'title' => $b['title'] ?? '', 'html' => $b['html'] ?? '', 'sort' => (int) ($b['sort'] ?? 0), 'enabled' => (bool) ($b['enabled'] ?? true), ]; } return $normalized; } }