切换中英日法西
当前为
// ==UserScript==
// @name 语言切换
// @namespace http://tampermonkey.net/
// @version 20250703
// @license MIT
// @description 切换中英日法西
// @author zr
// @match https://doctor-frontend.dev.chohotech.com/*
// @match https://doctor-frontend.alpha.chohotech.com/*
// @match https://doctor-frontend.uat.chohotech.com/*
// @match https://doctor-frontend.tenant.chohotech.com/*
// @match https://doctor-frontend.uat-sg.chohotech.com/*
// @match localhost:5173/*
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(function() {
'use strict';
// 检查当前页面是否在 iframe 中
if (window.self !== window.top) {
return; // 如果在 iframe 中,则不执行脚本
}
// 创建样式
const style = document.createElement('style');
style.textContent = `
.language-panel {
position: fixed;
left: -100px;
top: 50%;
transform: translateY(-50%);
width: 100px;
background: #fff;
border-radius: 0 6px 6px 0;
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.2);
z-index: 10000;
transition: all 0.25s ease;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
border: 1px solid #ccc;
border-left: none;
}
.language-panel:hover {
left: 0;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.25);
}
.panel-trigger {
position: absolute;
right: -12px;
top: 50%;
transform: translateY(-50%);
width: 12px;
height: 40px;
background: #4a90e2;
border: 1px solid #357abd;
border-left: none;
border-radius: 0 6px 6px 0;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: white;
font-size: 8px;
font-weight: 600;
writing-mode: vertical-rl;
text-orientation: mixed;
letter-spacing: 0.5px;
transition: all 0.25s ease;
}
.panel-trigger:hover {
background: #357abd;
color: white;
width: 15px;
}
.panel-content {
padding: 8px 6px;
opacity: 0;
transform: translateX(-10px);
transition: all 0.25s ease 0.1s;
}
.language-panel:hover .panel-content {
opacity: 1;
transform: translateX(0);
}
.button-group {
display: flex;
flex-direction: column;
gap: 3px;
}
.group-title {
color: #777;
font-size: 8px;
font-weight: 600;
margin: 5px 0 2px 0;
text-transform: uppercase;
letter-spacing: 0.3px;
}
.lang-btn {
background: #f5f5f5;
border: 1px solid #ccc;
color: #333;
padding: 4px 6px;
border-radius: 4px;
cursor: pointer;
font-size: 9px;
font-weight: 500;
transition: all 0.2s ease;
text-align: center;
}
.lang-btn:hover {
background: #e9e9e9;
border-color: #aaa;
color: #000;
}
.lang-btn:active {
background: #ddd;
transform: translateY(1px);
}
.lang-btn.info {
background: #5bc0de;
border-color: #46b8da;
color: white;
font-weight: 600;
}
.lang-btn.info:hover {
background: #46b8da;
border-color: #31b0d5;
color: white;
}
`;
document.head.appendChild(style);
// 创建主面板
const panel = document.createElement('div');
panel.className = 'language-panel';
// 创建触发器
const trigger = document.createElement('div');
trigger.className = 'panel-trigger';
trigger.textContent = '语言';
// 创建面板内容
const content = document.createElement('div');
content.className = 'panel-content';
// 创建按钮组容器
const buttonGroup = document.createElement('div');
buttonGroup.className = 'button-group';
// 语言切换组标题
const langGroupTitle = document.createElement('div');
langGroupTitle.className = 'group-title';
langGroupTitle.textContent = '语言切换';
// 创建按钮配置
const buttons = [
{ text: '中文', class: 'info', action: 'setLangZh' },
{ text: '英语', class: 'info', action: 'setLangEn' },
{ text: '日语', class: 'info', action: 'setLangJa' },
{ text: '法语', class: 'info', action: 'setLangFr' },
{ text: '西语', class: 'info', action: 'setLangEs' }
];
// 添加标题
buttonGroup.appendChild(langGroupTitle);
// 创建按钮
buttons.forEach((btnConfig) => {
const btn = document.createElement('div');
btn.className = `lang-btn ${btnConfig.class}`;
btn.textContent = btnConfig.text;
btn.addEventListener('click', () => handleButtonClick(btnConfig.action));
buttonGroup.appendChild(btn);
});
// 组装面板
content.appendChild(buttonGroup);
panel.appendChild(trigger);
panel.appendChild(content);
document.body.appendChild(panel);
// 通知函数
function showNotification(message, type = 'success') {
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed;
top: 15px;
right: 15px;
background: ${type === 'success' ? '#28a745' : '#dc3545'};
color: white;
padding: 6px 12px;
border-radius: 3px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
z-index: 10001;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 11px;
font-weight: 500;
transform: translateX(100%);
transition: transform 0.25s ease;
max-width: 200px;
`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
notification.style.transform = 'translateX(0)';
}, 100);
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
setTimeout(() => {
document.body.removeChild(notification);
}, 250);
}, 2000);
}
// 获取当前URL中hash部分的language值
function getCurrentLanguageFromHash() {
const hash = window.location.hash;
if (hash && hash.includes('?')) {
const hashQuery = hash.split('?')[1];
const hashParams = new URLSearchParams(hashQuery);
return hashParams.get('language');
}
return null;
}
// 检查hash部分是否包含language参数
function hasLanguageInHash() {
const hash = window.location.hash;
if (hash && hash.includes('?')) {
const hashQuery = hash.split('?')[1];
const hashParams = new URLSearchParams(hashQuery);
return hashParams.has('language');
}
return false;
}
// 修改hash部分的language参数并重定向
function redirectWithLanguage(newLang) {
const hash = window.location.hash;
if (hash && hash.includes('?')) {
const hashParts = hash.split('?');
const hashBase = hashParts[0]; // #/
const hashQuery = hashParts[1];
const hashParams = new URLSearchParams(hashQuery);
// 修改language参数
hashParams.set('language', newLang);
// 重新构造URL
const newHash = hashBase + '?' + hashParams.toString();
// 同时更新localStorage和URL hash
localStorage.setItem('language', newLang);
window.location.hash = newHash;
// 立即刷新页面以应用语言变化
setTimeout(() => {
window.location.reload();
}, 50);
}
}
// 只修改localStorage
function setLanguageLocalStorageOnly(newLang) {
localStorage.setItem('language', newLang);
showNotification(`已切换到${getLanguageName(newLang)},页面将自动刷新...`);
setTimeout(() => location.reload(), 1000);
}
// 获取语言名称
function getLanguageName(lang) {
const langMap = {
'zh': '中文',
'en': '英语',
'ja': '日语',
'fr': '法语',
'es': '西语'
};
return langMap[lang] || lang;
}
// 按钮点击处理函数
function handleButtonClick(action) {
switch(action) {
case 'setLangZh':
if(hasLanguageInHash()) {
let currentLang = getCurrentLanguageFromHash();
if(currentLang !== 'zh'){
showNotification('切换到中文,即将重定向...');
setTimeout(() => redirectWithLanguage('zh'), 500);
} else {
showNotification('当前已经是中文');
}
} else {
let currentLangStorage = localStorage.getItem('language');
if(currentLangStorage !== 'zh'){
setLanguageLocalStorageOnly('zh');
} else {
showNotification('当前已经是中文');
}
}
break;
case 'setLangEn':
if(hasLanguageInHash()) {
let currentLangEn = getCurrentLanguageFromHash();
if(currentLangEn !== 'en'){
showNotification('切换到英语,即将重定向...');
setTimeout(() => redirectWithLanguage('en'), 500);
} else {
showNotification('当前已经是英语');
}
} else {
let currentLangStorage = localStorage.getItem('language');
if(currentLangStorage !== 'en'){
setLanguageLocalStorageOnly('en');
} else {
showNotification('当前已经是英语');
}
}
break;
case 'setLangJa':
if(hasLanguageInHash()) {
let currentLangJa = getCurrentLanguageFromHash();
if(currentLangJa !== 'ja'){
showNotification('切换到日语,即将重定向...');
setTimeout(() => redirectWithLanguage('ja'), 500);
} else {
showNotification('当前已经是日语');
}
} else {
let currentLangStorage = localStorage.getItem('language');
if(currentLangStorage !== 'ja'){
setLanguageLocalStorageOnly('ja');
} else {
showNotification('当前已经是日语');
}
}
break;
case 'setLangFr':
if(hasLanguageInHash()) {
let currentLangFr = getCurrentLanguageFromHash();
if(currentLangFr !== 'fr'){
showNotification('切换到法语,即将重定向...');
setTimeout(() => redirectWithLanguage('fr'), 500);
} else {
showNotification('当前已经是法语');
}
} else {
let currentLangStorage = localStorage.getItem('language');
if(currentLangStorage !== 'fr'){
setLanguageLocalStorageOnly('fr');
} else {
showNotification('当前已经是法语');
}
}
break;
case 'setLangEs':
if(hasLanguageInHash()) {
let currentLangEs = getCurrentLanguageFromHash();
if(currentLangEs !== 'es'){
showNotification('切换到西语,即将重定向...');
setTimeout(() => redirectWithLanguage('es'), 500);
} else {
showNotification('当前已经是西语');
}
} else {
let currentLangStorage = localStorage.getItem('language');
if(currentLangStorage !== 'es'){
setLanguageLocalStorageOnly('es');
} else {
showNotification('当前已经是西语');
}
}
break;
}
}
})();