更新显示架构
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\service;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\facade\Config;
|
||||
|
||||
/**
|
||||
* 模板服务类
|
||||
* 负责扫描 public/themes 目录,管理模板配置
|
||||
*/
|
||||
class ThemeService
|
||||
{
|
||||
private string $themesPath;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->themesPath = root_path() . 'public' . DIRECTORY_SEPARATOR . 'themes';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有可用模板列表
|
||||
* @return array
|
||||
*/
|
||||
public function getThemeList(): array
|
||||
{
|
||||
$themes = [];
|
||||
$dirs = $this->scanThemeDirs();
|
||||
|
||||
foreach ($dirs as $dir) {
|
||||
$config = $this->readThemeConfig($dir);
|
||||
$preview = $this->getThemePreview($dir);
|
||||
|
||||
$themes[] = [
|
||||
'key' => $dir,
|
||||
'name' => $config['name'] ?? $dir,
|
||||
'description'=> $config['description'] ?? '',
|
||||
'version' => $config['version'] ?? '1.0.0',
|
||||
'author' => $config['author'] ?? '',
|
||||
'preview' => $preview,
|
||||
'path' => '/themes/' . $dir . '/index.html',
|
||||
'fields' => $config['fields'] ?? [],
|
||||
];
|
||||
}
|
||||
|
||||
return $themes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描模板目录
|
||||
* @return array
|
||||
*/
|
||||
private function scanThemeDirs(): array
|
||||
{
|
||||
$dirs = [];
|
||||
|
||||
if (!is_dir($this->themesPath)) {
|
||||
return $dirs;
|
||||
}
|
||||
|
||||
$items = scandir($this->themesPath);
|
||||
foreach ($items as $item) {
|
||||
if ($item === '.' || $item === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fullPath = $this->themesPath . DIRECTORY_SEPARATOR . $item;
|
||||
if (is_dir($fullPath) && is_file($fullPath . DIRECTORY_SEPARATOR . 'index.html')) {
|
||||
$dirs[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取模板配置文件
|
||||
* @param string $themeDir
|
||||
* @return array
|
||||
*/
|
||||
private function readThemeConfig(string $themeDir): array
|
||||
{
|
||||
$configPath = $this->themesPath . DIRECTORY_SEPARATOR . $themeDir . DIRECTORY_SEPARATOR . 'config.json';
|
||||
|
||||
if (!is_file($configPath)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$content = file_get_contents($configPath);
|
||||
$config = json_decode($content, true);
|
||||
|
||||
return $config ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模板预览图
|
||||
* @param string $themeDir
|
||||
* @return string
|
||||
*/
|
||||
private function getThemePreview(string $themeDir): string
|
||||
{
|
||||
$previewPath = '/themes/' . $themeDir . '/preview.png';
|
||||
|
||||
// 如果 preview.png 不存在,使用默认占位图
|
||||
$fullPath = $this->themesPath . DIRECTORY_SEPARATOR . $themeDir . DIRECTORY_SEPARATOR . 'preview.png';
|
||||
if (!is_file($fullPath)) {
|
||||
return 'https://picsum.photos/300/200?random=' . ord($themeDir[0]);
|
||||
}
|
||||
|
||||
return $previewPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前激活的模板Key
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrentTheme(): string
|
||||
{
|
||||
try {
|
||||
$config = Db::name('mete_template_site_config')
|
||||
->where('key', 'current_theme')
|
||||
->where('delete_time', null)
|
||||
->find();
|
||||
return $config['value'] ?? 'default';
|
||||
} catch (\Exception $e) {
|
||||
return 'default';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换当前模板
|
||||
* @param string $themeKey
|
||||
* @return bool
|
||||
*/
|
||||
public function switchTheme(string $themeKey): bool
|
||||
{
|
||||
// 验证模板是否存在
|
||||
$themes = $this->getThemeList();
|
||||
$exists = false;
|
||||
foreach ($themes as $theme) {
|
||||
if ($theme['key'] === $themeKey) {
|
||||
$exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$exists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 查找或创建配置记录
|
||||
$config = Db::name('mete_template_site_config')
|
||||
->where('key', 'current_theme')
|
||||
->where('delete_time', null)
|
||||
->find();
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
if ($config) {
|
||||
Db::name('mete_template_site_config')->where('id', $config['id'])->update([
|
||||
'value' => $themeKey,
|
||||
'update_time' => $now
|
||||
]);
|
||||
} else {
|
||||
Db::name('mete_template_site_config')->insert([
|
||||
'key' => 'current_theme',
|
||||
'value' => $themeKey,
|
||||
'create_time' => $now,
|
||||
'update_time' => $now
|
||||
]);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模板数据(用于前端渲染)
|
||||
* @param string|null $themeKey
|
||||
* @return array
|
||||
*/
|
||||
public function getThemeData(?string $themeKey = null): array
|
||||
{
|
||||
$themeKey = $themeKey ?? $this->getCurrentTheme();
|
||||
|
||||
try {
|
||||
$themeData = Db::name('mete_template_theme_data')
|
||||
->where('theme_key', $themeKey)
|
||||
->where('delete_time', null)
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$data = [];
|
||||
foreach ($themeData as $item) {
|
||||
$data[$item['field_key']] = $item['field_value'];
|
||||
}
|
||||
|
||||
return [
|
||||
'theme_key' => $themeKey,
|
||||
'theme_path' => '/themes/' . $themeKey . '/index.html',
|
||||
'data' => $data
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
return [
|
||||
'theme_key' => $themeKey,
|
||||
'theme_path' => '/themes/' . $themeKey . '/index.html',
|
||||
'data' => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存模板字段数据
|
||||
* @param string $themeKey
|
||||
* @param string $fieldKey
|
||||
* @param mixed $fieldValue
|
||||
* @return bool
|
||||
*/
|
||||
public function saveThemeField(string $themeKey, string $fieldKey, $fieldValue): bool
|
||||
{
|
||||
try {
|
||||
$existing = Db::name('mete_template_theme_data')
|
||||
->where('theme_key', $themeKey)
|
||||
->where('field_key', $fieldKey)
|
||||
->where('delete_time', null)
|
||||
->find();
|
||||
|
||||
$value = is_array($fieldValue) ? json_encode($fieldValue, JSON_UNESCAPED_UNICODE) : $fieldValue;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
if ($existing) {
|
||||
Db::name('mete_template_theme_data')
|
||||
->where('id', $existing['id'])
|
||||
->update([
|
||||
'field_value' => $value,
|
||||
'update_time' => $now
|
||||
]);
|
||||
} else {
|
||||
Db::name('mete_template_theme_data')->insert([
|
||||
'theme_key' => $themeKey,
|
||||
'field_key' => $fieldKey,
|
||||
'field_value' => $value,
|
||||
'create_time' => $now,
|
||||
'update_time' => $now
|
||||
]);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user