Files
boursecu_admin/src/components/UploadPic.vue
T
2026-07-16 17:55:08 +03:30

141 lines
3.6 KiB
Vue

<template>
<div style="overflow: hidden">
<a-upload
class="relative fix-capture"
name="file"
:show-upload-list="false"
list-type="picture-card"
:action="url"
:headers="fileHeader"
accept="image/*"
:before-upload="beforeUpload"
:custom-request="customRequest"
@change="handelChange"
>
<div
@click="deleteAvatar"
style="position: absolute; bottom: 10px; left: 0; z-index: 10"
>
<BaseIcon icon="vuesax-linear:trash" class="text-red-600 cursor-pointer" />
</div>
<div class="relative" v-if="imageUrl">
<img
:src="imageUrl"
alt="avatar"
style="min-width: 104px; max-height: 104px; object-fit: cover; display: inline"
/>
</div>
<div v-if="!imageUrl" class="flex flex-col items-center">
<span>
<slot name="TitlePic">افزودن عکس</slot>
</span>
<div v-if="loading" class="flex gap-4 items-center mt-2">
<loading-outlined></loading-outlined>
<span>{{ percent }} %</span>
</div>
</div>
</a-upload>
</div>
</template>
<script lang="ts" setup>
import { uploadURL } from '@root/config'
import { onMounted, ref, watch, computed } from 'vue'
import { LoadingOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import type { UploadProps } from 'ant-design-vue'
import { getToken } from '@/utils'
import { fixFileCapture } from '@/utils/fixFileCapture'
import {
createImageBeforeUpload,
createImageCustomRequest
} from '@/utils/prepareImageForUpload'
import { normalizeUploadFileResponse, toAbsoluteFileUrl } from '@/utils/file'
const loading = ref<boolean>(false)
const percent = ref<number>(0)
const url = ref<string | undefined>(`${uploadURL}`)
const fileHeader = computed(() => ({
Authorization: `Bearer ${getToken()}`
}))
interface Props {
imageUrl?: string
compressed?: boolean
}
const props = withDefaults(defineProps<Props>(), {
compressed: false
})
const imageUrl = ref('')
const emit = defineEmits<{
(e: 'remove'): void
(e: 'upload', file: any): void
(e: 'startUpload'): void
(e: 'errorUpload'): void
}>()
const beforeUpload: UploadProps['beforeUpload'] = createImageBeforeUpload((msg) =>
message.error(msg)
)
const customRequest: UploadProps['customRequest'] = createImageCustomRequest({
action: () => url.value || uploadURL,
getHeaders: () => fileHeader.value,
messageError: (msg) => message.error(msg),
onStarted: () => {
loading.value = true
percent.value = 0
emit('startUpload')
},
onUploaded: (body) => {
const fileResource = normalizeUploadFileResponse(body)
const record = body && typeof body === 'object' ? (body as Record<string, any>) : undefined
imageUrl.value =
fileResource?.full_src ||
toAbsoluteFileUrl(record?.full_src || record?.src) ||
''
loading.value = false
percent.value = 100
emit('upload', body)
message.success('فایل با موفقیت آپلود شد')
},
onFailed: () => {
loading.value = false
emit('errorUpload')
}
})
function handelChange({ file }) {
if (Object.hasOwn(file, 'percent') && file.percent != null) {
percent.value = Math.floor(file.percent)
}
fixFileCapture()
if (file.status === 'uploading') {
loading.value = true
}
}
onMounted(() => {
fixFileCapture()
})
function deleteAvatar(e) {
imageUrl.value = null
emit('remove')
e.stopPropagation()
}
watch(
() => props.imageUrl,
() => {
imageUrl.value = props.imageUrl
},
{ immediate: true }
)
</script>
<style></style>