// ==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
// ==/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 += `<div class="vps-item">
<strong>${vps.name}</strong>: 需要续期
<div>下次提醒日期: ${vps.nextDate}</div>
<button class="vps-item-renew" data-id="${vps.id}">已续期</button>
</div>`;
});
// 添加其他VPS的状态信息(可选)
vpsData.forEach(vps => {
if (!vps.needRemind) {
const nextDate = parseDate(vps.nextDate);
const daysUntil = daysBetween(today, nextDate);
reminderContent += `<div class="vps-item" style="opacity: 0.6;">
<strong>${vps.name}</strong>: 还有 ${daysUntil} 天到期
<div>下次提醒日期: ${vps.nextDate}</div>
</div>`;
}
});
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);
})();