// ==UserScript== // @name 常用邮箱手机号一键填写助手(可隐藏+导入导出) // @namespace https://example.com // @version 0.6.0 // @description 注册表单快速填写常用邮箱/手机号,支持隐藏面板、导入导出 // @author You // @match *://*/* // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant GM_clipboard // @run-at document-end // ==/UserScript== (function () { 'use strict'; // ─────────────── 数据 ─────────────── let data = GM_getValue('fastfill_data', { emails: ["example@gmail.com", "test@outlook.com"], phones: ["13812345678", "13900002222"] }); let panelPos = GM_getValue('fastfill_panel_pos', { bottom: 24, right: 24 }); let panelVisible = GM_getValue('fastfill_panel_visible', true); let panel = null; // ─────────────── CSS ─────────────── GM_addStyle(` #fastfill-panel { position: fixed; z-index: 999998; width: 240px; max-height: 80vh; overflow-y: auto; background: rgba(30, 30, 38, 0.94); backdrop-filter: blur(10px); color: #e0e0ff; border-radius: 16px; box-shadow: 0 10px 40px rgba(0,0,0,0.6); font-family: system-ui, -apple-system, sans-serif; font-size: 14px; padding: 12px 14px; border: 1px solid rgba(120,120,180,0.3); user-select: none; transition: all 0.18s ease, opacity 0.3s, transform 0.3s; } #fastfill-panel.hidden { opacity: 0; transform: scale(0.85); pointer-events: none; } #fastfill-header { font-weight: 600; color: #a5b4fc; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; cursor: move; } .fastfill-section-title { color: #c7d2fe; font-size: 13px; font-weight: 600; margin: 12px 0 6px; } .fastfill-item { padding: 8px 10px; margin: 4px 0; background: rgba(50,50,70,0.6); border-radius: 8px; cursor: pointer; transition: all 0.13s; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .fastfill-item:hover { background: rgba(80,80,120,0.8); transform: translateX(2px); } .fastfill-item.email { color: #a5b4fc; } .fastfill-item.phone { color: #86efac; } #fastfill-btn-area { margin-top: 16px; display: flex; gap: 8px; flex-wrap: wrap; } .fastfill-btn { flex: 1; min-width: 80px; padding: 8px 10px; border-radius: 8px; text-align: center; cursor: pointer; font-size: 13px; background: #4b5563; color: #e0e0ff; transition: background 0.15s; } .fastfill-btn:hover { background: #6366f1; color: white; } .fastfill-btn.primary { background: linear-gradient(135deg, #6366f1, #8b5cf6); } #fastfill-manage-btn { background: linear-gradient(135deg, #6366f1, #8b5cf6); color: white; } `); // ─────────────── 核心函数 ─────────────── function saveData() { GM_setValue('fastfill_data', data); } function fillEmail(value) { fillInputs(value, el => /email|mail|邮箱|account|user/i.test((el.name||'') + (el.id||'') + (el.placeholder||''))); } function fillPhone(value) { fillInputs(value, el => /phone|mobile|tel|手机|电话/i.test((el.name||'') + (el.id||'') + (el.placeholder||''))); } function fillInputs(value, matcher) { document.querySelectorAll('input:not([type="hidden"]):not([type="submit"]):not([type="button"])').forEach(el => { if (matcher(el) && el.offsetParent !== null) { // 只填可见的 if (el.value && el.value !== value) { if (!confirm(`覆盖已有值?\n原: ${el.value}\n新: ${value}`)) return; } el.value = value; el.dispatchEvent(new Event('input', {bubbles: true})); el.dispatchEvent(new Event('change', {bubbles: true})); } }); } // ─────────────── 面板创建与渲染 ─────────────── function createOrUpdatePanel() { if (panel) panel.remove(); if (!panelVisible) return; panel = document.createElement('div'); panel.id = 'fastfill-panel'; panel.style.bottom = panelPos.bottom + 'px'; panel.style.right = panelPos.right + 'px'; panel.innerHTML = `
常用账号助手 ×
邮箱
手机号
导出
导入
管理
`; document.body.appendChild(panel); // 渲染列表 const emailList = panel.querySelector('#email-list'); const phoneList = panel.querySelector('#phone-list'); emailList.innerHTML = data.emails.map(v => `
${v}
`).join(''); phoneList.innerHTML = data.phones.map(v => `
${v}
`).join(''); // 点击填充 panel.querySelectorAll('.fastfill-item').forEach(item => { item.onclick = () => { const val = item.textContent.trim(); if (item.classList.contains('email')) fillEmail(val); else fillPhone(val); }; }); // 关闭(隐藏) panel.querySelector('#fastfill-close').onclick = () => { panelVisible = false; GM_setValue('fastfill_panel_visible', false); panel.classList.add('hidden'); setTimeout(() => panel.remove(), 350); panel = null; }; // 导出 panel.querySelector('#fastfill-export').onclick = () => { const json = JSON.stringify(data, null, 2); GM_setValue('fastfill_last_export', json); // 备用 GM_clipboard(json).then(() => { alert("已复制到剪贴板!\n可保存到记事本等地方"); }).catch(() => { prompt("复制失败,请手动复制:", json); }); }; // 导入 panel.querySelector('#fastfill-import').onclick = () => { const text = prompt("请粘贴之前导出的 JSON 数据:", ""); if (!text) return; try { const imported = JSON.parse(text); if (!imported || typeof imported !== 'object') throw new Error(); if (Array.isArray(imported.emails)) data.emails = imported.emails.filter(v => typeof v === 'string'); if (Array.isArray(imported.phones)) data.phones = imported.phones.filter(v => typeof v === 'string'); saveData(); alert("导入成功!"); createOrUpdatePanel(); // 刷新 } catch (e) { alert("格式错误,请检查是否为正确的 JSON"); } }; // 管理 panel.querySelector('#fastfill-manage').onclick = showManageModal; // 拖拽 let isDragging = false, startX, startY, startRight, startBottom; const header = panel.querySelector('#fastfill-header'); header.onmousedown = e => { if (e.target.id === 'fastfill-close') return; isDragging = true; startX = e.clientX; startY = e.clientY; startRight = parseFloat(panel.style.right || 24); startBottom = parseFloat(panel.style.bottom || 24); e.preventDefault(); }; document.onmousemove = e => { if (!isDragging) return; const dx = e.clientX - startX; const dy = e.clientY - startY; panelPos.right = Math.max(12, startRight - dx); panelPos.bottom = Math.max(12, startBottom - dy); panel.style.right = panelPos.right + 'px'; panel.style.bottom = panelPos.bottom + 'px'; }; document.onmouseup = () => { if (isDragging) { isDragging = false; GM_setValue('fastfill_panel_pos', panelPos); } }; } // ─────────────── 管理弹窗(保持不变,略微精简) ─────────────── function showManageModal() { let modal = document.getElementById('fastfill-modal'); if (modal) modal.remove(); modal = document.createElement('div'); modal.id = 'fastfill-modal'; modal.innerHTML = `

管理常用账号

邮箱
手机号
`; document.body.appendChild(modal); function renderList(type) { const container = document.getElementById(type + '-edit-list'); const arr = type === 'email' ? data.emails : data.phones; container.innerHTML = arr.map((v,i)=>`
`).join(''); } renderList('email'); renderList('phone'); // tab modal.querySelectorAll('[data-tab]').forEach(el=>{ el.onclick = ()=>{ modal.querySelectorAll('[data-tab]').forEach(e=>e.classList.remove('active')); modal.querySelectorAll('#tab-email,#tab-phone').forEach(e=>e.style.display='none'); el.classList.add('active'); document.getElementById('tab-'+el.dataset.tab).style.display='block'; }; }); // 添加 modal.querySelectorAll('button:not(.save):not(.del)').forEach(btn=>{ btn.onclick = ()=>{ const input = btn.previousElementSibling.previousElementSibling || btn.previousElementSibling; const val = input.value.trim(); if(!val) return; const type = btn.closest('#tab-email') ? 'email' : 'phone'; const arr = type==='email'?data.emails:data.phones; if(arr.includes(val)) return alert('已存在'); arr.push(val); saveData(); input.value=''; renderList(type); }; }); // 保存/删除 modal.addEventListener('click', e=>{ if(!e.target.matches('.save,.del')) return; const row = e.target.closest('div'); const input = row.querySelector('input'); const i = +input.dataset.i; const type = input.dataset.t; const arr = type==='email'?data.emails:data.phones; if(e.target.classList.contains('save')){ const val = input.value.trim(); if(val && !arr.includes(val)){ arr[i] = val; saveData(); renderList(type); } } else if(e.target.classList.contains('del')){ if(!confirm('确定删除?')) return; arr.splice(i,1); saveData(); renderList(type); } }); // 关闭 modal.querySelector('button:last-child').onclick = ()=>{ modal.remove(); createOrUpdatePanel(); }; } // ─────────────── 显示/隐藏控制 ─────────────── GM_registerMenuCommand("显示/隐藏 账号助手面板", () => { panelVisible = !panelVisible; GM_setValue('fastfill_panel_visible', panelVisible); if (panelVisible) { createOrUpdatePanel(); } else if (panel) { panel.classList.add('hidden'); setTimeout(() => { panel.remove(); panel = null; }, 350); } alert(panelVisible ? "面板已显示" : "面板已隐藏\n可通过菜单重新显示"); }); // ─────────────── 自动出现逻辑 ─────────────── function shouldShow() { return panelVisible && !!document.querySelector(` input[type="email" i], input[type="tel" i], input[name*="email" i], input[name*="mail" i], input[name*="phone" i], input[name*="mobile" i], input[placeholder*="邮箱" i], input[placeholder*="手机" i], input[placeholder*="电话" i] `); } function checkAndShow() { if (shouldShow() && !panel) { createOrUpdatePanel(); } else if (!shouldShow() && panel) { panel.remove(); panel = null; } } setTimeout(checkAndShow, 800); const observer = new MutationObserver(checkAndShow); observer.observe(document.body, { childList: true, subtree: true }); // 菜单快速添加当前填写的值 GM_registerMenuCommand("添加当前页面填写的邮箱/手机号", () => { const emailEl = document.querySelector('input[type="email" i], input[name*="email" i], input[name*="mail" i]'); const phoneEl = document.querySelector('input[type="tel" i], input[name*="phone" i], input[name*="mobile" i]'); let added = false; if (emailEl?.value?.trim() && !data.emails.includes(emailEl.value.trim())) { data.emails.push(emailEl.value.trim()); added = true; } if (phoneEl?.value?.trim() && !data.phones.includes(phoneEl.value.trim())) { data.phones.push(phoneEl.value.trim()); added = true; } if (added) { saveData(); alert("已添加!"); if (panel) createOrUpdatePanel(); } }); // 初始显示 if (panelVisible) checkAndShow(); })();