Greasy Fork

Greasy Fork is available in English.

EPIC游戏库存导出

精确提取EPIC游戏订单信息,基于HTML表格结构,包括付款金额、游戏名称、订单日期等。

当前为 2025-06-29 提交的版本,查看 最新版本

// ==UserScript==
// @name         EPIC游戏库存导出
// @namespace    http://tampermonkey.net/
// @version      1.3
// @license PaperTiger
// @description  精确提取EPIC游戏订单信息,基于HTML表格结构,包括付款金额、游戏名称、订单日期等。
// @author       Paper Tiger
// @match         *://*.epicgames.com/account/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.0/xlsx.full.min.js
// @grant        none
// ==/UserScript==

/* global XLSX */

(function() {
    'use strict';

    let isProcessing = false;
    let currentPage = 0;
    let allOrderData = [];

    function createExportButton() {
        const button = document.createElement('button');
        button.textContent = '开始导出';
        button.id = 'epic-export-btn';
        button.style.position = 'fixed';
        button.style.top = '10px';
        button.style.right = '400px';
        button.style.zIndex = '99999';
        button.style.padding = '10px';
        button.style.backgroundColor = 'rgba(40, 167, 69, 1)';
        button.style.color = 'white';
        button.style.border = '2px solid red';
        button.style.borderRadius = '5px';
        button.style.cursor = 'pointer';
        document.body.appendChild(button);

        // 创建进度显示区域
        const progressDiv = document.createElement('div');
        progressDiv.id = 'epic-progress';
        progressDiv.style.position = 'fixed';
        progressDiv.style.top = '50px';
        progressDiv.style.right = '400px';
        progressDiv.style.zIndex = '99999';
        progressDiv.style.padding = '10px';
        progressDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
        progressDiv.style.color = 'white';
        progressDiv.style.borderRadius = '5px';
        progressDiv.style.display = 'none';
        progressDiv.style.maxWidth = '300px';
        document.body.appendChild(progressDiv);

        button.addEventListener('click', function() {
            if (!isProcessing) {
                isProcessing = true;
                button.textContent = '处理中...';
                button.disabled = true;
                allOrderData = []; // 清空之前的数据
                currentPage = 0;
                clickTransactions();
            }
        });
    }

    function updateProgress(message) {
        const progressDiv = document.getElementById('epic-progress');
        if (progressDiv) {
            progressDiv.style.display = 'block';
            progressDiv.innerHTML = message;
        }
    }

    function clickTransactions() {
        const transactionsButton = document.querySelector('#nav-link-transactions');
        if (transactionsButton) {
            transactionsButton.click();
            console.log('点击了交易按钮');
            updateProgress('正在加载交易页面...');
            // 等待页面加载后开始提取数据
            setTimeout(extractCurrentPageData, 2000);
        } else {
            console.log("找不到交易按钮。");
            updateProgress('找不到交易按钮,请确保在正确的页面上。');
            resetButton();
        }
    }

    function extractCurrentPageData() {
        currentPage++;
        updateProgress(`正在处理第 ${currentPage} 页...`);

        // 查找所有订单行 - 使用更精确的选择器
        const orderRows = document.querySelectorAll('tr[data-orderid]');
        console.log(`第 ${currentPage} 页找到 ${orderRows.length} 个订单`);

        orderRows.forEach((row, index) => {
            try {
                const orderData = extractOrderDataFromRow(row);
                if (orderData) {
                    allOrderData.push(orderData);
                    console.log(`提取订单: ${orderData['游戏名称']} - ${orderData['付款金额']}`);
                }
            } catch (error) {
                console.error(`提取第 ${index + 1} 个订单数据时出错:`, error);
            }
        });

        console.log(`第 ${currentPage} 页提取了 ${orderRows.length} 个订单,总计 ${allOrderData.length} 个订单`);

        // 检查是否有下一页
        setTimeout(checkNextPage, 1000);
    }

    function extractOrderDataFromRow(row) {
        try {
            // 获取订单ID
            const orderId = row.getAttribute('data-orderid') || '';

            // 获取订单信息单元格 (第二个td)
            const infoCell = row.querySelector('td:nth-child(2)');
            if (!infoCell) {
                console.warn('找不到订单信息单元格');
                return null;
            }

            // 提取日期 - 第一个div元素
            const dateElement = infoCell.querySelector('div:first-child');
            const orderDate = dateElement ? dateElement.textContent.trim() : '';

            // 提取游戏名称 - 查找包含游戏名称的span元素
            let gameName = '';
            const gameNameElements = infoCell.querySelectorAll('.am-hoct6b');
            if (gameNameElements.length > 0) {
                gameName = gameNameElements[0].textContent.trim();
            }

            // 提取价格信息 - 查找包含"价格"文本的元素
            let price = '0.00';
            const priceElements = infoCell.querySelectorAll('.am-brjg0');
            for (let element of priceElements) {
                if (element.textContent.includes('价格')) {
                    const priceContainer = element.nextElementSibling;
                    if (priceContainer && priceContainer.classList.contains('am-1v0j95h')) {
                        const priceText = priceContainer.textContent.trim();
                        // 提取价格数字,处理 "¥0.00" 或 "- ¥0.00" 格式
                        const priceMatch = priceText.match(/[¥$]?([\d.,]+)/);
                        if (priceMatch) {
                            price = priceMatch[1];
                        }
                        break;
                    }
                }
            }

            // 提取商城信息
            let marketplace = '';
            for (let element of priceElements) {
                if (element.textContent.includes('商城')) {
                    const marketplaceContainer = element.nextElementSibling;
                    if (marketplaceContainer && marketplaceContainer.classList.contains('am-1v0j95h')) {
                        marketplace = marketplaceContainer.textContent.trim();
                        break;
                    }
                }
            }

            // 提取说明信息
            let description = '';
            for (let element of priceElements) {
                if (element.textContent.includes('说明')) {
                    const descContainer = element.nextElementSibling;
                    if (descContainer && descContainer.classList.contains('am-1v0j95h')) {
                        const descElement = descContainer.querySelector('.am-1rqw9bo');
                        if (descElement) {
                            description = descElement.textContent.trim();
                        }
                        break;
                    }
                }
            }

            return {
                '订单ID': orderId,
                '订单日期': orderDate,
                '游戏名称': gameName,
                '说明': description,
                '付款金额': price,
                '商城': marketplace,
                '页面': currentPage
            };
        } catch (error) {
            console.error('提取订单数据时出错:', error);
            return null;
        }
    }

    function checkNextPage() {
        const nextButton = document.querySelector('#next-btn');
        if (nextButton && !nextButton.disabled) {
            nextButton.click();
            console.log('点击了下一页按钮');
            updateProgress(`正在加载第 ${currentPage + 1} 页...`);
            // 等待页面加载后继续提取
            setTimeout(extractCurrentPageData, 2000);
        } else {
            console.log("没有更多页面可以加载。");
            updateProgress(`处理完成!共提取 ${allOrderData.length} 个订单。正在生成Excel文件...`);
            // 等待最后一页数据完全加载
            setTimeout(exportData, 2000);
        }
    }

    function exportData() {
        if (allOrderData.length === 0) {
            alert('没有提取到任何订单数据,请检查页面是否正确加载。');
            resetButton();
            return;
        }

        console.log(`准备导出 ${allOrderData.length} 条订单数据`);

        const workbook = XLSX.utils.book_new();
        const worksheet = XLSX.utils.json_to_sheet(allOrderData);
        XLSX.utils.book_append_sheet(workbook, worksheet, '订单历史');
        XLSX.writeFile(workbook, `EPIC游戏订单历史_${new Date().toISOString().slice(0, 10)}.xlsx`);

        alert(`导出完成!共导出 ${allOrderData.length} 条订单数据。`);
        resetButton();
    }

    function resetButton() {
        const button = document.getElementById('epic-export-btn');
        const progressDiv = document.getElementById('epic-progress');

        if (button) {
            button.textContent = '开始导出';
            button.disabled = false;
        }

        if (progressDiv) {
            progressDiv.style.display = 'none';
        }

        isProcessing = false;
    }

    createExportButton();
})();