dcat-admin

1. ScaffoldController.php
2. scaffold.blade.php
3. ModelCreator.php
4. ControllerCreator.php
5. FormCreator.php
6. GridCreator.php

修改列表页数据库字段翻译

第一种:

protected function grid()
{
    $model = JhTypeModel::where('click','>',0);
    return Grid::make($model, function (Grid $grid) {
        $grid->id->sortable();
        $grid->column('title','标题');
        $grid->column('click','点击数');

        $grid->quickSearch('id','title');

        $grid->filter(function (Grid\Filter $filter) {
            $filter->equal('id');
            $filter->equal('title');
        });
    });
}

第二种:

传入关联模型

protected function grid()
{
	//关联模型
	$model = Model::with('...')->where(...);
    
    return Grid::make($model, function (Grid $grid) {
        ...
    });
}
protected function detail($id)
{

    //关联模型
	$model = HomestayModel::with(['chengshi','zousheng','guojium']);
       
    return Show::make($id,  $model, function  (Show $show) {
    	$show->width(6)->field("guojium.name",'国家');
        $show->width(6)->field('zousheng.ywmc', '州省');
        $show->width(6)->field('chengshi.name', '城市');
    });
}

通过display($callback)方法来格式化显示输出

$grid->column('text')->display(function($text) {
    return str_limit($text, 30, '...');
});


// 添加不存在的字段
$grid->column('full_name')->display(function () {
    return $this->first_name.' '.$this->last_name;
});


$form->image('jsjt_xsws')->uniqueName()->maxSize(40960);

弹出模态框 (modal)

modal 方法可以把内容隐藏,点击按钮的时候显示在表格下一行

$grid->column('content')
    ->display('查看') // 设置按钮名称
    ->modal(function ($modal) {
        // 设置弹窗标题
        $modal->title('标题 '.$this->username);

        $card = new Card(null, $this->content);

        return "<div style='padding:10px 10px 0'>$card</div>";
    });

// 也可以通过这种方式设置弹窗标题
$grid->column('content')
    ->display('查看') // 设置按钮名称
    ->modal('弹窗标题', ...);
      

模态框异步加载 显示

$grid->post->display('家庭成员')->modal('JsFamily', JsFamily::make(['jtcy' => $grid->id]));


<?php
namespace App\Admin\Renderable;

class JsFamily extends LazyRenderable
{
    public function render()
    {
        // 获取ID
        $jtcy = $this->jtcy;

        // 获取其他自定义参数
        // $type = $this->post_type;

        $data = JsFamilyModel::where('jtcy', $jtcy)
            // ->where('type', $type)
            // ->get(['id', 'name','js_applicant'])
            ->get(['name','js_surname2','js_applicant','js_cy_sex','id'])
            ->toArray();
            $newData = [];
           
            foreach ($data as $key => &$value) {
                $tt = [];
                $tt['name'] =  $value['name'];
                $tt['js_surname2'] =  $value['js_surname2'];
                $tt['js_applicant'] =  $value['js_applicant'];
                $tt['js_cy_sex'] =  $value['js_cy_sex'];
                $tt['link'] =  "<a  href='".admin_url('/jsfamily/'.$value['id'].'/edit'."' target='_blank'>查看详情</a>");
                 $newData[] = $tt;
            }
        $titles = [
            // 'User ID',
            '姓名',
            '姓',
            '关系',
            '性别',
            ''
           
        ];
        return Table::make($titles, $newData);
    }
}

多选

下拉选框单选 (select)

$form->select($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);

或者从 api 中获取选项列表:

$form->select($column[, $label])->options('/api/users');

其中 api 接口的格式必须为下面格式:

[
    {
        "id": 9,
        "text": "xxx"
    },
    {
        "id": 21,
        "text": "xxx"
    },
    ...
]

控制器 action 的代码示例如下:

public function city(Request $request)
{
    $provinceId = $request->get('q');

    return ChinaArea::city()->where('parent_id', $provinceId)->get(['id', DB::raw('name as text')]);
}

下拉选框联动 (load)

select 组件支持父子关系的单向联动:

$form->select('province')->options(...)->load('city', '/api/city');

$form->select('city');

其中 load('city', '/api/city'); 的意思是,在当前 select 的选项切换之后,会把当前选项的值通过参数 q, 调用接口 /api/city,并把 api 返回的数据填充为 city 选择框的选项,其中 api/api/city 返回的数据格式必须符合:

[
    {
        "id": 9,
        "text": "xxx"
    },
    {
        "id": 21,
        "text": "xxx"
    },
    ...
]

下拉选框多选 (multipleSelect)

注入这个字段的数据(从数据库查出来的)可以是一个以 , 隔开的字符串,也可以是 json 字符串或 array 数组。

$form->multipleSelect($column[, $label])
    ->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name'])
    ->saving(function ($value) {
        // 转化成json字符串保存到数据库
        return json_encode($value);
    });

多选框可以处理两种情况,第一种是 ManyToMany 的关系。

class Post extends Models
{
    public function tags()
    {
        return $this->belongsToMany(Tag::class);
    }
}

return Form::make(Post::with('tags'), function (Form $form) {
    ...

    $form->multipleSelect('tags')
        ->options(Tag::all()->pluck('name', 'id'))
        ->customFormat(function ($v) {
            if (! $v) {
                return [];
            }

            // 从数据库中查出的二维数组中转化成ID
            return array_column($v, 'id');
        });
});

下拉选框多选 (multipleSelect)

$form->multipleSelect('tag')->options('api/housetag')->saving(function ($value) {
	return implode(';', $value);
});;

表格选择器 (selectTable) 多选

use App\Admin\Renderable\UserTable;
use Dcat\Admin\Models\Administrator;

$form->selectTable($field)
    ->title('弹窗标题')
    ->dialogWidth('50%') // 弹窗宽度,默认 800px
    ->from(UserTable::make(['id' => $form->getKey()])) // 设置渲染类实例,并传递自定义参数
    ->model(Administrator::class, 'id', 'name'); // 设置编辑数据显示

// 上面的代码等同于
$form->selectTable($field)
    ->from(UserTable::make(['id' => $form->getKey()])) // 设置渲染类实例,并传递自定义参数
    ->options(function ($v) { // 设置编辑数据显示
        if (! $v) {
            return [];
        }

        return Administrator::find($v)->pluck('name', 'id');
    });

定义渲染类如下,需要继承 Dcat\Admin\Grid\LazyRenderable

<?php

namespace App\Admin\Renderable;

use Dcat\Admin\Grid;
use Dcat\Admin\Grid\LazyRenderable;
use Dcat\Admin\Models\Administrator;

class UserTable extends LazyRenderable
{
    public function grid(): Grid
    {
        // 获取外部传递的参数
        $id = $this->id;

        return Grid::make(new Administrator(), function (Grid $grid) {
            $grid->column('id');
            $grid->column('username');
            $grid->column('name');
            $grid->column('created_at');
            $grid->column('updated_at');

            // 指定行选择器选中时显示的值的字段名称
            // 指定行选择器选中时显示的值的字段名称
            // 指定行选择器选中时显示的值的字段名称
            // 如果表格数据中带有 “name”、“title”或“username”字段,则可以不用设置
            $grid->rowSelector()->titleColumn('username');

            $grid->quickSearch(['id', 'username', 'name']);

            $grid->paginate(10);
            $grid->disableActions();

            $grid->filter(function (Grid\Filter $filter) {
                $filter->like('username')->width(4);
                $filter->like('name')->width(4);
            });
        });
    }
}

多图和多文件上传

多图 / 文件上传的时候提交的数据是一个 array 数组,你可以通过以下方式把数据在保存进数据库之前改为你想要的格式:

// 转化为json格式保存到数据库
$form->multipleFile($column[, $label])->saving(function ($paths) {
    // 可以转化为由 , 隔开的字符串格式
    // return implode(',', $paths);

    // 也可以转化为json
    return json_encode($paths);
});

JSON 格式字段处理

dcat-admin 的表单提供了下面几个组件来处理 JSON 格式的字段,方便用来处理 JOSN 格式的对象、一维数组、二维数组等对象。

键值对象 (keyValue)

如果你的字段存储的是不固定{"field":"value"} 格式,可以用 keyValue 组件:

$form->keyValue('column_name');

// 设置校验规则
$form->keyValue('column_name')->rules('required|min:5');

一维数组 (list)

如果你的字段是用来存储 ["foo", "Bar"] 格式的一维数组,可以使用 list 组件:

$form->list('column_name');

// 设置校验规则
$form->list('column_name')->rules('required|min:5');

// 设置最大和最小元素个数
$form->list('column_name')->max(10)->min(5);

二维数组 (table)

如果某一个字段存储的是 json 格式的二维数组,可以使用 table 表单组件来实现快速的编辑:

$form->table('column_name', function ($table) {
    $table->text('key');
    $table->text('value');
    $table->text('desc');
})->saving(function ($v) {
    return json_encode($v);
});

这个组件类似于 hasMany 组件,不过是用来处理单个字段的情况,适用于简单的二维数据。

二维数组 (array)

如果某一个字段存储的是 json 格式的二维数组,并且字段比较多,可以使用 array 表单组件来实现快速的编辑:

$form->array('column_name', function ($table) {
    $table->text('key');
    $table->text('value');
    $table->textarea('desc');
})->saveAsJson();

表单验证

$form->text('title')->rules('required|min:3');

// 复杂的验证规则可以在回调里面实现
$form->text('title')->rules(function (Form $form) {

    // 如果不是编辑状态,则添加字段唯一验证
    if (!$id = $form->model()->id) {
        return 'unique:users,email_address';
    }

});

也可以给验证规则自定义错误提示消息:

$form->text('code')->rules('required|regex:/^\d+$/|min:10', [
    'regex' => 'code必须全部为数字',
    'min'   => 'code不能少于10个字符',
]);

表单布局

多列布局 (column)

左右两列布局方式,可以参考下面的代码来实现

// 第一列占据1/2的页面宽度
$form->column(6, function (Form $form) {
    $form->text('name')->required();
    $form->date('born')->required();
    $form->select('education')->options([...])->required();
    $form->text('nation')->required();
    $form->text('native')->required();
    $form->text('job')->required();
    $form->text('code')->required();
    $form->text('phone')->required();
    $form->text('work')->required();
    $form->text('census')->required();
});

// 第二列占据1/2的页面宽度
$form->column(6, function (Form $form) {
    $form->image('avatar');
    $form->decimal('wages');
    $form->decimal('fund');
    $form->decimal('pension');
    $form->decimal('fee');
    $form->decimal('business');
    $form->decimal('other');
    $form->text('area')->default(0);
    $form->textarea('illness');
    $form->textarea('comment');
});

// 调整所有表单的宽度
$form->width(9, 2);

以上布局功能使用了 bootstrap 的栅格布局系统,所有列的宽度总和不得超出 12,并且也支持在 hasManyarray 表单中使用

$form->hasMany('jobs', function ($form) {
     $form->column(6, function (Form $form) {
         $form->text('name')->required();
         $form->date('born')->required();
     });

     $form->column(6, function (Form $form) {
         $form->image('avatar');
         $form->decimal('wages');
     });
});

多行布局 (row)

使用

$form->row(function (Form\Row $form) {
    $form->width(4)->text('username')->required();
    $form->width(3)->text('title');
    ...
});

$form->row(function (Form\Row $form) {
    ...
});

...

并且也支持在 hasManyarray 表单中使用

$form->hasMany('jobs', function ($form) {
     $form->row(function (Form\Row $form) {
         ...
     });

     $form->row(function (Form\Row $form) {
         ...
     });
});

选项卡表单 (tab)

如果表单元素太多,会导致表单页面太长,这种情况下可以使用 tab 方法来分隔表单:

$form->tab('Basic info', function (Form $form) {

    $form->text('username');
    $form->email('email');

})->tab('Profile', function (Form $form) {

   $form->image('avatar');
   $form->text('address');
   $form->mobile('phone');

})->tab('Jobs', function (Form $form) {

     $form->hasMany('jobs', function ($form) {
         $form->text('company');
         $form->date('start_date');
         $form->date('end_date');
     });

})

同时,tab 布局中也允许嵌套使用 columnrow 布局

$form->tab('Basic info', function (Form $form) {
    $form->column(6, function (Form\BlockForm $form) {
        $form->display('id');
        $form->text('name');
    });

    $form->column(6, function (Form\BlockForm $form) {
        $form->text('username');
    });
})

分块布局 (block)

如果你的表单中字段非常多,那么可以通过以下方式让你的表单分块布局,并且允许嵌套使用 columnrow 布局

$form->block(8, function (Form\BlockForm $form) {
    // 设置标题
    $form->title('基本设置');

    // 显示底部提交按钮
    $form->showFooter();

    // 设置字段宽度
    $form->width(9, 2);

    $form->column(6, function (Form\BlockForm $form) {
        $form->display('id');
        $form->text('name');
        $form->email('email');
        $form->image('avatar');
        $form->password('password');
    });

    $form->column(6, function (Form\BlockForm $form) {
        $form->text('username');
        $form->email('mobile');
        $form->textarea('description');
    });
});
$form->block(4, function (Form\BlockForm $form) {
    $form->title('分块2');

    $form->text('nickname');
    $form->number('age');
    $form->radio('status')->options(['1' => '默认', 2 => '冻结'])->default(1);

    $form->next(function (Form\BlockForm $form) {
        $form->title('分块3');

        $form->date('birthday');
        $form->date('created_at');
    });
});

表单字段动态显示

表单字段动态显示是指,在选择表单项的指定的选项时,联动显示其他的表单项。

目前支持的表单联动的组件有:

  • select
  • multipleSelect
  • radio
  • checkbox

使用方法

可以将上面的组件分为单选和多选两种类型,其中 select、radio 为单选组件,其它为多选组件

单选组件

下面的例子中,选择不同的国籍类型,将会切换选择不同的联动表单项:

$form->radio('radio')
    ->when([1, 4], function (Form $form) {
        // 值为1和4时显示文本框
        $form->text('text1');
        $form->text('text2');
        $form->text('text3');
    })
    ->when(2, function (Form $form) {
        $form->editor('editor');
    })
    ->when(3, function (Form $form) {
        $form->image('image');
    })
    ->options([
        1 => '显示文本框',
        2 => '显示编辑器',
        3 => '显示文件上传',
        4 => '还是显示文本框',
    ])
    ->default(1);

上例中,方法 when(1, $callback) 等效于 when('=', 1, $callback), 如果用操作符 =,则可以省略这个参数

同时也支持这些操作符,=、>、>=、<、<=、!= 使用方法如下:

$form->radio('check')
    ->when('>', 1, function () {

    })->when('>=', 2, function () {

    });

select 组件的使用方法和 radio 是一样的。

多选组件
$form->checkbox('nationality', '国籍')
    ->options([
        1 => '中国',
        2 => '外国',
    ])->when([1, 2], function (Form $form) { 

        $form->text('name', '姓名');
        $form->text('idcard', '身份证');

    })->when('notIn', 2, function (Form $form) { 

        $form->text('name', '姓名');
        $form->text('passport', '护照');

    });

multipleSelect 组件的使用方法和 checkbox 是一样的。

布局

表单动态显示功能支持结合 column 以及 tab 布局功能一起使用,用法如下

tab 布局

$form->tab('Radio', function (Form $form) {
    $form->display('title')->value('单选框动态展示');

    $form->radio('radio')
        ->when([1, 4], function (Form $form) {
            $form->text('text1');
            $form->text('text2');
        })
        ->when(2, function (Form $form) {
            $form->editor('editor');
        })
        ->options($this->options)
        ->default(1);
});

column 布局

$form->column(6, function (Form $form) {
    $form->radio('radio')
        ->when([1, 4], function (Form $form) {
            $form->text('text1');
            $form->text('text2');
        })
        ->when(2, function (Form $form) {
            $form->editor('editor');
        })
        ->options($this->options)
        ->default(1);
});

数据详情

修改显示内容

用下面的方法修改显示内容

$show->title()->as(function ($title) {
    // 获取当前行的其他字段
    $username = $this->username;

    return "<{$title}> {$username}";
});

$show->contents()->as(function ($content) {
    return "<pre>{$content}</pre>";
});

view

view 方法可以引入一个视图文件。

// 模板中接收以下三个变量:
// name 字段名称
// value 字段值
// model 当前行数据
$show->content->view('admin.fields.content');

explode

explode 方法可以把字符串分割为数组。

$show->tag->explode()->label();

// 可以指定分隔符,默认","
$show->tag->explode('|')->label();

image

字段 avatar 的内容是图片的路径或者 url,可以将它显示为图片:

$show->avatar()->image();

file

字段 document 的内容是文件的路径或者 url,可以将它显示为文件:

$show->avatar()->file();

label

将字段 tag 的内容显示为 label:

$show->tag()->label();

badge

将字段 rate 的内容显示为 badge:

$show->rate()->badge();

dot

通过 dot 方法可以在列文字前面加上一个带颜色的圆点

use Dcat\Admin\Admin;

$show->state
    ->using([1 => '未处理', 2 => '已处理', ...])
    ->dot(
        [
            1 => 'primary',
            2 => 'danger',
            3 => 'success',
            4 => Admin::color()->info(),
        ], 
        'primary' // 第二个参数为默认值
    );

显示文件尺寸

如果字段数据是表示文件大小的字节数,可以通过调用 filezise 方法来显示更有可读性的文字

$show->field('file_size')->filesize();

这样数值 199812019 将会显示为 190.56 MB

模型树

这个功能可以实现一个树状组件,可以用拖拽的方式实现数据的层级、排序等操作,下面是基本的用法。

表结构和模型

要使用 model-tree,要遵守约定的表结构:

{tip} parent_id 字段一定要默认为 0!!!

CREATE TABLE `demo_categories` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL DEFAULT '0',
  `order` int(11) NOT NULL DEFAULT '0',
  `title` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

上面的表格结构里面有三个必要的字段 parent_idordertitle, 其它字段没有要求。

对应的模型为 app/Models/Category.php:

<?php

namespace App\Models\Demo;

use Dcat\Admin\Traits\ModelTree;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use ModelTree;

    protected $table = 'demo_categories';
}

表结构中的三个字段 parent_idordertitle 的字段名也是可以修改的:

{tip} 为了便于阅读,这里不再展示 Repository 代码。

<?php

namespace App\Models\Demo;

use Dcat\Admin\Traits\ModelTree;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use ModelTree;

    protected $table = 'demo_categories';

    // 父级ID字段名称,默认值为 parent_id
    protected $parentColumn = 'pid';

    // 排序字段名称,默认值为 order
    protected $orderColumn = 'sort';

    // 标题字段名称,默认值为 title
    protected $titleColumn = 'name';
}

使用方法

然后就是在页面中使用 model-tree 了:

<?php

namespace App\Admin\Controllers\Demo;

use App\Models\Category;
use Dcat\Admin\Layout\Row;
use Dcat\Admin\Layout\Content;
use Dcat\Admin\Tree;
use Dcat\Admin\Controllers\AdminController;

class CategoryController extends AdminController
{
    public function index(Content $content)
    {
        return $content->header('树状模型')
            ->body(function (Row $row) {
                $tree = new Tree(new Category);

                $row->column(12, $tree);
            });
    }
}

可以通过下面的方式来修改行数据的显示:

$tree = new Tree(new Category);

$tree->branch(function ($branch) {
    $src = config('admin.upload.host') . '/' . $branch['logo'] ;
    $logo = "<img src='$src' style='max-width:30px;max-height:30px' class='img'/>";

    return "{$branch['id']} - {$branch['title']} $logo";
});

在回调函数中返回的字符串类型数据,就是在树状组件中的每一行的显示内容,$branch 参数是当前行的数据数组。

修改模型查询条件

如果要修改模型的查询,用下面的方式

$tree->query(function ($model) {
    return $model->where('type', 1);
});

限制最大层级数

默认 5

$tree->maxDepth(3);

自定义行操作

use Dcat\Admin\Tree;

$tree->actions(function (Tree\Actions $actions) {
    if ($actions->row->id > 5) {
        $actions->disableDelete(); // 禁用删除按钮
    }

    // 添加新的action
    $actions->append(...);
});

// 批量添加action
$tree->actions([
    new Action1(),
    "<div>...</div>",
    ...
]);

开发工具

IDE 自动补全

通过 php artisan admin:ide-helper 命令可以生成 IDE 自动补全文件,可以生成 Grid、Form、Show 等功能的 IDE 自动补全提示文件。

代码生成器

代码生成器可以通过界面一键生成增删改查代码,支持根据已有数据表生成增删改查代码,打开浏览器访问 http://localhost:8000/admin/helpers/scaffold 即可使用。

如果你的开发环境不是 windows 系统,请给整个项目 777 权限,否则可能无法生成文件。

扩展包管理

Dcat Admin 支持可视化管理扩展包,只要通过 composer 安装进来的扩展包都能在管理界面中看到,支持通过界面启用和导入扩展包,打开浏览器访问 http://localhost:8000/admin/helpers/extensions 即可使用。

posted @ 2021-01-06 16:10  caibaotimes  阅读(3554)  评论(0编辑  收藏  举报