拼多多订单导出与分析

导出拼多多订单并生成详细分析报告,包含商品图片、消费统计与购买趋势分析 改版自 @[seeker](https://greasyfork.org/zh-CN/scripts/534938-%E5%AF%BC%E5%87%BA%E6%8B%BC%E5%A4%9A%E5%A4%9A%E8%AE%A2%E5%8D%95)

安装此脚本?
作者推荐脚本

你可能也喜欢 导出拼多多订单

安装此脚本
// ==UserScript==
// @name 拼多多订单导出与分析
// @namespace win.somereason.web.utils
// @version 1.0.1
// @description 导出拼多多订单并生成详细分析报告,包含商品图片、消费统计与购买趋势分析 改版自 @[seeker](https://greasyfork.org/zh-CN/scripts/534938-%E5%AF%BC%E5%87%BA%E6%8B%BC%E5%A4%9A%E5%A4%9A%E8%AE%A2%E5%8D%95)
// @author wenmoux
// @match *://mobile.pinduoduo.com/orders.html*
// @grant none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // ===== 数据结构 =====
    let orderData = {
        items: [],
        summary: {
            totalOrders: 0,
            totalAmount: 0,
            averagePrice: 0,
            frequentCategories: {},
            frequentShops: {},
            repurchasedItems: [],
            monthlyTrends: {}
        }
    };

    // ===== 插入控制面板和日志浮窗 =====
    (function setupUI() {
        const controlPanel = document.createElement("div");
        controlPanel.id = "pdd-analysis-panel";
        controlPanel.innerHTML = `
            <style>
                /* Material Design 3 风格 */
                #pdd-analysis-panel {
                    position: fixed;
                    bottom: 20px;
                    right: 20px;
                    width: 360px;
                    background: #ffffff;
                    border-radius: 16px;
                    box-shadow: 0 4px 20px rgba(0,0,0,0.15);
                    padding: 16px;
                    z-index: 9999;
                    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
                    display: flex;
                    flex-direction: column;
                    gap: 12px;
                    transition: all 0.3s ease;
                    max-height: 80vh;
                    overflow-y: auto;
                }
                #pdd-control-buttons {
                    display: flex;
                    gap: 8px;
                }
                .pdd-btn {
                    flex: 1;
                    background-color: #e2231a;
                    color: white;
                    border: none;
                    padding: 12px;
                    border-radius: 8px;
                    font-size: 14px;
                    cursor: pointer;
                    transition: all 0.2s ease;
                    font-weight: 600;
                    text-align: center;
                }
                .pdd-btn:hover {
                    background-color: #c41c14;
                    transform: translateY(-1px);
                }
                .pdd-btn-secondary {
                    background-color: #f5f5f5;
                    color: #333;
                }
                .pdd-btn-secondary:hover {
                    background-color: #e0e0e0;
                }
                #pdd-log-container {
                    max-height: 200px;
                    overflow-y: auto;
                    padding: 10px;
                    background: #f5f5f5;
                    border-radius: 8px;
                    font-size: 13px;
                    color: #333;
                }
                .log-entry {
                    margin-bottom: 6px;
                    padding-bottom: 6px;
                    border-bottom: 1px solid #e0e0e0;
                }
                .log-time {
                    font-size: 11px;
                    color: #888;
                    margin-right: 5px;
                }
                .log-message {
                    font-weight: 500;
                }
                .progress-container {
                    width: 100%;
                    height: 6px;
                    background-color: #e0e0e0;
                    border-radius: 3px;
                    margin-top: 8px;
                }
                .progress-bar {
                    height: 100%;
                    width: 0%;
                    background-color: #e2231a;
                    border-radius: 3px;
                    transition: width 0.3s ease;
                }
                .panel-header {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    margin-bottom: 4px;
                }
                .panel-title {
                    font-size: 16px;
                    font-weight: 700;
                    color: #333;
                }
                .panel-actions {
                    display: flex;
                    gap: 8px;
                }
                .panel-action {
                    width: 28px;
                    height: 28px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    background: #f5f5f5;
                    border-radius: 50%;
                    cursor: pointer;
                }
                .panel-action:hover {
                    background: #e0e0e0;
                }
            </style>
            <div class="panel-header">
                <div class="panel-title">拼多多订单分析器</div>
                <div class="panel-actions">
                    <div class="panel-action" id="pdd-panel-minimize" title="最小化">−</div>
                </div>
            </div>
            <div id="pdd-control-buttons">
                <button id="exportOrdersBtn" class="pdd-btn">导出订单数据</button>
                <button id="generateReportBtn" class="pdd-btn pdd-btn-secondary">生成分析报告</button>
            </div>
            <div id="pdd-log-container"></div>
            <div class="progress-container">
                <div class="progress-bar" id="progress-indicator"></div>
            </div>`;
        document.body.appendChild(controlPanel);

        // 事件绑定
        document.getElementById('pdd-panel-minimize').addEventListener('click', function() {
            const panel = document.getElementById('pdd-analysis-panel');
            if (panel.style.height === '42px') {
                panel.style.height = '';
            } else {
                panel.style.height = '42px';
                setTimeout(() => {
                    panel.querySelector('.panel-actions').style.display = 'flex';
                    panel.querySelector('#pdd-control-buttons').style.display = 'none';
                    panel.querySelector('#pdd-log-container').style.display = 'none';
                    panel.querySelector('.progress-container').style.display = 'none';
                }, 300);
            }
        });
    })();

    // ===== 日志记录函数 =====
    window.logMessage = function(msg, type = 'info') {
        const logContainer = document.getElementById('pdd-log-container');
        if (!logContainer) return;

        const logEntry = document.createElement("div");
        logEntry.className = `log-entry log-${type}`;

        const timeSpan = document.createElement("span");
        timeSpan.className = "log-time";
        timeSpan.textContent = `[${new Date().toLocaleTimeString()}]`;

        const messageSpan = document.createElement("span");
        messageSpan.className = "log-message";
        messageSpan.textContent = msg;

        logEntry.appendChild(timeSpan);
        logEntry.appendChild(messageSpan);
        logContainer.appendChild(logEntry);
        logContainer.scrollTop = logContainer.scrollHeight;
    };

    // ===== 进度条更新函数 =====
    function updateProgress(percent) {
        const progressBar = document.getElementById('progress-indicator');
        if (progressBar) {
            progressBar.style.width = `${percent}%`;
        }
    }

    // ===== 自动滚动到底部后调用 callback =====
    function autoScrollUntilDone(callback) {
        let lastHeight = document.body.scrollHeight;
        let noChangeCount = 0;
        let progress = 0;
        logMessage("🚀 开始自动滚动加载更多订单...");
        updateProgress(5);

        const interval = setInterval(() => {
            const doneText = document.querySelector('.loading-text');
            if (doneText && doneText.innerText.includes('您已经没有更多的订单了')) {
                logMessage("✅ 已滚动到底部,加载完成!");
                updateProgress(100);
                clearInterval(interval);
                setTimeout(callback, 1000);
                return;
            }

            const currentHeight = document.body.scrollHeight;
            if (currentHeight === lastHeight) {
                noChangeCount++;
                if (noChangeCount > 5) {
                    window.scrollBy({ top: 1500, behavior: 'smooth' });
                    noChangeCount = 0;
                }
            } else {
                noChangeCount = 0;
                progress = Math.min(95, progress + 5);
                updateProgress(progress);
            }

            lastHeight = currentHeight;
            window.scrollBy({ top: 800, behavior: 'smooth' });
            logMessage("⬇️ 正在加载更多订单...");
        }, 800);
    }

    // ===== 提取订单数据 =====
    function extractOrderData() {
        logMessage("📦 正在提取订单商品信息...");
        orderData.items = [];

        const orderItems = document.querySelectorAll(".U6SAh0Eo");
        if (!orderItems || orderItems.length === 0) {
            logMessage("⚠️ 未找到订单项,请确认页面加载完成", "error");
            return false;
        }orderItems.forEach((item, index) => {
            try {
                // 基本信息提取
                const shopName = item.querySelector('[data-test="店铺名称"]')?.innerText.trim() || "未知店铺";
                const productName = item.querySelector('[data-test="商品名称"]')?.innerText.trim() || "未知商品";
                const productModel = item.querySelector(".bJrhQPD0")?.innerText.trim() || "";
                const price = parseFloat((item.querySelector('[data-test="商品价格"]')?.innerText.replace("¥", "").trim() || "0"));
                const status = item.querySelector('[data-test="订单状态"]')?.innerText.trim() || "";
                const paid = parseFloat((item.querySelector(".pdcOje4N")?.innerText.replace("¥", "").trim() || "0"));

                // 提取图片
                const imgElement = item.querySelector('[data-test="商品图片"] img');
                const imgUrl = imgElement ? imgElement.getAttribute('src') : "";// 提取订单时间
                const orderTimeElement = item.parentNode.querySelector('.MZwI5r1b');
                const orderTime = orderTimeElement ? orderTimeElement.innerText.replace('下单时间:', '').trim() : "";

                // 提取订单号
                const orderIdElement = item.parentNode.querySelector('.TQ8iHK1y');
                const orderId = orderIdElement ? orderIdElement.innerText.replace('订单号:', '').trim() : "";// 商品分类推断(简单基于关键词)
                let category = "其他";
const keywordCategories = {
    "食品生鲜": [
        // 基础食品类
        "食品", "零食", "饼干", "糖果", "巧克力", "坚果", "水果", "蔬菜", "肉", "海鲜", "调料", "酒", "茶", "咖啡",
        // 中国特色零食
        "鲜花饼", "玫瑰花饼", "月饼", "辣条", "休闲食品", "小吃", "批发", "整箱", "网红食品", "麻辣", "手工", "老式",
        // 地方特产
        "土特产", "云南特产", "东北特产", "新疆特产", "广式月饼", "苏式月饼", "粽子", "腊肉", "香肠",
        // 休闲食品细分
        "薯片", "膨化食品", "瓜子", "开心果", "碧根果", "夏威夷果", "腰果", "话梅", "鱿鱼丝", "牛肉干", "猪肉脯",
        // 方便速食
        "方便面", "自热火锅", "自热米饭", "即食", "速食", "冲泡", "螺蛳粉", "酸辣粉", "米线",
        // 生鲜
        "水产", "三文鱼", "龙虾", "大闸蟹", "咸鸭蛋", "松花蛋", "皮蛋", "咸鸭蛋黄", "腊肠"
    ],

    "服饰穿搭": [
        // 基础服装类
        "衣", "裤", "鞋", "袜", "帽", "围巾", "包", "服", "裙", "外套", "内衣", "T恤", "西装", "牛仔",
        // 时尚服装
        "男鞋", "运动鞋", "板鞋", "潮鞋", "小白鞋", "休闲鞋", "古着", "vintage", "宽松", "直筒", "牛仔裤", "男装", "女装", "百搭",
        // 中国风服装
        "汉服", "旗袍", "唐装", "中式服装", "中国风", "复古风", "中式婚礼", "盘扣", "团扇", "香囊",
        // 季节性服装
        "羽绒服", "棉衣", "保暖内衣", "秋裤", "毛衣", "卫衣", "雪地靴", "泳装", "沙滩裤", "防晒衣", "防晒霜",
        // 配饰
        "项链", "耳环", "手镯", "戒指", "发饰", "胸针", "丝巾", "皮带", "钱包", "手表", "墨镜",
        // 家纺
        "干衣机", "烘干机", "风干机", "床单", "四件套", "被罩", "枕套", "毛毯", "凉席", "蚊帐"
    ],

    "家居家装": [
        // 基础家居类
        "床", "沙发", "桌", "椅", "柜", "灯", "窗帘", "地毯", "家具", "装饰", "摆件", "餐具", "厨具",
        // 新增家居
        "香薰机", "香氛", "杯子", "塑料杯", "水杯", "一次性杯", "智能家居", "全屋智能", "小米智能", "排插", "电源板", "开关", "灯具", "空调", "智能开关", "干衣柜",
        // 家装细分
        "床垫", "席梦思", "乳胶床垫", "床头柜", "衣柜", "电视柜", "书柜", "鞋柜", "餐桌", "茶几", "梳妆台", "电脑桌",
        // 厨房用品
        "电饭煲", "电压力锅", "豆浆机", "破壁机", "料理机", "空气炸锅", "微波炉", "电磁炉", "蒸锅", "炒锅", "菜刀", "砧板",
        // 中式家居
        "紫砂壶", "茶具", "茶盘", "香道", "瓷器", "青花瓷", "景德镇", "陶瓷", "刺绣", "十字绣", "福字", "春联", "中国结"
    ],

    "数码电器": [
        // 基础电子类
        "手机", "电脑", "平板", "相机", "耳机", "音箱", "充电器", "电视", "显示器", "键盘", "鼠标",
        // 智能设备
        "智能设备", "米家", "APP智能", "远程控制", "USB", "电量统计", "遥控", "定时开关", "接线端子", "电源板", "数码配件", "分控排插",
        // 手机品牌
        "华为", "小米", "OPPO", "vivo", "苹果", "三星", "荣耀", "红米", "realme", "iQOO",
        // 电脑配件
        "CPU", "显卡", "主板", "内存", "硬盘", "SSD", "机械硬盘", "散热器", "电源", "机箱", "显示器", "路由器",
        // 游戏设备
        "游戏本", "游戏台式机", "游戏显卡", "游戏鼠标", "游戏键盘", "机械键盘", "耳麦", "游戏耳机", "游戏手柄", "RGB灯效",
        // 家用电器
        "冰箱", "洗衣机", "油烟机", "燃气灶", "热水器", "净水器", "空气净化器", "扫地机器人", "加湿器", "吸尘器", "除螨仪"
    ],

    "美妆个护": [
        // 基础美妆类
        "化妆品", "护肤", "面膜", "口红", "粉底", "眼影", "香水", "洗面奶", "护发", "美妆工具",
        // 护肤成分
        "烟酰胺", "珍珠", "海盐", "手工皂", "美白", "黑色素", "改善肤质", "精油", "玻尿酸", "胶原蛋白", "维生素C",
        // 国货美妆
        "花西子", "完美日记", "colorkey", "橘朵", "稚优泉", "美康粉黛", "大宝", "百雀羚", "相宜本草", "百草味",
        // 个人护理
        "洗发水", "护发素", "沐浴露", "身体乳", "香体", "防晒霜", "卫生巾", "洗手液", "消毒液", "漱口水", "牙膏", "牙刷",
        // 男士护理
        "男士护肤", "剃须刀", "刮胡刀", "须后水", "男士面霜", "男士洗面奶", "控油", "祛痘", "美容仪", "脱毛器"
    ],

    "母婴亲子": [
        // 基础母婴类
        "奶粉", "尿布", "婴儿", "童装", "玩具", "孕妇", "奶瓶", "推车", "儿童", "宝宝",
        // 婴幼儿用品
        "婴儿车", "婴儿床", "学步车", "婴儿餐椅", "婴儿洗澡盆", "婴儿背带", "婴儿睡袋", "婴儿枕头", "婴儿床垫",
        // 婴幼儿食品
        "辅食", "婴儿米粉", "婴儿面条", "婴儿饼干", "DHA", "钙铁锌", "益生菌", "鱼肝油", "婴儿营养品",
        // 孕产妇用品
        "月子服", "哺乳内衣", "孕妇裤", "孕妇枕", "孕妇护肤", "防辐射服", "产后修复", "催奶", "吸奶器",
        // 儿童教育
        "早教", "绘本", "识字卡", "拼图", "积木", "乐高", "画板", "学习桌", "书包", "文具盒"
    ],

    "日用百货": [
        // 基础日用品
        "纸巾", "洗发水", "沐浴露", "牙膏", "洗衣液", "清洁", "卫生纸", "毛巾", "卫生巾",
        // 纸品细分
        "抽纸", "原木纸巾", "便携装", "原生木浆", "面巾纸", "餐巾纸", "批发整箱", "家庭装", "湿厕纸", "湿巾",
        // 清洁用品
        "洗衣粉", "消毒剂", "洁厕灵", "管道疏通", "地板清洁", "玻璃清洁", "厨房清洁", "除湿剂", "除味剂", "垃圾袋",
        // 居家日用
        "衣架", "晾衣架", "收纳盒", "收纳箱", "防尘罩", "防潮垫", "防滑垫", "门垫", "蚊香", "电蚊香", "灭蚊灯"
    ],

    "办公文具": [
        // 基础办公用品
        "美工刀", "壁纸刀", "介刀", "刀片", "工具刀", "拆箱刀", "快递刀", "物流刀", "电商用品", "五金工具",
        // 文具
        "笔记本", "签字笔", "中性笔", "钢笔", "铅笔", "橡皮", "文件夹", "档案袋", "订书机", "打孔器", "计算器",
        // 办公耗材
        "复印纸", "打印纸", "彩色纸", "照片纸", "标签纸", "墨盒", "硒鼓", "碳粉", "打印机", "复印机", "扫描仪",
        // 学生文具
        "课本保护套", "作业本", "日记本", "练习册", "书皮", "书套", "尺子", "圆规", "三角板", "涂改液", "荧光笔"
    ],

    "医药健康": [
        // 基础医疗保健
        "口罩", "医用口罩", "外科口罩", "防疫", "防护", "防尘", "抗病毒", "防细菌", "三层防护",
        // 中医药品
        "中药", "中成药", "膏药", "创可贴", "云南白药", "正红花油", "板蓝根", "清热解毒", "感冒灵", "退烧药",
        // 营养保健
        "维生素", "蛋白粉", "钙片", "鱼油", "蜂王浆", "蜂蜜", "阿胶", "燕窝", "人参", "灵芝", "西洋参",
        // 医疗器械
        "血压计", "血糖仪", "体温计", "电子体温计", "雾化器", "制氧机", "助听器", "轮椅", "拐杖", "医用手套",
        // 消毒用品
        "酒精", "碘伏", "过氧化氢", "84消毒液", "免洗洗手液", "消毒湿巾", "紫外线消毒灯"
    ],

    "运动户外": [
        // 基础运动户外
        "运动装备", "户外用品", "运动服装", "运动鞋", "休闲运动", "健身器材",
        // 体育用品
        "篮球", "足球", "排球", "乒乓球", "羽毛球", "网球", "高尔夫", "游泳", "瑜伽垫", "瑜伽服", "健身手套",
        // 户外装备
        "帐篷", "睡袋", "登山包", "户外服装", "户外鞋", "望远镜", "指南针", "登山杖", "野餐垫", "防潮垫", "野营灯",
        // 运动智能
        "智能手环", "运动手表", "心率带", "计步器", "GPS导航", "运动相机", "骑行码表", "骑行灯", "头戴式耳机"
    ],

    "宠物用品": [
        // 基础宠物用品
        "宠物食品", "宠物玩具", "宠物床", "宠物清洁", "宠物医疗", "猫砂", "狗粮", "猫粮",
        // 猫咪用品
        "猫抓板", "猫爬架", "猫窝", "猫厕所", "猫砂盆", "猫粮盆", "猫玩具", "逗猫棒", "猫咪零食", "猫草",
        // 狗狗用品
        "狗窝", "狗链", "狗厕所", "狗尿垫", "狗狗玩具", "狗粮盆", "狗狗衣服", "狗狗鞋", "狗狗零食", "狗狗磨牙",
        // 宠物医疗
        "宠物驱虫", "宠物体外驱虫", "宠物体内驱虫", "宠物疫苗", "宠物消毒", "宠物医院", "宠物保健", "宠物美容"
    ],

    "汽车用品": [
        // 基础汽车用品
        "汽车配件", "车载设备", "汽车装饰", "汽车清洁", "汽车维修", "车载香薰",
        // 车内装饰
        "座垫", "方向盘套", "头枕", "腰靠", "脚垫", "后备箱垫", "香水", "车载挂饰", "车贴", "车衣", "遮阳挡",
        // 车载电子
        "行车记录仪", "车载充电器", "车载蓝牙", "导航仪", "倒车雷达", "胎压监测", "车载净化器", "车载吸尘器",
        // 汽车维护
        "机油", "防冻液", "玻璃水", "轮胎", "电瓶", "雨刷", "灯泡", "刹车片", "火花塞", "汽车贴膜", "洗车工具"
    ],

    "图书文娱": [
        // 新增类别
        "图书", "小说", "文学", "教育", "历史", "科学", "艺术", "杂志", "漫画", "绘本",
        // 教育类
        "教材", "教辅", "考试", "中小学教辅", "大学教材", "考研", "公务员", "英语", "字帖", "课外读物",
        // 文艺类
        "武侠小说", "言情小说", "科幻小说", "悬疑推理", "青春文学", "历史小说", "诗歌", "散文", "传记", "艺术欣赏",
        // 娱乐产品
        "CD", "DVD", "蓝光", "黑胶唱片", "电影", "音乐", "乐器", "吉他", "钢琴", "电子琴", "口琴"
    ],

    "数字虚拟": [
        // 新增类别
        "游戏点卡", "充值卡", "Q币", "视频会员", "音乐会员", "电子书", "虚拟资产", "主题", "皮肤", "表情包",
        // 游戏类
        "网游充值", "手游充值", "王者荣耀", "和平精英", "阴阳师", "LOL", "DNF", "梦幻西游", "游戏装备", "游戏代练",
        // 服务类
        "腾讯视频会员", "爱奇艺会员", "优酷会员", "芒果TV会员", "网易云音乐", "QQ音乐", "酷狗音乐", "喜马拉雅",
        // 电商服务
        "淘宝会员", "京东PLUS", "拼多多会员", "美团会员", "饿了么会员", "滴滴打车券"
    ],

    "礼品鲜花": [
        // 新增类别
        "鲜花", "绿植", "干花", "永生花", "礼盒", "贺卡", "创意礼品", "纪念品", "定制礼品", "生日礼物",
        // 节日礼品
        "春节礼品", "元宵礼品", "情人节礼物", "母亲节礼物", "父亲节礼物", "儿童节礼物", "教师节礼物", "中秋礼品", "圣诞礼物",
        // 鲜花类别
        "玫瑰", "康乃馨", "百合", "向日葵", "郁金香", "满天星", "扶郎花", "马蹄莲", "绣球花", "风信子"
    ],

    "特产区域": [
        // 新增类别
        "华北特产", "东北特产", "华东特产", "华中特产", "华南特产", "西南特产", "西北特产", "港澳台特产", "进口商品",
        // 地方特产
        "新疆特产", "内蒙古特产", "云南特产", "四川特产", "广东特产", "福建特产", "浙江特产", "山东特产", "东北特产",
        // 特产细分
        "大闸蟹", "西湖龙井", "金华火腿", "临安山核桃", "安溪铁观音", "武夷岩茶", "陈皮", "东阿阿胶", "枸杞", "红枣"
    ]
};
                for (const [cat, keywords] of Object.entries(keywordCategories)) {
                    if (keywords.some(word => productName.includes(word))) {
                        category = cat;
                        break;
                    }
                }

                // 构造订单数据对象
                const orderItem = {
                    orderId,
                    shopName,
                    productName,
                    productModel,
                    price,
                    status,
                    paid,
                    imgUrl,
                    orderTime,
                    category,
                    timeStamp: new Date(orderTime).getTime() || Date.now()
                };

                orderData.items.push(orderItem);
            } catch (e) {
                logMessage(`⚠️ 订单项${index+1} 提取失败,已跳过: ${e.message}`, "error");}
        });
        logMessage(`✅ 成功提取 ${orderData.items.length} 条订单信息`);
        return orderData.items.length > 0;
    }

    // ===== 计算数据统计和分析 =====
    function calculateStatistics() {
        logMessage("📊 正在生成数据统计和购买趋势分析...");

        const items = orderData.items;
        if (!items || items.length === 0) {
            logMessage("⚠️ 没有订单数据可供分析", "error");
            return false;
        }

        // 基本统计
        const totalOrders = items.length;
        const totalAmount = items.reduce((sum, item) => sum + item.paid, 0);
        const averagePrice = totalAmount / totalOrders;

        // 分类统计
        const categoryCounts = {};
        const shopCounts = {};
        items.forEach(item => {
            // 品类统计
            categoryCounts[item.category] = (categoryCounts[item.category] || 0) + 1;
            // 店铺统计
            shopCounts[item.shopName] = (shopCounts[item.shopName] || 0) + 1;
        });

        // 常购商品分析(找出相同或相似名称的商品)
        const productNameMap = {};
        items.forEach(item => {
            // 简化商品名称用于匹配(取前10个字符作为基础名称)
            const simpleName = item.productName.substring(0, 10);
            if (!productNameMap[simpleName]) {
                productNameMap[simpleName] = [];
            }
            productNameMap[simpleName].push(item);
        });

        // 找出购买次数超过1次的商品
        const repurchasedItems = [];
        for (const [name, products] of Object.entries(productNameMap)) {
            if (products.length > 1) {
                repurchasedItems.push({
                    name: name,
                    count: products.length,
                    totalSpent: products.reduce((sum, p) => sum + p.paid, 0),
                    items: products
                });
            }
        }

        // 按月消费趋势
        const monthlyTrends = {};
        items.forEach(item => {
            if (item.orderTime) {
                const date = new Date(item.orderTime);
                if (!isNaN(date.getTime())) {
                    const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
                    if (!monthlyTrends[monthKey]) {
                        monthlyTrends[monthKey] = {
                            count: 0,
                            amount: 0,
                            items: []
                        };
                    }
                    monthlyTrends[monthKey].count++;
                    monthlyTrends[monthKey].amount += item.paid;
                    monthlyTrends[monthKey].items.push(item);
                }
            }
        });

        // 保存统计结果
        orderData.summary = {
            totalOrders,
            totalAmount,
            averagePrice,
            frequentCategories: categoryCounts,
            frequentShops: shopCounts,
            repurchasedItems,
            monthlyTrends
        };

        logMessage("✅ 数据统计分析完成!");
        return true;
    }

    // ===== 下载 CSV 文件 =====
    function downloadCSV() {
        logMessage("📄 正在生成 CSV 文件...");let csv = `订单号,店铺名称,商品名称,商品型号,商品价格,订单状态,实付价格,订单时间,商品分类,图片链接\n`;

        orderData.items.forEach(item => {
            csv += `"${item.orderId}","${item.shopName}","${item.productName}","${item.productModel}","${item.price}","${item.status}","${item.paid}","${item.orderTime}","${item.category}","${item.imgUrl}"\n`;
        });const blob = new Blob(['\uFEFF' + csv], { type: "text/csv;charset=utf-8;" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = `PDD_订单数据_${new Date().toISOString().slice(0,10)}.csv`;
        document.body.appendChild(a);
        a.click();
        setTimeout(() => {
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        }, 100);

        logMessage("✅ CSV 文件导出成功!");
    }

    // ===== 生成HTML报告 =====
    function generateHTMLReport() {
        logMessage("📊 正在生成详细分析报告...");

        // 格式化货币
        const formatCurrency = num => `¥${num.toFixed(2)}`;

        // 准备分类数据
        const categoryLabels = Object.keys(orderData.summary.frequentCategories);
        const categoryData = categoryLabels.map(cat => orderData.summary.frequentCategories[cat]);
        // 准备店铺数据
        const shopLabels = Object.keys(orderData.summary.frequentShops).filter((_, i) => i < 10); // 最多显示前10个店铺
        const shopData = shopLabels.map(shop => orderData.summary.frequentShops[shop]);

        // 准备月度趋势数据
        const trendLabels = Object.keys(orderData.summary.monthlyTrends).sort();
        const trendAmounts = trendLabels.map(month => orderData.summary.monthlyTrends[month].amount);
        const trendCounts = trendLabels.map(month => orderData.summary.monthlyTrends[month].count);

        // 构建报告HTML
        const reportHTML = `
        <!DOCTYPE html>
        <html lang="zh-CN">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>拼多多订单分析报告</title>
            <style>
                :root {
                    --primary-color: #e2231a;
                    --secondary-color: #f5762a;
                    --background-color: #f5f5f5;
                    --card-background: #ffffff;
                    --text-color: #333333;
                    --text-secondary: #757575;
                    --border-radius: 16px;
                }
                * {
                    box-sizing: border-box;margin: 0;
                    padding: 0;
                }body {
                    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
                    background-color: var(--background-color);
                    color: var(--text-color);
                    line-height: 1.6;
                    padding: 20px;
                }

                .container {
                    max-width: 1200px;
                    margin: 0 auto;
                }h1, h2, h3 {
                    color: var(--text-color);
                    margin-bottom: 16px;
                }

                .header {
                    text-align: center;
                    margin-bottom: 40px;
                padding: 24px;
                    background: var(--card-background);
                    border-radius: var(--border-radius);
                    box-shadow: 0 4px 20px rgba(0,0,0,0.08);
                }.header h1 {
                    color: var(--primary-color);
                    font-size: 32px;
                    margin-bottom: 8px;
                }

                .header p {
                    color: var(--text-secondary);
                    font-size: 16px;
                }.summary-cards {
                    display: grid;
                    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
                    gap: 20px;
                margin-bottom: 40px;
                }

                .card {
                    background: var(--card-background);
                    border-radius: var(--border-radius);
                    padding: 24px;
                    box-shadow: 0 4px 20px rgba(0,0,0,0.08);
                }.card-title {
                    font-size: 16px;
                    color: var(--text-secondary);
                    margin-bottom: 8px;
                }

                .card-value {
                    font-size: 28px;
                    font-weight: bold;
                    color: var(--primary-color);
                }.tab-container {
                    margin-bottom: 40px;
                }

                .tab-nav {
                    display: flex;
                    margin-bottom: 20px;
                background: var(--card-background);
                    border-radius: var(--border-radius);
                    padding: 4px;
                    overflow: hidden;
                    box-shadow: 0 4px 20px rgba(0,0,0,0.08);
                }

                .tab-btn {
                    padding: 12px 20px;
                    cursor: pointer;
                    border: none;
                    background: transparent;
                    font-size: 16px;
                    font-weight: 500;
                    color: var(--text-secondary);
                    flex-grow: 1;
                    text-align: center;
                    transition: all 0.3s;border-radius: 12px;
                }.tab-btn.active {
                    color: var(--card-background);
                    background: var(--primary-color);
                }.tab-content {
                    display: none;
                    background: var(--card-background);
                    border-radius: var(--border-radius);
                    padding: 24px;
                    box-shadow: 0 4px 20px rgba(0,0,0,0.08);
                }

                .tab-content.active {
                    display: block;
                }.chart-container {
                    margin-bottom: 40px;height: 400px;
                }.items-grid {
                    display: grid;
                    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
                    gap: 20px;
                    margin-bottom: 40px;
                }

                .item-card {
                    background: var(--card-background);
                    border-radius: var(--border-radius);
                    overflow: hidden;
                    box-shadow: 0 4px 20px rgba(0,0,0,0.08);
                    transition: transform 0.3s ease;
                }.item-card:hover {
                    transform: translateY(-5px);
                }.item-image {
                    height: 200px;
                    overflow: hidden;
                }.item-image img {
                    width: 100%;
                    height: 100%;
                    object-fit: cover;
                    transition: transform 0.3s ease;
                }.item-card:hover .item-image img {
                    transform: scale(1.05);
                }.item-details {
                    padding: 16px;
                }

                .item-name {
                    font-weight: bold;
                    margin-bottom: 8px;
                white-space: nowrap;
                    overflow: hidden;
                    text-overflow: ellipsis;
                }

                .item-shop {
                    color: var(--text-secondary);
                    margin-bottom: 8px;
                font-size: 14px;
                }

                .item-meta {
                    display: flex;
                    justify-content: space-between;
                    color: var(--text-secondary);
                    font-size: 14px;
                }.item-price {
                    color: var(--primary-color);
                    font-weight: bold;
                }.footer {
                    text-align: center;
                    margin-top: 60px;
                    padding: 20px;
                    color: var(--text-secondary);
                }
                table {
                    width: 100%;
                    border-collapse: collapse;
                    margin-bottom: 20px;
                }

                table th, table td {
                    padding: 12px;
                    text-align: left;
                    border-bottom: 1px solid #eeeeee;
                }

                table th {
                    font-weight: 600;
                    background-color: #f9f9f9;
                }.repurchase-stats {
                    display: flex;
                    align-items: center;
                    gap: 12px;
                margin-bottom: 8px;
                flex-wrap: wrap;
                }

                .repurchase-count, .repurchase-total {
                    background: #f3f3f3;
                    border-radius: 20px;
                    padding: 4px 12px;
                    font-size: 14px;
                    font-weight: 500;
                }.repurchase-count {
                    color: var(--secondary-color);
                }

                .repurchase-total {
                    color: var(--primary-color);
                }.repurchase-item {
                    margin-bottom: 24px;
                }

                @media (max-width: 768px) {
                    .summary-cards {
                        grid-template-columns: 1fr;
                    }
                    .items-grid {
                        grid-template-columns: 1fr;
                    }
                }</style>
        </head>
        <body>
            <div class="container">
                <div class="header"><h1>拼多多订单分析报告</h1>
                    <p>生成时间: ${new Date().toLocaleString('zh-CN')}</p>
                </div>
                <div class="summary-cards">
                    <div class="card">
                        <div class="card-title">总订单数</div>
                        <div class="card-value">${orderData.summary.totalOrders}</div>
                    </div>
                    <div class="card">
                        <div class="card-title">总消费金额</div><div class="card-value">${formatCurrency(orderData.summary.totalAmount)}</div>
                    </div><div class="card">
                        <div class="card-title">平均每单</div>
                        <div class="card-value">${formatCurrency(orderData.summary.averagePrice)}</div></div>
                <div class="card">
                        <div class="card-title">常购商品数</div>
                        <div class="card-value">${orderData.summary.repurchasedItems.length}</div></div>
                </div><div class="tab-container">
                    <div class="tab-nav">
                        <button class="tab-btn active" data-tab="overview">消费概览</button><button class="tab-btn" data-tab="category">品类分析</button><button class="tab-btn" data-tab="products">商品分析</button><button class="tab-btn" data-tab="orders">订单明细</button></div>

                    <div id="overview" class="tab-content active">
                        <h2>近期购买的商品</h2>
                        <div class="items-grid">
                            ${orderData.items.slice(0, 6).map(item => `
                                <div class="item-card">
                                    <div class="item-image">
                                        <img src="${item.imgUrl || 'https://img.pddpic.com/mms-material-img/2023-07-19/2c0b7d3b-a63e-42c9-8426-44ea5ed7e84d.png'}" alt="${item.productName}"></div>
                                    <div class="item-details">
                                        <div class="item-name">${item.productName}</div>
                                        <div class="item-shop">${item.shopName}</div>
                                        <div class="item-meta">
                                            <div>${item.orderTime}</div><div class="item-price">${formatCurrency(item.paid)}</div></div></div>
                                </div>
                            `).join('')}</div>
                    </div>
                    <div id="category" class="tab-content">
                        <h2>品类占比</h2>
                        <div class="chart-container">
                            <canvas id="categoryChart"></canvas>
                        </div><h2>店铺分布</h2><div class="chart-container">
                            <canvas id="shopChart"></canvas>
                        </div>
                    </div>    <div id="products" class="tab-content">
                        <h2>经常复购的商品</h2>
                        <div class="items-grid">
                            ${orderData.summary.repurchasedItems.map(item => {
                                // 获取该商品的最新一条订单项
                                const latestItem = item.items.sort((a, b) => {
                                    return new Date(b.orderTime).getTime() - new Date(a.orderTime).getTime();
                                })[0];
                return `
                <div class="item-card repurchase-item">
                                    <div class="item-image">
                                        <img src="${latestItem.imgUrl || 'https://img.pddpic.com/mms-material-img/2023-07-19/2c0b7d3b-a63e-42c9-8426-44ea5ed7e84d.png'}" alt="${item.name}">
                                    </div>
                                    <div class="item-details">
                                        <div class="item-name">${latestItem.productName}</div><div class="item-shop">${latestItem.shopName}</div>
                                        <div class="repurchase-stats">
                                            <div class="repurchase-count">购买${item.count}次</div><div class="repurchase-total">共${formatCurrency(item.totalSpent)}</div></div>
                <div class="item-meta"><div>最近: ${new Date(Math.max(...item.items.map(i => new Date(i.orderTime).getTime()))).toLocaleDateString()}</div>
                                            <div class="item-price">均价: ${formatCurrency(item.totalSpent / item.count)}</div>
                                        </div>
                                    </div></div>
                                `;
                            }).join('')}
                        </div></div>
                <div id="orders" class="tab-content">
                        <h2>订单明细</h2>
                        <table>
                            <thead>
                                <tr>
                                    <th>商品</th><th>店铺</th>
                                    <th>价格</th>
                                    <th>订单时间</th>
                                    <th>状态</th></tr>
                            </thead><tbody>
                                ${orderData.items.map(item => `<tr><td>${item.productName}</td><td>${item.shopName}</td>
                                        <td>${formatCurrency(item.paid)}</td><td>${item.orderTime}</td>
                                        <td>${item.status}</td></tr>
                                `).join('')}
                            </tbody></table>
                    </div>
                </div>

                <div class="footer">
                    <p>数据来源:拼多多订单 · 共${orderData.summary.totalOrders}条记录</p></div>
            </div>
            <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.min.js"></script>
            <script>
                // 标签切换
                document.querySelectorAll('.tab-btn').forEach(button => {
                    button.addEventListener('click', () => {
                document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
                        document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
                        button.classList.add('active');
                        document.getElementById(button.getAttribute('data-tab')).classList.add('active');
                    });
                });

                // 消费趋势图
                const trendCtx = document.getElementById('trendChart').getContext('2d');
                new Chart(trendCtx, {
                    type: 'line',
                    data: {
                        labels: ${JSON.stringify(trendLabels)},
                        datasets: [
                            {
                                label: '消费金额',
                                data: ${JSON.stringify(trendAmounts)},
                                backgroundColor: 'rgba(226, 35, 26, 0.2)',
                                borderColor: 'rgba(226, 35, 26, 1)',
                                borderWidth: 2,tension: 0.3,
                                fill: true
                            },
                            {
                                label: '订单数量',
                                data: ${JSON.stringify(trendCounts)},
                                backgroundColor: 'rgba(245, 118, 42, 0.2)',
                                borderColor: 'rgba(245, 118, 42, 1)',
                                borderWidth: 2,
                                tension: 0.3,
                                yAxisID: 'y1'
                            }
                        ]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        scales: {
                            y: {
                                beginAtZero: true,
                                title: {
                                    display: true,
                                    text: '金额 (元)'
                                }
                            },
                            y1: {
                                beginAtZero: true,
                                position: 'right',
                                title: {
                                    display: true,
                                    text: '订单数'
                                },
                                grid: {
                                    drawOnChartArea: false
                                }
                            }
                        }
                    }
                });

                // 品类占比图
                const categoryCtx = document.getElementById('categoryChart').getContext('2d');
                new Chart(categoryCtx, {
                    type: 'doughnut',
                    data: {
                        labels: ${JSON.stringify(categoryLabels)},
                        datasets: [{
                            data: ${JSON.stringify(categoryData)},
                            backgroundColor: [
                                'rgba(226, 35, 26, 0.8)',
                                'rgba(245, 118, 42, 0.8)',
                                'rgba(255, 193, 7, 0.8)',
                                'rgba(76, 175, 80, 0.8)',
                                'rgba(33, 150, 243, 0.8)',
                                'rgba(156, 39, 176, 0.8)',
                                'rgba(233, 30, 99, 0.8)'
                            ],
                            borderWidth: 1
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        plugins: {
                            legend: {
                                position: 'right'
                            }
                        }
                    }
                });

                // 店铺分布图
                const shopCtx = document.getElementById('shopChart').getContext('2d');
                new Chart(shopCtx, {
                    type: 'bar',
                    data: {
                        labels: ${JSON.stringify(shopLabels)},
                        datasets: [{
                            label: '订单数量',
                            data: ${JSON.stringify(shopData)},
                            backgroundColor: 'rgba(226, 35, 26, 0.7)',
                            borderWidth: 0
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        scales: {
                            y: {
                                beginAtZero: true
                            }
                        }
                    }
                });
            </script>
        </body>
        </html>
        `;

        // 创建下载
        const blob = new Blob([reportHTML], { type: "text/html;charset=utf-8;" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = `PDD_分析报告_${new Date().toISOString().slice(0,10)}.html`;
        document.body.appendChild(a);
        a.click();

        // 自动打开报告
        setTimeout(() => {
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
            window.open(url, '_blank');
        }, 100);

        logMessage("✅ 分析报告生成成功!");
    }

    // ===== 绑定点击事件 =====
    document.getElementById("exportOrdersBtn").addEventListener("click", function() {
        autoScrollUntilDone(() => {
            if (extractOrderData()) {
                calculateStatistics();
                downloadCSV();
            } else {
                logMessage("⚠️ 未找到有效订单数据", "error");
            }
        });
    });

    document.getElementById("generateReportBtn").addEventListener("click", function() {
        if (orderData.items.length > 0) {
            calculateStatistics();
            generateHTMLReport();
        } else {
            logMessage("⚠️ 请先导出订单数据", "error");
            autoScrollUntilDone(() => {
                if (extractOrderData()) {
                    calculateStatistics();
                    generateHTMLReport();
                }
            });
        }
    });

    // ===== 初始化提示 =====
    setTimeout(() => {
        logMessage("🛒 拼多多订单分析工具已加载,点击按钮开始导出/分析");
    }, 1000);
})();