Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-03-15 22:14:49 +03:00
parent d1790b7357
commit 7e98ea66d2
4 changed files with 193 additions and 118 deletions

View File

@@ -182,12 +182,12 @@
<q-card flat bordered class="product-image-card cursor-pointer" @click.stop="openProductCard(grp1, grp2)">
<q-card-section class="q-pa-xs product-image-wrap">
<q-img
v-if="getProductImageUrl(grp1.productCode, grp2.colorCode, grp2.secondColor)"
:src="getProductImageUrl(grp1.productCode, grp2.colorCode, grp2.secondColor)"
v-if="getProductImageUrl(grp1.productCode, grp2.colorCode, grp2.photoDim3 || grp2.secondColor, grp2.photoDim1ID || '', grp2.photoDim3ID || '')"
:src="getProductImageUrl(grp1.productCode, grp2.colorCode, grp2.photoDim3 || grp2.secondColor, grp2.photoDim1ID || '', grp2.photoDim3ID || '')"
fit="contain"
class="product-image"
loading="lazy"
@error="onProductImageError(grp1.productCode, grp2.colorCode, grp2.secondColor)"
@error="onProductImageError(grp1.productCode, grp2.colorCode, grp2.photoDim3 || grp2.secondColor, grp2.photoDim1ID || '', grp2.photoDim3ID || '')"
/>
<div v-else class="product-image-placeholder">
<q-icon name="image_not_supported" size="22px" color="grey-6" />
@@ -458,8 +458,8 @@ function sortByColorCodeAsc(a, b) {
return compareCodeLike(a?.secondColor, b?.secondColor)
}
function buildImageKey(code, color, secondColor = '') {
return `${String(code || '').trim().toUpperCase()}::${String(color || '').trim().toUpperCase()}::${String(secondColor || '').trim().toUpperCase()}`
function buildImageKey(code, color, secondColor = '', dim1Id = '', dim3Id = '') {
return `${String(code || '').trim().toUpperCase()}::${String(color || '').trim().toUpperCase()}::${String(secondColor || '').trim().toUpperCase()}::${String(dim1Id || '').trim().toUpperCase()}::${String(dim3Id || '').trim().toUpperCase()}`
}
function normalizeImageDim3(value) {
@@ -478,6 +478,34 @@ function resolvePhotoDim3(item, secondColorDisplay = '') {
)
}
function resolvePhotoDim1ID(item) {
const candidates = [
item?.ItemDim1Code,
item?.itemDim1Code,
item?.ITEMDIM1CODE,
item?.RenkID,
item?.Renk_Id
]
for (const value of candidates) {
const s = String(value || '').trim()
if (/^\d+$/.test(s)) return s
}
return ''
}
function resolvePhotoDim3ID(item) {
const candidates = [
item?.ItemDim3Code,
item?.itemDim3Code,
item?.ITEMDIM3CODE
]
for (const value of candidates) {
const s = String(value || '').trim()
if (/^\d+$/.test(s)) return s
}
return ''
}
function buildDim3Candidates(secondColor) {
const secondTrim = normalizeImageDim3(secondColor)
if (!secondTrim) return ['']
@@ -486,10 +514,12 @@ function buildDim3Candidates(secondColor) {
return Array.from(set)
}
async function fetchProductImageList(codeTrim, colorTrim, secondTrim) {
async function fetchProductImageList(codeTrim, colorTrim, secondTrim, dim1IdTrim = '', dim3IdTrim = '') {
const dim3Candidates = buildDim3Candidates(secondTrim)
for (const dim3Candidate of dim3Candidates) {
const params = { code: codeTrim, dim1: colorTrim }
if (String(dim1IdTrim || '').trim()) params.dim1_id = String(dim1IdTrim || '').trim()
if (String(dim3IdTrim || '').trim()) params.dim3_id = String(dim3IdTrim || '').trim()
if (dim3Candidate) params.dim3 = dim3Candidate
const res = await api.get('/product-images', { params })
const list = Array.isArray(res?.data) ? res.data : []
@@ -537,6 +567,8 @@ function resolveProductImageUrl(item) {
async function resolveProductImageUrlForCarousel(item) {
const resolved = resolveProductImageUrl(item)
const publicUrl = String(resolved.publicUrl || '').trim()
if (publicUrl) return publicUrl
const contentUrl = String(resolved.contentUrl || '').trim()
if (contentUrl) {
try {
@@ -551,46 +583,30 @@ async function resolveProductImageUrlForCarousel(item) {
// fall through to public url
}
}
return String(resolved.publicUrl || contentUrl || '').trim()
return String(contentUrl || '').trim()
}
function getProductImageUrl(code, color, secondColor = '') {
const key = buildImageKey(code, color, secondColor)
function getProductImageUrl(code, color, secondColor = '', dim1Id = '', dim3Id = '') {
const key = buildImageKey(code, color, secondColor, dim1Id, dim3Id)
const existing = productImageCache.value[key]
if (existing !== undefined) return existing || ''
void ensureProductImage(code, color, secondColor)
void ensureProductImage(code, color, secondColor, dim1Id, dim3Id)
return ''
}
async function onProductImageError(code, color, secondColor = '') {
const key = buildImageKey(code, color, secondColor)
const fallback = String(productImageFallbackByKey.value[key] || '')
if (fallback && !productImageContentLoading.value[key]) {
productImageContentLoading.value[key] = true
try {
const blobRes = await api.get(fallback, { baseURL: '', responseType: 'blob' })
const blob = blobRes?.data
if (blob instanceof Blob) {
const objectUrl = URL.createObjectURL(blob)
productImageBlobUrls.value.push(objectUrl)
productImageCache.value[key] = objectUrl
return
}
} catch {
// no-op
} finally {
delete productImageContentLoading.value[key]
}
}
async function onProductImageError(code, color, secondColor = '', dim1Id = '', dim3Id = '') {
const key = buildImageKey(code, color, secondColor, dim1Id, dim3Id)
productImageCache.value[key] = ''
}
async function ensureProductImage(code, color, secondColor = '') {
const key = buildImageKey(code, color, secondColor)
async function ensureProductImage(code, color, secondColor = '', dim1Id = '', dim3Id = '') {
const key = buildImageKey(code, color, secondColor, dim1Id, dim3Id)
const codeTrim = String(code || '').trim().toUpperCase()
const colorTrim = String(color || '').trim().toUpperCase()
const secondTrim = String(secondColor || '').trim().toUpperCase()
const listKey = buildImageKey(codeTrim, colorTrim, secondTrim)
const dim1IDTrim = String(dim1Id || '').trim().toUpperCase()
const dim3IDTrim = String(dim3Id || '').trim().toUpperCase()
const listKey = buildImageKey(codeTrim, colorTrim, secondTrim, dim1IDTrim, dim3IDTrim)
if (!codeTrim) {
productImageCache.value[key] = ''
return ''
@@ -612,7 +628,7 @@ async function ensureProductImage(code, color, secondColor = '') {
await new Promise((resolve) => imageListWaitQueue.push(resolve))
}
imageListActiveRequests++
productImageListByCode.value[listKey] = await fetchProductImageList(codeTrim, colorTrim, secondTrim)
productImageListByCode.value[listKey] = await fetchProductImageList(codeTrim, colorTrim, secondTrim, dim1IDTrim, dim3IDTrim)
} catch (err) {
productImageListByCode.value[listKey] = []
const status = Number(err?.response?.status || 0)
@@ -637,8 +653,8 @@ async function ensureProductImage(code, color, secondColor = '') {
const first = list[0] || null
const resolved = resolveProductImageUrl(first)
productImageCache.value[key] = resolved.contentUrl || resolved.publicUrl || ''
productImageFallbackByKey.value[key] = resolved.contentUrl || ''
productImageCache.value[key] = resolved.publicUrl || resolved.contentUrl || ''
productImageFallbackByKey.value[key] = resolved.publicUrl ? '' : (resolved.contentUrl || '')
} catch (err) {
console.warn('[ProductStockQuery] product image fetch failed', { code, color, err })
productImageCache.value[key] = ''
@@ -760,6 +776,8 @@ const level1Groups = computed(() => {
const colorDesc = String(item.Renk_Aciklamasi || '').trim()
const secondColor = String(item.Yaka || '').trim()
const photoDim3 = resolvePhotoDim3(item, secondColor)
const photoDim1ID = resolvePhotoDim1ID(item)
const photoDim3ID = resolvePhotoDim3ID(item)
const depoKodu = String(item.Depo_Kodu || '').trim()
const depoAdi = String(item.Depo_Adi || '').trim()
const kategori = String(item.YETISKIN_GARSON || '').trim()
@@ -790,7 +808,7 @@ const level1Groups = computed(() => {
}
l1.totalQty += qty
const l2Key = `${colorCode}|${secondColor}|${photoDim3}`
const l2Key = `${colorCode}|${secondColor}|${photoDim3}|${photoDim1ID}|${photoDim3ID}`
if (!l1.childrenMap.has(l2Key)) {
l1.childrenMap.set(l2Key, {
key: `L2|${productCode}|${l2Key}`,
@@ -798,6 +816,8 @@ const level1Groups = computed(() => {
colorDesc,
secondColor,
photoDim3,
photoDim1ID,
photoDim3ID,
kategori,
urunAnaGrubu,
urunAltGrubu,
@@ -946,7 +966,7 @@ async function fetchStockByCode() {
function onLevel2Click(productCode, grp2) {
toggleOpen(grp2.key)
if (isOpen(grp2.key)) {
void ensureProductImage(productCode, grp2.colorCode, grp2.photoDim3 || grp2.secondColor)
void ensureProductImage(productCode, grp2.colorCode, grp2.photoDim3 || grp2.secondColor, grp2.photoDim1ID || '', grp2.photoDim3ID || '')
}
}
@@ -955,28 +975,36 @@ async function openProductCard(grp1, grp2) {
const colorCode = String(grp2?.colorCode || '').trim()
const secondColor = String(grp2?.secondColor || '').trim()
const photoDim3 = String(grp2?.photoDim3 || secondColor).trim()
const listKey = buildImageKey(productCode, colorCode, photoDim3)
const photoDim1ID = String(grp2?.photoDim1ID || '').trim()
const photoDim3ID = String(grp2?.photoDim3ID || '').trim()
const listKey = buildImageKey(productCode, colorCode, photoDim3, photoDim1ID, photoDim3ID)
const codeTrim = String(productCode || '').trim().toUpperCase()
const colorTrim = String(colorCode || '').trim().toUpperCase()
const secondTrim = String(photoDim3 || '').trim().toUpperCase()
const dim1IDTrim = String(photoDim1ID || '').trim().toUpperCase()
const dim3IDTrim = String(photoDim3ID || '').trim().toUpperCase()
await ensureProductImage(productCode, colorCode, photoDim3)
await ensureProductImage(productCode, colorCode, photoDim3, photoDim1ID, photoDim3ID)
let list = Array.isArray(productImageListByCode.value[listKey]) ? productImageListByCode.value[listKey] : []
console.info('[ProductStockQuery][openProductCard] request', {
productCode,
colorCode,
secondColor,
dim1ID: dim1IDTrim,
dim3ID: dim3IDTrim,
listKey,
cachedListCount: list.length
})
if (!list.length && codeTrim) {
try {
list = await fetchProductImageList(codeTrim, colorTrim, secondTrim)
list = await fetchProductImageList(codeTrim, colorTrim, secondTrim, dim1IDTrim, dim3IDTrim)
productImageListByCode.value[listKey] = list
console.info('[ProductStockQuery][openProductCard] refetch', {
productCode: codeTrim,
dim1: colorTrim,
dim1ID: dim1IDTrim,
dim3: secondTrim,
dim3ID: dim3IDTrim,
fetchedCount: list.length,
fileNames: list.map((x) => String(x?.file_name || x?.FileName || '').trim()).filter(Boolean)
})
@@ -1004,7 +1032,7 @@ async function openProductCard(grp1, grp2) {
const uniqueImages = Array.from(new Set(images))
if (!uniqueImages.length) {
const single = getProductImageUrl(productCode, colorCode, photoDim3)
const single = getProductImageUrl(productCode, colorCode, photoDim3, photoDim1ID, photoDim3ID)
if (single) uniqueImages.push(single)
}