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

// ==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}`);
    }
})();