import { joinFileUrl, API_HOST } from '@/config' const PLACEHOLDER_PATHS = ['/static/logo.png'] /** 是否外链或 data URL */ export function isExternalUrl(url) { if (!url) return false return /^(https?:|data:|\/\/)/i.test(String(url).trim()) } /** 去掉 /dev-api 等代理前缀,得到后端真实路径 */ function stripApiProxyPrefix(path) { return String(path).replace(/^\/(dev-api|prod-api|shop-api)/, '') || '/' } function isPlaceholderPath(path) { const raw = String(path || '').trim() return PLACEHOLDER_PATHS.includes(raw) } /** * 是否已是可直接使用的图片地址(避免重复拼接) */ export function isResolvedFileUrl(url) { if (!url) return false const raw = String(url).trim() if (isExternalUrl(raw)) return true if (raw.startsWith('/static/')) return true const apiHost = String(API_HOST).replace(/\/$/, '') return !!(apiHost && (raw === apiHost || raw.startsWith(`${apiHost}/`))) } /** * 将后端返回的图片路径转为可展示的完整 URL(可重复调用) * 结果形如:http://192.168.1.6:8020/profile/upload/xxx.jpg * @param {string} path bannerImage / categoryPic / mainPic 等 */ export function resolveFileUrl(path) { if (path == null || path === '') { return '' } let raw = String(path).split(',')[0].trim() if (!raw || isPlaceholderPath(raw)) { return '' } if (isExternalUrl(raw)) { return raw } if (raw.startsWith('/static/')) { return raw } const apiHost = String(API_HOST).replace(/\/$/, '') if (apiHost && (raw === apiHost || raw.startsWith(`${apiHost}/`))) { return raw } if (/^\/(dev-api|prod-api|shop-api)\//i.test(raw)) { raw = stripApiProxyPrefix(raw) } const normalized = raw.startsWith('/') ? raw : `/${raw}` return joinFileUrl(normalized) } /** * 将逗号分隔或数组形式的图片路径转为完整 URL 列表 * @param {string|string[]|null|undefined} pathOrList */ export function resolveFileUrlList(pathOrList) { if (pathOrList == null || pathOrList === '') return [] if (Array.isArray(pathOrList)) { return pathOrList.map((item) => resolveFileUrl(item)).filter(Boolean) } return String(pathOrList) .split(',') .map((s) => resolveFileUrl(s.trim())) .filter(Boolean) }