热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
本提示词模板专为浏览器自动化脚本开发设计,能够根据用户需求智能生成功能完整、安全可靠的UserScript代码。通过深度分析目标网站特性和自动化需求,提供结构清晰、注释详尽的脚本代码,支持多种浏览器扩展兼容。亮点包括:采用任务分步法确保代码逻辑严密,内置安全检测机制防止恶意脚本生成,支持动态元素识别和事件处理,提供完善的错误处理和兼容性保障。该模板能够显著降低脚本开发门槛,让非专业用户也能快速创建高质量的浏览器自动化脚本,同时为专业开发者提供灵活的定制空间,适用于网页内容修改、数据提取、界面优化等多种应用场景。
// ==UserScript==
// @name Deals助手:促销高亮+监控+CSV导出(shop.example.cn)
// @namespace https://example.user.scripts
// @version 1.0.0
// @description 列表/详情页监听价格与库存变动;低价/满减高亮;今日促销清单;批量勾选导出CSV;只看降价/包邮筛选;顶部最近降价提醒。仅Chrome/Edge生效。
// @author YourName
// @match https://shop.example.cn/*
// @run-at document-end
// @noframes
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @compatible chrome
// @compatible edge
// ==/UserScript==
(function () {
'use strict';
// 仅在Chrome/Edge生效
const ua = navigator.userAgent || '';
const isChromium = /\bChrome\/\d+/.test(ua) || /\bEdg\/\d+/.test(ua);
if (!isChromium) {
console.info('[Deals助手] 非Chrome/Edge浏览器,脚本不启用。');
return;
}
// --------------------------- 配置与选择器 ---------------------------
const STORAGE_KEYS = {
THRESHOLD: 'tm_deals_threshold',
WATCHLIST: 'tm_deals_watchlist',
LAST_PRICES: 'tm_deals_last_prices',
DROPS: 'tm_deals_price_drops',
FILTERS: 'tm_deals_filters',
HIDDEN_TOPBAR: 'tm_deals_hidden_topbar',
};
// 默认选择器(可在下方“自定义建议”中调整)
const SELECTORS = {
list: {
container: '.deal-list, .product-list, [data-role="deal-list"], .items, .list',
item: '.deal-item, .product-card, li[data-sku], .item, .product',
id: '[data-sku], [data-id]',
link: 'a[href*="/item/"], a[href*="/detail"], .title a, .name a',
title: '.title, .product-title, [data-role="title"], .name',
price: '.price, .current-price, [data-role="price"], .p-price, .deal-price',
stock: '.stock, .inventory, [data-role="stock"], .p-stock',
coupon: '.coupon, .voucher, [data-role="coupon"], .coupon-area',
promo: '.promo, .tag, .promotion, [data-role="promo"], .p-promos',
shipping: '.shipping, .postage, .freight, [data-role="shipping"], .tag-shipping',
},
detail: {
root: '.product-detail, #product-detail, [data-role="detail-root"], .detail',
id: '[data-sku], [data-id], meta[itemprop="sku"]',
title: 'h1.title, .product-name, [data-role="title"], h1',
price: '.price, .current-price, [data-role="price"], .p-price, .deal-price',
stock: '.stock, .inventory, [data-role="stock"], .p-stock',
coupon: '.coupon-box, .voucher, [data-role="coupon"], .coupon-area',
promo: '.promo, .promotion, [data-role="promo"], .p-promos',
shipping: '.shipping, .postage, .freight, [data-role="shipping"], .ship',
}
};
// --------------------------- 工具函数 ---------------------------
const $ = (sel, root = document) => root.querySelector(sel);
const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel));
const text = (el) => (el ? (el.textContent || '').trim() : '');
const nowTs = () => Date.now();
const clamp = (n, min, max) => Math.min(Math.max(n, min), max);
function parsePrice(str) {
if (!str) return NaN;
// 支持 "¥123.45"、"¥123"、"123元"、"123.45" 等
const m = String(str).replace(/,/g, '').match(/(\d+(?:\.\d+)?)/);
return m ? parseFloat(m[1]) : NaN;
}
function hasFreeShipping(s) {
if (!s) return false;
const t = s.replace(/\s+/g, '');
return /包邮|免邮|免运费/.test(t);
}
function hasFullReduction(s) {
if (!s) return false;
const t = s.replace(/\s+/g, '');
return /满减|满\d+减\d+/.test(t);
}
function toCSV(rows) {
// rows: Array<Array<string|number>>
const escape = (v) => {
const s = (v == null ? '' : String(v)).replace(/"/g, '""');
return `"${s}"`;
};
const lines = rows.map((r) => r.map(escape).join(',')).join('\r\n');
return '\ufeff' + lines; // 加BOM,便于Excel识别中文
}
function download(filename, content, mime = 'text/csv;charset=utf-8;') {
const blob = new Blob([content], { type: mime });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(() => {
URL.revokeObjectURL(url);
a.remove();
}, 0);
}
function throttle(fn, wait = 100) {
let last = 0, timer = null, ctx, args;
return function throttled(...a) {
const now = Date.now();
ctx = this; args = a;
if (now - last >= wait) {
last = now;
fn.apply(ctx, args);
} else {
clearTimeout(timer);
timer = setTimeout(() => {
last = Date.now();
fn.apply(ctx, args);
}, wait - (now - last));
}
};
}
function debounce(fn, wait = 150) {
let timer = null;
return function debounced(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), wait);
};
}
function hashId(str) {
// 简易hash(避免过长ID)
let h = 0;
for (let i = 0; i < str.length; i++) {
h = (h << 5) - h + str.charCodeAt(i);
h |= 0;
}
return 'H' + Math.abs(h);
}
// --------------------------- 状态与存储 ---------------------------
let threshold = Number(GM_getValue(STORAGE_KEYS.THRESHOLD, 99)); // 默认阈值99
let watchlist = GM_getValue(STORAGE_KEYS.WATCHLIST, {}); // { id: { favorite: bool, threshold: number } }
let lastPrices = GM_getValue(STORAGE_KEYS.LAST_PRICES, {}); // { id: { price: number, stock: string, t: number } }
let drops = GM_getValue(STORAGE_KEYS.DROPS, []); // [ {id,title,oldPrice,newPrice,time,url} ]
let filters = GM_getValue(STORAGE_KEYS.FILTERS, { onlyDrop: false, onlyFreeShip: false });
let topbarHidden = !!GM_getValue(STORAGE_KEYS.HIDDEN_TOPBAR, false);
// 内存结构
const itemState = new Map(); // id -> { el, title, price, stock, coupon, promo, shipping, url, isDrop, isHighlighted, selected }
const itemObservers = new Map(); // id -> MutationObserver
const todayHighlightSet = new Set(); // id集合(被高亮的今日促销清单)
// --------------------------- 样式 ---------------------------
GM_addStyle(`
.tmdeals-topbar {
position: fixed; top: 0; left: 0; right: 0; z-index: 999999;
background: #0f172a; color: #fff; font-size: 12px; font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial;
display: flex; align-items: center; gap: 10px; padding: 6px 10px; box-shadow: 0 2px 8px rgba(0,0,0,.15);
}
.tmdeals-topbar a, .tmdeals-topbar button { color: #fff; }
.tmdeals-topbar .drops { display: flex; gap: 10px; flex-wrap: nowrap; overflow: hidden; }
.tmdeals-topbar .drop-item { white-space: nowrap; opacity: .9; }
.tmdeals-topbar .threshold { margin-left: auto; display: flex; align-items: center; gap: 6px; }
.tmdeals-topbar .threshold input {
width: 72px; padding: 2px 6px; border-radius: 4px; border: 1px solid #334155; background: #0b1220; color: #fff;
}
.tmdeals-topbar .filters { display: flex; gap: 8px; margin-left: 10px; }
.tmdeals-topbar .btn {
border: 1px solid #334155; background: #0b1220; padding: 2px 6px; border-radius: 4px; cursor: pointer;
}
.tmdeals-topbar .close { margin-left: 8px; background: transparent; border: none; color: #94a3b8; cursor: pointer; }
.tmdeals-sidebar {
position: fixed; top: 64px; right: 10px; width: 300px; max-height: calc(100vh - 80px);
z-index: 999998; background: #ffffff; color: #111827; border: 1px solid #e5e7eb; border-radius: 8px;
box-shadow: 0 6px 24px rgba(0,0,0,.12); display: flex; flex-direction: column; overflow: hidden;
}
.tmdeals-sidebar .header { padding: 8px 10px; background: #f8fafc; border-bottom: 1px solid #e5e7eb; display: flex; align-items: center; justify-content: space-between; }
.tmdeals-sidebar .list { padding: 8px 10px; overflow: auto; }
.tmdeals-sidebar .item { font-size: 12px; padding: 6px 0; border-bottom: 1px dashed #e5e7eb; }
.tmdeals-sidebar .item a { color: #2563eb; text-decoration: none; }
.tmdeals-sidebar .footer { padding: 8px 10px; border-top: 1px solid #e5e7eb; display: flex; gap: 8px; }
.tmdeals-sidebar .btn { background: #2563eb; color: #fff; border: none; border-radius: 4px; padding: 6px 8px; cursor: pointer; }
.tmdeals-sidebar .btn.secondary { background: #f1f5f9; color: #111827; }
.tmdeals-toolbar {
position: fixed; bottom: 16px; left: 16px; z-index: 999997; background: #fff; color: #111827;
border: 1px solid #e5e7eb; border-radius: 8px; box-shadow: 0 6px 24px rgba(0,0,0,.12);
display: flex; gap: 8px; align-items: center; padding: 8px 10px; font-size: 12px;
}
.tmdeals-toolbar .btn { background: #f1f5f9; border: 1px solid #e5e7eb; border-radius: 4px; padding: 6px 8px; cursor: pointer; }
.tmdeals-checkbox { margin-right: 6px; }
.tmdeals-highlight {
outline: 2px solid #22c55e !important;
box-shadow: 0 0 0 4px rgba(34,197,94,0.15) !important;
border-radius: 6px;
}
.tmdeals-drop-badge {
display: inline-block; margin-left: 6px; padding: 0 6px; font-size: 12px; color: #16a34a; background: #dcfce7; border-radius: 12px;
}
.tmdeals-ctrls {
display: inline-flex; gap: 6px; margin-left: 8px;
}
.tmdeals-ctrls .btn {
font-size: 12px; padding: 2px 6px; border: 1px dashed #94a3b8; border-radius: 4px; background: #f8fafc; cursor: pointer;
}
.tmdeals-hidden { display: none !important; }
`);
// --------------------------- UI 构建 ---------------------------
let topbarEl = null;
let sidebarEl = null;
let toolbarEl = null;
function createTopbar() {
if (topbarEl) return;
topbarEl = document.createElement('div');
topbarEl.className = 'tmdeals-topbar';
topbarEl.innerHTML = `
<strong>降价提醒</strong>
<div class="drops"></div>
<div class="filters">
<label><input type="checkbox" data-action="toggle-only-drop"${filters.onlyDrop ? ' checked' : ''}> 只看降价</label>
<label><input type="checkbox" data-action="toggle-only-freeship"${filters.onlyFreeShip ? ' checked' : ''}> 只看包邮</label>
</div>
<div class="threshold">
<span>阈值¥</span>
<input type="number" min="0" step="0.01" value="${threshold}">
<button class="btn" data-action="save-threshold">保存</button>
</div>
<button class="close" title="隐藏">✕</button>
`;
document.body.appendChild(topbarEl);
if (topbarHidden) {
topbarEl.style.display = 'none';
}
// 事件
const dropsBox = topbarEl.querySelector('.drops');
const refreshDrops = () => {
const list = (drops || []).slice(-5).reverse();
dropsBox.innerHTML = list.map(d => {
return `<span class="drop-item" title="${new Date(d.time).toLocaleString()}">${escapeHtml(d.title)} ¥${d.oldPrice} → ¥${d.newPrice}</span>`;
}).join('') || '<span class="drop-item">暂无数据</span>';
};
refreshDrops();
topbarEl.addEventListener('click', (e) => {
const target = e.target;
if (!(target instanceof Element)) return;
const action = target.getAttribute('data-action');
if (action === 'save-threshold') {
const input = topbarEl.querySelector('.threshold input');
const v = Number(input.value);
if (!isNaN(v) && v >= 0) {
threshold = v;
GM_setValue(STORAGE_KEYS.THRESHOLD, threshold);
applyAllHighlights();
}
} else if (action === 'toggle-only-drop') {
// handled by change event
} else if (action === 'toggle-only-freeship') {
// handled by change event
}
});
topbarEl.querySelector('.close').addEventListener('click', () => {
topbarEl.style.display = 'none';
GM_setValue(STORAGE_KEYS.HIDDEN_TOPBAR, true);
});
topbarEl.addEventListener('change', (e) => {
const target = e.target;
if (!(target instanceof HTMLInputElement)) return;
if (target.getAttribute('data-action') === 'toggle-only-drop') {
filters.onlyDrop = target.checked;
GM_setValue(STORAGE_KEYS.FILTERS, filters);
applyFilters();
} else if (target.getAttribute('data-action') === 'toggle-only-freeship') {
filters.onlyFreeShip = target.checked;
GM_setValue(STORAGE_KEYS.FILTERS, filters);
applyFilters();
}
});
// 暴露刷新方法
createTopbar.refreshDrops = refreshDrops;
}
function createSidebar() {
if (sidebarEl) return;
sidebarEl = document.createElement('div');
sidebarEl.className = 'tmdeals-sidebar';
sidebarEl.innerHTML = `
<div class="header">
<strong>今日促销清单</strong>
<span class="count">0</span>
</div>
<div class="list"></div>
<div class="footer">
<button class="btn" data-action="export-today">导出清单CSV</button>
<button class="btn secondary" data-action="copy-today">复制CSV</button>
</div>
`;
document.body.appendChild(sidebarEl);
sidebarEl.addEventListener('click', (e) => {
const btn = e.target.closest('button');
if (!btn) return;
const action = btn.getAttribute('data-action');
if (action === 'export-today') {
exportTodayCSV();
} else if (action === 'copy-today') {
copyTodayCSV();
}
});
updateSidebar();
}
function createToolbar() {
if (toolbarEl) return;
toolbarEl = document.createElement('div');
toolbarEl.className = 'tmdeals-toolbar';
toolbarEl.innerHTML = `
<label><input type="checkbox" class="tmdeals-select-all"> 全选</label>
<button class="btn" data-action="invert">反选</button>
<button class="btn" data-action="export-selected">导出选中CSV</button>
`;
document.body.appendChild(toolbarEl);
toolbarEl.addEventListener('change', (e) => {
const checkbox = e.target.closest('.tmdeals-select-all');
if (!checkbox) return;
const checked = checkbox.checked;
itemState.forEach(st => {
st.selected = checked;
if (st.el && st.el.isConnected) {
const cb = st.el.querySelector('.tmdeals-item-checkbox');
if (cb) cb.checked = checked;
}
});
});
toolbarEl.addEventListener('click', (e) => {
const btn = e.target.closest('button');
if (!btn) return;
const action = btn.getAttribute('data-action');
if (action === 'invert') {
itemState.forEach(st => {
st.selected = !st.selected;
const cb = st.el?.querySelector('.tmdeals-item-checkbox');
if (cb) cb.checked = !!st.selected;
});
} else if (action === 'export-selected') {
exportSelectedCSV();
}
});
}
function updateSidebar() {
if (!sidebarEl) return;
const listEl = sidebarEl.querySelector('.list');
const countEl = sidebarEl.querySelector('.count');
const items = Array.from(todayHighlightSet)
.map(id => itemState.get(id))
.filter(Boolean);
countEl.textContent = String(items.length);
listEl.innerHTML = items.map(st => {
const price = isFinite(st.price) ? `¥${st.price}` : '—';
const flags = [
st.isDrop ? '降价' : '',
hasFullReduction(st.promo) ? '满减' : '',
(st.coupon ? '券' : ''),
hasFreeShipping(st.shipping) ? '包邮' : ''
].filter(Boolean).join('·');
return `<div class="item">
<a href="${st.url || 'javascript:'}" target="_blank" rel="noreferrer">${escapeHtml(st.title || st.id)}</a>
<div>${price} ${flags ? `<span style="color:#16a34a">[${flags}]</span>` : ''}</div>
</div>`;
}).join('') || '<div class="item">暂无符合条件的商品</div>';
}
function escapeHtml(s) {
return String(s || '')
.replace(/&/g, '&').replace(/</g, '<')
.replace(/>/g, '>').replace(/"/g, '"')
.replace(/'/g, ''');
}
// --------------------------- 页面分析 ---------------------------
function detectPageType() {
// 判断是否为详情页(存在明显详情根节点或URL包含特征)
const isDetail = !!document.querySelector(SELECTORS.detail.root) ||
/\/item\/|\/detail/ig.test(location.pathname);
return { isDetail };
}
// --------------------------- 处理逻辑 ---------------------------
const scheduleScan = debounce(() => {
if (detectPageType().isDetail) {
processDetailPage();
} else {
processListPage();
}
}, 120);
function processListPage() {
const container = $(SELECTORS.list.container) || document.body;
const items = $$(SELECTORS.list.item, container);
if (!items.length) return;
items.forEach(el => processOneItemInList(el));
applyFilters();
}
function processDetailPage() {
const root = $(SELECTORS.detail.root) || document.body;
// 用详情根节点作为单个“item”
processOneDetail(root);
}
function extractFromListItem(el) {
const idNode = el.querySelector(SELECTORS.list.id);
const linkEl = el.querySelector(SELECTORS.list.link);
const titleEl = el.querySelector(SELECTORS.list.title);
const priceEl = el.querySelector(SELECTORS.list.price);
const stockEl = el.querySelector(SELECTORS.list.stock);
const couponEl = el.querySelector(SELECTORS.list.coupon);
const promoEl = el.querySelector(SELECTORS.list.promo);
const shippingEl = el.querySelector(SELECTORS.list.shipping);
const url = linkEl ? linkEl.href : (location.origin + location.pathname);
let id = idNode?.getAttribute('data-sku') || idNode?.getAttribute('data-id');
if (!id) {
// 从URL或标题派生ID
const base = (url || '') + '|' + text(titleEl);
id = hashId(base);
}
const title = text(titleEl) || (linkEl ? text(linkEl) : '');
const price = parsePrice(text(priceEl));
const stock = text(stockEl);
const coupon = text(couponEl);
const promo = text(promoEl);
const shipping = text(shippingEl);
return { id, url, title, price, stock, coupon, promo, shipping, priceEl, stockEl };
}
function extractFromDetail(root) {
const idNode = root.querySelector(SELECTORS.detail.id);
const titleEl = root.querySelector(SELECTORS.detail.title);
const priceEl = root.querySelector(SELECTORS.detail.price);
const stockEl = root.querySelector(SELECTORS.detail.stock);
const couponEl = root.querySelector(SELECTORS.detail.coupon);
const promoEl = root.querySelector(SELECTORS.detail.promo);
const shippingEl = root.querySelector(SELECTORS.detail.shipping);
const url = location.href;
let id = idNode?.getAttribute('content') || idNode?.getAttribute('data-sku') || idNode?.getAttribute('data-id');
if (!id) {
const base = (url || '') + '|' + text(titleEl);
id = hashId(base);
}
const title = text(titleEl);
const price = parsePrice(text(priceEl));
const stock = text(stockEl);
const coupon = text(couponEl);
const promo = text(promoEl);
const shipping = text(shippingEl);
return { id, url, title, price, stock, coupon, promo, shipping, priceEl, stockEl };
}
function ensureItemControls(el, id) {
if (el.querySelector('.tmdeals-item-checkbox')) return;
// 插入勾选框与按钮(尽量靠近标题或价格)
const ctrlWrap = document.createElement('span');
ctrlWrap.className = 'tmdeals-ctrls';
ctrlWrap.innerHTML = `
<label><input type="checkbox" class="tmdeals-item-checkbox tmdeals-checkbox"></label>
<button class="btn" data-action="monitor">监控</button>
<button class="btn" data-action="fav">收藏</button>
`;
// 优先放在标题附近
let anchor = el.querySelector(SELECTORS.list.title) || el.querySelector(SELECTORS.detail.title) || el;
anchor.appendChild(ctrlWrap);
ctrlWrap.addEventListener('click', (e) => {
const btn = e.target.closest('button');
if (!btn) return;
const action = btn.getAttribute('data-action');
if (action === 'monitor') {
const w = watchlist[id] || {};
w.threshold = threshold;
watchlist[id] = w;
GM_setValue(STORAGE_KEYS.WATCHLIST, watchlist);
btn.textContent = '已监控';
} else if (action === 'fav') {
const w = watchlist[id] || {};
w.favorite = true;
watchlist[id] = w;
GM_setValue(STORAGE_KEYS.WATCHLIST, watchlist);
btn.textContent = '已收藏';
}
});
const cb = ctrlWrap.querySelector('.tmdeals-item-checkbox');
cb.addEventListener('change', (e) => {
const st = itemState.get(id);
if (st) st.selected = cb.checked;
});
}
function processOneItemInList(el) {
if (!el || el.dataset.tmdealsProcessed) return;
const data = extractFromListItem(el);
if (!data.id) return;
// 保存/更新状态
const prev = itemState.get(data.id);
const st = Object.assign(prev || {}, data, { el });
itemState.set(data.id, st);
// 价格/库存变动检测
detectChangeAndMark(st);
// 高亮策略(价格<=阈值 或 存在满减)
const highlight = shouldHighlight(st);
applyHighlight(st, highlight);
// 注入控件
ensureItemControls(el, data.id);
// 监听价格与库存节点变动(精确到文本变更)
attachNodeObservers(st);
el.dataset.tmdealsProcessed = '1';
}
function processOneDetail(root) {
if (root.dataset.tmdealsProcessed) return;
const data = extractFromDetail(root);
if (!data.id) return;
const prev = itemState.get(data.id);
const st = Object.assign(prev || {}, data, { el: root });
itemState.set(data.id, st);
detectChangeAndMark(st);
const highlight = shouldHighlight(st);
applyHighlight(st, highlight);
ensureItemControls(root, data.id);
attachNodeObservers(st);
root.dataset.tmdealsProcessed = '1';
}
function shouldHighlight(st) {
const lowPrice = isFinite(st.price) && st.price >= 0 && st.price <= threshold;
const fullReduction = hasFullReduction(st.promo);
return !!(lowPrice || fullReduction);
}
function applyHighlight(st, highlight) {
if (!st || !st.el) return;
st.isHighlighted = !!highlight;
if (st.isHighlighted) {
st.el.classList.add('tmdeals-highlight');
todayHighlightSet.add(st.id);
} else {
st.el.classList.remove('tmdeals-highlight');
todayHighlightSet.delete(st.id);
}
updateSidebar();
}
function detectChangeAndMark(st) {
// 降价检测
const lp = lastPrices[st.id];
if (lp && isFinite(lp.price) && isFinite(st.price) && st.price < lp.price) {
st.isDrop = true;
addDropRecord(st, lp.price, st.price);
// 在标题后追加“降价”徽标(若无则添加)
const titleEl = st.el.querySelector(SELECTORS.list.title) || st.el.querySelector(SELECTORS.detail.title);
if (titleEl && !titleEl.querySelector('.tmdeals-drop-badge')) {
const b = document.createElement('span');
b.className = 'tmdeals-drop-badge';
b.textContent = '降价';
titleEl.appendChild(b);
}
} else {
st.isDrop = false;
}
// 保存最新价格/库存
lastPrices[st.id] = { price: st.price, stock: st.stock, t: nowTs() };
GM_setValue(STORAGE_KEYS.LAST_PRICES, lastPrices);
}
function addDropRecord(st, oldPrice, newPrice) {
const record = {
id: st.id,
title: st.title || st.id,
oldPrice: Number(oldPrice.toFixed ? oldPrice.toFixed(2) : oldPrice),
newPrice: Number(newPrice.toFixed ? newPrice.toFixed(2) : newPrice),
time: Date.now(),
url: st.url || location.href,
};
drops.push(record);
if (drops.length > 50) drops.splice(0, drops.length - 50);
GM_setValue(STORAGE_KEYS.DROPS, drops);
if (createTopbar.refreshDrops) createTopbar.refreshDrops();
}
function attachNodeObservers(st) {
// 避免重复绑定
if (itemObservers.has(st.id)) return;
const obs = new MutationObserver(debounce(() => {
// 重新抽取关键字段(限当前元素)
if (!st.el || !st.el.isConnected) {
// 断开观察
const o = itemObservers.get(st.id);
if (o) o.disconnect();
itemObservers.delete(st.id);
return;
}
const isDetail = detectPageType().isDetail && st.el.matches(SELECTORS.detail.root + ', body, html, .detail');
const data = isDetail ? extractFromDetail(st.el) : extractFromListItem(st.el);
Object.assign(st, data);
detectChangeAndMark(st);
const highlight = shouldHighlight(st);
applyHighlight(st, highlight);
applyFilters(); // 受“只看降价/包邮”影响
}, 120));
const targets = [st.priceEl, st.stockEl].filter(Boolean);
if (!targets.length) return;
targets.forEach(t => {
obs.observe(t, { characterData: true, childList: true, subtree: true });
});
itemObservers.set(st.id, obs);
}
// --------------------------- 筛选与应用 ---------------------------
function applyFilters() {
itemState.forEach((st, id) => {
if (!st.el) return;
let visible = true;
if (filters.onlyDrop && !st.isDrop) visible = false;
if (filters.onlyFreeShip && !hasFreeShipping(st.shipping)) visible = false;
st.el.classList.toggle('tmdeals-hidden', !visible);
});
}
function applyAllHighlights() {
itemState.forEach((st) => {
const highlight = shouldHighlight(st);
applyHighlight(st, highlight);
});
applyFilters();
}
// --------------------------- CSV 导出 ---------------------------
function buildCSVRows(states) {
const header = ['ID', '标题', '价格', '库存', '促销', '券', '运费', '是否降价', 'URL', '时间'];
const rows = [header];
states.forEach(st => {
rows.push([
st.id,
st.title || '',
isFinite(st.price) ? st.price : '',
st.stock || '',
st.promo || '',
st.coupon || '',
st.shipping || '',
st.isDrop ? '是' : '否',
st.url || '',
new Date().toLocaleString()
]);
});
return rows;
}
function exportSelectedCSV() {
const selected = Array.from(itemState.values()).filter(st => st.selected);
if (!selected.length) {
alert('请先勾选要导出的商品。');
return;
}
const rows = buildCSVRows(selected);
const csv = toCSV(rows);
download(`选中商品_${formatDate()}.csv`, csv);
}
function exportTodayCSV() {
const items = Array.from(todayHighlightSet).map(id => itemState.get(id)).filter(Boolean);
if (!items.length) {
alert('今日促销清单为空。');
return;
}
const rows = buildCSVRows(items);
const csv = toCSV(rows);
download(`今日促销清单_${formatDate()}.csv`, csv);
}
function copyTodayCSV() {
const items = Array.from(todayHighlightSet).map(id => itemState.get(id)).filter(Boolean);
const rows = buildCSVRows(items);
const csv = toCSV(rows);
navigator.clipboard.writeText(csv).then(() => {
alert('已复制CSV到剪贴板。');
}).catch(() => {
alert('复制失败,请检查浏览器权限。');
});
}
function formatDate(d = new Date()) {
const p = (n) => String(n).padStart(2, '0');
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}_${p(d.getHours())}${p(d.getMinutes())}${p(d.getSeconds())}`;
}
// --------------------------- 观察与滚动节流 ---------------------------
const onScroll = throttle(() => {
// 预留:可在此添加懒处理逻辑(如按需处理可视区域新元素)
// 当前仅维持UI稳定,无额外操作,避免性能负担
}, 120);
function observeContainerMutations() {
const root = detectPageType().isDetail ? (document.querySelector(SELECTORS.detail.root) || document.body)
: (document.querySelector(SELECTORS.list.container) || document.body);
const obs = new MutationObserver((muts) => {
let needScan = false;
for (const m of muts) {
if (m.addedNodes && m.addedNodes.length) {
needScan = true; break;
}
}
if (needScan) scheduleScan();
});
obs.observe(root, { childList: true, subtree: true });
}
// --------------------------- 菜单命令 ---------------------------
try {
GM_registerMenuCommand('设置阈值', () => {
const v = prompt('请输入价格阈值(元):', String(threshold));
if (v == null) return;
const num = Number(v);
if (!isNaN(num) && num >= 0) {
threshold = num;
GM_setValue(STORAGE_KEYS.THRESHOLD, threshold);
// 顶栏输入也更新
const input = topbarEl?.querySelector('.threshold input');
if (input) input.value = String(threshold);
applyAllHighlights();
} else {
alert('输入无效,请输入非负数字。');
}
});
GM_registerMenuCommand('显示/隐藏 顶部降价栏', () => {
topbarHidden = !topbarHidden;
GM_setValue(STORAGE_KEYS.HIDDEN_TOPBAR, topbarHidden);
if (topbarEl) topbarEl.style.display = topbarHidden ? 'none' : '';
});
} catch (e) {
// 某些环境不支持菜单
}
// --------------------------- 启动 ---------------------------
function init() {
createTopbar();
createSidebar();
createToolbar();
scheduleScan();
observeContainerMutations();
window.addEventListener('scroll', onScroll, { passive: true });
}
// 启动
init();
})();
快速搭建价格监测与优惠提醒脚本,自动高亮重点商品信息,整理促销清单,减少逐页查看与重复点击。
一键过滤关键词与噪音内容,整理公开评论要点,生成互动周报草案,配合快捷回复提升日常运营效率。
无需改动代码即可做页面微改与可用性验证,高亮关键路径、标注交互瓶颈,为A/B决策提供更直观的现场证据。
用一条高效提示词,帮你把“想做的网页自动化”快速变成“可运行的油猴脚本”。通过需求-分析-设计-生成-审查-优化的全流程打包输出,让非技术用户也能在几分钟内得到可用脚本,开发者则拥有可深度定制的工程化模板。核心价值:1) 高成功率:采用分步思考与逻辑校验,减少脚本失效与反复调试;2) 更安全:内置合规与安全检查,避免违规与隐私风险;3) 真易用:结构清晰、注释完整、附安装与使用指南;4) 更稳定:适配动态元素、异常处理、浏览器兼容;5) 可扩展:可在价格监控、社媒自动化、内容过滤、数据提取、学习场景等快速复用。即刻试用,3分钟拿到可运行脚本,显著缩短从想法到上线的距离,提升效率并降低成本。
将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。
把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。
在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。
免费获取高级提示词-优惠即将到期