Dcat Admin 自定义 Form 表单实现后台系统配置内容的自定义,并可扩展配置项。
Laravel框架
1369
0
0
2022-09-19
可配置项目代码Gitee地址
起因 之前在做项目的时候,后台管理扩展使用的是 Laravel-Admin
,需要在后台可以灵活添加和修改一些项目需求的配置。然后我在 Github
上搜索了相关扩展,当时找到了这个 Config manager for laravel-admin 。这个确实解决了我的燃眉之急,只不过这个配置比较简单,就是 key => value
的配置,而且 value 的值也只是一个 text
类型的 input
框,不能使用时间区、下拉框、选择按钮、上传图片等控件。页面效果如下:
当时心想我怎么实现灵活的添加配置,并且可以任意的使用 form
表单控件,想了好久还是没有好的办法。这件事情一直搁在心里,直到最近才把它给做出来。 灵感 最近项目后台管理扩展使用的是 Dcat Admin
,这个是基于 Laravel-Admin
的二次开发的,使用起来几乎没有障碍。UI界面比原先 Laravel-Admin
的要好看,所以就用它了。 这次我还是需要在后台做可灵活添加的配置,然后我就看 Dcat Admin
的文档和演示案例。突然发现了一个页面是我想要的效果。页面如下 :
然后我就获取了页面的预览代码,分析了一下。得出这个控制器里面有三个主要的方法,一个是 index()
,另外两个是 form1()
和 form2()
。大概意思就是通过 tab栏
的选择来控制显示对应的表单页面。index 方法默认显示的是 form1 的页面。 虽然这个预览的代码显示的是两个 form
表单页面,但是只要你愿意,它还可以增加的新的表单,它的可扩展性是我所看重的一个点。
复制
<?php
namespace App \Admin \Controllers ;
...
class FormController extends Controller
{
public function index (Content $content )
{
...
$content ->row (function (Row $row ) {
$type = request ('_t' , 1 );
$tab = new Tab ();
if ($type == 1 ) {
$tab ->add ('Form-1' , $this ->form1 ());
$tab ->addLink ('Form-2' , request ()->fullUrlWithQuery (['_t' => 2 ]));
} else {
$tab ->addLink ('Form-1' , request ()->fullUrlWithQuery (['_t' => 1 ]));
$tab ->add ('Form-2' , $this ->form2 (), true );
}
$row ->column (12 , $tab ->withCard ());
});
return $content ->header ('Form' );
}
protected function form1 ()
{
...
}
protected function form2 ()
{
...
}
}
Dcat Admin 有办法给 $form ->dateRange (‘column’)、 $form ->timeRange (‘column’) 等区间组件设置默认值么?use Dcat \Admin \Form ;
不过还有一个问题就是,use Dcat\Admin\Form;
默认有一个 header
头,把它隐藏就行。
复制
$form = new Form ();
$form ->disableHeader ();
我这边为了存入的数据在页面上展示,统一使用了 Form
表单的 default()
方法进行设置的。
复制
$form = new Form ();
$form ->text ('config_one.text' , '标题' )->required ()->default (Arr ::get ($configArr , 'text' ));
$form ->dateRange ('config_one.date-start' , 'config_one.date-end' , '日期区间1' )->default ([
'start' => Arr ::get ($configArr , 'date-start' ),
'end' => Arr ::get ($configArr , 'date-end' ),
]);
复制
<?php
namespace App \Admin \Controllers ;
use Dcat \Admin \Form \Field \UploadField ;
use Illuminate \Routing \Controller ;
class SystemConfigController extends Controller
{
use UploadField ;
public function store ()
{
$request = request ();
if (empty ($allData = $request ->all ())) {
return JsonResponse ::make ()->error ('没有数据提交!' );
}
if ($request ->hasFile ('_file_' )) {
try {
return $this ->upload ($request ->file ('_file_' ));
} catch (\Exception $e ) {
return JsonResponse ::make ()->error ('上传失败:' . $e ->getMessage ());
}
}
foreach ($allData as $k => $v ) {
if (!in_array ($k , array_keys (self ::CONFIG_TYPE ))) {
continue ;
}
SystemConfig ::query ()->updateOrCreate (['name' => $k ], ['name' => $k , 'value' => json_encode ($v )]);
}
return JsonResponse ::make ()->success ('提交成功!' )->refresh ();
}
}
这里面除了文件和图片的上传需要单独处理,其他的正常入库就行。 因为我这个 Form
表单是自定义的,里面的文件上传请求的还是控制器的 store()
方法,因为我重写了 store()
方法,我的方法中没有对应的文件上传的处理,然后我就根据编辑器的 Ctrl + 点击
进入到源代码中,查找图片上传的逻辑代码。
复制
public function store ()
{
return $this ->form ()->store ();
}
protected function form ()
{
return Form ::make (new User (), function (Form $form ) {
...
});
}
源代码的内容:vendor\dcat\laravel-admin\src\Form.php
找到 image 和 file 的配置:
复制
protected static $availableFields = [
...
'file' => Field\File ::class ,
'image' => Field\Image ::class ,
...
]
点击进 Field\Image::class
类中,里面有 prepareFile()
方法:
复制
protected function prepareFile (UploadedFile $file )
{
$this ->callInterventionMethods ($file ->getRealPath (), $file ->getMimeType ());
$this ->uploadAndDeleteOriginalThumbnail ($file );
}
然后我点击 prepareFile()
方法,看哪里使用了,结果就找到了 \vendor\dcat\laravel-admin\src\Form\Field\UploadField.php
这个文件,里面有一个 upload()
方法,这个就是上传图片和文件走的方法。
复制
public function upload (UploadedFile $file )
{
$request = request ();
$id = $request ->get ('_id' );
if (! $id ) {
return $this ->responseErrorMessage ('Missing id' );
}
if ($errors = $this ->getValidationErrors ($file )) {
return $this ->responseValidationMessage ($errors );
}
$this ->name = $this ->getStoreName ($file );
$this ->renameIfExists ($file );
$this ->prepareFile ($file );
if (! is_null ($this ->storagePermission)) {
$result = $this ->getStorage ()->putFileAs ($this ->getDirectory (), $file , $this ->name, $this ->storagePermission);
} else {
$result = $this ->getStorage ()->putFileAs ($this ->getDirectory (), $file , $this ->name);
}
if ($result ) {
$path = $this ->getUploadPath ();
$url = $this ->objectUrl ($path );
return $this ->responseUploaded ($this ->saveFullUrl ? $url : $path , $url );
}
throw new UploadException (trans ('admin.uploader.upload_failed' ));
}
use Dcat\Admin\Form\Field\UploadField;
这个引用很重要,文件上传需要这个引用。(费好大劲翻源码找到的方法)但是它有个 destroy 方法和 AdminController 控制器的冲突了。到最后我取消继承 AdminController 控制器改为 Controller 控制器了。结束 到此为止,这个后台可配置的逻辑已经写完了。 不过还可以在 SystemConfig
模型增加配置的调用,将常用的配置缓存到 Redis
中,这样可以任意的在程序里面快速的调用配置了。不过需要注意的是,后台配置修改,要清理 Redis
缓存中配置才行。