Insert image for product
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
import { baseURL, baseURLStorage } from '@root/config'
|
||||
import { getConfigApp } from '@/utils/config'
|
||||
import type { FileResource } from '@/api/file'
|
||||
|
||||
export function unwrapApiRecord(payload: unknown): Record<string, any> | null {
|
||||
if (!payload || typeof payload !== 'object') return null
|
||||
|
||||
const data = payload as Record<string, unknown>
|
||||
|
||||
if (data.data && typeof data.data === 'object') {
|
||||
return unwrapApiRecord(data.data)
|
||||
}
|
||||
|
||||
if (data.product && typeof data.product === 'object') {
|
||||
return unwrapApiRecord(data.product)
|
||||
}
|
||||
|
||||
if (data.row && typeof data.row === 'object') {
|
||||
return unwrapApiRecord(data.row)
|
||||
}
|
||||
|
||||
return data as Record<string, any>
|
||||
}
|
||||
|
||||
export function unwrapFileResource(payload: unknown): FileResource | null {
|
||||
if (!payload || typeof payload !== 'object') return null
|
||||
|
||||
const data = payload as Record<string, unknown>
|
||||
|
||||
if (
|
||||
typeof data.full_src === 'string' ||
|
||||
typeof data.src === 'string' ||
|
||||
typeof data.path === 'string' ||
|
||||
typeof data.url === 'string'
|
||||
) {
|
||||
return normalizeFileResource(data as Record<string, any>)
|
||||
}
|
||||
|
||||
if (data.data && typeof data.data === 'object') {
|
||||
return unwrapFileResource(data.data)
|
||||
}
|
||||
|
||||
if (data.file && typeof data.file === 'object') {
|
||||
return unwrapFileResource(data.file)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/** Site domain + API base, e.g. https://example.ir/server */
|
||||
export function getFileBaseUrl(): string {
|
||||
const fromConfig =
|
||||
getConfigApp('node_server') ||
|
||||
getConfigApp('storage_url') ||
|
||||
getConfigApp('storage') ||
|
||||
getConfigApp('file_url') ||
|
||||
getConfigApp('file_base')
|
||||
|
||||
if (typeof fromConfig === 'string' && fromConfig.trim()) {
|
||||
return fromConfig.replace(/\/$/, '')
|
||||
}
|
||||
|
||||
const storageBase = baseURLStorage || baseURL
|
||||
if (storageBase) {
|
||||
return storageBase.replace(/\/$/, '')
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
return `${window.location.origin}/server`.replace(/\/$/, '')
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns API paths like "storage/1405/02/27/file.jpg" into a full URL.
|
||||
*/
|
||||
export function toAbsoluteFileUrl(path?: string | null): string | undefined {
|
||||
if (!path?.trim()) return undefined
|
||||
|
||||
const trimmed = path.trim()
|
||||
|
||||
if (/^https?:\/\//i.test(trimmed)) {
|
||||
return trimmed
|
||||
}
|
||||
|
||||
const base = getFileBaseUrl()
|
||||
if (!base) return undefined
|
||||
|
||||
if (trimmed.startsWith('/')) {
|
||||
return `${base}${trimmed}`
|
||||
}
|
||||
|
||||
return `${base}/${trimmed.replace(/^\//, '')}`
|
||||
}
|
||||
|
||||
function isBareFileName(value: string): boolean {
|
||||
return !value.includes('/') && /\.[a-z0-9]+$/i.test(value)
|
||||
}
|
||||
|
||||
export function normalizeFileResource(record: Record<string, any>): FileResource | null {
|
||||
const src =
|
||||
typeof record.src === 'string'
|
||||
? record.src
|
||||
: typeof record.path === 'string'
|
||||
? record.path
|
||||
: undefined
|
||||
|
||||
if (!src && !record.full_src) return null
|
||||
|
||||
const absoluteUrl = toAbsoluteFileUrl(record.full_src || src)
|
||||
if (!absoluteUrl) return null
|
||||
|
||||
return {
|
||||
id: record.id != null ? Number(record.id) : undefined,
|
||||
name: record.title || record.original_name || record.name,
|
||||
src,
|
||||
full_src: absoluteUrl
|
||||
}
|
||||
}
|
||||
|
||||
/** Normalize upload API response: { id, src: "storage/...", title, ... } */
|
||||
export function normalizeUploadFileResponse(response: unknown): FileResource | null {
|
||||
const record = unwrapApiRecord(response)
|
||||
if (!record) return null
|
||||
return normalizeFileResource(record)
|
||||
}
|
||||
|
||||
export function resolveFileImageUrl(file?: FileResource | null): string | undefined {
|
||||
if (!file) return undefined
|
||||
if (file.full_src) return file.full_src
|
||||
return toAbsoluteFileUrl(file.src || file.path)
|
||||
}
|
||||
|
||||
export function pickRawFileFromRecord(record: Record<string, any>): Record<string, any> | null {
|
||||
for (const key of ['file', 'original_image', 'image', 'index_image', 'product_image']) {
|
||||
const value = record[key]
|
||||
if (value && typeof value === 'object') return value as Record<string, any>
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function resolveProductImageSrc(record: Record<string, any>): string | undefined {
|
||||
const fromRelation = resolveFileImageUrl(pickImageFromRecord(record))
|
||||
if (fromRelation) return fromRelation
|
||||
|
||||
const rawFile = pickRawFileFromRecord(record)
|
||||
if (rawFile?.src) return toAbsoluteFileUrl(rawFile.src)
|
||||
|
||||
if (typeof record.file_src === 'string') return toAbsoluteFileUrl(record.file_src)
|
||||
if (typeof record.image_src === 'string') return toAbsoluteFileUrl(record.image_src)
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function pickImageFromRecord(record: Record<string, any>): FileResource | null {
|
||||
const keys = [
|
||||
'file',
|
||||
'original_image',
|
||||
'image',
|
||||
'index_image',
|
||||
'product_image',
|
||||
'image_file',
|
||||
'uploaded_file'
|
||||
]
|
||||
|
||||
for (const key of keys) {
|
||||
const value = record[key]
|
||||
const resource = unwrapFileResource(value)
|
||||
if (resource) return resource
|
||||
|
||||
if (value && typeof value === 'object') {
|
||||
const normalized = normalizeFileResource(value as Record<string, any>)
|
||||
if (normalized) return normalized
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof record.src === 'string') {
|
||||
return normalizeFileResource(record)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function applyFileToUploadList(
|
||||
fileId: number | string,
|
||||
file?: FileResource | null,
|
||||
fallbackName = 'image'
|
||||
) {
|
||||
const imageSrc = resolveFileImageUrl(file)
|
||||
if (!imageSrc) return []
|
||||
|
||||
return [
|
||||
{
|
||||
uid: String(fileId),
|
||||
name: file?.name || fallbackName,
|
||||
status: 'done',
|
||||
url: imageSrc,
|
||||
thumbUrl: imageSrc
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user