M2: 主题系统(sablog经典+modern简约)+ 前台全部页面 + 老 URL 301 兼容 + markdown 双份导入

This commit is contained in:
ak
2026-08-11 17:58:29 +08:00
parent f16bb75538
commit 6214976a88
66 changed files with 2763 additions and 10 deletions
+112
View File
@@ -0,0 +1,112 @@
<?php
namespace App\Blog\Support;
use App\Models\Setting;
use Illuminate\Support\Facades\File;
class ThemeManager
{
public function path(?string $theme = null): string
{
return config('themes.path').($theme ? '/'.$theme : '');
}
public function active(): string
{
$active = Setting::get('active_theme', config('themes.default'));
return $this->exists($active) ? $active : config('themes.default');
}
public function exists(string $theme): bool
{
return is_dir($this->path($theme)) && File::exists($this->path($theme).'/theme.json');
}
public function manifest(string $theme): array
{
$file = $this->path($theme).'/theme.json';
if (! File::exists($file)) {
return [];
}
return json_decode(File::get($file), true) ?? [];
}
/**
* 扫描主题目录,返回所有主题 manifest。
*/
public function all(): array
{
$themes = [];
foreach (File::directories(config('themes.path')) as $dir) {
$name = basename($dir);
if (! File::exists($dir.'/theme.json')) {
continue;
}
$manifest = $this->manifest($name);
$themes[$name] = [
'name' => $name,
'title' => $manifest['title'] ?? $name,
'version' => $manifest['version'] ?? '0.0.0',
'description' => $manifest['description'] ?? '',
'author' => $manifest['author'] ?? '',
'screenshot' => $manifest['screenshot'] ?? null,
'active' => $name === $this->active(),
];
}
return $themes;
}
public function activate(string $theme): void
{
if (! $this->exists($theme)) {
throw new \InvalidArgumentException("主题不存在: {$theme}");
}
Setting::set('active_theme', $theme);
}
/**
* 解析主题下的一个视图名。
* 优先使用激活主题的视图,缺失时回退到内置兜底视图(blog-default)。
*/
public function view(string $view): string
{
$active = $this->active();
if (view()->exists("theme.{$active}.{$view}")) {
return "theme.{$active}.{$view}";
}
return "blog-default::{$view}";
}
public function assetUrl(string $path, ?string $theme = null): string
{
$theme = $theme ?? $this->active();
return url('/themes/'.$theme.'/assets/'.ltrim($path, '/'));
}
/**
* 主题变量(原 sablog stylevars 的现代化替代:主题级自定义配置)。
*/
public function variables(?string $theme = null): array
{
$theme = $theme ?? $this->active();
$vars = Setting::get('theme_vars_'.$theme, []);
return is_array($vars) ? $vars : (json_decode((string) $vars, true) ?: []);
}
public function variable(string $key, mixed $default = null, ?string $theme = null): mixed
{
return $this->variables($theme)[$key] ?? $default;
}
}