// ==UserScript== // @name 网站数据清除工具 Website Data Cleaner // @namespace http://tampermonkey.net/ // @version 1.1.0 // @description 油猴菜单触发,一键清除当前网站的localStorage、sessionStorage、Cookie、IndexedDB、Web SQL数据 // @author ChiamZhang // @match *://*/* // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_getValue // @grant GM_setValue // @grant GM_openInTab // @run-at document-end // @license MIT表 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // ================= 全局变量 ================= const menuId = []; // 存储菜单ID,用于后续注销 // 菜单配置(参考用户提供的格式) const menuAll = [ ['menu_clearAll', '清除当前网站所有数据', '清除所有数据', false], // [ID, 菜单名称, 描述, 状态] ['menu_clearBasic', '仅清除 localStorage + SessionStorage', '基础存储清除', false], ['menu_clearCookie', '仅清除当前网站Cookie', 'Cookie清除', false], ['menu_clearDB', '仅清除 IndexedDB + Web SQL', '数据库清除', false] ]; // ================= 核心清除函数 ================= /** * 清除localStorage */ function clearLocalStorage() { try { localStorage.clear(); console.log('[数据清除] localStorage 清除成功'); return true; } catch (e) { console.error('[数据清除] localStorage 清除失败:', e); return false; } } /** * 清除sessionStorage */ function clearSessionStorage() { try { sessionStorage.clear(); console.log('[数据清除] sessionStorage 清除成功'); return true; } catch (e) { console.error('[数据清除] sessionStorage 清除失败:', e); return false; } } /** * 清除当前网站的Cookie */ function clearCookies() { try { const cookies = document.cookie.split(';'); const domain = window.location.hostname; // 兼容不同子域名和路径的Cookie清除 cookies.forEach(cookie => { const eqPos = cookie.indexOf('='); const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim(); // 多场景清除确保生效 document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${domain}; SameSite=None; Secure`; document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.${domain}; SameSite=None; Secure`; document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=None; Secure`; document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/${domain}; SameSite=None; Secure`; }); console.log('[数据清除] Cookie 清除成功(共', cookies.length, '个)'); return true; } catch (e) { console.error('[数据清除] Cookie 清除失败:', e); return false; } } /** * 清除IndexedDB */ async function clearIndexedDB() { try { if (!window.indexedDB) return true; const databases = await indexedDB.databases(); if (databases.length === 0) return true; for (const db of databases) { await new Promise((resolve) => { const request = indexedDB.deleteDatabase(db.name); request.onsuccess = () => resolve(true); request.onerror = (err) => { console.warn(`[数据清除] IndexedDB ${db.name} 清除失败:`, err); resolve(false); }; request.onblocked = () => { console.warn(`[数据清除] IndexedDB ${db.name} 被占用(可能有其他标签页打开)`); resolve(false); }; }); } console.log('[数据清除] IndexedDB 清除完成(共', databases.length, '个数据库)'); return true; } catch (e) { console.error('[数据清除] IndexedDB 清除异常:', e); return false; } } /** * 清除Web SQL */ function clearWebSQL() { try { if (!window.openDatabase) return true; // 遍历常见的Web SQL数据库名称模式 const dbNamePatterns = ['web sql', 'site_', 'app_', 'local_', 'data_', 'db_']; let clearedCount = 0; dbNamePatterns.forEach(pattern => { try { // 尝试打开并删除匹配的数据库 const db = openDatabase( `temp_${pattern}`, '1.0', 'Temporary database for deletion', 1024 * 1024 ); db.transaction(tx => { tx.executeSql('DROP TABLE IF EXISTS main'); clearedCount++; }); } catch (e) {} }); console.log('[数据清除] Web SQL 清除完成(处理', clearedCount, '个匹配模式)'); return true; } catch (e) { console.error('[数据清除] Web SQL 清除异常:', e); return true; // Web SQL兼容性较差,失败不影响整体流程 } } // ================= 功能入口函数 ================= /** * 显示操作结果通知 * @param {string} message 通知内容 * @param {boolean} success 是否成功 */ function showResult(message, success = true) { // 优先使用浏览器通知API if (Notification.permission === 'granted') { new Notification('网站数据清除工具', { body: message }); } else if (Notification.permission !== 'denied') { Notification.requestPermission().then(perm => { if (perm === 'granted') { new Notification('网站数据清除工具', { body: message }); } }); } // 控制台打印详细信息 console.log(`[数据清除${success ? '成功' : '失败'}]`, message); // 页面顶部临时提示(避免完全无反馈) const toast = document.createElement('div'); toast.style.cssText = ` position: fixed; top: 20px; left: 50%; transform: translateX(-50%); padding: 12px 24px; border-radius: 4px; background: ${success ? '#4CAF50' : '#f44336'}; color: white; font-size: 14px; z-index: 999999; box-shadow: 0 2px 10px rgba(0,0,0,0.2); opacity: 0; transition: opacity 0.3s ease; `; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => toast.style.opacity = '1', 10); setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => document.body.removeChild(toast), 300); }, 3000); } /** * 清除所有数据(完整模式) */ async function clearAllData() { if (!confirm('⚠️ 确认清除当前网站所有数据?\n包含:localStorage、SessionStorage、Cookie、IndexedDB、Web SQL\n清除后不可恢复,登录状态会失效!')) { return; } try { const results = [ clearLocalStorage(), clearSessionStorage(), clearCookies(), await clearIndexedDB(), clearWebSQL() ]; const hasFailure = results.some(res => !res); if (hasFailure) { showResult('部分数据清除成功,部分数据可能未清除(详见控制台)', false); } else { showResult('✅ 当前网站所有数据清除成功!'); // 可选:清除后刷新页面(取消注释启用) // if (confirm('是否刷新页面使清除生效?')) location.reload(); } } catch (e) { showResult('❌ 数据清除过程中发生错误', false); console.error('[数据清除] 全局异常:', e); } } /** * 仅清除基础存储(localStorage + SessionStorage) */ function clearBasicData() { if (!confirm('确认清除当前网站的localStorage和SessionStorage?\n这会清除网站保存的本地设置和临时数据!')) { return; } const res1 = clearLocalStorage(); const res2 = clearSessionStorage(); if (res1 && res2) { showResult('✅ 基础存储数据清除成功!'); } else { showResult('❌ 基础存储数据清除失败', false); } } /** * 仅清除Cookie */ function clearOnlyCookie() { if (!confirm('确认清除当前网站的所有Cookie?\n这会导致登录状态失效,需要重新登录!')) { return; } const res = clearCookies(); if (res) { showResult('✅ Cookie清除成功!'); } else { showResult('❌ Cookie清除失败', false); } } /** * 仅清除数据库(IndexedDB + Web SQL) */ async function clearOnlyDB() { if (!confirm('确认清除当前网站的IndexedDB和Web SQL数据库?\n这会清除网站保存的离线数据和缓存内容!')) { return; } const res1 = await clearIndexedDB(); const res2 = clearWebSQL(); if (res1 && res2) { showResult('✅ 数据库数据清除成功!'); } else { showResult('部分数据库可能未清除(可能被占用)', false); } } // ================= 菜单注册函数 ================= /** * 注册油猴菜单(参考用户提供的代码风格) */ function registerMenuCommand() { // 先注销已存在的菜单,避免重复 if (menuId.length > 0) { menuId.forEach(id => { try { GM_unregisterMenuCommand(id); } catch (e) {} }); menuId.length = 0; // 清空数组 } // 循环注册菜单 for (let i = 0; i < menuAll.length; i++) { const [menuKey, menuName, menuDesc, menuState] = menuAll[i]; // 从存储中读取菜单状态(如果有) menuAll[i][3] = GM_getValue(menuKey, menuState); // 根据菜单ID绑定对应的功能 switch (menuKey) { case 'menu_clearAll': menuId[i] = GM_registerMenuCommand(`🗑️ ${menuName}`, clearAllData); break; case 'menu_clearBasic': menuId[i] = GM_registerMenuCommand(`📦 ${menuName}`, clearBasicData); break; case 'menu_clearCookie': menuId[i] = GM_registerMenuCommand(`🍪 ${menuName}`, clearOnlyCookie); break; case 'menu_clearDB': menuId[i] = GM_registerMenuCommand(`🗄️ ${menuName}`, clearOnlyDB); break; case 'menu_feedback': menuId[i] = GM_registerMenuCommand(`💬 ${menuName}`, openFeedback); break; default: // 通用菜单模板(如果需要开关状态) menuId[i] = GM_registerMenuCommand( `${menuAll[i][3] ? '✅' : '❌'} ${menuName}`, () => menuSwitch(menuAll[i][3], menuKey, menuDesc) ); } } } /** * 菜单开关状态切换(预留功能,当前版本未使用) * @param {boolean} currentState 当前状态 * @param {string} menuKey 菜单ID * @param {string} menuDesc 菜单描述 */ function menuSwitch(currentState, menuKey, menuDesc) { const newState = !currentState; GM_setValue(menuKey, newState); showResult(`${menuDesc}已${newState ? '启用' : '禁用'}`); // 重新注册菜单更新状态显示 registerMenuCommand(); } // ================= 初始化 ================= // 检查通知权限(可选,提升用户体验) if (Notification.permission !== 'granted' && Notification.permission !== 'denied') { // 不主动请求,避免打扰用户,仅在首次使用时提示 console.log('[数据清除工具] 可在浏览器设置中开启通知权限,获取清除结果提醒'); } // 注册菜单(确保菜单ID长度正常) if (menuId.length < 4) { registerMenuCommand(); } console.log('[数据清除工具] 菜单已加载完成,可在油猴菜单中操作'); })();