Browse Source

重构数据导出功能

jqh 6 years ago
parent
commit
5089c1401a

+ 1 - 7
src/Grid.php

@@ -160,6 +160,7 @@ class Grid
         'show_quick_create_btn'  => false,
         'show_bordered'          => false,
         'show_toolbar'           => true,
+        'show_exporter'          => false,
 
         'row_selector_style'     => 'primary',
         'row_selector_circle'    => true,
@@ -167,15 +168,8 @@ class Grid
         'row_selector_label_key' => null,
         'row_selector_bg'        => 'var(--20)',
 
-        'show_exporter'             => false,
-        'show_export_all'           => true,
-        'show_export_current_page'  => true,
-        'show_export_selected_rows' => true,
-        'export_chunk_size'         => 5000,
-
         'dialog_form_area'   => ['700px', '670px'],
         'table_header_style' => 'table-header-gray',
-
     ];
 
     /**

+ 21 - 33
src/Grid/Concerns/HasExporter.php

@@ -24,15 +24,24 @@ trait HasExporter
     /**
      * Set exporter driver for Grid to export.
      *
-     * @param string|Grid\Exporters\AbstractExporter $exporter
+     * @param string|Grid\Exporters\AbstractExporter|array $exporter
      *
-     * @return $this
+     * @return Grid\Exporters\AbstractExporter
      */
-    public function exporter($exporter)
+    public function exporter($exporter = null)
     {
-        $this->exportDriver = $exporter;
+        $titles = [];
+
+        if (is_array($exporter) || $exporter === false) {
+            $titles   = $exporter;
+            $exporter = null;
+        }
 
-        return $this;
+        $this->showExporter();
+
+        $driver = $this->exportDriver ?: ($this->exportDriver = $this->getExporter()->resolve($exporter));
+
+        return $driver->titles($titles);
     }
 
     /**
@@ -67,7 +76,7 @@ trait HasExporter
     /**
      * @return Exporter
      */
-    protected function getExporter()
+    public function getExporter()
     {
         return $this->exporter ?: ($this->exporter = new Exporter($this));
     }
@@ -75,7 +84,7 @@ trait HasExporter
     /**
      * @param string $gridName
      */
-    protected function setExporterQueryName($gridName)
+    public function setExporterQueryName($gridName)
     {
         if (! $this->allowExporter()) {
             return;
@@ -91,7 +100,11 @@ trait HasExporter
      */
     protected function resolveExportDriver($scope)
     {
-        return $this->getExporter()->resolve($this->exportDriver)->withScope($scope);
+        if (! $this->exportDriver) {
+            $this->exportDriver = $this->getExporter()->resolve();
+        }
+
+        return $this->exportDriver->withScope($scope);
     }
 
 
@@ -114,31 +127,6 @@ trait HasExporter
         return $this->getResource().'?'.http_build_query($input);
     }
 
-    /**
-     * @param array $options
-     * @return $this
-     */
-    public function setExporterOptions(array $options)
-    {
-        if (isset($options['chunk_size'])) {
-            $this->options['export_chunk_size'] = (int) $options['chunk_size'];
-        }
-
-        if (isset($options['all'])) {
-            $this->options['show_export_all'] = $options['show_all'];
-        }
-
-        if (isset($options['current_page'])) {
-            $this->options['show_export_current_page'] = $options['current_page'];
-        }
-
-        if (isset($options['selected_rows'])) {
-            $this->options['show_export_selected_rows'] = $options['selected_rows'];
-        }
-
-        return $this;
-    }
-
     /**
      * Render export button.
      *

+ 79 - 10
src/Grid/Exporter.php

@@ -3,7 +3,6 @@
 namespace Dcat\Admin\Grid;
 
 use Dcat\Admin\Grid;
-use Dcat\Admin\Grid\Exporters\CsvExporter;
 
 class Exporter
 {
@@ -33,6 +32,16 @@ class Exporter
      */
     protected $grid;
 
+    /**
+     * @var array
+     */
+    protected $options = [
+        'show_export_all'           => true,
+        'show_export_current_page'  => true,
+        'show_export_selected_rows' => true,
+        'chunk_size'                => 5000,
+    ];
+
     /**
      * Create a new Exporter instance.
      *
@@ -57,6 +66,66 @@ class Exporter
         return $this;
     }
 
+    /**
+     *  Get or set option for exporter.
+     *
+     * @param string $key
+     * @param mixed|null $value
+     * @return $this|mixed|null
+     */
+    public function option($key, $value = null)
+    {
+        if ($value === null) {
+            return $this->options[$key] ?? null;
+        }
+
+        $this->options[$key] = $value;
+
+        return $this;
+    }
+
+    /**
+     * Disable export all.
+     *
+     * @param bool $value
+     * @return $this
+     */
+    public function disableExportAll(bool $value = true)
+    {
+        return $this->option('show_export_all', ! $value);
+    }
+
+    /**
+     * Disable export current page.
+     *
+     * @param bool $value
+     * @return $this
+     */
+    public function disableExportCurrentPage(bool $value = true)
+    {
+        return $this->option('show_export_current_page', ! $value);
+    }
+
+    /**
+     * Disable export selected rows.
+     *
+     * @param bool $value
+     * @return $this
+     */
+    public function disableExportSelectedRow(bool $value = true)
+    {
+        return $this->option('show_export_selected_rows', ! $value);
+    }
+
+    /**
+     * @param int $value
+     * @return $this
+     */
+    public function chunkSize(int $value)
+    {
+        return $this->option('chunk_size', $value);
+    }
+
     /**
      * Get export query name.
      *
@@ -83,11 +152,11 @@ class Exporter
      *
      * @param string $driver
      *
-     * @return CsvExporter
+     * @return Grid\Exporters\AbstractExporter
      */
-    public function resolve($driver)
+    public function resolve($driver = null)
     {
-        if ($driver instanceof Grid\Exporters\AbstractExporter) {
+        if ($driver && $driver instanceof Grid\Exporters\AbstractExporter) {
             return $driver->setGrid($this->grid);
         }
 
@@ -101,9 +170,9 @@ class Exporter
      *
      * @return Grid\Exporters\AbstractExporter
      */
-    protected function getExporter($driver)
+    protected function getExporter($driver): Grid\Exporters\AbstractExporter
     {
-        if (!array_key_exists($driver, static::$drivers)) {
+        if (! $driver || ! array_key_exists($driver, static::$drivers)) {
             return $this->getDefaultExporter();
         }
 
@@ -117,7 +186,7 @@ class Exporter
      */
     public function getDefaultExporter()
     {
-        return (new Grid\Exporters\XlsxExporter())->setGrid($this->grid);
+        return Grid\Exporters\ExcelExporter::make()->setGrid($this->grid);
     }
 
     /**
@@ -133,15 +202,15 @@ class Exporter
         $query = '';
 
         if ($scope == static::SCOPE_ALL) {
-            $query = 'all';
+            $query = $scope;
         }
 
         if ($scope == static::SCOPE_CURRENT_PAGE) {
-            $query = "page:$args";
+            $query = "$scope:$args";
         }
 
         if ($scope == static::SCOPE_SELECTED_ROWS) {
-            $query = "selected:$args";
+            $query = "$scope:$args";
         }
 
         return [$this->queryName => $query];

+ 143 - 16
src/Grid/Exporters/AbstractExporter.php

@@ -5,6 +5,11 @@ namespace Dcat\Admin\Grid\Exporters;
 use Dcat\Admin\Grid;
 use Illuminate\Support\Str;
 
+/**
+ * @method $this disableExportAll(bool $value = true)
+ * @method $this disableExportCurrentPage(bool $value = true)
+ * @method $this disableExportSelectedRow(bool $value = true)
+ */
 abstract class AbstractExporter implements ExporterInterface
 {
     /**
@@ -12,6 +17,11 @@ abstract class AbstractExporter implements ExporterInterface
      */
     protected $grid;
 
+    /**
+     * @var Grid\Exporter
+     */
+    protected $parent;
+
     /**
      * @var \Closure
      */
@@ -20,37 +30,125 @@ abstract class AbstractExporter implements ExporterInterface
     /**
      * @var array
      */
-    public $titles = [];
+    protected $titles = [];
 
     /**
      * @var array
      */
-    public $data;
+    protected $data;
 
     /**
      * @var string
      */
-    public $filename;
+    protected $filename;
 
     /**
      * @var string
      */
     protected $scope;
 
+    /**
+     * @var string
+     */
+    protected $extension = 'xlsx';
+
     /**
      * Create a new exporter instance.
      *
-     * @param $builder
+     * @param array $titles
      */
-    public function __construct($builder = null)
+    public function __construct($titles = [])
     {
-        if ($builder instanceof \Closure) {
-            $builder->bindTo($this);
+        $this->titles($titles);
+    }
 
-            $this->builder = $builder;
-        } elseif (is_array($builder)) {
-            $this->titles = $builder;
+    /**
+     * Set the headings of excel sheet.
+     *
+     * @param array|false $titles
+     * @return $this
+     */
+    public function titles($titles)
+    {
+        if (is_array($titles) || $titles === false) {
+            $this->titles = $titles;
         }
+
+        return $this;
+    }
+
+    /**
+     * Set filename.
+     *
+     * @param string|\Closure $filename
+     * @return $this
+     */
+    public function filename($filename)
+    {
+        $this->filename = value($filename);
+
+        return $this;
+    }
+
+    /**
+     * Set export data.
+     *
+     * @param array $data
+     * @return $this
+     */
+    public function data($data)
+    {
+        $this->data = $data;
+
+        return $this;
+    }
+
+    /**
+     * Set export data callback function.
+     *
+     * @param \Closure $builder
+     * @return $this
+     */
+    public function rows(\Closure $builder)
+    {
+        $this->builder = $builder;
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    public function xlsx()
+    {
+        return $this->extension('xlsx');
+    }
+
+    /**
+     * @return $this
+     */
+    public function csv()
+    {
+        return $this->extension('csv');
+    }
+
+    /**
+     * @return $this
+     */
+    public function ods()
+    {
+        return $this->extension('ods');
+    }
+
+    /**
+     * @param string $ext e.g. csv/xlsx/ods
+     * @return $this
+     */
+    public function extension(string $ext)
+    {
+        $this->extension = $ext;
+
+        return $this;
     }
 
     /**
@@ -62,7 +160,8 @@ abstract class AbstractExporter implements ExporterInterface
      */
     public function setGrid(Grid $grid)
     {
-        $this->grid = $grid;
+        $this->grid   = $grid;
+        $this->parent = $grid->getExporter();
 
         return $this;
     }
@@ -73,7 +172,7 @@ abstract class AbstractExporter implements ExporterInterface
      */
     public function getFilename()
     {
-        return $this->filename ?? (date('Ymd-His') . '-' . Str::random(6));
+        return $this->filename ?: (admin_trans_label().'-'.date('Ymd-His').'-'.Str::random(6));
     }
 
     /**
@@ -97,16 +196,31 @@ abstract class AbstractExporter implements ExporterInterface
             $perPage = $model->getPerPage();
         }
 
-        $model->reset();
         $model->usePaginate(false);
 
         if ($page && $this->scope !== Grid\Exporter::SCOPE_SELECTED_ROWS) {
-            $perPage = $perPage ?: $this->grid->option('export_chunk_size');
+            $perPage = $perPage ?: $this->getChunkSize();
 
             $model->forPage($page, $perPage);
         }
 
-        return $this->grid->getFilter()->execute(true);
+        $array = $this->grid->getFilter()->execute(true);
+
+        $model->reset();
+
+        if ($this->builder) {
+            return ($this->builder)($array);
+        }
+
+        return $array;
+    }
+
+    /**
+     * @return int
+     */
+    protected function getChunkSize()
+    {
+        return $this->parent->option('chunk_size') ?: 5000;
     }
 
     /**
@@ -139,13 +253,26 @@ abstract class AbstractExporter implements ExporterInterface
      */
     abstract public function export();
 
+    /**
+     * @param $method
+     * @param $arguments
+     * @return mixed
+     */
+    public function __call($method, $arguments)
+    {
+        $this->parent->{$method}(...$arguments);
+
+        return $this;
+    }
+
     /**
      * Create a new exporter instance.
      *
      * @param \Closure|array $closure
      */
-    public static function create($builder = null)
+    public static function make($builder = null)
     {
         return new static($builder);
     }
+
 }

+ 1 - 6
src/Grid/Exporters/CsvExporter.php → src/Grid/Exporters/ExcelExporter.php

@@ -5,13 +5,8 @@ namespace Dcat\Admin\Grid\Exporters;
 use Dcat\EasyExcel\Excel;
 use Dcat\Admin\Grid;
 
-class CsvExporter extends AbstractExporter
+class ExcelExporter extends AbstractExporter
 {
-    /**
-     * @var string
-     */
-    protected $extension = 'csv';
-
     /**
      * {@inheritdoc}
      */

+ 0 - 11
src/Grid/Exporters/XlsxExporter.php

@@ -1,11 +0,0 @@
-<?php
-
-namespace Dcat\Admin\Grid\Exporters;
-
-class XlsxExporter extends CsvExporter
-{
-    /**
-     * @var string
-     */
-    protected $extension = 'xlsx';
-}

+ 3 - 2
src/Grid/Model.php

@@ -697,8 +697,9 @@ class Model
      */
     public function reset()
     {
-        $this->data  = null;
-        $this->model = null;
+        $this->data    = null;
+        $this->model   = null;
+        $this->queries = collect();
 
         return $this;
     }

+ 6 - 3
src/Grid/Tools/ExportButton.php

@@ -51,7 +51,7 @@ JS;
      */
     protected function renderExportAll()
     {
-        if (! $this->grid->option('show_export_all')) {
+        if (! $this->grid->getExporter()->option('show_export_all')) {
             return;
         }
         $all = trans('admin.all');
@@ -64,7 +64,7 @@ JS;
      */
     protected function renderExportCurrentPage()
     {
-        if (! $this->grid->option('show_export_current_page')) {
+        if (! $this->grid->getExporter()->option('show_export_current_page')) {
             return;
         }
 
@@ -79,7 +79,10 @@ JS;
      */
     protected function renderExportSelectedRows()
     {
-        if (! $this->grid->option('show_row_selector') || ! $this->grid->option('show_export_selected_rows')) {
+        if (
+            ! $this->grid->option('show_row_selector')
+            || ! $this->grid->getExporter()->option('show_export_selected_rows')
+        ) {
             return;
         }