1.效果(解决循环组件赋值问题)
废话不多说直接上代码
2.下载七牛云依赖
npm install qiniu-js
# 或者使用 yarn
yarn add qiniu-js
3.在vue组件中引入
import * as qiniu from 'qiniu-js'
4.在components文件夹下创建UploadImg1/uploadImg.vue组件
<template>
<div
:style="{
display: 'grid',
'justify-content': 'space-between',
'grid-template-columns': `repeat(auto-fill,minmax(${w},1fr))`
}"
class="imgBoxSty"
>
<div
class="img-list-item common mb_10"
:style="{ width: w }"
v-for="(item, index) in fileList"
:key="index"
>
<!-- <video
v-if="!matchType(item.name)"
:style="{ width: w, height: h, margin: '0 9px' }"
controls="controls"
:src="item.url"
>
您的浏览器不支持视频播放
</video> -->
<el-image
@mouseover="srcList = [item]"
:preview-src-list="srcList"
:style="{ width: w, height: h, margin: '0 9px' }"
:src="item"
fit="cover"
></el-image>
<i class="del-img" @click="forkImage(index)" v-if="isShowImg == true"></i>
</div>
<div v-if="maxlength < limit" @click="change">
<el-upload
:multiple="imgmultiple"
action=""
:data="dataObj"
:show-file-list="false"
:auto-upload="true"
:on-remove="handleRemove"
:on-success="handleUploadSuccess"
:before-upload="beforeUpload"
:on-progress="uploadVideoProcess"
:http-request="FileForQiNiu"
>
<span
class="warpss"
:style="{ width: w, height: h, lineHeight: h }"
v-if="isShowImg == true"
>
<i
class="el-icon-plus"
:style="{
color: '#8C939D',
fontSize: '18px',
fontWeight: 'bold',
padding: paddings
}"
></i>
</span>
</el-upload>
</div>
</div>
</template>
<script>
import { GetqiniuToken } from "@/api/tools/qiniu";//这个是获取七牛云token接口,由后端提供
import * as qiniu from "qiniu-js";//引入七牛云依赖
// 或者按需导入(推荐)
export default {
name: "uploadImg",
props: {
//是否多选
imgmultiple: {
type: Boolean,
default: false
},
//是否需要上传图片(false:需要,true:不需要,只能查看图片不能做任何操作)
isShowImg: {
type: Boolean,
default: false
},
//个数显示
limit: {
type: Number,
default: 5
},
maxlength: {
type: Number
},
value: Array,
//最大上传图片数量
maxCount: {
type: Number,
default: 5
},
//宽度
w: {
type: String
// default:'100px'
},
//高度
h: {
type: String
// default:'100px'
},
paddings: {
type: String
},
// 上传类型,1图片,2视频,3图片或视频
uploadType: {
type: Number,
default: 1
}
},
data: function() {
return {
flag: true,
srcList: [],
videoFlag: false,
isShow: true,
videoUploadPercent: 0,
count: 5,
videis: false,
dataObj: {
policy: "",
signature: "",
key: "",
ossaccessKeyId: "",
dir: "",
host: ""
},
dialogVisible: false,
dialogImageUrl: []
};
},
computed: {
fileList() {
return this.value;
}
},
mounted() {
if (this.fileList.length < this.limit) {
this.isShow = true;
} else {
this.isShow = false;
}
},
methods: {
//图片视频匹配
matchType(name) {
// console.log("图片视频匹配");
//后缀获取
let suffic = "";
//获取类型结果
let result = "";
try {
let fileArr = name.split(".");
suffic = fileArr[fileArr.length - 1];
// console.log('suffic',suffic);
} catch (error) {
suffic = "";
}
//图片格式
var imgList = ["png", "jpg", "jpeg", "bmp", "gif"];
//进行图片匹配
result = imgList.some(item => {
return item === suffic;
});
// console.log('结果',result);
if (result) {
result = "image";
// console.log('结果',result);
return result;
}
},
//删除视频/图片
forkImage(index) {
console.log("删除视频/图片", this.fileList, "索引", index);
// var data = this.fileList.splice(index, 1);
// this.$emit("delFile", this.fileList);
// if (this.fileList.length < this.limit) {
// this.isShow = true;
// } else {
// this.isShow = false;
// }
// 创建新数组而不是修改原数组
// 创建新数组(不要直接修改props)
const newFileList = [...this.value];
newFileList.splice(index, 1);
// 只使用input事件更新数据
this.$emit("input", newFileList);
// 更新显示状态
this.isShow = newFileList.length < this.limit;
},
change() {
// console.log("change函数", this.fileList);
if (this.fileList.length < this.limit) {
this.isShow = true;
} else {
this.isShow = false;
}
},
getUUID() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {
return (c === "x"
? (Math.random() * 16) | 0
: "r&0x3" | "0x8"
).toString(16);
});
},
emitInput(fileList) {
// console.log("emitInput韩束", fileList);
if (!this.flag) {
return false;
}
let value = [];
for (let i = 0; i < fileList.length; i++) {
value.push(fileList[i]);
}
this.$emit("input", value);
},
handleRemove(file, fileList) {
if (this.flag) {
// console.log("handleRemove函数", file, fileList);
this.emitInput(fileList);
}
},
//上传图片/视频成功后的操作
handleUploadSuccess(res, file) {
console.log("handleUploadSuccess函数上传图片/视频成功");
const url =
this.dataObj.host +
"/" +
this.dataObj.key.replace("${filename}", file.name);
const newFileList = [...this.value, url];
this.$emit("input", newFileList);
if (newFileList.length >= this.limit) {
this.$message({
message: `最多只能上传${this.limit}个文件`,
type: "warning",
duration: 1000
});
}
},
//进度条
uploadVideoProcess(event, file, fileList) {
this.videoUploadPercent = Math.floor(event.percent);
},
beforeUpload(file) {
this.flag = true;
// 上传限制视频
//let vedioArr = [
// "video/mp4",
// "video/m4v",
// "video/ogg",
// "video/flv",
//"video/avi",
// "video/wmv",
// "video/rmvb"
// ];
// 上传限制图片
let imgArr = ["image/jpeg", "image/PNG", "image/gif", "image/png"];
// 既可上传图片、视频
let bothArr = [
"video/mp4",
"video/m4v",
"video/ogg",
"video/flv",
"video/avi",
"video/wmv",
"video/rmvb",
"image/jpeg",
"image/PNG",
"image/gif",
"image/png"
];
//视频/图片校验
if (
[
// "video/mp4",
// "video/m4v",
// "video/ogg",
// "video/flv",
// "video/avi",
// "video/wmv",
// "video/rmvb",
"image/jpeg",
"image/PNG",
"image/gif",
"image/png"
].indexOf(file.type) == -1
) {
this.$message.error("请上传正确的视频/图片格式");
this.flag = false;
// return false;
}
console.log("canshu", this.flag);
return this.flag;
},
// 获取七牛云token
FileForQiNiu(param) {
GetqiniuToken().then(response => {
console.log("七牛云上传", response);
const key =
"七牛云创建的文件夹名称/" +
this.formatTimestamp(new Date().getTime()) +
"_" +
param.file.size +
param.file.name;
const observable = qiniu.upload(
param.file,
key,
response,
{},
{ useCdnDomain: true }
);
observable.subscribe(
res => {
param.onProgress({ percent: res.total.percent });
},
err => console.error(err),
res => {
const newFileList = [
...this.value,
"https://域名/" + res.key
];
this.$emit("input", newFileList);
}
);
});
},
formatTimestamp(timestamp) {
// 如果 timestamp 是字符串,尝试转换为数字
const time = new Date(
typeof timestamp === "string" ? parseInt(timestamp) : timestamp
);
// 获取各个时间部分
const year = time.getFullYear();
const month = String(time.getMonth() + 1).padStart(2, "0"); // 月份从0开始,所以要+1
const day = String(time.getDate()).padStart(2, "0");
const hours = String(time.getHours()).padStart(2, "0");
const minutes = String(time.getMinutes()).padStart(2, "0");
const seconds = String(time.getSeconds()).padStart(2, "0");
// 拼接成格式化的字符串
return `${year}_${month}_${day}${hours}${minutes}${seconds}`;
}
}
};
</script>
<style lang="scss" scoped>
.warpss {
display: inline-block;
border: 1px dashed #dee5ed;
margin-left: 13px;
}
::v-deep.el-upload-list {
display: none;
}
.el-upload-video {
width: 149px;
height: 149px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.el-upload-video-i {
font-size: 20px;
font-weight: bold;
padding-top: 43px;
color: #8c939d;
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
}
//视频
.img-list-item {
position: relative;
margin: auto;
}
.img-list-item i.del-img {
width: 20px;
height: 20px;
display: inline-block;
background: rgba(0, 0, 0, 0.6);
background-image: url(../../assets/images/close.png);//关闭按钮图标
background-size: 18px;
background-repeat: no-repeat;
background-position: 50%;
position: absolute;
top: 0;
right: -7px;
}
.imgBoxSty {
// display: flex;
// flex-wrap: wrap;
// justify-content: flex-start;
width: 100% !important;
// border: 1px solid;
// grid-gap: 40px 30px;
}
</style>
5.父组件引用
<template>
<div>
<div v-for="(item, index) in form.resources" :key="index">
<upload-img
@input="handleImageChange(index, $event)"
:isShowImg="isShowImg"
:maxlength="item.imageArr.length"
:limit="1"
w="100px"
h="100px"
v-model="item.imageArr"
></upload-img>
</div></div>
</<template>
import uploadImg from "@/components/UploadImg1/uploadImg.vue";
export default {
components: { uploadImg },
data() {
return {
form:{
isShowImg:true,
resources:[{
img: "",
activityName: "",
jumpType: "", //类型
jumpLink: "", //商品/科普/运营/自我诊疗/外部链接参数
path: "", //路径
imageArr: [] //拿到的图片
}]
}
}
},
methods: {
handleImageChange(index, newValue) {
// this.form.resources[index].imageArr = [newValue];
// this.form.resources[index].img = newValue[0];
// 使用Vue.set确保响应式更新
this.$set(this.form.resources, index, {
...this.form.resources[index],
imageArr: newValue,
img: newValue[0] || "" // 保持同步
});
this.$forceUpdate();
console.log("获取图片数据", index, "图片", newValue, this.form.resources);
},
}
}