Files
goukiandCursor ae47447062
Build and Deploy / verify (push) Successful in 40s
Build and Deploy / deploy (push) Successful in 36s
feat: restore sablog browse modes and clean imported HTML
Keep the public site readable after import (nbsp, highlighter, wrapping code, compact pager) and finish the admin extras already in this tree: sticky levels, preview, page cache, and live llms.txt.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 21:33:02 +00:00

195 lines
11 KiB
PHP
Raw Permalink 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
declare(strict_types=1);
namespace App\Filament\Pages;
use App\Models\Setting;
use Filament\Actions\Action;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
use Filament\Schemas\Schema;
class BlogSettings extends Page
{
use InteractsWithForms;
protected static \UnitEnum|string|null $navigationGroup = '管理';
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-cog-6-tooth';
protected static ?string $navigationLabel = '博客设置';
protected static ?string $title = '博客设置';
protected string $view = 'filament.pages.blog-settings';
public array $data = [];
public function mount(): void
{
$this->form->fill([
// 站点
'site_name' => Setting::get('site_name', config('blog.name')),
'site_description' => Setting::get('site_description', config('blog.description')),
'site_icp' => Setting::get('site_icp', config('blog.icp')),
// 外观
'active_theme' => Setting::get('active_theme', config('themes.default')),
'per_page' => Setting::get('per_page', config('blog.per_page')),
'home_view_mode' => Setting::get('home_view_mode', config('blog.home_view_mode', 'list')),
'list_shownum' => Setting::get('list_shownum', '50'),
'listtime' => Setting::get('listtime', 'Y-m-d'),
'normaltime' => Setting::get('normaltime', 'Y-m-d H:i'),
// 订阅与 SEO
'rss_num' => Setting::get('rss_num', config('blog.rss_num')),
'rss_ttl' => Setting::get('rss_ttl', '30'),
'seo_default_keywords' => Setting::get('seo_default_keywords', ''),
'seo_default_description' => Setting::get('seo_default_description', ''),
// 评论
'comment_audit' => Setting::get('comment_audit', '0'),
'comment_order' => Setting::get('comment_order', '1'),
'comment_min_len' => Setting::get('comment_min_len', config('blog.comment_min_len')),
'comment_max_len' => Setting::get('comment_max_len', config('blog.comment_max_len')),
'comment_post_space' => Setting::get('comment_post_space', config('blog.comment_post_space')),
'comment_timeformat' => Setting::get('comment_timeformat', 'Y-m-d H:i'),
// 附件
'attachments_thumbs' => Setting::get('attachments_thumbs', '1'),
'attachments_thumbs_size' => Setting::get('attachments_thumbs_size', '500x500'),
'watermark' => Setting::get('watermark', '0'),
'watermark_size' => Setting::get('watermark_size', '300x300'),
'watermarktrans' => Setting::get('watermarktrans', '100'),
// 维护
'site_closed' => Setting::get('site_closed', '0'),
'site_closed_note' => Setting::get('site_closed_note', ''),
// 社交账号
'social_weibo' => Setting::get('social_weibo', ''),
'social_github' => Setting::get('social_github', ''),
'social_twitter' => Setting::get('social_twitter', ''),
'social_facebook' => Setting::get('social_facebook', ''),
'social_zhihu' => Setting::get('social_zhihu', ''),
'social_bilibili' => Setting::get('social_bilibili', ''),
'social_xiaohongshu' => Setting::get('social_xiaohongshu', ''),
'social_douyin' => Setting::get('social_douyin', ''),
'social_wechat_channel' => Setting::get('social_wechat_channel', ''),
'social_wechat_public' => Setting::get('social_wechat_public', ''),
'social_email' => Setting::get('social_email', ''),
'social_other' => Setting::get('social_other', []),
]);
}
public function form(Schema $schema): Schema
{
return $schema
->components([
Tabs::make('settings-tabs')
->tabs([
Tab::make('站点')
->schema([
TextInput::make('site_name')->label('站点名称')->required(),
TextInput::make('site_description')->label('站点描述')->columnSpanFull(),
TextInput::make('site_icp')->label('ICP 备案号'),
]),
Tab::make('外观')
->columns(2)
->schema([
Select::make('active_theme')
->label('激活主题')
->columnSpanFull()
->options(collect(app(\App\Blog\Support\ThemeManager::class)->all())->pluck('title', 'name')),
TextInput::make('per_page')->label('首页每页文章数')->numeric(),
Select::make('home_view_mode')
->label('首页浏览模式')
->options([
'list' => '列表(标题 + 摘要)',
'full' => '标准(全文)',
])
->helperText('前台右上角仍可临时切换,和老 sablog 的「标准 | 列表」一样'),
TextInput::make('list_shownum')->label('列表每页数量')->numeric()->helperText('分类/标签/搜索等列表页'),
TextInput::make('listtime')->label('列表时间格式')->placeholder('Y-m-d'),
TextInput::make('normaltime')->label('详情时间格式')->placeholder('Y-m-d H:i'),
]),
Tab::make('订阅与 SEO')
->columns(2)
->schema([
TextInput::make('rss_num')->label('RSS 文章数')->numeric(),
TextInput::make('rss_ttl')->label('RSS TTL(分钟)')->numeric(),
TextInput::make('seo_default_keywords')->label('默认关键词')->columnSpanFull(),
TextInput::make('seo_default_description')->label('默认描述')->columnSpanFull(),
]),
Tab::make('评论')
->columns(2)
->schema([
Toggle::make('comment_audit')->label('新评论需审核')->default(false),
Select::make('comment_order')->label('评论排序')
->options(['1' => '正序(旧在前)', '0' => '倒序(新在前)']),
TextInput::make('comment_min_len')->label('最短字数')->numeric(),
TextInput::make('comment_max_len')->label('最长字数')->numeric(),
TextInput::make('comment_post_space')->label('评论间隔(秒)')->numeric(),
TextInput::make('comment_timeformat')->label('评论时间格式')->placeholder('Y-m-d H:i'),
]),
Tab::make('附件')
->columns(2)
->schema([
Toggle::make('attachments_thumbs')->label('生成缩略图')->default(true),
TextInput::make('attachments_thumbs_size')->label('缩略图尺寸')->placeholder('500x500'),
Toggle::make('watermark')->label('图片水印')->default(false),
TextInput::make('watermark_size')->label('水印触发尺寸')->placeholder('300x300'),
TextInput::make('watermarktrans')->label('水印透明度(%)')->numeric(),
]),
Tab::make('社交账号')
->columns(2)
->schema([
TextInput::make('social_weibo')->label('微博')->url()->placeholder('https://weibo.com/xxx'),
TextInput::make('social_zhihu')->label('知乎')->url()->placeholder('https://zhihu.com/people/xxx'),
TextInput::make('social_bilibili')->label('哔哩哔哩')->url()->placeholder('https://space.bilibili.com/xxx'),
TextInput::make('social_xiaohongshu')->label('小红书')->url()->placeholder('https://xiaohongshu.com/user/profile/xxx'),
TextInput::make('social_douyin')->label('抖音')->url()->placeholder('https://www.douyin.com/user/xxx'),
TextInput::make('social_wechat_channel')->label('视频号')->url()->placeholder('https://channels.weixin.qq.com/xxx'),
TextInput::make('social_wechat_public')->label('微信公众号')->placeholder('公众号名称 / 微信号(无外链时用于展示)'),
TextInput::make('social_github')->label('GitHub')->url()->placeholder('https://github.com/xxx'),
TextInput::make('social_twitter')->label('Twitter / X')->url()->placeholder('https://x.com/xxx'),
TextInput::make('social_facebook')->label('Facebook')->url()->placeholder('https://facebook.com/xxx'),
TextInput::make('social_email')->label('邮箱')->email()->placeholder('contact@example.com'),
\Filament\Forms\Components\KeyValue::make('social_other')
->label('其他平台')
->keyLabel('平台名')
->valueLabel('链接 / 名称')
->columnSpanFull(),
]),
Tab::make('维护')
->schema([
Toggle::make('site_closed')->label('关闭站点')->default(false),
TextInput::make('site_closed_note')->label('关闭说明')->columnSpanFull(),
]),
]),
])
->statePath('data');
}
public function save(): void
{
$data = $this->form->getState();
foreach ($data as $key => $value) {
Setting::set($key, is_bool($value) ? (string) (int) $value : (string) $value);
}
Notification::make()->title('设置已保存')->success()->send();
}
protected function getFormActions(): array
{
return [
Action::make('save')
->label('保存设置')
->submit('save'),
];
}
}