[Laravel Admin] 多图上传功能之扩展 -- 已上传图片之可拖拽排序

最近公司使用 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'); // 重点在这里

至此,问题解决。

敢竭鄙怀,恭疏短引;
一言均赋,四韵俱成。
请洒潘江,各倾陆海云尔。

本作品采用《CC 协议》,转载必须注明作者和本文链接
夏蟲不語冰
本帖由系统于 4年前 自动加精
Elijah_Wang
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 7

标记一下,之前遇到过这样的问题 :joy:

5年前 评论

MASK一下,刚好想完善一下laravel-admin多图上传功能

4年前 评论
Elijah_Wang

@Hetoo Mark 一下 :stuck_out_tongue_winking_eye:

4年前 评论

可以写个包直接引入到 admin 中

4年前 评论
Elijah_Wang (楼主) 4年前
foobar

mark

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!