// ==UserScript== // @name VPS续期提醒 // @namespace http://tampermonkey.net/ // @version 0.3 // @description VPS续期提醒工具,支持自定义提醒周期和单个VPS续期 // @author You // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_addSty // @license MIT // <--- 添加许可证声明le // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 添加样式 GM_addStyle(` #vps-reminder-container { position: fixed; right: 20px; bottom: 20px; width: 300px; background-color: #fff; border: 1px solid #ccc; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.2); padding: 15px; z-index: 9999; font-family: Arial, sans-serif; display: none; } #vps-reminder-title { font-size: 16px; font-weight: bold; margin-bottom: 10px; color: #333; } #vps-reminder-content { margin-bottom: 15px; color: #555; max-height: 200px; overflow-y: auto; } .vps-item { margin-bottom: 8px; padding-bottom: 8px; border-bottom: 1px solid #eee; position: relative; } .vps-item:last-child { border-bottom: none; } .vps-item-renew { position: absolute; right: 0; top: 0; padding: 3px 8px; background-color: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 12px; } #vps-reminder-buttons { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px; } #vps-reminder-renew-all, #vps-reminder-settings, #vps-reminder-dismiss { padding: 8px 15px; border: none; border-radius: 3px; cursor: pointer; } #vps-reminder-renew-all { background-color: #4CAF50; color: white; } #vps-reminder-settings { background-color: #f1f1f1; color: #333; } #vps-reminder-dismiss { background-color: #ff9800; color: white; flex: 1; margin-top: 10px; } #vps-settings-container { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 500px; max-height: 80vh; overflow-y: auto; background-color: #fff; border: 1px solid #ccc; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.3); padding: 20px; z-index: 10000; font-family: Arial, sans-serif; display: none; } #vps-settings-title { font-size: 18px; font-weight: bold; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #eee; } .vps-settings-item { margin-bottom: 15px; position: relative; } .vps-settings-item label { display: block; margin-bottom: 5px; font-weight: bold; } .vps-settings-item input, .vps-settings-item select { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 3px; } .vps-delete-btn { position: absolute; right: 0; top: 0; background-color: #f44336; color: white; border: none; border-radius: 3px; padding: 3px 8px; cursor: pointer; font-size: 12px; } #vps-settings-buttons { display: flex; justify-content: space-between; margin-top: 15px; } #vps-settings-save { padding: 8px 15px; background-color: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; } #vps-settings-cancel { padding: 8px 15px; background-color: #f1f1f1; color: #333; border: none; border-radius: 3px; cursor: pointer; } #vps-add-new { padding: 8px 15px; background-color: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer; margin-top: 15px; width: 100%; } `); // 默认VPS数据 const defaultVpsData = [ { id: 1, name: 'VPS 1', cycle: 3, nextDate: '', needRemind: false }, { id: 2, name: 'VPS 2', cycle: 3, nextDate: '', needRemind: false }, { id: 3, name: 'VPS 3', cycle: 3, nextDate: '', needRemind: false }, { id: 4, name: 'VPS 4', cycle: 3, nextDate: '', needRemind: false }, { id: 5, name: 'VPS 5', cycle: 30, nextDate: '', needRemind: false } ]; // 获取VPS数据 let vpsData = GM_getValue('vpsData', defaultVpsData); // 用于记录今天是否已经关闭过提醒 let dismissedForToday = false; // 创建提醒容器 function createReminderContainer() { const container = document.createElement('div'); container.id = 'vps-reminder-container'; const title = document.createElement('div'); title.id = 'vps-reminder-title'; title.textContent = 'VPS续期提醒'; const content = document.createElement('div'); content.id = 'vps-reminder-content'; const buttons = document.createElement('div'); buttons.id = 'vps-reminder-buttons'; const renewAllButton = document.createElement('button'); renewAllButton.id = 'vps-reminder-renew-all'; renewAllButton.textContent = '全部已续期'; renewAllButton.addEventListener('click', handleRenewAll); const settingsButton = document.createElement('button'); settingsButton.id = 'vps-reminder-settings'; settingsButton.textContent = '设置'; settingsButton.addEventListener('click', showSettings); const dismissButton = document.createElement('button'); dismissButton.id = 'vps-reminder-dismiss'; dismissButton.textContent = '今天不再提醒'; dismissButton.addEventListener('click', dismissForToday); buttons.appendChild(renewAllButton); buttons.appendChild(settingsButton); buttons.appendChild(dismissButton); container.appendChild(title); container.appendChild(content); container.appendChild(buttons); document.body.appendChild(container); } // 创建设置容器 function createSettingsContainer() { const container = document.createElement('div'); container.id = 'vps-settings-container'; const title = document.createElement('div'); title.id = 'vps-settings-title'; title.textContent = 'VPS提醒设置'; container.appendChild(title); const settingsContent = document.createElement('div'); settingsContent.id = 'vps-settings-content'; container.appendChild(settingsContent); // 创建添加新VPS按钮 const addNewButton = document.createElement('button'); addNewButton.id = 'vps-add-new'; addNewButton.textContent = '添加新VPS'; addNewButton.addEventListener('click', addNewVps); container.appendChild(addNewButton); const buttons = document.createElement('div'); buttons.id = 'vps-settings-buttons'; const cancelButton = document.createElement('button'); cancelButton.id = 'vps-settings-cancel'; cancelButton.textContent = '取消'; cancelButton.addEventListener('click', () => { document.getElementById('vps-settings-container').style.display = 'none'; }); const saveButton = document.createElement('button'); saveButton.id = 'vps-settings-save'; saveButton.textContent = '保存'; saveButton.addEventListener('click', saveSettings); buttons.appendChild(cancelButton); buttons.appendChild(saveButton); container.appendChild(buttons); document.body.appendChild(container); // 更新设置内容 updateSettingsContent(); } // 更新设置内容 function updateSettingsContent() { const settingsContent = document.getElementById('vps-settings-content'); settingsContent.innerHTML = ''; // 为每个VPS创建设置项 vpsData.forEach(vps => { const item = document.createElement('div'); item.className = 'vps-settings-item'; item.dataset.id = vps.id; // 删除按钮 if (vpsData.length > 1) { const deleteBtn = document.createElement('button'); deleteBtn.className = 'vps-delete-btn'; deleteBtn.textContent = '删除'; deleteBtn.addEventListener('click', function() { deleteVps(vps.id); }); item.appendChild(deleteBtn); } const nameLabel = document.createElement('label'); nameLabel.textContent = `${vps.name} 名称`; const nameInput = document.createElement('input'); nameInput.type = 'text'; nameInput.id = `vps-name-${vps.id}`; nameInput.value = vps.name; const cycleLabel = document.createElement('label'); cycleLabel.textContent = `${vps.name} 提醒周期(天)`; const cycleInput = document.createElement('input'); cycleInput.type = 'number'; cycleInput.id = `vps-cycle-${vps.id}`; cycleInput.value = vps.cycle; cycleInput.min = 1; const dateLabel = document.createElement('label'); dateLabel.textContent = `${vps.name} 下次提醒日期`; const dateInput = document.createElement('input'); dateInput.type = 'date'; dateInput.id = `vps-date-${vps.id}`; dateInput.value = vps.nextDate || formatDate(new Date()); item.appendChild(nameLabel); item.appendChild(nameInput); item.appendChild(cycleLabel); item.appendChild(cycleInput); item.appendChild(dateLabel); item.appendChild(dateInput); settingsContent.appendChild(item); }); } // 添加新VPS function addNewVps() { // 生成新ID let maxId = 0; vpsData.forEach(vps => { if (vps.id > maxId) maxId = vps.id; }); // 添加新VPS数据 const newVps = { id: maxId + 1, name: `VPS ${maxId + 1}`, cycle: 3, nextDate: formatDate(new Date()), needRemind: false }; vpsData.push(newVps); // 更新设置内容 updateSettingsContent(); } // 删除VPS function deleteVps(id) { vpsData = vpsData.filter(vps => vps.id !== id); updateSettingsContent(); } // 显示设置界面 function showSettings() { document.getElementById('vps-settings-container').style.display = 'block'; } // 保存设置 function saveSettings() { const newVpsData = []; // 获取所有设置项 const settingsItems = document.querySelectorAll('.vps-settings-item'); settingsItems.forEach(item => { const id = parseInt(item.dataset.id); const name = document.getElementById(`vps-name-${id}`).value; const cycle = parseInt(document.getElementById(`vps-cycle-${id}`).value); const nextDate = document.getElementById(`vps-date-${id}`).value; // 查找原始数据中的needRemind状态 const originalVps = vpsData.find(vps => vps.id === id); const needRemind = originalVps ? originalVps.needRemind : false; newVpsData.push({ id, name, cycle, nextDate, needRemind }); }); vpsData = newVpsData; GM_setValue('vpsData', vpsData); document.getElementById('vps-settings-container').style.display = 'none'; // 重新检查提醒 checkReminders(); } // 格式化日期为YYYY-MM-DD function formatDate(date) { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } // 解析日期字符串为Date对象 function parseDate(dateString) { return new Date(dateString); } // 计算两个日期之间的天数差 function daysBetween(date1, date2) { const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数 const diffTime = Math.abs(date2 - date1); return Math.floor(diffTime / oneDay); } // 处理"今天不再提醒"按钮点击 function dismissForToday() { dismissedForToday = true; document.getElementById('vps-reminder-container').style.display = 'none'; } // 检查是否需要提醒 function checkReminders() { // 如果今天已经关闭过提醒,则不再显示 if (dismissedForToday) { return; } const today = new Date(); today.setHours(0, 0, 0, 0); let hasRemindersNeedAttention = false; // 是否有VPS需要立即提醒 let allVpsNeedingAttention = []; // 所有需要提醒的VPS // 第一次遍历:检查是否有VPS需要立即提醒 vpsData.forEach(vps => { if (!vps.nextDate) return; const nextDate = parseDate(vps.nextDate); nextDate.setHours(0, 0, 0, 0); const daysUntil = daysBetween(today, nextDate); // 只有当前日期已超过到期日期,或者距离到期日期还有1天或2天时才提醒 if (today >= nextDate || daysUntil === 1 || daysUntil === 2) { hasRemindersNeedAttention = true; vps.needRemind = true; allVpsNeedingAttention.push(vps); } else { vps.needRemind = false; } }); // 如果有需要提醒的VPS,显示所有VPS的信息 if (hasRemindersNeedAttention) { let reminderContent = ''; // 添加需要提醒的VPS allVpsNeedingAttention.forEach(vps => { reminderContent += `
${vps.name}: 需要续期
下次提醒日期: ${vps.nextDate}
`; }); // 添加其他VPS的状态信息(可选) vpsData.forEach(vps => { if (!vps.needRemind) { const nextDate = parseDate(vps.nextDate); const daysUntil = daysBetween(today, nextDate); reminderContent += `
${vps.name}: 还有 ${daysUntil} 天到期
下次提醒日期: ${vps.nextDate}
`; } }); document.getElementById('vps-reminder-content').innerHTML = reminderContent; document.getElementById('vps-reminder-container').style.display = 'block'; // 为每个单独的续期按钮添加事件 document.querySelectorAll('.vps-item-renew').forEach(button => { button.addEventListener('click', function(e) { e.stopPropagation(); handleRenewSingle(parseInt(this.dataset.id)); }); }); } // 更新存储的数据 GM_setValue('vpsData', vpsData); } // 处理单个VPS续期 function handleRenewSingle(id) { const today = new Date(); vpsData.forEach(vps => { if (vps.id === id && vps.needRemind) { // 计算新的提醒日期 const newDate = new Date(today); newDate.setDate(today.getDate() + vps.cycle); vps.nextDate = formatDate(newDate); vps.needRemind = false; } }); // 更新存储的数据 GM_setValue('vpsData', vpsData); // 重新检查是否还有需要提醒的VPS checkReminders(); } // 处理全部已续期按钮点击 function handleRenewAll() { const today = new Date(); vpsData.forEach(vps => { if (vps.needRemind) { // 计算新的提醒日期 const newDate = new Date(today); newDate.setDate(today.getDate() + vps.cycle); vps.nextDate = formatDate(newDate); vps.needRemind = false; } }); // 更新存储的数据 GM_setValue('vpsData', vpsData); // 隐藏提醒 document.getElementById('vps-reminder-container').style.display = 'none'; } // 初始化 function init() { createReminderContainer(); createSettingsContainer(); // 如果是首次使用,显示设置界面 if (!GM_getValue('initialized', false)) { showSettings(); GM_setValue('initialized', true); } else { // 检查是否需要提醒 checkReminders(); } } // 等待页面加载完成后初始化 window.addEventListener('load', init); })();