模板部分
<template>
<view class="annex-wrap ">
<view class="annex-box">
<view class="file-list flex-wrap">
<view class="file-list-item" v-for="(item, index) in dataList" :key="index">
<view class="file-list-item-inner">
<!--图片-->
<view class="" @tap.stop="toPreview(item)" style="position: relative;height: 100%;width: 100%;">
<image :src="item.type === 'image' ? item.url : `${item.url}?x-oss-process=video/snapshot,t_0,f_jpg`" class="upload-temp-img" mode="aspectFill"
/>
<!--视频-->
<!-- <view v-if="item.type === 'video'" class="file-area">
<view @tap.stop="toPreview(item)">
<view class="name">{{ item.fileName }}</view>
</view>
</view> -->
<u-icon name="play-circle-fill" color="#00000080" size="40" v-if="item.type === 'video'" style="position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);"></u-icon>
</view>
<view @tap.stop="removeFile(index)" class="close-btn">
<u-icon name="close" size="20"></u-icon>
</view>
</view>
</view>
<view class="file-list-item" @tap.stop="toShowChooseSheet" v-if="dataList.length<maxFilesNum">
<view class="file-list-item-inner upload-btn flex-center">
<view class="flex-center" style="flex-direction: column;">
<u-icon name="plus" color="#929AA5" size="36"></u-icon>
<view>{{ dataList.length }}/{{ maxFilesNum }}</view>
</view>
</view>
</view>
</view>
</view>
<u-action-sheet :actions="uploadTypeList" :show="showUploadTypeSheet" title="请选择上传文件类型"
@close='showUploadTypeSheet=false' :round="20" closeOnClickOverlay cancelText='取消'
@select="chooseUploadType"></u-action-sheet>
<u-popup :show="showPreview" mode="center" width="95%" @close="closePreview" v-if="play" class="pop" closeOnClickOverlay>
<view class="preview-content flex-center">
<image :src="previewItem.url" mode="widthFix" v-if="previewItem.type === 'image'" style="width: 80%;"></image>
<video :src="previewItem.url" id="preview-video" :autoplay="false" controls :show-progress="true" style=" height: 400px;width: 100vw;"
:show-center-play-btn="true" v-if="previewItem.type === 'video'"></video>
</view>
</u-popup>
</view>
</template>
js部分
<script>
import COS from 'cos-wx-sdk-v5'
import {
coskey
} from '@/api/common'
import {
qcloudTempSecreKey
} from '@/api/newApi/mine'
export default {
props: {
maxFilesNum: {
type: Number,
default: 1
},
play: {
type: Boolean,
default: false
},
videoCount:{
type: Number,
default: 1,
}
},
data() {
return {
showPreview: false,
previewItem: {
url: "",
type: "",
},
uploadTypeList: [{
name: "图片",
id: 1,
},
{
name: "视频",
id: 2,
},
],
dataList: [],
showUploadTypeSheet: false,
};
},
created() {
this.getCosFun()
},
methods: {
//获取腾讯云配置
getCosFun() {
const fun = () => this.isMall ? qcloudTempSecreKey() : coskey({
custom: {
auth: true
}
})
fun().then(res => {
this.$u.vuex('vuex_coskey', res)
const {
credentials,
expiredTime
} = res
this.$u.vuex('vuex_cosapi', new COS({
ForcePathStyle: true,
getAuthorization: (options, callback) => {
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
XCosSecurityToken: credentials.sessionToken,
ExpiredTime: expiredTime
});
}
}))
})
},
// 获取附件列表-查看或编辑时候用
getFileList() {
let data = {
id: id,
};
getFileList(data).then((res) => {
if (res.code === 200) {
this.dataList = res.result;
this.dataList.forEach((item) => {
item,
(item.tempFilePath = `域名/file/downloadFile?filePath=${item.filePath}`);
//tempFilePath:文件的临时地址,或者拼一个获取文件临时地址的接口,临时文件地址才可以预览
});
}
});
},
// 打开预览
toPreview(item) {
this.showPreview = true;
this.previewItem = {
url: item.url,
type: item.type,
};
},
// 关闭预览
closePreview() {
console.log(1111)
this.showPreview = false
this.previewItem = {
url: "",
fileType: "",
};
},
// 移除文件
removeFile(index) {
let that = this;
uni.showModal({
title: "提示",
content: "确定删除此项吗?",
success: function(res) {
if (res.confirm) {
that.dataList.splice(index, 1);
that.$emit('success', that.dataList)
}
},
});
},
// 上传图片
chooseImage() {
let that = this;
uni.chooseImage({
count: this.maxFilesNum - this.dataList.length, //默认100
sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有
sourceType: ["album", "camera"],
success: ({
tempFiles
}) => {
// 图片批量上传
tempFiles.map(({
path,
name,
type,
size
}) => {
this.uploadFilePromise({
url: path,
name,
type: 'image',
size
}).then(result => {
this.dataList.push(result)
this.$emit('success', this.dataList)
})
})
},
});
},
// 上传视频
chooseVideo() {
let that = this;
uni.chooseVideo({
sourceType: ["album", "camera"],
success: ({
tempFile,
duration,
tempFilePath,
size,
name
}) => {
console.log({
tempFile,
duration,
tempFilePath,
size,
name
})
this.uploadFilePromise({
url: tempFilePath,
name,
type: 'video',
size
}).then(result => {
console.log('result', result)
this.dataList.push(result)
this.$emit('success', this.dataList)
})
},
});
},
// 选择上传文件类型
chooseUploadType({
id
}) {
if (id === 1) {
// 图片
this.chooseImage();
} else if (id === 2) {
// 视频
if(this.dataList.filter(ele=>ele.type == 'video').length < this.videoCount) this.chooseVideo()
else uni.showToast({ title: `最多只能上传${this.videoCount}个视频`, icon: "none", });
}
},
// 打开文件上传选择类型弹窗
toShowChooseSheet() {
if (this.dataList.length >= this.maxFilesNum) {
uni.showToast({
title: `最多只能上传${this.maxFilesNum}个文件`,
icon: "none",
});
return false;
} else {
console.log(33333, '++++++++++', this.dataList.length, this.maxFilesNum)
this.showUploadTypeSheet = true;
}
},
uploadFilePromise({
url,
name,
type
}) {
return new Promise((resolve, reject) => {
if (url) {
var oldStr = url.match('[^/]+(?!.*/)')[0]
var newStr = this.vuex_coskey.tempUploadPath + oldStr
// #ifdef H5
newStr += name.slice(-4)
// #endif
this.vuex_cosapi.postObject({
Bucket: this.vuex_coskey.bucket,
Region: this.vuex_coskey.region,
Key: newStr,
FilePath: url
}, (err, data) => {
console.log('+++++++++++++++++++++++++++++++++++', newStr,data)
if (data) resolve({
url: `https://${data.Location}`,
temp: newStr,
type
})
else uni.showToast({
icon: 'none',
position: 'center',
title: '上传失败,请重新上传'
})
})
}
})
},
},
}
</script>
<style lang="scss" scoped>
.annex-wrap {
width: 100%;
.err-color {
color: #f00;
}
.border-dashed {
margin: 24rpx 0;
border: 1px dashed #eff0f2;
}
.icon-arrow {
margin-left: 12rpx;
}
.annex-box {
background: #ffffff;
border-radius: 10px;
// margin-top: 24rpx;
color: #475569;
// margin-top: 24rpx;
// padding: 24rpx 34rpx;
position: relative;
overflow: hidden;
position: relative;
line-height: 1.6;
.lab {
font-size: 28rpx;
color: #475569;
padding: 10rpx;
}
&.select-box {
padding: 0 34rpx;
.u-form-item {
color: #475569;
padding: 16rpx 0;
}
}
.mt-10 {
margin-top: 10rpx;
}
.top {
position: relative;
.left {
margin-right: 150rpx;
}
.title {
font-size: 34rpx;
color: #303133;
font-weight: 550;
}
.desc {
color: #929aa5;
font-size: 24rpx;
}
.user-tag {
margin-left: 24rpx;
background-color: #f4f9ff;
color: #1890ff;
font-size: 22rpx;
display: inline-block;
border-radius: 6rpx;
padding: 4rpx 20rpx;
.text {
margin-left: 10rpx;
}
}
.right-icon {
position: absolute;
right: 0rpx;
top: -20rpx;
.icon {
width: 170rpx;
height: 170rpx;
}
}
.result-items {
overflow: hidden;
.result-item {
width: 33%;
float: left;
padding: 12rpx 0;
text-align: center;
position: relative;
.red {
color: #ff7676;
}
}
.result-item:after {
height: 60rpx;
width: 1px;
border-left: 1px solid #eff0f2;
content: "";
display: inline-block;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.result-item:nth-child(3n):after {
display: none;
}
.name {
color: #929aa5;
font-size: 24rpx;
}
.num {
color: #303133;
font-size: 30rpx;
}
}
}
}
.file-list-item {
width: 172rpx;
padding: 20rpx;
height: 172rpx;
margin-right: 10rpx;
position: relative;
display: inline-block;
margin-bottom: 30rpx;
overflow: hidden;
&-inner {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
display: flex;
.upload-temp-img {
max-width: 100%;
max-height: 100%;
border-radius: 10rpx;
}
}
.upload-btn {
// border: 2px dashed #e2e8f0;
border: 2rpx solid #e2e8f0;
border-radius: 10rpx;
background: #fff;
text-align: center;
font-size: 26rpx;
color: #929aa5;
cursor: pointer;
}
&:nth-child(3n) {
margin-right: 0;
}
.file-area {
position: relative;
display: flex;
align-items: center;
justify-content: center;
background: rgba(77, 151, 255, 0.05);
text-align: center;
width: 100%;
border-radius: 10rpx;
.name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 160rpx;
}
.icon-file {
width: 60rpx;
height: 74rpx;
}
video {
width: 100%;
height: 100%;
}
}
.close-btn {
position: absolute;
right: 0;
top: 0;
background: rgba(71, 85, 105, 0.3);
border-radius: 0px 10rpx 0px 10rpx;
display: inline-block;
width: 40rpx;
height: 40rpx;
cursor: pointer;
text-align: center;
color: #fff;
z-index: 9;
}
}
.file-list-item:nth-child(3n){
margin-right: 0;
}
.file-list-item:last-child:nth-child(3n-1){
margin-right: 240rpx;
}
}
.preview-content {
width: 100vw;
// height: 90vh;
text-align: center;
display: flex;
align-items: center;
video {
width: 100%;
height: 100%;
}
}
/deep/ .pop {
.u-popup__content {
background-color: unset;
}
}
.file-list{
justify-content: space-between;
}
</style>
使用
<template>
<view class="containerbox">
<my-upload :maxFilesNum='6' width="65.2" height="65.2" @success='uploadSuccess' :videoCount="3"></my-upload>
</view>
</template>
<script>
import myUpload from '@/pages/newPages/mall/music/components/my-upload.vue'
import form from './form'
export default {
components: { myUpload },
methods: {
uploadSuccess(e){
console.log(e)
}
}
}
</script>
效果展示