You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
4.0 KiB
Vue

8 months ago
<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">
8 months ago
<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>
8 months ago
<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');
8 months ago
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)
8 months ago
}
})
8 months ago
})
// 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: '选择失败'
// })
// }
// })
8 months ago
}
// 上传
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)
// }
8 months ago
})
resolve(uploadFileRes)
},
fail: (error) => {
uni.showToast({
icon: 'fail',
title: '上传失败'
})
console.log('上传失败', error)
reject(error)
8 months ago
}
})
})
}
function delImg (path) {
imageList.value = imageList.value.filter(item => item.path !== path)
emit('update:modelValue', imageList.value)
8 months ago
}
// 格式化image列表
function formatImageFiles (fileList) {
return imageList.value.map(item => {
return {
name: item.name || 'image',
// size: item.size,
8 months ago
uri: item.path,
// file: item
8 months ago
}
})
}
// 过滤重复的图片
function filterImage (images) {
return images.filter(item => {
const result = imageList.value.find(img => img.path === item.path );
8 months ago
return !result;
})
}
</script>
<style lang="scss" scoped>
@import './ch-image-uploader.scss';
</style>