目前参与的项目使用的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 返还一个完整的线上路径,如果你的项目返回的是一个完整的线上图片路径,可以自己把上面代码稍作修改使用