Xboard/app/Http/Controllers/V2/Admin/ThemeController.php

150 lines
4.2 KiB
PHP
Raw 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
namespace App\Http\Controllers\V2\Admin;
use App\Exceptions\ApiException;
use App\Http\Controllers\Controller;
use App\Services\ThemeService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
class ThemeController extends Controller
{
private $themeService;
public function __construct(ThemeService $themeService)
{
$this->themeService = $themeService;
}
/**
* 上传新主题
*
* @throws ApiException
*/
public function upload(Request $request)
{
$request->validate([
'file' => [
'required',
'file',
'mimes:zip',
'max:10240', // 最大10MB
]
], [
'file.required' => '请选择主题包文件',
'file.file' => '无效的文件类型',
'file.mimes' => '主题包必须是zip格式',
'file.max' => '主题包大小不能超过10MB'
]);
try {
// 检查上传目录权限
$uploadPath = storage_path('tmp');
if (!File::exists($uploadPath)) {
File::makeDirectory($uploadPath, 0755, true);
}
if (!is_writable($uploadPath)) {
throw new ApiException('上传目录无写入权限');
}
// 检查主题目录权限
$themePath = base_path('theme');
if (!is_writable($themePath)) {
throw new ApiException('主题目录无写入权限');
}
$file = $request->file('file');
// 检查文件MIME类型
$mimeType = $file->getMimeType();
if (!in_array($mimeType, ['application/zip', 'application/x-zip-compressed'])) {
throw new ApiException('无效的文件类型仅支持ZIP格式');
}
// 检查文件名安全性
$originalName = $file->getClientOriginalName();
if (!preg_match('/^[a-zA-Z0-9\-\_\.]+\.zip$/', $originalName)) {
throw new ApiException('主题包文件名只能包含字母、数字、下划线、中划线和点');
}
$this->themeService->upload($file);
return $this->success(true);
} catch (ApiException $e) {
throw $e;
} catch (\Exception $e) {
\Log::error('Theme upload failed', [
'error' => $e->getMessage(),
'file' => $request->file('file')?->getClientOriginalName()
]);
throw new ApiException('主题上传失败:' . $e->getMessage());
}
}
/**
* 删除主题
*/
public function delete(Request $request)
{
$payload = $request->validate([
'name' => 'required'
]);
$this->themeService->delete($payload['name']);
return $this->success(true);
}
/**
* 获取所有主题和其配置列
*
* @return \Illuminate\Http\JsonResponse
*/
public function getThemes()
{
$data = [
'themes' => $this->themeService->getList(),
'active' => admin_setting('frontend_theme', 'Xboard')
];
return $this->success($data);
}
/**
* 切换主题
*/
public function switchTheme(Request $request)
{
$payload = $request->validate([
'name' => 'required'
]);
$this->themeService->switch($payload['name']);
return $this->success(true);
}
/**
* 获取主题配置
*/
public function getThemeConfig(Request $request)
{
$payload = $request->validate([
'name' => 'required'
]);
$data = $this->themeService->getConfig($payload['name']);
return $this->success($data);
}
/**
* 保存主题配置
*/
public function saveThemeConfig(Request $request)
{
$payload = $request->validate([
'name' => 'required',
'config' => 'required'
]);
$this->themeService->updateConfig($payload['name'], $payload['config']);
$config = $this->themeService->getConfig($payload['name']);
return $this->success($config);
}
}