lowerCodeHelper

低代码平台助手

目前為 2023-12-01 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         lowerCodeHelper
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  低代码平台助手
// @author       Ziker
// @match        https://ops.iyunquna.com/63008/*
// @require      https://code.jquery.com/jquery-3.4.1.min.js
// @icon         https://favicon.qqsuu.cn/work.yqn.com
// @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 = {
        // 等待元素可见
        async 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;
        },
        getCurrentAppId() {
            const nodes = document.getElementsByClassName("tab-content-presentation-components");
            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);
        },
        copyToClipboard(text) {
            // 创建一个临时的 textarea 元素
            let textarea = document.createElement('textarea');
            // 设置 textarea 的值为要拷贝的文本内容
            textarea.value = text;
            // 将 textarea 添加到文档中
            document.body.appendChild(textarea);
            // 选中 textarea 的内容
            textarea.select();
            // 执行复制操作
            document.execCommand('copy');
            // 移除临时的 textarea 元素
            document.body.removeChild(textarea);
            this.showToast("已拷贝 " + text)
        }
    }
})(window);


(function () {
    let historyTrace = ''
    'use strict';
    jq(document).ready(function () {
        // 监听api tab变动
        waitObserve(".tabs-bar", () => {
            // 应用接口面板
            const appPanelTag = ".tab-content-presentation-components.theia-tab-" + window.pageHelper.getCurrentAppId();
            // 监听属性面板变动
            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");
                    let nodeName = nonNull(childProcessNode) ? childProcessNode.value : p8.querySelector(".dashboard-code span").textContent
                    // 获取当前节点信息
                    getNodeInfo(nodeName, node => {
                        // 处理信息
                        const divNode = document.querySelector(appPanelTag + " .customScriptInfo");
                        // 清空显示
                        divNode.innerHTML = ""
                        // 脚本
                        if (nonNull(node.scriptId)) {
                            divNode.appendChild(createButton("脚本:" + node.scriptId, () => window.pageHelper.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;
                        }
                        if (isNull(id) && nonNull(node.dslBulidData)) {
                            id = node.dslBulidData.dslScriptId;
                        }
                        if (nonNull(id)) {
                            divNode.appendChild(createButton("入参:" + id, () => window.pageHelper.copyToClipboard(id)))
                        }
                        // 条件
                        const executeScriptId = node.executeScriptId;
                        if (nonNull(executeScriptId)) {
                            divNode.appendChild(createButton("条件:" + executeScriptId, () => window.pageHelper.copyToClipboard(executeScriptId)))
                        }
                        // 校验
                        const assertScriptId = node.assertScriptId;
                        if (nonNull(assertScriptId)) {
                            divNode.appendChild(createButton("校验:" + assertScriptId, () => window.pageHelper.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", "101")
                                rtNode.setAttribute("y", "45")
                                rtNode.textContent = "RT:" + log.rt
                            }
                        }
                    })
                }
            }, false)
        })
    })

    function nonNull(o) {
        return o !== null && o !== undefined;
    }

    function isNull(o) {
        return o === null || o === undefined;
    }

    // 等待出现并监听变化
    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
            })
        }).then(r => {
        })
    }

    // 创建按钮
    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) {
        getNodeInfoByApiMode(0, nodeName, fuc)
    }

    const addressArr = ['', '/process', '/mq', '/job'];

    // 拿流程信息
    function getNodeInfoByApiMode(apiMode, nodeName, fuc) {
        jq.ajax({
            url: 'https://gw-ops.iyunquna.com/api/42080/api' + addressArr[apiMode] + '/details_composer?guid=6f87e073-1da1-4017-b2de-c109abcd6d123',
            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": {
                    "id": window.pageHelper.getCurrentAppId(),
                    "appId": new URLSearchParams(window.location.href.split('?')[1]).get('appId')
                }
            }),
            success: function (response) {
                if (response.code === 200) {
                    if (response.data === null && apiMode === 0) {
                        getNodeInfoByApiMode(apiMode + 1, nodeName, fuc)
                        getNodeInfoByApiMode(apiMode + 2, nodeName, fuc)
                        getNodeInfoByApiMode(apiMode + 3, nodeName, fuc)
                        return
                    }
                    let processDefine = JSON.parse(response.data.processDefine);
                    for (let i = 0; i < processDefine.nodes.length; i++) {
                        if (processDefine.nodes[i].code === nodeName) {
                            fuc(processDefine.nodes[i])
                            break
                        }
                    }
                }
            },
            error: function (xhr, status, error) {
                console.log('Request failed:', error);
            }
        });
    }

    // 拿历史执行数据
    function getExecuteHistory(fuc) {
        jq.ajax({
            url: 'https://gw-ops.iyunquna.com/api/42086/apiLog/list?guid=c74610c3-b840-446f-a452-f678b32a39e8',
            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": {
                    "apiId": window.pageHelper.getCurrentAppId(),
                    "appId": new URLSearchParams(window.location.href.split('?')[1]).get('appId')
                }
            }),
            success: function (response) {
                if (response.code === 200 && nonNull(response.data) && nonNull(response.data.content)) {
                    fuc(response.data.content)
                }
            },
            error: function (xhr, status, error) {
                console.log('Request failed:', error);
            }
        });
    }

    const apiType = ['api', 'process', 'mq', 'job'];

    // 拿 trace 执行数据
    function getByTraceId(fuc) {
        return getByTraceIdByApiMode(0, fuc)
    }

    // 拿 trace 执行数据
    function getByTraceIdByApiMode(apiMode, fuc) {
        jq.ajax({
            url: 'https://gw-ops.iyunquna.com/api/42086/apiLog/getByTraceId?guid=3862879a-b379-4171-9644-289ee637dae0',
            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": {
                    "appId": new URLSearchParams(window.location.href.split('?')[1]).get('appId'),
                    "env": "qa4",
                    "traceIdLike": historyTrace,
                    "apiId": window.pageHelper.getCurrentAppId(),
                    "testCaseId": null,
                    "apiTypeCode": apiMode === 0 ? "api" : apiType[apiMode]
                }
            }),
            success: function (response) {
                if (response.code === 200 && nonNull(response.data) && nonNull(response.data.apiNodeLogList) && response.data.apiNodeLogList.length !== 0) {
                    fuc(response.data.apiNodeLogList)
                } else if (apiMode === 0) {
                    getByTraceIdByApiMode(1, fuc)
                    getByTraceIdByApiMode(2, fuc)
                    getByTraceIdByApiMode(3, fuc)
                }
            },
            error: function (xhr, status, error) {
                console.log('Request failed:', error);
            }
        });
    }
})();