Xshell for JumpServer

JumpServer自动打开Xshell

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Advertisement:

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

Advertisement:

// ==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();
  }
})();