Greasy Fork

来自缓存

Greasy Fork is available in English.

孔夫子旧书网库存显示及自动计算售价

孔夫子库存显示

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         孔夫子旧书网库存显示及自动计算售价
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  孔夫子库存显示
// @author       图南
// @match        https://search.kongfz.com/product_result/*
// @match        https://book.kongfz.com/*
// @grant        GM_xmlhttpRequest
// @connect      book.kongfz.com
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // Function to show price details when on detail page
    function showPriceDetailsOnDetailPage() {
        let productPriceElement = document.querySelector('.now-price .now-price-text');
        let productPrice = parseFloat(productPriceElement.textContent.trim().replace('¥', ''));
        let shippingFeeElement = document.querySelector('.carry-cont .express-wrapper');
        let shippingFeeText = shippingFeeElement.textContent.match(/快递 ¥(\d+(\.\d{1,2})?)/);
        let shippingFee = shippingFeeText ? parseFloat(shippingFeeText[1]) : 0;
        let costPrice = productPrice + shippingFee;
        //修改下面这行,costPrice * 1.3 ,这里的数字就可以了,1.3就是加价30%
        let sellingPrice = costPrice * 1.3;
        let profit = sellingPrice - costPrice;
        let priceInfoDiv = document.createElement('div');
        priceInfoDiv.style.marginTop = '10px';
        priceInfoDiv.style.border = '1px solid #e0e0e0';
        priceInfoDiv.style.padding = '10px';
        priceInfoDiv.style.backgroundColor = '#f7f7f7';
        priceInfoDiv.style.borderRadius = '5px';
        priceInfoDiv.innerHTML = `
            <div style="margin-bottom: 5px;"><strong>包含快递总价:</strong> ¥${costPrice.toFixed(2)}</div>
            <div style="margin-bottom: 5px;"><strong>建议售价:</strong> ¥${sellingPrice.toFixed(2)}</div>
            <div><strong>预计利润(+30%):</strong> ¥${profit.toFixed(2)}</div>
        `;
        let priceContainer = document.querySelector('.now-price');
        priceContainer.insertAdjacentElement('afterend', priceInfoDiv);
    }

    // Functions related to the search page
    function getDetailPageLinks() {
        let detailPageLinks = document.querySelectorAll('.item-info .title a.link');
        let links = Array.from(detailPageLinks).map(link => link.href);
        console.log(`找到了 ${links.length} 个商品详情页链接`);
        return links;
    }

    function fetchStockInfo(link) {
        return new Promise(resolve => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: link,
                onload: function(response) {
                    const parser = new DOMParser();
                    const doc = parser.parseFromString(response.responseText, 'text/html');
                    const stockInfoElementOne = doc.querySelector('.count-state.state-one');
                    const stockInfoElementMultiple = doc.querySelector('.count-state .store-count');
                    let stockInfo = '';
                    if (stockInfoElementOne) {
                        stockInfo = '库存:1';
                    } else if (stockInfoElementMultiple) {
                        stockInfo = '库存:' + stockInfoElementMultiple.textContent.trim();
                    } else {
                        stockInfo = '库存信息暂无';
                    }
                    console.log(`已获取 ${link} 的库存信息: ${stockInfo}`);
                    resolve(stockInfo);
                }
            });
        });
    }

    function displayStockInfo(stockInfo, stockInfoDiv) {
        if (stockInfo) {
            stockInfoDiv.innerText = stockInfo;
            if (stockInfo === '库存:1') {
                stockInfoDiv.style.color = 'red';
                stockInfoDiv.style.fontWeight = 'bold';
            }
        } else {
            stockInfoDiv.innerText = '库存信息暂无';
        }
    }

    async function fetchAndDisplayStockInfo() {
        let detailPageLinks = getDetailPageLinks();
        let concurrentRequests = 5;
        let index = 0;
        while (index < detailPageLinks.length) {
            let batchLinks = detailPageLinks.slice(index, index + concurrentRequests);
            let batchPromises = batchLinks.map(link => fetchStockInfo(link));
            let batchResults = await Promise.all(batchPromises);
            batchResults.forEach((stockInfo, i) => {
                let currentIndex = index + i;
                let stockInfoDiv = document.querySelectorAll('.collection-btn.stock-info')[currentIndex];
                displayStockInfo(stockInfo, stockInfoDiv);
            });
            index += concurrentRequests;
        }
    }

    function removeStockInfoDivs() {
        let oldDivs = document.querySelectorAll('.collection-btn.stock-info');
        oldDivs.forEach(div => div.remove());
        let buyButtonContainers = document.querySelectorAll('.collection-btn.stockInfoAdded');
        buyButtonContainers.forEach(container => container.classList.remove('stockInfoAdded'));
    }

    function initSearchPage() {
        function addStockInfoDivs() {
            let buyButtonContainers = document.querySelectorAll('.collection-btn:not(.stockInfoAdded)');
            console.log(`找到了 ${buyButtonContainers.length} 个“立即购买”容器`);
            buyButtonContainers.forEach(container => {
                let stockInfoDiv = document.createElement('div');
                stockInfoDiv.className = 'collection-btn stock-info';
                stockInfoDiv.style.marginRight = '10px';
                let stockInfoSpan = document.createElement('span');
                stockInfoSpan.className = 'bold';
                stockInfoSpan.innerText = '库存信息加载中...';
                stockInfoDiv.appendChild(stockInfoSpan);
                container.parentNode.insertBefore(stockInfoDiv, container.nextSibling);
                container.classList.add('stockInfoAdded');
            });
        }
        addStockInfoDivs();
        let startFetchButton = document.createElement('button');
        startFetchButton.style.position = 'fixed';
        startFetchButton.style.bottom = '10px';
        startFetchButton.style.right = '10px';
        startFetchButton.style.padding = '10px 20px';
        startFetchButton.style.border = 'none';
        startFetchButton.style.borderRadius = '5px';
        startFetchButton.style.background = '#3498db';
        startFetchButton.style.color = 'white';
        startFetchButton.style.cursor = 'pointer';
        startFetchButton.style.fontSize = '16px';
        startFetchButton.style.transition = 'background 0.3s';
        startFetchButton.style.width = '120px';
        startFetchButton.style.height = '60px';
        startFetchButton.innerHTML = '点击查询<br>展示库存';
        startFetchButton.addEventListener('mouseover', () => {
            startFetchButton.style.background = '#2980b9';
        });
        startFetchButton.addEventListener('mouseout', () => {
            startFetchButton.style.background = '#3498db';
        });
        document.body.appendChild(startFetchButton);
        let isDragging = false;
        let deltaX = 0;
        let deltaY = 0;
        startFetchButton.addEventListener('mousedown', (e) => {
            isDragging = true;
            deltaX = e.clientX - startFetchButton.getBoundingClientRect().left;
            deltaY = e.clientY - startFetchButton.getBoundingClientRect().top;
            e.preventDefault();
        });
        document.addEventListener('mousemove', (e) => {
            if (isDragging) {
                startFetchButton.style.left = e.clientX - deltaX + 'px';
                startFetchButton.style.bottom = 'auto';
                startFetchButton.style.top = e.clientY - deltaY + 'px';
            }
        });
        document.addEventListener('mouseup', () => {
            isDragging = false;
        });
        startFetchButton.addEventListener('click', () => {
            removeStockInfoDivs();
            addStockInfoDivs();
            fetchAndDisplayStockInfo();
        });
    }

    window.onload = function() {
        if (window.location.href.includes("book.kongfz.com")) {
            showPriceDetailsOnDetailPage();
        } else if (window.location.href.includes("search.kongfz.com")) {
            initSearchPage();
        }
    };
})();