TutorDBOps Helper

try to improve TutorDBOps

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         TutorDBOps Helper
// @namespace    http://tpdbops.tutorabc.com/
// @version      0.62
// @description  try to improve TutorDBOps
// @author       Tex
// @match        http://tpdbops.tutorabc.com/mysqlmanage/select_*
// @icon         https://www.google.com/s2/favicons?domain=tutorabc.com
// @grant        none
// ==/UserScript==

(function() {
    const isMssqlPage = location.pathname.includes('mssql');

    const dbopsStorage = {
        prefix: isMssqlPage ? 'dbops-mssql-' : 'dbops-mysql-',
        set:(key, value) => localStorage.setItem(dbopsStorage.prefix+key, value),
        get:(key) => localStorage.getItem(dbopsStorage.prefix+key),
    }
    function addCss(cssString) {
        const head = document.getElementsByTagName('head')[0];
        const newCss = document.createElement('style');
        newCss.type = "text/css";
        newCss.innerHTML = cssString;
        head.appendChild(newCss);
    }
    function loadScript(url, callback) {
        if(!url) return;
        const head = document.getElementsByTagName('head')[0];
        const script = document.createElement('script');
        head.appendChild(script);
        script.src = url;
        script.onload = script.onreadystagechange = function() {
            console.log('loaded:', url);
            callback && callback();
        }
    }

    const searchBtn = document.getElementById("search");
    function submitSql() {
        searchBtn.click();
    }

    function collapse(showLeftArea) {
        // hide sidebar
        const sidebar = document.querySelector("#container > aside");
        sidebar.style.width = showLeftArea? '230px' : '0px';
        sidebar.style.opacity = showLeftArea? '1' : '0';
        sidebar.style['z-index'] = showLeftArea? 'unset' : '-1';
        //  remove right area margin left
        const rightblock = document.querySelector("#container > section");
        rightblock.style['margin-left'] = showLeftArea ? '230px':'0px';
    }

    function aceLoadCallback() {
        ace.config.loadModule('ace/ext/textarea', function(m) {
            const textArea = document.querySelector("form div > textarea");
            m.transformTextarea(textArea, {fontSize: '14px', mode: isMssqlPage ? 'sqlserver':'mysql', theme: 'cobalt', showPrintMargin: false });
        })
    }

    loadScript('https://ajaxorg.github.io/ace-builds/src-noconflict/ace.js', aceLoadCallback);

    const storageVal = dbopsStorage.get('showLeftArea');
    let showLeftArea = storageVal === 'true' ?? true;
    collapse(showLeftArea)

    function toggleRightArea() {
        // toggle state
        showLeftArea = !showLeftArea;
        dbopsStorage.set('showLeftArea',showLeftArea);
        collapse(showLeftArea)
    }

    const hint = document.querySelector("div.box.box-success > form > table > tbody > tr > td:nth-child(2)");
    hint.style.display = 'none';

    const executePlanBtn = document.querySelector("div.box.box-success > form > table > tbody > tr > td:nth-child(1) > div > div > button:nth-child(7)")
    const hostTitle = document.querySelector("form > div.box-header.with-border.table_sort_form > a:nth-child(1) > input");
    const dbTitle = document.querySelector("form > div.box-header.with-border.table_sort_form > a:nth-child(3) > input");
    if(executePlanBtn) executePlanBtn.innerText="查看執行計畫";
    searchBtn.innerText="執行"
    hostTitle.value="主機 (雙擊輸入框清空)"
    dbTitle.value="資料庫"

    const hostSelector = document.querySelector("#doc-vld-post-1");
    const dbSelector = document.querySelector("#doc-vld-level-1")

    const storedHost = dbopsStorage.get('host');
    const storedDB = dbopsStorage.get('db');

    const hosts = Array.from(hostSelector.children).map(e => e.value);
    const hostInput = document.createElement('input');
    hostInput.setAttribute("list", "hostlist");
    hostInput.id='hosts';
    hostInput.name='hosts';
    hostInput.placeholder="請選擇主機";
    hostInput.className="topInput"
    hostInput.ondblclick = (e) => {
        e.target.value='';
    }
    if(storedHost) hostInput.value = storedHost;
    const hostDataList = document.createElement('datalist');
    hostDataList.id = 'hostlist';
    hosts.forEach(e => {
        const op = document.createElement('option');
        op.value = e;
        hostDataList.appendChild(op)
    });

    const hostAnchor = document.querySelector("form > div.box-header.with-border.table_sort_form > a:nth-child(1)");
    hostAnchor.parentNode.insertBefore(hostDataList, hostAnchor.nextSibling);
    hostAnchor.parentNode.insertBefore(hostInput, hostAnchor.nextSibling);

    //hostSelector.remove();
    hostSelector.style.display="none";
    hostSelector.removeAttribute("required");
    hostSelector.name="hh";


    function updateDBInput(val, callback) {
        fetch('http://tpdbops.tutorabc.com/mysqlmanage/ipdbname/'+val)
            .then(r => r.json())
            .then(dbs => {
            dbDataList.replaceChildren(null);
            dbInput.value='';
            dbs.forEach((e, index) => {
                const op = document.createElement('option');
                op.value = e;
                dbDataList.appendChild(op)
            })
            const dbAnchor = document.querySelector("form > div.box-header.with-border.table_sort_form > a:nth-child(5)");
            dbAnchor.parentNode.insertBefore(dbDataList, dbAnchor.nextSibling);
            dbAnchor.parentNode.insertBefore(dbInput, dbAnchor.nextSibling);
            callback();
        })
    }

    const dbInput = document.createElement('input');
    dbInput.setAttribute("list", "dblist");
    dbInput.id='dbs';
    dbInput.name='dbs';
    dbInput.placeholder="請選擇資料庫";
    dbInput.className="topInput"
    dbInput.ondblclick = (e) => {
        e.target.value='';
    }
    if(storedHost && storedDB) {
        updateDBInput(storedHost, () => {dbInput.value = storedDB})
    };
    const dbDataList = document.createElement('datalist');
    dbDataList.id='dblist'
    hostInput.onchange = (e) => {
        dbopsStorage.set('host',e.target.value);
        updateDBInput(e.target.value)
        hostSelector.value=e.target.value;
    }

    dbInput.onchange = (e) => {
        dbopsStorage.set('db',e.target.value);
        dbSelector.value=e.target.value;
    }

    //dbSelector.remove();
    dbSelector.style.display="none";
    dbSelector.removeAttribute("required");
    dbSelector.name="dd";

    // autofocus sql textarea
    const sqlTextArea = document.querySelector("form > table > tbody > tr > td:nth-child(1) > div > div > textarea")
    sqlTextArea.focus();

    // enroll event
    document.onkeydown = function(e) {
        if(e.code === 'Enter' && e.ctrlKey) {
            submitSql();
        }
        if(e.code === 'KeyB' && e.ctrlKey) {
            toggleRightArea();
        }
    }

    addCss(`
       * {
        font-family: Consolas;
        font-weight: bold;
        font-size: 14px;
       }
       .form-group, div.box.box-success > form > table {
         width: 100%;
       }
       textarea.form-control {
         width: 100% !important;
         height: 60vh;
       }
       table.table-hover, small{
         transform: rotateX(180deg);
       }
       .box-footer {
       transform: rotateX(180deg);
       }
       .box-footer ~ .box-footer{
         margin-top: 30px;
         overflow: unset !important;
         overflow-x: auto !important;
       }
       .box-footer table {
         width: 99%;
         margin: 0 auto;
       }
       .topInput {
         margin-left: 10px;
         width: 250px;
       }
       .table_sort_form > a:nth-child(1) > input {
         cursor: default;
       }
       .table_sort_form > a:nth-child(3) > input {
         cursor: default;
       }
       form > table > tbody > tr > td:nth-child(1) > div > div > div {
         width: 100% !important;
       ]
    `)
})();