Greasy Fork

Greasy Fork is available in English.

店小蜜5倍价格筛选

5倍价格筛选

当前为 2025-11-05 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         店小蜜5倍价格筛选
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  5倍价格筛选
// @author       Rayu
// @match        https://www.dianxiaomi.com/web/shopeeSite/*
// @exclude      https://www.dianxiaomi.com/web/shopeeSite/edit*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 等待页面加载完成
    function waitForElement(selector, callback, maxWait = 10000) {
        const startTime = Date.now();
        const interval = setInterval(() => {
            const element = document.querySelector(selector);
            if (element) {
                clearInterval(interval);
                callback();
            } else if (Date.now() - startTime > maxWait) {
                clearInterval(interval);
                console.log('等待元素超时');
            }
        }, 500);
    }

    // ================== 数据持久化缓存模块 ==================
    const CACHE_KEY = 'dianxiaomi_product_cache';
    const CACHE_EXPIRE_DAYS = 7; // 缓存过期天数

    // 缓存管理器
    const CacheManager = {
        // 保存数据到localStorage
        save(data) {
            try {
                const cacheData = {
                    data: data,
                    timestamp: Date.now(),
                    version: '1.0.0'
                };
                localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData));
                console.log('💾 数据已保存到localStorage,当前数量:', data.length);
            } catch (e) {
                console.error('❌ 保存缓存失败:', e);
            }
        },

        // 从localStorage加载数据
        load() {
            try {
                const cached = localStorage.getItem(CACHE_KEY);
                if (!cached) {
                    console.log('📂 未找到缓存数据,初始化为空数组');
                    return [];
                }

                const cacheData = JSON.parse(cached);
                const age = Date.now() - cacheData.timestamp;
                const ageDays = Math.floor(age / (1000 * 60 * 60 * 24));

                console.log(`📂 加载缓存数据: ${cacheData.data.length} 条记录`);
                console.log(`⏰ 缓存时间: ${ageDays} 天前`);

                return cacheData.data || [];
            } catch (e) {
                console.error('❌ 加载缓存失败:', e);
                return [];
            }
        },

        // 清除所有缓存
        clear() {
            try {
                localStorage.removeItem(CACHE_KEY);
                console.log('🗑️ 已清除localStorage中的所有缓存');
            } catch (e) {
                console.error('❌ 清除缓存失败:', e);
            }
        },

        // 清理过期缓存(超过7天)
        cleanExpired() {
            try {
                const cached = localStorage.getItem(CACHE_KEY);
                if (!cached) return;

                const cacheData = JSON.parse(cached);
                const age = Date.now() - cacheData.timestamp;
                const ageDays = age / (1000 * 60 * 60 * 24);

                if (ageDays > CACHE_EXPIRE_DAYS) {
                    this.clear();
                    console.log(`🧹 自动清理 ${Math.floor(ageDays)} 天前的过期缓存`);
                    return true;
                }
                return false;
            } catch (e) {
                console.error('❌ 清理过期缓存失败:', e);
                return false;
            }
        },

        // 获取缓存信息
        getInfo() {
            try {
                const cached = localStorage.getItem(CACHE_KEY);
                if (!cached) {
                    return { exists: false, count: 0, ageDays: 0 };
                }

                const cacheData = JSON.parse(cached);
                const age = Date.now() - cacheData.timestamp;
                const ageDays = Math.floor(age / (1000 * 60 * 60 * 24));

                return {
                    exists: true,
                    count: cacheData.data?.length || 0,
                    ageDays: ageDays,
                    timestamp: cacheData.timestamp
                };
            } catch (e) {
                console.error('❌ 获取缓存信息失败:', e);
                return { exists: false, count: 0, ageDays: 0 };
            }
        }
    };

    // 页面加载时自动清理过期缓存
    CacheManager.cleanExpired();

    // 从localStorage加载已缓存的数据
    let capturedApiData = CacheManager.load();

    // 将capturedApiData和缓存管理器暴露到全局作用域
    window.capturedApiData = capturedApiData;
    window.CacheManager = CacheManager;

    console.log('🚀 API拦截器已启动');
    console.log('💡 提示: 可以在控制台使用 window.capturedApiData 或 capturedApiData 访问捕获的数据');

    // ================== 分类数据持久化模块 ==================
    const CATEGORY_CACHE_KEY = 'dianxiaomi_categories';

    // 分类数据管理器
    const CategoryManager = {
        // 保存分类数据到localStorage
        save(categories) {
            try {
                const cacheData = {
                    categories: categories,
                    lastUpdate: Date.now(),
                    version: '1.0.0'
                };
                localStorage.setItem(CATEGORY_CACHE_KEY, JSON.stringify(cacheData));
                console.log('💾 [分类] 数据已保存到localStorage,分类数量:', categories.length);
                return true;
            } catch (e) {
                console.error('❌ [分类] 保存失败:', e);
                return false;
            }
        },

        // 从localStorage加载分类数据
        load() {
            try {
                const cached = localStorage.getItem(CATEGORY_CACHE_KEY);
                if (!cached) {
                    console.log('📂 [分类] 未找到缓存数据');
                    return null;
                }

                const cacheData = JSON.parse(cached);
                const age = Date.now() - cacheData.lastUpdate;
                const ageDays = Math.floor(age / (1000 * 60 * 60 * 24));

                console.log(`📂 [分类] 加载缓存数据: ${cacheData.categories.length} 个分类`);
                console.log(`⏰ [分类] 缓存时间: ${ageDays} 天前`);

                return cacheData.categories || [];
            } catch (e) {
                console.error('❌ [分类] 加载失败:', e);
                return null;
            }
        },

        // 检查是否存在缓存
        exists() {
            try {
                const cached = localStorage.getItem(CATEGORY_CACHE_KEY);
                return !!cached;
            } catch (e) {
                return false;
            }
        },

        // 对比并更新分类数据
        updateIfChanged(newCategories) {
            const oldCategories = this.load() || [];

            // 创建ID映射用于对比
            const oldMap = new Map(oldCategories.map(c => [c.id, c.name]));
            const newMap = new Map(newCategories.map(c => [c.id, c.name]));

            let hasChanges = false;
            const changes = [];

            // 检查新增或修改
            for (const [id, name] of newMap) {
                if (!oldMap.has(id)) {
                    changes.push(`新增: ${name} (${id})`);
                    hasChanges = true;
                } else if (oldMap.get(id) !== name) {
                    changes.push(`修改: ${oldMap.get(id)} → ${name} (${id})`);
                    hasChanges = true;
                }
            }

            // 检查删除
            for (const [id, name] of oldMap) {
                if (!newMap.has(id)) {
                    changes.push(`删除: ${name} (${id})`);
                    hasChanges = true;
                }
            }

            if (hasChanges) {
                console.log('🔄 [分类] 检测到数据变化:');
                changes.forEach(change => console.log(`  ${change}`));
                this.save(newCategories);
                return true;
            } else {
                console.log('✓ [分类] 数据无变化,跳过保存');
                return false;
            }
        }
    };

    // 暴露分类管理器到全局
    window.CategoryManager = CategoryManager;

    // 显示首次使用提示
    function showFirstTimeGuide() {
        const modal = document.createElement('div');
        modal.id = 'category-first-time-guide';
        modal.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.7);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 999999;
        `;

        const dialog = document.createElement('div');
        dialog.style.cssText = `
            background: white;
            border-radius: 12px;
            padding: 32px;
            width: 480px;
            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
            text-align: center;
        `;

        dialog.innerHTML = `
            <div style="font-size: 48px; margin-bottom: 16px;">📦</div>
            <div style="font-size: 20px; font-weight: bold; color: #262626; margin-bottom: 16px;">
                首次使用提示
            </div>
            <div style="font-size: 14px; color: #595959; line-height: 1.6; margin-bottom: 24px;">
                检测到您尚未初始化分类数据<br>
                请手动移动一次分类,系统将自动捕获并保存分类列表<br>
                完成后即可正常使用批量移动功能
            </div>
            <div style="padding: 16px; background: #f0f7ff; border-radius: 8px; border-left: 3px solid #1890ff; text-align: left;">
                <div style="font-size: 14px; color: #0050b3; font-weight: bold; margin-bottom: 8px;">💡 操作步骤:</div>
                <div style="font-size: 13px; color: #096dd9; line-height: 1.8;">
                    1. 在商品列表中选择任意商品<br>
                    2. 点击「移动分类」按钮<br>
                    3. 选择目标分类并确认<br>
                    4. 系统将自动保存分类数据
                </div>
            </div>
            <button id="close-guide-btn" style="
                margin-top: 20px;
                padding: 10px 24px;
                background: #1890ff;
                color: white;
                border: none;
                border-radius: 6px;
                font-size: 14px;
                cursor: pointer;
                transition: background 0.3s;
            ">我知道了</button>
        `;

        modal.appendChild(dialog);
        document.body.appendChild(modal);

        console.log('📢 [分类] 显示首次使用引导');

        // 关闭按钮事件
        const closeBtn = dialog.querySelector('#close-guide-btn');
        closeBtn.addEventListener('click', () => {
            if (document.body.contains(modal)) {
                document.body.removeChild(modal);
            }
            console.log('ℹ️ [分类] 用户手动关闭引导');
        });

        // 鼠标悬停效果
        closeBtn.addEventListener('mouseenter', () => {
            closeBtn.style.background = '#40a9ff';
        });
        closeBtn.addEventListener('mouseleave', () => {
            closeBtn.style.background = '#1890ff';
        });

        // 返回Promise,当分类数据保存后自动关闭
        return new Promise((resolve) => {
            const checkInterval = setInterval(() => {
                if (CategoryManager.exists()) {
                    clearInterval(checkInterval);
                    if (document.body.contains(modal)) {
                        document.body.removeChild(modal);
                    }
                    console.log('✅ [分类] 首次使用引导已完成');
                    resolve();
                }
            }, 500);
        });
    }

    // 页面加载时检查分类数据
    window.addEventListener('load', function() {
        setTimeout(() => {
            if (!CategoryManager.exists()) {
                console.log('⚠️ [分类] 首次使用,显示引导提示');
                showFirstTimeGuide();
            } else {
                console.log('✅ [分类] 分类数据已存在,跳过引导');
            }
        }, 1000);
    });



    // 公共函数:处理分类移动API响应
    function handleCategoryApiResponse(data, source) {
        console.log(`🏷️ [分类] API响应完整数据 (${source}):`, JSON.stringify(data, null, 2));

        let categoryList = null;

        // 尝试从 data.msg 解析 JSON 字符串
        if (data && data.msg && typeof data.msg === 'string') {
            try {
                categoryList = JSON.parse(data.msg);
                console.log('🎯 [分类] 从msg字段解析到分类列表:', categoryList);
            } catch (e) {
                console.error('❌ [分类] 解析msg字段失败:', e);
            }
        }
        // 尝试 data.data 数组
        else if (data && Array.isArray(data.data)) {
            categoryList = data.data;
        }
        // 尝试直接从 data 获取数组
        else if (Array.isArray(data)) {
            categoryList = data;
        }

        if (Array.isArray(categoryList) && categoryList.length > 0) {
            console.log(`🎯 [分类] 提取到 ${categoryList.length} 个分类`);

            // 格式化新的分类数据
            const newCategories = categoryList
                .filter(cat => cat.id && cat.name)
                .map(cat => ({
                    id: cat.id,
                    name: cat.name
                }));

            // 加载现有分类数据进行对比
            const oldCategories = CategoryManager.load() || [];

            // 检查数据是否相同
            const isSame = oldCategories.length === newCategories.length &&
                          oldCategories.every((oldCat, index) => {
                              const newCat = newCategories.find(c => c.id === oldCat.id);
                              return newCat && newCat.name === oldCat.name;
                          });

            if (!isSame) {
                // 数据不同,直接替换
                CategoryManager.save(newCategories);
                console.log(`✅ [分类] 检测到数据变化,已替换为新数据,总数: ${newCategories.length}`);
            } else {
                console.log(`ℹ️ [分类] 数据无变化,跳过保存`);
            }
        } else {
            console.warn('⚠️ [分类] 无法从API响应中提取分类列表,请检查数据结构');
            console.log('💡 [分类] 完整响应数据:', data);
        }
    }

    // 公共函数:添加悬停效果
    function addHoverEffect(element, hoverColor, normalColor) {
        element.addEventListener('mouseenter', function() {
            this.style.backgroundColor = hoverColor;
        });
        element.addEventListener('mouseleave', function() {
            this.style.backgroundColor = normalColor;
        });
    }

    // 拦截XMLHttpRequest
    const originalXHROpen = XMLHttpRequest.prototype.open;
    const originalXHRSend = XMLHttpRequest.prototype.send;

    XMLHttpRequest.prototype.open = function(method, url) {
        this._url = url;
        this._method = method;
        return originalXHROpen.apply(this, arguments);
    };

    XMLHttpRequest.prototype.send = function(body) {
        const xhr = this;
        const requestBody = body;

        this.addEventListener('load', function() {
            try {
                if (this._url && this.responseText) {
                    // 检查是否是目标API
                    const isTargetApi = this._url.includes('shopeeProduct') ||
                                       this._url.includes('getProductById');

                    // 检查是否是分类移动API
                    const isCategoryMoveApi = this._url.includes('batchChangeCategory.json');

                    if (isTargetApi) {
                        console.log('🎯 捕获到目标API (XHR):', this._url);
                    }

                    if (isCategoryMoveApi) {
                        console.log('🏷️ [分类] 捕获到分类移动API (XHR):', this._url);
                    }

                    // 尝试解析JSON响应
                    const data = JSON.parse(this.responseText);
                    console.log('🔍 XHR请求:', this._url);
                    console.log('📦 响应数据:', data);

                    // 处理分类移动API
                    if (isCategoryMoveApi) {
                        handleCategoryApiResponse(data, 'XHR');
                    }


                    capturedApiData.push({
                        url: this._url,
                        method: 'XHR',
                        data: data,
                        timestamp: new Date().toISOString()
                    });

                    // 自动保存到localStorage
                    CacheManager.save(capturedApiData);

                    if (isTargetApi) {
                        console.log('✅ 已保存到 capturedApiData,当前总数:', capturedApiData.length);
                    }


                }
            } catch (e) {
                // 忽略非JSON响应
                if (this._url && (this._url.includes('shopeeProduct') || this._url.includes('getProductById'))) {
                    console.error('❌ 解析目标API响应失败:', this._url, e);
                }
            }
        });

        this.addEventListener('error', function() {
            console.error('❌ XHR请求失败:', this._url);
        });

        return originalXHRSend.apply(this, arguments);
    };

    // 拦截fetch
    const originalFetch = window.fetch;
    window.fetch = function() {
        const url = arguments[0];
        const isTargetApi = typeof url === 'string' &&
                           (url.includes('shopeeProduct') || url.includes('getProductById'));

        const isCategoryMoveApi = typeof url === 'string' && url.includes('batchChangeCategory.json');

        if (isTargetApi) {
            console.log('🎯 准备发起目标API请求 (Fetch):', url);
        }

        if (isCategoryMoveApi) {
            console.log('🏷️ [分类] 捕获到分类移动API (Fetch):', url);
        }

        return originalFetch.apply(this, arguments).then(response => {
            // 克隆响应以便读取
            const clonedResponse = response.clone();

            clonedResponse.json().then(data => {
                console.log('🔍 Fetch请求:', url);
                console.log('📦 响应数据:', data);

                // 处理分类移动API
                    if (isCategoryMoveApi) {
                        handleCategoryApiResponse(data, 'Fetch');
                    }


                capturedApiData.push({
                    url: url,
                    method: 'Fetch',
                    data: data,
                    timestamp: new Date().toISOString()
                });

                // 自动保存到localStorage
                CacheManager.save(capturedApiData);

                if (isTargetApi) {
                    console.log('✅ 已保存到 capturedApiData,当前总数:', capturedApiData.length);
                }
            }).catch((e) => {
                // 忽略非JSON响应
                if (isTargetApi) {
                    console.error('❌ 解析目标API响应失败:', url, e);
                }
            });

            return response;
        }).catch(error => {
            console.error('❌ Fetch请求失败:', url, error);
            throw error;
        });
    };

    // 从API数据中提取商品信息(新格式)
    function extractProductInfo() {
        const products = [];
        console.log('开始从API数据中提取商品信息...');
        console.log(`已捕获 ${capturedApiData.length} 个API请求`);

        // 遍历所有捕获的API数据
        capturedApiData.forEach((apiCall, index) => {
            console.log(`\n处理API请求 ${index + 1}:`, apiCall.url);

            // 判断API类型
            const isGetProductById = apiCall.url.includes('getProductById');
            console.log(`🔖 API类型: ${isGetProductById ? 'getProductById (规格列表)' : 'pageList (商品列表)'}`);

            // 如果是getProductById API,直接提取variations数组
            if (isGetProductById && apiCall.data && apiCall.data.data && Array.isArray(apiCall.data.data)) {
                console.log(`📦 发现 getProductById 数据,包含 ${apiCall.data.data.length} 个规格`);

                // 从第一个variation中获取商品基本信息
                const firstVariation = apiCall.data.data[0];
                if (firstVariation) {
                    const product = {
                        name: firstVariation.dxmProductName || '(从规格数据获取)',
                        id: firstVariation.dxmProductId || firstVariation.id, // 保留原始ID用于数据合并
                        idStr: firstVariation.idStr || firstVariation.id, // 用于UI显示
                        dxmProductId: firstVariation.dxmProductId || firstVariation.id,
                        specifications: []
                    };

                    // 提取所有规格
                    apiCall.data.data.forEach((variation, vIndex) => {
                        // 组合 option1 和 option2
                        const optionText = [variation.option1, variation.option2].filter(Boolean).join(' - ');
                        console.log(`  [${vIndex + 1}] ${optionText}: ¥${variation.price} (idStr: ${variation.idStr || '无'})`);
                        if ((variation.option1 !== undefined || variation.option2 !== undefined) && variation.price !== undefined) {
                            product.specifications.push({
                                option: optionText,
                                price: variation.price,
                                idStr: variation.idStr || variation.id
                            });
                        }
                    });

                    if (product.specifications.length > 0) {
                        console.log(`✅ 从 getProductById 提取商品: ${product.name} (DXM ID: ${product.dxmProductId})`);
                        console.log(`   └─ 规格数量: ${product.specifications.length}`);
                        products.push(product);
                    }
                }

                // getProductById API处理完毕,跳过递归查找
                return;
            }

            // 对于pageList API,使用递归查找
            // 递归查找数据中的商品信息
            function findProducts(obj, path = '') {
                if (!obj || typeof obj !== 'object') return;

                // 检查当前对象是否包含商品信息(必须有name和id)
                if (obj.name && obj.id) {
                    console.log(`\n🔍 发现潜在商品对象: ${obj.name} (ID: ${obj.id})`);
                    console.log(`  ├─ 路径: ${path}`);
                    console.log(`  ├─ idStr: ${obj.idStr || '无'}`);
                    console.log(`  ├─ dxmProductId: ${obj.dxmProductId || '无'}`);
                    console.log(`  ├─ variations 类型: ${Array.isArray(obj.variations) ? '数组' : typeof obj.variations}`);
                    console.log(`  └─ variations 长度: ${Array.isArray(obj.variations) ? obj.variations.length : 'N/A'}`);

                    const product = {
                        name: obj.name,
                        id: obj.id, // 保留原始ID用于数据合并
                        idStr: obj.idStr || obj.id, // 用于UI显示
                        dxmProductId: obj.idStr || obj.dxmProductId || obj.id, // 优先使用idStr
                        specifications: []
                    };

                    // 提取variations数组
                    if (Array.isArray(obj.variations)) {
                        console.log(`  📦 开始处理 ${obj.variations.length} 个 variations...`);
                        obj.variations.forEach((variation, vIndex) => {
                            // 组合 option1 和 option2
                            const optionText = [variation.option1, variation.option2].filter(Boolean).join(' - ');
                            console.log(`    [${vIndex + 1}] option1=${variation.option1}, option2=${variation.option2 || '无'}, price=${variation.price}, dxmProductId=${variation.dxmProductId || '无'}`);
                            if ((variation.option1 !== undefined || variation.option2 !== undefined) && variation.price !== undefined) {
                                product.specifications.push({
                                    option: optionText,
                                    price: variation.price
                                });
                            }
                        });
                        console.log(`  ✅ 成功提取 ${product.specifications.length} 个规格`);
                    } else {
                        console.log(`  ⚠️ variations 不是数组或不存在`);
                        // 输出整个对象的键,帮助调试
                        console.log(`  📋 对象的所有键:`, Object.keys(obj).join(', '));
                    }

                    // dxmProductId已在创建product时设置(优先级:idStr > dxmProductId > id)
                    console.log(`  ✓ 使用的 dxmProductId: ${product.dxmProductId}`);

                    // 只有当有规格数据时才添加商品
                    if (product.specifications.length > 0) {
                        console.log(`✓ 找到商品: ${product.name} (ID: ${product.id}, DXM ID: ${product.dxmProductId || '无'})`);
                        console.log(`  └─ 规格数量: ${product.specifications.length}`);
                        console.log(`  └─ 路径: ${path}`);
                        products.push(product);
                        console.log(`  ⚙️ 调试模式: 继续递归查找所有嵌套对象`);
                    } else {
                        console.log(`  ❌ 该商品没有有效的规格数据,跳过`);
                    }
                }

                // 递归遍历对象和数组
                if (Array.isArray(obj)) {
                    obj.forEach((item, idx) => findProducts(item, `${path}[${idx}]`));
                } else {
                    // 遍历对象的所有属性
                    for (let key in obj) {
                        if (obj.hasOwnProperty(key)) {
                            findProducts(obj[key], path ? `${path}.${key}` : key);
                        }
                    }
                }
            }

            findProducts(apiCall.data);
        });

        console.log(`\n共找到 ${products.length} 个商品(去重前)`);

        // 去重:合并相同ID的商品数据
        const productMap = new Map();
        products.forEach(product => {
            const key = product.id; // 使用原始ID作为唯一标识符

            if (productMap.has(key)) {
                // 如果已存在该商品,合并规格数据
                const existing = productMap.get(key);
                console.log(`🔄 发现重复商品: ${product.name} (ID: ${key})`);
                console.log(`   合并前规格数量: ${existing.specifications.length}`);
                console.log(`   待合并规格数量: ${product.specifications.length}`);

                // 合并规格数组(去重相同option的规格)
                const specMap = new Map();
                existing.specifications.forEach(spec => {
                    specMap.set(spec.option, spec);
                });
                product.specifications.forEach(spec => {
                    if (!specMap.has(spec.option)) {
                        specMap.set(spec.option, spec);
                    }
                });

                existing.specifications = Array.from(specMap.values());
                console.log(`   合并后规格数量: ${existing.specifications.length}`);
            } else {
                // 首次出现该商品,直接添加
                productMap.set(key, product);
            }
        });

        const mergedProducts = Array.from(productMap.values());
        console.log(`\n✅ 去重后共 ${mergedProducts.length} 个商品`);

        return mergedProducts;
    }

    // 显示商品数据
    function displayProductData(products) {
        console.log('\n=== 商品信息数据 ===');
        console.log(`共找到 ${products.length} 个商品`);

        console.log('\n详细列表:');
        products.forEach((product, index) => {
            console.log(`${index + 1}. 商品: ${product.name}`);
            console.log(`   ID: ${product.id}`);
            console.log(`   DXM ID: ${product.dxmProductId}`);
            console.log(`   规格数量: ${product.specifications.length} 个`);

            product.specifications.forEach((spec, sIndex) => {
                console.log(`   [${sIndex + 1}] ${spec.option}: ${spec.price}`);
            });
            console.log('---');
        });

        return products;
    }

    // 创建浮动窗口UI
    function createFloatingPanel() {
        // 创建容器
        const panel = document.createElement('div');
        panel.id = 'dianxiaomi-price-panel';
        panel.style.cssText = `
            position: fixed;
            top: 10px;
            right: 10px;
            width: 400px;
            max-height: 600px;
            background: white;
            border: 2px solid #1890ff;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            z-index: 999999;
            font-family: Arial, sans-serif;
            overflow: hidden;
            display: flex;
            flex-direction: column;
        `;

        // 创建标题栏
        const header = document.createElement('div');
        header.style.cssText = `
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 12px 15px;
            font-weight: bold;
            font-size: 16px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            cursor: move;
        `;
        header.innerHTML = `
            <span>📊 商品价格数据</span>
            <button id="dianxiaomi-close-btn" style="
                background: rgba(255,255,255,0.2);
                border: none;
                color: white;
                cursor: pointer;
                padding: 4px 8px;
                border-radius: 4px;
                font-size: 18px;
                line-height: 1;
            ">×</button>
        `;

        // 创建工具栏
        const toolbar = document.createElement('div');
        toolbar.style.cssText = `
            padding: 10px 15px;
            background: #f5f5f5;
            border-bottom: 1px solid #e0e0e0;
            display: flex;
            gap: 10px;
        `;
        toolbar.innerHTML = `
            <button id="dianxiaomi-refresh-btn" style="
                background: #1890ff;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                font-weight: 500;
                transition: background 0.3s;
            ">🔄 手动获取</button>
            <button id="dianxiaomi-clear-btn" style="
                background: #ff4d4f;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                font-weight: 500;
                transition: background 0.3s;
            ">🗑️ 清除缓存</button>
            <button id="dianxiaomi-move-category-btn" style="
                background: #52c41a;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                font-weight: 500;
                transition: background 0.3s;
                display: none;
            ">📁 移动分类</button>
            <span id="dianxiaomi-status" style="
                line-height: 32px;
                color: #666;
                font-size: 14px;
            ">准备就绪</span>
        `;

        // 创建内容区域
        const content = document.createElement('div');
        content.id = 'dianxiaomi-content';
        content.style.cssText = `
            flex: 1;
            overflow-y: auto;
            padding: 15px;
            max-height: 500px;
        `;
        content.innerHTML = '<div style="color: #999; text-align: center; padding: 40px 20px;">点击"手动获取"按钮开始获取数据</div>';

        // 组装面板
        panel.appendChild(header);
        panel.appendChild(toolbar);
        panel.appendChild(content);
        document.body.appendChild(panel);

        // 添加拖拽功能
        let isDragging = false;
        let currentX;
        let currentY;
        let initialX;
        let initialY;

        header.addEventListener('mousedown', (e) => {
            if (e.target.id === 'dianxiaomi-close-btn') return;
            isDragging = true;
            initialX = e.clientX - panel.offsetLeft;
            initialY = e.clientY - panel.offsetTop;
        });

        document.addEventListener('mousemove', (e) => {
            if (isDragging) {
                e.preventDefault();
                currentX = e.clientX - initialX;
                currentY = e.clientY - initialY;
                panel.style.left = currentX + 'px';
                panel.style.top = currentY + 'px';
                panel.style.right = 'auto';
            }
        });

        document.addEventListener('mouseup', () => {
            isDragging = false;
        });

        // 关闭按钮事件
        document.getElementById('dianxiaomi-close-btn').addEventListener('click', () => {
            panel.style.display = 'none';
        });

        // 刷新按钮事件
        document.getElementById('dianxiaomi-refresh-btn').addEventListener('click', () => {
            updatePanelData(true); // 自动展开
        });

        // 清除缓存按钮事件
        document.getElementById('dianxiaomi-clear-btn').addEventListener('click', () => {
            // 清空内存中的数组
            capturedApiData.length = 0;

            // 清除localStorage中的缓存
            CacheManager.clear();

            console.log('🗑️ 已清除所有缓存数据(内存 + localStorage)');
            console.log('💡 当前 capturedApiData.length =', window.capturedApiData.length);

            const contentEl = document.getElementById('dianxiaomi-content');
            const statusEl = document.getElementById('dianxiaomi-status');

            contentEl.innerHTML = '<div style="color: #52c41a; text-align: center; padding: 40px 20px;">✓ 缓存已清除<br/><small style="color: #999;">内存和localStorage数据已全部清空</small><br/><small style="color: #999;">点击"手动获取"重新加载数据</small></div>';
            statusEl.textContent = '缓存已清除';
            statusEl.style.color = '#52c41a';

            // 隐藏移动分类按钮
            document.getElementById('dianxiaomi-move-category-btn').style.display = 'none';
        });

        // ================== 分类提取和选择功能 ==================

        // 获取分类列表(从本地缓存读取)
        function getCategories() {
            // 从localStorage加载分类数据
            const categories = CategoryManager.load() || [];

            if (categories.length > 0) {
                console.log(`✅ 使用本地缓存的分类数据: ${categories.length} 个分类`);
            } else {
                console.log(`⚠️ 本地缓存中没有分类数据`);
            }

            return categories;
        }

        // 显示分类选择对话框
        function showCategorySelector(categories, productCount) {
            return new Promise((resolve) => {
                // 创建模态对话框
                const modal = document.createElement('div');
                modal.style.cssText = `
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background: rgba(0, 0, 0, 0.5);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    z-index: 999999;
                `;

                const dialog = document.createElement('div');
                dialog.style.cssText = `
                    background: white;
                    border-radius: 8px;
                    padding: 0;
                    width: 500px;
                    max-height: 600px;
                    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
                    display: flex;
                    flex-direction: column;
                `;

                // 对话框标题
                const header = document.createElement('div');
                header.style.cssText = `
                    padding: 16px 24px;
                    border-bottom: 1px solid #f0f0f0;
                    font-weight: bold;
                    font-size: 16px;
                `;
                header.textContent = `选择目标分类 (将移动 ${productCount} 个商品)`;

                // 搜索框
                const searchBox = document.createElement('input');
                searchBox.type = 'text';
                searchBox.placeholder = '搜索分类名称...';
                searchBox.style.cssText = `
                    margin: 16px 24px;
                    padding: 8px 12px;
                    border: 1px solid #d9d9d9;
                    border-radius: 4px;
                    font-size: 14px;
                    outline: none;
                `;

                // 分类列表容器
                const listContainer = document.createElement('div');
                listContainer.style.cssText = `
                    flex: 1;
                    overflow-y: auto;
                    padding: 0 24px;
                    max-height: 400px;
                `;

                // 渲染分类列表
                function renderCategories(filter = '') {
                    listContainer.innerHTML = '';
                    const filtered = categories.filter(cat =>
                        cat.name.toLowerCase().includes(filter.toLowerCase()) ||
                        cat.id.toString().includes(filter)
                    );

                    if (filtered.length === 0) {
                        listContainer.innerHTML = '<div style="text-align: center; color: #999; padding: 40px;">未找到匹配的分类</div>';
                        return;
                    }

                    filtered.forEach(cat => {
                        const item = document.createElement('div');
                        item.style.cssText = `
                            padding: 12px;
                            margin-bottom: 8px;
                            border: 1px solid #f0f0f0;
                            border-radius: 4px;
                            cursor: pointer;
                            transition: all 0.2s;
                        `;
                        item.innerHTML = `
                            <div style="font-size: 14px; color: #262626; margin-bottom: 4px;">${cat.name}</div>
                            <div style="font-size: 12px; color: #8c8c8c;">ID: ${cat.id}</div>
                        `;

                        item.onmouseenter = () => {
                            item.style.background = '#f5f5f5';
                            item.style.borderColor = '#1890ff';
                        };
                        item.onmouseleave = () => {
                            item.style.background = 'white';
                            item.style.borderColor = '#f0f0f0';
                        };
                        item.onclick = () => {
                            document.body.removeChild(modal);
                            resolve(cat.id);
                        };

                        listContainer.appendChild(item);
                    });
                }

                renderCategories();

                // 搜索功能
                searchBox.oninput = (e) => {
                    renderCategories(e.target.value);
                };

                // 底部按钮
                const footer = document.createElement('div');
                footer.style.cssText = `
                    padding: 16px 24px;
                    border-top: 1px solid #f0f0f0;
                    text-align: right;
                `;

                const cancelBtn = document.createElement('button');
                cancelBtn.textContent = '取消';
                cancelBtn.style.cssText = `
                    padding: 8px 16px;
                    border: 1px solid #d9d9d9;
                    border-radius: 4px;
                    background: white;
                    cursor: pointer;
                    font-size: 14px;
                `;
                cancelBtn.onclick = () => {
                    document.body.removeChild(modal);
                    resolve(null);
                };

                footer.appendChild(cancelBtn);

                // 组装对话框
                dialog.appendChild(header);
                dialog.appendChild(searchBox);
                dialog.appendChild(listContainer);
                dialog.appendChild(footer);
                modal.appendChild(dialog);
                document.body.appendChild(modal);

                // 点击背景关闭
                modal.onclick = (e) => {
                    if (e.target === modal) {
                        document.body.removeChild(modal);
                        resolve(null);
                    }
                };

                // 聚焦搜索框
                searchBox.focus();
            });
        }

        // 存储捕获的API信息(已预配置)
        window.dxmBatchMoveAPI = {
            url: '/api/shopeeProduct/batchChangeCategory.json',
            method: 'POST',
            bodyTemplate: 'ids={{PRODUCT_IDS}}&fullCid={{CATEGORY_ID}}&dxmState=offline'
        };

        // 尝试从localStorage加载用户自定义配置(如果有的话会覆盖默认配置)
        try {
            const savedConfig = localStorage.getItem('dxmBatchMoveAPI');
            if (savedConfig) {
                window.dxmBatchMoveAPI = JSON.parse(savedConfig);
                console.log('📋 已加载自定义API配置');
            } else {
                console.log('📋 使用默认API配置');
            }
        } catch (e) {
            console.log('📋 使用默认API配置');
        }

        // 移动分类按钮事件 - API直调版本
        document.getElementById('dianxiaomi-move-category-btn').addEventListener('click', async () => {
            const btn = document.getElementById('dianxiaomi-move-category-btn');

            // 获取所有高价差商品
            const highPriceProducts = [];
            window.dianxiaomiProductData.forEach((product, index) => {
                if (product.specifications && product.specifications.length > 0) {
                    const prices = product.specifications.map(s => s.price).filter(p => p > 0);
                    if (prices.length > 1) {
                        const minPrice = Math.min(...prices);
                        const maxPrice = Math.max(...prices);
                        const priceRatio = maxPrice / minPrice;
                        if (priceRatio > 5) {
                            highPriceProducts.push({
                                index: index,
                                name: product.name,
                                idStr: product.idStr,
                                dxmProductId: product.dxmProductId
                            });
                        }
                    }
                }
            });

            console.log(`🎯 找到 ${highPriceProducts.length} 个高价差商品`);

            if (highPriceProducts.length === 0) {
                alert('未找到高价差商品(价格比>5)');
                return;
            }

            // 检查是否需要重新配置API(按住Ctrl键点击可重新配置)
            if (event.ctrlKey) {
                const reconfigure = confirm('🔧 是否要重新配置API信息?\n\n当前配置:\nURL: ' + window.dxmBatchMoveAPI.url + '\nMethod: ' + window.dxmBatchMoveAPI.method);
                if (!reconfigure) return;
                window.dxmBatchMoveAPI = null;
            }

            if (false && !window.dxmBatchMoveAPI) {
                // 第一次使用:引导用户配置API
                const guide = `📋 批量移动分类 - API配置向导

找到 ${highPriceProducts.length} 个高价差商品

⚠️ 首次使用需要配置API信息:

1️⃣ 打开浏览器开发者工具(F12)
2️⃣ 切换到 Network(网络)标签
3️⃣ 手动勾选1-2个商品
4️⃣ 选择一个分类并点击确认
5️⃣ 在Network中找到批量移动的API请求
6️⃣ 复制请求URL和请求体(Request Payload)
7️⃣ 再次点击本按钮,粘贴API信息

💡 提示:要复制的商品ID列表:`;

                const productIds = highPriceProducts.map(p => p.dxmProductId || p.idStr).filter(id => id).join('\n');

                console.log('%c📋 高价差商品ID列表(用于测试):', 'color: #ff6b6b; font-weight: bold; font-size: 14px');
                console.log(productIds);

                // 复制ID到剪贴板
                navigator.clipboard.writeText(productIds).then(() => {
                    alert(guide + '\n\n✅ 商品ID已复制到剪贴板!');
                }).catch(() => {
                    alert(guide + '\n\n' + productIds);
                });

                // 提示用户输入API信息
                const apiUrl = prompt('请输入批量移动API的URL\n(从Network面板复制):');
                if (!apiUrl) return;

                const apiMethod = prompt('请输入API方法(GET/POST/PUT等):', 'POST');
                if (!apiMethod) return;

                alert('请准备好请求体JSON格式\n(下一步粘贴)');
                const apiBody = prompt('请输入请求体模板\n(JSON格式,商品ID用 {{PRODUCT_IDS}} 占位):');
                if (!apiBody) return;

                // 保存API配置
                window.dxmBatchMoveAPI = {
                    url: apiUrl,
                    method: apiMethod.toUpperCase(),
                    bodyTemplate: apiBody
                };

                // 保存到localStorage
                localStorage.setItem('dxmBatchMoveAPI', JSON.stringify(window.dxmBatchMoveAPI));

                alert('✅ API配置已保存!\n\n请再次点击按钮执行批量移动');
                return;
            }

            // 已配置API,执行批量移动
            btn.textContent = '🔄 正在批量移动...';
            btn.disabled = true;

            try {
                // 提取所有商品ID
                const productIds = highPriceProducts.map(p => p.dxmProductId || p.idStr).filter(id => id);

                console.log(`📤 准备批量移动 ${productIds.length} 个商品`);
                console.log('商品ID列表:', productIds);

                // 获取预配置的分类列表
                const categories = getCategories();

                // 显示分类选择对话框
                const categoryId = await showCategorySelector(categories, productIds.length);
                if (!categoryId) {
                    btn.textContent = '📁 移动分类';
                    btn.disabled = false;
                    return;
                }

                // 替换请求体模板中的占位符
                let requestBody = window.dxmBatchMoveAPI.bodyTemplate;

                // 将商品ID数组转换为逗号分隔的字符串(URL编码格式)
                const idsString = productIds.join(',');

                // 替换商品ID占位符
                requestBody = requestBody.replace(/\{\{PRODUCT_IDS\}\}/g, encodeURIComponent(idsString));
                // 替换分类ID占位符
                requestBody = requestBody.replace(/\{\{CATEGORY_ID\}\}/g, encodeURIComponent(categoryId));

                // 如果模板中没有占位符,说明是直接粘贴的请求体,需要手动构建
                if (!window.dxmBatchMoveAPI.bodyTemplate.includes('{{')) {
                    requestBody = `ids=${encodeURIComponent(idsString)}&fullCid=${encodeURIComponent(categoryId)}&dxmState=offline`;
                }

                console.log('📡 发送API请求...');
                console.log('URL:', window.dxmBatchMoveAPI.url);
                console.log('Method:', window.dxmBatchMoveAPI.method);
                console.log('Body:', requestBody);

                // 构建完整的API URL
                const apiUrl = window.dxmBatchMoveAPI.url.startsWith('http')
                    ? window.dxmBatchMoveAPI.url
                    : window.location.origin + window.dxmBatchMoveAPI.url;

                // 发送API请求
                const response = await fetch(apiUrl, {
                    method: window.dxmBatchMoveAPI.method,
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                        'X-Requested-With': 'XMLHttpRequest'
                    },
                    body: requestBody,
                    credentials: 'include'
                });

                const result = await response.json();

                console.log('📥 API响应:', result);

                if (response.ok && (result.success || result.code === 0 || result.code === 200)) {
                    console.log(`✅ 批量移动成功!`);
                    alert(`✅ 成功移动 ${productIds.length} 个商品到分类 ${categoryId}!\n\n请刷新页面查看结果`);
                    btn.textContent = `✅ 已移动 ${productIds.length} 个`;
                } else {
                    throw new Error(result.message || result.msg || '移动失败');
                }
            } catch (error) {
                console.error('❌ 批量移动失败:', error);
                alert(`❌ 批量移动失败:\n\n${error.message}\n\n请检查:\n1. API配置是否正确\n2. 分类ID是否有效\n3. 是否有操作权限\n\n详细信息请查看控制台`);
                btn.textContent = '📁 移动分类';
            } finally {
                btn.disabled = false;
                // 5秒后恢复按钮文本
                setTimeout(() => {
                    btn.textContent = '📁 移动分类';
                }, 5000);
            }


         });

        // 鼠标悬停效果
        addHoverEffect(document.getElementById('dianxiaomi-refresh-btn'), '#1890ff', '#40a9ff');
        addHoverEffect(document.getElementById('dianxiaomi-clear-btn'), '#ff4d4f', '#ff7875');

        return panel;
    }

    // 自动展开所有商品
    async function expandAllProducts() {
        console.log('🔍 开始查找展开按钮...');

        // 定义所有可能的选择器
        const selectors = [
            'td.col_10 span.link',
            'td[class*="col_10"] span.link',
            '.vxe-body--column.col_10 span.link',
            'span.link'
        ];

        // 循环尝试所有选择器,找到第一个有结果的
        let expandButtons = [];
        for (const selector of selectors) {
            expandButtons = document.querySelectorAll(selector);
            if (expandButtons.length > 0) break;
        }

        console.log(`✓ 找到 ${expandButtons.length} 个潜在展开按钮`);

        if (expandButtons.length === 0) {
            console.log('⚠️ 未找到展开按钮');
            return 0;
        }

        // 输出第一个按钮的详细信息用于调试
        if (expandButtons.length > 0) {
            const firstButton = expandButtons[0];
            console.log('📋 第一个按钮详情:');
            console.log('  - 标签:', firstButton.tagName);
            console.log('  - 类名:', firstButton.className);
            console.log('  - 内容:', firstButton.textContent?.trim() || '无文本');
            console.log('  - 父元素:', firstButton.parentElement?.tagName);
            console.log('  - HTML:', firstButton.outerHTML.substring(0, 200));
        }

        // 记录展开前的API数据数量
        const beforeApiCount = capturedApiData.length;
        console.log(`📊 展开前已捕获 ${beforeApiCount} 个API请求`);

        let expandedCount = 0;

        // 批量点击所有展开按钮(使用真实的鼠标事件模拟)
        const clickPromises = [];
        for (let i = 0; i < expandButtons.length; i++) {
            const button = expandButtons[i];

            // 检查按钮是否可见且可点击
            if (button && button.offsetParent !== null) {
                try {
                    // 模拟真实的鼠标事件序列
                    const eventConfig = {
                        view: window,
                        bubbles: true,
                        cancelable: true,
                        button: 0
                    };
                    ['mousedown', 'mouseup', 'click'].forEach(eventType => {
                        button.dispatchEvent(new MouseEvent(eventType, eventConfig));
                    });

                    expandedCount++;

                    if (i < 3) {
                        console.log(`✓ 已触发第 ${i + 1} 个展开按钮`);
                    }

                    // 每10个按钮后稍微延迟一下,给浏览器处理时间
                    if (expandedCount % 10 === 0) {
                        clickPromises.push(new Promise(resolve => setTimeout(resolve, 200)));
                    }
                } catch (e) {
                    console.error(`❌ 展开第 ${i + 1} 个商品失败:`, e);
                }
            }
        }

        console.log(`✓ 已触发 ${expandedCount} 个展开按钮(模拟点击事件)`);

        // 等待所有点击延迟完成
        await Promise.all(clickPromises);

        // 等待API请求完成(优化为更短的等待时间)
        const waitTime = Math.max(1000, expandedCount * 80); // 最少1秒,每个商品80ms
        console.log(`⏳ 等待 ${waitTime}ms 让API请求完成...`);

        // 分段检查API请求数量(减少检查次数,更快响应)
        for (let i = 0; i < 2; i++) {
            await new Promise(resolve => setTimeout(resolve, waitTime / 2));
            const currentApiCount = capturedApiData.length;
            const newCount = currentApiCount - beforeApiCount;
            if (newCount > 0) {
                console.log(`  ✓ 已捕获 ${newCount} 个新API请求...`);
            }
        }

        // 检查是否捕获到新的API数据
        const afterApiCount = capturedApiData.length;
        const newApiCount = afterApiCount - beforeApiCount;
        console.log(`📊 展开后共捕获 ${afterApiCount} 个API请求(新增 ${newApiCount} 个)`);

        if (newApiCount === 0) {
            console.log('⚠️ 警告:展开后未捕获到新的API请求!');
        } else {
            console.log(`✓ 成功捕获到 ${newApiCount} 个新的API请求`);
        }

        return expandedCount;
    }

    // 更新面板数据
    async function updatePanelData(autoExpand = true) {
        const statusEl = document.getElementById('dianxiaomi-status');
        const contentEl = document.getElementById('dianxiaomi-content');

        // 如果启用自动展开
        if (autoExpand) {
            statusEl.textContent = '正在处理...';
            statusEl.style.color = '#ff9800';

            const expandedCount = await expandAllProducts();

            if (expandedCount === 0) {
                statusEl.textContent = '未找到可展开的商品';
                statusEl.style.color = '#ff4d4f';
                return;
            }
        }

        statusEl.textContent = '正在获取数据...';
        statusEl.style.color = '#1890ff';

        setTimeout(() => {
            const productData = extractProductInfo();
            displayProductData(productData);
            window.dianxiaomiProductData = productData;

            // 更新UI显示
            if (productData.length === 0) {
                contentEl.innerHTML = '<div style="color: #ff4d4f; text-align: center; padding: 40px 20px;">⚠️ 未找到商品数据<br/><small style="color: #999;">请确保页面已加载完成</small></div>';
                statusEl.textContent = '未找到数据';
                statusEl.style.color = '#ff4d4f';
            } else {
                const totalSpecs = productData.reduce((sum, p) => sum + p.specifications.length, 0);
                // 统计高价差商品数量
                let highPriceRatioCount = 0;
                // 检查分类数据是否初始化
                const categoryExists = CategoryManager.exists();

                let html = `
                    <div style="margin-bottom: 10px; padding: 10px; background: #e6f7ff; border-radius: 4px; border-left: 3px solid #1890ff;">
                        <strong style="color: #1890ff;">✓ 成功获取 ${productData.length} 个商品,共 ${totalSpecs} 个规格</strong>
                    </div>
                    <div style="font-size: 12px; color: #666; margin-bottom: 10px; display: flex; align-items: center; gap: 12px;">
                        <span>最新更新: ${new Date().toLocaleTimeString()}</span>
                        <span style="${categoryExists ? 'color: #52c41a;' : 'color: #ff9800; font-weight: bold;'}">
                            ${categoryExists ? '📁 分类数据: 已初始化' : '⚠️ 分类数据: 未初始化'}
                        </span>
                    </div>
                    ${!categoryExists ? `
                        <div style="
                            margin-bottom: 10px;
                            padding: 12px;
                            background: #fff3e0;
                            border-left: 3px solid #ff9800;
                            border-radius: 4px;
                            color: #e65100;
                            font-size: 13px;
                            line-height: 1.6;
                        ">
                            <div style="font-weight: bold; margin-bottom: 4px;">⚠️ 提示</div>
                            <div>需要手动移动一次分类来初始化分类数据,完成后即可使用批量移动功能。</div>
                        </div>
                    ` : ''}
                `;

                productData.forEach((item, index) => {
                    // 计算最低价和最高价
                    let minPrice = Infinity;
                    let maxPrice = -Infinity;
                    item.specifications.forEach(spec => {
                        const price = parseFloat(spec.price);
                        if (!isNaN(price)) {
                            minPrice = Math.min(minPrice, price);
                            maxPrice = Math.max(maxPrice, price);
                        }
                    });

                    // 判断价格差是否超过5倍
                    const priceRatio = maxPrice / minPrice;
                    const hasHighPriceRatio = priceRatio > 5;
                    if (hasHighPriceRatio) highPriceRatioCount++;
                    const warningStyle = hasHighPriceRatio ? 'border: 2px solid #ff4d4f; background: #fff1f0;' : '';
                    const warningBadge = hasHighPriceRatio ? `<span style="background: #ff4d4f; color: white; padding: 2px 8px; border-radius: 12px; font-size: 11px; margin-left: 8px;">⚠️ 价差${priceRatio.toFixed(1)}倍</span>` : '';

                    html += `
                        <div style="
                            margin-bottom: 10px;
                            padding: 12px;
                            background: #fafafa;
                            border-radius: 6px;
                            border: 1px solid #e0e0e0;
                            ${warningStyle}
                            transition: all 0.3s;
                            position: relative;
                        " onmouseover="this.style.borderColor='#1890ff';" onmouseout="this.style.borderColor='${hasHighPriceRatio ? '#ff4d4f' : '#e0e0e0'}';">
                            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;">
                                <div style="display: flex; align-items: center; flex: 1;">
                                    <input type="checkbox" class="dianxiaomi-product-checkbox" data-high-price="${hasHighPriceRatio}" data-product-index="${index}" style="
                                        width: 18px;
                                        height: 18px;
                                        margin-right: 8px;
                                        cursor: pointer;
                                        ${hasHighPriceRatio ? '' : 'display: none;'}
                                    " />
                                    <div style="font-weight: 600; color: #333; font-size: 14px; flex: 1;">
                                        ${index + 1}. ${item.name || '未知商品'}
                                        ${warningBadge}
                                    </div>
                                </div>
                                <button onclick="window.editProduct(${index})" style="
                                    background: #1890ff;
                                    color: white;
                                    border: none;
                                    padding: 4px 12px;
                                    border-radius: 4px;
                                    cursor: pointer;
                                    font-size: 12px;
                                    transition: all 0.2s;
                                " onmouseover="this.style.background='#40a9ff'" onmouseout="this.style.background='#1890ff'">✏️ 编辑</button>
                            </div>
                            <div style="color: #666; font-size: 12px; margin-bottom: 8px;">
                                📦 共 ${item.specifications.length} 个规格 | ID: ${item.idStr}
                            </div>
                        </div>
                    `;
                });

                // 获取缓存信息
                const cacheInfo = CacheManager.getInfo();

                // 添加统计信息
                html += `
                    <div style="
                        margin-top: 15px;
                        padding: 12px;
                        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                        border-radius: 6px;
                        color: white;
                    ">
                        <div style="font-weight: bold; margin-bottom: 8px;">📈 统计信息</div>
                        <div style="font-size: 13px; line-height: 1.8;">
                            商品数量: ${productData.length} 件<br/>
                            规格数量: ${totalSpecs} 个<br/>
                            API记录: ${capturedApiData.length} 条<br/>
                            ${cacheInfo.exists ? `💾 缓存: ${cacheInfo.ageDays}天前 (${cacheInfo.count}条)` : '💾 缓存: 无'}
                        </div>
                    </div>
                `;



                 contentEl.innerHTML = html;
                statusEl.textContent = `已加载 ${productData.length} 个商品`;
                statusEl.style.color = '#52c41a';

                // 控制移动分类按钮显示
                const moveCategoryBtn = document.getElementById('dianxiaomi-move-category-btn');
                if (moveCategoryBtn) {
                    if (highPriceRatioCount > 0) {
                        moveCategoryBtn.style.display = 'block';
                        moveCategoryBtn.textContent = `📁 移动分类 (${highPriceRatioCount})`;
                    } else {
                        moveCategoryBtn.style.display = 'none';
                    }
                }
            }
        }, 500);
    }

    // 编辑商品函数 - 打开店小秘编辑页面
    window.editProduct = function(index) {
        const product = window.dianxiaomiProductData[index];
        if (!product) {
            alert('商品数据不存在');
            return;
        }

        // 使用 idStr 构建编辑链接
        const editUrl = `https://www.dianxiaomi.com/web/shopeeSite/edit?id=${product.idStr}`;
        console.log('🔗 打开编辑页面:', editUrl);

        // 在新标签页打开编辑链接
        window.open(editUrl, '_blank');
    };

    // 主函数
    function main() {
        console.log('店小蜜价格助手已启动');

        // 创建浮动面板
        setTimeout(() => {
            createFloatingPanel();
            console.log('✓ UI面板已创建');

            // 不再自动执行数据获取,只保留手动获取功能
        }, 1000);
    }

    // 页面加载完成后执行
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', main);
    } else {
        main();
    }

})();