// ==UserScript==
// @name 乐斗辅助
// @namespace http://tampermonkey.net/
// @version 1.7.2
// @description 提供系统繁忙监控、定时刷新、碎片监控、骑士岛任务、自动抢地盘、武器血量高亮、黄历、购物道具仓库余量显示、静默方向键控制、定时任务
// @author xiong1136108122
// @match https://dld.qzapp.z.qq.com/*
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addStyle
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @connect qzapp.z.qq.com
// @connect fight.pet.qq.com
// @connect dld.qzapp.z.qq.com
// ==/UserScript==
(function() {
'use strict';
// 配置存储
const CONFIG = {
systemBusy: {
enabled: GM_getValue('systemBusyEnabled', true),
targetText: GM_getValue('systemBusyTargetText', '系统繁忙'),
checkInterval: GM_getValue('systemBusyCheckInterval', 100),
refreshCooldown: GM_getValue('systemBusyRefreshCooldown', 2000)
},
autoRefresh: {
enabled: GM_getValue('autoRefreshEnabled', false),
interval: GM_getValue('autoRefreshInterval', 2),
stopKeywords: GM_getValue('autoRefreshStopKeywords', ['不足','不够'])
},
fragmentMonitor: {
enabled: GM_getValue('fragmentMonitorEnabled', false),
checkUrl: 'https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?zapp_uin=&B_UID=0&sid=&channel=0&g_ut=1&cmd=newAct&subtype=154',
jumpUrl: 'https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?zapp_uin=&B_UID=0&sid=&channel=0&g_ut=1&cmd=newAct&subtype=155',
triggerKeywords: GM_getValue('fragmentTriggerKeywords', ['王重阳', '王处一']),
stopKeywords: GM_getValue('fragmentStopKeywords', ['数量:0', '碎片*5']),
interval: GM_getValue('fragmentMonitorInterval', 2)
},
knightIsland: {
enabled: GM_getValue('knightIslandEnabled', true),
checkInterval: GM_getValue('knightIslandCheckInterval', 90)
},
territoryGrabber: {
enabled: GM_getValue('territoryGrabberEnabled', false),
targetLevel: GM_getValue('territoryGrabberTargetLevel', 30),
retryLimit: GM_getValue('territoryGrabberRetryLimit', 3),
baseDelay: GM_getValue('territoryGrabberBaseDelay', 2000),
maxRandomDelay: GM_getValue('territoryGrabberMaxRandomDelay', 3000)
},
hpHighlight: {
enabled: GM_getValue('hpHighlightEnabled', true)
},
goodsStock: {
enabled: GM_getValue('goodsStockEnabled', true)
},
// 新增:方向键控制配置
directionKey: {
enabled: GM_getValue('directionKeyEnabled', true),
scrollAmount: GM_getValue('directionKeyScrollAmount', 200),
fastScrollAmount: GM_getValue('directionKeyFastScrollAmount', 300),
enableShiftScroll: GM_getValue('directionKeyEnableShiftScroll', true),
ignoreInputs: GM_getValue('directionKeyIgnoreInputs', true),
smoothScroll: GM_getValue('directionKeySmoothScroll', true)
},
// 新增:定时任务配置
scheduledTasks: {
enabled: GM_getValue('scheduledTasksEnabled', false),
tasks: GM_getValue('scheduledTasks', [
{
name: '定时任务',
url: ' ',
time: '06:00:01',
count: 3,
interval: 1000, // 存储为毫秒
enabled: true
}
])
}
};
// 定时器变量
let module2Timer = null;
let module3Timer = null;
let territoryGrabberRetryCount = 0;
let directionKeyLastScrollTime = 0;
/* ========== 新增:定时任务模块 ========== */
// 发送单个请求
function sendScheduledRequest(task, index) {
return new Promise((resolve) => {
GM_xmlhttpRequest({
method: 'GET',
url: task.url,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': '*/*'
},
timeout: 8000,
onload: function(response) {
Mylog(`[定时任务 ${task.name}] 请求 ${index}/${task.count} - 状态: ${response.status}`);
resolve({ success: response.status === 200, status: response.status });
},
onerror: function(error) {
Mylog(`[定时任务 ${task.name}] 请求 ${index}/${task.count} 失败: ${error}`);
resolve({ success: false, error: error });
},
ontimeout: function() {
Mylog(`[定时任务 ${task.name}] 请求 ${index}/${task.count} 超时`);
resolve({ success: false, error: 'timeout' });
}
});
});
}
// 执行单个任务的所有请求
async function executeScheduledTask(task) {
if (!task.enabled) return;
// 记录开始执行时间
const startTime = new Date();
Mylog(`[定时任务 ${task.name}] 开始执行 ${task.count} 次请求 (${startTime.toLocaleString()})`);
const results = [];
for (let i = 1; i <= task.count; i++) {
if (i > 1) {
await new Promise(resolve => setTimeout(resolve, task.interval));
}
const result = await sendScheduledRequest(task, i);
results.push(result);
}
// 统计结果
const successCount = results.filter(r => r.success).length;
const endTime = new Date();
const duration = endTime - startTime;
// 保存执行记录
task.lastExecution = endTime.toISOString();
GM_setValue(`task_lastExecution_${task.name}`, task.lastExecution);
Mylog(`[定时任务 ${task.name}] 执行完成,成功 ${successCount}/${task.count} 次,耗时 ${duration}ms`);
return results;
}
// 添加任务状态检查函数
function checkTaskStatus() {
if (!CONFIG.scheduledTasks.enabled) return;
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
CONFIG.scheduledTasks.tasks.forEach(task => {
if (task.enabled && task.lastExecution) {
const lastExec = new Date(task.lastExecution);
const lastExecDay = new Date(lastExec.getFullYear(), lastExec.getMonth(), lastExec.getDate());
// 如果上次执行不是今天
if (lastExecDay.getTime() !== today.getTime()) {
const [hours, minutes] = task.time.split(':').map(Number);
const taskTime = new Date(today);
taskTime.setHours(hours, minutes, 0, 0);
// 如果任务时间已经过去超过10分钟
if (now - taskTime > 10 * 60 * 1000) {
Mylog(`[定时任务 ${task.name}] 警告:今天可能错过了执行时间`);
}
}
}
});
}
// 格式化延迟时间显示
function formatDelayTime(ms) {
const totalSeconds = Math.floor(ms / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
if (hours > 0) {
return `${hours}小时${minutes}分钟${seconds}秒`;
} else if (minutes > 0) {
return `${minutes}分钟${seconds}秒`;
} else {
return `${seconds}秒`;
}
}
// 为单个任务设置定时器
function setupScheduledTaskTimer(task) {
if (task.timerId) {
clearTimeout(task.timerId);
task.timerId = null;
}
if (!task.enabled || !task.time ) {
Mylog(`[定时任务 ${task.name}] 时间格式无效或被禁用: ${task.time}`);
return;
}
// 使用更精确的时间计算方法
const delay = calculateExactDelay(task.time);
if (delay < 0 || delay > 24 * 60 * 60 * 1000) {
Mylog(`[定时任务 ${task.name}] 时间计算错误: ${task.time}, delay=${delay}ms`);
return;
}
const nextTime = new Date(Date.now() + delay);
Mylog(`[定时任务 ${task.name}] 下次执行: ${nextTime.toLocaleString()} (${formatDelayTime(delay)})`);
// 使用更精确的setTimeout,并记录设置时间
const startTime = Date.now();
task.timerId = setTimeout(async () => {
const actualDelay = Date.now() - startTime;
const deviation = actualDelay - delay;
if (Math.abs(deviation) > 1000) {
Mylog(`[定时任务 ${task.name}] 定时器偏差较大: ${deviation}ms`);
}
Mylog(`[定时任务 ${task.name}] 到达预定时间 ${task.time},开始执行...`);
try {
await executeScheduledTask(task);
Mylog(`[定时任务 ${task.name}] 执行完成`);
} catch (error) {
Mylog(`[定时任务 ${task.name}] 执行出错: ${error}`);
}
// 设置下一轮定时器(立即设置,避免延迟累积)
scheduleNextExecution(task);
}, delay);
}
// 更精确的时间计算方法
function calculateExactDelay(targetTime) {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
// 解析目标时间
const [hours, minutes, seconds] = targetTime.split(':').map(Number);
// 今天的执行时间
const targetToday = new Date(today);
targetToday.setHours(hours, minutes, seconds, 0);
// 明天的执行时间
const targetTomorrow = new Date(today);
targetTomorrow.setDate(targetTomorrow.getDate() + 1);
targetTomorrow.setHours(hours, minutes, seconds, 0);
// 选择最近的一个执行时间
let target = targetToday;
if (now > targetToday) {
target = targetTomorrow;
}
return target.getTime() - now.getTime();
}
// 安排下一次执行(使用更可靠的方法)
function scheduleNextExecution(task) {
// 先清除当前定时器
if (task.timerId) {
clearTimeout(task.timerId);
task.timerId = null;
}
// 等待一小段时间后重新计算,避免立即执行
setTimeout(() => {
setupScheduledTaskTimer(task);
}, 1000); // 1秒后重新设置
}
// 初始化所有定时任务
function initScheduledTasks() {
if (!CONFIG.scheduledTasks.enabled) return;
Mylog(`[定时任务] 初始化,共 ${CONFIG.scheduledTasks.tasks.length} 个任务`);
// 停止所有现有定时器
stopAllScheduledTasks();
// 为每个任务设置定时器
CONFIG.scheduledTasks.tasks.forEach(task => {
setupScheduledTaskTimer(task);
});
}
// 添加每日检查机制
function setupDailyCheck() {
// 每天凌晨2点检查所有定时任务状态
const checkTime = '02:00:00';
const checkDelay = calculateExactDelay(checkTime);
setTimeout(() => {
Mylog('[定时任务] 执行每日状态检查');
checkAndRescheduleTasks();
// 设置下一次检查
setupDailyCheck();
}, checkDelay);
}
// 检查和重新安排任务
function checkAndRescheduleTasks() {
if (!CONFIG.scheduledTasks.enabled) return;
const now = new Date();
const currentHour = now.getHours();
const currentMinute = now.getMinutes();
CONFIG.scheduledTasks.tasks.forEach(task => {
if (task.enabled && task.time) {
const [hours, minutes] = task.time.split(':').map(Number);
const taskTimeMinutes = hours * 60 + minutes;
const currentTimeMinutes = currentHour * 60 + currentMinute;
// 如果任务时间已经过去(在当前时间的2小时内),重新安排
if (taskTimeMinutes < currentTimeMinutes &&
(currentTimeMinutes - taskTimeMinutes) <= 120) {
Mylog(`[定时任务 ${task.name}] 可能错过了今天的执行,重新安排`);
// 强制重新安排
if (task.timerId) {
clearTimeout(task.timerId);
task.timerId = null;
}
setupScheduledTaskTimer(task);
}
}
});
}
// 停止所有定时任务
function stopAllScheduledTasks() {
CONFIG.scheduledTasks.tasks.forEach(task => {
if (task.timerId) {
clearTimeout(task.timerId);
task.timerId = null;
}
});
Mylog('[定时任务] 已停止所有定时任务');
}
// 保存定时任务设置
function saveScheduledTaskSettings() {
try {
// 收集任务数据
const tasks = [];
document.querySelectorAll('.scheduled-task-item').forEach((item, index) => {
const intervalInput = item.querySelector('.task-interval').value;
// 将秒转换为毫秒
const intervalInMs = Math.max(100, Math.floor(parseFloat(intervalInput) * 1000)) || 1000;
const task = {
name: item.querySelector('.task-name').value.trim() || `任务${index + 1}`,
url: item.querySelector('.task-url').value.trim(),
time: item.querySelector('.task-time').value,
count: parseInt(item.querySelector('.task-count').value) || 1,
interval: intervalInMs, // 存储为毫秒
enabled: item.querySelector('.task-enabled').checked
};
if (task.url && task.time) {
tasks.push(task);
}
});
CONFIG.scheduledTasks.tasks = tasks;
GM_setValue('scheduledTasks', tasks);
// 更新任务计数和状态
updateTaskCount();
const taskStatus = document.getElementById('taskStatus');
if (taskStatus) {
taskStatus.textContent = `已保存 ${tasks.length} 个任务`;
taskStatus.style.color = "#4CAF50";
}
// 重新初始化定时任务
if (CONFIG.scheduledTasks.enabled) {
initScheduledTasks();
}
Mylog(`[定时任务] 设置已保存,共 ${tasks.length} 个任务`);
} catch (error) {
console.error("[定时任务] 保存失败:", error);
Mylog("[定时任务] 保存失败: " + error.message);
const taskStatus = document.getElementById('taskStatus');
if (taskStatus) {
taskStatus.textContent = "保存失败";
taskStatus.style.color = "#ff4444";
}
}
}
// 手动执行任务
async function executeTaskNow(taskName) {
const task = CONFIG.scheduledTasks.tasks.find(t => t.name === taskName);
if (task) {
Mylog(`[定时任务] 手动执行: ${taskName}`);
return await executeScheduledTask(task);
} else {
Mylog(`[定时任务] 未找到任务: ${taskName}`);
return null;
}
}
// 测试第一个任务
function testFirstTask() {
if (CONFIG.scheduledTasks.tasks.length > 0) {
const firstTask = CONFIG.scheduledTasks.tasks[0];
Mylog(`[定时任务] 测试执行: ${firstTask.name}`);
executeScheduledTask(firstTask);
} else {
Mylog('[定时任务] 没有可测试的任务');
}
}
// 添加新任务
function addNewTask() {
const tasksContainer = document.getElementById('scheduledTasksList');
if (!tasksContainer) return;
const taskIndex = tasksContainer.children.length + 1;
const taskItem = document.createElement('div');
taskItem.className = 'scheduled-task-item';
taskItem.innerHTML = `
`;
tasksContainer.appendChild(taskItem);
// 绑定删除按钮事件
taskItem.querySelector('.task-remove').addEventListener('click', function() {
removeTaskItem(taskItem);
});
// 绑定输入事件
const inputs = taskItem.querySelectorAll('input');
inputs.forEach(input => {
input.addEventListener('change', function() {
showUnsavedChanges();
});
});
// 自动保存
setTimeout(saveScheduledTaskSettings, 100);
updateTaskCount();
Mylog("[定时任务] 已添加新任务");
}
// 删除任务项并自动保存
function removeTaskItem(taskItem) {
const tasksContainer = document.getElementById('scheduledTasksList');
if (!tasksContainer) return;
if (tasksContainer.children.length > 1) {
const taskName = taskItem.querySelector('.task-name').value;
taskItem.remove();
Mylog(`[定时任务] 已删除任务: ${taskName}`);
// 更新任务计数
updateTaskCount();
// 自动保存到配置
setTimeout(saveScheduledTaskSettings, 100);
} else {
alert('至少需要保留一个任务');
}
}
// 加载定时任务列表到UI
function loadScheduledTasksUI() {
const tasksList = document.getElementById('scheduledTasksList');
if (!tasksList) return;
tasksList.innerHTML = '';
if (CONFIG.scheduledTasks.tasks.length === 0) {
// 如果没有任务,添加一个默认任务
CONFIG.scheduledTasks.tasks = [{
name: '凌晨任务',
url: 'https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?zapp_uin=&sid=&channel=0&g_ut=1&cmd=notice&op=choice&optid=1',
time: '00:00:01',
count: 3,
interval: 1000,
enabled: true
}];
GM_setValue('scheduledTasks', CONFIG.scheduledTasks.tasks);
}
CONFIG.scheduledTasks.tasks.forEach((task, index) => {
const taskItem = document.createElement('div');
taskItem.className = 'scheduled-task-item';
// 转换间隔时间为秒(兼容旧数据)
const intervalInSeconds = typeof task.interval === 'number' ?
(task.interval >= 100 ? task.interval / 1000 : task.interval) : 1;
taskItem.innerHTML = `
`;
tasksList.appendChild(taskItem);
// 绑定删除按钮事件
taskItem.querySelector('.task-remove').addEventListener('click', function() {
removeTaskItem(taskItem);
});
// 绑定输入框变化事件
const inputs = taskItem.querySelectorAll('input');
inputs.forEach(input => {
input.addEventListener('change', function() {
showUnsavedChanges();
});
});
});
updateTaskCount();
}
// 更新任务计数显示
function updateTaskCount() {
const taskCountBadge = document.getElementById('taskCountBadge');
const tasksList = document.getElementById('scheduledTasksList');
if (taskCountBadge && tasksList) {
const count = tasksList.children.length;
taskCountBadge.textContent = `(${count})`;
taskCountBadge.style.color = count > 0 ? '#4CAF50' : '#888';
}
// 更新状态提示
const taskStatus = document.getElementById('taskStatus');
if (taskStatus) {
taskStatus.textContent = `当前有 ${tasksList ? tasksList.children.length : 0} 个任务`;
taskStatus.style.color = "#888";
}
}
// 显示未保存更改提示
function showUnsavedChanges() {
const taskStatus = document.getElementById('taskStatus');
if (taskStatus) {
taskStatus.textContent = "有未保存的更改";
taskStatus.style.color = "#FFA500";
}
// 延迟保存,避免频繁触发
clearTimeout(window.taskSaveTimer);
window.taskSaveTimer = setTimeout(saveScheduledTaskSettings, 1500);
}
/* ========== 新增:方向键控制功能 ========== */
// 初始化方向键控制
function initDirectionKeyControl() {
if (!CONFIG.directionKey.enabled) return;
document.addEventListener('keydown', handleDirectionKeyDown, true);
Mylog("[方向键控制] 已启用 - 上下滚动,左右前进后退");
}
// 检查是否在输入元素中
function isInInputElement(element) {
const inputTypes = ['input', 'textarea', 'select'];
const contentEditable = element.isContentEditable ||
element.getAttribute('contenteditable') === 'true';
if (contentEditable) return true;
const tagName = element.tagName.toLowerCase();
if (inputTypes.includes(tagName)) {
// 对于input元素,检查特定类型
if (tagName === 'input') {
const type = element.type.toLowerCase();
const editableTypes = ['text', 'password', 'email', 'search', 'tel', 'url', 'number'];
return editableTypes.includes(type);
}
return true;
}
return false;
}
// 处理方向键事件 - 简化版:上下滚动,左右前进后退
function handleDirectionKeyDown(event) {
if (!CONFIG.directionKey.enabled) return;
// 检查是否在输入框中
if (CONFIG.directionKey.ignoreInputs && isInInputElement(event.target)) {
return; // 不干扰输入
}
const { key, shiftKey } = event;
// 只处理方向键
if (!['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)) {
return;
}
// 防止默认行为
event.preventDefault();
event.stopPropagation();
const now = Date.now();
const scrollDelay = now - directionKeyLastScrollTime;
// 防止滚动过快
if (scrollDelay < 50) return;
directionKeyLastScrollTime = now;
// 确定滚动量
let scrollAmount = CONFIG.directionKey.scrollAmount;
if (shiftKey && CONFIG.directionKey.enableShiftScroll) {
scrollAmount = CONFIG.directionKey.fastScrollAmount;
}
// 滚动行为
const scrollOptions = CONFIG.directionKey.smoothScroll ? { behavior: 'smooth' } : {};
switch (key) {
case 'ArrowUp':
// 向上滚动
window.scrollBy({
top: -scrollAmount,
...scrollOptions
});
break;
case 'ArrowDown':
// 向下滚动
window.scrollBy({
top: scrollAmount,
...scrollOptions
});
break;
case 'ArrowLeft':
// 左:浏览器后退
if (window.history.length > 1) {
window.history.back();
}
break;
case 'ArrowRight':
// 右:浏览器前进
window.history.forward();
break;
}
}
/* ========== 模块1:系统繁忙监控 ========== */
let systemBusyMonitorInterval = null;
let lastRefreshTime = 0;
function startSystemBusyMonitor() {
stopSystemBusyMonitor();
Mylog("[系统繁忙监控] 已启动,正在检测 '" + CONFIG.systemBusy.targetText + "'...");
systemBusyMonitorInterval = setInterval(() => {
const now = Date.now();
if (now - lastRefreshTime < CONFIG.systemBusy.refreshCooldown) {
return;
}
if (document.body.innerText.includes(CONFIG.systemBusy.targetText)) {
Mylog("[系统繁忙监控] 检测到 '" + CONFIG.systemBusy.targetText + "',准备刷新页面...");
lastRefreshTime = now;
location.reload();
}
}, CONFIG.systemBusy.checkInterval);
}
function stopSystemBusyMonitor() {
if (systemBusyMonitorInterval) {
clearInterval(systemBusyMonitorInterval);
systemBusyMonitorInterval = null;
}
}
function saveSystemBusySettings() {
const targetText = document.getElementById('systemBusyTargetText').value.trim();
const checkInterval = parseInt(document.getElementById('systemBusyCheckInterval').value);
const refreshCooldown = parseInt(document.getElementById('systemBusyRefreshCooldown').value);
CONFIG.systemBusy.targetText = targetText;
CONFIG.systemBusy.checkInterval = checkInterval;
CONFIG.systemBusy.refreshCooldown = refreshCooldown;
GM_setValue('systemBusyTargetText', targetText);
GM_setValue('systemBusyCheckInterval', checkInterval);
GM_setValue('systemBusyRefreshCooldown', refreshCooldown);
if (CONFIG.systemBusy.enabled) {
stopSystemBusyMonitor();
startSystemBusyMonitor();
}
}
/* ========== 模块2:定时刷新功能 ========== */
function startAutoRefresh() {
stopAutoRefresh();
const interval = CONFIG.autoRefresh.interval * 1000;
module2Timer = setInterval(() => {
const bodyText = getPageText();
const shouldStop = CONFIG.autoRefresh.stopKeywords.some(
keyword => bodyText.includes(keyword)
);
if (shouldStop) {
stopAutoRefresh();
CONFIG.autoRefresh.enabled = false;
GM_setValue('autoRefreshEnabled', false);
document.getElementById('autoRefreshToggle').checked = false;
Mylog("[定时刷新] 已检测到停止关键词,自动关闭功能");
} else {
Mylog("[定时刷新] 执行定时刷新");
window.location.reload();
}
}, interval);
}
function stopAutoRefresh() {
if (module2Timer) {
clearInterval(module2Timer);
module2Timer = null;
}
}
function saveAutoRefreshSettings() {
const interval = parseFloat(document.getElementById('autoRefreshInterval').value);
const stopKeywords = document.getElementById('autoRefreshStopKeywords').value
.split(/[,,]/)
.map(s => s.trim())
.filter(s => s);
CONFIG.autoRefresh.interval = interval;
CONFIG.autoRefresh.stopKeywords = stopKeywords;
GM_setValue('autoRefreshInterval', interval);
GM_setValue('autoRefreshStopKeywords', stopKeywords);
if (CONFIG.autoRefresh.enabled) {
stopAutoRefresh();
startAutoRefresh();
}
}
function getPageText() {
return document.body.innerText || document.body.textContent;
}
/* ========== 模块3:客栈同福监控功能 ========== */
function startFragmentMonitor() {
stopFragmentMonitor();
const interval = CONFIG.fragmentMonitor.interval * 3600 * 1000;
checkTargetPage();
module3Timer = setInterval(checkTargetPage, interval);
Mylog("[来福监控] 已启动,间隔:" + CONFIG.fragmentMonitor.interval + "小时");
}
function stopFragmentMonitor() {
if (module3Timer) {
clearInterval(module3Timer);
module3Timer = null;
Mylog("[来福监控] 已停止");
}
}
function checkTargetPage() {
Mylog("[来福监控] 开始检查目标页面");
GM_xmlhttpRequest({
method: 'GET',
url: CONFIG.fragmentMonitor.checkUrl,
onload: function(response) {
const text = response.responseText;
const shouldJump = CONFIG.fragmentMonitor.triggerKeywords.some(
keyword => text.includes(keyword+"碎片")
) && !CONFIG.fragmentMonitor.stopKeywords.some(
keyword => text.includes(keyword)
);
if (shouldJump) {
Mylog("[来福监控] 检测到目标碎片,准备跳转");
window.location.href = CONFIG.fragmentMonitor.jumpUrl;
} else {
Mylog("[来福监控] 未检测到目标碎片");
}
},
onerror: function(error) {
console.error("[来福监控] 检查失败:", error);
}
});
}
function saveFragmentMonitorSettings() {
const interval = parseInt(document.getElementById('fragmentMonitorInterval').value);
const triggerKeywords = document.getElementById('fragmentTriggerKeywords').value
.split(/[,,]/)
.map(s => s.trim())
.filter(s => s);
const stopKeywords = document.getElementById('fragmentStopKeywords').value
.split(/[,,]/)
.map(s => s.trim())
.filter(s => s);
CONFIG.fragmentMonitor.interval = interval;
CONFIG.fragmentMonitor.triggerKeywords = triggerKeywords;
CONFIG.fragmentMonitor.stopKeywords = stopKeywords;
GM_setValue('fragmentMonitorInterval', interval);
GM_setValue('fragmentTriggerKeywords', triggerKeywords);
GM_setValue('fragmentStopKeywords', stopKeywords);
if (CONFIG.fragmentMonitor.enabled) {
stopFragmentMonitor();
startFragmentMonitor();
}
}
/* ========== 模块4:侠客岛任务模块 ========== */
let knightIslandObserver = null;
const TASK_DELAY = 5000; // 任务操作间隔5秒
let knightIslandCheckTimer = null; // 后台检查定时器
// 初始化侠客岛功能
function initKnightIsland() {
// 如果当前是侠客岛页面,初始化页面功能
if (isKnightIslandPage()) {
modifyKnightLinks();
// 设置观察者监控DOM变化
knightIslandObserver = new MutationObserver(function(mutations) {
// 检查是否有内容变化涉及到任务列表
const shouldUpdate = mutations.some(mutation => {
return Array.from(mutation.addedNodes).some(node => {
return node.nodeType === 1 &&
(node.querySelector('a[href*="op=refreshmission"]') ||
node.textContent.includes('今日免费刷新剩余'));
});
});
if (shouldUpdate) {
modifyKnightLinks();
}
});
knightIslandObserver.observe(document.body, {
childList: true,
subtree: true,
characterData: true
});
}
// 启动自动领取检查
startAutoClaimCheck();
}
// 检查是否是侠客岛页面
function isKnightIslandPage() {
return location.href.includes('cmd=knight_island');
}
// 修改任务链接样式和行为
function modifyKnightLinks() {
// 先检查免费刷新次数
const refreshText = document.body.textContent.match(/今日免费刷新剩余:(\d+)次/);
const freeRefreshCount = refreshText ? parseInt(refreshText[1]) : 0;
// 获取所有刷新按钮
const refreshLinks = document.querySelectorAll('a[href*="op=refreshmission"]');
// 如果免费刷新次数为0,禁用所有刷新按钮
if (freeRefreshCount === 0) {
refreshLinks.forEach(link => {
link.style.opacity = '0.5';
link.style.pointerEvents = 'none';
link.style.cursor = 'not-allowed';
link.title = '今日免费刷新次数已用完';
// 替换原有点击事件
link.addEventListener('click', function(e) {
e.preventDefault();
alert('今日免费刷新次数已用完!');
});
});
} else {
// 如果还有免费次数,恢复按钮状态
refreshLinks.forEach(link => {
link.style.opacity = '';
link.style.pointerEvents = '';
link.style.cursor = '';
link.title = '';
});
}
const viewLinks = document.querySelectorAll('a[href*="op=viewmissiondetail"]');
viewLinks.forEach(link => {
if (link.dataset.ledouProcessed) return;
link.dataset.ledouProcessed = 'true';
// 添加闪电图标
const badge = document.createElement('span');
badge.textContent = '⚡';
badge.className = 'knight-badge';
link.classList.add('knight-link');
link.appendChild(badge);
// 修改点击行为
link.addEventListener('click', function(e) {
e.preventDefault();
const url = new URL(this.href);
const params = Object.fromEntries(url.searchParams.entries());
try {
executeTaskFlow(
params.zapp_uin,
params.sid,
params.pos || '0',
this.href
);
} catch (error) {
Mylog('任务执行出错:', error);
}
});
});
}
// 修改后的执行任务流程函数
function executeTaskFlow(zapp_uin, sid, pos, originalUrl) {
const baseUrl = `https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?zapp_uin=${zapp_uin}&sid=${sid}&channel=0&g_ut=1&cmd=knight_island&pos=${pos}`;
// 前两个操作在后台执行
Promise.resolve()
.then(() => safeRequest(`${baseUrl}&op=viewmissiondetail`))
.then(() => safeRequest(`${baseUrl}&op=autoassign`))
.then(() => safeRequest(`${baseUrl}&op=autoassign`))//执行两次防止系统繁忙无法开始
.then(() => {
// begin操作在前台执行,触发页面刷新
window.location.href = `${baseUrl}&op=begin`;
})
.catch(error => {
Mylog('任务执行出错:', error);
// 出错时返回原始页面
window.location.href = originalUrl;
});
}
// 启动自动领取检查
function startAutoClaimCheck() {
stopAutoClaimCheck();
// 立即检查一次
checkAndClaimRewards();
// 设置定时检查(每5分钟检查一次)
knightIslandCheckTimer = setInterval(() => {
checkAndClaimRewards();
}, 5 * 60 * 1000);
}
// 停止自动领取检查
function stopAutoClaimCheck() {
if (knightIslandCheckTimer) {
clearInterval(knightIslandCheckTimer);
knightIslandCheckTimer = null;
}
}
// 检查并领取奖励(全页面可用,不跳转)
function checkAndClaimRewards() {
if (!CONFIG.knightIsland.enabled) return;
fetchKnightIslandData()
.then(data => {
if (data.hasRewards) {
Mylog(`[侠客岛] 发现${data.rewardCount}个可领取奖励,开始远程领取`);
// 直接通过API领取奖励
claimRewardsRemotely(data.rewardLinks);
}
});
}
// 通过API直接领取奖励
function claimRewardsRemotely(rewardLinks) {
rewardLinks.forEach((link, index) => {
setTimeout(() => {
const fullUrl = `https:${link.getAttribute('href')}`;
GM_xmlhttpRequest({
method: "GET",
url: fullUrl,
onload: function(response) {
Mylog(`[侠客岛] 远程领取成功: ${fullUrl}`);
// 可以在这里添加领取成功后的处理逻辑
},
onerror: function(error) {
Mylog(`[侠客岛] 远程领取失败: ${fullUrl}`, error);
}
});
}, index * TASK_DELAY);
});
}
// 获取侠客岛任务数据(增强版)
function fetchKnightIslandData() {
return new Promise((resolve) => {
const missionUrl = "https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?cmd=knight_island&op=viewmissionindex";
GM_xmlhttpRequest({
method: "GET",
url: missionUrl,
onload: function(response) {
try {
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText, "text/html");
const rewardLinks = [...doc.querySelectorAll('a[href*="op=getmissionreward"]')];
resolve({
hasRewards: rewardLinks.length > 0,
rewardCount: rewardLinks.length,
rewardLinks: rewardLinks,
missionUrl: missionUrl
});
} catch (e) {
console.error("[侠客岛] 解析任务数据失败:", e);
resolve({ hasRewards: false });
}
},
onerror: function(error) {
console.error("[侠客岛] 获取任务数据失败:", error);
resolve({ hasRewards: false });
}
});
});
}
// 清理侠客岛功能
function deinitKnightIsland() {
if (knightIslandObserver) {
knightIslandObserver.disconnect();
knightIslandObserver = null;
}
stopAutoClaimCheck();
const processedLinks = document.querySelectorAll('[data-ledou-processed]');
processedLinks.forEach(link => {
delete link.dataset.ledouProcessed;
const badge = link.querySelector('.knight-badge');
if (badge) badge.remove();
link.classList.remove('knight-link');
link.replaceWith(link.cloneNode(true));
});
}
// 保存侠客岛设置
function saveKnightIslandSettings() {
const checkInterval = parseInt(document.getElementById('knightIslandCheckInterval').value);
const backgroundCheck = document.getElementById('knightIslandBackgroundCheck').checked;
CONFIG.knightIsland.checkInterval = checkInterval;
CONFIG.knightIsland.backgroundCheck = backgroundCheck;
GM_setValue('knightIslandCheckInterval', checkInterval);
GM_setValue('knightIslandBackgroundCheck', backgroundCheck);
if (CONFIG.knightIsland.enabled && backgroundCheck) {
startAutoClaimCheck();
} else {
stopAutoClaimCheck();
}
Mylog("[侠客岛] 设置已保存");
}
// 辅助函数:安全请求
function safeRequest(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: url,
onload: resolve,
onerror: reject
});
});
}
/* ========== 模块5:每日黄历 ========== */
function fetchBuffInfo() {
GM_xmlhttpRequest({
method: "GET",
url: "https://fight.pet.qq.com/cgi-bin/petpk?cmd=calender",
onload: (response) => {
try {
const data = JSON.parse(response.responseText);
const simplifiedBuff = simplifyBuff(data.buff);
displayBuff(simplifiedBuff);
} catch (e) { console.error(e); }
}
});
}
const BUFF_MAPPING = {
"斗神塔": "刷塔",
"画卷": "画卷",
"副本经验双倍": "副本",
"乐斗经验双倍": "经验",
"阅历双倍": "阅历",
"暂无": "OvO"
};
function simplifyBuff(buffText) {
if (!buffText) return "OvO";
for (const [keyword, simplified] of Object.entries(BUFF_MAPPING)) {
if (buffText.includes(keyword)) {
return simplified;
}
}
return buffText.length > 20 ? buffText.substring(0, 20) + "..." : buffText;
}
function displayBuff(buffText) {
const title = document.getElementById('panelTitle');
if (title && !title.querySelector('.buff-info')) {
const buffSpan = document.createElement('span');
buffSpan.className = 'buff-info';
buffSpan.style.marginLeft = '10px';
buffSpan.style.fontSize = '14px';
buffSpan.style.color = '#FFD700';
buffSpan.textContent = `[${buffText || "暂无"}]`;
title.appendChild(buffSpan);
}
}
/* ========== 模块6:抢地盘 ========== */
function startTerritoryGrabber() {
territoryGrabberRetryCount = 0;
Mylog("[抢地盘] 功能已启动,正在寻找目标地盘...");
executeTerritoryGrabber();
}
function stopTerritoryGrabber() {
Mylog("[抢地盘] 功能已停止");
territoryGrabberRetryCount = 0;
}
async function executeTerritoryGrabber() {
if (!CONFIG.territoryGrabber.enabled) return;
try {
Mylog("[抢地盘] 正在获取地盘列表...");
const data = await getRecommendmanorData();
if (data.result === "0" && data.manors?.length > 0) {
const targetManor = data.manors.find(manor =>
manor.ownerlevel === CONFIG.territoryGrabber.targetLevel.toString()
);
if (targetManor) {
//await randomDelay();
//无法解析成功失败活繁忙,执行2次避免失败
await attackManor(targetManor.id);
await getReward();
await getReward();
Mylog(`[抢地盘] 找到${CONFIG.territoryGrabber.targetLevel}级NPC地盘: ${targetManor.name}, ID: ${targetManor.id}`);
// 完成后自动关闭
CONFIG.territoryGrabber.enabled = false;
GM_setValue('territoryGrabberEnabled', false);
document.getElementById('territoryGrabberToggle').checked = false;
Mylog("[抢地盘] 操作完成,功能已自动关闭");
} else {
handleTerritoryRetry("未找到目标等级NPC地盘");
}
} else {
handleTerritoryRetry("获取地盘列表失败或列表为空");
}
} catch (e) {
console.error("[抢地盘] 操作失败:", e);
handleTerritoryRetry(e.message);
}
}
function handleTerritoryRetry(reason) {
territoryGrabberRetryCount++;
Mylog(`[抢地盘] ${reason},准备重试 (${territoryGrabberRetryCount}`);
setTimeout(executeTerritoryGrabber, CONFIG.territoryGrabber.baseDelay);
}
function getRecommendmanorData() {
return new Promise((resolve, reject) => {
const apiUrl = 'https://fight.pet.qq.com/cgi-bin/petpk?cmd=recommendmanor&type=11&page=1';
GM_xmlhttpRequest({
method: "GET",
url: apiUrl,
timeout: 10000,
onload: function(response) {
try {
if (!response.responseText || response.responseText.trim().startsWith('<')) {
throw new Error('服务器返回无效响应');
}
const data = JSON.parse(response.responseText);
if (data.result !== "0") {
throw new Error(data.msg || '服务器返回错误');
}
if (!data.manors || !Array.isArray(data.manors)) {
throw new Error('无效的地盘数据');
}
resolve(data);
} catch (e) {
console.error('[抢地盘] 解析失败:', e);
reject(e);
}
},
onerror: function(error) {
reject(new Error(`请求失败: ${error.statusText}`));
},
ontimeout: function() {
reject(new Error('请求超时'));
}
});
});
}
function attackManor(manorId) {
return new Promise((resolve, reject) => {
const attackUrl = `https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?cmd=manorfight&fighttype=1&manorid=${manorId}`;
Mylog(`[抢地盘] 正在抢夺地盘: ${manorId}`);
GM_xmlhttpRequest({
method: "GET",
url: attackUrl,
onload: function(response) {
try {
const result = JSON.parse(response.responseText);
if (result.result === "0") {
Mylog("[抢地盘] 抢夺成功");
} else {
Mylog("[抢地盘] 抢夺失败", result.msg || "未知错误");
}
} catch (e) {
console.error("[抢地盘] 抢夺结果失败:", e);
} finally {
resolve();
}
},
onerror: function(error) {
console.error("[抢地盘] 抢夺请求失败:", error);
resolve();
}
});
});
}
function getReward() {
return new Promise((resolve) => {
const rewardUrl = "https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?cmd=manorget&type=1";
Mylog("[抢地盘] 正在尝试领取奖励...");
GM_xmlhttpRequest({
method: "GET",
url: rewardUrl,
onload: function(response) {
try {
const result = JSON.parse(response.responseText);
if (result.result === "0") {
Mylog("[抢地盘] 奖励领取成功");
} else {
Mylog("[抢地盘] 奖励领取失败:", result.msg || "未知错误");
}
} catch (e) {
console.error("[抢地盘] 解析奖励结果失败:", e);
} finally {
resolve();
}
},
onerror: function(error) {
console.error("[抢地盘] 领取奖励请求失败:", error);
resolve();
}
});
});
}
function saveTerritoryGrabberSettings() {
const targetLevel = parseInt(document.getElementById('territoryGrabberTargetLevel').value);
const retryLimit = parseInt(document.getElementById('territoryGrabberRetryLimit').value);
const baseDelay = parseInt(document.getElementById('territoryGrabberBaseDelay').value);
const maxRandomDelay = parseInt(document.getElementById('territoryGrabberMaxRandomDelay').value);
CONFIG.territoryGrabber.targetLevel = targetLevel;
CONFIG.territoryGrabber.retryLimit = retryLimit;
CONFIG.territoryGrabber.baseDelay = baseDelay;
CONFIG.territoryGrabber.maxRandomDelay = maxRandomDelay;
GM_setValue('territoryGrabberTargetLevel', targetLevel);
GM_setValue('territoryGrabberRetryLimit', retryLimit);
GM_setValue('territoryGrabberBaseDelay', baseDelay);
GM_setValue('territoryGrabberMaxRandomDelay', maxRandomDelay);
Mylog("[抢地盘] 设置已保存");
}
/* ========== 模块7:血量高亮 ========== */
function initHPHighlight() {
if (!CONFIG.hpHighlight.enabled) return;
GM_addStyle(`
.tm-hp-change {
display: inline;
white-space: nowrap;
}
.tm-hp-plus { color: #00aa00; font-weight: bold; } /* 绿色 */
.tm-hp-minus { color: #ff0000; font-weight: bold; } /* 红色 */
.tm-key-weapon { color: #aa00aa; font-weight: bold; } /* 紫色 */
.tm-keyword-bold { color: #1ba784; font-weight: bold; } /* 蓝色 */
`);
const hpRegexChange = /(HP[+-]\d+)/g;
const hpRegexRemain = /(HP余\d+)/g;
// 添加螺旋丸伤害规则
const spiralRegex = /(反弹给对方(\d+)的伤害!)/g;
// 关键武器列表(使用正则表达式匹配)
const weaponRegex = /(神·霸皇|盘古开天斧|神·大力神杯|神·雷神之锤|神·炼狱加特林|加特林|神·死寂|死神之镰|神·无限板砖|神·埃辛诺斯战刃|神·命运之枪|神·龙雀|神·马格南左轮|神·月光炮|神·电饭煲|神·星之杖|神·死亡笔记|生死簿|神·冈格尼尔|神·可乐切割枪|神·无敌飞鞋|神·花仙子)/g;
// 新增关键字列表(可以根据需要添加更多关键字)
// 基础关键字
const baseKeywords = [
'帮派商会', '帮派祭坛', '全民乱斗', '华山论剑',"竞技场",
'吉利兑', '飞升大作战', '群侠', '祝福宝库', '远方祝福',
'大侠回归三重好礼', '侠客岛', '任务', '九宫宝库', '符石宝箱',
'年兽大作战', '喜从天降', '春联大赛',
'新元婴神器', "徽章优惠", '乐斗驿站', '乐斗游记'
];
// 使用Set避免重复
const keywordSet = new Set(baseKeywords);
// 动态添加
if (document.body.innerText.includes("至尊传功")) {
keywordSet.add('经脉');
}
if (document.body.innerText.includes("军需处")) {
keywordSet.add('五行');
}
if (document.body.innerText.includes("达人特惠")) {
keywordSet.add('续费达人');
}
if (document.body.innerText.includes("巅峰之战军需处")) {
keywordSet.add('兵法');
}
if (document.body.innerText.includes("藏经阁")) {
keywordSet.add('兵法');
}
// 构建正则
const keywordRegex = new RegExp([...keywordSet].join('|'), 'g');
const safeReplace = (text) => {
// 先处理关键字加粗
if (document.body.innerText.includes("【大乐斗】") || document.body.innerText.includes("Q宠大乐斗")) {
text = text.replace(keywordRegex,
(keyword) => `${keyword}`
);
}
// 处理武器名称
text = text.replace(weaponRegex,
(weapon) => `${weapon}`
);
// 然后处理HP变化
text = text.replace(hpRegexChange,
(change) =>
`${change}`
);
text = text.replace(hpRegexRemain,
(remain) =>
`${remain}`
);
// 处理反弹的伤害(将数字部分变为红色)
text = text.replace(spiralRegex,
(fullMatch, fullText, damage) =>
fullText.replace(damage, `${damage}`)
);
return text;
};
const processNode = (node) => {
if (node.nodeType === Node.TEXT_NODE &&
!node.parentNode.classList.contains('tm-hp-processed') &&
(hpRegexChange.test(node.nodeValue) || hpRegexRemain.test(node.nodeValue) || weaponRegex.test(node.nodeValue) || spiralRegex.test(node.nodeValue) || keywordRegex.test(node.nodeValue))) {
const wrapper = document.createElement('span');
wrapper.className = 'tm-hp-processed';
wrapper.innerHTML = safeReplace(node.nodeValue);
node.parentNode.replaceChild(wrapper, node);
}
else if (node.nodeType === Node.ELEMENT_NODE &&
!node.classList.contains('tm-hp-processed')) {
Array.from(node.childNodes).forEach(processNode);
}
};
processNode(document.body);
}
/* ========== 模块8:商品库存显示 ========== */
// 检查是否在商品查看页面
function isViewGoodsPage() {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get('cmd') === 'viewgoods';
}
// 获取商品ID
function getGoodsId() {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get('id');
}
// 获取仓库中的商品数量
function getGoodsStock(goodsId, callback) {
const apiUrl = `https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?zapp_uin=&sid=&channel=0&g_ut=1&cmd=owngoods&id=${goodsId}`;
GM_xmlhttpRequest({
method: "GET",
url: apiUrl,
onload: function(response) {
if (response.status === 200) {
try {
// 尝试解析响应
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText, "text/html");
const content = doc.body.textContent || "";
// 检查是否返回繁忙
if (content.includes("繁忙")) {
callback(0, "API繁忙");
} else {
// 尝试从响应中提取数量信息
const match = content.match(/数量:\s*(\d+)/);
if (match && match[1]) {
callback(parseInt(match[1]), null);
} else {
callback(0, "无法解析数量");
}
}
} catch (e) {
callback(0, "解析响应失败");
}
} else {
callback(0, `请求失败: ${response.status}`);
}
},
onerror: function(error) {
callback(0, "网络请求错误");
},
timeout: 10000
});
}
// 在商品名称后面显示仓库数量
function displayStockInfo(goodsId, stock, error) {
// 查找商品名称元素 - 第一个p标签内的第一个文本节点
const firstParagraph = document.querySelector('body > div > p:first-child');
if (firstParagraph) {
// 查找商品名称文本节点
const textNodes = [];
const walker = document.createTreeWalker(firstParagraph, NodeFilter.SHOW_TEXT, null, false);
let node;
while (node = walker.nextNode()) {
textNodes.push(node);
}
if (textNodes.length > 0) {
// 找到商品名称文本节点(通常是第一个)
const goodsNameNode = textNodes[0];
// 移除可能已存在的库存信息
const existingStock = document.getElementById('goods-stock-info');
if (existingStock) {
existingStock.remove();
}
// 创建库存显示元素
const stockInfo = document.createElement('span');
stockInfo.id = 'goods-stock-info';
// 保持与页面原始样式一致
stockInfo.style.marginLeft = '5px';
stockInfo.style.fontSize = 'inherit';
stockInfo.style.fontFamily = 'inherit';
stockInfo.style.color = stock > 0 ? '#00aa00' : '#ff0000';
if (error) {
stockInfo.textContent = `【背包数量:0】`;
stockInfo.title = error;
} else {
stockInfo.textContent = `【背包数量:${stock}】`;
}
// 插入到商品名称后面
goodsNameNode.parentNode.insertBefore(stockInfo, goodsNameNode.nextSibling);
}
}
}
// 检查并显示商品库存
function checkAndDisplayGoodsStock() {
if (!CONFIG.goodsStock.enabled) return;
const goodsId = getGoodsId();
if (!goodsId) {
console.log('未找到商品ID');
return;
}
getGoodsStock(goodsId, function(stock, error) {
displayStockInfo(goodsId, stock, error);
});
}
function makePanelDraggable(panel) {
const title = panel.querySelector('h3');
let isDragging = false;
let offsetX, offsetY;
title.addEventListener('mousedown', function(e) {
isDragging = true;
offsetX = e.clientX - panel.getBoundingClientRect().left;
offsetY = e.clientY - panel.getBoundingClientRect().top;
panel.style.cursor = 'grabbing';
});
document.addEventListener('mousemove', function(e) {
if (!isDragging) return;
panel.style.left = (e.clientX - offsetX) + 'px';
panel.style.top = (e.clientY - offsetY) + 'px';
panel.style.right = 'auto';
panel.style.bottom = 'auto';
});
document.addEventListener('mouseup', function() {
isDragging = false;
panel.style.cursor = '';
});
}
function Mylog(message) {
const now = new Date();
const timeStr = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
console.log(`[${timeStr}] ${message}`);
}
// 创建控制面板UI
function createControlPanel() {
GM_addStyle(`
#gameHelperPanel {
position: fixed;
bottom: 50px;
right: 30px;
width: 180px;
background: rgba(0, 0, 0, 0.8);
color: white;
border-radius: 5px;
padding: 8px;
z-index: 9999;
font-family: Arial, sans-serif;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
#gameHelperPanel h3 {
margin-top: 0;
padding-bottom: 5px;
border-bottom: 1px solid #444;
cursor: move;
}
.module {
margin-bottom: 10px;
padding: 8px;
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
.module-title {
font-weight: bold;
margin-bottom: 3px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
font-size: 14px;
}
.module-content {
padding-left: 10px;
display: none;
}
.module.active .module-content {
display: block;
}
.switch {
position: relative;
display: inline-block;
width: 36px;
height: 18px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
border-radius: 18px;
}
.slider:before {
position: absolute;
content: "";
height: 14px;
width: 14px;
left: 2px;
bottom: 2px;
background-color: white;
transition: .4s;
border-radius: 50%;
}
input:checked + .slider {
background-color: #2196F3;
}
input:checked + .slider:before {
transform: translateX(16px);
}
.settings {
font-size: 12px;
margin-top: 5px;
}
.settings label {
display: block;
margin: 5px 0;
}
.settings input[type="text"],
.settings input[type="number"] {
width: 100%;
padding: 3px;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.2);
border: 1px solid #444;
color: white;
}
.settings button {
background: #2196F3;
color: white;
border: none;
padding: 3px 8px;
border-radius: 3px;
cursor: pointer;
margin-top: 5px;
}
.knight-link {
position: relative;
}
.knight-badge {
position: absolute;
top: -5px;
right: -5px;
font-size: 10px;
color: gold;
}
.task-auto-info {
color: #888;
font-size: 12px;
margin-top: 5px;
}
/* 定时任务样式 */
.scheduled-task-item {
background: rgba(255,255,255,0.05);
border: 1px solid #444;
border-radius: 3px;
margin-bottom: 8px;
padding: 6px;
}
.task-header {
display: flex;
align-items: center;
gap: 5px;
margin-bottom: 5px;
}
.task-header .task-name {
flex: 1;
background: rgba(255,255,255,0.1);
border: 1px solid #555;
color: white;
padding: 2px 4px;
font-size: 12px;
min-width: 60px;
}
.task-remove {
background: #ff4444;
color: white;
border: none;
width: 16px;
height: 16px;
border-radius: 50%;
cursor: pointer;
font-size: 11px;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
flex-shrink: 0;
}
.task-remove:hover {
background: #ff0000;
transform: scale(1.1);
}
.task-body {
padding-left: 24px;
}
.task-body label {
display: block;
margin-bottom: 3px;
font-size: 10px;
color: #ccc;
}
.task-body input[type="text"],
.task-body input[type="time"],
.task-body input[type="number"] {
width: 100%;
padding: 2px 4px;
box-sizing: border-box;
background: rgba(255,255,255,0.2);
border: 1px solid #555;
color: white;
font-size: 11px;
margin-top: 1px;
}
/* 隐藏数字输入框的上下箭头 */
.task-body input[type="number"]::-webkit-inner-spin-button,
.task-body input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.task-body input[type="number"] {
-moz-appearance: textfield;
}
.task-settings-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 5px;
margin-top: 5px;
}
.task-settings-row label {
font-size: 9px;
}
.task-settings-row input {
width: 100% !important;
margin-top: 1px;
font-size: 10px;
}
/* 任务控制按钮 */
.task-controls {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px;
margin-top: 6px;
}
.task-controls button {
background: #2196F3;
color: white;
border: none;
padding: 3px 4px;
border-radius: 2px;
cursor: pointer;
font-size: 10px;
text-align: center;
white-space: nowrap;
}
.task-controls button:hover {
background: #0b7dda;
}
.task-controls #testScheduledTask {
background: #4CAF50;
grid-column: span 2;
}
/* 任务列表容器 */
#scheduledTasksList {
max-height: 180px;
overflow-y: auto;
margin-bottom: 6px;
padding-right: 2px;
}
/* 滚动条样式 */
#scheduledTasksList::-webkit-scrollbar {
width: 4px;
}
#scheduledTasksList::-webkit-scrollbar-track {
background: rgba(255,255,255,0.1);
border-radius: 2px;
}
#scheduledTasksList::-webkit-scrollbar-thumb {
background: #555;
border-radius: 2px;
}
#scheduledTasksList::-webkit-scrollbar-thumb:hover {
background: #666;
}
/* 任务计数徽章 */
#taskCountBadge {
background: rgba(76, 175, 80, 0.2);
padding: 0 3px;
border-radius: 2px;
margin-left: 4px;
font-size: 10px;
}
/* 任务状态提示 */
#taskStatus {
font-size: 9px;
color: #888;
margin-top: 4px;
text-align: center;
}
`);
const panel = document.createElement('div');
panel.id = 'gameHelperPanel';
panel.innerHTML = `
请你愉快
定时任务 (${CONFIG.scheduledTasks.tasks.length})
每天自动执行HTTP请求
当前有 ${CONFIG.scheduledTasks.tasks.length} 个任务
`;
document.body.appendChild(panel);
// 获取并显示今日buff
fetchBuffInfo();
// 绑定事件
document.querySelectorAll('.module-title').forEach(title => {
title.addEventListener('click', function() {
this.parentElement.classList.toggle('active');
});
});
document.getElementById('systemBusyToggle').addEventListener('change', function() {
CONFIG.systemBusy.enabled = this.checked;
GM_setValue('systemBusyEnabled', this.checked);
if (this.checked) startSystemBusyMonitor();
else stopSystemBusyMonitor();
});
document.getElementById('autoRefreshToggle').addEventListener('change', function() {
CONFIG.autoRefresh.enabled = this.checked;
GM_setValue('autoRefreshEnabled', this.checked);
if (this.checked) startAutoRefresh();
else stopAutoRefresh();
});
document.getElementById('fragmentMonitorToggle').addEventListener('change', function() {
CONFIG.fragmentMonitor.enabled = this.checked;
GM_setValue('fragmentMonitorEnabled', this.checked);
if (this.checked) startFragmentMonitor();
else stopFragmentMonitor();
});
document.getElementById('knightIslandToggle').addEventListener('change', function() {
CONFIG.knightIsland.enabled = this.checked;
GM_setValue('knightIslandEnabled', this.checked);
if (this.checked) initKnightIsland();
else deinitKnightIsland();
});
document.getElementById('territoryGrabberToggle').addEventListener('change', function() {
CONFIG.territoryGrabber.enabled = this.checked;
GM_setValue('territoryGrabberEnabled', this.checked);
if (this.checked) startTerritoryGrabber();
else stopTerritoryGrabber();
});
// 定时任务切换
document.getElementById('scheduledTasksToggle').addEventListener('change', function() {
CONFIG.scheduledTasks.enabled = this.checked;
GM_setValue('scheduledTasksEnabled', this.checked);
if (this.checked) {
Mylog('[定时任务] 功能已启用');
initScheduledTasks();
} else {
Mylog('[定时任务] 功能已禁用');
stopAllScheduledTasks();
}
});
document.getElementById('saveSystemBusySettings').addEventListener('click', saveSystemBusySettings);
document.getElementById('saveAutoRefresh').addEventListener('click', saveAutoRefreshSettings);
document.getElementById('saveFragmentMonitor').addEventListener('click', saveFragmentMonitorSettings);
document.getElementById('saveKnightIsland').addEventListener('click', saveKnightIslandSettings);
document.getElementById('saveTerritoryGrabber').addEventListener('click', saveTerritoryGrabberSettings);
// 定时任务按钮事件
document.getElementById('addNewTask').addEventListener('click', addNewTask);
document.getElementById('saveScheduledTasks').addEventListener('click', saveScheduledTaskSettings);
document.getElementById('testScheduledTask').addEventListener('click', testFirstTask);
// 使面板可拖动
makePanelDraggable(panel);
// 加载定时任务UI
setTimeout(() => {
loadScheduledTasksUI();
updateTaskCount();
}, 100);
}
// 初始化控制面板
createControlPanel();
// 初始化功能模块
if (CONFIG.systemBusy.enabled) startSystemBusyMonitor();
if (CONFIG.autoRefresh.enabled) startAutoRefresh();
if (CONFIG.fragmentMonitor.enabled) startFragmentMonitor();
if (CONFIG.knightIsland.enabled) initKnightIsland();
if (CONFIG.territoryGrabber.enabled) startTerritoryGrabber();
if (CONFIG.hpHighlight.enabled) initHPHighlight();
if (CONFIG.goodsStock.enabled && isViewGoodsPage()) checkAndDisplayGoodsStock();
// 初始化方向键控制
if (CONFIG.directionKey.enabled) initDirectionKeyControl();
// 初始化定时任务
if (CONFIG.scheduledTasks.enabled) {
setTimeout(() => {
Mylog('[定时任务] 启动定时任务监控');
// 初始化任务
initScheduledTasks();
// 启动每日检查
setupDailyCheck();
// 每小时检查一次任务状态
setInterval(checkTaskStatus, 60 * 60 * 1000);
// 立即检查一次状态
checkTaskStatus();
}, 3000);
}
// 页面可见性变化时重新计算定时器
document.addEventListener('visibilitychange', () => {
if (!document.hidden && CONFIG.scheduledTasks.enabled) {
Mylog('[定时任务] 页面重新激活,检查定时任务状态...');
// 立即检查所有任务
CONFIG.scheduledTasks.tasks.forEach(task => {
if (task.enabled && task.timerId) {
// 可以添加额外的检查逻辑
Mylog(`[定时任务 ${task.name}] 页面激活时检查定时器状态`);
} else if (task.enabled && !task.timerId) {
// 如果没有定时器,立即重新设置
Mylog(`[定时任务 ${task.name}] 定时器丢失,重新设置`);
setupScheduledTaskTimer(task);
}
});
// 5秒后再次检查,确保稳定性
setTimeout(() => {
if (CONFIG.scheduledTasks.enabled) {
initScheduledTasks();
}
}, 5000);
}
});
// 暴露定时任务API到全局
window.taskManager = {
// 手动执行任务
executeTask: function(taskName) {
Mylog(`[定时任务API] 手动执行任务: ${taskName}`);
return executeTaskNow(taskName);
},
// 获取所有任务
getTasks: function() {
Mylog('[定时任务API] 获取所有任务列表');
return CONFIG.scheduledTasks.tasks.map(task => ({
name: task.name,
url: task.url,
time: task.time,
count: task.count,
interval: task.interval / 1000, // 转换为秒
enabled: task.enabled
}));
},
// 添加新任务
addTask: function(task) {
Mylog(`[定时任务API] 添加新任务: ${task.name || '未命名任务'}`);
CONFIG.scheduledTasks.tasks.push({
name: task.name || '新任务',
url: task.url,
time: task.time || '00:00:01',
count: task.count || 3,
interval: (task.interval || 1) * 1000, // 转换为毫秒
enabled: true
});
GM_setValue('scheduledTasks', CONFIG.scheduledTasks.tasks);
if (CONFIG.scheduledTasks.enabled) {
initScheduledTasks();
}
return true;
},
// 移除任务
removeTask: function(taskName) {
Mylog(`[定时任务API] 移除任务: ${taskName}`);
const index = CONFIG.scheduledTasks.tasks.findIndex(t => t.name === taskName);
if (index !== -1) {
CONFIG.scheduledTasks.tasks.splice(index, 1);
GM_setValue('scheduledTasks', CONFIG.scheduledTasks.tasks);
if (CONFIG.scheduledTasks.enabled) {
initScheduledTasks();
}
return true;
}
return false;
},
// 重置所有定时器
resetTimers: function() {
Mylog('[定时任务API] 重置所有定时器');
initScheduledTasks();
}
};
})();