123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- <template>
- <div class="mb-3 color-666">共<strong class="color-primary"> {{ srcList.length }} </strong>张,还能上传 <strong class="color-primary">{{ (Number(limit) - Number(srcList.length)) }}</strong> 张</div>
- <div class="d-flex flex-wrap">
- <div style="position: relative;" v-for="val in srcList" :key="val" class="mr-3 mb-3">
- <v-icon color="error" class="close" @click="handleClose(val)">mdi-close-circle</v-icon>
- <v-img :src="val" width="100" height="100" rounded class="imgBox"></v-img>
- </div>
- <div v-if="srcList.length < limit" class="upload d-flex align-center justify-center flex-column" @click="openFileInput">
- <v-icon color="#ccc" :size="tips ? 30 : 50">mdi-plus</v-icon>
- <div class="font-size-12 color-999">{{ tips }}</div>
- <input
- type="file"
- ref="fileInput"
- accept="image/*"
- style="display: none;"
- @change="handleUploadFile"
- />
- </div>
- </div>
- </template>
- <script setup>
- // 图片组上传
- defineOptions({ name: 'upload-imgs'})
- import { ref, watch } from 'vue'
- import { uploadFile } from '@/api/common'
- import { useI18n } from '@/hooks/web/useI18n'
- import Snackbar from '@/plugins/snackbar'
- const props = defineProps({
- modelValue: Array,
- tips: {
- type: String,
- default: '上传图片'
- },
- showSnackbar: {
- type: Boolean,
- default: false
- },
- limit: {
- type: [Number, String],
- default: 9
- }
- })
- const { t } = useI18n()
- const srcList = ref([])
- watch(() => props.modelValue, (newVal) => {
- srcList.value = newVal
- }, { immediate: true }, { deep: true })
- // 选择文件
- const fileInput = ref()
- const clicked = ref(false)
- const openFileInput = () => {
- if (srcList.value.length >= props.limit) return Snackbar.warning(`最多可上传${props.limit}张图片`)
- if (clicked.value) return
- clicked.value = true
- fileInput.value.click()
- clicked.value = false
- }
- // 文件上传
- const accept = ['jpg', 'png', 'webp', 'jpeg']
- const handleUploadFile = async (e) => {
- const file = e.target.files[0]
- const size = file.size
- if (size / (1024*1024) > 20) {
- Snackbar.warning(t('common.fileSizeExceed'))
- return
- }
- const arr = file.name.split('.')
- const fileType = arr?.length ? arr[arr.length-1] : ''
- if (!accept.includes(fileType)) return Snackbar.warning('请上传图片格式')
- const formData = new FormData()
- formData.append('file', file)
- formData.append('path', 'img')
- const { data } = await uploadFile(formData)
- if (!data) return Snackbar.error('上传失败')
- if (props.showSnackbar) Snackbar.success(t('common.uploadSucMsg'))
- srcList.value.push(data)
- }
- const handleClose = (src) => {
- const index = srcList.value.indexOf(src)
- if (index === -1) return
- srcList.value.splice(index, 1)
- }
- </script>
- <style scoped lang="scss">
- .upload {
- width: 100px;
- height: 100px;
- border: 1px solid #ccc;
- border-radius: 4px;
- cursor: pointer;
- }
- .imgBox {
- position: relative;
- border: 1px solid #ccc;
- border-radius: 4px;
- padding: 5px;
- }
- .close {
- position: absolute;
- top: -10px;
- right: -10px;
- cursor: pointer;
- z-index: 9;
- }
- </style>
|