1.本次使用的是uview的u-upload上傳組件
2.選擇圖庫使用了wx.chooseImage API
原理: 使用disabled禁用掉自帶的選擇文件的方法, 然后使用插槽自定義一個上傳文件的按鈕和方法
image.png
image.png
image.png
完整代碼
<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>