您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
低代码平台助手
当前为
// ==UserScript== // @name lowerCodeHelper // @namespace http://tampermonkey.net/ // @version 0.3.2 // @description 低代码平台助手 // @author Ziker // @match https://ops.iyunquna.com/63008/* // @match http://localhost:63342/api/file/* // @require https://code.jquery.com/jquery-3.4.1.min.js // @icon https://favicon.qqsuu.cn/work.yqn.com // @grant GM_openInTab // @grant unsafeWindow // @grant window.close // @grant window.focus // @run-at document-body // @noframes // @license AGPL License // ==/UserScript== window.jq = $.noConflict(true); (function (window) { window.pageHelper = { // 等待元素可见 waitElementVisible(visibleTag, index, fun) { let node = jq(visibleTag) if (node === null || node[index] === null || node[index] === undefined) { setTimeout(() => { pageHelper.waitElementVisible(visibleTag, index, fun) }, 500) } else { fun() } }, getCurrentAppIndex() { const nodes = document.getElementsByClassName("bar-tab"); for (let i = 0; i < nodes.length; i++) { if (nodes[i].className.indexOf("bar-tab-selected") > 0) { return i; } } return -1; }, getCurrentApiId() { const nodes = document.getElementsByClassName("tab-content-presentation-components"); if (nodes.length === 0) { return null; } let className = nodes[this.getCurrentAppIndex()].className; return className.substring(className.indexOf("theia-tab-") + "theia-tab-".length); }, sleep(duration) { return new Promise(resolve => { setTimeout(resolve, duration) }) }, showToast(msg, duration) { // 显示提示 duration = isNaN(duration) ? 3000 : duration; const m = document.createElement('div'); m.innerHTML = msg; m.style.cssText = "display: flex;justify-content: center;align-items: center;width:60%; min-width:180px; " + "background:#000000; opacity:0.98; height:auto;min-height: 50px;font-size:25px; color:#fff; " + "line-height:30px; text-align:center; border-radius:4px; position:fixed; top:85%; left:20%; z-index:999999;"; document.body.appendChild(m); setTimeout(function () { const d = 0.5; m.style.webkitTransition = '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in'; m.style.opacity = '0'; setTimeout(function () { document.body.removeChild(m) }, d * 1000); }, duration); }, // 关闭窗口 closeWindow() { window.opener = null; window.open('', '_self') window.close() }, formatString(str, len, padding) { const diff = len - str.toString().length; if (diff > 0) { return padding.repeat(diff) + str; } else { return str; } }, initSetting() { const customSetting = document.createElement("div"); document.body.appendChild(customSetting) customSetting.innerHTML = ` <div id="copy-setting" style="display: none;position: absolute;top: 0;right: 0;background-color: #fff3f3;padding: 10px;width: 600px;z-index: 9999"> <p>拷贝动作</p> <p><label>Copy File Id <input type="radio" name="copyValue" value="1" /></label></p> <p><label>Rest Api Open File <input type="radio" name="copyValue" value="2" checked/></label> 较新版本IDEA需要下载 <a target="_blank" href="https://plugins.jetbrains.com/plugin/19991-ide-remote-control">IDE Remote Control </a> 插件</p> <p><label>ToolBox Open File <input type="radio" name="copyValue" value="3" /></label> 需要下载 <a target="_blank" href="https://www.jetbrains.com/toolbox-app/">Jetbrains ToolBox</a> 工具箱软件</p> <div id="projectPath" style="visibility: visible"><p><label><input name="path" style="width: 100%" type="text" placeholder="项目路径截止到 src 前 E:/yqnProject/yqn-wms/yqn-wms-rest-provider/"/></label></p></div> <p style="visibility: hidden"><label>同时打开编排IDE <input type="checkbox" name="openIDE" /></label> </p> <div style="display: flex;margin: 5px;justify-content: space-between"> <button id="save" lang="zh" type="button" class="ant-btn ant-btn-default perf-tracked yqn-button"><span style="margin-left: 5px;">save</span></button> <button id="close" lang="zh" type="button" class="ant-btn ant-btn-default perf-tracked yqn-button"><span style="margin-left: 5px;">close</span></button> </div> </div> ` let copyValue = localStorage.getItem("copyValue") copyValue = copyValue === null || copyValue === undefined ? 1 : copyValue document.querySelector('input[name="copyValue"][value="' + copyValue + '"]').checked = true document.getElementById("projectPath").style.visibility = copyValue === "2" ? "visible" : "hidden" let path = localStorage.getItem("path") document.querySelector('input[name="path"]').value = path === null || path === undefined ? null : path let openIDE = JSON.parse(localStorage.getItem("openIDE")); document.querySelector('input[name="openIDE"]').checked = openIDE === null || openIDE === undefined ? false : openIDE const radios = document.querySelectorAll('input[name="copyValue"]'); for (let i = 0; i < radios.length; i++) { radios[i].onchange = () => { const remoteRadio = document.querySelector('input[name="copyValue"]:checked'); document.getElementById("projectPath").style.visibility = remoteRadio.value === "2" ? "visible" : "hidden"; } } document.getElementById("save").addEventListener("click", () => { const remoteRadio = document.querySelector('input[name="copyValue"]:checked').value; const pathInput = document.querySelector('input[name="path"]').value; const openIDEValue = document.querySelector('input[name="openIDE"]').checked; if (remoteRadio === '2' && (pathInput === null || pathInput.length === 0)) { this.showToast("路径不可为空", 1000) } else { localStorage.setItem("copyValue", remoteRadio) localStorage.setItem("path", pathInput) localStorage.setItem("openIDE", JSON.stringify(openIDEValue)) this.showToast("保存成功", 1000) } }) document.getElementById("close").addEventListener("click", () => { document.getElementById("copy-setting").style.display = "none" }) } } })(window); (function () { let historyTrace = '' 'use strict'; let appName = null jq(document).ready(function () { if (window.location.href.indexOf("localhost:63342/api/file/") >= 0) { window.pageHelper.closeWindow() return } // 监听api tab变动 waitObserve(".tabs-bar", () => { // 应用接口面板 const appPanelTag = ".tab-content-presentation-components.theia-tab-" + window.pageHelper.getCurrentApiId(); // 监听属性面板变动 waitObserve(appPanelTag + " .p-8", () => { const p8 = document.querySelector(appPanelTag + " .p-8"); const panel = p8.querySelector(".ant-form.ant-form-vertical.yqn-form"); if (nonNull(panel) && isNull(panel.querySelector(".customScriptInfo"))) { const div = document.createElement("div"); div.className = "customScriptInfo"; panel.appendChild(div) // 获取当前NodeName const childProcessNode = panel.querySelector("#code"); const codeSpan = p8.querySelector(".dashboard-code span"); if (isNull(childProcessNode) && isNull(codeSpan)) { return } let nodeName = nonNull(childProcessNode) ? childProcessNode.value : codeSpan.textContent // 获取当前节点信息 getNodeInfo(nodeName, node => { // 处理信息 const divNode = document.querySelector(appPanelTag + " .customScriptInfo"); // 清空显示 divNode.innerHTML = "" // 脚本 if (nonNull(node.scriptId)) { divNode.appendChild(createButton("脚本:" + node.scriptId, () => copyToClipboard(node.scriptId))) } // 入参 let id = node.inputScriptId; const inputScriptIds = node.inputScriptIds; if (nonNull(inputScriptIds)) { id = nonNull(id) ? id : inputScriptIds.example; id = nonNull(id) ? id : inputScriptIds.record; id = nonNull(id) ? id : inputScriptIds.recordList; id = nonNull(id) ? id : inputScriptIds.condition; id = nonNull(id) ? id : inputScriptIds.id; } let isJava = true if (nonNull(node.dslBulidData)) { isJava = false } if (isNull(id) && nonNull(node.dslBulidData)) { id = node.dslBulidData.dslScriptId; } if (nonNull(id)) { divNode.appendChild(createButton("入参:" + id, () => copyToClipboard(id, isJava))) } // 条件 const executeScriptId = node.executeScriptId; if (nonNull(executeScriptId)) { divNode.appendChild(createButton("条件:" + executeScriptId, () => copyToClipboard(executeScriptId))) } // 校验 const assertScriptId = node.assertScriptId; if (nonNull(assertScriptId)) { divNode.appendChild(createButton("校验:" + assertScriptId, () => copyToClipboard(assertScriptId))) } }) } }) // 监听执行历史面板变动 const executeHistoryBodyTag = appPanelTag + " .test-split-item.test-split-item-right .ant-table-body tbody"; waitObserve(executeHistoryBodyTag, () => { const lines = document.querySelectorAll(executeHistoryBodyTag + " .ant-table-row.ant-table-row-level-0"); if (nonNull(lines) && isNull(lines[0].querySelector(".customer-button-div"))) { const div = document.createElement("div"); lines[0].appendChild(div) div.className = "customer-button-div"; div.style.display = "none" getExecuteHistory(content => { for (let i = 0; i < content.length; i++) { const tds = lines[i].querySelectorAll("td"); const actionCol = tds[tds.length - 1]; const detailButton = actionCol.querySelectorAll("button")[0]; detailButton.style.display = "none" actionCol.insertBefore(createButton("RT:" + content[i].rt, () => { detailButton.click() historyTrace = tds[3].innerText }), detailButton) } }) } }) }) // 监听body变动 waitObserve("body", () => { // 监听执行日志流程图变动 const processPanelTag = ".node-bpmn #canvas .bjs-container .djs-container .viewport .layer-base"; waitObserve(processPanelTag, () => { const processPanel = document.querySelector(processPanelTag); const rtDiv = processPanel.querySelector(".customer-rt"); if (isNull(rtDiv)) { const div = document.createElement("div"); processPanel.appendChild(div) div.className = "customer-rt"; div.style.display = "none" getByTraceId(apiNodeLogList => { for (let i = 0; i < apiNodeLogList.length; i++) { const log = apiNodeLogList[i]; const textNode = processPanel.querySelector("[data-element-id='" + log.nodeId + "'] text"); if (isNull(textNode)) { continue } const tspan = textNode.querySelector("tspan"); if (nonNull(tspan)) { const rtNode = tspan.cloneNode(true); textNode.appendChild(rtNode) rtNode.setAttribute("x", "65") rtNode.setAttribute("y", "15") rtNode.innerHTML = window.pageHelper.formatString(log.rt, 4, ' ') } } }) } }, false) }) // 工具栏设置按钮 waitObserve(".app-actions", () => { const buttonLists = document.querySelector(".app-actions"); if (isNull(buttonLists) || nonNull(document.querySelector(".setting-flag"))) { return } appendFlagNode(document.body, "setting-flag") const settingButton = document.createElement("div"); settingButton.style.marginLeft = '10px' const button = document.createElement("button") button.type = "button" button.id = name button.className = "ant-btn ant-btn-default perf-tracked yqn-button" button.onclick = () => { const settingPanel = document.getElementById("copy-setting"); settingPanel.style.display = settingPanel.style.display === 'block' ? 'none' : "block" } const span = document.createElement("span") span.textContent = "CopySetting" button.appendChild(span) settingButton.appendChild(button) buttonLists.appendChild(settingButton) }) window.pageHelper.initSetting() getAppProjectName(data => appName = data) }) function nonNull(o) { return o !== null && o !== undefined; } function isNull(o) { return o === null || o === undefined; } // 追加标记节点 function appendFlagNode(node, flag) { const divFlag = document.createElement("div"); node.appendChild(divFlag) divFlag.className = flag; divFlag.style.display = "none" } // 等待出现并监听变化 function waitObserve(visibleTag, fun, attributes = true) { window.pageHelper.waitElementVisible(visibleTag, 0, () => { new MutationObserver(function (mutationsList) { fun() }).observe(document.querySelector(visibleTag), { attributes: attributes, childList: true, subtree: true, characterData: true }) }) } function copyToClipboard(text, isJava = true) { let copyValue = localStorage.getItem("copyValue"); copyValue = copyValue === null || copyValue === undefined ? '1' : copyValue; if (copyValue === '1') { let textarea = document.createElement('textarea'); textarea.value = text; document.body.appendChild(textarea); textarea.select(); document.execCommand('copy'); document.body.removeChild(textarea); window.pageHelper.showToast("已拷贝 " + text, 1500) } else if (copyValue === '2') { let path = localStorage.getItem("path"); path = path === null || path === undefined ? null : path; otherReq("http://127.0.0.1:63342/api/file/" + path + "src/main/java/com/yqn/framework/composer/api/api_" + window.pageHelper.getCurrentApiId() + "/script/Script_" + text + (isJava ? ".java" : ".json")) window.pageHelper.showToast("已打开文件,如未打开,检查插件是否安装以及path是否正确", 2000) } else if (copyValue === '3') { window.open('jetbrains://idea/navigate/reference?project=' + appName + '&fqn=com.yqn.framework.composer.api.api_' + window.pageHelper.getCurrentApiId() + '.script.Script_' + text) window.pageHelper.showToast("已打开文件,如未打开,请确认已安装Jetbrains Toolbox ", 2000) } } // 创建按钮 function createButton(name, listener) { const button = document.createElement("button") button.type = "button" button.id = name button.className = "ant-btn ant-btn-link perf-tracked yqn-button yqn-link-no-padding customer-button" button.onclick = listener const span = document.createElement("span") span.textContent = name button.appendChild(span) return button; } // 拿流程信息 function getNodeInfo(nodeName, fuc, apiMode = 0) { const addressArr = ['', '/process', '/mq', '/job']; remoteReq('/api/42080/api' + addressArr[apiMode] + '/details_composer', { "id": window.pageHelper.getCurrentApiId(), }, data => { if (isNull(data)) { if (apiMode === 0) { getNodeInfo(nodeName, fuc, 1) getNodeInfo(nodeName, fuc, 2) getNodeInfo(nodeName, fuc, 3) } return } let processDefine = JSON.parse(data.processDefine); for (let i = 0; i < processDefine.nodes.length; i++) { if (processDefine.nodes[i].code === nodeName) { fuc(processDefine.nodes[i]) break } } }) } // 拿历史执行数据 function getExecuteHistory(fuc) { remoteReq('/api/42086/apiLog/list', {}, data => { if (nonNull(data) && nonNull(data.content)) { fuc(data.content) } }) } // 拿 trace 执行数据 function getByTraceId(fuc, apiMode = 0) { const apiType = ['api', 'process', 'mq', 'job']; remoteReq('/api/42086/apiLog/getByTraceId', { "traceIdLike": historyTrace, "testCaseId": null, "apiTypeCode": apiMode === 0 ? "api" : apiType[apiMode] }, data => { if (nonNull(data) && nonNull(data.apiNodeLogList) && data.apiNodeLogList.length !== 0) { fuc(data.apiNodeLogList) } else if (apiMode === 0) { getByTraceId(fuc, 1) getByTraceId(fuc, 2) getByTraceId(fuc, 3) } }) } // 获取应用名称 function getAppProjectName(fuc) { remoteReq('/api/42080/application/getById', {}, data => { if (nonNull(data)) { fuc(data.appName) } }) } function remoteReq(url, model, fuc) { model.apiId = window.pageHelper.getCurrentApiId() model.appId = new URLSearchParams(window.location.href.split('?')[1]).get('appId') model.env = "qa4" model.page = 1 model.size = 20 jq.ajax({ url: 'https://gw-ops.iyunquna.com' + url, method: 'POST', xhrFields: { withCredentials: true }, crossDomain: true, contentType: 'application/json', data: JSON.stringify({ "header": { "xSourceAppId": "63008", "guid": "6f87e073-1da1-4017-b2de-c109abcd6d123", "lang": "zh", "timezone": "Asia/Shanghai" }, "model": model }), success: function (response) { if (response.code === 200) { fuc(response.data) } }, error: function (xhr, status, error) { console.log('Request failed:', error); } }); } function otherReq(url) { jq.ajax(url, { method: "GET", xhrFields: { withCredentials: true }, crossDomain: true }) } })();