Greasy Fork

来自缓存

Greasy Fork is available in English.

卓大爷-报活动

悬停滚动优化+操作提示+状态同步

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         卓大爷-报活动
// @namespace    http://your-namespace.com
// @version      8.7.2
// @description  悬停滚动优化+操作提示+状态同步
// @author       卓大爷
// @match        https://seller.kuajingmaihuo.com/*
// @run-at       document-end
// @grant        none
// @icon         https://www.example.com/hisoka-official-art.png
// ==/UserScript==

(function() {
    'use strict';

    let calculatorInitialized = false;
    let currentZIndex = 1000000;
    const MATERIAL_CONFIG = {
        '丝印钢化膜 0.55元': {
            base: 0.55,
            material: [0.40, 0.45+0.55*1, 0.49+0.55*2, 0.54+0.55*3, 0.58+0.55*4],
            unit: '张'
        },
        '水凝膜 0.5元': {
            base: 0.50,
            material: [0.40, 0.45+0.50*1, 0.49+0.50*2, 0.54+0.50*3, 0.58+0.50*4],
            unit: '张'
        },
        '白片 0.35元': {
            base: 0.35,
            material: [0.40, 0.45+0.35*1, 0.49+0.35*2, 0.54+0.35*3, 0.58+0.35*4],
            unit: '张'
        },
        '透明手机壳 1元': {
            base: 1.00,
            material: [0.12, 0.14+1*1, 0.16+1*2, 0.18+1*3, 0.20+1*4],
            unit: '个'
        },
        '备用1': {
            base: 1.20,
            material: [0.15, 0.18+1.2*1, 0.20+1.2*2, 0.22+1.2*3, 0.25+1.2*4],
            unit: '个'
        },
        '备用2': {
            base: 1.20,
            material: [0.15, 0.18+1.2*1, 0.20+1.2*2, 0.22+1.2*3, 0.25+1.2*4],
            unit: '个'
        }
    };

    // 创建悬浮球
    function createFloatingBall() {
        const floatingBall = document.createElement('div');
        floatingBall.id = 'hisoka-floating-ball';
        floatingBall.style.cssText = `
            position: fixed;
            bottom: 40px;
            right: 40px;
            width: 50px;
            height: 50px;
            background: #4CAF50;
            border-radius: 13%;
            cursor: pointer;
            box-shadow: 0 4px 12px rgba(0,0,0,0.25);
            z-index: ${currentZIndex + 1};
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
            font-size: 15px;
            user-select: none;
            transition: all 0.2s;
        `;
        floatingBall.textContent = '来💰财';

        floatingBall.addEventListener('mousedown', () => floatingBall.style.transform = 'scale(0.9)');
        floatingBall.addEventListener('mouseup', () => floatingBall.style.transform = 'scale(1)');
        floatingBall.addEventListener('click', toggleCalculator);
        document.body.appendChild(floatingBall);
    }

    // 切换计算器显示
    function toggleCalculator() {
        const container = document.getElementById('profit-calculator-container');
        if (!container) return initCalculator();

        if (container.style.display === 'none') {
            currentZIndex += 2;
            container.style.cssText = `
                display: block;
                z-index: ${currentZIndex};
                left: 50%;
                top: 50%;
                transform: translate(-50%, -50%);
            `;
            document.getElementById('hisoka-floating-ball').style.zIndex = currentZIndex + 1;
        } else {
            container.style.display = 'none';
        }
    }

    // 双击处理函数
    function handleDoubleClick(e) {
        const container = document.getElementById('profit-calculator-container');
        if (!container || container.style.display === 'none') return;
        if (e.target.closest('input, button, select')) return;

        const selection = window.getSelection();
        if (!selection.rangeCount) return;

        const clickedText = selection.toString().trim();
        const numberMatch = clickedText.match(/(-?\d+\.?\d*)/);
        if (!numberMatch) return;

        const parsedNumber = parseFloat(numberMatch[0]);
        if (isNaN(parsedNumber)) return;

        const priceInput = document.getElementById('profit-price-input');
        priceInput.value = Math.max(0, parsedNumber).toFixed(2);
        priceInput.dispatchEvent(new Event('input', { bubbles: true }));

        document.querySelectorAll('.preset-profit-btn').forEach(b => b.classList.remove('active'));

        e.stopPropagation();
        e.preventDefault();
    }

    function initCalculator() {
        if (calculatorInitialized) return;
        calculatorInitialized = true;

        // 防覆盖样式
        const antiCoverStyle = document.createElement('style');
        antiCoverStyle.textContent = `
            div[style*="z-index: 999999"] { z-index: 99999 !important; }
            #profit-calculator-container { z-index: ${currentZIndex} !important; }
            #hisoka-floating-ball { z-index: ${currentZIndex + 1} !important; }
        `;
        document.head.appendChild(antiCoverStyle);

        // 主样式
        const style = document.createElement('style');
        style.textContent = `
            #profit-calculator-container {
                position: fixed;
                width: 400px;
                background: white;
                border-radius: 8px;
                box-shadow: 0 4px 20px rgba(0,0,0,0.15);
                font-family: "Microsoft YaHei", sans-serif;
                border: 1px solid #4CAF50;
                transition: all 0.3s;
            }
            #profit-calculator-header {
                padding: 12px;
                background: #4CAF50;
                color: white;
                cursor: move;
                user-select: none;
                border-radius: 8px 8px 0 0;
            }
            .header-controls {
                display: flex;
                justify-content: space-between;
                align-items: center;
            }
            .window-controls button {
                background: transparent;
                border: none;
                color: white;
                cursor: pointer;
                padding: 3px 3px;
                font-size: 35px;
            }
            .profit-input-grid {
                display: grid;
                grid-template-columns: 1fr 1fr;
                gap: 12px;
                padding: 20px;
            }
            .profit-input-field {
                width: 100%;
                padding: 8px;
                border: 1px solid #ddd;
                border-radius: 4px;
            }
            .profit-result-table {
                width: 100%;
                border-collapse: collapse;
                margin: 20px 0;
            }
            .profit-result-table td {
                padding: 12px;
                border: 1px solid #ddd;
                text-align: center;
                cursor: ns-resize;
            }
            .profit-high { color: #28a745; }
            .profit-medium { color: #1f618d; }
            .profit-lingyuangou { color: #8A2BE2; }
            .profit-low { color: #dc3545; }
            .preset-buttons-container {
                padding: 0 20px 10px;
                display: flex;
                flex-wrap: wrap;
                gap: 5px;
            }
            .preset-profit-btn {
                flex: 1 1 15%;
                min-width: 60px;
                padding: 6px;
                border: 1px solid #ddd;
                border-radius: 4px;
                background: #f8f9fa;
                cursor: pointer;
                transition: all 0.2s;
                font-size: 12px;
            }
            .preset-profit-btn.clear-btn {
                background-color: #dc3545 !important;
                color: white !important;
                border-color: #bd2130 !important;
            }
            .preset-profit-btn.clear-btn:hover {
                background-color: #c82333 !important;
            }
            .preset-profit-btn.active {
                background: #4CAF50 !important;
                color: white;
                border-color: #45a049;
            }
            .preset-profit-btn:hover {
                background: #e9ecef;
            }
            .tip-icon {
                margin-right: 5px;
                font-size: 14px;
            }
            .image-tip {
                font-size: 12px;
                color: #666;
                padding: 8px 12px;
                border-top: 1px solid #eee;
                background: #f8f8f8;
            }
        `;
        document.head.appendChild(style);

        // 容器结构
        const container = document.createElement('div');
        container.id = 'profit-calculator-container';
        container.innerHTML = `
            <div id="profit-calculator-header">
                <div class="header-controls">
                    <span>   报活动利润检查器 上架选200% 三倍报价</span>
                    <div class="window-controls">
                        <button id="profit-close-btn">×</button>
                    </div>
                </div>
                <div class="image-tip">
                    <span class="tip-icon">ℹ️</span>鼠标悬停可滚轮调价,双击数字自动填充ℹ️卓大爷
                </div>
            </div>
            <div class="profit-input-grid">
                <div>
                    <select id="profit-material-type" class="profit-input-field">
                        <option value="">选择产品款式</option>
                        ${Object.keys(MATERIAL_CONFIG).map(k => `<option value="${k}">${k}</option>`).join('')}
                    </select>
                </div>
                <div>
                    <select id="profit-quantity" class="profit-input-field">
                        <option value="">选择数量</option>
                        ${[1,2,3,4,5].map(n => `<option value="${n}">${n}</option>`).join('')}
                    </select>
                </div>
                <div>
                    <input type="number" id="profit-price-input" class="profit-input-field" placeholder="活动申报价 (¥)" step="0.01">
                </div>
                <div>
                    <input type="number" id="profit-cost-input" class="profit-input-field" placeholder="总成本 (¥)" readonly>
                </div>
            </div>
            <div class="preset-buttons-container" id="preset-buttons"></div>
            <table class="profit-result-table">
                <tr>
                    <td id="profit-rate">利润率%</td>
                    <td id="profit-amount">利润额人民币</td>
                    <td id="profit-suggestion">建议</td>
                </tr>
            </table>
        `;
        document.body.appendChild(container);

        // 添加预设按钮
        const presetPercentages = [0,5,10,15,20,25,30,35,40,45,50,100,"上架>",200,"<三倍"];

        const buttonsContainer = document.getElementById('preset-buttons');
        presetPercentages.forEach(pct => {
            const btn = document.createElement('button');
            btn.className = 'preset-profit-btn';
            btn.textContent = `${pct}%`;
            btn.dataset.percentage = pct;
            buttonsContainer.appendChild(btn);
        });
        const clearBtn = document.createElement('button');
        clearBtn.className = 'preset-profit-btn clear-btn';
        clearBtn.textContent = '清空申报价';
        clearBtn.onclick = () => {
            document.getElementById('profit-price-input').value = '';
            calculateProfit();
            document.querySelectorAll('.preset-profit-btn').forEach(b => b.classList.remove('active'));
        };
        buttonsContainer.appendChild(clearBtn);

        // 拖拽功能
        let isDragging = false;
        let startX = 0, startY = 0;
        let initialX = 0, initialY = 0;

        document.getElementById('profit-calculator-header').addEventListener('mousedown', (e) => {
            if (e.target.closest('button')) return;

            isDragging = true;
            const rect = container.getBoundingClientRect();
            startX = e.clientX;
            startY = e.clientY;
            initialX = rect.left;
            initialY = rect.top;

            currentZIndex += 2;
            container.style.zIndex = currentZIndex;
            document.body.style.userSelect = 'none';
            document.body.style.cursor = 'grabbing';
            container.style.transition = 'none';
        });

        document.addEventListener('mousemove', (e) => {
            if (!isDragging) return;

            const newX = initialX + (e.clientX - startX);
            const newY = initialY + (e.clientY - startY);
            const maxX = window.innerWidth - container.offsetWidth;

            container.style.left = `${Math.max(-20, Math.min(newX, maxX + 20))}px`;
            container.style.top = `${Math.max(0, newY)}px`;
        });

        document.addEventListener('mouseup', () => {
            if (!isDragging) return;
            isDragging = false;

            const rect = container.getBoundingClientRect();
            const finalX = Math.max(0, Math.min(rect.left, window.innerWidth - container.offsetWidth));

            container.style.cssText = `
                left: ${finalX}px;
                top: ${rect.top}px;
                transition: all 0.3s;
                z-index: ${currentZIndex};
            `;
            document.body.style.userSelect = '';
            document.body.style.cursor = '';
        });

        // 核心业务逻辑
        function updateCost() {
            const material = document.getElementById('profit-material-type').value;
            const quantity = document.getElementById('profit-quantity').value;
            if (!material || !quantity) {
                document.getElementById('profit-cost-input').value = '';
                return;
            }

            const config = MATERIAL_CONFIG[material];
            if (!config || !config.material[quantity-1]) return;

            const totalCost = (config.base + config.material[quantity-1]).toFixed(2);
            document.getElementById('profit-cost-input').value = totalCost;
            calculateProfit();
        }

        function calculateProfit() {
            const price = parseFloat(document.getElementById('profit-price-input').value);
            const cost = parseFloat(document.getElementById('profit-cost-input').value);

            if (isNaN(price)) {
                document.getElementById('profit-rate').textContent = '-';
                document.getElementById('profit-amount').textContent = '-';
                document.getElementById('profit-suggestion').textContent = '-';
                return;
            }

            if (isNaN(cost)) return;

            const profit = (price - cost).toFixed(2);
            const profitRate = cost ? ((profit / cost) * 100).toFixed(2) : 0;

            document.getElementById('profit-rate').textContent = `${profitRate}%`;
            document.getElementById('profit-amount').textContent = profit;

            const suggestion = document.getElementById('profit-suggestion');
            suggestion.className = '';
            if (profit < 0) {
                suggestion.textContent = '❌ 亏损 狗都不做';
                suggestion.classList.add('profit-low');
            } else if (profitRate >= 30) {
                suggestion.textContent = '✅ 吃鸡 大吉大利';
                suggestion.classList.add('profit-high');
            } else if (profitRate >= 15) {
                suggestion.textContent = '⚠️ 及时提高利润';
                suggestion.classList.add('profit-medium');
            } else {
                suggestion.textContent = '❗ 零元购 主打陪伴吗?';
                suggestion.classList.add('profit-lingyuangou');
            }
        }

        // 新增悬停滚动选择功能
        const productSelect = document.getElementById('profit-material-type');
        const quantitySelect = document.getElementById('profit-quantity');

        function setupScrollSelect(selectElement) {
            const handleWheel = (e) => {
                e.preventDefault();
                const validOptions = Array.from(selectElement.options)
                    .filter(opt => opt.value !== '');

                if (validOptions.length === 0) return;

                let currentIndex = validOptions.findIndex(opt =>
                    opt === selectElement.options[selectElement.selectedIndex]
                );

                // 处理初始未选择状态
                if (currentIndex === -1) {
                    selectElement.selectedIndex = validOptions[0].index;
                    currentIndex = 0;
                } else {
                    const delta = e.deltaY > 0 ? 1 : -1;
                    currentIndex = (currentIndex + delta + validOptions.length) % validOptions.length;
                }

                selectElement.selectedIndex = validOptions[currentIndex].index;
                selectElement.dispatchEvent(new Event('change'));
            };

            selectElement.addEventListener('mouseenter', () => {
                selectElement.addEventListener('wheel', handleWheel);
            });

            selectElement.addEventListener('mouseleave', () => {
                selectElement.removeEventListener('wheel', handleWheel);
            });
        }

        // 启用滚动选择
        setupScrollSelect(productSelect);
        setupScrollSelect(quantitySelect);

        // 增强版滚轮处理
        function handleWheel(e, step) {
            e.preventDefault();
            const priceInput = document.getElementById('profit-price-input');
            let price = parseFloat(priceInput.value) || 0;
            price = (price + step).toFixed(2);
            priceInput.value = Math.max(0, price);

            document.querySelectorAll('.preset-profit-btn').forEach(b => b.classList.remove('active'));
            calculateProfit();
        }

        // 优化事件绑定
        const priceInputContainer = document.querySelector('.profit-input-grid > div:nth-child(3)');
        priceInputContainer.addEventListener('wheel', (e) => {
            if (!document.activeElement.matches('#profit-price-input')) {
                handleWheel(e, e.deltaY > 0 ? -0.01 : 0.01);
            }
        });

        // 保持原有单元格滚动
        document.getElementById('profit-rate').addEventListener('wheel', (e) => handleWheel(e, e.deltaY > 0 ? -0.01 : 0.01));
        document.getElementById('profit-amount').addEventListener('wheel', (e) => handleWheel(e, e.deltaY > 0 ? -0.01 : 0.01));

        // 输入框聚焦状态处理
        document.getElementById('profit-price-input').addEventListener('focus', () => {
            priceInputContainer.style.pointerEvents = 'none';
        });
        document.getElementById('profit-price-input').addEventListener('blur', () => {
            priceInputContainer.style.pointerEvents = 'auto';
        });

        // 事件绑定
        document.addEventListener('dblclick', handleDoubleClick);

        buttonsContainer.addEventListener('click', (e) => {
            const btn = e.target.closest('.preset-profit-btn');
            if (!btn) return;

            document.querySelectorAll('.preset-profit-btn').forEach(b => b.classList.remove('active'));

            const material = document.getElementById('profit-material-type').value;
            const quantity = document.getElementById('profit-quantity').value;
            const costInput = document.getElementById('profit-cost-input');

            if (!material || !quantity) return alert('请先选择产品和数量');
            if (!costInput.value) return alert('无法获取成本信息');

            const cost = parseFloat(costInput.value);
            const percentage = parseFloat(btn.dataset.percentage) / 100;
            const suggestedPrice = (cost * (1 + percentage)).toFixed(2);

            document.getElementById('profit-price-input').value = suggestedPrice;
            calculateProfit();
            btn.classList.add('active');
        });

        buttonsContainer.addEventListener('dblclick', (e) => {
            const btn = e.target.closest('.preset-profit-btn');
            if (btn) btn.classList.remove('active');
        });

        document.getElementById('profit-price-input').addEventListener('input', function() {
            document.querySelectorAll('.preset-profit-btn').forEach(b => b.classList.remove('active'));
            calculateProfit();
        });

        document.getElementById('profit-material-type').addEventListener('change', function() {
            document.querySelectorAll('.preset-profit-btn').forEach(b => b.classList.remove('active'));
            const unit = MATERIAL_CONFIG[this.value]?.unit || '';
            Array.from(document.getElementById('profit-quantity').options).forEach(opt => {
                if (opt.value) opt.text = `${opt.value} ${unit}`;
            });
            updateCost();
        });

        document.getElementById('profit-quantity').addEventListener('change', function() {
            document.querySelectorAll('.preset-profit-btn').forEach(b => b.classList.remove('active'));
            updateCost();
        });

        document.getElementById('profit-close-btn').addEventListener('click', () => container.style.display = 'none');

        // 初始化计算
        updateCost();
        container.style.display = 'block';
    }

    window.addEventListener('load', createFloatingBall);
})();