1.本次使用的是uview的u-upload上传组件
2.选择图库使用了wx.chooseImage API
原理: 使用disabled禁用掉自带的选择文件的方法, 然后使用插槽自定义一个上传文件的按钮和方法
完整代码
<template>
<view class="img-wrap">
<u-upload :accept="accept" :fileList="fileList"
@afterRead="afterRead" @delete="deletePic"
name="1" multiple
:maxCount="20" uploadIcon="plus"
disabled>
<view @click="WxChooseImage" class="slot-btn" hover-class="slot-btn__hover" hover-stay-time="150">
<u-icon name="photo" size="30" color="#c0c4cc"></u-icon>
<span class="slot-txt">添加图片</span>
</view>
</u-upload>
</view>
</template>
<script setup>
import {
computed,
getCurrentInstance,
ref
} from 'vue';
const {
proxy
} = getCurrentInstance()
const props = defineProps({
modelValue: {
type: Array,
default: () => ([])
},
accept: {
type: String,
default: 'image'
},
})
const emit = defineEmits(['update:modelValue'])
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 上传文件服务器地址
const ossUrl = ref(import.meta.env.VITE_APP_OSS_ADD); // 上传文件服务器地址
const fileList = computed({
get: () => {
let returnArr = []
if (props.modelValue.length == 0) return props.modelValue
props.modelValue.forEach(item => {
if (typeof item == 'string') {
returnArr.push({
url: ossUrl.value + item,
filePath: item,
status: 'success',
message: '',
})
} else {
returnArr.push({
...item,
filePath: item.url,
})
}
})
return returnArr
},
set: (val) => {
emit('update:modelValue', val)
}
})
// 删除图片
const deletePic = (event) => {
fileList.value = fileList.value.filter((item, index) => (index != event.index))
};
// 新增图片
const afterRead = async (event) => {
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
await uploadFileFn([].concat(event.file))
};
// 文件上传前-参数转化
const uploadFileFn = async (lists) => {
if (!lists || lists && !lists.length) return
let fileListLen = fileList.value.length;
for (let i = 0; i < lists.length; i++) {
const res = await uploadFilePromise(lists[i].url, lists[i]);
if (res.code == 200) {
fileList.value = [...fileList.value.map(item => item.filePath), res.data]
fileListLen++;
} else {
proxy.$modal.msgError(`上传失败`)
}
}
}
// 文件上传中-调用接口
const uploadFilePromise = (url, item) => {
const token = uni.getStorageSync('App-Token')
return new Promise((resolve, reject) => {
uni.uploadFile({
url: uploadFileUrl.value, // 仅为示例,非真实的接口地址
filePath: url,
name: 'file',
header: {
"Authorization": 'Bearer ' + token,
"Content-Type": "multipart/form-data"
},
formData: {
name: uploadFileUrl.value,
url: uploadFileUrl.value,
},
success: (res) => {
resolve(JSON.parse(res.data));
},
});
});
};
const WxChooseImage = () => {
var tempFilePaths;
wx.chooseImage({
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
// sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
sourceType: ['album'], // 指定相册
success: async function(res) {
// 返回选定照片的本地文件路径列表,tempFilePaths可以作为img标签的src属性显示图片
tempFilePaths = res.tempFiles.map(x => ({
...x,
url: x.path,
name: x.path,
}));
await uploadFileFn([].concat(tempFilePaths))
}
})
}
</script>
<style>
.img-wrap {
position: relative;
}
.img-wrap-mask {
position: absolute;
width: calc(100% - 90px);
height: 100%;
right: 0;
bottom: 0;
z-index: 999;
}
.slot-btn {
width: 80px;
height: 80px;
display: flex;
justify-content: center;
align-items: center;
background: rgb(244, 245, 246);
border-radius: 3px;
flex-direction: column;
}
.slot-btn__hover {
background-color: rgb(235, 236, 238);
}
.slot-txt {
font-size: 12px;
color: #999;
padding-top: 2px;
}
</style>