diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 772a0dfd..2e65bc4a 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use View; use Utils; +use Option; use App\Models\User; use App\Models\Player; use App\Models\Texture; @@ -31,7 +32,53 @@ class AdminController extends Controller public function options() { - return view('admin.options'); + $general = Option::form('general', '常规选项', function($form) + { + $form->text('site_name', '站点标题'); + $form->text('site_description', '站点描述'); + $form->text('site_url', '站点地址(URL)')->hint('以 http(s):// 开头,不要以 / 结尾'); + + $form->checkbox('user_can_register', '开放注册', '任何人都可以注册'); + + $form->text('regs_per_ip', '每个 IP 限制注册数'); + + $form->group('max_upload_file_size', '最大允许上传大小', function($group) { + // main textbox + $group->text('max_upload_file_size', option('max_upload_file_size')); + $group->addon('KB'); + })->hint('PHP 限制:'.ini_get('post_max_size').',定义在 php.ini 中。'); + + $form->checkbox('allow_chinese_playername', '角色名', '允许中文角色名'); + + $form->select('api_type', '首选 JSON API', function($options) { + $options->add('0', 'CustomSkinLoader API'); + $options->add('1', 'UniversalSkinAPI'); + + $options->setSelected(option('api_type')); + }); + + $form->checkbox('auto_del_invalid_texture', '失效材质', '自动删除失效材质')->hint('自动从皮肤库中删除文件不存在的材质记录'); + + $form->textarea('comment_script', '评论代码', option('comment_script'), function($textarea) { + $textarea->setRows(6); + $textarea->setDescription('评论代码内可使用占位符,{tid} 将会被自动替换为材质的 id,{name} 会被替换为材质名称,{url} 会被替换为当前页面地址。'); + }); + })->handle(function() { + if (substr($_POST['site_url'], -1) == "/") + $_POST['site_url'] = substr($_POST['site_url'], 0, -1); + }); + + $cache = Option::form('cache', '缓存相关配置', function($form) + { + $form->checkbox('avatar_query_string', '头像缓存', '为头像添加 Query String'); + $form->checkbox('auto_detect_asset_url', '资源地址', '自动判断资源文件地址')->hint('根据当前 URL 自动加载资源文件。如果出现 CDN 回源问题请关闭'); + $form->checkbox('return_200_when_notfound', 'HTTP 响应码', '请求不存在的角色时返回 200 而不是 404'); + + $form->text('cache_expire_time', '缓存失效时间')->hint('秒数,86400 = 一天,31536000 = 一年'); + + })->hint('如果启用了 CDN 缓存请适当修改这些配置')->handle(); + + return view('admin.options')->with('forms', compact('general', 'cache')); } /** diff --git a/app/Services/Facades/Option.php b/app/Services/Facades/Option.php index 02c522a8..51d7267c 100644 --- a/app/Services/Facades/Option.php +++ b/app/Services/Facades/Option.php @@ -2,7 +2,8 @@ namespace App\Services\Facades; -use \Illuminate\Support\Facades\Facade; +use App\Services\OptionForm; +use Illuminate\Support\Facades\Facade; class Option extends Facade { @@ -15,4 +16,13 @@ class Option extends Facade { return 'option'; } + + public static function form($id, $title, $callback) + { + $form = new OptionForm($id, $title); + + call_user_func($callback, $form); + + return $form; + } } diff --git a/app/Services/OptionForm.php b/app/Services/OptionForm.php new file mode 100644 index 00000000..caa1e2e0 --- /dev/null +++ b/app/Services/OptionForm.php @@ -0,0 +1,304 @@ +id = $id; + $this->title = $title; + } + + public function text($id, $name, $value = null) + { + return $this->addItem('text', $id, $name); + } + + public function checkbox($id, $name, $label, $checked = null) + { + $checkbox = $this->addItem('checkbox', $id, $name); + + $checkbox->set('label', $label); + + return $checkbox; + } + + public function select($id, $name, $callback) + { + $item = $this->addItem('select', $id, $name); + + $select = new OptionFormSelect($id); + + call_user_func($callback, $select); + + $item->set('view', $select->render()); + + return $select; + } + + public function textarea($id, $name, $value, $callback) + { + $item = $this->addItem('textarea', $id, $name); + + $textarea = new OptionFormTextarea($id, $value); + + call_user_func($callback, $textarea); + + $item->set('view', $textarea->render()); + + return $textarea; + } + + public function group($id, $name, $callback) + { + $item = $this->addItem('group', $id, $name); + + $group = new OptionFormGroup($id); + + call_user_func($callback, $group); + + $item->set('view', $group->render()); + + return $item; + } + + public function addItem($type, $id, $name) + { + $item = new OptionFormItem($id, $name, $type); + + $this->items[] = $item; + + return $item; + } + + public function hint($hint_content) + { + $this->hint = view('vendor.option-form.hint')->with('hint', $hint_content)->render(); + + return $this; + } + + public function handle($callback = null) + { + if (Arr::get($_POST, 'option') == $this->id) { + if (!is_null($callback)) { + call_user_func($callback); + } + + foreach ($this->items as $item) { + if ($item->type == "checkbox" && !isset($_POST[$item->id])) { + $_POST[$item->id] = "0"; + } + + if ($_POST[$item->id] != option($item->id)) { + Option::set($item->id, $_POST[$item->id]); + } + } + + $this->success = true; + } + + return $this; + } + + public function render() + { + foreach ($this->items as $item) { + $id = $item->id; + $value = Option::get($item->id); + + switch ($item->type) { + case 'text': + $view = view('vendor.option-form.text')->with(compact('id', 'value')); + break; + + case 'checkbox': + $view = view('vendor.option-form.checkbox')->with([ + 'id' => $id, + 'label' => $item->get('label'), + 'checked' => (bool) $value + ]); + break; + + case 'select': + case 'textarea': + case 'group': + $view = $item->get('view'); + break; + } + + $item->setContent($view->render()); + } + + + return view('vendor.option-form.main')->with([ + 'title' => $this->title, + 'id' => $this->id, + 'hint' => $this->hint, + 'items' => $this->items, + 'success' => $this->success + ])->render(); + } +} + +class OptionFormItem +{ + public $id; + public $type; + public $title; + + protected $data; + + protected $hint; + protected $content; + + public function __construct($id, $title, $type = "") + { + $this->id = $id; + $this->type = $type; + $this->title = $title; + } + + public function hint($hint_content) + { + $this->hint = view('vendor.option-form.hint')->with('hint', $hint_content)->render(); + + return $this; + } + + public function setContent($content) + { + $this->content = $content; + + return $this; + } + + public function set($key, $value) + { + $this->data[$key] = $value; + } + + public function get($key) + { + return Arr::get($this->data, $key); + } + + public function render() + { + return view('vendor.option-form.item')->with([ + 'title' => $this->title, + 'content' => $this->content, + 'hint' => $this->hint + ]); + } + +} + +class OptionFormSelect +{ + protected $id; + + protected $items; + + protected $selected; + + public function __construct($id) + { + $this->id = $id; + } + + public function add($id, $name) + { + $this->items[] = [$id, $name]; + } + + public function setSelected($id) + { + $this->selected = $id; + } + + public function render() + { + return view('vendor.option-form.select')->with([ + 'id' => $this->id, + 'items' => $this->items, + 'selected' => $this->selected + ]); + } +} + +class OptionFormTextarea +{ + protected $id; + + protected $value; + + protected $rows = 3; + + protected $description = ""; + + public function __construct($id, $value) + { + $this->id = $id; + $this->value = $value; + } + + public function setRows($rows) + { + $this->rows = $rows; + } + + public function setDescription($description) + { + $this->description = $description; + } + + public function render() + { + return view('vendor.option-form.textarea')->with([ + 'rows' => $this->rows, + 'id' => $this->id, + 'value' => $this->value, + 'description' => $this->description + ]); + } +} + +class OptionFormGroup +{ + protected $id; + + protected $items = []; + + public function __construct($id) + { + $this->id = $id; + } + + public function text($id, $value) + { + $this->items[] = view('vendor.option-form.text')->withId($id)->withValue($value); + } + + public function addon($value) + { + $this->items[] = view('vendor.option-form.addon')->withValue($value); + } + + public function render() + { + return view('vendor.option-form.group')->with('items', $this->items); + } +} diff --git a/resources/views/admin/options.tpl b/resources/views/admin/options.tpl index a705587e..e587c6ac 100644 --- a/resources/views/admin/options.tpl +++ b/resources/views/admin/options.tpl @@ -2,13 +2,6 @@ @section('title', trans('general.options')) -@section('style') - -@endsection - @section('content') @@ -26,134 +19,7 @@
-
-
-

常规选项

-
-
- -
- $value) { - // remove slash if site_url is ended with slash - if ($key == "site_url" && substr($value, -1) == "/") - $value = substr($value, 0, -1); - - if ($key != "option" && $key != "submit") - Option::set($key, $value); - } - echo '
设置已保存。
'; - } ?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
站点标题 - -
站点描述 - -
站点地址(URL) - -
开放注册 - -
每个 IP 限制注册数 - -
最大允许上传大小 - - -
- - KB -
-
角色名 - -
首选 JSON API - -
失效材质 - - - -
评论代码 - - - -

评论代码内可使用占位符,{tid} 将会被自动替换为材质的 id,{name} 会被替换为材质名称,{url} 会被替换为当前页面地址。

-
-
- -
-
+ {!! $forms['general']->render() !!}
@@ -180,85 +46,7 @@
-
-
-

缓存相关配置 - -

-
-
- -
- $value) { - // remove slash if site_url is ended with slash - if ($key == "site_url" && substr($value, -1) == "/") - $value = substr($value, 0, -1); - - if ($key != "option" && $key != "submit") - Option::set($key, $value); - } - echo '
设置已保存。
'; - } ?> - - - - - - - - - - - - - - - - - - - - - - -
头像缓存 - -
资源地址 - - - -
HTTP 响应码 - -
缓存失效时间 - - - -
-
- -
-
+ {!! $forms['cache']->render() !!}
@@ -267,3 +55,10 @@ @endsection + +@section('style') + +@endsection diff --git a/resources/views/vendor/option-form/addon.tpl b/resources/views/vendor/option-form/addon.tpl new file mode 100644 index 00000000..0798401e --- /dev/null +++ b/resources/views/vendor/option-form/addon.tpl @@ -0,0 +1 @@ +{{ $value }} diff --git a/resources/views/vendor/option-form/checkbox.tpl b/resources/views/vendor/option-form/checkbox.tpl new file mode 100644 index 00000000..7a8455b4 --- /dev/null +++ b/resources/views/vendor/option-form/checkbox.tpl @@ -0,0 +1,3 @@ + diff --git a/resources/views/vendor/option-form/group.tpl b/resources/views/vendor/option-form/group.tpl new file mode 100644 index 00000000..7d70e79f --- /dev/null +++ b/resources/views/vendor/option-form/group.tpl @@ -0,0 +1,5 @@ +
+ @foreach($items as $item) + {!! $item->render() !!} + @endforeach +
diff --git a/resources/views/vendor/option-form/hint.tpl b/resources/views/vendor/option-form/hint.tpl new file mode 100644 index 00000000..0ff95827 --- /dev/null +++ b/resources/views/vendor/option-form/hint.tpl @@ -0,0 +1 @@ + diff --git a/resources/views/vendor/option-form/item.tpl b/resources/views/vendor/option-form/item.tpl new file mode 100644 index 00000000..3f2b28d2 --- /dev/null +++ b/resources/views/vendor/option-form/item.tpl @@ -0,0 +1,6 @@ + + {{ $title }} {!! $hint or '' !!} + + {!! $content !!} + + diff --git a/resources/views/vendor/option-form/main.tpl b/resources/views/vendor/option-form/main.tpl new file mode 100644 index 00000000..1f8f6a4a --- /dev/null +++ b/resources/views/vendor/option-form/main.tpl @@ -0,0 +1,23 @@ +
+
+

{{ $title }} {!! $hint or '' !!}

+
+
+ +
+ @if ($success) +
设置已保存。
+ @endif + + + @foreach($items as $item) + {!! $item->render() !!} + @endforeach + +
+
+ +
+
diff --git a/resources/views/vendor/option-form/select.tpl b/resources/views/vendor/option-form/select.tpl new file mode 100644 index 00000000..bb20da8a --- /dev/null +++ b/resources/views/vendor/option-form/select.tpl @@ -0,0 +1,8 @@ + diff --git a/resources/views/vendor/option-form/text.tpl b/resources/views/vendor/option-form/text.tpl new file mode 100644 index 00000000..207716d9 --- /dev/null +++ b/resources/views/vendor/option-form/text.tpl @@ -0,0 +1 @@ + diff --git a/resources/views/vendor/option-form/textarea.tpl b/resources/views/vendor/option-form/textarea.tpl new file mode 100644 index 00000000..2e4ef1f7 --- /dev/null +++ b/resources/views/vendor/option-form/textarea.tpl @@ -0,0 +1,5 @@ + + +@if ($description != "") +

{!! $description !!}

+@endif