// ==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
// @downloadURL https://update.greasyfork.icu/scripts/475705/%E5%AD%94%E5%A4%AB%E5%AD%90%E6%97%A7%E4%B9%A6%E7%BD%91%E5%BA%93%E5%AD%98%E6%98%BE%E7%A4%BA%E5%8F%8A%E8%87%AA%E5%8A%A8%E8%AE%A1%E7%AE%97%E5%94%AE%E4%BB%B7.user.js
// @updateURL https://update.greasyfork.icu/scripts/475705/%E5%AD%94%E5%A4%AB%E5%AD%90%E6%97%A7%E4%B9%A6%E7%BD%91%E5%BA%93%E5%AD%98%E6%98%BE%E7%A4%BA%E5%8F%8A%E8%87%AA%E5%8A%A8%E8%AE%A1%E7%AE%97%E5%94%AE%E4%BB%B7.meta.js
// ==/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 = `
包含快递总价: ¥${costPrice.toFixed(2)}
建议售价: ¥${sellingPrice.toFixed(2)}
预计利润(+30%): ¥${profit.toFixed(2)}
`;
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 = '点击查询
展示库存';
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();
}
};
})();