美文网首页
10分钟用Laravel-admin快速自定义创建tree菜单

10分钟用Laravel-admin快速自定义创建tree菜单

作者: liurongming | 来源:发表于2024-01-24 11:26 被阅读0次

一、介绍

有时候,我们需要实现一些表自关联的菜单效果,比如类目(Category )管理等,laravel-admin能够帮助我们快速,创建树形效果菜单。laravel-admin有丰富的组件库,其底层是基于boostrap封装的,因此基本组件没有的可以自己定义实现。查看了laravel-admin的官方文档,使用介绍也非常详细,基本上一分钟即可搭建一个高可用的基础后台管理系统。结合php和laravel,三者都是在提速增效。做全栈快速应对业务变化,做一些小程序、公众号、cms的开发,简直就是神速。官网https://laravel-admin.org/

  • 默认系统自带效果如下。今天就是自定义实现这个效果。


    image.png
  • 实现参考文档


    image.png

二、实现步骤

  • 创建表迁移文件
php artisan make:migration create_menus_table 

在生成的迁移文件中,添加以下代码:


image.png
 Schema::create('menus', function (Blueprint $table) {
            $table->comment('菜单表');
            $table->id()->comment('主键');
            $table->bigInteger('pid')->comment('父ID');
            $table->integer('order')->comment('排序');
            $table->string('title')->unique()->comment('名称');
            $table->string('icon',64)->comment('图标');
            $table->string('uri')->comment('路径');
            $table->timestamps();
 });
  • 执行迁移命令
 php artisan migrate 

即可生成如下表:

CREATE TABLE `menus` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `pid` bigint(20) NOT NULL COMMENT '父ID',
  `order` int(11) NOT NULL COMMENT '排序',
  `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '名称',
  `icon` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '图标',
  `uri` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '路径',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `menus_title_unique` (`title`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='菜单表';
  • 生成菜单模型
php artisan make:model Menu 

执行生成前,需要正确安装好了laravel-admin,其安装此处省略。

<?php

namespace App\Models;

use App\Helpers\core\SerializeDate;
use Encore\Admin\Traits\ModelTree;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Menu extends Model
{
    use HasFactory;
    use SerializeDate;
    use ModelTree;

    protected $fillable = ['pid', 'order', 'title', 'icon', 'uri'];

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        $this->setParentColumn('pid');  // 父ID
        $this->setOrderColumn('order'); // 排序
        $this->setTitleColumn('title'); // 标题
    }
}

其中关键代码:

use Encore\Admin\Traits\ModelTree;
use ModelTree;

    protected $fillable = ['pid', 'order', 'title', 'icon', 'uri'];

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        $this->setParentColumn('pid');  // 父ID
        $this->setOrderColumn('order'); // 排序
        $this->setTitleColumn('title'); // 标题
    }
  • 剩下什么都不需要做,直接生成控制器。指定--model=App\Models\Menu生成。
php artisan admin:make MenuController --model=App\Models\Menu

清空app/Admin/Controllers/MenuController.php自动生成内容,采用如下代码替换。

<?php

namespace App\Admin\Controllers;

use App\Models\Menu;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Form;
use Encore\Admin\Layout\Column;
use Encore\Admin\Layout\Content;
use Encore\Admin\Layout\Row;
use Encore\Admin\Tree;
use Encore\Admin\Widgets\Box;

class MenuController extends AdminController
{
    use HasResourceActions;
    /**
     * Title for current resource.
     *
     * @var string
     */
    protected $title = 'Menu';

    public function index(Content $content)
    {
        return $content
            ->title('菜单')
            ->description('菜单描述')
            ->header('菜单')
            ->row(function (Row $row) {
                $row->column(6, $this->treeView()->render());
                $row->column(6, function (Column $column) {
                    $form = new \Encore\Admin\Widgets\Form();
                    $form->action(admin_url('menus'));
                    $form->select('pid', trans('admin.parent_id'))->options(Menu::selectOptions());
                    $form->text('title', trans('admin.title'))->rules('required');
                    $form->icon('icon', trans('admin.icon'))->default('fa-bars')->rules('required')->help($this->iconHelp());
                    $form->text('uri', trans('admin.uri'));
                    $form->number('order', trans('admin.order'))->default(99)->help('越小越靠前');
                    $form->hidden('_token')->default(csrf_token());
                    $column->append((new Box(trans('admin.new'), $form))->style('success'));
                });
            });
    }

    public function show($id, Content $content)
    {
        return redirect()->route('admin.menus.edit', ['menu' => $id]);
    }

    protected function treeView()
    {
        $tree = new Tree(new Menu());
        $tree->disableCreate();
        $tree->branch(function ($branch) {
            $payload = "<i class='fa {$branch['icon']}'></i>&nbsp;<strong>{$branch['title']}</strong>";

            if (!isset($branch['children'])) {
                if (url()->isValidUrl($branch['uri'])) {
                    $uri = $branch['uri'];
                } else {
                    $uri = url($branch['uri']);
                }

                $payload .= "&nbsp;&nbsp;&nbsp;<a href=\"$uri\" class=\"dd-nodrag\">$uri</a>";
            }

            return $payload;
        });

        return $tree;
    }

    public function edit($id, Content $content)
    {
        return $content
            ->title(trans('admin.menu'))
            ->description(trans('admin.edit'))
            ->row($this->form()->edit($id));
    }

    public function form()
    {
        $form = new Form(new Menu());

        $form->display('id', 'ID');
        $form->select('pid', trans('admin.parent_id'))->options(Menu::selectOptions());
        $form->text('title', trans('admin.title'))->rules('required');
        $form->icon('icon', trans('admin.icon'))->default('fa-bars')->rules('required')->help($this->iconHelp());
        $form->text('uri', trans('admin.uri'));
        $form->number('order', trans('admin.order'))->default(99)->help('越小越靠前');
        $form->display('created_at', trans('admin.created_at'));
        $form->display('updated_at', trans('admin.updated_at'));

        return $form;
    }

    protected function iconHelp()
    {
        return 'For more icons please see <a href="http://fontawesome.io/icons/" target="_blank">http://fontawesome.io/icons/</a>';
    }
}
  • 至此,即可实现完成。实现非常简单,参考官网源码即可。
    vendor/encore/laravel-admin/src/Controllers/MenuController.php
    打开vendor目录,找到控制器目录下的MenuController.php文件然后复制粘贴即可。
  • 记得添加路由


    image.png

    就一行代码搞定:

   $router->resource('menus', \App\Admin\Controllers\MenuController::class);

自动实现了相关路由:


image.png
  • 细节处理
    菜单的编辑页面的查看按钮,自动生成无法隐藏,因此也直接跳转到编辑页面。
    image.png
    执行php artisan route:list找到admin/auth/menu/{menu}/edit路由的别名admin.menus.editshow函数中填写如下即可。
 public function show($id, Content $content)
    {
        return redirect()->route('admin.menus.edit', ['menu' => $id]);
    }

添加一个排序字段,测试效果。

 $form->number('order', trans('admin.order'))->default(99)->help('越小越靠前');

注意添加csrf隐藏域,目的是为了防止csrf攻击,laravel默认开启了csrf的token。这有别于一般的其他语言的框架,使得使用laravel编写项目,同时安全性也得到保障。

$form->hidden('_token')->default(csrf_token());

三、最终效果

image.png
  • 至此,所有效果均已实现。其它类似效果,参考实现即可。

相关文章

网友评论

      本文标题:10分钟用Laravel-admin快速自定义创建tree菜单

      本文链接:https://www.haomeiwen.com/subject/slzpodtx.html