PageSourceSearch

https://www.svbony.com/businessJs/Product/Index/priceDisplay_Index_t120.js?v=006

js svbony.com collected 2026-10-03 19:02:58 UTC 10,335 bytes, 260 lines download raw bytes

1/**
2 * 产品列表页价格显示功能模块 - t120主题专用
3 * 用于处理产品列表页面中产品价格的显示逻辑,包括促销价、原价和折扣计算
4 * 
5 * 功能包括:
6 * - HTML实体解码
7 * - 价格字符串数值提取
8 * - 产品列表价格显示初始化
9 * - 折扣计算和显示
10 * - 批量处理多个产品的价格显示
11 */
12(function() {
13    'use strict';
14
15    // 确保价格工具已加载
16    if (typeof window.PriceUtils === 'undefined') {
17        return;
18    }
19
20    /**
21     * 获取价格展示配置
22     * @returns {Object} 价格展示配置对象
23     */
24    function getPriceDisplayConfig() {
25        return window.PriceDisplayConfig || {
26            DisplayOrder: 'original,promotion,discount_amount,discount_percent',
27            ShowOriginalPrice: true,
28            ShowPromotionPrice: true,
29            ShowDiscountAmount: true,
30            ShowDiscountPercent: true,
31            ShowStrikethrough: true,
32            OriginalPriceFontSize: '16',
33            OriginalPriceColor: '#999999',
34            PromotionPriceFontSize: '24',
35            PromotionPriceColor: '#ff0000',
36            DiscountAmountFontSize: '14',
37            DiscountAmountColor: '#ff6600',
38            DiscountPercentFontSize: '14',
39            DiscountPercentColor: '#ff6600'
40        };
41    }
42
43    /**
44     * 禁用产品的加购和Buy Now按钮
45     * @param {HTMLElement} productElement - 产品元素
46     */
47    function disableCartButtons(productElement) {
48        const addToCartBtn = productElement.querySelector('.btn-addto-cart');
49        const buyNowBtn = productElement.querySelector('.btn-buy-now');
50        
51        if (addToCartBtn) {
52            addToCartBtn.classList.add('disabled');
53            addToCartBtn.style.pointerEvents = 'none';
54            addToCartBtn.style.opacity = '0.5';
55            addToCartBtn.setAttribute('disabled', 'disabled');
56        }
57        
58        if (buyNowBtn) {
59            buyNowBtn.classList.add('disabled');
60            buyNowBtn.style.pointerEvents = 'none';
61            buyNowBtn.style.opacity = '0.5';
62            buyNowBtn.setAttribute('disabled', 'disabled');
63        }
64    }
65
66    /**
67     * 为单个产品初始化价格显示
68     * @param {HTMLElement} productElement - 产品元素
69     */
70    function initializeProductPriceDisplay(productElement) {
71        const priceContainerWithData = productElement.querySelector('.product-price[data-price-container]');
72        const basicPriceContainer = productElement.querySelector('.product-price');
73        
74        if (priceContainerWithData) {
75            // 处理带有完整价格数据的容器(Shop页面)
76            initializeDataPriceContainer(priceContainerWithData);
77        } else if (basicPriceContainer) {
78            // 处理基本价格容器(首页和其他页面)
79            initializeBasicPriceContainer(basicPriceContainer);
80        }
81    }
82
83    /**
84     * 处理带有data-price-container的价格容器
85     * @param {HTMLElement} priceContainer - 价格容器
86     */
87    function initializeDataPriceContainer(priceContainer) {
88        const originalPriceStr = priceContainer.getAttribute('data-original-price');
89        const currentPriceStr = priceContainer.getAttribute('data-current-price');
90        const promotionPriceStr = priceContainer.getAttribute('data-promotion-price');
91
92        const originalPrice = window.PriceUtils.extractPriceValue(originalPriceStr);
93        const currentPrice = window.PriceUtils.extractPriceValue(currentPriceStr);
94        const promotionPrice = window.PriceUtils.extractPriceValue(promotionPriceStr);
95
96        const config = getPriceDisplayConfig();
97        
98        // 准备价格项数据
99        const priceItems = {};
100        
101        // 原价(划线价)- 只有当原价大于促销价或当前价时才显示
102        const effectivePrice = promotionPrice > 0 ? promotionPrice : currentPrice;
103        if (config.ShowOriginalPrice && originalPrice > 0 && originalPrice > effectivePrice) {
104            const strikethroughStyle = config.ShowStrikethrough ? 'text-decoration: line-through !important;' : 'text-decoration: none !important;';
105            priceItems.original = {
106                html: `<del class="price-old" style="font-size: ${config.OriginalPriceFontSize}px; color: ${config.OriginalPriceColor}; ${strikethroughStyle}">${originalPriceStr}</del>`,
107                order: 0
108            };
109        }
110        
111        // 促销价或当前价
112        if (config.ShowPromotionPrice) {
113            // 如果促销价或当前价为0,显示"价格即将公布"
114            let displayPrice = promotionPrice > 0 ? promotionPriceStr : currentPriceStr;
115            if (effectivePrice <= 0) {
116                displayPrice = config.PricingRevealedSoonText || 'Pricing Revealed Soon';
117            }
118            priceItems.promotion = {
119                html: `<span class="price-current" style="font-size: ${config.PromotionPriceFontSize}px; color: ${config.PromotionPriceColor};">${displayPrice}</span>`,
120                order: 1
121            };
122        }
123        
124        // 根据配置的显示顺序排序
125        const displayOrder = config.DisplayOrder.split(',');
126        const sortedItems = [];
127        
128        displayOrder.forEach((key, index) => {
129            if (priceItems[key]) {
130                priceItems[key].order = index;
131                sortedItems.push(priceItems[key]);
132            }
133        });
134        
135        // 生成HTML
136        const html = sortedItems.map(item => item.html).join(' ');
137        priceContainer.innerHTML = html || `<span class="price-current">${currentPriceStr}</span>`;
138        
139        // 如果有效价格为0,禁用加购和Buy Now按钮
140        if (effectivePrice <= 0) {
141            const productElement = priceContainer.closest('.product-card') || priceContainer.closest('.item') || priceContainer.closest('.product');
142            if (productElement) {
143                disableCartButtons(productElement);
144            }
145        }
146    }
147
148    /**
149     * 处理基本价格容器(首页等)
150     * @param {HTMLElement} priceContainer - 价格容器
151     */
152    function initializeBasicPriceContainer(priceContainer) {
153        const currentPriceElement = priceContainer.querySelector('.price-current, .price');
154        const oldPriceElement = priceContainer.querySelector('.price-old, .old-price');
155
156        if (!currentPriceElement) return;
157
158        const config = getPriceDisplayConfig();
159        
160        // 应用配置样式
161        if (config && config.ShowPromotionPrice) {
162            currentPriceElement.style.fontSize = config.PromotionPriceFontSize + 'px';
163            currentPriceElement.style.color = config.PromotionPriceColor;
164        }
165
166        if (oldPriceElement && config && config.ShowOriginalPrice) {
167            oldPriceElement.style.fontSize = config.OriginalPriceFontSize + 'px';
168            oldPriceElement.style.color = config.OriginalPriceColor;
169        }
170    }
171
172    /**
173     * 初始化所有产品的价格显示
174     */
175    function initializeAllProductsPriceDisplay() {
176        const productSelectors = [
177            '.product-card',
178            '.item',
179            '.product-item',
180            '.product',
181            'td.item-row'                              // ProductCompare页面的产品行
182        ];
183        
184        productSelectors.forEach(selector => {
185            const productElements = document.querySelectorAll(selector);
186            productElements.forEach(productElement => {
187                if (productElement.querySelector('.product-price')) {
188                    initializeProductPriceDisplay(productElement);
189                }
190            });
191        });
192    }
193
194    /**
195     * 观察DOM变化,处理动态加载的产品
196     */
197    function observeProductChanges() {
198        const observer = new MutationObserver(function(mutations) {
199            mutations.forEach(function(mutation) {
200                if (mutation.type === 'childList') {
201                    mutation.addedNodes.forEach(function(node) {
202                        if (node.nodeType === Node.ELEMENT_NODE) {
203                            // 检查新添加的节点是否是产品元素或包含产品元素
204                            if (node.classList && node.classList.contains('product-card')) {
205                                initializeProductPriceDisplay(node);
206                            } else {
207                                // 查找新添加节点内的产品元素
208                                const productElements = node.querySelectorAll && node.querySelectorAll('.product-card');
209                                if (productElements) {
210                                    productElements.forEach(productElement => {
211                                        initializeProductPriceDisplay(productElement);
212                                    });
213                                }
214                            }
215                        }
216                    });
217                }
218            });
219        });
220
221        // 开始观察产品列表容器 - t120主题使用.product-grid作为产品列表容器
222        const productContainer = document.querySelector('.product-grid');
223        if (productContainer) {
224            observer.observe(productContainer, {
225                childList: true,
226                subtree: true
227            });
228        }
229    }
230
231    /**
232     * 初始化函数
233     */
234    function init() {
235        // DOM加载完成后初始化价格显示
236        if (document.readyState === 'loading') {
237            document.addEventListener('DOMContentLoaded', function() {
238                initializeAllProductsPriceDisplay();
239                observeProductChanges();
240            });
241        } else {
242            // DOM已经加载完成,直接执行
243            initializeAllProductsPriceDisplay();
244            observeProductChanges();
245        }
246    }
247
248    // 将函数暴露到全局作用域,以便外部调用
249    window.PriceDisplayIndexT120 = {
250        initializeProductPriceDisplay: initializeProductPriceDisplay,
251        initializeAllProductsPriceDisplay: initializeAllProductsPriceDisplay,
252        initializeDataPriceContainer: initializeDataPriceContainer,
253        initializeBasicPriceContainer: initializeBasicPriceContainer,
254        init: init
255    };
256
257    // 自动初始化
258    init();
259
260}
vendor: 5 bytes, line 260
260)();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.