Greasy Fork is available in English.
5倍价格
当前为
// ==UserScript==
// @name 店小蜜价格助手
// @namespace http://tampermonkey.net/
// @version 4.0.0
// @description 5倍价格
// @author Rayu
// @match https://www.dianxiaomi.com/web/shopeeSite/edit*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// ========================================
// 配置项
// ========================================
const CONFIG = {
// 价格高亮配置
HIGHLIGHT_COLOR: 'yellow',
MULTIPLE_THRESHOLD: 5,
INCLUDE_EQUAL: true,
DEBOUNCE_DELAY: 300,
};
let debounceTimer;
// ========================================
// 公共函数:等待元素加载
// ========================================
function waitForElement(selector, callback, maxAttempts = 50) {
let attempts = 0;
const interval = setInterval(() => {
const element = document.querySelector(selector);
if (element || attempts >= maxAttempts) {
clearInterval(interval);
if (element) callback(element);
}
attempts++;
}, 200);
}
// ========================================
// 公共函数:智能查找价格列
// ========================================
function findPriceColumnIndex() {
const table = document.querySelector('#skuDataInfo table.myj-table');
if (!table) {
console.warn('[价格工具] 未找到表格');
return -1;
}
const headers = table.querySelectorAll('thead th');
let priceColumnIndex = -1;
headers.forEach((th, index) => {
const text = th.textContent.trim();
if ((text.includes('价格') && (text.includes('TWD') || text.includes('$')))
&& !text.includes('促销')) {
priceColumnIndex = index + 1;
console.log(`[价格工具] 找到"价格"列,索引为 ${priceColumnIndex},表头文本: "${text}"`);
}
});
return priceColumnIndex;
}
// ========================================
// 公共函数:获取价格输入框
// ========================================
function findPriceInputs() {
const priceColumnIndex = findPriceColumnIndex();
if (priceColumnIndex !== -1) {
const selector = `#skuDataInfo tbody tr td:nth-child(${priceColumnIndex}) .sku-valid-item > div > input.g-form-component:not([disabled])`;
const inputs = document.querySelectorAll(selector);
if (inputs.length > 0) {
console.log(`[价格工具] 通过表头匹配找到 ${inputs.length} 个价格输入框`);
return Array.from(inputs);
}
}
// 回退策略
const fallbackSelectors = [
'#skuDataInfo tbody tr td:nth-child(4) input.g-form-component:not([disabled])',
'#skuDataInfo tbody tr td:nth-child(5) input.g-form-component:not([disabled])',
];
for (let selector of fallbackSelectors) {
const inputs = document.querySelectorAll(selector);
if (inputs.length > 0) {
console.log(`[价格工具] 使用回退选择器找到 ${inputs.length} 个价格输入框: ${selector}`);
return Array.from(inputs);
}
}
console.warn('[价格工具] 无法找到任何价格输入框');
return [];
}
// ========================================
// 功能1: 价格高亮显示
// ========================================
function highlightPrices() {
console.log('[价格高亮] 执行价格高亮...');
const priceInputs = findPriceInputs();
if (priceInputs.length === 0) {
console.log('[价格高亮] 未找到价格输入框');
return;
}
const validPrices = [];
const inputElements = [];
priceInputs.forEach(input => {
input.style.backgroundColor = '';
const priceStr = input.value.trim();
const price = parseFloat(priceStr);
if (!isNaN(price) && price > 0) {
validPrices.push(price);
inputElements.push(input);
}
});
if (validPrices.length === 0) {
console.log('[价格高亮] 没有有效价格可供比较');
return;
}
const minPrice = Math.min(...validPrices);
const thresholdPrice = minPrice * CONFIG.MULTIPLE_THRESHOLD;
console.log(`[价格高亮] 最低价: ${minPrice}, 阈值: ${thresholdPrice} (${CONFIG.MULTIPLE_THRESHOLD}倍)`);
let highlightCount = 0;
inputElements.forEach(input => {
const currentPrice = parseFloat(input.value);
if (!isNaN(currentPrice)) {
if (CONFIG.INCLUDE_EQUAL) {
if (currentPrice >= thresholdPrice) {
input.style.backgroundColor = CONFIG.HIGHLIGHT_COLOR;
highlightCount++;
}
} else {
if (currentPrice > thresholdPrice) {
input.style.backgroundColor = CONFIG.HIGHLIGHT_COLOR;
highlightCount++;
}
}
}
});
console.log(`[价格高亮] 共高亮 ${highlightCount} 个价格,总计 ${inputElements.length} 个`);
}
// ========================================
// 功能2: 移除极值价格商品
// ========================================
// 提取价格数据
function extractPriceData() {
const priceInputs = findPriceInputs();
if (priceInputs.length === 0) return null;
const priceData = [];
priceInputs.forEach((input, index) => {
const value = input.value.trim();
const price = parseFloat(value);
if (!isNaN(price) && price > 0) {
priceData.push({
price: price,
rowIndex: index,
input: input
});
}
});
console.log(`[价格移除] 成功提取 ${priceData.length} 个有效价格数据`);
return priceData.length > 0 ? priceData : null;
}
// 找到所有最低价和最高价的商品
function findPriceExtremes(priceData) {
if (!priceData || priceData.length === 0) return null;
let minPriceValue = Math.min(...priceData.map(item => item.price));
let maxPriceValue = Math.max(...priceData.map(item => item.price));
let minPriceItems = priceData.filter(item => item.price === minPriceValue);
let maxPriceItems = priceData.filter(item => item.price === maxPriceValue);
return { minPriceItems, maxPriceItems };
}
// 获取所有复选框
function getAllCheckboxes() {
const checkboxes = [];
const container1 = document.querySelector('#skuAttrInfo > div.form-card-content > div > form > div.sku-attrs-container > div:nth-child(1)');
const container2 = document.querySelector('#skuAttrInfo > div.form-card-content > div > form > div.sku-attrs-container > div:nth-child(2)');
[container1, container2].forEach(container => {
if (container) {
const inputs = container.querySelectorAll('input[type="checkbox"]');
inputs.forEach(input => checkboxes.push(input));
}
});
return checkboxes;
}
// 根据行索引找到对应的复选框并取消勾选
function uncheckByRowIndex(rowIndex) {
const checkboxes = getAllCheckboxes();
if (rowIndex < checkboxes.length) {
const checkbox = checkboxes[rowIndex];
if (checkbox && checkbox.checked) {
checkbox.click();
return true;
}
}
return false;
}
// 移除最低价商品
async function removeMinPrice() {
const priceData = extractPriceData();
if (!priceData || priceData.length === 0) {
alert('无法提取价格数据');
return;
}
const extremes = findPriceExtremes(priceData);
if (!extremes || !extremes.minPriceItems || extremes.minPriceItems.length === 0) {
alert('无法找到最低价');
return;
}
const { minPriceItems } = extremes;
let successCount = 0;
for (const item of minPriceItems) {
if (uncheckByRowIndex(item.rowIndex)) {
successCount++;
console.log(`已移除最低价商品: ¥${item.price}`);
await new Promise(resolve => setTimeout(resolve, 100));
}
}
if (successCount > 0) {
alert(`成功移除 ${successCount} 个最低价商品\n价格: ¥${minPriceItems[0].price}`);
// 移除后重新高亮
setTimeout(highlightPrices, 500);
} else {
alert('移除失败,请检查页面结构');
}
}
// 移除最高价商品
async function removeMaxPrice() {
const priceData = extractPriceData();
if (!priceData || priceData.length === 0) {
alert('无法提取价格数据');
return;
}
const extremes = findPriceExtremes(priceData);
if (!extremes || !extremes.maxPriceItems || extremes.maxPriceItems.length === 0) {
alert('无法找到最高价');
return;
}
const { maxPriceItems } = extremes;
let successCount = 0;
for (const item of maxPriceItems) {
if (uncheckByRowIndex(item.rowIndex)) {
successCount++;
console.log(`已移除最高价商品: ¥${item.price}`);
await new Promise(resolve => setTimeout(resolve, 100));
}
}
if (successCount > 0) {
alert(`成功移除 ${successCount} 个最高价商品\n价格: ¥${maxPriceItems[0].price}`);
// 移除后重新高亮
setTimeout(highlightPrices, 500);
} else {
alert('移除失败,请检查页面结构');
}
}
// ========================================
// UI: 创建操作按钮
// ========================================
function createButtons() {
const container = document.createElement('div');
container.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
z-index: 10000;
display: flex;
flex-direction: column;
gap: 10px;
`;
const minButton = document.createElement('button');
minButton.textContent = '移除最低价';
minButton.style.cssText = `
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
transition: background-color 0.3s;
`;
minButton.addEventListener('mouseenter', () => {
minButton.style.backgroundColor = '#45a049';
});
minButton.addEventListener('mouseleave', () => {
minButton.style.backgroundColor = '#4CAF50';
});
minButton.addEventListener('click', removeMinPrice);
const maxButton = document.createElement('button');
maxButton.textContent = '移除最高价';
maxButton.style.cssText = `
padding: 10px 20px;
background-color: #ff4444;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
transition: background-color 0.3s;
`;
maxButton.addEventListener('mouseenter', () => {
maxButton.style.backgroundColor = '#cc0000';
});
maxButton.addEventListener('mouseleave', () => {
maxButton.style.backgroundColor = '#ff4444';
});
maxButton.addEventListener('click', removeMaxPrice);
container.appendChild(minButton);
container.appendChild(maxButton);
document.body.appendChild(container);
}
// ========================================
// 监听器: MutationObserver
// ========================================
const observerCallback = function(mutationsList, observer) {
console.log('[价格工具] DOM变化检测');
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
highlightPrices();
}, CONFIG.DEBOUNCE_DELAY);
};
function startObserver() {
const targetNode = document.getElementById('skuDataInfo');
if (targetNode) {
const config = {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['value']
};
const observer = new MutationObserver(observerCallback);
observer.observe(targetNode, config);
console.log('[价格工具] MutationObserver 已启动');
highlightPrices();
} else {
console.warn('[价格工具] #skuDataInfo 未找到,重试中...');
let retryCount = 0;
const maxRetries = 10;
const retryInterval = 500;
const findAndObserve = () => {
const dynamicTargetNode = document.getElementById('skuDataInfo');
if (dynamicTargetNode) {
const config = {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['value']
};
const observer = new MutationObserver(observerCallback);
observer.observe(dynamicTargetNode, config);
highlightPrices();
console.log('[价格工具] #skuDataInfo 找到并启动观察器');
} else if (retryCount < maxRetries) {
retryCount++;
console.warn(`[价格工具] 重试中 (${retryCount}/${maxRetries})...`);
setTimeout(findAndObserve, retryInterval);
} else {
console.error('[价格工具] 多次重试后仍未找到 #skuDataInfo');
}
};
setTimeout(findAndObserve, 1000);
}
}
// 监听价格输入框的 input 事件
function attachInputListeners() {
document.addEventListener('input', function(e) {
if (e.target && e.target.classList && e.target.classList.contains('g-form-component')) {
const parentTd = e.target.closest('td');
if (parentTd) {
const table = parentTd.closest('table');
const skuDataInfo = parentTd.closest('#skuDataInfo');
if (table && skuDataInfo && !e.target.disabled) {
console.log('[价格工具] 检测到价格输入,重新计算...');
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
highlightPrices();
}, CONFIG.DEBOUNCE_DELAY);
}
}
}
}, true);
console.log('[价格工具] Input 事件监听器已附加');
}
// ========================================
// 初始化
// ========================================
function init() {
waitForElement('#skuDataInfo', () => {
console.log('[价格工具] 检测到SKU数据表格,初始化功能...');
createButtons();
startObserver();
attachInputListeners();
});
}
// 启动脚本
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
// 延迟执行,确保异步加载的内容也能被处理
setTimeout(() => {
console.log('[价格工具] 延迟执行 (1.5s)');
highlightPrices();
}, 1500);
setTimeout(() => {
console.log('[价格工具] 延迟执行 (4s)');
highlightPrices();
}, 4000);
// 监听页面路由变化(单页应用)
let lastUrl = location.href;
new MutationObserver(() => {
const url = location.href;
if (url !== lastUrl) {
lastUrl = url;
console.log('[价格工具] URL变化,重新初始化...');
setTimeout(() => {
startObserver();
highlightPrices();
}, 2000);
}
}).observe(document, {subtree: true, childList: true});
})();