diff --git a/src/components/ProductUploader/IndexImageUploader.vue b/src/components/ProductUploader/IndexImageUploader.vue index 3f3e32b..eb80a32 100644 --- a/src/components/ProductUploader/IndexImageUploader.vue +++ b/src/components/ProductUploader/IndexImageUploader.vue @@ -19,6 +19,7 @@ :action="uploadURL" :headers="fileHeader" :before-upload="beforeUpload" + :custom-request="customRequest" :file-list="fileList" @change="handleChange" @update:file-list="onFileListUpdate" @@ -57,6 +58,7 @@ :action="uploadURL" :headers="fileHeader" :before-upload="beforeUpload" + :custom-request="customRequest" :file-list="fileList" @change="handleChange" @update:file-list="onFileListUpdate" @@ -91,7 +93,10 @@ import { uploadURL } from '@root/config' import { getToken } from '@/utils' import { fixFileCapture } from '@/utils/fixFileCapture' import { normalizeUploadFileResponse } from '@/utils/file' -import { createWebpBeforeUpload } from '@/utils/prepareImageForUpload' +import { + createImageBeforeUpload, + createImageCustomRequest +} from '@/utils/prepareImageForUpload' import { computed, onMounted, ref } from 'vue' const { prefixCls } = usePrefix('index-image-uploader') @@ -100,9 +105,9 @@ const previewImage = ref('') const previewTitle = ref('تصویر شاخص') const loading = ref(false) -const fileHeader = { +const fileHeader = computed(() => ({ Authorization: `Bearer ${getToken()}` -} +})) interface Props { fileList?: Array @@ -151,56 +156,58 @@ function removeImage() { } } -const beforeUpload: UploadProps['beforeUpload'] = createWebpBeforeUpload((msg) => +const beforeUpload: UploadProps['beforeUpload'] = createImageBeforeUpload((msg) => message.error(msg) ) +function applyUploadedIndexImage(body: unknown) { + loading.value = false + const fileResource = normalizeUploadFileResponse(body) + + if (!fileResource?.id || !fileResource.full_src) { + fileList.value = [] + message.error('آپلود انجام شد ولی آدرس تصویر ساخته نشد') + return + } + + fileList.value = [ + { + uid: String(fileResource.id), + name: fileResource.name || 'image', + status: 'done', + url: fileResource.full_src, + thumbUrl: fileResource.full_src, + response: body + } + ] + message.success('تصویر شاخص با موفقیت بارگذاری شد') + emits('ok', fileResource.id, body as Record) +} + +const customRequest: UploadProps['customRequest'] = createImageCustomRequest({ + action: () => uploadURL, + getHeaders: () => fileHeader.value, + messageError: (msg) => message.error(msg), + onStarted: () => { + loading.value = true + }, + onUploaded: applyUploadedIndexImage, + onFailed: () => { + loading.value = false + fileList.value = [] + } +}) + function handleChange(info: UploadChangeParam) { fixFileCapture() - const status = info.file.status - - if (status === 'uploading') { + // success/error از onUploaded/onFailed اعمال می‌شود (fileList کنترل‌شده گاهی done را می‌بلعد) + if (info.file.status === 'uploading') { loading.value = true - return } - // هر وضعیت غیر از uploading باید اسپینر را ببندد (error/done/removed/undefined) - loading.value = false - - if (status === 'error') { - fileList.value = [] - const serverMsg = - (info.file.response as { message?: string } | undefined)?.message || - (info.file.error as { message?: string } | undefined)?.message - message.error(serverMsg || 'خطا در بارگذاری تصویر') - return - } - - if (status === 'done') { - const fileResource = normalizeUploadFileResponse(info.file.response) - - if (!fileResource?.id || !fileResource.full_src) { - fileList.value = [] - message.error('آپلود انجام شد ولی آدرس تصویر ساخته نشد') - return - } - - fileList.value = [ - { - ...info.file, - uid: String(fileResource.id), - status: 'done', - url: fileResource.full_src, - thumbUrl: fileResource.full_src - } - ] - message.success('تصویر شاخص با موفقیت بارگذاری شد') - emits('ok', fileResource.id, info.file.response) - return - } - - if (status === 'removed') { + if (info.file.status === 'removed') { + loading.value = false emits('delete', info.file.uid) } } diff --git a/src/components/ProductUploader/ProductImageUploader.vue b/src/components/ProductUploader/ProductImageUploader.vue index e25cb91..80fd76d 100644 --- a/src/components/ProductUploader/ProductImageUploader.vue +++ b/src/components/ProductUploader/ProductImageUploader.vue @@ -13,6 +13,7 @@ :headers="fileHeader" :showUploadList="true" :before-upload="beforeUpload" + :custom-request="customRequest" @change="handleChange" >
@@ -32,16 +33,19 @@ import {uploadURL} from '@root/config' import {getToken} from '@/utils' import {fixFileCapture} from '@/utils/fixFileCapture' import {normalizeUploadFileResponse} from '@/utils/file' -import {createWebpBeforeUpload} from '@/utils/prepareImageForUpload' +import { + createImageBeforeUpload, + createImageCustomRequest +} from '@/utils/prepareImageForUpload' import {usePrefix} from '@core/composable/usePrefix' import {computed, onMounted, ref} from 'vue' const {prefixCls} = usePrefix('product-image-uploader') const loading = ref(false) -const fileHeader = { +const fileHeader = computed(() => ({ Authorization: `Bearer ${getToken()}` -} +})) interface Props { fileList?: Array @@ -60,47 +64,66 @@ const fileList = computed({ } }) -const beforeUpload: UploadProps['beforeUpload'] = createWebpBeforeUpload((msg) => +const beforeUpload: UploadProps['beforeUpload'] = createImageBeforeUpload((msg) => message.error(msg) ) +function applyUploadedProductImage(body: unknown, meta: { uid?: string }) { + loading.value = false + const fileResource = normalizeUploadFileResponse(body) + + if (!fileResource?.id || !fileResource.full_src) { + if (meta.uid) { + fileList.value = fileList.value.filter((item) => item.uid !== meta.uid) + } + message.error('خطا در ساخت آدرس تصویر') + return + } + + const doneItem = { + uid: String(fileResource.id), + name: fileResource.name || 'image', + status: 'done' as const, + url: fileResource.full_src, + thumbUrl: fileResource.full_src, + response: body + } + + const matched = meta.uid && fileList.value.some((item) => item.uid === meta.uid) + fileList.value = matched + ? fileList.value.map((item) => (item.uid === meta.uid ? doneItem : item)) + : [ + ...fileList.value.filter((item) => item.status !== 'uploading'), + doneItem + ] + + message.success('تصویر با موفقیت بارگذاری شد') + emits('ok', fileResource.id, body) +} + +const customRequest: UploadProps['customRequest'] = createImageCustomRequest({ + action: () => uploadURL, + getHeaders: () => fileHeader.value, + messageError: (msg) => message.error(msg), + onStarted: () => { + loading.value = true + }, + onUploaded: applyUploadedProductImage, + onFailed: (_err, meta) => { + loading.value = false + if (meta.uid) { + fileList.value = fileList.value.filter((item) => item.uid !== meta.uid) + } + } +}) + function handleChange(info: UploadChangeParam) { fixFileCapture() 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 - 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, - ) - message.success('تصویر با موفقیت بارگذاری شد') - emits('ok', fileResource.id, info.file.response) - } if (info.file.status === 'removed') { emits('delete', info.file.uid) } diff --git a/src/components/UploadPic.vue b/src/components/UploadPic.vue index cb161db..e969281 100644 --- a/src/components/UploadPic.vue +++ b/src/components/UploadPic.vue @@ -9,6 +9,7 @@ :headers="fileHeader" accept="image/*" :before-upload="beforeUpload" + :custom-request="customRequest" @change="handelChange" >
(false) @@ -72,37 +76,45 @@ const emit = defineEmits<{ (e: 'errorUpload'): void }>() -const beforeUpload: UploadProps['beforeUpload'] = createWebpBeforeUpload((msg) => +const beforeUpload: UploadProps['beforeUpload'] = createImageBeforeUpload((msg) => message.error(msg) ) -function handelChange({ file, fileList }) { - if (Object.hasOwn(file, 'percent')) { +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) : 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 - emit('startUpload') - return - } - - if (file.status === 'error') { - loading.value = false - emit('errorUpload') - message.error('خطا در آپلود فایل') - } - if (file.status == 'done') { - const fileResource = normalizeUploadFileResponse(file.response) - imageUrl.value = - fileResource?.full_src || - toAbsoluteFileUrl(file.response?.full_src || file.response?.src) || - '' - loading.value = false - emit('upload', file.response) - message.success('فایل با موفقیت آپلود شد') - } else if (fileList.status == 'removed') { } } diff --git a/src/pages/menuPages/banners/components/BannerImageUpload.vue b/src/pages/menuPages/banners/components/BannerImageUpload.vue index c0460ed..fb7c99f 100644 --- a/src/pages/menuPages/banners/components/BannerImageUpload.vue +++ b/src/pages/menuPages/banners/components/BannerImageUpload.vue @@ -9,6 +9,7 @@ :action="uploadURL" :headers="fileHeader" :before-upload="beforeUpload" + :custom-request="customRequest" @change="onChange" >