目前參與的項目使用的UI庫是阿裡的Ant Design of Vue
由于項目中多處要用到上傳元件,又不想每次照着官網的上傳元件複制多次上傳、删除、檢視圖檔事件,因為可能需要多次修改,是以自己進行了二次封裝,将上傳單張(上傳頭像需求)和多張弄到一起
<template>
<div>
<a-upload :action="uploadAction"
list-type="picture-card"
:disabled="disabled"
:headers="headers"
:file-list="fileList"
:beforeUpload="beforeUpload"
:data="{biz:bizPath}"
:multiple="isMultiple"
:showUploadList="isMultiple"
@preview="handlePreview"
@change="handleChange">
<img v-if="!isMultiple && picUrl"
:src="getAvatarView()"
style="height:104px;max-width:300px" />
<div v-else-if="(isMultiple && fileList.length < limit && !disabled) || (!isMultiple && !picUrl)">
<a-icon type="plus" />
<div class="ant-upload-text">{{text}}</div>
</div>
</a-upload>
<a-modal :visible="previewVisible"
:footer="null"
@cancel="previewHandleCancel">
<img alt="example"
style="width: 100%"
:src="previewImage" />
</a-modal>
</div>
</template>
<script>
import Vue from 'vue'
import { ACCESS_TOKEN } from "@/store/mutation-types"
// import { getFileAccessHttpUrl } from '@/api/manage'
const getFileAccessHttpUrl = (avatar, subStr) => {
if (!subStr) subStr = 'http'
if (avatar && avatar.startsWith(subStr)) {
return avatar;
} else {
if (avatar && avatar.length > 0 && avatar.indexOf('[') == -1) {
return window._CONFIG['staticDomainURL'] + "/" + avatar;
}
}
}
const uidGenerator = () => {
return '-' + parseInt(Math.random() * 10000 + 1, 10);
}
const getFileName = (path) => {
if (path.lastIndexOf("\\") >= 0) {
let reg = new RegExp("\\\\", "g");
path = path.replace(reg, "/");
}
return path.substring(path.lastIndexOf("/") + 1);
}
export default {
name: 'LImageUpload',
data() {
return {
uploadAction: window._CONFIG['domianURL'] + "/sys/common/upload",
headers: {},
fileList: [],
previewImage: "",
previewVisible: false,
picUrl: false
}
},
props: {
text: {
type: String,
default: '上傳'
},
// 父元件傳進來的已有的圖檔資料
value: {
type: [String, Array],
required: false
},
// 後端要求攜帶的其他參數
bizPath: {
type: String,
required: false,
default: "temp"
},
// 隻能檢視不可上傳和删除時開啟該屬性
disabled: {
type: Boolean,
required: false,
default: false
},
// 是否多圖
isMultiple: {
type: Boolean,
required: false,
default: false
},
// 多圖情況下限制圖檔張數
limit: {
type: Number,
required: false,
default: 9
}
},
watch: {
value: {
handler(val) {
if (val instanceof Array) {
this.initFileList(val.join(','))
} else {
this.initFileList(val)
}
},
deep: true,
immediate: true
}
},
created() {
const token = Vue.ls.get(ACCESS_TOKEN);
this.headers = { "X-Access-Token": token }
},
methods: {
// 顯示已有圖檔
initFileList(paths) {
console.log('initFileList', paths)
if (!paths || paths.length == 0) {
this.fileList = [];
return;
}
this.picUrl = true;
let fileList = [];
let arr = paths.split(",")
for (var a = 0; a < arr.length; a++) {
let url = getFileAccessHttpUrl(arr[a]);
fileList.push({
uid: uidGenerator(),
name: getFileName(arr[a]),
status: 'done',
url: url,
response: {
status: "history",
message: arr[a]
}
})
}
this.fileList = fileList
console.log('fileList', this.fileList)
},
beforeUpload: function (file) {
var fileType = file.type;
if (fileType.indexOf('image') < 0) {
this.$message.warning('請上傳圖檔');
return false;
}
},
// 關閉彈框
previewHandleCancel() {
this.previewVisible = false;
},
// 預覽
handlePreview(file) {
this.previewImage = file.url || file.preview;
this.previewVisible = true;
},
// 上傳
handleChange(info) {
console.log('info----handleChange', info)
this.picUrl = false;
let fileList = info.fileList
if (info.file.status === 'done') {
if (info.file.response.success) {
this.picUrl = true;
fileList = fileList.map((file) => {
if (file.response) {
file.url = getFileAccessHttpUrl(file.response.message);
}
return file;
});
}
//this.$message.success(`${info.file.name} 上傳成功!`);
} else if (info.file.status === 'error') {
this.$message.error(`${info.file.name} 上傳失敗.`);
} else if (info.file.status === 'removed') {
this.handleDelete(info.file)
}
this.fileList = fileList
if (info.file.status === 'done' || info.file.status === 'removed') {
this.handlePathChange()
}
},
// 回傳父元件
handlePathChange() {
let uploadFiles = this.fileList
let path = ''
if (!uploadFiles || uploadFiles.length == 0) {
path = ''
}
let arr = [];
if (!this.isMultiple) {
arr.push(uploadFiles[uploadFiles.length - 1].response.message)
} else {
for (var a = 0; a < uploadFiles.length; a++) {
arr.push(uploadFiles[a].response.message)
}
}
if (arr.length > 0) {
path = arr.join(",")
}
this.$emit('change', path);
},
// 删除
handleDelete(file) {
},
// 單圖上傳顯示最新的一張
getAvatarView() {
if (this.fileList.length > 0) {
let url = this.fileList[this.fileList.length - 1].url
return getFileAccessHttpUrl(url)
}
},
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
項目和後端互動,圖檔的位址不是完整的線上路徑,需要通過getFileAccessHttpUrl 返還一個完整的線上路徑,如果你的項目傳回的是一個完整的線上圖檔路徑,可以自己把上面代碼稍作修改使用