| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- <template>
- <div class="sc-upload-file">
- <el-upload ref="uploader"
- :class="hideAdd && 'el-upload-hide-add'"
- v-model:file-list="defaultFileList"
- action=""
- :accept="accept"
- :limit="limit"
- :drag="drag"
- :multiple="multiple"
- :disabled="disabled"
- show-file-list
- :http-request="request"
- :before-upload="before"
- :before-remove="beforeRemove"
- :on-success="success"
- :on-error="error"
- :on-preview="handlePreview"
- :on-exceed="handleExceed">
- <slot>
- <div v-if="drag" class="file-empty">
- <el-icon><el-icon-upload-filled /></el-icon>
- <h4>将文件拖到此处,或<el-text type="primary">点击上传</el-text></h4>
- </div>
- <vxe-button v-else status="primary" size="mini" content="点击上传" :disabled="disabled"></vxe-button>
- </slot>
- <template #tip>
- <div v-if="tip" :class="['el-upload__tip', tipRequired && 'el-upload__tip-required']">{{ tip }}</div>
- </template>
- </el-upload>
- <span style="display: none!important;"><el-input v-model="value"></el-input></span>
- </div>
- <file-viewer v-if="showViewer" ref="fileViewer" @closed="showViewer = false"></file-viewer>
- </template>
- <script>
- import XEUtils from "xe-utils";
- export default {
- props: {
- modelValue: { type: Array, default: () => [] },
- tip: { type: String, default: "" },
- tipRequired: { type: Boolean, default: false },
- accept: { type: String, default: "" },
- maxSize: { type: Number, default: 50 },
- limit: { type: Number, default: 0 },
- drag: { type: Boolean, default: false },
- multiple: { type: Boolean, default: true },
- disabled: { type: Boolean, default: false },
- hideAdd: { type: Boolean, default: false },
- onSuccess: { type: Function, default: () => true },
- params: { type: Object, default: () => ({}) }
- },
- data() {
- return {
- value: "",
- defaultFileList: [],
- showViewer: false
- }
- },
- watch: {
- modelValue(val) {
- if (JSON.stringify(val) != JSON.stringify(this.formatArr(this.defaultFileList))) {
- this.defaultFileList = val;
- this.value = val;
- }
- },
- defaultFileList: {
- deep: true,
- handler(val) {
- this.$emit("update:modelValue", this.formatArr(val));
- this.value = val.map(v => v.path).join();
- }
- }
- },
- mounted() {
- this.defaultFileList = this.modelValue;
- this.value = this.modelValue;
- },
- methods: {
- // 格式化数组值
- formatArr(arr) {
- return arr.map(item => ({ id: item.id, name: item.name, contentType: item.contentType, path: item.path }));
- },
- before(file) {
- const maxSize = file.size / 1024 / 1024 < this.maxSize;
- if (!maxSize) {
- this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`);
- return false;
- }
- },
- success(res, file) {
- const os = this.onSuccess(res, file);
- if (os === false) return false;
-
- file.path = res.path;
- file.contentType = file.raw.type;
- },
- error(message) {
- message && this.$notify.error({ title: "上传文件未成功", message });
- },
- beforeRemove(file) {
- if (file.status == "success") {
- return new Promise((resolve, reject) => {
- this.$confirm(`是否移除 ${file.name}? 此操作不可逆!`, "提示", {
- type: "warning",
- confirmButtonText: "移除"
- }).then(() => {
- this.$API.common.minio.rm(XEUtils.pick(file, "id", "path")).then(res => {
- this.$emit("removeSuccess");
- resolve();
- }).catch(() => reject());
- }).catch(() => reject());
- });
- }
- },
- handleExceed() {
- this.$message.warning(`当前设置最多上传 ${this.limit} 个文件,请移除后上传!`);
- },
- handlePreview(uploadFile) {
- this.showViewer = true;
- nextTick(() => this.$refs.fileViewer.init(uploadFile));
- },
- request(param) {
- const data = new FormData();
- data.append(param.filename, param.file);
- XEUtils.objectEach(this.params, (value, key) => data.append(key, value));
- this.$API.common.minio.up(data, {
- onUploadProgress: e => {
- const percent = parseInt(((e.loaded / e.total) * 100) | 0, 10);
- param.onProgress({ percent });
- },
- transformRequest: [function (data, headers) {
- // 移除 Axios 可能自动设置的 Content-Type,让浏览器自动设置
- delete headers["Content-Type"];
- return data;
- }]
- }).then(res => {
- if (res.code == 200) param.onSuccess({ path: res.expands.file });
- else param.onError();
- }).catch(() => param.onError());
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .sc-upload-file:deep(.el-upload-dragger) {border-radius: 0;}
- .el-form-item.is-error .sc-upload-file:deep(.el-upload-dragger) {border-color: var(--el-color-danger);border-radius: 0;}
- .sc-upload-file {
- width: 100%;
- :deep(.el-upload-list__item) {transition: none !important;}
- .el-upload-hide-add {
- :deep(.el-upload) {display: none;}
- :deep(.el-upload-list) {
- margin-top: 0;
- .el-upload-list__item {
- &:last-child {margin-bottom: 0;}
- &:hover {background-color: transparent;}
- .el-upload-list__item-info {width: 100%;}
- .el-upload-list__item-status-label {display: none;}
- }
- }
- }
- .file-empty i {font-size: 28px;}
- .file-empty h4 {
- font-size: 13px;
- font-weight: normal;
- color: #8c939d;
-
- .el-text {font-size: inherit;}
- }
-
- .el-upload__tip {color: #999;}
- .el-upload__tip-required {
- position: relative;
- &::before {
- content: "*";
- margin-right: 4px;
- color: var(--el-color-danger);
- }
- }
- }
- </style>
|