DcatAdmin 配合 `maatwebsite/excel` 扩展 在后台增加 excel 导出的功能,并可导出图片

1. 准备

1.1 环境

  1. Laravel 版本:Laravel Framework 8.77.1
  2. PHP 版本:PHP 8.0.6 (cli)

1.2 扩展包

  1. dcatAdmin 的扩展,文档链接:传送

    composer require dcat/laravel-admin
  2. maatwebsite/exce 的扩展,文档链接:传送

    composer require maatwebsite/excel

2. 代码

2.1 新增GridTool文件

  1. 新增 dcatAdmin 的 GridTool 文件

    php artisan admin:action
  2. 选择 [3] grid-tool

    Which type of action would you like to make?:
    ...
    [3] grid-tool
    ...
  3. 设置 grid-tool 的文件名

    InspectionItemsPostExportTool
  4. InspectionItemsPostExportTool 文件内容主要的方法:

    ...
     /**
      *  接收参数 * InspectionItemsPost constructor
      * @param null $filename
      * @param $title
      */
     public function __construct($filename = null, $title = '')
     {
         parent::__construct($title);
         $this->title = $title;
     }
    
     /**
      * @return string
      */
     protected $title = '导出巡检信息';
    
     /**
      *  按钮的样式 * @var string
      */
     protected $style = 'btn btn-outline-info';
    
     /**
      *  业务处理 * @param Request $request
      * @return Response
      */
     public function handle(Request $request)
     {
         // 获取文件名
         $filename = $request->get('filename');
         // 这里有一个 admin_route 路由,接下来在 route.php 文件添加
         return $this->response()->download(admin_route('inspection-item-posts.export'[
             'filename' => $filename,
         ]);
     }
     ...

2.2 新增控制器方法

  1. 控制器增加 export() 方法

    ...
     /**
      *  巡检记录数据的导出
      * @param Request $request
      * @return BinaryFileResponse
      */
     public function export(Request $request)
     {
         $filename = $request->get('filename');
         ob_end_clean();
         // 这里面有一个 InspectionItemPostExport 文件,接下来通过 php artisan make:export 命令创建
         return Excel::download(new InspectionItemPostExport(), $filename . '.xlsx');
     }
    ...
  2. 新增控制器路由:

     // 记着:单个方法的路由一定要放到 resource 资源路由前面
     $router->get('inspection-item-posts/export', 'InspectionItemPostController@export')->name('inspection-item-posts.export');
  3. 在控制器的 grid 方法中引入这个 tool 按钮文件

    /**
      * Make a grid builder.
      *
      * @return Grid
      */
     protected function grid()
     {
         return Grid::make(new InspectionItemPost(['productionLine', 'inspectionPoint', 'inspectionItem', 'user']), function (Grid $grid) {
             $grid->column('id')->sortable();
             // 引入导出工具按钮
             $grid->tools(function (Grid\Tools $tools) use ($grid) {
                 // 导出
                 $tools->append(new InspectionItemsPostExportTool('巡检问题信息', '导出巡检问题信息'));
             });
         });
     }

2.3 创建导出文件

  1. 创建 export 文件

    php artisan make:export InspectionItemPostExport
  2. InspectionItemPostExport 文件的方法

    // 我这里实现了几个接口
    // FromCollection 必须实现 collection() 方法
    // ShouldAutoSize 不需要实现接口,自动设定 excel 表格 column 的宽度
    // WithDrawings 必须实现 drawings() 方法,可以在 excel 表格中添加图片(图片需是本地地址)
    // WithColumnWidths 必须实现 columnWidths() 可以设定对应列的宽,可与 ShouldAutoSize 一起使用,不过本设定优先
    class InspectionItemPostExport implements FromCollection, ShouldAutoSize, WithDrawings, WithColumnWidths
    {
         // 最总数据
         private $data;
         // 图片数据
         private $imageData;
    
         /**
         *  构造方法
         * InspectionItemPostExport constructor.
         */
         public function __construct()
         {
             // 表头设定
             $this->data = $this->createData();
         }
    
         /**
          *  数组转集合 
          * @return Collection
          */
         public function collection()
         {
              return new Collection($this->data);
         }
    
         /**
          *  业务代码 
          * @return array|string[][]
           */
         public function createData()
         {
             $headTitle = [
                 '编号',
                 '提交类型',
                 '生产线',
                 '巡检点',
                 '观察项',
                 '巡检人',
                 '紧急状态',
                 '问题图片',
                 '问题说明',
                 '创建时间',
             ];
             $bodyData = [];
             $data = InspectionItemPost::with('productionLine:id,name')
                 ->with('inspectionPoint:id,name')
                 ->with('inspectionItem:id,name')
                 ->with('user:id,name')
                 ->get();
             if (empty($data)) {
                 return [$headTitle];
             }
             // 数据循环
             foreach ($data as $k => $item) {
                 $arr[0] = $item->id;
                 $arr[1] = Arr::get(InspectionItemPostRepositories::TYPE_OPTION, $item->type, '无');
                 $arr[2] = $item->productionLine->name ?? '';
                 $arr[3] = $item->inspectionPoint->name ?? '';
                 $arr[4] = $item->inspectionItem->name ?? '';
                 $arr[5] = $item->user->name ?? '';
                 $arr[6] = Arr::get(InspectionItemPostRepositories::STATUS_OPTION, $item->status, '无');
                 $arr[7] = '';    // 这里设置为空为后续添加图片腾出地方
                 $this->imageData[] = $url;
                 $arr[8] = $item->remark;
                 $arr[9] = $item->created_at;
                 $bodyData[] = $arr;
             }
             // 清除掉 $arr
             unset($arr);
             return [$headTitle, $bodyData];
         }
    
         /**
          *  绘画 * @return array|BaseDrawing|BaseDrawing[]
           */
         public function drawings()
         {
             $result = [];
             foreach ($this->imageData as $k => $v) {
                 // 如果存在全连接跳出
                 if (strpos($v, 'http') === 0 || strpos($v, 'https') === 0) {
                     continue;
                 }
                 // 如果图片不存在跳出
                 if (!Storage::exists($v)) {
                     continue;
                 }
                 $k += 2;
                 ${'drawing' . $k} = new Drawing();
                 ${'drawing' . $k}->setName('问题图片');
                 ${'drawing' . $k}->setDescription('问题图片');
                 //图片路径
                 ${'drawing' . $k}->setPath(Storage::path($v));
                 ${'drawing' . $k}->setHeight(50);
                 //设置图片列
                 ${'drawing' . $k}->setCoordinates('H' . $k);
                 $result[] = ${'drawing' . $k};
             }
             return $result;
         }
    
         /**
          *  列宽限制 * @return int[]
          */
         public function columnWidths(): array
         {
             return [
                 'A' => 10,
                 'B' => 15,
                 'C' => 15,
                 'D' => 15,
                 'E' => 40,
                 'F' => 10,
                 'G' => 10,
                 'H' => 20,
                 'I' => 30,
                 'J' => 20,
             ];
         }
    }
本作品采用《CC 协议》,转载必须注明作者和本文链接
Xiao Peng
本帖由系统于 6个月前 自动加精
laravel_peng
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
技术员 @ 北之海信息科技有限公司
文章
9
粉丝
8
喜欢
77
收藏
128
排名:860
访问:6840
私信
所有博文
社区赞助商