2026-01-24 17:45:54 +03:30
|
|
|
<template>
|
|
|
|
|
<div :class="[prefixCls]">
|
|
|
|
|
<div class="border border-solid border-blue-600 bg-gray-50 w-full rounded-md p-2">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<AUpload
|
2026-06-26 18:29:24 +03:30
|
|
|
class="fix-capture"
|
|
|
|
|
accept="image/*"
|
2026-05-12 17:36:54 +03:30
|
|
|
v-model:file-list="fileList"
|
|
|
|
|
name="file"
|
|
|
|
|
list-type="picture-card"
|
|
|
|
|
:show-upload-list="false"
|
|
|
|
|
:action="uploadURL"
|
|
|
|
|
:headers="fileHeader"
|
|
|
|
|
:showUploadList="true"
|
|
|
|
|
:before-upload="beforeUpload"
|
|
|
|
|
@change="handleChange"
|
2026-01-24 17:45:54 +03:30
|
|
|
>
|
|
|
|
|
<div>
|
2026-05-12 17:36:54 +03:30
|
|
|
<BaseIcon icon="vuesax-linear:add" color="#6B7280"/>
|
2026-01-24 17:45:54 +03:30
|
|
|
<div class="text-gray-500 text-center text-xs font-normal">بارگذاری فایل</div>
|
|
|
|
|
</div>
|
|
|
|
|
</AUpload>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2026-05-12 17:36:54 +03:30
|
|
|
import type {UploadChangeParam, UploadProps} from 'ant-design-vue'
|
2026-07-16 17:30:06 +03:30
|
|
|
import {message} from 'ant-design-vue'
|
2026-05-12 17:36:54 +03:30
|
|
|
import {uploadURL} from '@root/config'
|
|
|
|
|
import {getToken} from '@/utils'
|
2026-06-26 18:29:24 +03:30
|
|
|
import {fixFileCapture} from '@/utils/fixFileCapture'
|
2026-07-06 17:06:25 +03:30
|
|
|
import {normalizeUploadFileResponse} from '@/utils/file'
|
2026-07-16 17:30:06 +03:30
|
|
|
import {createWebpBeforeUpload} from '@/utils/prepareImageForUpload'
|
2026-05-12 17:36:54 +03:30
|
|
|
import {usePrefix} from '@core/composable/usePrefix'
|
2026-07-06 17:06:25 +03:30
|
|
|
import {computed, onMounted, ref} from 'vue'
|
2026-01-24 17:45:54 +03:30
|
|
|
|
2026-05-12 17:36:54 +03:30
|
|
|
const {prefixCls} = usePrefix('product-image-uploader')
|
2026-01-24 17:45:54 +03:30
|
|
|
const loading = ref<boolean>(false)
|
|
|
|
|
|
|
|
|
|
const fileHeader = {
|
|
|
|
|
Authorization: `Bearer ${getToken()}`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface Props {
|
|
|
|
|
fileList?: Array<FileList>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const props = withDefaults(defineProps<Props>(), {})
|
|
|
|
|
|
|
|
|
|
const emits = defineEmits(['update:fileList', 'ok', 'delete'])
|
|
|
|
|
|
|
|
|
|
const fileList = computed({
|
|
|
|
|
get() {
|
|
|
|
|
return props.fileList || ([] as Array<FileList>)
|
|
|
|
|
},
|
|
|
|
|
set(value) {
|
|
|
|
|
emits('update:fileList', value)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2026-07-16 17:30:06 +03:30
|
|
|
const beforeUpload: UploadProps['beforeUpload'] = createWebpBeforeUpload((msg) =>
|
|
|
|
|
message.error(msg)
|
|
|
|
|
)
|
2026-01-24 17:45:54 +03:30
|
|
|
|
|
|
|
|
function handleChange(info: UploadChangeParam) {
|
2026-06-26 18:29:24 +03:30
|
|
|
fixFileCapture()
|
|
|
|
|
|
2026-01-24 17:45:54 +03:30
|
|
|
if (info.file.status === 'uploading') {
|
|
|
|
|
loading.value = true
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info.file.status === 'error') {
|
|
|
|
|
loading.value = false
|
|
|
|
|
message.error('خطا در بارگذاری')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info.file.status === 'done') {
|
|
|
|
|
loading.value = false
|
2026-07-06 17:06:25 +03:30
|
|
|
const fileResource = normalizeUploadFileResponse(info.file.response)
|
|
|
|
|
|
|
|
|
|
if (!fileResource?.id || !fileResource.full_src) {
|
|
|
|
|
fileList.value = fileList.value.filter((item) => item.uid !== info.file.uid)
|
|
|
|
|
message.error('خطا در ساخت آدرس تصویر')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fileList.value = fileList.value.map((item) =>
|
|
|
|
|
item.uid === info.file.uid
|
|
|
|
|
? {
|
|
|
|
|
...item,
|
|
|
|
|
uid: String(fileResource.id),
|
|
|
|
|
status: 'done',
|
|
|
|
|
url: fileResource.full_src,
|
|
|
|
|
thumbUrl: fileResource.full_src,
|
|
|
|
|
}
|
|
|
|
|
: item,
|
|
|
|
|
)
|
2026-01-24 17:45:54 +03:30
|
|
|
message.success('تصویر با موفقیت بارگذاری شد')
|
2026-07-06 17:06:25 +03:30
|
|
|
emits('ok', fileResource.id, info.file.response)
|
2026-01-24 17:45:54 +03:30
|
|
|
}
|
|
|
|
|
if (info.file.status === 'removed') {
|
|
|
|
|
emits('delete', info.file.uid)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-06-26 18:29:24 +03:30
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
fixFileCapture()
|
|
|
|
|
})
|
2026-01-24 17:45:54 +03:30
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="less">
|
|
|
|
|
@prefix: ~'@{prefixCls}-product-image-uploader';
|
|
|
|
|
|
|
|
|
|
.@{prefix} {
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
|
|
.ant-upload-rtl.ant-upload.ant-upload-select-picture-card {
|
|
|
|
|
margin: 0 !important;
|
|
|
|
|
border: none;
|
|
|
|
|
}
|
2026-05-12 17:36:54 +03:30
|
|
|
|
2026-01-24 17:45:54 +03:30
|
|
|
.ant-upload-picture-card-wrapper {
|
|
|
|
|
width: fit-content;
|
|
|
|
|
}
|
2026-05-12 17:36:54 +03:30
|
|
|
|
2026-01-24 17:45:54 +03:30
|
|
|
.ant-upload {
|
|
|
|
|
width: 78px !important;
|
|
|
|
|
height: 78px !important;
|
|
|
|
|
background-color: #eff6ff;
|
|
|
|
|
border: dashed 1px #93c5fd;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
2026-05-12 17:36:54 +03:30
|
|
|
|
2026-01-24 17:45:54 +03:30
|
|
|
.ant-upload-list-picture-card-container {
|
|
|
|
|
margin: 0;
|
|
|
|
|
width: 78px !important;
|
|
|
|
|
height: 78px !important;
|
|
|
|
|
}
|
2026-05-12 17:36:54 +03:30
|
|
|
|
2026-01-24 17:45:54 +03:30
|
|
|
.ant-upload-list-picture-card .ant-upload-list-item {
|
|
|
|
|
padding: 0;
|
|
|
|
|
border: none;
|
|
|
|
|
}
|
2026-05-12 17:36:54 +03:30
|
|
|
|
2026-01-24 17:45:54 +03:30
|
|
|
.ant-upload-list-picture-card .ant-upload-list-item-info {
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
2026-05-12 17:36:54 +03:30
|
|
|
|
2026-01-24 17:45:54 +03:30
|
|
|
.ant-upload-list {
|
|
|
|
|
display: flex !important;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|