您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
低代码平台助手
当前为
- // ==UserScript==
- // @name lowerCodeHelper
- // @namespace http://tampermonkey.net/
- // @version 0.3.8
- // @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 顶部工具栏按钮新增多个工具按钮
- // @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()
- }
- },
- getCurrentApiIndex() {
- 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.getCurrentApiIndex()].className
- return className.substring(className.indexOf("theia-tab-") + "theia-tab-".length)
- },
- 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 = []
- jq(document).ready(function () {
- if (window.location.href.indexOf("localhost:63342/api/file/") >= 0) {
- window.pageHelper.closeWindow()
- return
- }
- // 监听api tab变动
- waitObserve(".tabs-bar", () => {
- // 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")
- // 清空显示
- 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)))
- }
- })
- }
- })
- // 监听执行历史面板变动
- 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)) {
- if (nonNull(lines[0].querySelector(".customer-button-div"))) {
- return
- }
- 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)
- }
- })
- }
- })
- 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
- }
- })
- }
- })
- // 监听body变动
- waitObserve("body", () => {
- // 监听执行日志流程图变动
- const processPanelTag = ".node-bpmn #canvas .bjs-container .djs-container .viewport .layer-base"
- waitObserve(processPanelTag, () => {
- const processPanel = document.querySelector(processPanelTag)
- 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")
- console.log("ziker", textNode)
- 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)
- })
- })
- 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 () {
- 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.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;
- console.log("ziker", url)
- 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
- })
- }
- })();