DactAdmin 省市區元件

思遠發表於2021-10-26

關於 "super-eggs/dcat-admin-extensions-distpicker": "^0.0.7"在 DactAdmin-v2.* 版本下無法使用。

做出如下調整,cj一枚,大家諒解。

:page_facing_up:/app/Admin/Extensions/Form/Distpicker.php

<?php

namespace App\Admin\Extensions\Form;

use Dcat\Admin\Form\Field;
use Illuminate\Support\Arr;

class Distpicker extends Field
{
    /**
     * @var string
     */
    protected $view = 'admin.distpicker.select';

    /**
     * @var array
     */
    protected static $js = [
        '/assets/distpicker/distpicker.min.js'
    ];

    /**
     * @var array
     */
    protected $columnKeys = ['province', 'city', 'district'];

    /**
     * @var array
     */
    protected $placeholder = [];

    /**
     * Distpicker constructor.
     *
     * @param array $column
     * @param array $arguments
     */
    public function __construct($column, $arguments)
    {
        if (!Arr::isAssoc($column)) {
            $this->column = array_combine($this->columnKeys, $column);
        } else {
            $this->column      = array_combine($this->columnKeys, array_keys($column));
            $this->placeholder = array_combine($this->columnKeys, $column);
        }

        $this->label = empty($arguments) ? '地區選擇' : current($arguments);
    }

    public function getValidator(array $input)
    {
        if ($this->validator) {
            return $this->validator->call($this, $input);
        }

        $rules = $attributes = [];

        if (!$fieldRules = $this->getRules()) {
            return false;
        }

        foreach ($this->column as $key => $column) {
            if (!Arr::has($input, $column)) {
                continue;
            }
            $input[$column] = Arr::get($input, $column);
            $rules[$column] = $fieldRules;
            $attributes[$column] = $this->label."[$column]";
        }

        return \validator($input, $rules, $this->getValidationMessages(), $attributes);
    }

    /**
     * @param int $count
     * @return $this
     */
    public function autoselect($count = 0)
    {
        return $this->attribute('data-autoselect', $count);
    }

    /**
     * {@inheritdoc}
     */
    public function render()
    {
        $this->attribute('data-value-type', 'code');

        $province = old($this->column['province'], Arr::get($this->value(), 'province')) ?: Arr::get($this->placeholder, 'province');
        $city     = old($this->column['city'],     Arr::get($this->value(), 'city'))     ?: Arr::get($this->placeholder, 'city');
        $district = old($this->column['district'], Arr::get($this->value(), 'district')) ?: Arr::get($this->placeholder, 'district');

        $id = uniqid('distpicker-');

        $this->script = <<<EOT
var oid = '{$id}',
    nid = 'distpicker-' + Math.random().toString(36).substring(2);
$('label[for=' + oid + ']').attr('for', nid);
$('#' + oid).attr('id', nid).distpicker({
  province: '$province',
  city: '$city',
  district: '$district'
});
EOT;
        $this->addVariables(compact('id'));
        return parent::render();
    }
}

:page_facing_up: /resources/views/admin/distpicker/select.blade.php

<div class="{{$viewClass['form-group']}} {!! !$errors->hasAny($errorKey) ? '' : 'has-error' !!}">

    <label for="{{$id}}" class="{{$viewClass['label']}} control-label">{{$label}}</label>

    <div class="{{$viewClass['field']}} form-inline">

        @foreach($errorKey as $key => $col)
            @if($errors->has($col))
                @foreach($errors->get($col) as $message)
                    <label class="control-label" for="inputError"><i class="fa fa-times-circle-o"></i> {{$message}}</label><br/>
                @endforeach
            @endif
        @endforeach

        <div id="{{ $id }}" {!! $attributes !!}>
            <select class="form-control" name="{{$name['province']}}"></select>&nbsp;
            <select class="form-control" name="{{$name['city']}}"></select>&nbsp;
            <select class="form-control" name="{{$name['district']}}"></select>&nbsp;
        </div>
        @include('admin::form.help-block')

    </div>
</div>

:page_facing_up: /app/Admin/Extensions/Form/DistpickerFilter.php

<?php

namespace App\Admin\Extensions\Form;

use Dcat\Admin\Admin;
use Dcat\Admin\Grid\Filter\AbstractFilter;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Dcat\Admin\Grid\Filter;

class DistpickerFilter extends AbstractFilter
{
    /**
     * @var array
     */
    protected $column = [];

    protected static $js = [
        '/assets/distpicker/distpicker.min.js'
    ];

    /**
     * @var array
     */
    protected $value = [];

    /**
     * @var array
     */
    protected $defaultValue = [];

    /**
     * DistpickerFilter constructor.
     *
     * @param string $province
     * @param string $city
     * @param string $district
     * @param string $label
     */
    public function __construct($province, $city, $district, $label = '')
    {
        $this->column = compact('province', 'city', 'district');
        $this->label  = $label;

        $this->setPresenter(new FilterPresenter());
    }

    public function setParent(Filter $filter)
    {
        $this->parent = $filter;

        $this->id = $this->formatId($this->column);
    }


    /**
     * {@inheritdoc}
     */
    public function getColumn()
    {
        $columns = [];

        $parentName = $this->parent->getName();

        foreach ($this->column as $column) {
            $columns[] = $parentName ? "{$parentName}_{$column}" : $column;
        }

        return $columns;
    }

    /**
     * {@inheritdoc}
     */
    public function condition($inputs)
    {
        $value = array_filter([
            $this->column['province'] => Arr::get($inputs, $this->column['province']),
            $this->column['city']     => Arr::get($inputs, $this->column['city']),
            $this->column['district'] => Arr::get($inputs, $this->column['district']),
        ]);

        if (!isset($value)) {
            return;
        }

        $this->value = $value;

         if (!$this->value) {
            return [];
        }


        if (Str::contains(key($value), '.')) {
            return $this->buildRelationQuery($value);
        }

        return [$this->query => [$value]];
    }

    /**
     * {@inheritdoc}
     */
    protected function buildRelationQuery(...$columns)
    {
        $data = [];

        foreach ($columns as $column => $value) {
            Arr::set($data, $column, $value);
        }

        $relation = key($data);

        $args = $data[$relation];

        return ['whereHas' => [$relation, function ($relation) use ($args) {
            call_user_func_array([$relation, $this->query], [$args]);
        }]];
    }

    /**
     * {@inheritdoc}
     */
    public function formatName($column)
    {
        $columns = [];

        foreach ($column as $col => $name) {
            $columns[$col] = parent::formatName($name);
        }

        return $columns;
    }

    protected function formatId($columns)
    {
        return str_replace('.', '_', $columns);
    }

    /**
     * Setup js scripts.
     */
    protected function setupScript()
    {
        $province = old($this->column['province'], Arr::get($this->value, $this->column['province']));
        $city     = old($this->column['city'], Arr::get($this->value, $this->column['city']));
        $district = old($this->column['district'], Arr::get($this->value, $this->column['district']));

        $script = <<<JS
$("#{$this->id}").distpicker({
  province: '$province',
  city: '$city',
  district: '$district'
});
JS;
        Admin::script($script);
        Admin::js(static::$js);
    }

    /**
     * {@inheritdoc}
     */
    protected function variables()
    {
        $this->id = 'distpicker-filter-' . uniqid();

        $this->setupScript();

        return array_merge([
            'id'        => $this->id,
            'name'      => $this->formatName($this->column),
            'label'     => $this->label,
            'value'     => $this->value ?: $this->defaultValue,
            'presenter' => $this->presenter(),
        ], $this->presenter()->variables());
    }

    public function render()
    {
        return view('admin.distpicker.filter', $this->variables());
    }
}

:page_facing_up: /resources/views/admin/distpicker/select.blade.php

<div class="filter-input col-sm-10" style="">
    <div class="form-group">
        <div class="input-group input-group-sm">
            <div class="input-group-prepend" id="{{ $id }}" data-value-type="code">
                <span class="input-group-text bg-white text-capitalize"><b>{!! $label !!}</b></span>
                    <select class="form-control" name="{{$name['province']}}"></select>&nbsp;
                    <select class="form-control" name="{{$name['city']}}"></select>&nbsp;
                    <select class="form-control" name="{{$name['district']}}"></select>&nbsp;
            </div>
        </div>
    </div>
</div>

:page_facing_up: /app/Admin/bootstrap.php

...
Form::extend('distpicker', Distpicker::class);

:page_facing_up: /app/Admin/Controllers/AutoController

$form->distpicker(['work_province_id', 'work_city_id', 'work_district_id']);

不要站著除錯程式,那會使得你的耐心減半,你需要的是全神貫注。—— Dave Storer

本作品採用《CC 協議》,轉載必須註明作者和本文連結
siYuanJun

相關文章