fix(products): keep newly uploaded image when SSE list is stale
The live product stream was replacing the catalog with an older payload, so the new photo flashed then jumped back. Keep the newer file_id and stop resetting the img on unrelated price ticks. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -29,16 +29,26 @@ const props = withDefaults(
|
||||
}
|
||||
)
|
||||
|
||||
function productImageKey(product?: ProductImageSource): string {
|
||||
return [
|
||||
product?.file_id ?? '',
|
||||
product?.file?.id ?? '',
|
||||
product?.file?.full_src ?? '',
|
||||
product?.file?.src ?? '',
|
||||
product?.file?.url ?? '',
|
||||
product?.img ?? '',
|
||||
].join('|')
|
||||
}
|
||||
|
||||
const currentSrc = ref(resolveProductImageSrc(props.product))
|
||||
const usingFallback = ref(false)
|
||||
|
||||
watch(
|
||||
() => props.product,
|
||||
(product) => {
|
||||
() => productImageKey(props.product),
|
||||
() => {
|
||||
usingFallback.value = false
|
||||
currentSrc.value = resolveProductImageSrc(product)
|
||||
currentSrc.value = resolveProductImageSrc(props.product)
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
function handleError() {
|
||||
|
||||
@@ -6,7 +6,9 @@ import parsianImg from '@/assets/img/parsianImg.svg'
|
||||
import venusImg from '@/assets/img/venousImg.svg'
|
||||
|
||||
export type ProductImageSource = {
|
||||
file?: { src?: string | null } | null
|
||||
file?: { id?: number | null; src?: string | null; full_src?: string | null; url?: string | null } | null
|
||||
file_id?: number | string | null
|
||||
img?: string | null
|
||||
group_type?: string | null
|
||||
} | null | undefined
|
||||
|
||||
@@ -43,9 +45,14 @@ export function getProductFallbackImage(product?: ProductImageSource): string {
|
||||
}
|
||||
|
||||
export function resolveProductImageSrc(product?: ProductImageSource): string {
|
||||
const remoteSrc = product?.file?.src
|
||||
const remoteSrc = product?.file?.full_src || product?.file?.url || product?.file?.src
|
||||
if (isUsableImageSrc(remoteSrc)) {
|
||||
return remoteSrc!.trim()
|
||||
const url = remoteSrc!.trim()
|
||||
const version = product?.file_id ?? product?.file?.id
|
||||
if (version != null && version !== '' && Number(version) > 0 && /^https?:\/\//i.test(url) && !/[?&]v=/.test(url)) {
|
||||
return `${url}${url.includes('?') ? '&' : '?'}v=${encodeURIComponent(String(version))}`
|
||||
}
|
||||
return url
|
||||
}
|
||||
return getProductFallbackImage(product)
|
||||
}
|
||||
|
||||
@@ -53,6 +53,29 @@ async function loadCategoryTabs() {
|
||||
}
|
||||
}
|
||||
|
||||
function productFileId(product: Product): number {
|
||||
return Number(product.file_id ?? (product.file as { id?: number } | undefined)?.id ?? 0)
|
||||
}
|
||||
|
||||
function mergeLiveProductList(incoming: Product[], current?: Product[]): Product[] {
|
||||
if (!current?.length) return incoming
|
||||
|
||||
const currentById = new Map(current.map((item) => [item.id, item]))
|
||||
return incoming.map((item) => {
|
||||
const prev = currentById.get(item.id)
|
||||
if (!prev || productFileId(prev) <= productFileId(item)) {
|
||||
return item
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
file: prev.file,
|
||||
file_id: prev.file_id,
|
||||
img: prev.img,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function applyProductsList(products: Product[]) {
|
||||
const sorted = sortProductsByInventory(products)
|
||||
productsFirstItems.value = sorted
|
||||
@@ -76,8 +99,12 @@ export function applyProductsListFromSocket(products: Product[]) {
|
||||
return
|
||||
}
|
||||
|
||||
getProductsCatalogRef().value = products
|
||||
applyProductsList(products)
|
||||
const merged = mergeLiveProductList(
|
||||
products,
|
||||
getProductsCatalogRef().value.length ? getProductsCatalogRef().value : productsFirstItems.value,
|
||||
)
|
||||
getProductsCatalogRef().value = merged
|
||||
applyProductsList(merged)
|
||||
}
|
||||
|
||||
function startProductListPolling() {
|
||||
|
||||
Reference in New Issue
Block a user