|
|
|
<template>
|
|
|
|
<view class="ch-image-uploader">
|
|
|
|
<ch-flex class="img-list" justify="center" items="center" @click.native="handleSelect">
|
|
|
|
<block v-for="item in imageList" key="item.path">
|
|
|
|
<view class="img-item" data-type="img">
|
|
|
|
<uni-icons type="clear" class="del-btn" size="50" v-if="showClose" data-type="delete" @click="delImg(item.path)"></uni-icons>
|
|
|
|
<image :src="item.path" mode="aspectFit"></image>
|
|
|
|
</view>
|
|
|
|
</block>
|
|
|
|
<view class="select-btn" data-type="btn" v-if="showBtn">
|
|
|
|
<uni-icons type="plusempty" data-type="add" size="70"/>
|
|
|
|
</view>
|
|
|
|
</ch-flex>
|
|
|
|
</view>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup name="ch-image-uploader">
|
|
|
|
import { ref, defineProps, reactive, toRefs, watchEffect, watch, computed, defineEmits, defineExpose } from 'vue';
|
|
|
|
|
|
|
|
const camera = uni.requireNativePlugin('yun-camerax-module');
|
|
|
|
const emit = defineEmits(['update:modelValue'])
|
|
|
|
defineExpose({
|
|
|
|
upload
|
|
|
|
})
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
limit: {
|
|
|
|
type: Number,
|
|
|
|
default: 8
|
|
|
|
},
|
|
|
|
extList: {
|
|
|
|
type: Array,
|
|
|
|
default: () => ['png', 'jepg', 'jpg']
|
|
|
|
},
|
|
|
|
sourceType: {
|
|
|
|
type: Array,
|
|
|
|
default: () => ['album', 'camera']
|
|
|
|
},
|
|
|
|
showClose: {
|
|
|
|
type: Boolean,
|
|
|
|
default: true
|
|
|
|
},
|
|
|
|
url: {
|
|
|
|
type: String,
|
|
|
|
default: ''
|
|
|
|
},
|
|
|
|
modelValue: {
|
|
|
|
type: Array,
|
|
|
|
default: () => []
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
const data = reactive({
|
|
|
|
imageList: []
|
|
|
|
})
|
|
|
|
|
|
|
|
const { imageList } = toRefs(data);
|
|
|
|
|
|
|
|
const showBtn = computed(() => {
|
|
|
|
return (props.limit <= 1 && imageList.value.length <= 0)
|
|
|
|
|| (props.limit > 1 && imageList.value.length <= props.limit - 1)
|
|
|
|
})
|
|
|
|
|
|
|
|
watchEffect(() => {
|
|
|
|
imageList.value = props.modelValue;
|
|
|
|
})
|
|
|
|
|
|
|
|
function handleSelect (e) {
|
|
|
|
const type = e.target.dataset.type || false;
|
|
|
|
|
|
|
|
if (!type || (type === 'img' && props.limit > 1)) return;
|
|
|
|
if (type === 'delete') {
|
|
|
|
delImg();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
camera.takePhoto({
|
|
|
|
// type: 2,
|
|
|
|
backColor: '',
|
|
|
|
enableTorch: false,
|
|
|
|
fullSrc: false
|
|
|
|
}, (res) => {
|
|
|
|
uni.getImageInfo({
|
|
|
|
src: res.file,
|
|
|
|
success: (info) => {
|
|
|
|
console.log(info)
|
|
|
|
const resList = [{
|
|
|
|
name: 'image' + (+new Date()),
|
|
|
|
extname: `image/${info.type}`,
|
|
|
|
path: info.path,
|
|
|
|
}];
|
|
|
|
if (props.limit > 1) {
|
|
|
|
const newImageList = filterImage(resList)
|
|
|
|
imageList.value = [...imageList.value, ...newImageList]
|
|
|
|
} else {
|
|
|
|
imageList.value = resList
|
|
|
|
}
|
|
|
|
emit('update:modelValue', imageList.value)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
// uni.chooseImage({
|
|
|
|
// count: props.limit,
|
|
|
|
// extension: props.extList,
|
|
|
|
// sourceType: props.sourceType,
|
|
|
|
// success: (res) => {
|
|
|
|
// console.log(res)
|
|
|
|
// if (props.limit > 1) {
|
|
|
|
// const newImageList = filterImage(res.tempFiles)
|
|
|
|
// imageList.value = [...imageList.value, ...newImageList]
|
|
|
|
// } else {
|
|
|
|
// imageList.value = res.tempFiles
|
|
|
|
// }
|
|
|
|
// emit('update:modelValue', imageList.value)
|
|
|
|
// },
|
|
|
|
// fail: (res) => {
|
|
|
|
// uni.showToast({
|
|
|
|
// icon: 'error',
|
|
|
|
// title: '选择失败'
|
|
|
|
// })
|
|
|
|
// }
|
|
|
|
// })
|
|
|
|
}
|
|
|
|
|
|
|
|
// 上传
|
|
|
|
function upload () {
|
|
|
|
const files = formatImageFiles(imageList.value);
|
|
|
|
console.log(files)
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
uni.uploadFile({
|
|
|
|
url: props.url,
|
|
|
|
files,
|
|
|
|
name: 'task-image',
|
|
|
|
success: (uploadFileRes) => {
|
|
|
|
uni.showToast({
|
|
|
|
title: '上传成功',
|
|
|
|
icon: 'success',
|
|
|
|
// success: () => {
|
|
|
|
// resolve(uploadFileRes)
|
|
|
|
// }
|
|
|
|
})
|
|
|
|
resolve(uploadFileRes)
|
|
|
|
},
|
|
|
|
fail: (error) => {
|
|
|
|
uni.showToast({
|
|
|
|
icon: 'fail',
|
|
|
|
title: '上传失败'
|
|
|
|
})
|
|
|
|
console.log('上传失败', error)
|
|
|
|
reject(error)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function delImg (path) {
|
|
|
|
imageList.value = imageList.value.filter(item => item.path !== path)
|
|
|
|
emit('update:modelValue', imageList.value)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 格式化image列表
|
|
|
|
function formatImageFiles (fileList) {
|
|
|
|
return imageList.value.map(item => {
|
|
|
|
return {
|
|
|
|
name: item.name || 'image',
|
|
|
|
// size: item.size,
|
|
|
|
uri: item.path,
|
|
|
|
// file: item
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 过滤重复的图片
|
|
|
|
function filterImage (images) {
|
|
|
|
return images.filter(item => {
|
|
|
|
const result = imageList.value.find(img => img.path === item.path );
|
|
|
|
return !result;
|
|
|
|
})
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
@import './ch-image-uploader.scss';
|
|
|
|
</style>
|