Laravel 後臺擴充套件包 Laravel-admin 多圖上傳功能之擴充套件 -- 已上傳圖片之可拖拽排序

Elijah_Wang發表於2019-03-15

最近公司使用 laravel(v5.5) 框架開發電商專案,後臺使用的是 laravel-admin(v1.5) 擴充套件包
laravel-admin 是一款優秀的 laravel 後臺擴充套件,感謝作者一直持續維護專案,並給出詳盡的開發文件,也是有心了,致敬~
然鵝,使用過程中也有一些不順手的地方,其中之一便是: Form 元件多圖上傳功能未能實現圖片可拖拽排序功能。
經過一天時間的除錯工作,該功能已被補充至公司線上專案,並執行正常。接下來,將功能擴充套件之開發流程分享一下,以期對其它 laravel-admin 使用者有所助益。

解決思路

  • 首先,通過追溯專案程式碼$form->multipleImage('photos', '相簿'),閱讀 PHP 類檔案 vendor/encore/laravel-admin/src/Form/Field/MultipleImage.phpvendor/encore/laravel-admin/src/Form/Field/MultipleFile.php ,發覺該多圖片/檔案上傳功能是藉由 HTML5 檔案上傳外掛 bootstrap-fileinput 實現的。
  • 通過閱讀該外掛的中文文件中的事件部分,猜想圖片拖拽排序行為觸發的應該是 filesorted 事件。
  • 至此,解決思路比較清晰了,需要修改 laravel-admin 擴充套件包 PHP 類檔案 MultipleFile.php ,然後在前端頁面引入 js 檔案,捕捉相關 form 表單元素節點的 filesorted 事件,做非同步 Ajax 提交實現多圖上傳之圖片拖拽排序功能

具體方案

  • 參考 bootstrap-fileinput 中文文件中的首頁介紹,圖片拖拽排序功能的實現依賴於 js 子外掛 sortable.min.js 的引入,因此,修改 laravel-admin 擴充套件包 PHP 類檔案 MultipleFile.php
    @vendor/encore/laravel-admin/src/Form/Field/MultipleFile.php on Line:27
    protected static $js = [
        '/vendor/laravel-admin/bootstrap-fileinput/js/plugins/canvas-to-blob.min.js?v=4.3.7',
        '/vendor/laravel-admin/bootstrap-fileinput/js/plugins/purify.min.js?v=4.3.7', // 視需求而定
        '/vendor/laravel-admin/bootstrap-fileinput/js/plugins/sortable.min.js?v=4.3.7', // 重點在這裡
        '/vendor/laravel-admin/bootstrap-fileinput/js/fileinput.min.js?v=4.3.7',
    ];
  • 開啟後臺路由檔案 app/Admin/routes.php,為該圖片拖拽排序功能新增一條路由規則,以備 Ajax 請求使用。另,在對應的後臺控制類檔案內,form() 方法下追加 <input type="hidden"> 標籤,為 Ajax 請求提供相關資料準備,具體資料內容視業務需求而定:
    if ($this->mode == Builder::MODE_EDIT) { // 判斷:經由 edit() 方法呼叫該 form() 方法
        ...
        $form->hidden('some_key')->default('some_value');
        $form->hidden('another_key')->default('another_value');
        ...
    }
  • 引入前端 js 檔案,根據 laravel-admin 官方文件介紹,開啟後臺 bootstrap 檔案(app/Admin/bootstrap.php):
    @app/Admin/bootstrap.php
    Admin::js('path/to/your/js');
  • js 部分程式碼之主要邏輯:
    @path/to/your/js
    var file_input_element = $('input.photos[name="photos[]"]');
    file_input_element.on('filesorted', function (event, params) {
        // console.log(params);
        // console.log(params.stack);
        // console.log('File sorted ', params.previewId, params.oldIndex, params.newIndex, params.stack);
        var token = $('input[name="_token"]').val(),
            some_photos = $('input.some_photos[name="some_photos"]').val(),
            sort_photos_url = $('input.sort_photos_url[name="sort_photos_url"]').val();
        var sorted_photos = params.stack,
            old_photos = JSON.parse(some_photos),
            new_photos = {};
        var photo_count = sorted_photos.length;
        for (var i = 0; i < photo_count; i++) {
            new_photos[i] = old_photos[sorted_photos[i].key];
        }
        var some_data = {
            _token: token,
            photos: new_photos,
        };
        $.ajax({
            type: "post",
            url: sort_photos_url,
            data: some_data,
            success: function (data) {
                console.log("Some Photos Sorted!");
            },
            error: function (error) {
                console.log(error);
            }
        });
    });

補刀

經同事點撥,發覺之前 具體方案 中,通過修改laravel-admin擴充套件包原始檔來實現js外掛引入的操作很傻,不利於新增程式碼版本控制,正確的操作應該是醬紫的:

@app/Admin/bootstrap.php
Admin::js('/vendor/laravel-admin/bootstrap-fileinput/js/plugins/purify.min.js?v=4.3.7'); // 視需求而定
Admin::js('/vendor/laravel-admin/bootstrap-fileinput/js/plugins/sortable.min.js?v=4.3.7'); // 重點在這裡

至此,問題解決。

敢竭鄙懷,恭疏短引;
一言均賦,四韻俱成。
請灑潘江,各傾陸海云爾。

夏蟲不語冰

相關文章