panhui %!s(int64=5) %!d(string=hai) anos
pai
achega
28d1616f22
Modificáronse 1 ficheiros con 249 adicións e 0 borrados
  1. 249 0
      src/main/vue/src/components/AttachmentUpload.vue

+ 249 - 0
src/main/vue/src/components/AttachmentUpload.vue

@@ -0,0 +1,249 @@
+<template>
+    <div>
+        <el-upload
+            class="file-upload"
+            :action="uploadUrl"
+            :on-success="onSuccess"
+            :headers="headers"
+            :file-list="fileList"
+            :limit="filesLimit"
+            :on-exceed="onExceed"
+            :on-preview="onPreview"
+            ref="upload"
+        >
+            <el-button type="primary" v-if="fileList.length < filesLimit" size="mini" slot="trigger">
+                点击上传
+            </el-button>
+            <div slot="tip" class="el-upload__tip">
+                <slot></slot>
+            </div>
+            <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>
+        <el-input
+            class="file-remark"
+            v-model="remark"
+            @change="remarkChange"
+            placeholder="请输入备注内容…"
+            size="mini"
+            clearable
+        ></el-input>
+    </div>
+</template>
+
+<script>
+import resolveUrl from 'resolve-url';
+import axios from 'axios';
+export default {
+    name: 'FileUpload',
+    props: {
+        single: {
+            type: Boolean,
+            default() {
+                return true;
+            }
+        },
+        limit: {
+            type: Number,
+            default() {
+                return 10000;
+            }
+        },
+        value: {},
+        format: {
+            type: String,
+            default: 'json'
+        }
+    },
+    data() {
+        return {
+            fileList: [],
+            emitting: false,
+            uploadUrl: '',
+            previewUrl: null,
+            remark: ''
+        };
+    },
+    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) {
+            file.url = res;
+            this.fileList = fileList;
+            this.emit();
+        },
+        update(value) {
+            this.fileList = value && value.url ? [{ name: value.fileName, url: value.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;
+            this.$emit(
+                'input',
+                this.fileList[0]
+                    ? {
+                          ...this.value,
+                          fileName: this.fileList[0].name,
+                          url: this.fileList[0].url
+                      }
+                    : null
+            );
+            this.$nextTick(() => {
+                this.emitting = false;
+            });
+        },
+        remarkChange() {
+            this.emitting = true;
+            this.$emit('input', { ...this.value, remark: this.remark });
+            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: #67c23a;
+    }
+    .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: #d7ab41;
+            }
+        }
+    }
+}
+.file-remark {
+    margin-top: 14px;
+}
+
+.el-upload {
+    line-height: 0px;
+}
+</style>
+<style lang="less">
+.file-remark {
+    input {
+        padding: 0 30px 0 8px;
+
+        background: #f5f7fa;
+        border-width: 0;
+    }
+}
+</style>