iWhaleCloudGit

git 批量操作

目前為 2024-07-17 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         iWhaleCloudGit
// @namespace    http://tampermonkey.net/
// @version      0.1.2
// @description  git 批量操作
// @author       HolmesZhao
// @match        *://globaltech-code.alipay.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=alipay.com
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.toast.min.js
// @resource customCSS https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.toast.min.css
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @license MIT
// ==/UserScript==

(function () {
    "use strict";

    // 吕廷元,4913
    // 林伟,4896
    // 赵五一,4940

    const beProjectUrl =
          "https://globaltech-code.alipay.com/webapi/groups/Banco/overview?types=&page=1&per_page=15&events_page=1&_output_charset=utf-8&_input_charset=utf-8&ctoken=VXzCenNuvtS5YEzN";
    const beProjectReferrerUrl =
          "https://globaltech-code.alipay.com/groups/Banco";
    // Your code here...
    async function getProjects(url, referrer) {
        const source = await fetch(url, {
            headers: {
                accept: "*/*",
                "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
                "antcode-request-type": "ANTCODE_WEB_REQUEST",
                "linkc-request-type": "LINKC_WEB_REQUEST",
                priority: "u=1, i",
                "sec-ch-ua": '"Not-A.Brand";v="99", "Chromium";v="124"',
                "sec-ch-ua-mobile": "?0",
                "sec-ch-ua-platform": '"macOS"',
                "sec-fetch-dest": "empty",
                "sec-fetch-mode": "cors",
                "sec-fetch-site": "same-origin",
                "x-request-lib": "@alipay/bigfish/sdk/fetch",
            },
            referrer: referrer,
            referrerPolicy: "strict-origin-when-cross-origin",
            body: null,
            method: "GET",
            mode: "cors",
            credentials: "include",
        });
        return source.json();
    }

    function createList(datas, top, left) {
        var myDiv = document.getElementById("myDiv");
        if (myDiv == null) {
            myDiv = document.createElement("div");
            myDiv.setAttribute("id", "myDiv");
            myDiv.setAttribute(
                "style",
                `position: fixed;top: ${top}px;left: ${left}px;background-color: #ddd;border: 1px solid #000;padding: 10px;z-index:1000`
      );
        document.body.appendChild(myDiv);
    } else {
        myDiv.innerHTML = "";
    }

      var selectList = document.createElement("select");
      selectList.setAttribute("multiple", "");
      selectList.setAttribute(
          "style",
          "background-color: white; padding-right: 9px; height:" +
          datas.length * 22 +
          "px;" // 22 = 18(字号) + 4(间隙)
      );

      const selectedValues = [];
      selectList.addEventListener("change", () => {
          selectedValues.length = 0;
          for (let i = 0; i < selectList.options.length; i++) {
              const option = selectList.options[i];
              if (option.selected) {
                  selectedValues.push(option.value);
              }
          }
      });

      const inputHTML = `
    <div style="padding: 10px;">
        <div style="display: flex;">
            <span style="width: 80px;">标题</span>
            <textarea id="iwc_title" placeholder="请输入标题" style="margin-left: 5px;"></textarea>
        </div>
        <div style="display: flex;margin-top: 10px;">
            <span style="width: 80px;">描述</span>
            <textarea id="iwc_desc" placeholder="请输入描述" style="margin-left: 5px;"></textarea>
        </div>
        <div style="display: flex;margin-top: 10px;">
            <span style="width: 80px;">源分支</span>
            <textarea id="iwc_source" placeholder="请输入源分支, eg: develop-4b-xxxxx" style="margin-left: 5px;"></textarea>
        </div>
        <div style="display: flex;margin-top: 10px;">
            <span style="width: 80px;">目标分支</span>
            <textarea id="iwc_target" placeholder="请输入目标分支, eg: develop-4b" style="margin-left: 5px;"></textarea>
        </div>
        <div style="display: flex;margin-top: 10px;">
            <span style="width: 80px;">合并后删除来源分支</span>
            <textarea
            id="iwc_delete"
            placeholder="默认不删除 0 也可以代码为默认删除 1"
            style="margin-left: 5px;"
            >0</textarea>
        </div>
        <div style="display: flex;margin-top: 10px;">
            <span style="width: 80px;">合并指派给</span>
            <textarea id="iwc_assignee" placeholder="请输入合并人" style="margin-left: 5px;"></textarea>
        </div>
        <div style="display: flex;margin-top: 10px;">
            <span style="width: 80px;">审核人</span>
            <textarea
            id="iwc_reviewer_ids"
            placeholder="请输入审核人, 用英文逗号链接"
            style="margin-left: 5px;"
            ></textarea>
        </div>
        <div style="display: flex;margin-top: 10px;">
            <span style="width: 80px;">审核票数</span>
            <textarea
            id="iwc_threshold"
            placeholder="请输入审核票数"
            style="margin-left: 5px;"
            ></textarea>
        </div>
    </div>
    `;
      const inputDiv = document.createElement("div");
      inputDiv.innerHTML = inputHTML;

      var contentDiv = document.createElement("div");
      contentDiv.style.display = "flex";
      myDiv.appendChild(contentDiv);
      contentDiv.appendChild(selectList);
      contentDiv.appendChild(inputDiv);

      var buttonDiv = document.createElement("div");
      myDiv.appendChild(buttonDiv);

      var buttonClose = document.createElement("button");
      buttonClose.textContent = "关闭";
      buttonClose.style.marginLeft = "10px";
      buttonClose.style.marginTop = "10px";
      buttonClose.onclick = () => {
          myDiv.style.display = "none";
      };
      buttonDiv.appendChild(buttonClose);

      var buttonRefresh = document.createElement("button");
      buttonRefresh.textContent = "刷新列表";
      buttonRefresh.style.marginLeft = "10px";
      buttonRefresh.style.marginTop = "10px";
      buttonRefresh.onclick = async () => {
          // selectList 移除所有子节点
          while (selectList.firstChild) {
              selectList.removeChild(selectList.firstChild);
          }
          const result = await getProjects(beProjectUrl, beProjectReferrerUrl);
          let options = result.projects;

          for (var i = 0; i < options.length; i++) {
              var option = document.createElement("option");
              option.setAttribute("value", options[i].id);
              option.text = options[i].path_with_namespace;
              option.style.fontSize = "18px";
              selectList.appendChild(option);
          }
      };
      buttonDiv.appendChild(buttonRefresh);

      var button = document.createElement("button");
      button.textContent = "批量 MR";
      button.style.marginTop = "10px";
      button.style.marginLeft = "10px";
      button.onclick = () => {
          var textArr = [];
          datas.forEach((e) => {
              if (selectedValues.indexOf(e.id + "") === -1) return;

              const id = e.id;
              const title = e.path_with_namespace;
              const json = { id: id, title: title };
              textArr.push(json);
          });

          console.log(textArr);
          batchMR(textArr);
      };
      buttonDiv.appendChild(button);

      var options = datas;

      for (var i = 0; i < options.length; i++) {
          var option = document.createElement("option");
          option.setAttribute("value", options[i].id);
          option.text = options[i].path_with_namespace;
          option.style.fontSize = "18px";
          selectList.appendChild(option);
      }
  }

    function batchMR(datas) {
        if (datas.length === 0) {
            alert("请选择项目");
            return false;
        }

        const iwc_title = document.getElementById("iwc_title");
        const iwc_desc = document.getElementById("iwc_desc");
        const iwc_source = document.getElementById("iwc_source");
        const iwc_target = document.getElementById("iwc_target");
        const iwc_delete = document.getElementById("iwc_delete");
        const iwc_assignee = document.getElementById("iwc_assignee");
        const iwc_reviewer_ids = document.getElementById("iwc_reviewer_ids");
        const iwc_threshold = document.getElementById("iwc_threshold");
        // 校验是否存在并且字符串长度是否满足要求
        if (!iwc_title || iwc_title.value.trim().length === 0) {
            alert("Title is required");
            return false;
        }

        if (!iwc_desc || iwc_desc.value.trim().length === 0) {
            alert("Description is required");
            return false;
        }

        if (!iwc_source || iwc_source.value.trim().length === 0) {
            alert("Source is required");
            return false;
        }

        if (!iwc_target || iwc_target.value.trim().length === 0) {
            alert("Target is required");
            return false;
        }

        if (!iwc_delete || iwc_delete.value.trim().length === 0) {
            alert("Delete is required");
            return false;
        }

        if (!iwc_assignee || iwc_assignee.value.trim().length === 0) {
            alert("Assignee is required");
            return false;
        }

        if (!iwc_reviewer_ids || iwc_reviewer_ids.value.trim().length === 0) {
            alert("Reviewer IDs is required");
            return false;
        }

        if (!iwc_threshold || iwc_threshold.value.trim().length === 0) {
            alert("Threshold is required");
            return false;
        }
        const myHeaders = new Headers();
        myHeaders.append("accept", "application/json");
        myHeaders.append("accept-language", "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7");
        myHeaders.append("antcode-request-type", "ANTCODE_WEB_REQUEST");
        myHeaders.append("content-type", "application/json");
        myHeaders.append("dnt", "1");
        myHeaders.append("linkc-request-type", "LINKC_WEB_REQUEST");
        myHeaders.append("origin", "https://globaltech-code.alipay.com");
        myHeaders.append("priority", "u=1, i");
        myHeaders.append("sec-ch-ua", "\"Not-A.Brand\";v=\"99\", \"Chromium\";v=\"124\"");
        myHeaders.append("sec-ch-ua-mobile", "?0");
        myHeaders.append("sec-ch-ua-platform", "\"macOS\"");
        myHeaders.append("sec-fetch-dest", "empty");
        myHeaders.append("sec-fetch-mode", "cors");
        myHeaders.append("sec-fetch-site", "same-origin");
        myHeaders.append("x-request-lib", "@alipay/bigfish/sdk/fetch");

        const raw = JSON.stringify({
            "title": iwc_title.value,
            "source_branch": iwc_source.value,
            "target_branch": iwc_target.value,
            "description": iwc_desc.value,
            "labels": "",
            "should_remove_source_branch": iwc_delete.value === "1",
            "squash_merge": false,
            "assignee_id": iwc_assignee.value,
            "review_required": true,
            "reviewer_ids": iwc_reviewer_ids.value,
            "threshold": iwc_threshold.value
        });

        const requestOptions = {
            method: "POST",
            headers: myHeaders,
            body: raw,
            redirect: "follow"
        };

        datas.forEach((e) => {
            fetch(`https://globaltech-code.alipay.com/api/v3/projects/${e.id}/pull_requests?_output_charset=utf-8&_input_charset=utf-8`, requestOptions)
                .then((response) => response.text())
                .then((result) => console.log(result))
                .catch((error) => console.error(error));
        });
    }

    async function startLoad(title) {
        const myDiv = document.getElementById("myDiv");
        if (myDiv) {
            myDiv.style.display = "block";
            return;
        }
        const buttons = document.getElementsByClassName("mmbutton");
        let button = null;
        for (let index = 0; index < buttons.length; index++) {
            const element = buttons[index];
            if (element.innerText == title) {
                button = element;
            }
        }
        if (button == null) {
            alert(`没有找到 ${title} 按钮`);
            return;
        }
        const result = await getProjects(beProjectUrl, beProjectReferrerUrl);
        createList(result.projects, button.offsetHeight, button.offsetLeft);
    }

    function addButton(name, marginLeft, top, fun) {
        var txt = document.createTextNode(name);
        var btn = document.createElement("button");
        btn.className = "mmbutton";
        btn.style =
            "z-index: 9999; font-size: large; position: fixed; top: " +
            top +
            "px; left: " +
            marginLeft +
            "px;border:1px solid black; padding: 0 10px;";
        btn.onclick = () => {
            fun(name);
        };
        btn.appendChild(txt);
        document.body.appendChild(btn);
        return btn.offsetWidth + btn.offsetLeft;
    }

    async function review() {
        try {
            await fetch("https://globaltech-code.alipay.com/webapi/projects/2076/pull_requests/198185/comments?type=Comment&note=%23codeReviewResult%23success&_output_charset=utf-8&_input_charset=utf-8&ctoken=ElGV8J1MmfmUFbun", {
                "headers": {
                    "accept": "*/*",
                    "accept-language": "zh-CN,zh;q=0.9",
                    "antcode-request-type": "ANTCODE_WEB_REQUEST",
                    "linkc-request-type": "LINKC_WEB_REQUEST",
                    "priority": "u=1, i",
                    "sec-ch-ua": "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\"",
                    "sec-ch-ua-mobile": "?0",
                    "sec-ch-ua-platform": "\"macOS\"",
                    "sec-fetch-dest": "empty",
                    "sec-fetch-mode": "cors",
                    "sec-fetch-site": "same-origin",
                    "x-request-lib": "@alipay/bigfish/sdk/fetch"
                },
                "referrer": "https://globaltech-code.alipay.com/qicard/debug-iOS/pull_requests/67",
                "referrerPolicy": "strict-origin-when-cross-origin",
                "body": null,
                "method": "POST",
                "mode": "cors",
                "credentials": "include"
            });
            $.toast({
                heading: 'Success',
                text: '请求成功',
                showHideTransition: 'slide',
                icon: 'success'
            })
        } catch(e) {
            $.toast({
                heading: 'Error',
                text: e,
                showHideTransition: 'fade',
                icon: 'error'
            })
        }
    }

    // onload
    const isFunction = (variable) => {
        return typeof variable === "function";
    };
    const bakOnload = window.onload;
    window.onload = async () => {
        const css = GM_getResourceText("customCSS");
        GM_addStyle(css);
        if (isFunction(bakOnload)) {
            bakOnload();
        }
    };

    console.log('执行了');

    var btnLeft = screen.width / 8;
    var marginLeft = 30;
    btnLeft += marginLeft;
    btnLeft = addButton("批量 MR", btnLeft, 0, startLoad);
    btnLeft = addButton("通过Review(只有 Xone 合并才能用)", btnLeft, 0, review);
    //   addButton('批量 MR', btnLeft, 40, copyImagesJSON2);
})();