TutorDBOps Helper

try to improve TutorDBOps

目前为 2021-10-01 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name TutorDBOps Helper
  3. // @namespace http://tpdbops.tutorabc.com/
  4. // @version 0.62
  5. // @description try to improve TutorDBOps
  6. // @author Tex
  7. // @match http://tpdbops.tutorabc.com/mysqlmanage/select_*
  8. // @icon https://www.google.com/s2/favicons?domain=tutorabc.com
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. const isMssqlPage = location.pathname.includes('mssql');
  14.  
  15. const dbopsStorage = {
  16. prefix: isMssqlPage ? 'dbops-mssql-' : 'dbops-mysql-',
  17. set:(key, value) => localStorage.setItem(dbopsStorage.prefix+key, value),
  18. get:(key) => localStorage.getItem(dbopsStorage.prefix+key),
  19. }
  20. function addCss(cssString) {
  21. const head = document.getElementsByTagName('head')[0];
  22. const newCss = document.createElement('style');
  23. newCss.type = "text/css";
  24. newCss.innerHTML = cssString;
  25. head.appendChild(newCss);
  26. }
  27. function loadScript(url, callback) {
  28. if(!url) return;
  29. const head = document.getElementsByTagName('head')[0];
  30. const script = document.createElement('script');
  31. head.appendChild(script);
  32. script.src = url;
  33. script.onload = script.onreadystagechange = function() {
  34. console.log('loaded:', url);
  35. callback && callback();
  36. }
  37. }
  38.  
  39. const searchBtn = document.getElementById("search");
  40. function submitSql() {
  41. searchBtn.click();
  42. }
  43.  
  44. function collapse(showLeftArea) {
  45. // hide sidebar
  46. const sidebar = document.querySelector("#container > aside");
  47. sidebar.style.width = showLeftArea? '230px' : '0px';
  48. sidebar.style.opacity = showLeftArea? '1' : '0';
  49. sidebar.style['z-index'] = showLeftArea? 'unset' : '-1';
  50. // remove right area margin left
  51. const rightblock = document.querySelector("#container > section");
  52. rightblock.style['margin-left'] = showLeftArea ? '230px':'0px';
  53. }
  54.  
  55. function aceLoadCallback() {
  56. ace.config.loadModule('ace/ext/textarea', function(m) {
  57. const textArea = document.querySelector("form div > textarea");
  58. m.transformTextarea(textArea, {fontSize: '14px', mode: isMssqlPage ? 'sqlserver':'mysql', theme: 'cobalt', showPrintMargin: false });
  59. })
  60. }
  61.  
  62. loadScript('https://ajaxorg.github.io/ace-builds/src-noconflict/ace.js', aceLoadCallback);
  63.  
  64. const storageVal = dbopsStorage.get('showLeftArea');
  65. let showLeftArea = storageVal === 'true' ?? true;
  66. collapse(showLeftArea)
  67.  
  68. function toggleRightArea() {
  69. // toggle state
  70. showLeftArea = !showLeftArea;
  71. dbopsStorage.set('showLeftArea',showLeftArea);
  72. collapse(showLeftArea)
  73. }
  74.  
  75. const hint = document.querySelector("div.box.box-success > form > table > tbody > tr > td:nth-child(2)");
  76. hint.style.display = 'none';
  77.  
  78. const executePlanBtn = document.querySelector("div.box.box-success > form > table > tbody > tr > td:nth-child(1) > div > div > button:nth-child(7)")
  79. const hostTitle = document.querySelector("form > div.box-header.with-border.table_sort_form > a:nth-child(1) > input");
  80. const dbTitle = document.querySelector("form > div.box-header.with-border.table_sort_form > a:nth-child(3) > input");
  81. if(executePlanBtn) executePlanBtn.innerText="查看執行計畫";
  82. searchBtn.innerText="執行"
  83. hostTitle.value="主機 (雙擊輸入框清空)"
  84. dbTitle.value="資料庫"
  85.  
  86. const hostSelector = document.querySelector("#doc-vld-post-1");
  87. const dbSelector = document.querySelector("#doc-vld-level-1")
  88.  
  89. const storedHost = dbopsStorage.get('host');
  90. const storedDB = dbopsStorage.get('db');
  91.  
  92. const hosts = Array.from(hostSelector.children).map(e => e.value);
  93. const hostInput = document.createElement('input');
  94. hostInput.setAttribute("list", "hostlist");
  95. hostInput.id='hosts';
  96. hostInput.name='hosts';
  97. hostInput.placeholder="請選擇主機";
  98. hostInput.className="topInput"
  99. hostInput.ondblclick = (e) => {
  100. e.target.value='';
  101. }
  102. if(storedHost) hostInput.value = storedHost;
  103. const hostDataList = document.createElement('datalist');
  104. hostDataList.id = 'hostlist';
  105. hosts.forEach(e => {
  106. const op = document.createElement('option');
  107. op.value = e;
  108. hostDataList.appendChild(op)
  109. });
  110.  
  111. const hostAnchor = document.querySelector("form > div.box-header.with-border.table_sort_form > a:nth-child(1)");
  112. hostAnchor.parentNode.insertBefore(hostDataList, hostAnchor.nextSibling);
  113. hostAnchor.parentNode.insertBefore(hostInput, hostAnchor.nextSibling);
  114.  
  115. //hostSelector.remove();
  116. hostSelector.style.display="none";
  117. hostSelector.removeAttribute("required");
  118. hostSelector.name="hh";
  119.  
  120.  
  121. function updateDBInput(val, callback) {
  122. fetch('http://tpdbops.tutorabc.com/mysqlmanage/ipdbname/'+val)
  123. .then(r => r.json())
  124. .then(dbs => {
  125. dbDataList.replaceChildren(null);
  126. dbInput.value='';
  127. dbs.forEach((e, index) => {
  128. const op = document.createElement('option');
  129. op.value = e;
  130. dbDataList.appendChild(op)
  131. })
  132. const dbAnchor = document.querySelector("form > div.box-header.with-border.table_sort_form > a:nth-child(5)");
  133. dbAnchor.parentNode.insertBefore(dbDataList, dbAnchor.nextSibling);
  134. dbAnchor.parentNode.insertBefore(dbInput, dbAnchor.nextSibling);
  135. callback();
  136. })
  137. }
  138.  
  139. const dbInput = document.createElement('input');
  140. dbInput.setAttribute("list", "dblist");
  141. dbInput.id='dbs';
  142. dbInput.name='dbs';
  143. dbInput.placeholder="請選擇資料庫";
  144. dbInput.className="topInput"
  145. dbInput.ondblclick = (e) => {
  146. e.target.value='';
  147. }
  148. if(storedHost && storedDB) {
  149. updateDBInput(storedHost, () => {dbInput.value = storedDB})
  150. };
  151. const dbDataList = document.createElement('datalist');
  152. dbDataList.id='dblist'
  153. hostInput.onchange = (e) => {
  154. dbopsStorage.set('host',e.target.value);
  155. updateDBInput(e.target.value)
  156. hostSelector.value=e.target.value;
  157. }
  158.  
  159. dbInput.onchange = (e) => {
  160. dbopsStorage.set('db',e.target.value);
  161. dbSelector.value=e.target.value;
  162. }
  163.  
  164. //dbSelector.remove();
  165. dbSelector.style.display="none";
  166. dbSelector.removeAttribute("required");
  167. dbSelector.name="dd";
  168.  
  169. // autofocus sql textarea
  170. const sqlTextArea = document.querySelector("form > table > tbody > tr > td:nth-child(1) > div > div > textarea")
  171. sqlTextArea.focus();
  172.  
  173. // enroll event
  174. document.onkeydown = function(e) {
  175. if(e.code === 'Enter' && e.ctrlKey) {
  176. submitSql();
  177. }
  178. if(e.code === 'KeyB' && e.ctrlKey) {
  179. toggleRightArea();
  180. }
  181. }
  182.  
  183. addCss(`
  184. * {
  185. font-family: Consolas;
  186. font-weight: bold;
  187. font-size: 14px;
  188. }
  189. .form-group, div.box.box-success > form > table {
  190. width: 100%;
  191. }
  192. textarea.form-control {
  193. width: 100% !important;
  194. height: 60vh;
  195. }
  196. table.table-hover, small{
  197. transform: rotateX(180deg);
  198. }
  199. .box-footer {
  200. transform: rotateX(180deg);
  201. }
  202. .box-footer ~ .box-footer{
  203. margin-top: 30px;
  204. overflow: unset !important;
  205. overflow-x: auto !important;
  206. }
  207. .box-footer table {
  208. width: 99%;
  209. margin: 0 auto;
  210. }
  211. .topInput {
  212. margin-left: 10px;
  213. width: 250px;
  214. }
  215. .table_sort_form > a:nth-child(1) > input {
  216. cursor: default;
  217. }
  218. .table_sort_form > a:nth-child(3) > input {
  219. cursor: default;
  220. }
  221. form > table > tbody > tr > td:nth-child(1) > div > div > div {
  222. width: 100% !important;
  223. ]
  224. `)
  225. })();
  226.