// ==UserScript==
// @name 车牌标注-阿拉伯字符
// @namespace http://tampermonkey.net/
// @version 1.2
// @description KacstOne字体、数字字母分组提示、拖拽折叠复制
// @match *://*/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 拆分数字、字母两组
const numArr = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'];
const charArr = ['أ', 'ب', 'ص', 'د', 'ع', 'ف', 'ج', 'ه', 'ق', 'ل', 'م', 'ن', 'ر', 'س', 'ط', 'و', 'ى'];
const panel = document.createElement('div');
panel.id = 'eg-plate-helper';
panel.innerHTML = `
`;
const style = document.createElement('style');
style.textContent = `
@font-face {
font-family: "KacstOne";
src: url('https://cdn.jsdelivr.net/npm/font-kacstone@1.0.0/KacstOne.ttf') format('truetype');
font-display: swap;
}
#eg-plate-helper {
position: fixed !important;
top: 50px !important;
left: 100px !important;
width: 280px !important;
background: #ffffff !important;
border: 1px solid #e0e0e0 !important;
border-radius: 8px !important;
box-shadow: 0 4px 15px rgba(0,0,0,0.2) !important;
z-index: 2147483647 !important;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
overflow: hidden !important;
user-select: none !important;
pointer-events: auto !important;
will-change: transform !important;
}
#eg-plate-header {
display: flex !important;
justify-content: space-between !important;
align-items: center !important;
padding: 8px 12px !important;
background: #2563eb !important;
color: white !important;
font-size: 13px !important;
font-weight: bold !important;
cursor: move !important;
}
#eg-plate-toggle {
cursor: pointer !important;
padding: 0 4px !important;
font-size: 16px !important;
line-height: 1 !important;
pointer-events: auto !important;
}
#eg-plate-toggle:hover {
opacity: 0.8 !important;
}
#eg-plate-body {
padding: 8px !important;
max-height: 400px !important;
overflow-y: auto !important;
background: white !important;
pointer-events: auto !important;
}
#eg-plate-body.hidden {
display: none !important;
}
.group-tip{
font-size:12px;
color:#666;
margin:6px 0 4px;
}
.wrap-row{
display:flex;
flex-wrap:wrap;
gap:6px;
margin-bottom:8px;
}
.eg-char-btn {
width: 40px !important;
height: 40px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 26px !important;
font-family: "KacstOne",sans-serif !important;
background: #f8f9fa !important;
border: 1px solid #dee2e6 !important;
border-radius: 6px !important;
cursor: pointer !important;
transition: all 0.15s ease !important;
color: black !important;
user-select: none !important;
pointer-events: auto !important;
}
.eg-char-btn:hover {
background: #eff6ff !important;
border-color: #2563eb !important;
color: #2563eb !important;
transform: translateY(-2px) !important;
}
.eg-char-btn:active {
transform: translateY(0) !important;
}
.eg-copy-toast {
position: fixed !important;
top: 20px !important;
left: 50% !important;
transform: translateX(-50%) translateY(-20px) !important;
background: #10b981 !important;
color: white !important;
padding: 6px 16px !important;
border-radius: 4px !important;
font-size: 14px !important;
z-index: 2147483648 !important;
opacity: 0 !important;
transition: all 0.3s ease !important;
pointer-events: none !important;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
white-space: nowrap !important;
}
.eg-copy-toast.show {
opacity: 1 !important;
transform: translateX(-50%) translateY(0) !important;
}
`;
document.head.appendChild(style);
document.body.appendChild(panel);
const bodyEl = document.getElementById('eg-plate-body');
// 数字分组
let html = `▸ 车牌数字
`;
numArr.forEach(char=>{
html += `
${char}
`;
})
html += `
`;
// 字母分组
html += `▸ 车牌字母
`;
charArr.forEach(char=>{
html += `
${char}
`;
})
html += `
`;
bodyEl.innerHTML = html;
// 绑定点击复制
bodyEl.addEventListener('click',e=>{
const btn = e.target.closest('.eg-char-btn');
if(!btn) return;
copyChar(btn.dataset.char);
})
const toggleBtn = document.getElementById('eg-plate-toggle');
toggleBtn.onclick = (e) => {
e.stopPropagation();
if (bodyEl.classList.contains('hidden')) {
bodyEl.classList.remove('hidden');
toggleBtn.textContent = '—';
} else {
bodyEl.classList.add('hidden');
toggleBtn.textContent = '+';
}
};
// 复制函数
async function copyChar(text) {
console.log('复制:', text);
try {
await navigator.clipboard.writeText(text);
showToast(`已复制: ${text}`);
} catch (err) {
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
textarea.style.top = '-9999px';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
textarea.setSelectionRange(0, textarea.value.length);
try {
const success = document.execCommand('copy');
if (success) showToast(`已复制: ${text}`);
else showToast(`复制失败`);
} catch (e) {
showToast(`复制失败`);
}
document.body.removeChild(textarea);
}
}
let toastTimeout;
function showToast(msg) {
let toast = document.querySelector('.eg-copy-toast');
if (!toast) {
toast = document.createElement('div');
toast.className = 'eg-copy-toast';
document.body.appendChild(toast);
}
toast.textContent = msg;
toast.classList.add('show');
clearTimeout(toastTimeout);
toastTimeout = setTimeout(() => toast.classList.remove('show'), 1200);
}
// 拖拽逻辑保持原样
let isDragging = false;
let dragStartX = 0, dragStartY = 0;
let currentTranslateX = 0, currentTranslateY = 0;
let initialTranslateX = 0, initialTranslateY = 0;
let hasMoved = false;
const header = document.getElementById('eg-plate-header');
function getCurrentTransform() {
const transform = window.getComputedStyle(panel).transform;
if (transform === 'none') return { x: 0, y: 0 };
const matrix = transform.match(/matrix\(([^)]+)\)/);
if (matrix) {
const values = matrix[1].split(', ');
return { x: parseFloat(values[4]) || 0, y: parseFloat(values[5]) || 0 };
}
return { x: 0, y: 0 };
}
function onMouseMove(e) {
if (!isDragging) return;
e.preventDefault();
const dx = e.clientX - dragStartX;
const dy = e.clientY - dragStartY;
currentTranslateX = initialTranslateX + dx;
currentTranslateY = initialTranslateY + dy;
panel.style.transform = `translate(${currentTranslateX}px, ${currentTranslateY}px)`;
panel.style.top = panel.style.left = panel.style.right = panel.style.bottom = 'auto';
hasMoved = true;
}
function onMouseUp() {
if (!isDragging) return;
isDragging = false;
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
document.body.style.userSelect = '';
setTimeout(() => { hasMoved = false; }, 10);
}
function onMouseDown(e) {
if (e.target === toggleBtn || toggleBtn.contains(e.target)) return;
e.preventDefault();
isDragging = true;
hasMoved = false;
dragStartX = e.clientX;
dragStartY = e.clientY;
const transform = getCurrentTransform();
initialTranslateX = transform.x;
initialTranslateY = transform.y;
document.body.style.userSelect = 'none';
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
}
header.addEventListener('mousedown', onMouseDown);
panel.addEventListener('click', (e) => {
if (hasMoved) e.stopPropagation();
});
})();