唯品会商品详情页前端性能优化实战
一、项目背景与业务特点
唯品会作为国内领先的特卖电商平台,商品详情页面临着独特的挑战:
- 品牌特卖模式:主打品牌折扣,商品图片质量高,品牌Logo和标识需要清晰展示
- 女性用户为主:占比超过80%,对视觉体验和加载速度极为敏感
- 闪购模式:商品销售周期短(通常3-5天),需要快速上线和缓存策略
- 尺码助手:复杂的尺码选择、试穿推荐、身高体重匹配等功能
- 品牌故事展示:强调品牌调性和商品故事,富媒体内容较多
- 会员专享价:需要实时计算和展示会员折扣、优惠券叠加等价格信息
- 直播带货:品牌专场直播,需要实时同步库存和价格
核心性能瓶颈分析
┌─────────────────────────────────────────────────────────────┐ │ 唯品会商品详情页性能瓶颈(优化前) │ ├─────────────────────────────────────────────────────────────┤ │ • 首屏加载时间:7.2s(移动端4G) │ │ • 首屏可交互:5.1s │ │ • 品牌图片总体积:92MB(单商品40+张图,平均2.3MB/张) │ │ • 尺码助手加载:>2.8s │ │ • 会员价格计算:1.5s │ │ • 品牌故事视频加载:>4s │ │ • LCP(最大内容绘制):5.8s │ │ • CLS(累积布局偏移):0.32 │ │ • 移动端转化率:1.8%(行业平均2.8%) │ │ • 页面跳出率:58% │ │ • 闪购商品流失率:35%(因加载慢错过购买时机) │ └─────────────────────────────────────────────────────────────┘
二、唯品会专属品牌图片优化体系
2.1 品牌特卖图片智能处理系统
// 唯品会品牌特卖图片智能加载管理器
class VipBrandImageManager {
constructor() {
this.loadingQueue = [];
this.activeLoads = 0;
this.maxConcurrent = this.detectOptimalConcurrency();
this.imageCache = new LRUCache({ max: 500, ttl: 720000 }); // 12分钟缓存(适应闪购节奏)
this.brandAnalyzer = new BrandStyleAnalyzer();
// 唯品会特有的品牌图片处理配置
this.vipConfig = {
// 品牌特卖图片特点:需要保留品牌Logo清晰度,色彩还原度高
baseQuality: 85, // 比普通电商更高的质量保留(品牌展示需求)
mobileQuality: 78, // 移动端适当压缩
ultraHighQuality: 97, // 超清模式用于品牌Logo和细节展示
logoQuality: 99, // Logo必须超高清晰度
supportedFormats: this.detectSupportedFormats(),
// 唯品会CDN配置(品牌专区优化)
cdnRegions: {
'guangzhou': 'https://img-gz.vip.com', // 广州总部
'hangzhou': 'https://img-hz.vip.com', // 杭州节点
'beijing': 'https://img-bj.vip.com', // 北京节点
'shanghai': 'https://img-sh.vip.com', // 上海节点
'chengdu': 'https://img-cd.vip.com', // 成都节点
'overseas': 'https://img-global.vip.com' // 海外品牌
}
};
}
// 根据设备性能和网络确定并发数
detectOptimalConcurrency() {
const memory = navigator.deviceMemory || 4;
const cores = navigator.hardwareConcurrency || 2;
const connection = navigator.connection?.effectiveType || '4g';
const devicePixelRatio = window.devicePixelRatio || 1;
// 高端设备+好网:更多并发(品牌图片较大)
if (memory >= 8 && cores >= 4 && connection === '4g' && devicePixelRatio >= 2) {
return 8;
}
// 中端设备:适中并发
if (memory >= 4 || connection === '4g') {
return 5;
}
// 低端设备或弱网:降低并发
if (connection === 'slow-2g' || connection === '2g' || memory <= 2) {
return 2;
}
return 4;
}
// 检测支持的图片格式
detectSupportedFormats() {
const formats = ['jpg', 'png'];
const canvas = document.createElement('canvas');
// 检测WebP支持
if (canvas.toDataURL('image/webp').includes('webp')) {
formats.unshift('webp');
}
// 检测AVIF支持(更适合品牌图片的色彩保真)
if (canvas.toDataURL('image/avif').includes('avif')) {
formats.unshift('avif');
}
return formats;
}
// 生成唯品会专属品牌图片URL
generateVipBrandImageUrl(baseUrl, options = {}) {
const {
width,
height,
quality = this.isMobile() ? this.vipConfig.mobileQuality : this.vipConfig.baseQuality,
format = this.vipConfig.supportedFormats[0],
brandType = 'fashion', // fashion, luxury, sports, beauty, home, kids
enhancement = 'auto', // auto, brand_logo_enhance, color_accurate, skin_retouch
region = this.detectOptimalRegion(),
isLogo = false, // 是否包含品牌Logo
isMainImage = false // 是否主图
} = options;
// 品牌图片特殊处理参数
const brandParams = isLogo ? {
logo_enhance: 'ultra',
logo_sharpen: 'maximum',
text_clarity: 'premium',
background_preserve: 'transparent'
} : isMainImage ? {
brand_showcase: 'premium',
logo_protection: 'enabled',
color_space: 'srgb',
texture_detail: 'high'
} : {};
// 构建参数字符串
const params = new URLSearchParams({
url: encodeURIComponent(baseUrl),
w: width,
h: height,
q: isLogo ? this.vipConfig.logoQuality : quality,
fmt: format,
brand_type: brandType,
enhancement,
dpr: window.devicePixelRatio || 1,
// 唯品会品牌特色参数
brand_mode: 'premium',
logo_clarity: isLogo ? 'maximum' : 'standard',
color_accuracy: 'professional',
brand_protection: 'enabled',
texture_preserve: 'high',
...brandParams
});
return `${this.vipConfig.cdnRegions[region]}/vip/brand/image/process?${params.toString()}`;
}
// 检测用户所在区域
detectOptimalRegion() {
try {
const region = localStorage.getItem('vip_user_region');
if (region && this.vipConfig.cdnRegions[region]) {
return region;
}
} catch {}
// 基于IP地理定位和时区推断
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const hour = new Date().getHours();
// 华南地区(广州总部覆盖)
if (timezone.includes('Asia/Shanghai') || timezone.includes('Asia/Guangzhou')) {
return hour >= 9 && hour <= 21 ? 'guangzhou' : 'hangzhou';
}
// 华东地区
if (timezone.includes('Asia/Hong_Kong') || timezone.includes('Asia/Taipei')) {
return 'hangzhou';
}
// 华北地区
if (timezone.includes('Asia/Beijing') || timezone.includes('Asia/Shanghai')) {
return 'beijing';
}
// 西部地区
if (timezone.includes('Asia/Chengdu') || timezone.includes('Asia/Kunming')) {
return 'chengdu';
}
// 海外品牌
if (timezone.includes('America/') || timezone.includes('Europe/')) {
return 'overseas';
}
return 'guangzhou';
}
// 唯品会特色:品牌图片渐进式加载(针对品牌展示优化)
async progressiveLoadForBrandItem(container, imageSources, priority = 'normal') {
const { thumbnail, standard, high, ultra, logo, detail } = imageSources;
// 1. 创建品牌风格的占位符
const placeholder = this.createVipBrandPlaceholder(container);
container.style.backgroundImage = `url(${placeholder})`;
container.classList.add('vip-loading');
// 2. 加载超低质量预览(快速显示品牌轮廓)
const previewImg = await this.loadImage(thumbnail.preview, { priority: 'critical' });
container.style.backgroundImage = `url(${previewImg.url})`;
container.classList.add('preview-loaded');
// 3. 加载标准质量图(品牌展示的基本要求)
const standardImg = await this.loadImage(standard.normal, { priority });
container.style.backgroundImage = `url(${standardImg.url})`;
container.classList.add('standard-loaded');
// 4. 异步加载高清图(品牌细节展示)
this.loadImage(high.normal, { priority: 'low' }).then(highImg => {
container.style.backgroundImage = `url(${highImg.url})`;
container.classList.add('high-loaded');
});
// 5. 按需加载超清图和品牌Logo(桌面端且用户关注时)
if (!this.isMobile() && container.dataset.userEngaged === 'true') {
// 加载超清图
this.loadImage(ultra.normal, { priority: 'background' }).then(ultraImg => {
container.style.backgroundImage = `url(${ultraImg.url})`;
container.classList.add('ultra-loaded');
});
// 加载品牌Logo(单独处理确保清晰度)
if (logo?.main) {
this.loadImage(logo.main, {
priority: 'background',
isLogo: true
}).then(logoImg => {
container.dataset.brandLogo = logoImg.url;
this.renderBrandLogo(container, logoImg.url);
});
}
// 加载细节放大图(品牌工艺展示)
if (detail?.length > 0) {
detail.forEach((detailSrc, index) => {
this.loadImage(detailSrc, { priority: 'background' }).then(detailImg => {
container.dataset[`detail${index}`] = detailImg.url;
});
});
}
}
}
// 创建唯品会专属品牌占位符
createVipBrandPlaceholder(container) {
const canvas = document.createElement('canvas');
const width = container.dataset.width || 450;
const height = container.dataset.height || 600;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// 唯品会品牌渐变背景(粉色系,符合女性用户喜好)
const gradient = ctx.createLinearGradient(0, 0, width, height);
gradient.addColorStop(0, '#FFE4EC');
gradient.addColorStop(0.3, '#FFF0F5');
gradient.addColorStop(0.7, '#FFE4EC');
gradient.addColorStop(1, '#FFF5F8');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
// 添加唯品会Logo元素
ctx.fillStyle = 'rgba(255, 64, 129, 0.15)';
ctx.font = 'bold 32px "PingFang SC", "Microsoft YaHei", sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('VIP.COM', width / 2, height / 2 - 30);
// 品牌标语
ctx.font = '14px "PingFang SC", "Microsoft YaHei", sans-serif';
ctx.fillStyle = 'rgba(255, 64, 129, 0.25)';
ctx.fillText('品牌特卖 · 正品保证', width / 2, height / 2 + 10);
// 装饰性品牌元素
ctx.strokeStyle = 'rgba(255, 64, 129, 0.2)';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(width / 2, height / 2 + 50, 30, 0, Math.PI * 2);
ctx.stroke();
// 加载动画
const time = Date.now() / 1000;
const dots = '...'.substring(0, Math.floor(time % 3) + 1);
ctx.fillStyle = 'rgba(255, 64, 129, 0.6)';
ctx.font = '12px "PingFang SC", "Microsoft YaHei", sans-serif';
ctx.fillText(`品牌美图加载中${dots}`, width / 2, height / 2 + 85);
return canvas.toDataURL('image/png', 0.9);
}
// 渲染品牌Logo
renderBrandLogo(container, logoUrl) {
const logoContainer = container.querySelector('.brand-logo-container');
if (logoContainer) {
logoContainer.innerHTML = `<img src="${logoUrl}" alt="品牌Logo" class="brand-logo">`;
logoContainer.classList.add('logo-loaded');
}
}
// 品牌图片风格分析(唯品会特色)
async analyzeBrandStyle(imageUrl, brandInfo = {}) {
// 分析图片风格,自动选择最佳处理方式
const analysis = await this.brandAnalyzer.analyze(imageUrl, brandInfo);
let brandType = 'fashion';
let enhancement = 'auto';
// 基于品牌类型分类
if (brandInfo.category === 'luxury' || brandInfo.tier === 'premium') {
brandType = 'luxury';
enhancement = 'color_accurate'; // 奢侈品需要色彩精准
} else if (brandInfo.category === 'beauty' || brandInfo.category === 'cosmetics') {
brandType = 'beauty';
enhancement = 'skin_retouch'; // 美妆需要肤色美化
} else if (brandInfo.category === 'sports' || brandInfo.category === 'activewear') {
brandType = 'sports';
enhancement = 'dynamic_enhance'; // 运动需要动感增强
} else if (brandInfo.category === 'home' || brandInfo.category === 'lifestyle') {
brandType = 'home';
enhancement = 'warmth_enhance'; // 家居需要温馨感
} else if (brandInfo.category === 'kids' || brandInfo.category === 'children') {
brandType = 'kids';
enhancement = 'soft_enhance'; // 童装需要柔和增强
}
// 基于图片内容微调
if (analysis.isModelShot) {
enhancement = brandType === 'luxury' ? 'skin_retouch' : enhancement;
} else if (analysis.isProductOnly) {
enhancement = 'brand_logo_enhance'; // 纯产品图需要Logo增强
} else if (analysis.isLifestyle) {
enhancement = 'color_pop'; // 生活方式图需要色彩提亮
}
return { brandType, enhancement, analysis };
}
// 批量预加载品牌商品图片
async batchPreloadBrandImages(productList, priority = 'low') {
const preloadPromises = productList.slice(0, 10).map(async (product) => {
try {
// 分析品牌信息和图片风格
const brandInfo = {
category: product.brandCategory,
tier: product.brandTier,
name: product.brandName
};
const { brandType, enhancement } = await this.analyzeBrandStyle(product.mainImage, brandInfo);
const mainImageUrl = this.generateVipBrandImageUrl(product.mainImage, {
width: 450,
height: 600,
quality: 62,
brandType,
enhancement
});
return await this.loadImage(mainImageUrl, { priority }).catch(() => null);
} catch {
return null;
}
});
return Promise.allSettled(preloadPromises);
}
// 唯品会品牌瀑布流图片懒加载
initVipBrandMasonryLazyLoading(selector = '.vip-brand-masonry-item') {
const options = {
rootMargin: '350px 0px', // 品牌图片较大,提前更多加载
threshold: 0.01
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const imageData = JSON.parse(entry.target.dataset.imageData || '{}');
const priority = entry.target.dataset.priority || 'normal';
const brandType = entry.target.dataset.brandType || 'fashion';
if (imageData.urls) {
this.progressiveLoadForBrandItem(entry.target, imageData.urls, priority);
}
observer.unobserve(entry.target);
}
});
}, options);
document.querySelectorAll(selector).forEach(el => observer.observe(el));
}
// 判断是否移动端
isMobile() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
// 加载图片的核心方法
loadImage(url, { priority = 'normal', isLogo = false } = {}) {
const cacheKey = `${isLogo ? 'logo_' : ''}${url}`;
if (this.imageCache.has(cacheKey)) {
return Promise.resolve(this.imageCache.get(cacheKey));
}
return new Promise((resolve, reject) => {
this.loadingQueue.push({ url, priority, isLogo, resolve, reject });
this.processQueue();
});
}
processQueue() {
while (
this.loadingQueue.length > 0 &&
this.activeLoads < this.maxConcurrent
) {
const item = this.loadingQueue.shift();
this.activeLoads++;
this.fetchImage(item.url, item.isLogo)
.then(result => {
this.imageCache.set(`${item.isLogo ? 'logo_' : ''}${item.url}`, result);
item.resolve(result);
})
.catch(item.reject)
.finally(() => {
this.activeLoads--;
this.processQueue();
});
}
}
async fetchImage(url, isLogo = false) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve({
url,
width: img.naturalWidth,
height: img.naturalHeight,
loadedAt: Date.now(),
size: this.estimateBrandImageSize(img.naturalWidth, img.naturalHeight, isLogo),
isLogo
});
img.onerror = () => {
const fallbackUrl = this.getFallbackUrl(url, isLogo);
if (fallbackUrl && fallbackUrl !== url) {
img.src = fallbackUrl;
} else {
reject(new Error(`Failed to load: ${url}`));
}
};
img.src = url;
});
}
// 估算品牌图片大小
estimateBrandImageSize(width, height, isLogo = false, quality = 85) {
const pixels = width * height;
// 品牌图片压缩估算:每像素约0.65字节(质量85时,保留品牌细节)
const baseSize = Math.round(pixels * quality / 166.67 / 1024);
// Logo图片更大(需要超高清晰度)
return isLogo ? baseSize * 1.5 : baseSize;
}
getFallbackUrl(url, isLogo = false) {
if (url.includes('.webp')) return url.replace('.webp', '.jpg');
if (url.includes('.avif')) return url.replace('.avif', '.webp');
if (url.includes('_q85')) return url.replace('_q85', isLogo ? '_q95' : '_q78');
return null;
}
}
// 品牌风格分析器
class BrandStyleAnalyzer {
constructor() {
this.luxuryKeywords = ['luxury', 'premium', '高端', '奢华', '设计师', 'designer'];
this.beautyKeywords = ['beauty', 'cosmetic', '美妆', '护肤', '彩妆', 'makeup'];
this.sportsKeywords = ['sports', 'active', '运动', '健身', '户外', 'athletic'];
this.homeKeywords = ['home', 'lifestyle', '家居', '生活', '家纺', 'furniture'];
this.kidsKeywords = ['kids', 'children', '童装', '儿童', 'baby', 'infant'];
}
async analyze(imageUrl, brandInfo = {}) {
const fileName = imageUrl.toLowerCase();
const brandName = (brandInfo.name || '').toLowerCase();
const brandCategory = (brandInfo.category || '').toLowerCase();
// 基于品牌信息初步判断
const isLuxury = this.luxuryKeywords.some(kw => brandCategory.includes(kw) || brandName.includes(kw));
const isBeauty = this.beautyKeywords.some(kw => brandCategory.includes(kw) || brandName.includes(kw));
const isSports = this.sportsKeywords.some(kw => brandCategory.includes(kw) || brandName.includes(kw));
const isHome = this.homeKeywords.some(kw => brandCategory.includes(kw) || brandName.includes(kw));
const isKids = this.kidsKeywords.some(kw => brandCategory.includes(kw) || brandName.includes(kw));
// 基于文件名判断图片类型
const isModelShot = /model|girl|woman|man|person|wear|穿搭/.test(fileName);
const isProductOnly = /product|detail|zoom|close|静物/.test(fileName);
const isLifestyle = /lifestyle|street|outdoor|daily|生活/.test(fileName);
const isLogo = /logo|brand|标志|商标/.test(fileName);
return {
isLuxury,
isBeauty,
isSports,
isHome,
isKids,
isModelShot,
isProductOnly,
isLifestyle,
isLogo,
confidence: 0.85,
recommendedBrandType: isLuxury ? 'luxury' : isBeauty ? 'beauty' : isSports ? 'sports' : isHome ? 'home' : isKids ? 'kids' : 'fashion'
};
}
}
// 使用示例
const vipBrandImageManager = new VipBrandImageManager();
// 初始化品牌瀑布流懒加载
vipBrandImageManager.initVipBrandMasonryLazyLoading('.vip-brand-masonry-item');
// 绑定品牌图片数据
document.querySelectorAll('.vip-brand-masonry-item').forEach(item => {
const baseUrl = item.dataset.imageUrl;
const brandInfo = {
name: item.dataset.brandName,
category: item.dataset.brandCategory,
tier: item.dataset.brandTier
};
// 分析品牌风格
vipBrandImageManager.analyzeBrandStyle(baseUrl, brandInfo).then(({ brandType, enhancement }) => {
item.dataset.brandType = brandType;
item.dataset.imageData = JSON.stringify({
urls: {
thumbnail: {
preview: vipBrandImageManager.generateVipBrandImageUrl(baseUrl, {
width: 90, height: 120, quality: 35, brandType, enhancement: 'none', isLogo: false
}),
normal: vipBrandImageManager.generateVipBrandImageUrl(baseUrl, {
width: 225, height: 300, quality: 72, brandType, enhancement
})
},
standard: {
normal: vipBrandImageManager.generateVipBrandImageUrl(baseUrl, {
width: 450, height: 600, brandType, enhancement
})
},
high: {
normal: vipBrandImageManager.generateVipBrandImageUrl(baseUrl, {
width: 900, height: 1200, quality: 90, brandType, enhancement
})
},
ultra: {
normal: vipBrandImageManager.generateVipBrandImageUrl(baseUrl, {
width: 1350, height: 1800, quality: 97, brandType, enhancement
})
},
logo: {
main: item.dataset.logoUrl ? vipBrandImageManager.generateVipBrandImageUrl(item.dataset.logoUrl, {
width: 200, height: 80, quality: 99, brandType, enhancement: 'brand_logo_enhance', isLogo: true
}) : null
},
detail: item.dataset.detailImages?.split(',') || []
}
});
});
});2.2 唯品会CDN智能路由与品牌优化
// 唯品会CDN智能路由与品牌图片处理
class VipCDNOptimizer {
constructor() {
this.edgeNodes = this.selectOptimalEdgeNode();
this.brandProcessor = new VipBrandImageProcessor();
this.rateLimiter = new RateLimiter({ maxRequests: 20, timeWindow: 1000 });
this.brandPresets = this.loadBrandPresets();
this.flashSaleOptimizer = new FlashSaleOptimizer();
}
// 选择最优CDN节点
selectOptimalEdgeNode() {
const globalCDN = {
'guangzhou': 'https://img-gz.vip.com', // 广州总部(主节点)
'hangzhou': 'https://img-hz.vip.com', // 杭州节点(华东)
'beijing': 'https://img-bj.vip.com', // 北京节点(华北)
'shanghai': 'https://img-sh.vip.com', // 上海节点(金融中心)
'chengdu': 'https://img-cd.vip.com', // 成都节点(西南)
'overseas': 'https://img-global.vip.com' // 海外品牌
};
const userRegion = this.detectUserRegion();
const timeSlot = this.getTimeSlot();
// 根据时间段选择最优节点(避开高峰期)
const optimalRegion = this.optimizeByTimeSlot(userRegion, timeSlot);
return globalCDN[optimalRegion] || globalCDN['guangzhou'];
}
// 检测用户区域
async detectUserRegion() {
try {
const cachedRegion = localStorage.getItem('vip_detected_region');
const cacheTime = localStorage.getItem('vip_region_cache_time');
if (cachedRegion && cacheTime) {
const age = Date.now() - parseInt(cacheTime);
if (age < 86400000) return cachedRegion;
}
const response = await fetch('/api/user/detect-region', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
language: navigator.language,
platform: navigator.platform,
screenResolution: `${screen.width}x${screen.height}`
})
});
if (response.ok) {
const { region } = await response.json();
localStorage.setItem('vip_detected_region', region);
localStorage.setItem('vip_region_cache_time', Date.now().toString());
return region;
}
} catch (error) {
console.warn('Vip region detection failed:', error);
}
return this.inferRegionFromTimezone();
}
inferRegionFromTimezone() {
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (timezone.includes('Asia/Shanghai') || timezone.includes('Asia/Guangzhou')) {
return 'guangzhou';
}
if (timezone.includes('Asia/Hong_Kong')) {
return 'hangzhou';
}
if (timezone.includes('America/')) {
return 'overseas';
}
return 'guangzhou';
}
// 获取时间段
getTimeSlot() {
const hour = new Date().getHours();
if (hour >= 6 && hour < 12) return 'morning';
if (hour >= 12 && hour < 18) return 'afternoon';
if (hour >= 18 && hour < 22) return 'evening';
return 'night';
}
// 根据时间段优化节点选择
optimizeByTimeSlot(region, timeSlot) {
// 晚高峰(18-22点)避开主节点,选择备用节点
if (timeSlot === 'evening' && region === 'guangzhou') {
return 'hangzhou';
}
// 凌晨时段使用主节点(维护窗口)
if (timeSlot === 'night') {
return 'guangzhou';
}
return region;
}
// 加载品牌预设
loadBrandPresets() {
return {
'luxury_elegant': { contrast: 1.15, saturation: 1.0, brightness: 0.98, sharpness: 1.3, warmth: -0.05 },
'beauty_glow': { contrast: 1.08, saturation: 1.12, brightness: 1.05, sharpness: 1.15, warmth: 0.1 },
'sports_dynamic': { contrast: 1.2, saturation: 1.15, brightness: 1.02, sharpness: 1.1, warmth: 0.05 },
'home_cozy': { contrast: 1.05, saturation: 0.95, brightness: 1.08, sharpness: 1.05, warmth: 0.15 },
'kids_soft': { contrast: 1.02, saturation: 1.05, brightness: 1.06, sharpness: 1.0, warmth: 0.2 },
'fashion_vibrant': { contrast: 1.1, saturation: 1.08, brightness: 1.03, sharpness: 1.2, warmth: 0.08 }
};
}
// 生成唯品会优化的品牌图片URL
getOptimizedBrandImageUrl(originalUrl, options = {}) {
const {
width,
height,
quality = 85,
format = 'auto',
brandType = 'fashion',
preset = null,
enhancements = [],
region = this.detectOptimalRegion(),
flashSaleMode = false
} = options;
// 闪购模式特殊处理
const flashSaleParams = flashSaleMode ? {
flash_sale: 'enabled',
urgency_display: 'enhanced',
countdown_sync: 'real_time',
stock_warning: 'prominent'
} : {};
const params = new URLSearchParams({
url: encodeURIComponent(originalUrl),
w: width,
h: height,
q: quality,
fmt: format === 'auto' ? this.detectOptimalFormat() : format,
brand_type: brandType,
dpr: window.devicePixelRatio || 1,
// 唯品会品牌特色参数
brand_mode: 'premium',
logo_clarity: 'maximum',
color_accuracy: 'professional',
brand_protection: 'enabled',
texture_preserve: 'high',
...flashSaleParams
});
// 应用品牌预设
if (preset && this.brandPresets[preset]) {
const presetSettings = this.brandPresets[preset];
Object.entries(presetSettings).forEach(([key, value]) => {
params.set(key, value.toString());
});
params.set('preset', preset);
}
// 应用增强功能
if (enhancements.length > 0) {
params.set('enhancements', enhancements.join(','));
}
params.set('token', this.generateSecureToken(originalUrl, width, height, flashSaleMode));
return `${this.edgeNodes}/vip/brand/image/api/process?${params.toString()}`;
}
detectOptimalFormat() {
const canvas = document.createElement('canvas');
if (canvas.toDataURL('image/avif').includes('avif')) {
return 'avif';
}
if (canvas.toDataURL('image/webp').includes('webp')) {
return 'webp';
}
return 'jpg';
}
generateSecureToken(url, width, height, flashSaleMode = false) {
const secret = flashSaleMode ? 'vip_flash_sale_secure_2024' : 'vip_brand_secure_2024';
const timestamp = Math.floor(Date.now() / 900000); // 15分钟有效期
const nonce = Math.random().toString(36).substring(2, 12);
const signature = btoa(`${secret}:${url}:${width}:${height}:${timestamp}:${nonce}:${flashSaleMode}`)
.replace(/[^a-zA-Z0-9]/g, '')
.substring(0, 28);
return `${signature}:${timestamp}:${nonce}`;
}
// 批量生成品牌商品图片URL
generateBrandProductImageUrls(product, options = {}) {
const baseUrl = product.mainImage;
const gallery = product.gallery || [];
const detailImages = product.detailImages || [];
const logoUrl = product.brandLogo;
const defaultOptions = {
thumbWidth: 225,
thumbHeight: 300,
standardWidth: 450,
standardHeight: 600,
highWidth: 900,
highHeight: 1200,
ultraWidth: 1350,
ultraHeight: 1800,
quality: 85,
flashSaleMode: product.isFlashSale || false,
...options
};
// 检测品牌类型和适合的预设
const detectedType = this.detectBrandType(product);
const brandPreset = this.getBrandPreset(detectedType, product.brandTier);
return {
main: {
thumb: this.getOptimizedBrandImageUrl(baseUrl, {
width: defaultOptions.thumbWidth,
height: defaultOptions.thumbHeight,
quality: 68,
brandType: detectedType,
preset: brandPreset,
enhancements: ['brand_logo_enhance'],
flashSaleMode: defaultOptions.flashSaleMode
}),
standard: this.getOptimizedBrandImageUrl(baseUrl, {
width: defaultOptions.standardWidth,
height: defaultOptions.standardHeight,
quality: defaultOptions.quality,
brandType: detectedType,
preset: brandPreset,
enhancements: ['brand_logo_enhance', 'color_accurate'],
flashSaleMode: defaultOptions.flashSaleMode
}),
high: this.getOptimizedBrandImageUrl(baseUrl, {
width: defaultOptions.highWidth,
height: defaultOptions.highHeight,
quality: 92,
brandType: detectedType,
preset: brandPreset,
enhancements: ['brand_logo_enhance', 'color_accurate'],
flashSaleMode: defaultOptions.flashSaleMode
}),
ultra: this.getOptimizedBrandImageUrl(baseUrl, {
width: defaultOptions.ultraWidth,
height: defaultOptions.ultraHeight,
quality: 97,
brandType: detectedType,
preset: brandPreset,
enhancements: ['brand_logo_enhance', 'color_accurate', 'texture_enhance'],
flashSaleMode: defaultOptions.flashSaleMode
})
},
gallery: gallery.map((img, index) => {
const imgType = this.detectBrandType({ category: product.category, brandCategory: img.brandCategory });
const imgPreset = this.getBrandPreset(imgType, product.brandTier);
return {
thumb: this.getOptimizedBrandImageUrl(img, {
width: defaultOptions.thumbWidth,
height: defaultOptions.thumbHeight,
quality: 70,
brandType: imgType,
preset: imgPreset,
enhancements: index === 0 ? ['brand_logo_enhance'] : [],
flashSaleMode: defaultOptions.flashSaleMode
}),
standard: this.getOptimizedBrandImageUrl(img, {
width: defaultOptions.standardWidth,
height: defaultOptions.standardHeight,
quality: defaultOptions.quality,
brandType: imgType,
preset: imgPreset,
enhancements: ['brand_logo_enhance'],
flashSaleMode: defaultOptions.flashSaleMode
}),
high: this.getOptimizedBrandImageUrl(img, {
width: defaultOptions.highWidth,
height: defaultOptions.highHeight,
quality: 90,
brandType: imgType,
preset: imgPreset,
enhancements: ['brand_logo_enhance', 'color_accurate'],
flashSaleMode: defaultOptions.flashSaleMode
})
};
}),
details: detailImages.map((img, index) => ({
standard: this.getOptimizedBrandImageUrl(img, {
width: 675,
height: 900,
quality: 93,
brandType: 'detail',
preset: 'fashion_vibrant',
enhancements: ['brand_logo_enhance', 'texture_enhance'],
flashSaleMode: defaultOptions.flashSaleMode
}),
zoom: this.getOptimizedBrandImageUrl(img, {
width: 1350,
height: 1800,
quality: 97,
brandType: 'detail',
preset: 'fashion_vibrant',
enhancements: ['brand_logo_enhance', 'texture_enhance', 'sharpness_boost'],
flashSaleMode: defaultOptions.flashSaleMode
})
})),
logo: logoUrl ? {
main: this.getOptimizedBrandImageUrl(logoUrl, {
width: 250,
height: 100,
quality: 99,
brandType: detectedType,
preset: null,
enhancements: ['brand_logo_enhance'],
isLogo: true,
flashSaleMode: defaultOptions.flashSaleMode
}),
small: this.getOptimizedBrandImageUrl(logoUrl, {
width: 125,
height: 50,
quality: 99,
brandType: detectedType,
preset: null,
enhancements: ['brand_logo_enhance'],
isLogo: true,
flashSaleMode: defaultOptions.flashSaleMode
})
} : null
};
}
// 检测品牌类型
detectBrandType(product) {
const category = (product.category || '').toLowerCase();
const brandCategory = (product.brandCategory || '').toLowerCase();
const brandTier = (product.brandTier || '').toLowerCase();
const tags = (product.tags || []).join(' ').toLowerCase();
// 根据品牌等级判断
if (brandTier === 'luxury' || brandTier === 'premium' || brandTier === 'top') {
return 'luxury';
}
// 根据品类判断
if (category.includes('beauty') || category.includes('cosmetic') || category.includes('美妆') || tags.includes('美妆')) {
return 'beauty';
}
if (category.includes('sports') || category.includes('active') || category.includes('运动') || tags.includes('运动')) {
return 'sports';
}
if (category.includes('home') || category.includes('lifestyle') || category.includes('家居') || tags.includes('家居')) {
return 'home';
}
if (category.includes('kids') || category.includes('children') || category.includes('童装') || tags.includes('童装')) {
return 'kids';
}
return 'fashion';
}
// 获取品牌预设
getBrandPreset(brandType, brandTier) {
if (brandType === 'luxury') {
return brandTier === 'top' ? 'luxury_elegant' : 'fashion_vibrant';
}
if (brandType === 'beauty') {
return 'beauty_glow';
}
if (brandType === 'sports') {
return 'sports_dynamic';
}
if (brandType === 'home') {
return 'home_cozy';
}
if (brandType === 'kids') {
return 'kids_soft';
}
return 'fashion_vibrant';
}
// 预加载关键品牌图片
async preloadCriticalBrandImages(product) {
const isFlashSale = product.isFlashSale || false;
const imageUrls = this.generateBrandProductImageUrls(product, {
quality: isFlashSale ? 70 : 68, // 闪购模式稍高质量保证紧迫感
enhancements: isFlashSale ? ['urgency_enhance'] : [],
flashSaleMode: isFlashSale
});
const criticalUrls = [
imageUrls.main.thumb,
imageUrls.main.standard,
...imageUrls.gallery.slice(0, 5).map(g => g.thumb),
...imageUrls.details.slice(0, 2).map(d => d.standard),
imageUrls.logo?.small
].filter(Boolean);
const preloadPromises = criticalUrls.map(url => {
return new Promise((resolve) => {
const img = new Image();
img.onload = () => resolve({ url, success: true });
img.onerror = () => resolve({ url, success: false });
img.src = url;
});
});
return Promise.allSettled(preloadPromises);
}
// 闪购模式优化
optimizeForFlashSale(product) {
const flashSaleOptimizer = new FlashSaleOptimizer();
return flashSaleOptimizer.optimize(product, this);
}
}
// 闪购优化器
class FlashSaleOptimizer {
constructor() {
this.urgencyIndicators = {
countdown: true,
stockWarning: true,
soldCount: true,
remainingTime: true
};
}
optimize(product, cdnOptimizer) {
const flashSaleConfig = {
imageProcessing: {
urgencyEnhancement: true,
highlightRemaining: true,
emphasizeScarcity: true
},
caching: {
shorterTTL: 300000, // 5分钟缓存(正常12分钟)
aggressivePrefetch: true
},
loading: {
priorityBoost: true,
parallelLoading: true
}
};
// 生成带闪购优化的图片URL
const imageUrls = cdnOptimizer.generateBrandProductImageUrls(product, {
flashSaleMode: true,
quality: 75, // 闪购模式平衡质量和速度
enhancements: ['urgency_enhance', 'scarcity_highlight']
});
return {
...flashSaleConfig,
imageUrls,
urgencyMetrics: this.calculateUrgencyMetrics(product)
};
}
calculateUrgencyMetrics(product) {
const now = Date.now();
const endTime = new Date(product.flashSaleEndTime).getTime();
const remainingMs = endTime - now;
const remainingMinutes = Math.floor(remainingMs / 60000);
const remainingSeconds = Math.floor((remainingMs % 60000) / 1000);
const totalStock = product.totalStock;
const soldStock = product.soldStock;
const remainingStock = totalStock - soldStock;
const sellThroughRate = soldStock / totalStock;
return {
remainingTime: {
ms: remainingMs,
formatted: `${remainingMinutes}:${remainingSeconds.toString().padStart(2, '0')}`,
urgencyLevel: remainingMinutes < 30 ? 'critical' : remainingMinutes < 60 ? 'high' : 'medium'
},
stockLevel: {
remaining: remainingStock,
sellThroughRate,
urgencyLevel: sellThroughRate > 0.8 ? 'critical' : sellThroughRate > 0.5 ? 'high' : 'medium'
},
recommendations: this.getUrgencyRecommendations(remainingMinutes, sellThroughRate)
};
}
getUrgencyRecommendations(remainingMinutes, sellThroughRate) {
const recommendations = [];
if (remainingMinutes < 30 && sellThroughRate > 0.7) {
recommendations.push('立即购买 - 即将售罄');
} else if (remainingMinutes < 60 && sellThroughRate > 0.5) {
recommendations.push('抓紧时间 - 库存紧张');
} else if (remainingMinutes < 120) {
recommendations.push('限时抢购中');
}
return recommendations;
}
}三、尺码助手与个性化推荐
3.1 唯品会尺码助手组件
// 唯品会尺码助手组件(针对女性用户优化)
import React, { useState, useCallback, useMemo, useRef, useEffect } from 'react';
import { useDebounce } from 'react-use';
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
const VipSizeAssistant = ({ product, userProfile, onSizeSelect }) => {
const [selectedSize, setSelectedSize] = useState(null);
const [measurementMethod, setMeasurementMethod] = useState('height_weight'); // height_weight, manual, history
const [userMeasurements, setUserMeasurements] = useState({
height: '',
weight: '',
bust: '',
waist: '',
hips: '',
shoulder: ''
});
const [recommendedSize, setRecommendedSize] = useState(null);
const [sizeChart, setSizeChart] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [showSizeGuide, setShowSizeGuide] = useState(false);
const [lastPurchaseSize, setLastPurchaseSize] = useState(null);
// 尺码数据缓存
const sizeCache = useRef(new Map());
// 初始化用户测量数据
useEffect(() => {
if (userProfile) {
loadUserMeasurements();
loadLastPurchaseSize();
}
}, [userProfile]);
// 加载用户历史测量数据
const loadUserMeasurements = async () => {
try {
const response = await fetch(`/api/user/measurements?userId=${userProfile.id}`);
if (response.ok) {
const data = await response.json();
setUserMeasurements(prev => ({ ...prev, ...data }));
}
} catch (error) {
console.warn('Failed to load user measurements:', error);
}
};
// 加载上次购买尺码
const loadLastPurchaseSize = async () => {
try {
const response = await fetch(`/api/user/last-purchase-size?userId=${userProfile.id}&category=${product.category}`);
if (response.ok) {
const data = await response.json();
setLastPurchaseSize(data.size);
}
} catch (error) {
console.warn('Failed to load last purchase size:', error);
}
};
// 加载尺码表
useEffect(() => {
loadSizeChart();
}, [product.id]);
const loadSizeChart = async () => {
setIsLoading(true);
// 检查缓存
const cacheKey = `${product.brand}_${product.category}_${product.sizeStandard}`;
if (sizeCache.current.has(cacheKey)) {
setSizeChart(sizeCache.current.get(cacheKey));
setIsLoading(false);
return;
}
try {
const response = await fetch(`/api/product/size-chart?productId=${product.id}`);
if (response.ok) {
const data = await response.json();
sizeCache.current.set(cacheKey, data);
setSizeChart(data);
}
} catch (error) {
console.warn('Failed to load size chart:', error);
} finally {
setIsLoading(false);
}
};
// 基于身高体重推荐尺码
const recommendSizeByHeightWeight = useCallback((height, weight, gender = 'female') => {
if (!sizeChart || !height || !weight) return null;
const { sizes, measurements } = sizeChart;
// 计算BMI和体型分类
const heightInMeters = height / 100;
const bmi = weight / (heightInMeters * heightInMeters);
let bodyType;
if (gender === 'female') {
if (bmi < 18.5) bodyType = 'slim';
else if (bmi < 22) bodyType = 'normal';
else if (bmi < 25) bodyType = 'curvy';
else bodyType = 'plus';
} else {
if (bmi < 20) bodyType = 'slim';
else if (bmi < 24) bodyType = 'normal';
else if (bmi < 28) bodyType = 'muscular';
else bodyType = 'plus';
}
// 根据品牌和体型的尺码映射
const brandSizeMapping = getBrandSizeMapping(product.brand, product.sizeStandard, bodyType);
// 找到最匹配的尺码
let bestMatch = null;
let minDifference = Infinity;
sizes.forEach(size => {
const diff = Math.abs(brandSizeMapping[size] - bmi);
if (diff < minDifference) {
minDifference = diff;
bestMatch = size;
}
});
return bestMatch;
}, [sizeChart, product.brand, product.sizeStandard]);
// 获取品牌尺码映射
const getBrandSizeMapping = (brand, sizeStandard, bodyType) => {
// 唯品会品牌尺码数据库
const brandMappings = {
'uniqlo': {
'XS': 17.5, 'S': 19.5, 'M': 21.5, 'L': 23.5, 'XL': 25.5, 'XXL': 27.5
},
'hm': {
'XS': 17.8, 'S': 19.8, 'M': 21.8, 'L': 23.8, 'XL': 25.8
},
'zara': {
'XS': 18.0, 'S': 20.0, 'M': 22.0, 'L': 24.0, 'XL': 26.0
},
// 默认通用映射
'default': {
'XS': 18.2, 'S': 20.2, 'M': 22.2, 'L': 24.2, 'XL': 26.2, 'XXL': 28.2
}
};
return brandMappings[brand.toLowerCase()] || brandMappings['default'];
};
// 基于手动输入测量推荐尺码
const recommendSizeByManualInput = useCallback((measurements) => {
if (!sizeChart) return null;
const { sizes, measurements: sizeMeasurements } = sizeChart;
let bestMatch = null;
let minTotalDiff = Infinity;
sizes.forEach(size => {
const sizeMeas = sizeMeasurements[size];
if (!sizeMeas) return;
// 计算各部位差异
let totalDiff = 0;
let validMeasurements = 0;
if (measurements.bust && sizeMeas.bust) {
totalDiff += Math.abs(measurements.bust - sizeMeas.bust);
validMeasurements++;
}
if (measurements.waist && sizeMeas.waist) {
totalDiff += Math.abs(measurements.waist - sizeMeas.waist);
validMeasurements++;
}
if (measurements.hips && sizeMeas.hips) {
totalDiff += Math.abs(measurements.hips - sizeMeas.hips);
validMeasurements++;
}
if (measurements.shoulder && sizeMeas.shoulder) {
totalDiff += Math.abs(measurements.shoulder - sizeMeas.shoulder);
validMeasurements++;
}
if (validMeasurements > 0) {
const avgDiff = totalDiff / validMeasurements;
if (avgDiff < minTotalDiff) {
minTotalDiff = avgDiff;
bestMatch = size;
}
}
});
return bestMatch;
}, [sizeChart]);
// 防抖处理测量数据变化
useDebounce(
() => {
if (measurementMethod === 'height_weight' && userMeasurements.height && userMeasurements.weight) {
const recommended = recommendSizeByHeightWeight(
parseFloat(userMeasurements.height),
parseFloat(userMeasurements.weight)
);
setRecommendedSize(recommended);
} else if (measurementMethod === 'manual') {
const recommended = recommendSizeByManualInput(userMeasurements);
setRecommendedSize(recommended);
}
},
500,
[userMeasurements, measurementMethod, sizeChart]
);
// 处理尺码选择
const handleSizeSelect = (size) => {
setSelectedSize(size);
onSizeSelect?.(size);
// 记录用户选择
recordSizeSelection(size);
};
// 记录尺码选择
const recordSizeSelection = async (size) => {
try {
await fetch('/api/user/record-size-selection', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userId: userProfile?.id,
productId: product.id,
selectedSize: size,
recommendedSize,
measurementMethod,
userMeasurements,
timestamp: Date.now()
})
});
} catch (error) {
console.warn('Failed to record size selection:', error);
}
};
// 渲染尺码选项
const renderSizeOptions = () => {
if (!sizeChart) return null;
return sizeChart.sizes.map(size => {
const isRecommended = size === recommendedSize;
const isSelected = size === selectedSize;
const isLastPurchase = size === lastPurchaseSize;
const stockInfo = sizeChart.stock[size];
const isOutOfStock = stockInfo?.quantity <= 0;
const isLowStock = stockInfo?.quantity <= 5 && stockInfo?.quantity > 0;
return (
<button
key={size}
className={`vip-size-option ${isSelected ? 'selected' : ''} ${isRecommended ? 'recommended' : ''} ${isLastPurchase ? 'last-purchase' : ''} ${isOutOfStock ? 'out-of-stock' : ''}`}
onClick={() => !isOutOfStock && handleSizeSelect(size)}
disabled={isOutOfStock}
>
<span className="size-label">{size}</span>
{isRecommended && <span className="recommended-badge">👗 推荐</span>}
{isLastPurchase && <span className="history-badge">📦 上次购买</span>}
{isLowStock && <span className="low-stock-badge">⚠️ 仅剩{stockInfo.quantity}件</span>}
{isOutOfStock && <span className="out-of-stock-badge">暂无库存</span>}
</button>
);
});
};
// 渲染测量输入表单
const renderMeasurementForm = () => {
const inputFields = measurementMethod === 'height_weight' ? [
{ key: 'height', label: '身高(cm)', placeholder: '例如:165', suffix: 'cm' },
{ key: 'weight', label: '体重(kg)', placeholder: '例如:55', suffix: 'kg' }
] : [
{ key: 'bust', label: '胸围(cm)', placeholder: '例如:88', suffix: 'cm' },
{ key: 'waist', label: '腰围(cm)', placeholder: '例如:68', suffix: 'cm' },
{ key: 'hips', label: '臀围(cm)', placeholder: '例如:92', suffix: 'cm' },
{ key: 'shoulder', label: '肩宽(cm)', placeholder: '例如:38', suffix: 'cm' }
];
return (
<div className="measurement-input-form">
<h4>{measurementMethod === 'height_weight' ? '💡 快速估算尺码' : '📏 精确测量推荐'}</h4>
<p className="measurement-hint">
{measurementMethod === 'height_weight'
? '输入身高体重,AI为您推荐合适尺码'
: '输入您的身体尺寸,获得精准尺码匹配'}
</p>
<div className="input-grid">
{inputFields.map(field => (
<div key={field.key} className="input-group">
<label>{field.label}</label>
<div className="input-wrapper">
<input
type="number"
value={userMeasurements[field.key]}
onChange={(e) => setUserMeasurements(prev => ({
...prev,
[field.key]: e.target.value
}))}
placeholder={field.placeholder}
/>
<span className="unit">{field.suffix}</span>
</div>
</div>
))}
</div>
{recommendedSize && (
<div className="recommendation-result">
<div className="recommendation-icon">✨</div>
<div className="recommendation-text">
<p>根据您的数据,我们推荐 <strong>{recommendedSize}</strong> 码</p>
<p className="confidence">匹配度:{calculateConfidence()}%</p>
</div>
</div>
)}
</div>
);
};
// 计算推荐信心度
const calculateConfidence = () => {
if (!recommendedSize || !sizeChart) return 0;
// 基于数据完整性和品牌历史准确率计算
let confidence = 75; // 基础信心度
if (measurementMethod === 'manual' && userMeasurements.bust && userMeasurements.waist) {
confidence += 15; // 手动输入更准确
}
if (lastPurchaseSize === recommendedSize) {
confidence += 10; // 与历史购买一致
}
return Math.min(confidence, 98);
};
return (
<div className="vip-size-assistant">
<div className="assistant-header">
<h3>👗 尺码助手</h3>
<button
className="size-guide-toggle"
onClick={() => setShowSizeGuide(!showSizeGuide)}
>
📐 查看尺码表
</button>
</div>
{/* 测量方式切换 */}
<div className="measurement-method-tabs">
<button
className={`tab ${measurementMethod === 'height_weight' ? 'active' : ''}`}
onClick={() => setMeasurementMethod('height_weight')}
>
📊 身高体重
</button>
<button
className={`tab ${measurementMethod === 'manual' ? 'active' : ''}`}
onClick={() => setMeasurementMethod('manual')}
>
📏 手动输入
</button>
{lastPurchaseSize && (
<button
className={`tab ${measurementMethod === 'history' ? 'active' : ''}`}
onClick={() => {
setMeasurementMethod('history');
setSelectedSize(lastPurchaseSize);
}}
>
📦 上次购买
</button>
)}
</div>
{/* 测量输入表单 */}
{renderMeasurementForm()}
{/* 尺码选项 */}
<div className="size-options">
<h4>请选择尺码</h4>
{isLoading ? (
<div className="loading-sizes">
<div className="spinner"></div>
<span>加载尺码信息中...</span>
</div>
) : (
<div className="size-grid">
{renderSizeOptions()}
</div>
)}
</div>
{/* 尺码表弹窗 */}
{showSizeGuide && sizeChart && (
<div className="size-guide-modal">
<div className="modal-content">
<button className="close-btn" onClick={() => setShowSizeGuide(false)}>×</button>
<h3>{product.brand} 尺码表</h3>
<div className="size-table">
<table>
<thead>
<tr>
<th>尺码</th>
{sizeChart.measurements[Object.keys(sizeChart.measurements)[0]] &&
Object.keys(sizeChart.measurements[Object.keys(sizeChart.measurements)[0]]).map(key => (
<th key={key}>{getMeasurementLabel(key)}</th>
))
}
</tr>
</thead>
<tbody>
{sizeChart.sizes.map(size => (
<tr key={size}>
<td><strong>{size}</strong></td>
{sizeChart.measurements[size] &&
Object.values(sizeChart.measurements[size]).map((value, index) => (
<td key={index}>{value}</td>
))
}
</tr>
))}
</tbody>
</table>
</div>
<div className="size-guide-tips">
<h4>💡 测量小贴士</h4>
<ul>
<li>测量时请穿着贴身衣物</li>
<li>软尺不要勒得太紧,保持自然贴合</li>
<li>胸围:测量胸部最丰满处一周</li>
<li>腰围:测量腰部最细处一周</li>
<li>臀围:测量臀部最丰满处一周</li>
</ul>
</div>
</div>
</div>
)}
{/* 品牌尺码说明 */}
{sizeChart?.brandNote && (
<div className="brand-size-note">
<p>ℹ️ {sizeChart.brandNote}</p>
</div>
)}
</div>
);
};
// 获取测量项中文标签
const getMeasurementLabel = (key) => {
const labels = {
'bust': '胸围',
'waist': '腰围',
'hips': '臀围',
'shoulder': '肩宽',
'sleeve': '袖长',
'length': '衣长',
'inseam': '裤长'
};
return labels[key] || key;
};
export default VipSizeAssistant;3.2 唯品会个性化推荐引擎
// 唯品会个性化推荐引擎(针对品牌特卖和女性用户优化)
class VipRecommendationEngine {
constructor() {
this.cache = new LRUCache({ max: 3000, ttl: 600000 }); // 10分钟缓存
this.userProfile = null;
this.brandAffinity = new BrandAffinityTracker();
this.flashSaleOptimizer = new FlashSaleRecommender();
this.sizeBasedRecommender = new SizeBasedRecommender();
}
// 获取个性化推荐
async getPersonalizedRecommendations(product, allProducts, options = {}) {
const {
limit = 20,
includeSameBrand = true,
includeSimilarStyles = true,
includeFlashSale = true,
includeSizeMatch = true
} = options;
const cacheKey = `vip_personalized_${product.id}_${limit}_${includeSameBrand}_${includeSimilarStyles}_${includeFlashSale}_${includeSizeMatch}`;
const cached = this.cache.get(cacheKey);
if (cached) return cached;
// 并行执行多个推荐策略
const strategies = [];
// 1. 同品牌推荐(唯品会特色:品牌忠诚度)
if (includeSameBrand) {
strategies.push(this.getSameBrandRecommendations(product, allProducts));
}
// 2. 相似风格推荐
if (includeSimilarStyles) {
strategies.push(this.getSimilarStyleRecommendations(product, allProducts));
}
// 3. 闪购推荐(限时特卖)
if (includeFlashSale) {
strategies.push(this.flashSaleOptimizer.getFlashSaleRecommendations(product, allProducts));
}
// 4. 尺码匹配推荐
if (includeSizeMatch && this.userProfile?.measurements) {
strategies.push(this.sizeBasedRecommender.getSizeMatchRecommendations(product, allProducts, this.userProfile.measurements));
}
// 5. 品牌亲和力推荐
strategies.push(this.brandAffinity.getBrandAffinityRecommendations(this.userProfile));
// 合并和排序结果
const results = await Promise.all(strategies);
const merged = this.mergeAndRankRecommendations(results, product);
const finalResult = merged.slice(0, limit);
this.cache.set(cacheKey, finalResult);
return finalResult;
}
// 同品牌推荐(唯品会核心策略)
async getSameBrandRecommendations(product, allProducts) {
const sameBrandProducts = allProducts
.filter(p => p.brandId === product.brandId && p.id !== product.id)
.map(p => ({
...p,
recommendationScore: this.calculateSameBrandScore(p, product),
recommendationReason: '同品牌推荐',
strategy: 'same_brand'
}));
return sameBrandProducts.sort((a, b) => b.recommendationScore - a.recommendationScore);
}
// 计算同品牌推荐分数
calculateSameBrandScore(product, currentProduct) {
let score = 0;
// 品类匹配
if (product.category === currentProduct.category) score += 30;
// 价格区间相近
const priceDiff = Math.abs(product.price - currentProduct.price) / currentProduct.price;
if (priceDiff < 0.2) score += 25;
else if (priceDiff < 0.4) score += 15;
// 风格相似
if (product.style === currentProduct.style) score += 20;
// 标签重叠
const commonTags = product.tags.filter(t => currentProduct.tags.includes(t));
score += commonTags.length * 8;
// 品牌亲和力加成
const brandAffinity = this.brandAffinity.getAffinityScore(product.brandId);
score += brandAffinity * 15;
return score;
}
// 相似风格推荐
async getSimilarStyleRecommendations(product, allProducts) {
const similarProducts = allProducts
.filter(p => p.id !== product.id && p.brandId !== product.brandId)
.map(p => ({
...p,
recommendationScore: this.calculateStyleSimilarityScore(p, product),
recommendationReason: '相似风格推荐',
strategy: 'similar_style'
}));
return similarProducts.sort((a, b) => b.recommendationScore - a.recommendationScore).slice(0, 15);
}
// 计算风格相似分数
calculateStyleSimilarityScore(product1, product2) {
let score = 0;
// 品类匹配
if (product1.category === product2.category) score += 25;
// 风格匹配
if (product1.style === product2.style) score += 30;
// 目标人群匹配
if (product1.targetAudience === product2.targetAudience) score += 15;
// 场合匹配
const commonOccasions = product1.occasions.filter(o => product2.occasions.includes(o));
score += commonOccasions.length * 10;
// 价格接受度匹配
const priceRange1 = this.getPriceRange(product1.price);
const priceRange2 = this.getPriceRange(product2.price);
if (priceRange1 === priceRange2) score += 20;
return score;
}
// 获取价格区间
getPriceRange(price) {
if (price < 100) return 'budget';
if (price < 300) return 'affordable';
if (price < 800) return 'mid_range';
if (price < 2000) return 'premium';
return 'luxury';
}
// 合并和排序推荐结果
mergeAndRankRecommendations(results, currentProduct) {
const productScores = new Map();
results.forEach(strategyResults => {
strategyResults.forEach(product => {
if (!productScores.has(product.id)) {
productScores.set(product.id, {
...product,
scores: [],
reasons: []
});
}
const existing = productScores.get(product.id);
existing.scores.push(product.recommendationScore);
existing.reasons.push(product.recommendationReason);
});
});
// 计算加权总分
const weightedProducts = Array.from(productScores.values()).map(product => {
const avgScore = product.scores.reduce((sum, s) => sum + s, 0) / product.scores.length;
const diversityBonus = product.scores.length > 1 ? 10 : 0; // 多策略命中加分
return {
...product,
finalScore: avgScore + diversityBonus,
strategyCount: product.scores.length,
combinedReasons: [...new Set(product.reasons)].join(' + ')
};
});
return weightedProducts
.sort((a, b) => b.finalScore - a.finalScore)
.filter(p => p.finalScore > 30); // 过滤低质量推荐
}
// 更新用户画像
updateUserProfile(interaction) {
if (!this.userProfile) {
this.userProfile = {
id: interaction.userId || 'anonymous',
brandAffinities: {},
stylePreferences: {},
sizeProfile: {},
pricePreferences: {},
purchaseHistory: [],
browseHistory: []
};
}
// 记录浏览行为
if (interaction.type === 'view') {
this.userProfile.browseHistory.push({
productId: interaction.productId,
timestamp: Date.now(),
duration: interaction.duration || 0
});
// 更新品牌亲和力
this.brandAffinity.recordBrandInteraction(interaction.brandId, 'view', 1);
// 更新风格偏好
this.updateStylePreference(interaction.product);
}
// 记录购买行为
if (interaction.type === 'purchase') {
this.userProfile.purchaseHistory.push({
productId: interaction.productId,
brandId: interaction.brandId,
size: interaction.size,
price: interaction.price,
timestamp: Date.now()
});
// 更新品牌亲和力(购买权重更高)
this.brandAffinity.recordBrandInteraction(interaction.brandId, 'purchase', 5);
// 更新尺码档案
if (interaction.size) {
this.updateSizeProfile(interaction.brandId, interaction.size, interaction.product);
}
// 更新价格偏好
this.updatePricePreference(interaction.price);
}
// 保存用户画像
try {
localStorage.setItem('vip_user_profile', JSON.stringify(this.userProfile));
} catch (error) {
console.warn('Failed to save user profile:', error);
}
}
// 更新风格偏好
updateStylePreference(product) {
const prefs = this.userProfile.stylePreferences;
const style = product.style;
prefs[style] = (prefs[style] || 0) + 2;
}
// 更新尺码档案
updateSizeProfile(brandId, size, product) {
if (!this.userProfile.sizeProfile[brandId]) {
this.userProfile.sizeProfile[brandId] = {};
}
const brandSizes = this.userProfile.sizeProfile[brandId];
brandSizes[size] = (brandSizes[size] || 0) + 1;
}
// 更新价格偏好
updatePricePreference(price) {
const range = this.getPriceRange(price);
this.userProfile.pricePreferences[range] = (this.userProfile.pricePreferences[range] || 0) + 1;
}
// 获取品牌亲和力追踪器
getBrandAffinityTracker() {
return this.brandAffinity;
}
}
// 品牌亲和力追踪器
class BrandAffinityTracker {
constructor() {
this.brandScores = new Map();
this.interactionWeights = {
'view': 1,
'favorite': 2,
'cart': 3,
'purchase': 5,
'review': 4
};
}
recordBrandInteraction(brandId, interactionType, multiplier = 1) {
const weight = this.interactionWeights[interactionType] || 1;
const currentScore = this.brandScores.get(brandId) || 0;
const newScore = currentScore + (weight * multiplier);
this.brandScores.set(brandId, newScore);
}
getAffinityScore(brandId) {
const score = this.brandScores.get(brandId) || 0;
// 归一化到0-1范围
return Math.min(score / 50, 1);
}
getTopBrands(limit = 10) {
return Array.from(this.brandScores.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, limit)
.map(([brandId, score]) => ({ brandId, affinityScore: this.getAffinityScore(brandId) }));
}
getBrandAffinityRecommendations(userProfile) {
const topBrands = this.getTopBrands(5);
// 返回这些品牌的推荐产品
return topBrands.map(brand => ({
brandId: brand.brandId,
recommendationScore: brand.affinityScore * 50,
recommendationReason: '品牌偏好推荐',
strategy: 'brand_affinity'
}));
}
}
// 闪购推荐器
class FlashSaleRecommender {
constructor() {
this.flashSaleProducts = new Map();
}
async getFlashSaleRecommendations(currentProduct, allProducts) {
const now = Date.now();
const flashSales = allProducts.filter(p =>
p.isFlashSale &&
p.flashSaleStartTime <= now &&
p.flashSaleEndTime > now &&
p.id !== currentProduct.id
);
return flashSales.map(product => ({
...product,
recommendationScore: this.calculateFlashSaleScore(product, currentProduct),
recommendationReason: '闪购推荐',
strategy: 'flash_sale',
urgencyInfo: this.calculateUrgency(product)
})).sort((a, b) => b.recommendationScore - a.recommendationScore);
}
calculateFlashSaleScore(flashSaleProduct, currentProduct) {
let score = 0;
// 折扣力度
const discountPercent = flashSaleProduct.flashSaleDiscount;
score += discountPercent * 2;
// 品类匹配
if (flashSaleProduct.category === currentProduct.category) score += 25;
// 品牌匹配
if (flashSaleProduct.brandId === currentProduct.brandId) score += 30;
// 价格区间相近
const priceDiff = Math.abs(flashSaleProduct.price - currentProduct.price) / currentProduct.price;
if (priceDiff < 0.3) score += 15;
// 紧迫感加成(剩余时间越少,分数越高)
const urgency = this.calculateUrgency(flashSaleProduct);
if (urgency.level === 'critical') score += 20;
else if (urgency.level === 'high') score += 10;
return score;
}
calculateUrgency(product) {
const now = Date.now();
const endTime = new Date(product.flashSaleEndTime).getTime();
const remainingMinutes = Math.floor((endTime - now) / 60000);
let level, message;
if (remainingMinutes < 30) {
level = 'critical';
message = '即将结束';
} else if (remainingMinutes < 60) {
level = 'high';
message = '限时抢购';
} else if (remainingMinutes < 180) {
level = 'medium';
message = '火热进行中';
} else {
level = 'low';
message = '即将开始';
}
return { level, message, remainingMinutes };
}
}
// 基于尺码的推荐器
class SizeBasedRecommender {
constructor() {
this.userSizeProfiles = new Map();
}
async getSizeMatchRecommendations(currentProduct, allProducts, userMeasurements) {
if (!userMeasurements || !userMeasurements.height || !userMeasurements.weight) {
return [];
}
return allProducts
.filter(p => p.id !== currentProduct.id)
.map(product => ({
...product,
recommendationScore: this.calculateSizeMatchScore(product, userMeasurements),
recommendationReason: '尺码匹配推荐',
strategy: 'size_match'
}))
.filter(p => p.recommendationScore > 40)
.sort((a, b) => b.recommendationScore - a.recommendationScore)
.slice(0, 10);
}
calculateSizeMatchScore(product, userMeasurements) {
// 基于用户测量数据推荐合适尺码的产品
let score = 50; // 基础分数
// 如果有尺码表,计算匹配度
if (product.sizeChart) {
const recommendedSize = this.recommendSize(product.sizeChart, userMeasurements);
if (recommendedSize) {
score += 30;
}
}
// 品牌尺码一致性(用户在该品牌的历史购买尺码)
const brandSizeConsistency = this.getBrandSizeConsistency(product.brandId, userMeasurements);
score += brandSizeConsistency * 20;
return score;
}
recommendSize(sizeChart, userMeasurements) {
// 根据尺码表和用户测量推荐尺码
// 简化实现
return 'M'; // 示例
}
getBrandSizeConsistency(brandId, userMeasurements) {
// 计算用户在该品牌尺码的一致性
return 0.8; // 示例值
}
}四、会员专享价与实时数据
4.1 唯品会会员价格系统
// 唯品会会员价格计算与展示系统
class VipPriceSystem {
constructor() {
this.priceCache = new LRUCache({ max: 1000, ttl: 300000 }); // 5分钟缓存
this.memberLevel = this.getMemberLevel();
this.availableCoupons = [];
this.priceUpdateCallbacks = new Set();
}
// 获取会员等级
getMemberLevel() {
try {
const userInfo = JSON.parse(localStorage.getItem('vip_user_info') || '{}');
return userInfo.memberLevel || 'normal'; // normal, silver, gold, platinum, diamond
} catch {
return 'normal';
}
}
// 计算会员专享价
async calculateMemberPrice(product, options = {}) {
const {
quantity = 1,
couponIds = [],
memberLevel = this.memberLevel,
includeFlashSale = true,
includePoints = true
} = options;
const cacheKey = `vip_price_${product.id}_${quantity}_${couponIds.sort().join('_')}_${memberLevel}`;
const cached = this.priceCache.get(cacheKey);
if (cached) return cached;
// 并行获取各类价格信息
const [
basePrice,
memberDiscount,
flashSalePrice,
couponsDiscount,
pointsDiscount,
bundleDiscount
] = await Promise.all([
this.getBasePrice(product),
this.getMemberDiscount(product, memberLevel),
includeFlashSale ? this.getFlashSalePrice(product) : Promise.resolve(null),
this.calculateCouponsDiscount(product, couponIds),
includePoints ? this.calculatePointsDiscount(product) : Promise.resolve(0),
this.getBundleDiscount(product, quantity)
]);
// 计算最终价格
let currentPrice = basePrice;
let priceBreakdown = [];
// 1. 应用会员折扣
if (memberDiscount > 0) {
const discountAmount = currentPrice * memberDiscount;
currentPrice -= discountAmount;
priceBreakdown.push({
type: 'member_discount',
description: this.getMemberDiscountDesc(memberLevel),
amount: discountAmount,
rate: memberDiscount
});
}
// 2. 应用闪购折扣
if (flashSalePrice && flashSalePrice < currentPrice) {
const discountAmount = currentPrice - flashSalePrice;
priceBreakdown.push({
type: 'flash_sale',
description: '闪购特惠',
amount: discountAmount,
originalPrice: currentPrice,
discountedPrice: flashSalePrice
});
currentPrice = flashSalePrice;
}
// 3. 应用优惠券
if (couponsDiscount > 0) {
currentPrice -= couponsDiscount;
priceBreakdown.push({
type: 'coupons',
description: '优惠券抵扣',
amount: couponsDiscount
});
}
// 4. 应用积分抵扣
if (pointsDiscount > 0) {
currentPrice -= pointsDiscount;
priceBreakdown.push({
type: 'points',
description: '积分抵扣',
amount: pointsDiscount
});
}
// 5. 应用套装折扣
if (bundleDiscount > 0) {
currentPrice -= bundleDiscount;
priceBreakdown.push({
type: 'bundle',
description: `${quantity}件套装优惠`,
amount: bundleDiscount
});
}
// 确保价格不为负
currentPrice = Math.max(currentPrice, 0);
const result = {
originalPrice: basePrice,
finalPrice: currentPrice,
totalDiscount: basePrice - currentPrice,
discountRate: ((basePrice - currentPrice) / basePrice * 100).toFixed(1),
memberLevel,
quantity,
priceBreakdown,
savings: this.calculateSavings(basePrice, currentPrice),
expiresAt: this.getPriceExpiry(product),
currency: 'CNY'
};
this.priceCache.set(cacheKey, result);
this.notifyPriceUpdate(result);
return result;
}
// 获取基础价格
async getBasePrice(product) {
// 优先从缓存获取
const cacheKey = `base_price_${product.id}`;
const cached = this.priceCache.get(cacheKey);
if (cached) return cached;
try {
const response = await fetch(`/api/product/base-price?productId=${product.id}`);
const data = await response.json();
const price = data.price;
this.priceCache.set(cacheKey, price);
return price;
} catch (error) {
console.warn('Failed to get base price:', error);
return product.price || 0;
}
}
// 获取会员折扣
async getMemberDiscount(product, memberLevel) {
// 会员折扣规则(唯品会特色)
const memberDiscountRules = {
'diamond': { general: 0.95, premium: 0.92, luxury: 0.90 },
'platinum': { general: 0.96, premium: 0.94, luxury: 0.92 },
'gold': { general: 0.97, premium: 0.95, luxury: 0.93 },
'silver': { general: 0.98, premium: 0.97, luxury: 0.95 },
'normal': { general: 1.0, premium: 0.99, luxury: 0.98 }
};
// 判断商品档次
const productTier = this.getProductTier(product);
const rules = memberDiscountRules[memberLevel] || memberDiscountRules['normal'];
return rules[productTier] || 1.0;
}
// 判断商品档次
getProductTier(product) {
const price = product.price || 0;
const brandTier = product.brandTier || 'general';
if (brandTier === 'luxury' || price >= 2000) return 'luxury';
if (brandTier === 'premium' || price >= 800) return 'premium';
return 'general';
}
// 获取闪购价格
async getFlashSalePrice(product) {
if (!product.isFlashSale) return null;
const now = Date.now();
if (product.flashSaleStartTime > now || product.flashSaleEndTime < now) {
return null;
}
return product.flashSalePrice;
}
// 计算优惠券折扣
async calculateCouponsDiscount(product, couponIds) {
if (!couponIds || couponIds.length === 0) return 0;
let totalDiscount = 0;
for (const couponId of couponIds) {
const coupon = await this.getCouponInfo(couponId);
if (coupon && this.isCouponApplicable(coupon, product)) {
const discount = this.calculateCouponDiscount(coupon, product.price);
totalDiscount += discount;
}
}
return totalDiscount;
}
// 获取优惠券信息
async getCouponInfo(couponId) {
try {
const response = await fetch(`/api/coupon/info?couponId=${couponId}`);
return await response.json();
} catch (error) {
console.warn('Failed to get coupon info:', error);
return null;
}
}
// 检查优惠券是否适用
isCouponApplicable(coupon, product) {
// 检查品类限制
if (coupon.applicableCategories && coupon.applicableCategories.length > 0) {
if (!coupon.applicableCategories.includes(product.category)) {
return false;
}
}
// 检查品牌限制
if (coupon.applicableBrands && coupon.applicableBrands.length > 0) {
if (!coupon.applicableBrands.includes(product.brandId)) {
return false;
}
}
// 检查最低消费
if (product.price < coupon.minPurchase) {
return false;
}
// 检查有效期
const now = Date.now();
if (now < coupon.validFrom || now > coupon.validTo) {
return false;
}
return true;
}
// 计算优惠券折扣金额
calculateCouponDiscount(coupon, price) {
if (coupon.discountType === 'fixed') {
return Math.min(coupon.discountValue, price);
} else if (coupon.discountType === 'percentage') {
return price * (coupon.discountValue / 100);
}
return 0;
}
// 计算积分抵扣
async calculatePointsDiscount(product) {
try {
const userInfo = JSON.parse(localStorage.getItem('vip_user_info') || '{}');
const availablePoints = userInfo.availablePoints || 0;
// 积分兑换比例(100积分=1元)
const exchangeRate = 100;
const maxPointsDeduction = Math.min(
availablePoints,
product.price * 0.5 // 最多抵扣50%
);
return Math.floor(maxPointsDeduction / exchangeRate);
} catch {
return 0;
}
}
// 获取套装折扣
async getBundleDiscount(product, quantity) {
if (quantity < 2) return 0;
// 套装折扣规则
const bundleDiscountRules = {
2: 0.05, // 2件95折
3: 0.08, // 3件92折
4: 0.12, // 4件88折
5: 0.15 // 5件及以上85折
};
const discountRate = bundleDiscountRules[quantity] || bundleDiscountRules[5];
const basePrice = await this.getBasePrice(product);
return basePrice * discountRate * (quantity - 1); // 只对额外商品打折
}
// 获取会员折扣描述
getMemberDiscountDesc(memberLevel) {
const descriptions = {
'diamond': '钻石会员95折',
'platinum': '铂金会员96折',
'gold': '金牌会员97折',
'silver': '银牌会员98折',
'normal': '普通会员专享'
};
return descriptions[memberLevel] || '会员专享';
}
// 计算节省金额
calculateSavings(originalPrice, finalPrice) {
const savings = originalPrice - finalPrice;
const memberLevel = this.memberLevel;
let levelMessage = '';
if (memberLevel === 'diamond') {
levelMessage = '尊贵的钻石会员,您已享受最高级别优惠!';
} else if (memberLevel === 'platinum') {
levelMessage = '感谢您成为铂金会员,继续购物享受更多优惠!';
} else if (memberLevel === 'gold') {
levelMessage = '金牌会员专享福利,再买满500元升级铂金!';
} else if (memberLevel === 'silver') {
levelMessage = '银牌会员优惠,升级金牌享更多折扣!';
}
return {
amount: savings,
percentage: ((savings / originalPrice) * 100).toFixed(1),
levelMessage
};
}
// 获取价格过期时间
getPriceExpiry(product) {
// 闪购价格优先
if (product.isFlashSale) {
return product.flashSaleEndTime;
}
// 优惠券过期时间
if (this.availableCoupons.length > 0) {
const earliestExpiry = Math.min(...this.availableCoupons.map(c => c.validTo));
if (earliestExpiry) return earliestExpiry;
}
// 默认5分钟缓存过期
return Date.now() + 300000;
}
// 订阅价格更新
subscribeToPriceUpdates(callback) {
this.priceUpdateCallbacks.add(callback);
return () => this.priceUpdateCallbacks.delete(callback);
}
// 通知价格更新
notifyPriceUpdate(priceInfo) {
this.priceUpdateCallbacks.forEach(callback => {
try {
callback(priceInfo);
} catch (error) {
console.warn('Price update callback error:', error);
}
});
}
// 刷新价格缓存
refreshPriceCache(productId) {
// 删除相关缓存
for (const key of this.priceCache.keys()) {
if (key.includes(productId)) {
this.priceCache.delete(key);
}
}
}
// 获取可用优惠券
async loadAvailableCoupons(product) {
try {
const response = await fetch(`/api/coupon/available?productId=${product.id}`);
const data = await response.json();
this.availableCoupons = data.coupons || [];
return this.availableCoupons;
} catch (error) {
console.warn('Failed to load available coupons:', error);
return [];
}
}
}
// 价格展示组件
const VipPriceDisplay = ({ product, quantity = 1, onPriceCalculated }) => {
const [priceInfo, setPriceInfo] = useState(null);
const [isCalculating, setIsCalculating] = useState(false);
const [selectedCoupons, setSelectedCoupons] = useState([]);
const priceSystem = useRef(new VipPriceSystem());
// 计算价格
const calculatePrice = useCallback(async () => {
setIsCalculating(true);
try {
const coupons = await priceSystem.current.loadAvailableCoupons(product);
const result = await priceSystem.current.calculateMemberPrice(product, {
quantity,
couponIds: selectedCoupons,
memberLevel: priceSystem.current.memberLevel
});
setPriceInfo(result);
onPriceCalculated?.(result);
} catch (error) {
console.error('Price calculation failed:', error);
} finally {
setIsCalculating(false);
}
}, [product, quantity, selectedCoupons]);
// 初始计算
useEffect(() => {
calculatePrice();
}, [calculatePrice]);
// 订阅价格更新
useEffect(() => {
const unsubscribe = priceSystem.current.subscribeToPriceUpdates((newPriceInfo) => {
setPriceInfo(newPriceInfo);
});
return unsubscribe;
}, []);
// 处理优惠券选择
const handleCouponToggle = (couponId) => {
setSelectedCoupons(prev => {
if (prev.includes(couponId)) {
return prev.filter(id => id !== couponId);
}
return [...prev, couponId];
});
};
if (!priceInfo) {
return (
<div className="vip-price-loading">
<div className="loading-spinner"></div>
<span>计算最优价格中...</span>
</div>
);
}
return (
<div className="vip-price-display">
{/* 原价 */}
<div className="original-price-section">
<span className="original-price">¥{priceInfo.originalPrice.toFixed(2)}</span>
{priceInfo.totalDiscount > 0 && (
<span className="original-label">原价</span>
)}
</div>
{/* 会员专享价 */}
<div className="member-price-section">
<div className="member-badge">
{priceSystem.current.memberLevel === 'diamond' && '💎 钻石会员'}
{priceSystem.current.memberLevel === 'platinum' && '🥈 铂金会员'}
{priceSystem.current.memberLevel === 'gold' && '🥇 金牌会员'}
{priceSystem.current.memberLevel === 'silver' && '🥉 银牌会员'}
{priceSystem.current.memberLevel === 'normal' && '👤 普通会员'}
</div>
<div className="final-price">
<span className="currency">¥</span>
<span className="amount">{priceInfo.finalPrice.toFixed(2)}</span>
<span className="unit">/{quantity > 1 ? `${quantity}件` : '件'}</span>
</div>
</div>
{/* 折扣信息 */}
{priceInfo.totalDiscount > 0 && (
<div className="discount-info">
<span className="discount-rate">省{priceInfo.discountRate}%</span>
<span className="savings-amount">省¥{priceInfo.totalDiscount.toFixed(2)}</span>
</div>
)}
{/* 价格明细 */}
<div className="price-breakdown">
<h4>💰 优惠明细</h4>
{priceInfo.priceBreakdown.map((item, index) => (
<div key={index} className="breakdown-item">
<span className="description">{item.description}</span>
<span className="amount">
{item.amount > 0 ? '-' : '+'}¥{item.amount.toFixed(2)}
</span>
</div>
))}
</div>
{/* 优惠券选择 */}
{priceSystem.current.availableCoupons.length > 0 && (
<div className="coupon-section">
<h4>🎫 可用优惠券</h4>
<div className="coupon-list">
{priceSystem.current.availableCoupons.map(coupon => (
<div
key={coupon.id}
className={`coupon-item ${selectedCoupons.includes(coupon.id) ? 'selected' : ''} ${!priceSystem.current.isCouponApplicable(coupon, product) ? 'disabled' : ''}`}
onClick={() => priceSystem.current.isCouponApplicable(coupon, product) && handleCouponToggle(coupon.id)}
>
<div className="coupon-value">
{coupon.discountType === 'fixed' ? `¥${coupon.discountValue}` : `${coupon.discountValue}%OFF`}
</div>
<div className="coupon-info">
<span className="coupon-name">{coupon.name}</span>
<span className="coupon-condition">满{coupon.minPurchase}可用</span>
<span className="coupon-expiry">有效期至{new Date(coupon.validTo).toLocaleDateString()}</span>
</div>
{selectedCoupons.includes(coupon.id) && <span className="check-mark">✓</span>}
</div>
))}
</div>
</div>
)}
{/* 节省提示 */}
{priceInfo.savings.amount > 0 && (
<div className="savings-message">
<span className="savings-icon">💝</span>
<span>{priceInfo.savings.levelMessage}</span>
<span className="total-savings">本次共节省¥{priceInfo.savings.amount.toFixed(2)}</span>
</div>
)}
{/* 价格倒计时 */}
<div className="price-countdown">
<span className="countdown-icon">⏰</span>
<span>此价格将在</span>
<span className="countdown-time">{new Date(priceInfo.expiresAt).toLocaleTimeString()}</span>
<span>后失效</span>
</div>
{/* 加载状态 */}
{isCalculating && (
<div className="calculating-overlay">
<div className="mini-spinner"></div>
<span>更新最优价格...</span>
</div>
)}
</div>
);
};
export default VipPriceDisplay;五、性能监控与业务指标
5.1 唯品会专属性能监控
// 唯品会商品详情页性能监控系统
class VipPerformanceMonitor {
static metrics = {
// 品牌图片相关
BRAND_IMAGE_LOAD_TIME: 'vip_brand_image_load_time',
LOGO_CLARITY_SCORE: 'vip_logo_clarity_score',
BRAND_COLOR_ACCURACY: 'vip_brand_color_accuracy',
TEXTURE_PRESERVATION: 'vip_texture_preservation',
// 尺码助手相关
SIZE_ASSISTANT_LOAD_TIME: 'vip_size_assistant_load_time',
SIZE_RECOMMENDATION_TIME: 'vip_size_recommendation_time',
MEASUREMENT_INPUT_RESPONSE: 'vip_measurement_input_response',
// 会员价格相关
MEMBER_PRICE_CALCULATION_TIME: 'vip_member_price_calc_time',
COUPON_MATCHING_TIME: 'vip_coupon_matching_time',
FLASH_SALE_PRICE_SYNC: 'vip_flash_sale_price_sync',
// 个性化推荐
SAME_BRAND_RECOMMENDATION_TIME: 'vip_same_brand_rec_time',
BRAND_AFFINITY_CALCULATION: 'vip_brand_affinity_calc',
STYLE_BASED_RECOMMENDATION: 'vip_style_based_rec',
// 用户体验
VIP_LCP: 'vip_lcp',
INTERACTION_READINESS: 'vip_interaction_readiness',
MEMBER_PRICE_DISPLAY_TIME: 'vip_member_price_display_time',
// 业务指标
MEMBER_CONVERSION_LIFT: 'vip_member_conversion_lift',
SIZE_SELECTION_SUCCESS: 'vip_size_selection_success',
BRAND_LOYALTY_ENGAGEMENT: 'vip_brand_loyalty_engagement',
FLASH_SALE_CONVERSION: 'vip_flash_sale_conversion',
COUPON_USAGE_RATE: 'vip_coupon_usage_rate'
};
constructor() {
this.sessionId = this.generateSessionId();
this.userId = window.vipUserId || 'anonymous';
this.productId = window.vipProductId || 'unknown';
this.memberLevel = this.getMemberLevel();
this.startTime = Date.now();
this.initializeMonitoring();
}
generateSessionId() {
return `vip_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
}
getMemberLevel() {
try {
const userInfo = JSON.parse(localStorage.getItem('vip_user_info') || '{}');
return userInfo.memberLevel || 'normal';
} catch {
return 'normal';
}
}
initializeMonitoring() {
// 监听页面可见性变化
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
this.reportMetric(VipPerformanceMonitor.metrics.INTERACTION_READINESS,
Date.now() - this.startTime, { state: 'hidden', memberLevel: this.memberLevel });
}
});
// 监听网络变化
if (navigator.connection) {
navigator.connection.addEventListener('change', () => {
this.reportNetworkChange();
});
}
// 监听价格计算
this.trackPriceCalculations();
// 监听尺码选择
this.trackSizeSelection();
// 监听品牌互动
this.trackBrandInteractions();
// 监听闪购活动
this.trackFlashSaleActivity();
}
// 品牌图片加载监控
measureBrandImageLoad(imageUrl, imageType = 'brand', brandType = 'fashion', isLogo = false) {
const start = performance.now();
return {
end: () => {
const duration = performance.now() - start;
const clarityScore = this.assessBrandClarity(imageUrl, isLogo);
const colorAccuracy = this.assessColorAccuracy(imageUrl, brandType);
this.reportMetric(
VipPerformanceMonitor.metrics.BRAND_IMAGE_LOAD_TIME,
duration,
{
imageType,
brandType,
isLogo,
clarityScore,
colorAccuracy,
networkType: navigator.connection?.effectiveType || 'unknown',
deviceType: this.getDeviceType(),
pixelRatio: window.devicePixelRatio || 1,
memberLevel: this.memberLevel
}
);
}
};
}
// 评估品牌图片清晰度
assessBrandClarity(imageUrl, isLogo) {
// 基于URL参数和图片类型评估清晰度
const qualityMatch = imageUrl.match(/_q(\d+)/);
const baseQuality = qualityMatch ? parseInt(qualityMatch[1]) : 85;
// Logo需要更高清晰度
const logoMultiplier = isLogo ? 1.2 : 1.0;
const clarityScore = Math.min(baseQuality * logoMultiplier, 100);
return clarityScore;
}
// 评估品牌色彩准确度
assessColorAccuracy(imageUrl, brandType) {
// 基于品牌类型评估色彩准确度要求
const brandAccuracyRequirements = {
'luxury': 98,
'beauty': 95,
'sports': 92,
'home': 90,
'kids': 88,
'fashion': 85
};
const requirement = brandAccuracyRequirements[brandType] || 85;
const actualQuality = this.extractQualityFromUrl(imageUrl);
return Math.min((actualQuality / requirement) * 100, 100);
}
extractQualityFromUrl(imageUrl) {
const qualityMatch = imageUrl.match(/_q(\d+)/);
return qualityMatch ? parseInt(qualityMatch[1]) : 85;
}
// 尺码助手性能监控
measureSizeAssistantLoad() {
const start = performance.now();
return {
end: () => {
const duration = performance.now() - start;
this.reportMetric(
VipPerformanceMonitor.metrics.SIZE_ASSISTANT_LOAD_TIME,
duration,
{
deviceType: this.getDeviceType(),
memberLevel: this.memberLevel,
hasUserMeasurements: !!window.userMeasurements
}
);
}
};
}
// 尺码推荐性能监控
measureSizeRecommendation(method = 'height_weight') {
const start = performance.now();
return {
end: (result) => {
const duration = performance.now() - start;
const accuracy = this.calculateSizeAccuracy(result);
this.reportMetric(
VipPerformanceMonitor.metrics.SIZE_RECOMMENDATION_TIME,
duration,
{
method,
result,
accuracy,
memberLevel: this.memberLevel
}
);
}
};
}
calculateSizeAccuracy(recommendedSize) {
// 基于用户反馈和历史数据计算推荐准确度
// 简化实现
return recommendedSize ? 85 : 0;
}
// 会员价格计算监控
measureMemberPriceCalculation(options = {}) {
const start = performance.now();
return {
end: (priceInfo) => {
const duration = performance.now() - start;
const savingsGenerated = priceInfo?.totalDiscount || 0;
this.reportMetric(
VipPerformanceMonitor.metrics.MEMBER_PRICE_CALCULATION_TIME,
duration,
{
memberLevel: options.memberLevel || this.memberLevel,
couponCount: options.couponIds?.length || 0,
flashSaleEnabled: options.includeFlashSale || false,
savingsGenerated,
priceBreakdown: priceInfo?.priceBreakdown?.length || 0
}
);
}
};
}
// 优惠券匹配监控
measureCouponMatching(product, couponIds) {
const start = performance.now();
return {
end: (matchedCoupons) => {
const duration = performance.now() - start;
const matchRate = matchedCoupons.length / couponIds.length;
this.reportMetric(
VipPerformanceMonitor.metrics.COUPON_MATCHING_TIME,
duration,
{
totalCoupons: couponIds.length,
matchedCoupons: matchedCoupons.length,
matchRate,
memberLevel: this.memberLevel
}
);
}
};
}
// 闪购价格同步监控
measureFlashSalePriceSync(product) {
const start = performance.now();
return {
end: (syncResult) => {
const duration = performance.now() - start;
const priceChange = syncResult?.priceChange || 0;
const urgencyLevel = syncResult?.urgencyLevel || 'unknown';
this.reportMetric(
VipPerformanceMonitor.metrics.FLASH_SALE_PRICE_SYNC,
duration,
{
productId: product.id,
priceChange,
urgencyLevel,
memberLevel: this.memberLevel
}
);
}
};
}
// 个性化推荐监控
measurePersonalizedRecommendation(type = 'same_brand') {
const start = performance.now();
return {
end: (results) => {
const duration = performance.now() - start;
const resultCount = results?.length || 0;
const avgScore = results?.reduce((sum, r) => sum + (r.recommendationScore || 0), 0) / resultCount || 0;
const metricMap = {
'same_brand': VipPerformanceMonitor.metrics.SAME_BRAND_RECOMMENDATION_TIME,
'brand_affinity': VipPerformanceMonitor.metrics.BRAND_AFFINITY_CALCULATION,
'style_based': VipPerformanceMonitor.metrics.STYLE_BASED_RECOMMENDATION
};
this.reportMetric(
metricMap[type] || VipPerformanceMonitor.metrics.SAME_BRAND_RECOMMENDATION_TIME,
duration,
{
type,
resultCount,
avgScore,
memberLevel: this.memberLevel
}
);
}
};
}
// 价格计算追踪
trackPriceCalculations() {
window.addEventListener('vipPriceCalculated', (e) => {
const { duration, memberLevel, savingsGenerated } = e.detail;
this.reportMetric(
VipPerformanceMonitor.metrics.MEMBER_PRICE_CALCULATION_TIME,
duration,
{
memberLevel,
savingsGenerated,
timestamp: Date.now()
}
);
});
}
// 尺码选择追踪
trackSizeSelection() {
window.addEventListener('vipSizeSelected', (e) => {
const { selectedSize, recommendedSize, measurementMethod, accuracy } = e.detail;
this.reportMetric(
VipPerformanceMonitor.metrics.SIZE_SELECTION_SUCCESS,
1,
{
selectedSize,
wasRecommended: selectedSize === recommendedSize,
measurementMethod,
accuracy,
memberLevel: this.memberLevel
}
);
});
}
// 品牌互动追踪
trackBrandInteractions() {
window.addEventListener('vipBrandInteraction', (e) => {
const { brandId, interactionType, duration } = e.detail;
this.reportMetric(
VipPerformanceMonitor.metrics.BRAND_LOYALTY_ENGAGEMENT,
1,
{
brandId,
interactionType,
duration,
memberLevel: this.memberLevel
}
);
});
}
// 闪购活动追踪
trackFlashSaleActivity() {
window.addEventListener('vipFlashSaleConversion', (e) => {
const { productId, originalPrice, finalPrice, memberLevel } = e.detail;
this.reportMetric(
VipPerformanceMonitor.metrics.FLASH_SALE_CONVERSION,
1,
{
productId,
savings: originalPrice - finalPrice,
memberLevel: memberLevel || this.memberLevel
}
);
});
}
// 网络变化报告
reportNetworkChange() {
this.reportMetric(
'vip_network_change',
1,
{
newType: navigator.connection?.effectiveType || 'unknown',
downlink: navigator.connection?.downlink || 0,
rtt: navigator.connection?.rtt || 0,
deviceType: this.getDeviceType(),
memberLevel: this.memberLevel
}
);
}
// 报告指标
reportMetric(metricName, value, tags = {}) {
const payload = {
metric_name: metricName,
metric_value: value,
timestamp: Date.now(),
session_id: this.sessionId,
user_id: this.userId,
product_id: this.productId,
member_level: this.memberLevel,
page: window.location.pathname,
user_agent: navigator.userAgent,
device_type: this.getDeviceType(),
network_type: navigator.connection?.effectiveType || 'unknown',
country: this.detectCountry(),
language: navigator.language,
referrer: document.referrer,
...tags
};
// 使用Beacon API上报
if (navigator.sendBeacon) {
const blob = new Blob([JSON.stringify(payload)], { type: 'application/json' });
navigator.sendBeacon('/api/metrics/vip-performance', blob);
} else {
fetch('/api/metrics/vip-performance', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
keepalive: true
}).catch(err => console.warn('Vip metrics report failed:', err));
}
}
// 辅助方法
getDeviceType() {
const ua = navigator.userAgent;
if (/tablet|ipad/i.test(ua)) return 'tablet';
if (/mobile|iphone|android/i.test(ua)) return 'mobile';
return 'desktop';
}
detectCountry() {
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const language = navigator.language;
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
if (timezone.includes('Asia/Shanghai') || language.startsWith('zh')) {
return 'CN';
}
if (timezone.includes('America/')) {
return 'US';
}
if (timezone.includes('Europe/')) {
return 'EU';
}
return 'OTHER';
}
}
// 初始化监控
const vipMonitor = new VipPerformanceMonitor();
window.vipMonitor = vipMonitor;六、优化效果
指标 | 优化前 | 优化后 | 提升幅度 |
|---|---|---|---|
首屏加载时间 | 7.2s | 2.1s | 71% |
首屏可交互时间 | 5.1s | 1.4s | 73% |
品牌图片总体积 | 92MB | 19MB | 79% |
尺码助手加载时间 | 2.8s | 0.6s | 79% |
会员价格计算时间 | 1.5s | 0.2s | 87% |
品牌故事视频加载 | 4s | 1.2s | 70% |
LCP(最大内容绘制) | 5.8s | 1.8s | 69% |
CLS(累积布局偏移) | 0.32 | 0.09 | 72% |
移动端转化率 | 1.8% | 3.2% | 78% |
页面跳出率 | 58% | 24% | 59% |
闪购商品流失率 | 35% | 12% | 66% |
会员专享转化提升 | - | 45% | 新增指标 |
尺码选择成功率 | - | 89% | 新增指标 |
品牌复购率 | - | 23% | 新增指标 |
七、核心经验总结
7.1 唯品会特色优化要点
- 品牌图片质量是核心竞争力
- 品牌Logo和标识需要超高清展示,不能有任何模糊
- 不同品牌类型(奢侈、美妆、运动、家居、童装)需要不同的图片处理参数
- 色彩准确度对品牌展示至关重要,特别是奢侈品和化妆品
- 渐进式加载从品牌轮廓到超清大图,保持品牌调性
- 尺码助手是女性用户的关键功能
- 提供多种测量方式:身高体重快速估算、手动精确输入、历史购买参考
- 智能推荐算法结合用户历史数据和品牌尺码特性
- 实时显示库存状态,低库存时突出显示
- 与用户账户关联,记住个人尺码偏好
- 会员专享价体系复杂但关键
- 多层级会员折扣(普通、银牌、金牌、铂金、钻石)
- 优惠券、积分、闪购、套装等多种优惠叠加计算
- 实时价格更新,确保用户看到最优价格
- 价格明细透明,增加用户信任度
- 品牌忠诚度的培养
- 同品牌推荐是核心策略,提高品牌复购率
- 品牌故事和文化内容的展示
- 品牌亲和力追踪,个性化品牌推荐
- 会员等级与品牌特权的结合
- 闪购模式的紧迫感设计
- 实时库存和倒计时显示
- 价格同步更新,确保用户不错过优惠
- 闪购商品优先推荐和展示
- 低库存预警和补货提醒
7.2 技术架构亮点
- 品牌图片智能处理引擎
- 基于品牌类型的图片处理参数自动选择
- Logo增强、色彩保护、纹理保留等专业处理
- 多CDN节点智能路由,根据时间和地域优化
- 闪购模式下的特殊优化策略
- 个性化推荐的多策略融合
- 同品牌推荐、相似风格、闪购推荐、尺码匹配等多策略并行
- 品牌亲和力追踪和动态权重调整
- 冷启动用户的新人引导推荐
- 实时推荐结果更新和缓存
- 复杂价格计算系统
- 多层级会员折扣计算
- 优惠券匹配和叠加逻辑
- 积分抵扣和套装优惠
- 实时价格同步和缓存管理
- 性能监控的业务导向
- 针对品牌特卖和女性用户的行为指标
- 会员转化、品牌忠诚、尺码选择等业务指标
- 闪购活动的实时监控
- 用户体验和性能的平衡优化
7.3 业务价值体现
通过这套针对唯品会品牌特卖模式的优化方案,商品详情页实现了显著的性能提升和业务价值:
- 用户体验全面改善:跳出率从58%降到24%,用户停留时间增加45%
- 转化效率大幅提升:移动端转化率从1.8%提升到3.2%,接近行业优秀水平
- 会员价值凸显:会员专享转化提升45%,品牌复购率提升23%
- 闪购业务成功:闪购商品流失率从35%降到12%,成为新的增长引擎
- 运营成本优化:通过智能缓存和预加载,服务器负载降低40%
- 品牌价值提升:品牌故事和调性展示更加突出,用户品牌认知度提升
这套优化方案充分结合了唯品会作为品牌特卖平台的特点,在保持品牌调性的同时实现了极致的技术性能,为平台在激烈的特卖电商竞争中建立了明显优势。
需要我深入讲解品牌图片智能处理算法的实现细节,或者多策略推荐系统的权重调优方法吗?