鉴于坛里base64编码内容越来越多,vibe了一个简单的油猴脚本

城市猎人 2026-06-26 20:43 1

功能很简单,就是编码解码,支持多轮编码解码,支持一键复制,


使用方法:右键-Tampermonkey-Base64编解码助手,欢迎佬友们继续完善。


// ==UserScript==
// @name Base64 编解码助手
// @namespace https://github.com/mikylu
// @version 1.0
// @description 选中文字进行 Base64 编码/解码,支持反复再次操作
// @author 城市猎人
// @match *://*/*
// @grant GM_registerMenuCommand
// @grant GM_setClipboard
// @run-at document-start
// ==/UserScript==

(function () {
'use strict';

const STYLE = `
#b64-overlay{position:fixed;top:0;left:0;width:100%;height:100%;z-index:2147483646}
#b64-modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);
background:#fff;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,.25);
padding:24px 28px;min-width:360px;max-width:560px;z-index:2147483647;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}
#b64-modal .b64-round{font-size:13px;color:#888;margin-bottom:8px}
#b64-modal .b64-result{background:#f5f5f5;border:1px solid #e0e0e0;border-radius:8px;
padding:12px 14px;word-break:break-all;max-height:240px;overflow-y:auto;font-size:14px;
line-height:1.6;color:#333;white-space:pre-wrap;user-select:text}
#b64-modal .b64-actions{display:flex;gap:10px;margin-top:16px;justify-content:flex-end}
#b64-modal .b64-btn{border:none;border-radius:8px;padding:8px 20px;font-size:14px;
cursor:pointer;transition:opacity .15s}
#b64-modal .b64-btn:hover{opacity:.85}
#b64-modal .b64-btn-primary{background:#1677ff;color:#fff}
#b64-modal .b64-btn-secondary{background:#f0f0f0;color:#333}
#b64-modal .b64-btn-close{background:#f5f5f5;color:#999}
#b64-modal .b64-err{color:#ff4d4f;font-size:13px;margin-top:8px}
#b64-modal .b64-copied{color:#52c41a;font-size:13px;margin-top:8px;display:none}
`;

const LABELS = {
decode: { action: '解码', again: '再次解码' },
encode: { action: '编码', again: '再次编码' },
};

function injectStyle() {
if (document.getElementById('b64-style')) return;
const s = document.createElement('style');
s.id = 'b64-style';
s.textContent = STYLE;
(document.head || document.documentElement).appendChild(s);
}

function removeModal() {
document.getElementById('b64-overlay')?.remove();
document.getElementById('b64-modal')?.remove();
}

function tryTransform(text, mode) {
if (mode === 'decode') {
try {
return { ok: true, value: decodeURIComponent(atob(text)) };
} catch {
try {
return { ok: true, value: atob(text) };
} catch {
return { ok: false };
}
}
} else {
try {
return { ok: true, value: btoa(unescape(encodeURIComponent(text))) };
} catch {
return { ok: false };
}
}
}

function showModal(round, text, mode) {
removeModal();
injectStyle();
const L = LABELS[mode];

const overlay = document.createElement('div');
overlay.id = 'b64-overlay';
overlay.addEventListener('click', removeModal);

const modal = document.createElement('div');
modal.id = 'b64-modal';
modal.addEventListener('click', (e) => e.stopPropagation());

const roundLabel = document.createElement('div');
roundLabel.className = 'b64-round';
roundLabel.textContent = `第 ${round} 次${L.action}`;

const resultBox = document.createElement('div');
resultBox.className = 'b64-result';
resultBox.textContent = text;

const copiedHint = document.createElement('div');
copiedHint.className = 'b64-copied';
copiedHint.textContent = '✓ 已复制到剪贴板';

const actions = document.createElement('div');
actions.className = 'b64-actions';

const btnCopy = document.createElement('button');
btnCopy.className = 'b64-btn b64-btn-primary';
btnCopy.textContent = '复制结果';
btnCopy.addEventListener('click', () => {
GM_setClipboard(text, 'text');
copiedHint.style.display = 'block';
setTimeout(() => (copiedHint.style.display = 'none'), 1500);
});

const btnAgain = document.createElement('button');
btnAgain.className = 'b64-btn b64-btn-secondary';
btnAgain.textContent = L.again;
btnAgain.addEventListener('click', () => {
const next = tryTransform(text, mode);
if (next.ok) {
showModal(round + 1, next.value, mode);
} else {
resultBox.style.borderColor = '#ffccc7';
roundLabel.textContent = `第 ${round + 1} 次${L.action}失败`;
const errHint = document.createElement('div');
errHint.className = 'b64-err';
errHint.textContent = mode === 'decode'
? '当前内容不是有效的 Base64,无法继续解码'
: '当前内容编码失败';
modal.appendChild(errHint);
btnAgain.disabled = true;
btnAgain.style.opacity = '0.4';
btnAgain.style.cursor = 'not-allowed';
}
});

const btnClose = document.createElement('button');
btnClose.className = 'b64-btn b64-btn-close';
btnClose.textContent = '关闭';
btnClose.addEventListener('click', removeModal);

actions.append(btnCopy, btnAgain, btnClose);
modal.append(roundLabel, resultBox, copiedHint, actions);
document.body.append(overlay, modal);
}

function showError(msg) {
injectStyle();
removeModal();
const overlay = document.createElement('div');
overlay.id = 'b64-overlay';
overlay.addEventListener('click', removeModal);
const modal = document.createElement('div');
modal.id = 'b64-modal';
modal.innerHTML = `<div class="b64-err">${msg}</div>
<div class="b64-actions"><button class="b64-btn b64-btn-close" id="b64-close-only">关闭</button></div>`;
document.body.append(overlay, modal);
modal.querySelector('#b64-close-only').addEventListener('click', removeModal);
}

document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') removeModal();
});

function startAction(mode) {
const L = LABELS[mode];
const selectedText = (window.getSelection?.() || '').toString().trim();
if (!selectedText) {
showError('请先选中文字,再点击菜单进行' + L.action);
return;
}
const result = tryTransform(selectedText, mode);
if (result.ok) {
showModal(1, result.value, mode);
} else {
injectStyle();
removeModal();
const overlay = document.createElement('div');
overlay.id = 'b64-overlay';
overlay.addEventListener('click', removeModal);
const modal = document.createElement('div');
modal.id = 'b64-modal';
modal.innerHTML = `<div class="b64-round">第 1 次${L.action}失败</div>
<div class="b64-err">选中的文字不是有效的 Base64</div>
<div class="b64-actions"><button class="b64-btn b64-btn-close" id="b64-close-only">关闭</button></div>`;
document.body.append(overlay, modal);
modal.querySelector('#b64-close-only').addEventListener('click', removeModal);
}
}

GM_registerMenuCommand('Base64 解码', () => startAction('decode'));
GM_registerMenuCommand('Base64 编码', () => startAction('encode'));
})();

最新回复 (1)
  • MiluZz. 06-27 08:54
    1楼

    哪里的编码呢?帖子里应该是不让直接发那种的

* 帖子来源Linux.do
返回