xiongzhu vor 4 Jahren
Ursprung
Commit
57d6bc67bd

+ 243 - 0
src/main/vue/src/components/ModelUpload.vue

@@ -0,0 +1,243 @@
+<template>
+    <el-upload
+        class="file-upload"
+        :action="customUrl || uploadUrl"
+        :on-success="onSuccess"
+        :headers="headers"
+        :file-list="fileList"
+        :limit="filesLimit"
+        :on-exceed="onExceed"
+        :on-preview="onPreview"
+        :accept="accept || '*/*'"
+        ref="upload"
+    >
+        <el-button type="primary" size="mini" slot="trigger"> 点击上传 </el-button>
+        <div class="file-list-item" slot="file" slot-scope="{ file }">
+            <div class="file-name">
+                <i class="status-icon el-icon-warning-outline danger" v-if="file.status === 'fail'"></i>
+                <i class="status-icon el-icon-circle-check success" v-else-if="file.status === 'success'"></i>
+                <i class="status-icon el-icon-loading" v-else></i>
+                {{ file.name }}
+                <i class="opt">
+                    <i
+                        class="opt-icon el-icon-search"
+                        v-if="file.status === 'success' && isImage(file)"
+                        @click="preview(file)"
+                    ></i>
+                    <i class="opt-icon el-icon-download" v-if="file.status === 'success'" @click="download(file)"></i>
+                    <i class="opt-icon el-icon-delete" @click="removeFile(file)"></i>
+                </i>
+            </div>
+            <el-progress
+                v-if="file.status === 'uploading'"
+                :percentage="file.percentage"
+                :show-text="false"
+                :stroke-width="2"
+                class="upload-progress"
+            ></el-progress>
+        </div>
+        <el-image style="width: 0; height: 0" :src="previewUrl" :preview-src-list="[previewUrl]" ref="preview">
+        </el-image>
+    </el-upload>
+</template>
+
+<script>
+import resolveUrl from 'resolve-url';
+import axios from 'axios';
+export default {
+    name: 'FileUpload',
+    props: {
+        single: {
+            type: Boolean,
+            default() {
+                return false;
+            }
+        },
+        limit: {
+            type: Number,
+            default() {
+                return 10000;
+            }
+        },
+        value: {},
+        format: {
+            type: String,
+            default: 'string'
+        },
+        customUrl: {},
+        accept: {}
+    },
+    data() {
+        return {
+            fileList: [],
+            emitting: false,
+            uploadUrl: '',
+            previewUrl: null
+        };
+    },
+    computed: {
+        headers() {
+            return {
+                Authorization: 'Bearer ' + localStorage.getItem('token')
+            };
+        },
+        filesLimit() {
+            if (this.single) {
+                return 1;
+            }
+            return this.limit;
+        },
+        disabled() {
+            return this.fileList.length >= this.limit;
+        }
+    },
+    created() {
+        this.uploadUrl = resolveUrl(this.$baseUrl, 'upload/file');
+        this.update(this.value);
+    },
+    methods: {
+        onSuccess(res, file, fileList) {
+            this.fileList = [res];
+            this.emit();
+        },
+        update(value) {
+            if (this.filesLimit === 1) {
+                if (this.format === 'json') {
+                    this.fileList = value ? [{ name: value.name, url: value.url }] : [];
+                } else {
+                    this.fileList = value ? [{ name: value.split('/').pop(), url: value }] : [];
+                }
+            } else {
+                if (!value) {
+                    this.fileList = [];
+                } else {
+                    this.fileList = value.map(i => {
+                        return { name: i.name, url: i.url };
+                    });
+                }
+            }
+        },
+        onExceed(files, fileList) {
+            console.log(files, fileList);
+            this.$message.error(`最多上传${this.filesLimit}个文件`);
+        },
+        onPreview(file) {
+            console.log(file);
+        },
+        removeFile(file) {
+            if (file.status === 'uploading') {
+                this.$refs.upload.abort(file);
+            } else if (file.status === 'success') {
+                let index = this.fileList.findIndex(i => i.url === file.url);
+                if (index > -1) {
+                    this.fileList.splice(index, 1);
+                }
+            }
+            this.emit();
+        },
+        download(file) {
+            window.open(file.url, '_blank');
+        },
+        preview(file) {
+            this.previewUrl = file.url;
+            this.$nextTick(() => {
+                this.$refs.preview.clickHandler();
+            });
+        },
+        isImage(file) {
+            return /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(file.url);
+        },
+        emit() {
+            this.emitting = true;
+            if (this.filesLimit === 1) {
+                if (this.format === 'json') {
+                    this.$emit(
+                        'input',
+                        this.fileList[0]
+                            ? {
+                                  name: this.fileList[0].name,
+                                  url: this.fileList[0].url
+                              }
+                            : null
+                    );
+                } else {
+                    this.$emit('input', this.fileList[0] ? this.fileList[0].url : null);
+                }
+            } else {
+                if (this.format === 'json') {
+                    this.$emit(
+                        'input',
+                        this.fileList.map(i => {
+                            return {
+                                name: i.name,
+                                url: i.url
+                            };
+                        })
+                    );
+                } else {
+                    this.$emit(
+                        'input',
+                        this.fileList.map(i => i.url)
+                    );
+                }
+            }
+            this.$nextTick(() => {
+                this.emitting = false;
+            });
+        }
+    },
+    watch: {
+        value(value) {
+            if (this.emitting) return;
+            this.update(value);
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+.file-list-item {
+    line-height: 1.8;
+    margin-top: 5px;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    overflow: hidden;
+    cursor: pointer;
+    .file-name {
+        padding: 0 90px 0 20px;
+    }
+    .upload-progress {
+        margin-top: 2px;
+        position: absolute;
+        bottom: 0;
+        left: 20px;
+        right: 0;
+        width: auto;
+    }
+    .danger {
+        color: #f56c6c;
+    }
+    .success {
+        color: @success;
+    }
+    .status-icon {
+        position: absolute;
+        left: 0;
+        top: 0;
+        line-height: inherit;
+    }
+    .opt {
+        position: absolute;
+        right: 0;
+        top: 0;
+        line-height: inherit;
+        .opt-icon {
+            margin-left: 15px;
+            transition: color 0.3s;
+            &:hover {
+                color: @prim;
+            }
+        }
+    }
+}
+</style>

+ 4 - 2
src/main/vue/src/views/CollectionEdit.vue

@@ -30,14 +30,14 @@
                         <div class="tip">支持JPG、PNG、GIF、MP4,推荐长宽比1:1</div>
                     </el-form-item>
                     <el-form-item prop="model3d" label="3D模型">
-                        <file-upload
+                        <model-upload
                             :limit="1"
                             v-model="formData.model3d"
                             :customUrl="customUrl"
                             accept="application/zip"
                             format="json"
                             single
-                        ></file-upload>
+                        ></model-upload>
                         <div class="tip">请将FBX文件与贴图打包成zip压缩包上传</div>
                     </el-form-item>
                     <el-form-item prop="minterId" label="铸造者">
@@ -233,8 +233,10 @@
 </template>
 <script>
 import resolveUrl from 'resolve-url';
+import ModelUpload from '../components/ModelUpload.vue';
 export default {
     name: 'CollectionEdit',
+    components: { ModelUpload },
     created() {
         Promise.all([
             new Promise((resolve, reject) => {