您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
低代码平台助手
// ==UserScript== // @name lowerCodeHelper // @namespace http://tampermonkey.net/ // @version 0.4.0 // @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 // @note 2023年12月18日20:26:31 V0.3.4 fix RT 显示BUG // @note 2024年01月04日11:50:57 V0.3.5 支持自定义包名接口打开文件 // @note 2024年01月10日11:00:40 V0.3.6 修复子流程,mq,job 跳转不显示 // @note 2024年01月15日19:46:34 V0.3.7 修复自定义包名 子流程,mq,job 不跳转,MQ 消费RT显示 // @note 2024年01月19日17:22:12 V0.3.8 顶部工具栏按钮新增多个工具按钮 // @note 2024年01月28日18:32:49 V0.3.9 修复Bug // @note 2024年02月02日19:59:18 V0.4.0 修复导致游览器卡顿的问题 // @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, fun) { const observer = new MutationObserver(() => { // 如果是目标元素存在 if (document.querySelector(visibleTag)) { observer.disconnect(); fun(); } }); observer.observe(document.body, { attributes: true, childList: true, subtree: true, characterData: true }); }, getCurrentApiId() { return unsafeWindow.activeKey }, getAppId() { return parseInt(new URLSearchParams(window.location.href.split('?')[1]).get('appId')) }, 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 let packageNameMap = [] let typeMap = [] let mutationObserverApiList = [] jq(document).ready(function () { // 关闭第二种文件打开方位打开的网页 if (window.location.href.indexOf("localhost:63342/api/file/") >= 0) { window.pageHelper.closeWindow() return } // 监听api tab变动 waitObserve(".tabs-bar", () => { // 关闭刚刚加入的所有变动监听 for (let i = 0; i < mutationObserverApiList.length; i++) { mutationObserverApiList[i].disconnect() } mutationObserverApiList = [] // bar切换关闭首页显示 const homePage = document.querySelector(".tab-home-page"); const tabsBar = document.querySelector(".tabs-bar"); if (nonNull(homePage) && nonNull(tabsBar) && nonNull(tabsBar.childNodes) && tabsBar.childNodes.length > 0) { homePage.style.display = 'none' } // 监听属性面板变动 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") if (isNull(divNode)) { return } // 清空显示 divNode.innerHTML = "" // 脚本 if (nonNull(node.scriptId)) { divNode.appendChild(createTextButton("脚本:" + 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 (isNull(id) && nonNull(node.dslBulidData)) { id = node.dslBulidData.dslScriptId isJava = false } if (nonNull(id)) { divNode.appendChild(createTextButton("入参:" + id, () => copyToClipboard(id, isJava))) } // 条件 const executeScriptId = node.executeScriptId if (nonNull(executeScriptId)) { divNode.appendChild(createTextButton("条件:" + executeScriptId, () => copyToClipboard(executeScriptId))) } // 校验 const assertScriptId = node.assertScriptId if (nonNull(assertScriptId)) { divNode.appendChild(createTextButton("校验:" + assertScriptId, () => copyToClipboard(assertScriptId))) } }) } }, true, observe => mutationObserverApiList.push(observe)) // 监听执行历史面板变动 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) && lines.length > 0 && isNull(lines[0].querySelector(".customer-button-div"))) { appendFlagNode(lines[0], "customer-button-div") 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(createTextButton("RT:" + content[i].rt, () => { detailButton.click() historyTrace = tds[2].innerText }), detailButton) } }) } }, true, observe => mutationObserverApiList.push(observe)) // 获取接口package const currentApiId = window.pageHelper.getCurrentApiId(); if (isNull(packageNameMap[currentApiId])) { getApiPackageName(process => { packageNameMap[currentApiId] = isNull(process.packageName) || process.packageName === '' ? 'api_' + process.id : process.packageName const type = isNull(process.type) || process.type === '' ? 'api' : process.type; if (type === 'childProcess') { typeMap[currentApiId] = 'api' } else { typeMap[currentApiId] = type } }) } }, true) // 监听body变动 waitObserve("body", () => { // 监听执行日志流程图变动 const processPanelTag = ".node-bpmn #canvas .bjs-container .djs-container .viewport .layer-base" const processPanel = document.querySelector(processPanelTag) if (isNull(processPanel)) { return } if (isNull(processPanel.querySelector(".customer-rt"))) { appendFlagNode(processPanel, "customer-rt") const oldRtNode = processPanel.querySelectorAll(".bpmn-tiny-label"); if (nonNull(oldRtNode)) { oldRtNode.forEach(v => v.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") appendToolBarButton("设置", () => { const settingPanel = document.getElementById("copy-setting") settingPanel.style.display = settingPanel.style.display === 'block' ? 'none' : "block" }) appendToolBarButton("首页", () => { // 关闭首页显示 const homePage = document.querySelector(".tab-home-page"); const tabsBar = document.querySelector(".tabs-bar"); if (nonNull(homePage) && nonNull(tabsBar) && nonNull(tabsBar.childNodes) && tabsBar.childNodes.length > 0) { homePage.style.display = homePage.style.display === 'block' ? 'none' : "block" } }) appendToolBarButton("需求列表", () => { getVersionId(versionData => { if (isNull(versionData) || versionData.length === 0) { window.pageHelper.showToast("未在YWork查询到当前分支与之对应需求版本,先在YWork发布清单添加当前分支") } else { if (versionData.length > 1) { let name = ""; for (let i = 0; i < versionData.length; i++) { name += versionData[i].appVersion + " "; } window.pageHelper.showToast("当前分支查到了如下 " + name + " 多个版本,不能直接跳转!") } else { window.open("https://ops.iyunquna.com/request/list/3?versionId=" + versionData[0].id) } } }) }) appendToolBarButton("全量发布", () => { window.pageHelper.showToast("正在发布", 3000) getVersionId(versionData => { if (isNull(versionData) || versionData.length === 0) { window.pageHelper.showToast("未在YWork查询到当前分支与之对应版本,先在YWork发布清单添加当前分支") } else { if (versionData.length > 1) { let name = ""; for (let i = 0; i < versionData.length; i++) { name += versionData[i].appVersion + " "; } window.pageHelper.showToast("当前分支查到了如下 " + name + " 多个版本,不能直接发布!") } else { getPublishId(versionData[0].id, publishData => { if (isNull(publishData) || isNull(publishData.publishId)) { window.pageHelper.showToast("发布清单查询失败") } else { publish(publishData.publishId, pushData => { if (isNull(pushData) || pushData.result !== true) { window.pageHelper.showToast("发布失败", 2000) } else { window.pageHelper.showToast("发布成功", 1500) } }) } }) } } }) }) appendToolBarButton("发布记录", () => { window.open("https://ops.iyunquna.com/release-record/manage?appId=" + window.pageHelper.getAppId()) }) }) window.pageHelper.initSetting() getAppProjectName(data => { appName = data console.log("项目名称", data) }) sync2Idea() }) function sync2Idea() { const editor = document.getElementById("theia-editor"); if (nonNull(editor)) { setTimeout(() => { sync2Idea() }, 1000 * 60) jq.ajax({ url: 'http://127.0.0.1:63242/socket.io', method: 'POST', xhrFields: { withCredentials: true }, crossDomain: true, contentType: 'application/json', data: JSON.stringify({ "url": editor.src }), }) } else { window.pageHelper.sleep(500).then(() => sync2Idea()) } } 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" } let isProcessing = [] // 等待出现并监听变化 function waitObserve(visibleTag, fun, attributes = true, observeFuc = null) { window.pageHelper.waitElementVisible(visibleTag, () => { let mutationObserver = new MutationObserver(function () { if (isProcessing[visibleTag]) { return; } isProcessing[visibleTag] = true fun() setTimeout(() => isProcessing[visibleTag] = false, 150) }) mutationObserver.observe(document.querySelector(visibleTag), { attributes: attributes, childList: true, subtree: true, characterData: true }) observeFuc = observeFuc === null || observeFuc === undefined ? () => "" : observeFuc observeFuc(mutationObserver) }) } 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.endsWith("/") ? path : path + '/') otherReq("http://127.0.0.1:63342/api/file/" + path + "src/main/java/com/yqn/framework/composer/" + typeMap[window.pageHelper.getCurrentApiId()] + "/" + packageNameMap[window.pageHelper.getCurrentApiId()] + "/script/Script_" + text + (isJava ? ".java" : ".json")) window.pageHelper.showToast("已打开文件,如未打开,检查插件是否安装以及path是否正确", 2000) } else if (copyValue === '3') { const url = 'jetbrains://idea/navigate/reference?project=' + appName + '&fqn=com.yqn.framework.composer.' + typeMap[window.pageHelper.getCurrentApiId()] + '.' + packageNameMap[window.pageHelper.getCurrentApiId()] + '.script.Script_' + text; window.open(url) window.pageHelper.showToast("已打开文件,如未打开,请确认已安装Jetbrains Toolbox ", 2000) } } // 创建按钮 function createTextButton(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.style.marginRight = '5px' button.onclick = listener const span = document.createElement("span") span.textContent = name button.appendChild(span) return button } // 创建工具栏按钮 function appendToolBarButton(name, listener) { const buttonLists = document.querySelector(".app-actions") 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 = listener const span = document.createElement("span") span.textContent = name button.appendChild(span) settingButton.appendChild(button) buttonLists.appendChild(settingButton) } // 获取分支YWork版本ID function getVersionId(fuc) { remoteReq('/api/42070/yqn_integrate/bg/integrate_app_version/v2/query_application_version', { "appBranch": localStorage.getItem("defaultBranch") }, data => { fuc(data) }) } // 获取应用清单ID function getPublishId(versionId, fuc) { remoteReq('/api/42070/api/call/cicd/publish/get_app_list', { "appVersionId": versionId }, data => { fuc(data) }) } // 发布 function publish(publishId, fuc) { remoteReq('/api/42070/api/call/cicd/app/publish', { "colorTagId": "", "env": 4, "ignorePublishClash": 0, "publishId": publishId, "appIds": [window.pageHelper.getAppId()], "ignoreBranchBehind": 0 }, data => { fuc(data) }) } const addressArr = ['', '/process', '/mq', '/job'] function getApiPackageName(fuc, apiMode = 0) { remoteReq('/api/42080/api' + addressArr[apiMode] + '/details_composer', { "id": window.pageHelper.getCurrentApiId(), }, data => { if (isNull(data)) { if (apiMode === 0) { getApiPackageName(fuc, 1) getApiPackageName(fuc, 2) getApiPackageName(fuc, 3) } return } let processDefine = JSON.parse(data.processDefine) fuc(processDefine.process) }) } // 拿流程信息 function getNodeInfo(nodeName, fuc, apiMode = 0) { 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', 'consumer', '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 = window.pageHelper.getAppId() if (isNull(model.env)) { 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) } else { fuc(null) } }, error: function (xhr, status, error) { console.log('Request failed:', error) fuc(null) } }) } function otherReq(url) { jq.ajax(url, { method: "GET", xhrFields: { withCredentials: true }, crossDomain: true }) } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址