Greasy Fork is available in English.
JumpServer自动打开Xshell
// ==UserScript==
// @name Xshell for JumpServer
// @namespace Violentmonkey Scripts
// @icon http://10.21.1.10:20080/static/img/facio.ico
// @version 1.0.0
//
// @match http://10.21.1.10:20080/luna/*
// @grant none
// @license MIT
//
// @author vidda
// @description JumpServer自动打开Xshell
// ==/UserScript==
(function () {
'use strict';
// 点击查看密码按钮,显示密码
function clickEyeIcon(contentDiv) {
// 使用CSS选择器查找目标元素
const eyeIcon = contentDiv.querySelector('.show-password .fa-eye');
if (eyeIcon) {
eyeIcon.click();
return true;
}
return false;
}
// 获取密码
function getPassword(contentDiv) {
// 选择包含密码的span元素
const passwordSpan = contentDiv.querySelector('.show-password span');
if (passwordSpan) {
// 获取文本内容并去除首尾空格
const password = passwordSpan.textContent.trim();
return password;
} else {
console.log('未找到密码元素');
return null;
}
}
function getSshCmd(contentDiv) {
const commandPre = contentDiv.querySelector('.command pre');
if (commandPre) {
// 获取文本内容并去除首尾空格
const command = commandPre.textContent.trim();
return command;
} else {
console.log('未找到command元素');
return null;
}
}
function triggerContextMenu(element) {
const event = new MouseEvent('contextmenu', {
bubbles: true,
cancelable: true,
view: window,
button: 2,
buttons: 2,
clientX: element.getBoundingClientRect().left,
clientY: element.getBoundingClientRect().top
});
// 如果需要兼容极老浏览器,可以使用 initMouseEvent (现代浏览器一般不需要)
return element.dispatchEvent(event);
}
function refreshTab(contentDiv) {
const refreshMenu = document.querySelectorAll('div.view-menu table tr')[1].children[0];
refreshMenu.click();
setTimeout(() => {
const commandEle = contentDiv.querySelector('.command');
createButton(commandEle);
}, 200);
}
function openXshell(contentDiv) {
const password = getPassword(contentDiv);
let src = 'xshell://';
let command = getSshCmd(contentDiv);
command = command.substring(2);
command = command.replace('ssh ', 'ssh//');
// 在 @ 符号前插入 ":pwd"
command = command.replace(/@/, ':' + password + '@');
command = command.replace(' -p ', ':');
src += command;
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = src;
document.body.appendChild(iframe);
// 获取目标元素
let tabActive = document.querySelector('elements-content-tab li.active');
triggerContextMenu(tabActive);
setTimeout(() => {
clickEyeIcon(contentDiv);
refreshTab(contentDiv);
}, 100);
}
function loopContainer() {
const targetElement = document.querySelector('#winContainer');
const observer = new MutationObserver(function (mutations) {
setTimeout(() => {
const container = document.querySelectorAll('div.content');
if (container) {
container.forEach(function (parent) {
const commandContainer = parent.children[1];
const commandEle = commandContainer.querySelector('.command');
createButton(commandEle);
});
}
}, 100);
});
observer.observe(targetElement, { childList: true, subtree: false });
}
// 等待目标容器出现(如果是动态加载的页面)
function waitForWindowContainer() {
const container = document.querySelector('#winContainer');
if (container) {
loopContainer(container);
} else {
// 如果容器还没出现,用 MutationObserver 监听
const observer = new MutationObserver(function (mutations) {
const container = document.querySelector('#winContainer');
if (container) {
loopContainer();
observer.disconnect(); // 找到后停止监听
}
});
observer.observe(document.body, { childList: true, subtree: true });
// 设置超时,避免无限等待
setTimeout(() => observer.disconnect(), 10000);
}
}
function createButton(container) {
// 检查是否已存在,避免重复插入
if (container.querySelector('.xshell-button')) {
return;
}
// 创建圆形按钮
const button = document.createElement('button');
button.classList.add('xshell-button');
button.textContent = 'X';
button.title = '使用Xshell打开';
button.style.cssText = `
position: absolute;
right: 46px;
top: 4px;
width: 35px;
height: 35px;
background: transparent;
border-radius: 5px;
border: 1px solid rgba(240, 246, 252, .1);
color: #f74d38;
font-size: 18px;
font-weight: bold;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
`;
// 鼠标悬停效果
button.addEventListener('mouseenter', () => {
button.style.background = '#30363d';
button.style.borderColor = '#8b949e';
});
button.addEventListener('mouseleave', () => {
button.style.background = 'transparent';
button.style.borderColor = 'rgba(240, 246, 252, .1)';
});
// 点击事件
button.addEventListener('click', function () {
clickEyeIcon(container.parentElement.parentElement);
setTimeout(function () {
openXshell(container.parentElement.parentElement);
}, 100)
});
// 插入到容器最后一个子元素之后(即作为最后一个子元素)
container.prepend(button);
}
// 页面加载完成后执行
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', waitForWindowContainer);
} else {
waitForWindowContainer();
}
})();