123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- <template>
- <div v-if="!src" 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 v-else class="" style="position: relative;">
- <v-icon color="error" class="close" @click="handleClose">mdi-close-circle</v-icon>
- <v-img :src="src" width="100" height="100" rounded class="imgBox" :class="{'cursor-pointer': showCursor}" @click="emit('imgClick')"></v-img>
- <div @click="emit('imgClick')" class="color-primary cursor-pointer text-center text-decoration-underline">点击预览</div>
- </div>
- </template>
- <script setup>
- // 图片上传
- defineOptions({ name: 'upload-img'})
- import { ref, watch } from 'vue'
- import { uploadFile } from '@/api/common'
- import { useI18n } from '@/hooks/web/useI18n'
- import Snackbar from '@/plugins/snackbar'
- const emit = defineEmits(['success', 'delete', 'imgClick'])
- const props = defineProps({
- value: String,
- tips: String,
- showCursor: Boolean,
- showSnackbar: {
- type: Boolean,
- default: true
- }
- })
- const { t } = useI18n()
- const src = ref('')
- watch(() => props.value, (newVal) => {
- src.value = newVal
- }, { immediate: true }, { deep: true })
- // 选择文件
- const fileInput = ref()
- const clicked = ref(false)
- const openFileInput = () => {
- 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) > 10) {
- Snackbar.warning(t('common.fileSizeExceed'))
- return
- }
- const fileType = file.name.split('.')[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('上传失败')
- src.value = data
- if (props.showSnackbar) Snackbar.success(t('common.uploadSucMsg'))
- emit('success', data)
- }
- const handleClose = () => {
- src.value = ''
- emit('delete')
- }
- </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>
|