// ==UserScript==
// @name 52pj帖子列表增强
// @match https://www.52pojie.cn/*
// @version 3.1
// @description 实时监测并修改链接样式,集成可视化设置面板(支持回帖奖励、悬赏已解决、悬赏金额动态样式)
// @author aura service
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @license ISC
// ==/UserScript==
(function() {
'use strict';
// ---------- 配置存储 ----------
const defaultStyles = { fontWeight: 'bold', color: 'red', fontSize: '16px' };
let styles = {
fontWeight: GM_getValue('fontWeight', defaultStyles.fontWeight),
color: GM_getValue('color', defaultStyles.color),
fontSize: GM_getValue('fontSize', defaultStyles.fontSize)
};
const defaultResolvedAction = 'mark';
const defaultResolvedBgColor = '#f0f0f0';
let resolvedAction = GM_getValue('resolvedAction', defaultResolvedAction);
let resolvedBgColor = GM_getValue('resolvedBgColor', defaultResolvedBgColor);
const REWARD_ENABLED_KEY = 'rewardEnabled';
const REWARD_RULES_KEY = 'rewardRules';
const defaultRewardRules = [
{ min: 1, max: 9, style: { color: 'green', fontWeight: 'normal', fontSize: '', backgroundColor: '' } },
{ min: 10, max: 49, style: { color: 'orange', fontWeight: 'bold', fontSize: '', backgroundColor: '' } },
{ min: 50, max: 99, style: { color: 'red', fontWeight: 'bold', fontSize: '16px', backgroundColor: '' } },
{ min: 100, max: null, style: { color: 'purple', fontWeight: 'bold', fontSize: '18px', backgroundColor: '#ffffcc' } }
];
let rewardEnabled = GM_getValue(REWARD_ENABLED_KEY, false);
let rewardRules = GM_getValue(REWARD_RULES_KEY, defaultRewardRules);
// 预设规则集
const presets = {
default: defaultRewardRules,
warm: [
{ min: 1, max: 9, style: { color: '#d97706', fontWeight: 'normal', fontSize: '', backgroundColor: '' } },
{ min: 10, max: 49, style: { color: '#c2410c', fontWeight: 'bold', fontSize: '15px', backgroundColor: '' } },
{ min: 50, max: 99, style: { color: '#b91c1c', fontWeight: 'bold', fontSize: '16px', backgroundColor: '#fef3c7' } },
{ min: 100, max: null, style: { color: '#7b341e', fontWeight: 'bold', fontSize: '18px', backgroundColor: '#ffedd5' } }
],
cool: [
{ min: 1, max: 9, style: { color: '#0284c7', fontWeight: 'normal', fontSize: '', backgroundColor: '' } },
{ min: 10, max: 49, style: { color: '#075985', fontWeight: 'bold', fontSize: '15px', backgroundColor: '' } },
{ min: 50, max: 99, style: { color: '#1e3a8a', fontWeight: 'bold', fontSize: '16px', backgroundColor: '#dbeafe' } },
{ min: 100, max: null, style: { color: '#172554', fontWeight: 'bold', fontSize: '18px', backgroundColor: '#bfdbfe' } }
],
highlight: [
{ min: 1, max: 9, style: { color: 'black', fontWeight: 'normal', fontSize: '', backgroundColor: '#fef9c3' } },
{ min: 10, max: 49, style: { color: 'black', fontWeight: 'bold', fontSize: '15px', backgroundColor: '#fde047' } },
{ min: 50, max: 99, style: { color: 'black', fontWeight: 'bold', fontSize: '16px', backgroundColor: '#facc15' } },
{ min: 100, max: null, style: { color: 'black', fontWeight: 'bold', fontSize: '18px', backgroundColor: '#eab308' } }
]
};
// ---------- 辅助函数 ----------
function getStyleForReward(amount) {
if (!rewardEnabled) return null;
for (const rule of rewardRules) {
if (amount >= rule.min && (rule.max === null || amount <= rule.max)) {
return rule.style;
}
}
return null;
}
// ---------- 核心处理函数(与之前相同)----------
function checkAndModify() {
const rows = document.querySelectorAll('tbody tr');
rows.forEach(row => {
// 回帖奖励
const ths = row.querySelectorAll('th.common, th.new');
let hasReward = false;
ths.forEach(th => {
const span = th.querySelector('span');
if (span && span.textContent.includes('回帖奖励')) hasReward = true;
});
if (hasReward) {
const links = row.querySelectorAll('th.common a.s.xst, th.new a.s.xst');
links.forEach(link => {
link.style.fontWeight = styles.fontWeight;
link.style.color = styles.color;
link.style.fontSize = styles.fontSize;
});
}
// 悬赏已解决标记/隐藏
const rewardIcon = row.querySelector('td.icn img[src*="rewardsmall.gif"]');
if (rewardIcon) {
const resolvedLink = Array.from(row.querySelectorAll('th a')).find(a => a.textContent.trim() === '[已解决]');
if (resolvedLink) {
if (resolvedAction === 'mark') row.style.backgroundColor = resolvedBgColor;
else if (resolvedAction === 'hide') row.style.display = 'none';
}
}
// 悬赏金额动态样式
if (rewardEnabled && rewardIcon) {
const rewardLink = row.querySelector('th a[href*="specialtype=reward"]');
if (rewardLink) {
const amountSpan = rewardLink.querySelector('span.xw1');
if (amountSpan) {
const amount = parseInt(amountSpan.textContent.trim(), 10);
if (!isNaN(amount)) {
const style = getStyleForReward(amount);
if (style) {
const titleLink = row.querySelector('th.common a.s.xst, th.new a.s.xst');
if (titleLink) {
for (const [prop, val] of Object.entries(style)) {
if (val) titleLink.style[prop] = val;
}
}
}
}
}
}
}
});
}
// ---------- 优化后的设置面板 ----------
let settingsPanel = null;
function createSettingsPanel() {
if (settingsPanel) {
settingsPanel.style.display = settingsPanel.style.display === 'none' ? 'block' : 'none';
return;
}
// 创建面板容器
const panel = document.createElement('div');
panel.id = 'pj-settings-panel';
Object.assign(panel.style, {
position: 'fixed',
top: '60px',
right: '20px',
width: '560px',
maxHeight: '80vh',
overflowY: 'auto',
backgroundColor: '#fff',
border: 'none',
borderRadius: '12px',
boxShadow: '0 10px 25px rgba(0,0,0,0.15)',
padding: '20px',
zIndex: '9999',
fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
fontSize: '14px',
display: 'block',
transition: 'box-shadow 0.2s'
});
// ----- 可拖动的标题栏 -----
const header = document.createElement('div');
Object.assign(header.style, {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: '16px',
paddingBottom: '8px',
borderBottom: '1px solid #eef2f6',
cursor: 'move',
userSelect: 'none'
});
header.innerHTML = '
⚙️ 52pj 增强设置
';
const closeBtn = document.createElement('button');
closeBtn.textContent = '✕';
Object.assign(closeBtn.style, {
background: 'none',
border: 'none',
fontSize: '18px',
cursor: 'pointer',
padding: '0 8px',
color: '#64748b',
borderRadius: '4px'
});
closeBtn.onclick = () => panel.style.display = 'none';
header.appendChild(closeBtn);
panel.appendChild(header);
// 拖动逻辑
let isDragging = false, offsetX, offsetY;
header.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - panel.offsetLeft;
offsetY = e.clientY - panel.offsetTop;
panel.style.transition = 'none';
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
panel.style.left = (e.clientX - offsetX) + 'px';
panel.style.top = (e.clientY - offsetY) + 'px';
panel.style.right = 'auto';
});
document.addEventListener('mouseup', () => {
isDragging = false;
panel.style.transition = '';
});
// ----- 回帖奖励样式卡片 -----
const section1 = document.createElement('div');
section1.style.marginBottom = '24px';
section1.innerHTML = '📌 回帖奖励样式
';
const rewardStyleContainer = document.createElement('div');
rewardStyleContainer.style.display = 'flex';
rewardStyleContainer.style.gap = '12px';
rewardStyleContainer.style.flexWrap = 'wrap';
// 字体粗细
const weightGroup = document.createElement('div');
weightGroup.style.flex = '1 1 100px';
weightGroup.innerHTML = '';
const weightSelect = document.createElement('select');
weightSelect.style.width = '100%';
weightSelect.style.padding = '6px';
weightSelect.style.border = '1px solid #cbd5e1';
weightSelect.style.borderRadius = '6px';
weightSelect.innerHTML = '';
weightSelect.value = styles.fontWeight;
weightGroup.appendChild(weightSelect);
rewardStyleContainer.appendChild(weightGroup);
// 颜色
const colorGroup = document.createElement('div');
colorGroup.style.flex = '1 1 100px';
colorGroup.innerHTML = '';
const colorInput = document.createElement('input');
colorInput.type = 'color';
colorInput.value = styles.color;
colorInput.style.width = '100%';
colorInput.style.height = '34px';
colorInput.style.border = '1px solid #cbd5e1';
colorInput.style.borderRadius = '6px';
colorGroup.appendChild(colorInput);
rewardStyleContainer.appendChild(colorGroup);
// 字体大小
const sizeGroup = document.createElement('div');
sizeGroup.style.flex = '1 1 100px';
sizeGroup.innerHTML = '';
const sizeInput = document.createElement('input');
sizeInput.type = 'text';
sizeInput.value = styles.fontSize;
sizeInput.placeholder = '16px';
sizeInput.style.width = '100%';
sizeInput.style.padding = '6px';
sizeInput.style.border = '1px solid #cbd5e1';
sizeInput.style.borderRadius = '6px';
sizeGroup.appendChild(sizeInput);
rewardStyleContainer.appendChild(sizeGroup);
section1.appendChild(rewardStyleContainer);
// 预览
const previewReward = document.createElement('div');
previewReward.style.marginTop = '8px';
previewReward.style.padding = '8px 12px';
previewReward.style.background = '#f8fafc';
previewReward.style.borderRadius = '6px';
previewReward.style.border = '1px solid #e2e8f0';
previewReward.style.display = 'flex';
previewReward.style.alignItems = 'center';
previewReward.style.gap = '8px';
previewReward.innerHTML = '预览:';
const previewSpan = document.createElement('span');
previewSpan.textContent = '【回帖奖励】示例文本';
previewSpan.style.fontWeight = styles.fontWeight;
previewSpan.style.color = styles.color;
previewSpan.style.fontSize = styles.fontSize;
previewReward.appendChild(previewSpan);
section1.appendChild(previewReward);
panel.appendChild(section1);
// 实时更新预览
const updateRewardPreview = () => {
previewSpan.style.fontWeight = weightSelect.value;
previewSpan.style.color = colorInput.value;
previewSpan.style.fontSize = sizeInput.value;
};
weightSelect.addEventListener('change', updateRewardPreview);
colorInput.addEventListener('input', updateRewardPreview);
sizeInput.addEventListener('input', updateRewardPreview);
// ----- 悬赏已解决处理卡片 -----
const section2 = document.createElement('div');
section2.style.marginBottom = '24px';
section2.innerHTML = '🔍 悬赏已解决处理
';
const actionGroup = document.createElement('div');
actionGroup.style.display = 'flex';
actionGroup.style.gap = '8px';
actionGroup.style.marginBottom = '12px';
const actions = [
{ value: 'none', label: '无操作' },
{ value: 'mark', label: '标记背景' },
{ value: 'hide', label: '隐藏整行' }
];
const radioButtons = [];
actions.forEach(act => {
const btn = document.createElement('button');
btn.type = 'button';
btn.textContent = act.label;
btn.dataset.value = act.value;
Object.assign(btn.style, {
flex: '1',
padding: '8px 0',
border: '1px solid #cbd5e1',
borderRadius: '20px',
background: resolvedAction === act.value ? '#3b82f6' : '#ffffff',
color: resolvedAction === act.value ? '#ffffff' : '#334155',
fontWeight: resolvedAction === act.value ? '500' : 'normal',
cursor: 'pointer',
transition: '0.2s'
});
btn.addEventListener('click', () => {
radioButtons.forEach(b => {
b.style.background = '#ffffff';
b.style.color = '#334155';
});
btn.style.background = '#3b82f6';
btn.style.color = '#ffffff';
currentResolvedAction = act.value;
});
actionGroup.appendChild(btn);
radioButtons.push(btn);
});
section2.appendChild(actionGroup);
// 背景色选择
const bgGroup = document.createElement('div');
bgGroup.style.display = 'flex';
bgGroup.style.alignItems = 'center';
bgGroup.style.gap = '12px';
bgGroup.style.marginTop = '8px';
bgGroup.innerHTML = '背景色:';
const bgColorInput = document.createElement('input');
bgColorInput.type = 'color';
bgColorInput.value = resolvedBgColor;
bgColorInput.style.width = '60px';
bgColorInput.style.height = '34px';
bgColorInput.style.border = '1px solid #cbd5e1';
bgColorInput.style.borderRadius = '6px';
const bgPreview = document.createElement('div');
bgPreview.style.width = '30px';
bgPreview.style.height = '30px';
bgPreview.style.borderRadius = '4px';
bgPreview.style.border = '1px solid #cbd5e1';
bgPreview.style.background = resolvedBgColor;
bgGroup.appendChild(bgColorInput);
bgGroup.appendChild(bgPreview);
section2.appendChild(bgGroup);
let currentResolvedAction = resolvedAction;
bgColorInput.addEventListener('input', () => {
bgPreview.style.background = bgColorInput.value;
});
panel.appendChild(section2);
// ----- 悬赏金额动态样式卡片 -----
const section3 = document.createElement('div');
section3.style.marginBottom = '24px';
section3.innerHTML = '💰 悬赏金额动态样式
';
// 启用开关
const enableGroup = document.createElement('div');
enableGroup.style.display = 'flex';
enableGroup.style.alignItems = 'center';
enableGroup.style.gap = '8px';
enableGroup.style.marginBottom = '16px';
const enableCheck = document.createElement('input');
enableCheck.type = 'checkbox';
enableCheck.id = 'rewardEnableCheck';
enableCheck.checked = rewardEnabled;
const enableLabel = document.createElement('label');
enableLabel.htmlFor = 'rewardEnableCheck';
enableLabel.textContent = '启用悬赏金额样式';
enableLabel.style.color = '#334155';
enableGroup.appendChild(enableCheck);
enableGroup.appendChild(enableLabel);
section3.appendChild(enableGroup);
// 预设下拉菜单
const presetGroup = document.createElement('div');
presetGroup.style.display = 'flex';
presetGroup.style.alignItems = 'center';
presetGroup.style.gap = '8px';
presetGroup.style.marginBottom = '12px';
presetGroup.innerHTML = '预设样式:';
const presetSelect = document.createElement('select');
presetSelect.style.padding = '6px';
presetSelect.style.border = '1px solid #cbd5e1';
presetSelect.style.borderRadius = '6px';
presetSelect.innerHTML = `
`;
presetGroup.appendChild(presetSelect);
const applyPresetBtn = document.createElement('button');
applyPresetBtn.textContent = '应用预设';
applyPresetBtn.style.padding = '6px 12px';
applyPresetBtn.style.background = '#e2e8f0';
applyPresetBtn.style.border = '1px solid #cbd5e1';
applyPresetBtn.style.borderRadius = '6px';
applyPresetBtn.style.cursor = 'pointer';
presetGroup.appendChild(applyPresetBtn);
section3.appendChild(presetGroup);
// 规则表格
const table = document.createElement('table');
table.style.width = '100%';
table.style.borderCollapse = 'collapse';
table.style.fontSize = '13px';
table.innerHTML = `
| 最低 |
最高 |
颜色 |
加粗 |
背景色 |
字号 |
预览 |
|
`;
const tbody = table.querySelector('#rulesTbody');
section3.appendChild(table);
// 添加规则按钮
const addBtn = document.createElement('button');
addBtn.textContent = '+ 添加规则';
Object.assign(addBtn.style, {
marginTop: '8px',
padding: '6px 12px',
background: '#e2e8f0',
border: '1px solid #cbd5e1',
borderRadius: '6px',
cursor: 'pointer',
color: '#1e293b'
});
section3.appendChild(addBtn);
panel.appendChild(section3);
// ----- 按钮组 -----
const btnGroup = document.createElement('div');
btnGroup.style.display = 'flex';
btnGroup.style.justifyContent = 'flex-end';
btnGroup.style.gap = '10px';
btnGroup.style.marginTop = '20px';
btnGroup.style.borderTop = '1px solid #e2e8f0';
btnGroup.style.paddingTop = '16px';
const resetBtn = document.createElement('button');
resetBtn.textContent = '重置默认';
resetBtn.style.padding = '8px 16px';
resetBtn.style.background = '#f1f5f9';
resetBtn.style.border = '1px solid #cbd5e1';
resetBtn.style.borderRadius = '6px';
resetBtn.style.cursor = 'pointer';
const applyBtn = document.createElement('button');
applyBtn.textContent = '应用';
applyBtn.style.padding = '8px 20px';
applyBtn.style.background = '#3b82f6';
applyBtn.style.border = 'none';
applyBtn.style.borderRadius = '6px';
applyBtn.style.color = 'white';
applyBtn.style.cursor = 'pointer';
const saveBtn = document.createElement('button');
saveBtn.textContent = '保存并关闭';
saveBtn.style.padding = '8px 20px';
saveBtn.style.background = '#1e293b';
saveBtn.style.border = 'none';
saveBtn.style.borderRadius = '6px';
saveBtn.style.color = 'white';
saveBtn.style.cursor = 'pointer';
const cancelBtn = document.createElement('button');
cancelBtn.textContent = '关闭';
cancelBtn.style.padding = '8px 16px';
cancelBtn.style.background = '#ef4444';
cancelBtn.style.border = 'none';
cancelBtn.style.borderRadius = '6px';
cancelBtn.style.color = 'white';
cancelBtn.style.cursor = 'pointer';
btnGroup.appendChild(resetBtn);
btnGroup.appendChild(applyBtn);
btnGroup.appendChild(saveBtn);
btnGroup.appendChild(cancelBtn);
panel.appendChild(btnGroup);
document.body.appendChild(panel);
settingsPanel = panel;
// ---------- 辅助函数:创建规则行(带预览) ----------
function createRuleRow(rule = { min: 1, max: null, style: { color: '#000000', fontWeight: 'normal', backgroundColor: '#ffffff', fontSize: '' } }) {
const tr = document.createElement('tr');
tr.style.borderBottom = '1px solid #e2e8f0';
// 最低
const tdMin = document.createElement('td');
const minInput = document.createElement('input');
minInput.type = 'number';
minInput.value = rule.min;
minInput.style.width = '60px';
minInput.style.padding = '4px';
minInput.style.border = '1px solid #cbd5e1';
minInput.style.borderRadius = '4px';
tdMin.appendChild(minInput);
tr.appendChild(tdMin);
// 最高
const tdMax = document.createElement('td');
const maxInput = document.createElement('input');
maxInput.type = 'number';
maxInput.value = rule.max !== null ? rule.max : '';
maxInput.placeholder = '无上限';
maxInput.style.width = '60px';
maxInput.style.padding = '4px';
maxInput.style.border = '1px solid #cbd5e1';
maxInput.style.borderRadius = '4px';
tdMax.appendChild(maxInput);
tr.appendChild(tdMax);
// 颜色
const tdColor = document.createElement('td');
const colorPicker = document.createElement('input');
colorPicker.type = 'color';
colorPicker.value = rule.style.color || '#000000';
colorPicker.style.width = '40px';
colorPicker.style.height = '30px';
colorPicker.style.border = 'none';
tdColor.appendChild(colorPicker);
tr.appendChild(tdColor);
// 加粗
const tdBold = document.createElement('td');
tdBold.style.textAlign = 'center';
const boldCheck = document.createElement('input');
boldCheck.type = 'checkbox';
boldCheck.checked = rule.style.fontWeight === 'bold';
tdBold.appendChild(boldCheck);
tr.appendChild(tdBold);
// 背景色
const tdBg = document.createElement('td');
const bgPicker = document.createElement('input');
bgPicker.type = 'color';
bgPicker.value = rule.style.backgroundColor || '#ffffff';
bgPicker.style.width = '40px';
bgPicker.style.height = '30px';
bgPicker.style.border = 'none';
tdBg.appendChild(bgPicker);
tr.appendChild(tdBg);
// 字号
const tdSize = document.createElement('td');
const sizeInput = document.createElement('input');
sizeInput.type = 'text';
sizeInput.value = rule.style.fontSize || '';
sizeInput.placeholder = '14px';
sizeInput.style.width = '50px';
sizeInput.style.padding = '4px';
sizeInput.style.border = '1px solid #cbd5e1';
sizeInput.style.borderRadius = '4px';
tdSize.appendChild(sizeInput);
tr.appendChild(tdSize);
// 预览单元格
const tdPreview = document.createElement('td');
const previewSpan = document.createElement('span');
previewSpan.textContent = '预览';
previewSpan.style.padding = '2px 6px';
previewSpan.style.borderRadius = '4px';
previewSpan.style.color = rule.style.color || '#000000';
previewSpan.style.fontWeight = rule.style.fontWeight || 'normal';
previewSpan.style.backgroundColor = rule.style.backgroundColor || 'transparent';
previewSpan.style.fontSize = rule.style.fontSize || 'inherit';
tdPreview.appendChild(previewSpan);
tr.appendChild(tdPreview);
// 删除按钮
const tdDel = document.createElement('td');
const delBtn = document.createElement('button');
delBtn.textContent = '✕';
delBtn.style.background = 'none';
delBtn.style.border = 'none';
delBtn.style.color = '#ef4444';
delBtn.style.fontSize = '16px';
delBtn.style.cursor = 'pointer';
delBtn.onclick = () => tr.remove();
tdDel.appendChild(delBtn);
tr.appendChild(tdDel);
// 实时更新预览
function updatePreview() {
previewSpan.style.color = colorPicker.value;
previewSpan.style.fontWeight = boldCheck.checked ? 'bold' : 'normal';
previewSpan.style.backgroundColor = bgPicker.value === '#ffffff' ? 'transparent' : bgPicker.value;
previewSpan.style.fontSize = sizeInput.value || 'inherit';
}
colorPicker.addEventListener('input', updatePreview);
boldCheck.addEventListener('change', updatePreview);
bgPicker.addEventListener('input', updatePreview);
sizeInput.addEventListener('input', updatePreview);
minInput.addEventListener('input', updatePreview); // 虽然不影响预览,但为了统一
maxInput.addEventListener('input', updatePreview);
return tr;
}
// 填充现有规则
function loadRulesToTable(rules) {
tbody.innerHTML = '';
rules.forEach(rule => {
tbody.appendChild(createRuleRow(rule));
});
}
loadRulesToTable(rewardRules);
// 应用预设
applyPresetBtn.addEventListener('click', () => {
const presetName = presetSelect.value;
loadRulesToTable(presets[presetName]);
});
// 添加规则
addBtn.addEventListener('click', () => {
tbody.appendChild(createRuleRow());
});
// 重置默认
resetBtn.addEventListener('click', () => {
loadRulesToTable(defaultRewardRules);
});
// ---------- 保存功能 ----------
function saveSettings(closeAfterSave = false) {
// 回帖奖励样式
styles.fontWeight = weightSelect.value;
styles.color = colorInput.value;
styles.fontSize = sizeInput.value;
GM_setValue('fontWeight', styles.fontWeight);
GM_setValue('color', styles.color);
GM_setValue('fontSize', styles.fontSize);
// 悬赏已解决
resolvedAction = currentResolvedAction;
GM_setValue('resolvedAction', resolvedAction);
resolvedBgColor = bgColorInput.value;
GM_setValue('resolvedBgColor', resolvedBgColor);
// 悬赏金额
rewardEnabled = enableCheck.checked;
GM_setValue(REWARD_ENABLED_KEY, rewardEnabled);
// 从表格构建规则
const newRules = [];
for (const row of tbody.children) {
const inputs = row.querySelectorAll('input');
const min = parseInt(inputs[0].value);
if (isNaN(min)) continue;
const max = inputs[1].value ? parseInt(inputs[1].value) : null;
const color = inputs[2].value;
const bold = inputs[3].checked;
const bg = inputs[4].value;
const fontSize = inputs[5].value;
const style = {
color: color,
fontWeight: bold ? 'bold' : 'normal',
};
if (bg && bg !== '#ffffff') style.backgroundColor = bg;
if (fontSize) style.fontSize = fontSize;
newRules.push({ min, max, style });
}
rewardRules = newRules;
GM_setValue(REWARD_RULES_KEY, rewardRules);
// 立即应用
checkAndModify();
if (closeAfterSave) {
panel.style.display = 'none';
} else {
const savedTip = document.createElement('div');
savedTip.textContent = '✓ 已应用';
Object.assign(savedTip.style, {
position: 'fixed',
bottom: '20px',
right: '20px',
background: '#10b981',
color: 'white',
padding: '8px 16px',
borderRadius: '20px',
boxShadow: '0 2px 8px rgba(0,0,0,0.2)',
zIndex: '10000'
});
document.body.appendChild(savedTip);
setTimeout(() => savedTip.remove(), 1500);
}
}
applyBtn.addEventListener('click', () => saveSettings(false));
saveBtn.addEventListener('click', () => saveSettings(true));
cancelBtn.addEventListener('click', () => panel.style.display = 'none');
}
// ---------- 注册菜单命令 ----------
GM_registerMenuCommand("⚙️ 打开设置面板", createSettingsPanel);
// ---------- 启动核心功能 ----------
const observer = new MutationObserver(checkAndModify);
observer.observe(document.body, { childList: true, subtree: true });
checkAndModify();
setInterval(checkAndModify, 1000);
})();