diff --git a/src/composables/useAppBannersAdmin.ts b/src/composables/useAppBannersAdmin.ts index 27fae8e..df155e7 100644 --- a/src/composables/useAppBannersAdmin.ts +++ b/src/composables/useAppBannersAdmin.ts @@ -1,7 +1,9 @@ import { reactive, ref } from 'vue' import { message } from 'ant-design-vue' import { loadAppBannersConst, saveAppBannersConst } from '@/api/appBanners' -import { emptyAppBanners, type AppBannersValue } from '@/model/appBanners' +import { emptyAppBanners, type AppBannersValue, type ThemeImagePair } from '@/model/appBanners' +import { toAbsoluteFileUrl } from '@/utils/file' +import type { IBenefits } from '@/model/banner' const state = reactive(emptyAppBanners()) const constId = ref(null) @@ -9,6 +11,38 @@ const loaded = ref(false) const loading = ref(false) const saving = ref(false) let loadPromise: Promise | null = null +let saveTimer: ReturnType | null = null +let saveChain: Promise = Promise.resolve(true) + +function httpsUrl(raw: string | null | undefined): string | null { + if (typeof raw !== 'string' || !raw.trim()) return null + return toAbsoluteFileUrl(raw.trim()) ?? raw.trim() +} + +function httpsPair(pair: ThemeImagePair): ThemeImagePair { + return { light: httpsUrl(pair.light), dark: httpsUrl(pair.dark) } +} + +function httpsSlider(slides: IBenefits[]): IBenefits[] { + return slides.map((slide) => ({ + ...slide, + icon: httpsUrl(slide.icon), + })) +} + +function snapshotForSave(): AppBannersValue { + return { + slider: httpsSlider([...state.slider]), + homeAsset: httpsPair(state.homeAsset), + piggyCreate: httpsPair(state.piggyCreate), + productsHero1: httpsPair(state.productsHero1), + productsHero2: httpsPair(state.productsHero2), + productsHero3: httpsPair(state.productsHero3), + referral: httpsPair(state.referral), + share: httpsPair(state.share), + invite: httpsPair(state.invite), + } +} async function load(force = false) { if (!force && loaded.value) return @@ -36,17 +70,7 @@ async function load(force = false) { async function save(successText = 'بنرهای اپ ذخیره شد') { saving.value = true try { - const nextId = await saveAppBannersConst(constId.value, { - slider: [...state.slider], - homeAsset: { ...state.homeAsset }, - piggyCreate: { ...state.piggyCreate }, - productsHero1: { ...state.productsHero1 }, - productsHero2: { ...state.productsHero2 }, - productsHero3: { ...state.productsHero3 }, - referral: { ...state.referral }, - share: { ...state.share }, - invite: { ...state.invite }, - }) + const nextId = await saveAppBannersConst(constId.value, snapshotForSave()) constId.value = nextId loaded.value = true message.success(successText) @@ -60,6 +84,15 @@ async function save(successText = 'بنرهای اپ ذخیره شد') { } } +/** آپلود/حذف را با تأخیر کوتاه در const می‌نویسد تا رفرش تصویر را برنگرداند. */ +function saveSoon(successText = 'بنر ذخیره شد') { + if (saveTimer) clearTimeout(saveTimer) + saveTimer = setTimeout(() => { + saveTimer = null + saveChain = saveChain.then(() => save(successText)) + }, 450) +} + export function useAppBannersAdmin() { void load() @@ -71,5 +104,6 @@ export function useAppBannersAdmin() { saving, load, save, + saveSoon, } } diff --git a/src/pages/menuPages/banners/components/BannerImageUpload.vue b/src/pages/menuPages/banners/components/BannerImageUpload.vue index fb7c99f..a9c8a05 100644 --- a/src/pages/menuPages/banners/components/BannerImageUpload.vue +++ b/src/pages/menuPages/banners/components/BannerImageUpload.vue @@ -1,7 +1,7 @@