Greasy Fork

Greasy Fork is available in English.

亚马逊评论计算优化版(Enhanced Amazon Review Calculator)

精确计算各星级评价数量及提升评分所需五星好评数,支持全球亚马逊站点

当前为 2025-04-07 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         亚马逊评论计算优化版(Enhanced Amazon Review Calculator)
// @namespace    https://github.com/monty8800/amazon-seller-tools
// @version      3.3
// @description  精确计算各星级评价数量及提升评分所需五星好评数,支持全球亚马逊站点
// @author       Monty & Assistant
// @match        *://*.amazon.com/*dp/*
// @match        *://*.amazon.co.uk/*dp/*
// @match        *://*.amazon.de/*dp/*
// @match        *://*.amazon.fr/*dp/*
// @match        *://*.amazon.it/*dp/*
// @match        *://*.amazon.es/*dp/*
// @match        *://*.amazon.co.jp/*dp/*
// @match        *://*.amazon.ca/*dp/*
// @match        *://*.amazon.com.au/*dp/*
// @match        *://*.amazon.in/*dp/*
// @match        *://*.amazon.com.mx/*dp/*
// @match        *://*.amazon.com.br/*dp/*
// @match        *://*.amazon.nl/*dp/*
// @match        *://*.amazon.cn/*dp/*
// @match        *://*.amazon.sg/*dp/*
// @match        *://*.amazon.ae/*dp/*
// @match        *://*.amazon.sa/*dp/*
// @match        *://*.amzn.*/*dp/*
// @icon         https://www.amazon.com/favicon.ico
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

GM_addStyle(`
.monty-review-box {
    border: 1px solid #ddd;
    padding: 12px;
    margin: 10px 0;
    background: #f8f8f8;
    border-radius: 4px;
}
.monty-review-title {
    font-weight: bold;
    color: #111;
    margin-bottom: 8px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.monty-review-item {
    margin: 4px 0;
    font-size: 13px;
}
.monty-highlight {
    color: #B12704;
    font-weight: bold;
}
.monty-lang-selector {
    font-size: 12px;
    padding: 2px 5px;
    border: 1px solid #ddd;
    border-radius: 3px;
    background: white;
    cursor: pointer;
}
.monty-lang-selector:hover {
    border-color: #aaa;
}
`);

(function() {
    'use strict';

    const TARGET_SCORE = 4.3;
    const DEBUG_MODE = true; // 生产环境中关闭调试模式
    
    // 日志输出函数
    function log(...args) {
        if (DEBUG_MODE) {
            console.log('[Review Calculator]', ...args);
        }
    }

    // 获取用户语言偏好
    function getUserLanguage() {
        // 获取用户保存的语言偏好,默认为中文
        const savedLanguage = GM_getValue('user_language', 'zh');
        log('用户语言偏好:', savedLanguage);
        return savedLanguage;
    }
    
    // 设置用户语言偏好
    function setUserLanguage(language) {
        log('设置用户语言偏好:', language);
        GM_setValue('user_language', language);
    }
    
    // 获取本地化文本
    function getLocalizedText() {
        // 优先使用用户选择的语言
        const userLanguage = getUserLanguage();
        
        // 如果没有用户选择的语言,则根据域名自动检测
        if (!userLanguage || userLanguage === 'auto') {
            const domain = window.location.hostname;
            log('当前域名:', domain);
            
            // 根据域名确定语言
            let detectedLanguage = 'en'; // 默认英语
            
            if (domain.includes('.fr')) detectedLanguage = 'fr';
            else if (domain.includes('.de')) detectedLanguage = 'de';
            else if (domain.includes('.it')) detectedLanguage = 'it';
            else if (domain.includes('.es')) detectedLanguage = 'es';
            else if (domain.includes('.co.jp') || domain.includes('.jp')) detectedLanguage = 'jp';
            else if (domain.includes('.cn')) detectedLanguage = 'zh';
            else if (domain.includes('.nl')) detectedLanguage = 'nl';
            else if (domain.includes('.com.br')) detectedLanguage = 'pt-br';
            else if (domain.includes('.com.mx')) detectedLanguage = 'es-mx';
            else if (domain.includes('.in')) detectedLanguage = 'en-in';
            else if (domain.includes('.ca')) detectedLanguage = domain.includes('/fr/') ? 'fr-ca' : 'en-ca';
            
            log('检测到语言:', detectedLanguage);
            return getLocalizedTextByLanguage(detectedLanguage);
        }
        
        return getLocalizedTextByLanguage(userLanguage);
    }
    
    // 根据指定语言获取本地化文本
    function getLocalizedTextByLanguage(language) {
        log('使用语言:', language);
        
        // 各种语言的本地化文本
        const localizedTexts = {
            // 评论数文本
            ratingsText: {
                'en': 'ratings',
                'fr': 'évaluations',
                'de': 'Bewertungen',
                'it': 'recensioni',
                'es': 'valoraciones',
                'es-mx': 'calificaciones',
                'jp': '件の評価',
                'zh': '条评论',
                'nl': 'beoordelingen',
                'pt-br': 'avaliações',
                'en-in': 'ratings',
                'en-ca': 'ratings',
                'fr-ca': 'évaluations'
            },
            
            // 星级文本 (用于匹配评分文本)
            starText: {
                'en': 'out of 5 stars',
                'fr': 'sur 5 étoiles',
                'de': 'von 5 Sternen',
                'it': 'su 5 stelle',
                'es': 'de 5 estrellas',
                'es-mx': 'de 5 estrellas',
                'jp': '5つ星のうち',
                'zh': '5 星,最多 5 星',
                'nl': 'van de 5 sterren',
                'pt-br': 'de 5 estrelas',
                'en-in': 'out of 5 stars',
                'en-ca': 'out of 5 stars',
                'fr-ca': 'sur 5 étoiles'
            },
            
            // 结果面板文本
            resultText: {
                'en': {
                    title: '📊 Review Analysis',
                    currentScore: 'Current Rating:',
                    required: 'Need',
                    fiveStarReviews: '5-star reviews',
                    toReach: 'to reach',
                    noNeed: 'Current rating already exceeds',
                    noNeedSuffix: ', no additional reviews needed',
                    simplified: '(Simplified)',
                    note: 'Note: This is a simplified result due to inability to get detailed rating data',
                    error: '⚠️ Review Calculator encountered an issue',
                    errorHelp: 'If the problem persists, try refreshing the page or check for script updates.'
                },
                'fr': {
                    title: '📊 Analyse des Avis',
                    currentScore: 'Note actuelle:',
                    required: 'Besoin de',
                    fiveStarReviews: 'avis 5 étoiles',
                    toReach: 'pour atteindre',
                    noNeed: 'La note actuelle dépasse déjà',
                    noNeedSuffix: ', aucun avis supplémentaire nécessaire',
                    simplified: '(Simplifié)',
                    note: 'Remarque: Il s\'agit d\'un résultat simplifié en raison de l\'impossibilité d\'obtenir des données d\'évaluation détaillées',
                    error: '⚠️ Le calculateur d\'avis a rencontré un problème',
                    errorHelp: 'Si le problème persiste, essayez d\'actualiser la page ou vérifiez les mises à jour du script.'
                },
                'de': {
                    title: '📊 Bewertungsanalyse',
                    currentScore: 'Aktuelle Bewertung:',
                    required: 'Benötigt',
                    fiveStarReviews: '5-Sterne-Bewertungen',
                    toReach: 'um zu erreichen',
                    noNeed: 'Aktuelle Bewertung überschreitet bereits',
                    noNeedSuffix: ', keine zusätzlichen Bewertungen erforderlich',
                    simplified: '(Vereinfacht)',
                    note: 'Hinweis: Dies ist ein vereinfachtes Ergebnis, da detaillierte Bewertungsdaten nicht verfügbar sind',
                    error: '⚠️ Der Bewertungsrechner ist auf ein Problem gestoßen',
                    errorHelp: 'Wenn das Problem weiterhin besteht, aktualisieren Sie die Seite oder prüfen Sie auf Skript-Updates.'
                },
                'zh': {
                    title: '📊 评论分析结果',
                    currentScore: '当前评分:',
                    required: '需要',
                    fiveStarReviews: '个五星好评',
                    toReach: '才能达到',
                    noNeed: '当前评分已超过',
                    noNeedSuffix: ',无需补充好评',
                    simplified: '(简化版)',
                    note: '注意:由于无法获取详细评分数据,此结果为简化版',
                    error: '⚠️ 评论计算器遇到问题',
                    errorHelp: '如果问题持续存在,请尝试刷新页面或检查脚本更新。'
                },
                'jp': {
                    title: '📊 レビュー分析',
                    currentScore: '現在の評価:',
                    required: '',
                    fiveStarReviews: '件の5つ星レビューが必要',
                    toReach: 'で到達するために',
                    noNeed: '現在の評価はすでに',
                    noNeedSuffix: 'を超えています、追加のレビューは必要ありません',
                    simplified: '(簡易版)',
                    note: '注意:詳細な評価データを取得できないため、これは簡易結果です',
                    error: '⚠️ レビュー計算ツールで問題が発生しました',
                    errorHelp: '問題が解決しない場合は、ページを更新するかスクリプトの更新を確認してください。'
                }
                // 可以根据需要添加更多语言
            }
        };
        
        // 如果没有特定语言的翻译,使用英语作为后备
        const getTextWithFallback = (category, lang) => {
            return localizedTexts[category][lang] || localizedTexts[category]['en'];
        };
        
        return {
            ratingsText: getTextWithFallback('ratingsText', language),
            starText: getTextWithFallback('starText', language),
            resultText: localizedTexts.resultText[language] || localizedTexts.resultText['en']
        };
    }

    // 清洗数字格式(处理千位分隔符)
    function sanitizeNumber(numStr) {
        return numStr.replace(/[.,\s]/g, '')
                    .replace(/[^\d]/g, '');
    }

    // 计算加权平均分
    function calculateWeightedAverage(ratings) {
        const total = ratings.reduce((sum, r) => sum + r.count, 0);
        if (total === 0) return 0;

        return ratings.reduce((sum, r) => {
            return sum + (r.stars * r.count);
        }, 0) / total;
    }

    // 计算所需五星好评
    function calculateRequiredReviews(currentScore, totalReviews) {
        if (currentScore >= TARGET_SCORE) return 0;

        const numerator = totalReviews * (TARGET_SCORE - currentScore);
        const denominator = 5 - TARGET_SCORE;
        return Math.ceil(numerator / denominator);
    }

    // 主处理函数
    async function processReviews() {
        try {
            log('开始处理评论数据...');
            log('当前URL:', window.location.href);
            
            // 等待评分直方图加载 - 使用最新的选择器
            log('等待评分直方图加载...');
            const histogram = await waitForElement('#histogramTable');
            if (!histogram) {
                log('错误: 找不到评分直方图');
                throw new Error('找不到评分直方图');
            }
            log('成功找到评分直方图:', histogram);

            // 获取本地化文本
            const localizedText = getLocalizedText();
            log('本地化文本:', localizedText);
            
            // 直接使用data-hook属性查找总评论数
            const totalElement = document.querySelector('[data-hook="total-review-count"]');
            log('总评论数元素:', totalElement);
            
            if (!totalElement) {
                log('错误: 找不到总评论数元素');
                throw new Error('找不到总评论数元素');
            }

            log('总评论数文本:', totalElement.textContent);
            const totalReviews = parseInt(sanitizeNumber(totalElement.textContent));
            log('解析后的总评论数:', totalReviews);
            
            if (isNaN(totalReviews)) {
                log('错误: 总评论数格式错误');
                throw new Error('总评论数格式错误');
            }

            // 获取各星级评价 - 使用最新的选择器
            log('查找评分条...');
            const ratingBars = [...document.querySelectorAll('#histogramTable li a')];
            log('找到评分条数量:', ratingBars.length);
            
            if (ratingBars.length !== 5) {
                log('错误: 找不到完整的五星评价数据, 只找到', ratingBars.length, '条');
                throw new Error('找不到完整的五星评价数据');
            }

            log('开始提取各星级评价数据...');
            const ratings = ratingBars.map((bar, index) => {
                // 获取星级 (5星到1星)
                const stars = 5 - index;
                log(`处理 ${stars} 星评价...`);
                
                // 获取百分比 - 从aria-valuenow属性获取
                let percent = 0;
                const meter = bar.querySelector('.a-meter');
                log(`${stars}星评价条元素:`, meter);
                
                if (meter && meter.getAttribute('aria-valuenow')) {
                    percent = parseInt(meter.getAttribute('aria-valuenow')) / 100;
                    log(`${stars}星评价 - 从aria-valuenow获取百分比:`, percent);
                }
                
                // 如果无法从aria-valuenow获取,尝试从style.width获取
                if (percent === 0 && meter && meter.querySelector('.a-meter-bar')) {
                    const meterBar = meter.querySelector('.a-meter-bar');
                    const widthStyle = meterBar.style.width;
                    log(`${stars}星评价 - meter-bar宽度样式:`, widthStyle);
                    
                    if (widthStyle) {
                        percent = parseInt(widthStyle) / 100;
                        log(`${stars}星评价 - 从style.width获取百分比:`, percent);
                    }
                }
                
                // 如果仍然无法获取百分比,尝试从文本中提取
                if (percent === 0) {
                    log(`${stars}星评价 - 尝试从文本提取百分比...`);
                    const percentTexts = bar.querySelectorAll('.a-text-right, .aok-nowrap');
                    log(`${stars}星评价 - 找到可能包含百分比的文本元素:`, percentTexts.length);
                    
                    for (const el of percentTexts) {
                        log(`${stars}星评价 - 文本内容:`, el.textContent);
                        const percentMatch = el.textContent.match(/(\d+)%/);
                        if (percentMatch) {
                            percent = parseInt(percentMatch[1]) / 100;
                            log(`${stars}星评价 - 从文本提取的百分比:`, percent);
                            break;
                        }
                    }
                }
                
                const count = Math.round(totalReviews * percent);
                log(`${stars}星评价 - 最终数据:`, { stars, percent, count });
                
                return {
                    stars: stars,
                    percent: percent,
                    count: count
                };
            });

            // 计算当前评分
            log('计算加权平均分...');
            const currentScore = calculateWeightedAverage(ratings);
            log('计算得到的当前评分:', currentScore);

            // 计算结果
            log('计算所需五星好评数...');
            const required = calculateRequiredReviews(currentScore, totalReviews);
            log('需要的五星好评数:', required);

            // 生成结果面板
            const resultBox = document.createElement('div');
            resultBox.className = 'monty-review-box';
            resultBox.id = 'monty-review-box';
            
            // 使用本地化文本
            const rt = localizedText.resultText;
            
            // 创建语言选择器
            const currentLang = getUserLanguage();
            const langOptions = {
                'zh': '中文',
                'en': 'English',
                'fr': 'Français',
                'de': 'Deutsch',
                'jp': '日本語'
            };
            
            const langSelector = `
                <select class="monty-lang-selector" id="monty-lang-selector">
                    ${Object.entries(langOptions).map(([code, name]) => 
                        `<option value="${code}" ${code === currentLang ? 'selected' : ''}>${name}</option>`
                    ).join('')}
                </select>
            `;
            
            resultBox.innerHTML = `
                <div class="monty-review-title">
                    <span>${rt.title}</span>
                    ${langSelector}
                </div>
                ${ratings.map(r => `
                    <div class="monty-review-item">
                        ${'★'.repeat(r.stars)} ${r.count} (${(r.percent*100).toFixed(1)}%)
                    </div>
                `).join('')}
                <hr style="margin:8px 0">
                <div class="monty-review-item">
                    ${rt.currentScore} <span class="monty-highlight">${currentScore.toFixed(2)}</span>
                </div>
                ${required > 0 ? `
                    <div class="monty-review-item">
                        ${rt.required} <span class="monty-highlight">${required} ${rt.fiveStarReviews}</span>
                        ${rt.toReach} ${TARGET_SCORE}
                    </div>
                ` : `
                    <div class="monty-review-item monty-highlight">
                        ${rt.noNeed} ${TARGET_SCORE}${rt.noNeedSuffix}
                    </div>
                `}
                <div class="monty-review-item" style="font-size: 12px; margin-top: 10px; text-align: right; color: #555; border-top: 1px solid #eee; padding-top: 8px;">
                    © 2025 Monty Ng. All rights reserved.
                </div>
            `;
            
            // 保存评分数据,以便在切换语言时重新生成结果面板
            resultBox.dataset.currentScore = currentScore;
            resultBox.dataset.totalReviews = totalReviews;
            resultBox.dataset.required = required;
            resultBox.dataset.ratingsData = JSON.stringify(ratings);

            // 插入结果到页面 - 使用更准确的插入点
            log('准备插入结果面板到页面...');
            const possibleInsertPoints = [
                '#averageCustomerReviews',
                '#histogramTable',
                '[data-hook="cr-filter-info-review-rating-count"]',
                '.cr-widget-histogram'
            ];
            
            log('尝试以下插入点:', possibleInsertPoints);
            let inserted = false;
            for (const selector of possibleInsertPoints) {
                const insertPoint = document.querySelector(selector);
                log(`检查插入点 ${selector}:`, insertPoint ? '找到' : '未找到');
                
                if (insertPoint) {
                    // 尝试插入到元素之后
                    if (insertPoint.parentNode) {
                        log(`将结果面板插入到 ${selector} 之后`);
                        insertPoint.parentNode.insertBefore(resultBox, insertPoint.nextSibling);
                        inserted = true;
                        break;
                    }
                }
            }
            
            // 如果无法找到合适的插入点,则插入到直方图之前
            if (!inserted) {
                log('未找到理想插入点,尝试使用直方图作为插入点');
                if (histogram && histogram.parentNode) {
                    log('将结果面板插入到直方图之前');
                    histogram.parentNode.insertBefore(resultBox, histogram);
                    inserted = true;
                } else {
                    log('警告: 无法找到任何插入点');
                }
            }
            
            log('结果面板插入' + (inserted ? '成功' : '失败'));
            
            // 添加语言选择器的事件监听器
            if (inserted) {
                const langSelector = document.getElementById('monty-lang-selector');
                if (langSelector) {
                    langSelector.addEventListener('change', function() {
                        const newLang = this.value;
                        log('切换语言到:', newLang);
                        setUserLanguage(newLang);
                        
                        // 重新生成结果面板
                        regenerateResultPanel(resultBox);
                    });
                }
            }
            
            // 重新生成结果面板的函数
            function regenerateResultPanel(panel) {
                if (!panel) return;
                
                // 获取保存的数据
                const currentScore = parseFloat(panel.dataset.currentScore);
                const totalReviews = parseInt(panel.dataset.totalReviews);
                const required = parseInt(panel.dataset.required);
                const ratings = JSON.parse(panel.dataset.ratingsData);
                
                // 获取新的本地化文本
                const localizedText = getLocalizedText();
                const rt = localizedText.resultText;
                
                // 创建语言选择器
                const currentLang = getUserLanguage();
                const langOptions = {
                    'zh': '中文',
                    'en': 'English',
                    'fr': 'Français',
                    'de': 'Deutsch',
                    'jp': '日本語'
                };
                
                const langSelector = `
                    <select class="monty-lang-selector" id="monty-lang-selector">
                        ${Object.entries(langOptions).map(([code, name]) => 
                            `<option value="${code}" ${code === currentLang ? 'selected' : ''}>${name}</option>`
                        ).join('')}
                    </select>
                `;
                
                // 更新面板内容
                panel.innerHTML = `
                    <div class="monty-review-title">
                        <span>${rt.title}</span>
                        ${langSelector}
                    </div>
                    ${ratings.map(r => `
                        <div class="monty-review-item">
                            ${'★'.repeat(r.stars)} ${r.count} (${(r.percent*100).toFixed(1)}%)
                        </div>
                    `).join('')}
                    <hr style="margin:8px 0">
                    <div class="monty-review-item">
                        ${rt.currentScore} <span class="monty-highlight">${currentScore.toFixed(2)}</span>
                    </div>
                    ${required > 0 ? `
                        <div class="monty-review-item">
                            ${rt.required} <span class="monty-highlight">${required} ${rt.fiveStarReviews}</span>
                            ${rt.toReach} ${TARGET_SCORE}
                        </div>
                    ` : `
                        <div class="monty-review-item monty-highlight">
                            ${rt.noNeed} ${TARGET_SCORE}${rt.noNeedSuffix}
                        </div>
                    `}
                    <div class="monty-review-item" style="font-size: 12px; margin-top: 10px; text-align: right; color: #555; border-top: 1px solid #eee; padding-top: 8px;">
                        © 2025 Monty Ng. All rights reserved.
                    </div>
                `;
                
                // 重新添加事件监听器
                const newLangSelector = document.getElementById('monty-lang-selector');
                if (newLangSelector) {
                    newLangSelector.addEventListener('change', function() {
                        const newLang = this.value;
                        log('切换语言到:', newLang);
                        setUserLanguage(newLang);
                        
                        // 重新生成结果面板
                        regenerateResultPanel(panel);
                    });
                }
            }

        } catch (error) {
            if (DEBUG_MODE) console.error('[Review Calculator]', error);
            
            // 在页面上显示错误信息,帮助用户理解问题
            showError(`计算评论数据时出错: ${error.message}`);
            
            // 尝试使用备用方法获取评分
            log('主方法失败,尝试使用备用方法...');
            try {
                // 尝试从页面上直接获取平均评分
                log('尝试从页面直接获取平均评分...');
                const ratingElement = document.querySelector('[data-hook="average-star-rating"] .a-icon-alt');
                log('评分元素:', ratingElement);
                
                if (ratingElement) {
                    log('评分文本:', ratingElement.textContent);
                    const ratingMatch = ratingElement.textContent.match(/(\d+(\.\d+)?)/);
                    log('评分匹配结果:', ratingMatch);
                    
                    if (ratingMatch) {
                        const currentScore = parseFloat(ratingMatch[1]);
                        log('解析后的评分:', currentScore);
                        
                        // 尝试获取总评论数
                        log('尝试获取总评论数...');
                        const totalElement = document.querySelector('[data-hook="total-review-count"]');
                        log('总评论数元素:', totalElement);
                        
                        if (totalElement) {
                            log('总评论数文本:', totalElement.textContent);
                            const totalReviews = parseInt(sanitizeNumber(totalElement.textContent));
                            log('解析后的总评论数:', totalReviews);
                            
                            if (!isNaN(totalReviews) && !isNaN(currentScore)) {
                                log('成功获取评分和总评论数,计算所需五星好评...');
                                // 计算所需五星好评
                                const required = calculateRequiredReviews(currentScore, totalReviews);
                                log('需要的五星好评数:', required);
                                
                                // 获取本地化文本
                                const localizedText = getLocalizedText();
                                const rt = localizedText.resultText;
                                
                                // 创建简化版结果面板
                                log('创建简化版结果面板...');
                                const simpleBox = document.createElement('div');
                                simpleBox.className = 'monty-review-box';
                                simpleBox.id = 'monty-simple-review-box';
                                
                                // 创建语言选择器
                                const currentLang = getUserLanguage();
                                const langOptions = {
                                    'zh': '中文',
                                    'en': 'English',
                                    'fr': 'Français',
                                    'de': 'Deutsch',
                                    'jp': '日本語'
                                };
                                
                                const langSelector = `
                                    <select class="monty-lang-selector" id="monty-simple-lang-selector">
                                        ${Object.entries(langOptions).map(([code, name]) => 
                                            `<option value="${code}" ${code === currentLang ? 'selected' : ''}>${name}</option>`
                                        ).join('')}
                                    </select>
                                `;
                                
                                simpleBox.innerHTML = `
                                    <div class="monty-review-title">
                                        <span>${rt.title} ${rt.simplified}</span>
                                        ${langSelector}
                                    </div>
                                    <div class="monty-review-item">
                                        ${rt.currentScore} <span class="monty-highlight">${currentScore.toFixed(2)}</span>
                                    </div>
                                    ${required > 0 ? `
                                        <div class="monty-review-item">
                                            ${rt.required} <span class="monty-highlight">${required} ${rt.fiveStarReviews}</span>
                                            ${rt.toReach} ${TARGET_SCORE}
                                        </div>
                                    ` : `
                                        <div class="monty-review-item monty-highlight">
                                            ${rt.noNeed} ${TARGET_SCORE}${rt.noNeedSuffix}
                                        </div>
                                    `}
                                    <div class="monty-review-item">
                                        <small>${rt.note}</small>
                                    </div>
                                    <div class="monty-review-item" style="font-size: 12px; margin-top: 10px; text-align: right; color: #555; border-top: 1px solid #eee; padding-top: 8px;">
                                        © 2025 Monty Ng. All rights reserved.
                                    </div>
                                `;
                                
                                // 保存评分数据,以便在切换语言时重新生成结果面板
                                simpleBox.dataset.currentScore = currentScore;
                                simpleBox.dataset.totalReviews = totalReviews;
                                simpleBox.dataset.required = required;
                                
                                // 尝试插入到页面
                                log('尝试插入简化版结果面板...');
                                const insertPoint = document.querySelector('#averageCustomerReviews');
                                log('插入点:', insertPoint);
                                
                                if (insertPoint && insertPoint.parentNode) {
                                    log('将简化版结果面板插入到页面');
                                    insertPoint.parentNode.insertBefore(simpleBox, insertPoint.nextSibling);
                                    log('简化版结果面板插入成功');
                                    
                                    // 添加语言选择器的事件监听器
                                    const simpleLangSelector = document.getElementById('monty-simple-lang-selector');
                                    if (simpleLangSelector) {
                                        simpleLangSelector.addEventListener('change', function() {
                                            const newLang = this.value;
                                            log('切换语言到:', newLang);
                                            setUserLanguage(newLang);
                                            
                                            // 重新生成简化版结果面板
                                            regenerateSimpleResultPanel(simpleBox);
                                        });
                                    }
                                } else {
                                    log('警告: 无法找到插入点');
                                }
                                
                                // 重新生成简化版结果面板的函数
                                function regenerateSimpleResultPanel(panel) {
                                    if (!panel) return;
                                    
                                    // 获取保存的数据
                                    const currentScore = parseFloat(panel.dataset.currentScore);
                                    const totalReviews = parseInt(panel.dataset.totalReviews);
                                    const required = parseInt(panel.dataset.required);
                                    
                                    // 获取新的本地化文本
                                    const localizedText = getLocalizedText();
                                    const rt = localizedText.resultText;
                                    
                                    // 创建语言选择器
                                    const currentLang = getUserLanguage();
                                    const langOptions = {
                                        'zh': '中文',
                                        'en': 'English',
                                        'fr': 'Français',
                                        'de': 'Deutsch',
                                        'jp': '日本語'
                                    };
                                    
                                    const langSelector = `
                                        <select class="monty-lang-selector" id="monty-simple-lang-selector">
                                            ${Object.entries(langOptions).map(([code, name]) => 
                                                `<option value="${code}" ${code === currentLang ? 'selected' : ''}>${name}</option>`
                                            ).join('')}
                                        </select>
                                    `;
                                    
                                    // 更新面板内容
                                    panel.innerHTML = `
                                        <div class="monty-review-title">
                                            <span>${rt.title} ${rt.simplified}</span>
                                            ${langSelector}
                                        </div>
                                        <div class="monty-review-item">
                                            ${rt.currentScore} <span class="monty-highlight">${currentScore.toFixed(2)}</span>
                                        </div>
                                        ${required > 0 ? `
                                            <div class="monty-review-item">
                                                ${rt.required} <span class="monty-highlight">${required} ${rt.fiveStarReviews}</span>
                                                ${rt.toReach} ${TARGET_SCORE}
                                            </div>
                                        ` : `
                                            <div class="monty-review-item monty-highlight">
                                                ${rt.noNeed} ${TARGET_SCORE}${rt.noNeedSuffix}
                                            </div>
                                        `}
                                        <div class="monty-review-item">
                                            <small>${rt.note}</small>
                                        </div>
                                        <div class="monty-review-item" style="font-size: 12px; margin-top: 10px; text-align: right; color: #555; border-top: 1px solid #eee; padding-top: 8px;">
                                            © 2025 Monty Ng. All rights reserved.
                                        </div>
                                    `;
                                    
                                    // 重新添加事件监听器
                                    const newLangSelector = document.getElementById('monty-simple-lang-selector');
                                    if (newLangSelector) {
                                        newLangSelector.addEventListener('change', function() {
                                            const newLang = this.value;
                                            log('切换语言到:', newLang);
                                            setUserLanguage(newLang);
                                            
                                            // 重新生成简化版结果面板
                                            regenerateSimpleResultPanel(panel);
                                        });
                                    }
                                }
                            } else {
                                log('错误: 无效的评分或总评论数');
                            }
                        } else {
                            log('错误: 找不到总评论数元素');
                        }
                    } else {
                        log('错误: 无法从文本中提取评分');
                    }
                } else {
                    log('错误: 找不到评分元素');
                }
            } catch (backupError) {
                log('备用方法也失败:', backupError);
                if (DEBUG_MODE) console.error('[Review Calculator] 备用方法也失败:', backupError);
            }
        }
    }

    // 辅助函数:等待元素加载
    function waitForElement(selector, timeout = 5000) {
        return new Promise((resolve) => {
            // 如果元素已存在,立即返回
            const existingEl = document.querySelector(selector);
            if (existingEl) return resolve(existingEl);
            
            // 否则,设置观察器等待元素出现
            const start = Date.now();
            
            // 创建一个MutationObserver来监视DOM变化
            const observer = new MutationObserver(() => {
                const el = document.querySelector(selector);
                if (el) {
                    observer.disconnect(); // 停止观察
                    return resolve(el);
                }
                
                // 超时检查
                if (Date.now() - start > timeout) {
                    observer.disconnect();
                    return resolve(null);
                }
            });
            
            // 开始观察DOM变化
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
            
            // 额外的超时保障
            setTimeout(() => {
                observer.disconnect();
                resolve(document.querySelector(selector));
            }, timeout);
        });
    }

    // 显示错误信息
    function showError(message) {
        if (DEBUG_MODE) console.error('[Review Calculator]', message);
        
        // 获取本地化文本
        const localizedText = getLocalizedText();
        const rt = localizedText.resultText;
        
        // 在页面上显示错误信息
        const errorBox = document.createElement('div');
        errorBox.className = 'monty-review-box';
        errorBox.innerHTML = `
            <div class="monty-review-title">${rt.error}</div>
            <div class="monty-review-item">${message}</div>
            <div class="monty-review-item">
                <small>${rt.errorHelp}</small>
            </div>
            <div class="monty-review-item" style="font-size: 12px; margin-top: 10px; text-align: right; color: #555; border-top: 1px solid #eee; padding-top: 8px;">
                © 2025 Monty Ng. All rights reserved.
            </div>
        `;
        
        // 尝试插入到评论区域
        const insertPoints = [
            '#cm_cr-review_list',
            '.cr-widget-histogram',
            '#histogramTable',
            '#averageCustomerReviews',
            '#reviewsMedley'
        ];
        
        for (const selector of insertPoints) {
            const element = document.querySelector(selector);
            if (element) {
                element.parentNode.insertBefore(errorBox, element);
                return;
            }
        }
        
        // 如果找不到合适的插入点,插入到页面底部
        document.body.appendChild(errorBox);
    }
    
    // 初始化
    function init() {
        log('初始化脚本...');
        log('目标评分:', TARGET_SCORE);
        GM_setValue('target_score', TARGET_SCORE);
        
        // 确保我们在产品页面上
        log('当前页面路径:', window.location.pathname);
        if (!window.location.pathname.includes('/dp/')) {
            log('不是产品页面,脚本不执行');
            return;
        }
        
        // 等待DOM完全加载
        log('当前文档状态:', document.readyState);
        if (document.readyState === 'loading') {
            log('文档仍在加载中,等待DOMContentLoaded事件...');
            document.addEventListener('DOMContentLoaded', () => {
                log('DOM已加载,延迟1500ms执行主函数');
                setTimeout(processReviews, 1500);
            });
        } else {
            // 如果DOM已加载,给页面一些时间来完成动态内容加载
            log('DOM已加载,延迟1500ms执行主函数');
            setTimeout(processReviews, 1500);
        }
    }
    
    // 启动脚本
    try {
        log('脚本开始执行...');
        log('浏览器信息:', navigator.userAgent);
        init();
    } catch (error) {
        log('初始化失败:', error);
        showError(`初始化失败: ${error.message}`);
    }
})();