Greasy Fork is available in English.
自动复制,鼠标选中,直接复制,省去你的左手。
// ==UserScript==
// @name 自动复制
// @name:zh-CN 自动复制
// @name:en Auto-Copy
// @name:ja オートコピー
// @name:ko 자동 복사
// @name:es Copia Automática
// @namespace gura8390/copy/1
// @license MIT
// @version 2.5.1
// @description 自动复制,鼠标选中,直接复制,省去你的左手。
// @description:en Automatically copy selected text to clipboard
// @description:ja 選択したテキストを自動的にコピーします
// @description:ko 선택한 텍스트를 자동으로 복사합니다
// @description:es Copia automáticamente el texto seleccionado
// @author lbihhe
// @icon data:image/png;base64,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
// @match *://*/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
const STORAGE_KEY = 'auto_copy_enabled';
let isEnabled = GM_getValue(STORAGE_KEY, true);
let menuCommands = [];
let copyTimer;
// ========================
// 多语言支持(保持不变)
// ========================
const i18n = {
'en': {
panelTitle: 'Auto Copy',
toggleBtn: isEnabled => isEnabled ? 'Enabled' : 'Disabled',
statusText: isEnabled => isEnabled ? 'System Active' : 'System Paused',
copied: 'Copied to clipboard',
copyFailed: 'Copy failed',
openPanel: 'Control Panel',
closePanel: 'Close Panel'
},
'zh-CN': {
panelTitle: '智能复制',
toggleBtn: isEnabled => isEnabled ? '已启用' : '已禁用',
statusText: isEnabled => isEnabled ? '✓ 正在监控选中文字' : '✗ 自动复制已暂停',
copied: '文本已存入剪贴板',
copyFailed: '复制失败',
openPanel: '打开控制面板',
closePanel: '关闭控制面板'
}
};
const currentLang = navigator.language.startsWith('zh') ? 'zh-CN' : 'en';
const t = i18n[currentLang];
// ========================
// 全新现代 UI 样式(2026 审美)
// ========================
GM_addStyle(`
:root {
--ac-radius: 28px;
--ac-blur: 20px;
--ac-primary: 99 102 241;
--ac-success: 34 197 94;
--ac-danger: 239 68 68;
--ac-bg-light: 255 255 255 / 0.78;
--ac-bg-dark: 31 41 55 / 0.82;
--ac-border-light: 255 255 255 / 0.18;
--ac-border-dark: 255 255 255 / 0.12;
--ac-shadow: 0 16px 40px -12px rgb(0 0 0 / 0.18);
--ac-text: 15 23 42;
--ac-text-dark: 243 244 246;
}
@media (prefers-color-scheme: dark) {
:root {
--ac-bg: var(--ac-bg-dark);
--ac-border: var(--ac-border-dark);
--ac-text: var(--ac-text-dark);
}
}
@media (prefers-color-scheme: light) {
:root {
--ac-bg: var(--ac-bg-light);
--ac-border: var(--ac-border-light);
}
}
.ac-feedback,
.ac-status-icon,
.ac-panel {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: hsl(var(--ac-text));
background: rgba(var(--ac-bg));
backdrop-filter: blur(var(--ac-blur));
-webkit-backdrop-filter: blur(var(--ac-blur));
border: 1px solid rgba(var(--ac-border));
border-radius: var(--ac-radius);
box-shadow: var(--ac-shadow);
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* 反馈气泡 */
.ac-feedback {
position: fixed;
z-index: 2147483647;
pointer-events: none;
padding: 12px 20px;
font-size: 15px;
font-weight: 500;
display: flex;
align-items: center;
gap: 12px;
animation: ac-bounce-in 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
border: 1px solid rgba(255,255,255,0.25);
}
@keyframes ac-bounce-in {
0% { transform: scale(0.7) translateY(16px); opacity: 0; }
60% { transform: scale(1.08) translateY(-4px); }
100% { transform: scale(1) translateY(0); opacity: 1; }
}
/* 状态图标 - 胶囊形 + 悬浮光晕 */
.ac-status-icon {
position: fixed;
bottom: 24px;
right: 24px;
width: 56px;
height: 56px;
border-radius: 9999px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 2147483646;
transition: all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
box-shadow: 0 12px 32px -8px rgba(0,0,0,0.2);
}
.ac-status-icon:hover {
transform: scale(1.14) translateY(-4px);
box-shadow: 0 20px 48px -12px rgba(99,102,241,0.4);
}
.ac-status-icon svg {
width: 28px;
height: 28px;
stroke-width: 2.8;
transition: transform 0.4s ease;
}
.ac-status-icon:hover svg {
transform: rotate(360deg);
}
/* 控制面板 */
.ac-panel {
position: fixed;
bottom: 100px;
right: 24px;
width: 320px;
padding: 28px 24px;
z-index: 2147483647;
animation: ac-slide-up 0.55s cubic-bezier(0.16, 1, 0.3, 1);
overflow: hidden;
}
.ac-panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 28px;
}
.ac-panel-header h3 {
margin: 0;
font-size: 19px;
font-weight: 700;
letter-spacing: -0.02em;
}
.ac-close {
cursor: pointer;
font-size: 22px;
opacity: 0.6;
transition: all 0.3s;
}
.ac-close:hover {
opacity: 1;
transform: rotate(90deg);
}
.ac-toggle-btn {
width: 100%;
padding: 16px;
border: none;
border-radius: 20px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
box-shadow: inset 0 2px 8px rgba(0,0,0,0.08);
}
.ac-btn-on {
background: rgb(var(--ac-primary));
color: white;
box-shadow: 0 8px 24px -8px rgb(var(--ac-primary) / 0.5);
}
.ac-btn-on:hover {
transform: translateY(-2px) scale(1.02);
box-shadow: 0 16px 32px -10px rgb(var(--ac-primary) / 0.6);
}
.ac-btn-off {
background: rgba(229,231,235,0.9);
color: #4b5563;
}
.ac-btn-off:hover {
background: rgba(209,213,219,0.9);
}
.ac-status-hint {
margin-top: 20px;
font-size: 13px;
text-align: center;
opacity: 0.7;
letter-spacing: -0.01em;
}
@keyframes ac-slide-up {
from { transform: translateY(40px) scale(0.94); opacity: 0; }
to { transform: translateY(0) scale(1); opacity: 1; }
}
`);
// ========================
// 核心逻辑(基本保持原样)
// ========================
const handleSelection = (e) => {
if (!isEnabled) return;
clearTimeout(copyTimer);
copyTimer = setTimeout(() => {
const selection = window.getSelection();
const text = selection.toString().trim();
if (text.length > 0 && !['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)) {
navigator.clipboard.writeText(text).then(() => {
createFeedback('copied', e);
}).catch(() => {
createFeedback('copyFailed', e);
});
}
}, 200);
};
const createFeedback = (key, e) => {
const div = document.createElement('div');
div.className = 'ac-feedback';
const color = key === 'copied' ? `rgb(var(--ac-success))` : `rgb(var(--ac-danger))`;
div.innerHTML = `
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="${color}" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
${key === 'copied'
? '<polyline points="20 6 9 17 4 12"></polyline>'
: '<line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line>'}
</svg>
<span>${t[key]}</span>
`;
Object.assign(div.style, {
left: `${Math.min(e.clientX + 10, window.innerWidth - 220)}px`,
top: `${e.clientY + 20}px`
});
document.body.appendChild(div);
setTimeout(() => {
div.style.opacity = '0';
div.style.transition = 'opacity 0.6s ease';
setTimeout(() => div.remove(), 600);
}, 1800);
};
const toggleFeature = () => {
isEnabled = !isEnabled;
GM_setValue(STORAGE_KEY, isEnabled);
updateStatusIcon();
const panel = document.querySelector('.ac-panel');
if (panel) {
panel.remove();
showControlPanel();
}
updateMenuCommands();
};
const updateStatusIcon = () => {
const icon = document.querySelector('.ac-status-icon');
if (icon) {
const color = isEnabled ? `rgb(var(--ac-primary))` : `rgb(var(--ac-danger))`;
icon.style.color = color;
icon.style.borderColor = `rgba(${isEnabled ? '99,102,241' : '239,68,68'}, 0.3)`;
}
};
const showControlPanel = () => {
if (document.querySelector('.ac-panel')) return;
const panel = document.createElement('div');
panel.className = 'ac-panel';
panel.innerHTML = `
<div class="ac-panel-header">
<h3>${t.panelTitle}</h3>
<div class="ac-close">✕</div>
</div>
<button class="ac-toggle-btn ${isEnabled ? 'ac-btn-on' : 'ac-btn-off'}">
${isEnabled ? '✨' : '💤'} ${t.toggleBtn(isEnabled)}
</button>
<div class="ac-status-hint">${t.statusText(isEnabled)}</div>
`;
panel.querySelector('.ac-toggle-btn').onclick = toggleFeature;
panel.querySelector('.ac-close').onclick = () => panel.remove();
document.body.appendChild(panel);
};
const createStatusIcon = () => {
const btn = document.createElement('div');
btn.className = 'ac-status-icon';
btn.innerHTML = `
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="12" cy="12" r="10" stroke-width="2.5"/>
${isEnabled
? '<path d="M9 12l2 2 4-4" stroke-width="2.8"/>'
: '<path d="M8 8l8 8M16 8l-8 8" stroke-width="2.8"/>'}
</svg>
`;
btn.onclick = () => {
const panel = document.querySelector('.ac-panel');
panel ? panel.remove() : showControlPanel();
};
document.body.appendChild(btn);
updateStatusIcon();
};
const updateMenuCommands = () => {
menuCommands.forEach(cmd => GM_unregisterMenuCommand(cmd));
menuCommands = [];
menuCommands.push(GM_registerMenuCommand(
isEnabled ? '⏸ 禁用自动复制' : '▶️ 启用自动复制',
toggleFeature
));
};
// 初始化
createStatusIcon();
document.addEventListener('mouseup', handleSelection);
updateMenuCommands();
})();