Laravel Backpack 的多图上传及拖拽排序组件

更新日期: 2019-01-22 阅读次数: 6292 分类: backpack

功能

  • 多图上传
  • 拖拽图片排序
  • 删除图片
  • 点击放大预览
  • animated 特效

代码实现

<style type="text/css">
input.el-upload__input {
  display: none;
}
</style>

<div id="images_uploader_{{ $field['name'] }}"
     @include('crud::inc.field_wrapper_attributes') >

	<input type="hidden" name="{{ $field['name'] }}" value="{{ old($field['name']) ? old($field['name']) : (isset($field['value']) ? json_encode($field['value']) : (isset($field['default']) ? $field['default'] : '[]' )) }}" ref="input_hidden">
	<label>{!! $field['label'] !!}</label>

	@include('crud::inc.field_translatable_icon')

	<div>
        <div class="drag" style="float: left;">
            <ul class="el-upload-list el-upload-list--picture-card">
              <draggable v-model="images" class="dragArea">
                <li :tabindex="index" class="el-upload-list__item is-success animated" style=""
                    v-for="(element, index) in images"
                    v-bind:class="{flash: element.to_del}"
                    @click="preview(index)"
                    >
                    <img :src="element.url" alt="" class="el-upload-list__item-thumbnail ">
                    <a class="el-upload-list__item-name">
                        <i class="el-icon-document"></i>
                        @{{element.name}}
                    </a>
                    <label class="el-upload-list__item-status-label">
                        <i class="el-icon-upload-success el-icon-check"></i>
                    </label>
                    <i class="el-icon-close"></i>
                    <span class="el-upload-list__item-actions"><!---->
                        <span class="el-upload-list__item-delete">
                            <i class="el-icon-delete" @click.stop="remove(index)"></i>
                        </span>
                    </span>
                </li>
              </draggable>
            </ul>
        </div>

        <el-upload
             class="upload-demo"
             action="/api/upload_image_to_cdn"
             :multiple="true"
             @if (isset($field['limit']))
                :limit="{{ $field['limit'] }}"
             @else
                :limit="20"
             @endif
             :on-success="handle_success"
             list-type="picture-card"
             :show-file-list="false"
             >
              <el-button size="small" type="primary">点击上传</el-button>
        </el-upload>

        <el-dialog :visible.sync="dialogVisible">
            <img style="max-width: 100%; margin: 0 auto; display: block;" :src="dialogImageUrl" alt="">
        </el-dialog>
	</div>

    <br style="clear: both;"/>

	{{-- HINT --}}
	@if (isset($field['hint']))
	<p class="help-block">{!! $field['hint'] !!}</p>
	@endif
</div>

{{-- ########################################## --}}
{{-- Extra CSS and JS for this particular field --}}
{{-- If a field type is shown multiple times on a form, the CSS and JS will only be loaded once --}}
@if ($crud->checkIfFieldIsFirstOfItsType($field, $fields))

{{-- FIELD CSS - will be loaded in the after_styles section --}}
@push('crud_fields_styles')
    <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.4.11/theme-chalk/index.css" />
    <link rel="stylesheet" href="https://cdn.staticfile.org/animate.css/3.7.0/animate.min.css" />
@endpush

{{-- FIELD JS - will be loaded in the after_scripts section --}}
@push('crud_fields_scripts')
    <script type="text/javascript" src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
    <script type="text/javascript" src="https://cdn.staticfile.org/Sortable/1.8.1/Sortable.min.js"></script>
    <script type="text/javascript" src="https://cdn.staticfile.org/Vue.Draggable/2.17.0/vuedraggable.min.js"></script>
    <script type="text/javascript" src="https://cdn.staticfile.org/element-ui/2.4.11/index.js"></script>
@endpush

@endif

@push('crud_fields_scripts')
<script>
new Vue({
	el: "#images_uploader_{{ $field['name'] }}",

	data: {
		images: [],
        dialogVisible: false,
        dialogImageUrl: ''
	},

	mounted: function() {
        var value = this.$refs.input_hidden.value;
        var images = JSON.parse(value);
        var _images = [];

        for (var i = 0, len = images.length; i < len; i++) {
            _images.push({
                name: images[i],
                url: images[i],
                to_del: false
            });
        }

        this.images = _images;
	},

    watch: {
        images: function(nv, ov) {
            var images = [];
            for (var i = 0, len = nv.length; i < len; i++) {
                images.push(nv[i].url);
            }
            this.$refs.input_hidden.value = JSON.stringify(images);
        }
    },

	methods: {
        handle_success: function(response, file, fileList) {
            this.images.push({
                name: response.data,
                url: response.data,
                to_del: false
            });
        },

        remove: function(index) {
            var that = this;
			this.$confirm('确认删除?', '提示', {
				confirmButtonText: '确定',
				cancelButtonText: '取消',
				type: 'warning'
			}).then(function () {
				that.$message({
					type: 'success',
					message: '删除成功!'
				});
                that.images[index].to_del = true;
                setTimeout(function() {
            	    that.images.splice(index, 1);
                }, 1000);
			})
        },

        preview: function(index) {
            this.dialogImageUrl = this.images[index].url;
            this.dialogVisible = true;
        }
	}
});
</script>
@endpush
{{-- End of Extra CSS and JS --}}

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式