Laravel Dcat-admin 详情页多栏布局开发

背景


随着 dcat-admin 越来越多的人使用,相信有许多跟我一样热爱这个项目的的人最后也会参与到这个项目中来,从使用者到项目的维护者,可以为项目贡献一份自己的力量。我以后也会将维护这个项目的一些心得,底层代码的实现都以博文的形式分享给大家。

需求


有个同学提了一个这样的需求 ; 需要在表单 / 详情支持多栏布局,而这个需求刚好我自己用 dcat-admin 做项目时候也遇到过。尤其是 form 表单字段比较多的时候,我开始的解决方案是通过 form 的 tab 来减少表单一页的字段数量。

表单的多栏目布局
思路:我想的是 form 表单的字段外面包一次 row ,然后控制 row 里面每个字段的长宽。当我看了 dcat-admin 的代码后,发现是已经实现好了的,所以不需要自己在开发,我这里主要讲讲表单的多栏目布局的用法和底层代码怎么实现的。
效果:


使用代码:

在控制器创建一个 from 方法

protected function form()
  {
      return Form::make(new WxyMaterialItem(), function (Form $form) {
          $form->row(function (Form\Row $row) {
              $row->width(4)->text('name')->required();
              $row->width(4)->text('id');
              $row->width(4)->text('simple_code');
          });
          $form->row(function (Form\Row $row) {
              $row->width(6)->text('integral_money');
              $row->width(6)->text('stock_min');
          });
          $form->row(function (Form\Row $row) {
              $row->width(12)->text('attribute');
          });
          $form->row(function (Form\Row $row) {
              $row->width(3)->text('price1');
              $row->width(3)->text('price2');
              $row->width(3)->text('price3');
              $row->width(3)->text('status');
          });
      });
  }


代码分析:

整个 form 表单渲染出来的流程如下
Dcat\Admin\Form 对象 -> 方法 rows 实例化一个 Dcat\Admin\Form\Row 对象并保存对象属性 -> 最后通过 render 方法渲染界面

这里面核心作用文件是 Dcat\Admin\Form\Row,我们可以看看里面的几个方法

width 方法

public function width($width = 12)
  {
      $this->defaultFieldWidth = $width;

      return $this;
  }


这个方法主要设置当前行的每一个显示字段的宽度,比如你一行显示三个字段
建议每个字段的宽度设置为 3,例如 $row->width (3)->text (‘name’);

__call 方法

public function __call($method, $arguments)
  {
      $field = $this->form->__call($method, $arguments);

      $field->disableHorizontal();

      $this->fields[] = [
          'width'   => $this->defaultFieldWidth,
          'element' => $field,
      ];

      return $field;
  }


这个方法主要是保存当前行要显示的字段的信息,通过 __call 方法去调用 Dcat\Admin\Form 的字段方法获取字段信息,如使用代码的 $row->width (4)->text (‘name’),会保存一个宽度 col-md-4 的 Dcat\Admin\Form\Field\Text 字段。

render 方法

  public function render()
  {
      return view('admin::form.row', ['fields' => $this->fields]);
  }


admin::form.row 视图

<div class="row">
  @foreach($fields as $field)
  <div class="col-md-{{ $field['width'] }}">
      {!! $field['element']->render() !!}
  </div>
  @endforeach
</div>

$field [‘element’]->render () 就是将字段渲染成 html
我们可以 dd 下 $this->fields , 看看其数据结构


详情的多栏目布局
思路:详情的多栏目布局是需要重新开发的,思路逻辑是和表单的多栏目布局类似的
主要是创建一个 Dcat\Admin\Show\Row 文件,里面的代码如下

<?php
namespace Dcat\Admin\Show;
use Dcat\Admin\Show;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Support\Collection;
class Row implements Renderable
{
    /**
     * Callback for add field to current row.s.
     *
     * @var \Closure
     */
    protected $callback;

    /**
     * Parent show.
     *
     * @var Show
     */
    protected $show;

    /**
     * @var Collection
     */
    protected $fields;

    /**
     * Default field width for appended field.
     *
     * @var int
     */
    protected $defaultFieldWidth = 12;

    /**
     * Row constructor.
     *
     * @param \Closure $callback
     * @param Show $show
     */
    public function __construct(\Closure $callback, Show $show)
    {
        $this->callback = $callback;

        $this->show = $show;

        $this->fields = new Collection();

        call_user_func($this->callback, $this);
    }

    /**
     * Render the row.
     *
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function render()
    {
        return view('admin::show.row', ['fields' => $this->fields]);
    }

    /**
     * @return Collection|\Dcat\Admin\Show\Field[]
     */
    public function fields()
    {
        return $this->fields;
    }

    /**
     * Set width for a incomming field.
     *
     * @param int $width
     *
     * @return $this
     */
    public function width($width = 12)
    {
        $this->defaultFieldWidth = $width;

        return $this;
    }

    /**
     * Add field.
     *
     * @param string $name
     * @param string $label
     *
     * @return \Dcat\Admin\Show\Field
     */
    public function field($name, $label = '')
    {
        $field = $this->show->field($name, $label);

        $this->pushField($field);

        return $field;
    }

    /**
     * Add field.
     *
     * @param $name
     *
     * @return \Dcat\Admin\Show\Field|Collection
     */
    public function __get($name)
    {
        $field = $this->show->field($name);

        $this->pushField($field);

        return $field;
    }

    /**
     * @param $method
     * @param $arguments
     *
     * @return \Dcat\Admin\Show\Field
     */
    public function __call($method, $arguments)
    {
        $field = $this->show->__call($method, $arguments);

        $this->pushField($field);

        return $field;
    }

    /**
     * @param \Dcat\Admin\Show\Field $field
     *
     * @return void
     */
    protected function pushField($field)
    {
        $this->fields->push([
            'width'   => $this->defaultFieldWidth,
            'element' => $field,
        ]);
    }
}

里面 __ cal l, __get , field 三个方法都是获取当前行的字段信息,并保存到行的属性,在最后渲染详情的时候先循环 rows(这一步在 Dcat\Admin\Show\Panel 的 render 方法), 在通过上面代码中的 render 方法渲染 rows 的每个字段;如下:

html 如下

<div class="box-body">
  <div class="form-horizontal mt-1">
      @if($rows->isEmpty())
          @foreach($fields as $field)
              {!! $field->render() !!}
          @endforeach
      @else
          <div>
              @foreach($rows as $row)
                  {!! $row->render() !!}
              @endforeach
          </div>
      @endif
      <div class="clearfix"></div>
  </div>
</div>


使用代码:

控制器创建一个 detail 方法
 

protected function detail($id)
  {
      return Show::make($id, new WxyMaterialItem("brands"), function (Show $show) {
          $show->row(function (Show\Row $row) {
              $row->width(6)->name;
              $row->width(6)->simple_code;
          });
          $show->row(function (Show\Row $row) {
              $row->width(4)->specs;
              $row->width(4)->integral_money;
              $row->width(4)->field("aa", "你好");
          });
          $show->row(function (Show\Row $row) {
              $row->width(4)->mdept_id("部门");
              $row->width(4)->status;
              $row->width(4)->field("brands.name", "品牌");
          });
      });
  }

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lansonli

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值