2026-02-05 22:22:10 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Filament\Pages;
|
|
|
|
|
|
|
|
|
|
|
|
use App\Models\SiteSetting;
|
|
|
|
|
|
use Filament\Forms\Components\FileUpload;
|
|
|
|
|
|
use Filament\Forms\Components\Section;
|
|
|
|
|
|
use Filament\Forms\Components\Textarea;
|
|
|
|
|
|
use Filament\Forms\Components\TextInput;
|
|
|
|
|
|
use Filament\Forms\Components\Toggle;
|
|
|
|
|
|
use Filament\Forms\Concerns\InteractsWithForms;
|
|
|
|
|
|
use Filament\Forms\Contracts\HasForms;
|
|
|
|
|
|
use Filament\Forms\Form;
|
2026-02-07 22:55:07 +08:00
|
|
|
|
use Filament\Notifications\Notification;
|
2026-02-05 22:22:10 +08:00
|
|
|
|
use Filament\Pages\Page;
|
|
|
|
|
|
|
|
|
|
|
|
class SiteSettings extends Page implements HasForms
|
|
|
|
|
|
{
|
|
|
|
|
|
use InteractsWithForms;
|
|
|
|
|
|
|
|
|
|
|
|
protected static ?string $navigationIcon = 'heroicon-o-cog-6-tooth';
|
|
|
|
|
|
protected static ?string $navigationLabel = '站点配置';
|
|
|
|
|
|
protected static ?string $navigationGroup = '站点设置';
|
|
|
|
|
|
protected static string $view = 'filament.pages.site-settings';
|
|
|
|
|
|
|
|
|
|
|
|
public ?array $data = [];
|
|
|
|
|
|
|
|
|
|
|
|
public function mount(): void
|
|
|
|
|
|
{
|
|
|
|
|
|
$this->form->fill($this->getSettings());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function form(Form $form): Form
|
|
|
|
|
|
{
|
|
|
|
|
|
return $form
|
|
|
|
|
|
->schema([
|
|
|
|
|
|
Section::make('站点信息')
|
|
|
|
|
|
->schema([
|
|
|
|
|
|
TextInput::make('site_title')->label('站点标题')->required(),
|
|
|
|
|
|
TextInput::make('site_description')->label('站点描述'),
|
|
|
|
|
|
FileUpload::make('site_logo')
|
|
|
|
|
|
->label('站点 Logo')
|
|
|
|
|
|
->disk('public')
|
|
|
|
|
|
->directory('site')
|
|
|
|
|
|
->image()
|
|
|
|
|
|
->imagePreviewHeight('80')
|
|
|
|
|
|
->nullable(),
|
|
|
|
|
|
Textarea::make('site_footer')
|
|
|
|
|
|
->label('页脚文案')
|
|
|
|
|
|
->rows(2),
|
|
|
|
|
|
])->columns(2),
|
|
|
|
|
|
Section::make('首页配置')
|
|
|
|
|
|
->schema([
|
|
|
|
|
|
TextInput::make('home_featured_limit')->label('热门推荐数量')->numeric()->required(),
|
2026-02-07 22:55:07 +08:00
|
|
|
|
TextInput::make('home_new_limit')->label('新增产品数量')->numeric()->required(),
|
2026-02-05 22:22:10 +08:00
|
|
|
|
TextInput::make('home_category_limit')->label('分类展示数量')->numeric()->required(),
|
|
|
|
|
|
])->columns(3),
|
|
|
|
|
|
Section::make('列表配置')
|
|
|
|
|
|
->schema([
|
|
|
|
|
|
TextInput::make('list_page_size')->label('产品列表分页数')->numeric()->required(),
|
|
|
|
|
|
TextInput::make('list_more_threshold')->label('更多阈值')->numeric()->required(),
|
|
|
|
|
|
TextInput::make('article_page_size')->label('文章列表分页数')->numeric()->required(),
|
|
|
|
|
|
])->columns(3),
|
|
|
|
|
|
Section::make('评论与推广')
|
|
|
|
|
|
->schema([
|
|
|
|
|
|
Toggle::make('comments_enabled')->label('启用评论'),
|
|
|
|
|
|
Toggle::make('show_sponsor_label')->label('显示推广标识'),
|
|
|
|
|
|
])->columns(2),
|
|
|
|
|
|
Section::make('热度权重')
|
|
|
|
|
|
->schema([
|
|
|
|
|
|
TextInput::make('hot_weight_view')->label('浏览权重')->numeric()->required(),
|
|
|
|
|
|
TextInput::make('hot_weight_click')->label('点击权重')->numeric()->required(),
|
|
|
|
|
|
])->columns(2),
|
|
|
|
|
|
Section::make('SEO 与统计')
|
|
|
|
|
|
->schema([
|
|
|
|
|
|
TextInput::make('ga_id')->label('GA4 测量 ID')->nullable(),
|
|
|
|
|
|
TextInput::make('icp_number')->label('备案号')->nullable(),
|
|
|
|
|
|
Textarea::make('social_links')
|
|
|
|
|
|
->label('社交链接(每行:名称|URL)')
|
|
|
|
|
|
->rows(3)
|
|
|
|
|
|
->nullable(),
|
|
|
|
|
|
Textarea::make('about_content')
|
|
|
|
|
|
->label('关于页内容(Markdown)')
|
|
|
|
|
|
->rows(4)
|
|
|
|
|
|
->nullable(),
|
|
|
|
|
|
])->columns(2),
|
|
|
|
|
|
])
|
|
|
|
|
|
->statePath('data');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function save(): void
|
|
|
|
|
|
{
|
|
|
|
|
|
$data = $this->form->getState();
|
|
|
|
|
|
|
|
|
|
|
|
foreach ($data as $key => $value) {
|
|
|
|
|
|
$value = $this->normalizeValue($value);
|
|
|
|
|
|
SiteSetting::updateOrCreate(['key' => $key], ['value' => $value]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-07 22:55:07 +08:00
|
|
|
|
Notification::make()
|
|
|
|
|
|
->title('保存成功')
|
|
|
|
|
|
->success()
|
|
|
|
|
|
->send();
|
2026-02-05 22:22:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function getSettings(): array
|
|
|
|
|
|
{
|
|
|
|
|
|
$defaults = [
|
|
|
|
|
|
'site_title' => 'AI 工具导航',
|
|
|
|
|
|
'site_description' => '精选 AI 工具与产品导航',
|
|
|
|
|
|
'site_logo' => null,
|
|
|
|
|
|
'site_footer' => '',
|
|
|
|
|
|
'home_featured_limit' => '8',
|
|
|
|
|
|
'home_new_limit' => '8',
|
|
|
|
|
|
'home_category_limit' => '20',
|
|
|
|
|
|
'list_page_size' => '20',
|
|
|
|
|
|
'list_more_threshold' => '20',
|
|
|
|
|
|
'article_page_size' => '10',
|
|
|
|
|
|
'comments_enabled' => '1',
|
|
|
|
|
|
'show_sponsor_label' => '1',
|
|
|
|
|
|
'hot_weight_view' => '1',
|
|
|
|
|
|
'hot_weight_click' => '3',
|
|
|
|
|
|
'ga_id' => '',
|
|
|
|
|
|
'icp_number' => '',
|
|
|
|
|
|
'social_links' => '',
|
|
|
|
|
|
'about_content' => SiteSetting::value('about_content', ''),
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
$data = [];
|
|
|
|
|
|
foreach ($defaults as $key => $default) {
|
|
|
|
|
|
$data[$key] = SiteSetting::value($key, $default);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$data['comments_enabled'] = $data['comments_enabled'] === '1';
|
|
|
|
|
|
$data['show_sponsor_label'] = $data['show_sponsor_label'] === '1';
|
|
|
|
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function normalizeValue($value): ?string
|
|
|
|
|
|
{
|
|
|
|
|
|
if (is_bool($value)) {
|
|
|
|
|
|
return $value ? '1' : '0';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (is_array($value)) {
|
|
|
|
|
|
return json_encode($value, JSON_UNESCAPED_UNICODE);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ($value === null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return (string) $value;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|