您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
云效脚本
当前为
// ==UserScript== // @name monkey-yunxiao // @namespace npm/vite-plugin-monkey // @version 0.0.4.1 // @author monkey // @description 云效脚本 // @license MIT // @icon data:image/svg+xml,%3Csvg%20width%3D%22240%22%20height%3D%22240%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cdefs%3E%3ClinearGradient%20x1%3D%2250.007%25%22%20y1%3D%2299.839%25%22%20x2%3D%2250.007%25%22%20y2%3D%22.339%25%22%20id%3D%22a%22%3E%3Cstop%20stop-color%3D%22%23006ad4%22%20stop-opacity%3D%22.5%22%20offset%3D%220%25%22%2F%3E%3Cstop%20stop-color%3D%22%23006ad4%22%20stop-opacity%3D%22.2%22%20offset%3D%22100%25%22%2F%3E%3C%2FlinearGradient%3E%3ClinearGradient%20x1%3D%2250.035%25%22%20y1%3D%22-.079%25%22%20x2%3D%2250.035%25%22%20y2%3D%2299.929%25%22%20id%3D%22b%22%3E%3Cstop%20stop-color%3D%22%23006ad4%22%20offset%3D%220%25%22%2F%3E%3Cstop%20stop-color%3D%22%23006ad4%22%20stop-opacity%3D%22.5%22%20offset%3D%22100%25%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20width%3D%22240%22%20height%3D%22240%22%20rx%3D%2212%22%2F%3E%3Cg%20transform%3D%22translate(24%2024)%22%20fill-rule%3D%22nonzero%22%3E%3Cpath%20d%3D%22m192%20191.774-67.621-89.901%2048.997-67.087-33.921-26.202-69.395%2093.74%2060.748%2080.64c4.213%205.648%2010.642%208.81%2017.737%208.81H192Z%22%20fill%3D%22url(%23a)%22%2F%3E%3Cellipse%20fill%3D%22%23006ad4%22%20cx%3D%22156.527%22%20cy%3D%2221.685%22%20rx%3D%2221.284%22%20ry%3D%2221.685%22%2F%3E%3Cpath%20d%3D%22M124.379%20101.873%2061.413%2018.296c-4.212-5.647-10.642-8.809-17.736-8.809H0l69.838%2092.838L3.77%20192h43.012c7.094%200%2013.524-3.388%2017.736-9.035l59.862-81.092Z%22%20fill%3D%22url(%23b)%22%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E // @match https://devops.aliyun.com/projex/* // @match https://devops.aliyun.com/workbench* // @require https://lf9-cdn-tos.bytecdntp.com/cdn/expire-10-y/rxjs/7.5.4/rxjs.umd.min.js // @grant GM_addStyle // ==/UserScript== (t=>{if(typeof GM_addStyle=="function"){GM_addStyle(t);return}const e=document.createElement("style");e.textContent=t,document.head.append(e)})(" ._status-button-progress_1wcb5_1{position:absolute;bottom:0;left:0;width:100%;height:2px;background:red;transition:width .5s} "); (function (rxjs) { 'use strict'; var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value); const style = { "status-button-progress": "_status-button-progress_1wcb5_1" }; const match = (path) => { return ( // 任务视图 /^\/projex\/project\/.+\/task/.test(path) || // 工作项视图 /^\/projex\/workitem/.test(path) || // 工作台视图 /^\/workbench$/.test(path) ); }; const apiMaps = /* @__PURE__ */ new Map([ [ "/projex/api/workitem/workitem/list", (data) => { rxjs.interval(100).pipe( // 查询到元素存在后,停止轮询,并返回元素 rxjs.map(() => { let dom = document.querySelector( "#AONE_MY_WORKITEM_CARD .next-table-inner" ); let col = 1; if (dom) { return { dom, col }; } dom = document.querySelector( ".workitemListMainAreaWrap .next-table-inner" ); if (dom) { col = findColsNum(dom, "状态"); return { dom, col }; } return void 0; }), rxjs.first((data2) => !!data2), rxjs.takeUntil(rxjs.timer(500)) ).subscribe({ next: ({ dom: target, col }) => { if (target.getAttribute("init-progress")) { console.log("已经初始化过了"); return; } target.setAttribute("init-progress", "true"); if (col) { const elList = target.querySelectorAll( `.next-table-body tr td[data-next-table-col="${col}"] button` ); elList.forEach((el, i) => { const dataItem = data.result[i]; if (dataItem.workitemType.name !== "任务") return; el.style.position = "relative"; const div = document.createElement("div"); div.classList.add(style["status-button-progress"]); el.appendChild(div); const parentIdentifier = dataItem == null ? void 0 : dataItem.parentIdentifier; parentIdentifier && queryParentAndUpdateEl(parentIdentifier, div, dataItem); }); } } }); } ] ]); function findColsNum(target, title) { const thList = target.querySelectorAll( ".next-table-header th" ); for (let i = 0; i < thList.length; i++) { if (thList[i].innerText === title) { return i; } } return void 0; } async function queryParentAndUpdateEl(identifier, dom, dataItem) { var _a; const res = await fetch( `https://devops.aliyun.com/projex/api/workitem/v2/workitem/${identifier}/relation/workitem/list/by-relation-category?category=PARENT_SUB&isForward=true&_input_charset=utf-8`, { headers: { "Content-Type": "application/json" }, method: "GET", credentials: "include" } ).then((res2) => res2.json()); const taskList = (_a = res.result) == null ? void 0 : _a.filter((item) => item.workitemTypeName === "任务").filter((item) => item.identifier !== dataItem.identifier); function setStyle(n) { dom.style.width = `${n}%`; } if (!(taskList == null ? void 0 : taskList.length)) { setStyle(100); return; } const progress = taskList.length * 100; let completed = 0; taskList.forEach((task) => { var _a2; const progressStr = (_a2 = task.fieldValueVOList.find( (field) => field.fieldIdentifier === "progress" )) == null ? void 0 : _a2.value; if (progressStr === "0.1") return; const n = Number(progressStr); if (n) { completed += n; } }); const percent = completed / progress * 100; setStyle(percent); } const name = "任务进度条"; const taskHandler = { match, apiMaps, name }; class ChainOfResponsibility { constructor() { __publicField(this, "handlers"); this.handlers = []; } add(handler) { this.handlers.push(handler); return this; } handleApi(params) { for (const handler of this.handlers) { if (handler.match(params.triggerURLPath)) { const task = handler.apiMaps.get(params.path); if (task) { console.log(`通过接口请求,触发了脚本: ${params.path} ===> ${handler.name}`); task(params.responseJSON); } } } } } const chain = new ChainOfResponsibility(); chain.add(taskHandler); const xhrOpen = window.XMLHttpRequest.prototype.open; window.XMLHttpRequest.prototype.open = function(...args) { xhrOpen.apply(this, args); let triggerURLPath = location.pathname; this.addEventListener("readystatechange", function() { if (this.readyState === 4) { const path = new URL(this.responseURL).pathname; const responseJSON = this.responseType === "json" ? this.response : JSON.parse(this.responseText); chain.handleApi({ path, responseJSON, triggerURLPath }); } }); }; })(rxjs);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址